From f8349e9a1110691e76ab8e64bf7b8a927de68280 Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Sun, 9 Aug 2026 14:16:18 +0200 Subject: [PATCH] Added a private flag --- class.rkt | 11 +++++++++-- info.rkt | 4 ++-- main.rkt | 14 ++++++++++---- scribblings/ini.scrbl | 13 ++++++++++++- tests/private.rkt | 19 +++++++++++++++++++ 5 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 tests/private.rkt diff --git a/class.rkt b/class.rkt index 45660f9..cf0b47e 100644 --- a/class.rkt +++ b/class.rkt @@ -15,7 +15,7 @@ (define ini% (class object% - (init-field [file #f] [fail #f]) + (init-field [file #f] [fail #f] [private? #f]) (define content #f) @@ -33,6 +33,13 @@ (define/public (get-fail) fail) + (define/public (get-private?) + private?) + + (define/public (set-private! p) + (i-set! private? p) + this) + (define/public (get-contents) content) @@ -53,7 +60,7 @@ (if (eq? file #f) (when fail (error "ini: No filename set, cannot write ini after set!")) - (ini->file content file)) + (ini->file content file #:private? private?)) this)) (define/public (get section key . default-value) diff --git a/info.rkt b/info.rkt index 5917030..b1a3956 100644 --- a/info.rkt +++ b/info.rkt @@ -1,7 +1,7 @@ #lang info (define pkg-authors '(hnmdijkema)) -(define version "0.3.2") +(define version "0.3.3") (define license 'Apache-2.0) (define pkg-desc "A Simple .ini file reader/writer for racket") @@ -12,7 +12,7 @@ ) (define deps - '("base" "roos")) + '(("base" #:version "8.7.0.10") "roos")) (define build-deps '("racket-doc" diff --git a/main.rkt b/main.rkt index b6d1a0f..82c8298 100644 --- a/main.rkt +++ b/main.rkt @@ -41,8 +41,15 @@ ) ) -(define (ini->file ini file) - (let ((out (open-output-file (get-ini-file file) #:exists 'replace))) +(define (ini->file ini file #:private? [private? #f]) + (let* ((file (get-ini-file file)) + (out (if (and private? + (memq (system-type 'os) '(unix macosx))) + (open-output-file file + #:exists 'replace + #:permissions #o600 + #:replace-permissions? #t) + (open-output-file file #:exists 'replace)))) (let ((last-is-newline #f)) (for-each (lambda (section) (let ((section-name (car section))) @@ -74,10 +81,9 @@ (output-value (caddr line) out) (newline out)) (error "Unknown line format"))))) - lines)))) + lines)))) (mcdr ini))) (close-output-port out))) - (define (make-ini) (mcons 'ini (list))) diff --git a/scribblings/ini.scrbl b/scribblings/ini.scrbl index d9b1525..7b951d3 100644 --- a/scribblings/ini.scrbl +++ b/scribblings/ini.scrbl @@ -45,9 +45,10 @@ ] } -@defproc[(ini->file [ini mc-pair?] [file path-string?]) void?]{ +@defproc[(ini->file [ini mc-pair?] [file path-string?] [#:private? private? boolean? #f]) void?]{ Writes an INI structure (as produced by @racket[file->ini] or @racket[make-ini]) to the specified file. If file is a symbol?, the file will be constructed from the prefs-dir, the symbol and a suffix ".ini". + If @racket[private?] is @racket[#t], Unix-like systems restrict the file to mode @tt{0600} before the INI contents are written. The output preserves: @itemlist[ @@ -89,6 +90,7 @@ An OO wrapper around the ini functions. @defconstructor[([file (or/c symbol? string? path? boolean?) #f] [fail (or/c boolean?) #f] + [private? (or/c boolean?) #f] )]{ Creates the ini from the given file. * If (eq? file #f), an empty ini will be made. @@ -115,6 +117,15 @@ An OO wrapper around the ini functions. Sets the value of the 'fail' flag. See constructor for more information. } + +@defmethod*[([(get-private?) boolean?])]{ + Returns whether private file permissions are enabled. +} + +@defmethod*[([(set-private! [private? boolean?]) this])]{ + Enables or disables private file permissions for subsequent writes. +} + @defmethod*[([(get-contents) list?])]{ Gets the contents of the ini structure as stored in memory. } diff --git a/tests/private.rkt b/tests/private.rkt new file mode 100644 index 0000000..7fdcde2 --- /dev/null +++ b/tests/private.rkt @@ -0,0 +1,19 @@ +#lang racket/base + +(require rackunit + racket/file + "../main.rkt") + +(define tmp (make-temporary-file "simple-ini-private-~a.ini")) +(dynamic-wind + void + (lambda () + (define ini (make-ini)) + (ini-set! ini 'secret 'token "abc") + (ini->file ini tmp #:private? #t) + (when (memq (system-type 'os) '(unix macosx)) + (check-equal? (bitwise-and (file-or-directory-permissions tmp 'bits) #o777) + #o600))) + (lambda () + (when (file-exists? tmp) + (delete-file tmp))))