~ chicken-core (chicken-5) cb3552baadceeafdae06b381365e9815f14f8f1a
commit cb3552baadceeafdae06b381365e9815f14f8f1a Author: Peter Bex <peter@more-magic.net> AuthorDate: Sat May 13 20:53:45 2017 +0200 Commit: Kooda <kooda@upyum.com> CommitDate: Mon Jun 5 23:08:30 2017 +0200 Rename change-file-mode to set-file-permissions! for consistency This includes a SRFI-17 setter on file-permissions as well. The new setter is moved from (chicken file) to (chicken file posix), because the getter lives in that module too. file-permissions is changed to return just the permissions, so that the values used by setter and getter are symmetric. Before, the getter would also return the file type from stat(), as in it returned the raw value of st_mode. This makes no sense for the name "file-permissions", I'd expect only the permissions. Note that this doesn't remove any functionality: we can still get the file type or any of the special bits using other getters, and if we want we can still use "file-stat" to get the raw underlying values. Finally, the setter is modified to match the getter in accepting both a string and a fd or port, using fchmod. On Windows, fchmod is implemented using GetFinalPathNameByHandle() followed by chmod(). To make this work, the Windows API version has been bumped to Vista. It's probably better to officially require Windows 7 or newer, though. Signed-off-by: Kooda <kooda@upyum.com> diff --git a/chicken.h b/chicken.h index efd89789..d2e9db6d 100644 --- a/chicken.h +++ b/chicken.h @@ -110,10 +110,10 @@ # define C_LLP #endif -/* Declare base Win32 version for access to Timer Queue functions. */ +/* Declare base Win32 version: we require Vista or later */ #ifdef __MINGW32__ -# define _WIN32_WINNT 0x0500 +# define _WIN32_WINNT 0x0600 #endif diff --git a/file.scm b/file.scm index 68d9fc4b..b85f1cce 100644 --- a/file.scm +++ b/file.scm @@ -52,7 +52,6 @@ EOF (module chicken.file (block-device? - change-file-mode change-file-owner character-device? create-directory diff --git a/posix-common.scm b/posix-common.scm index b4ee2c1a..b22947f8 100644 --- a/posix-common.scm +++ b/posix-common.scm @@ -40,6 +40,7 @@ int C_not_implemented() { return -1; } static C_TLS struct stat C_statbuf; #define C_stat_type (C_statbuf.st_mode & S_IFMT) +#define C_stat_perm (C_statbuf.st_mode & ~S_IFMT) #define C_stat(fn) C_fix(stat((char *)C_data_pointer(fn), &C_statbuf)) #define C_fstat(f) C_fix(fstat(C_unfix(f), &C_statbuf)) @@ -253,7 +254,7 @@ EOF (##core#inline "C_stat" path) ) ) ) (else (##sys#signal-hook - #:type-error loc "bad argument type - not a fixnum or string" file)) ) ) ) + #:type-error loc "bad argument type - not a fixnum, port or string" file)) ) ) ) (if (fx< r 0) (if err (posix-error #:file-error loc "cannot access file" file) @@ -268,6 +269,20 @@ EOF _stat_st_dev _stat_st_rdev _stat_st_blksize _stat_st_blocks) ) +(define (set-file-permissions! f p) + (##sys#check-fixnum p 'set-file-permissions!) + (let ((r (cond ((fixnum? f) (##core#inline "C_fchmod" f p)) + ((port? f) (##core#inline "C_fchmod" (port->fileno f) p)) + ((string? f) + (##core#inline "C_chmod" + (##sys#make-c-string f 'set-file-permissions!) p)) + (else + (##sys#signal-hook + #:type-error 'file-permissions + "bad argument type - not a fixnum, port or string" f)) ) ) ) + (when (fx< r 0) + (posix-error #:file-error 'set-file-permissions! "cannot change file permissions" f p) ) )) + (define (file-modification-time f) (##sys#stat f #f #t 'file-modification-time) _stat_st_mtime) (define (file-access-time f) (##sys#stat f #f #t 'file-access-time) _stat_st_atime) (define (file-change-time f) (##sys#stat f #f #t 'file-change-time) _stat_st_ctime) @@ -285,9 +300,15 @@ EOF 'set-file-times! "cannot set file times" f rest))))) (define (file-owner f) (##sys#stat f #f #t 'file-owner) _stat_st_uid) -(define (file-permissions f) (##sys#stat f #f #t 'file-permissions) _stat_st_mode) (define (file-size f) (##sys#stat f #f #t 'file-size) _stat_st_size) +(define file-permissions + (getter-with-setter + (lambda (f) + (##sys#stat f #f #t 'file-permissions) + (foreign-value "C_stat_perm" unsigned-int)) + set-file-permissions! )) + (define (file-type file #!optional link (err #t)) (and (##sys#stat file link err 'file-type) (select (foreign-value "C_stat_type" unsigned-int) @@ -321,14 +342,6 @@ EOF (define (directory? file) (eq? 'directory (file-type file #f #f))) - -(define change-file-mode - (lambda (fname m) - (##sys#check-string fname 'change-file-mode) - (##sys#check-fixnum m 'change-file-mode) - (when (fx< (##core#inline "C_chmod" (##sys#make-c-string fname 'change-file-mode) m) 0) - (posix-error #:file-error 'change-file-mode "cannot change file mode" fname m) ) ) ) - (define file-read-access?) (define file-write-access?) (define file-execute-access?) diff --git a/posix.scm b/posix.scm index 0bb3818e..026a8595 100644 --- a/posix.scm +++ b/posix.scm @@ -101,8 +101,8 @@ open/trunc open/write open/wronly perm/irgrp perm/iroth perm/irusr perm/irwxg perm/irwxo perm/irwxu perm/isgid perm/isuid perm/isvtx perm/iwgrp perm/iwoth perm/iwusr perm/ixgrp perm/ixoth perm/ixusr - port->fileno seek/cur seek/end seek/set set-file-position! - set-file-times!) + port->fileno seek/cur seek/end seek/set set-file-permissions! + set-file-position! set-file-times!) (import chicken chicken.posix)) (module chicken.time.posix diff --git a/posixunix.scm b/posixunix.scm index 6e6a5569..5381cc02 100644 --- a/posixunix.scm +++ b/posixunix.scm @@ -32,7 +32,7 @@ (module chicken.posix (emergency-exit call-with-input-pipe call-with-output-pipe change-directory - change-directory* change-file-mode change-file-owner close-input-pipe + change-directory* change-file-owner close-input-pipe close-output-pipe create-directory create-fifo create-pipe create-session create-symbolic-link current-directory current-effective-group-id current-effective-user-id @@ -43,7 +43,8 @@ fifo? file-access-time file-change-time file-creation-mode file-close file-control file-execute-access? file-link file-lock file-lock/blocking file-mkstemp - file-modification-time file-open file-owner file-permissions + file-modification-time file-open file-owner + file-permissions set-file-permissions! file-position set-file-position! file-read file-read-access? file-select file-size file-stat file-test-lock file-truncate file-type file-unlock file-write file-write-access? fileno/stderr @@ -187,6 +188,7 @@ static C_TLS struct stat C_statbuf; #define C_getegid getegid #define C_chown(fn, u, g) C_fix(chown(C_data_pointer(fn), C_unfix(u), C_unfix(g))) #define C_chmod(fn, m) C_fix(chmod(C_data_pointer(fn), C_unfix(m))) +#define C_fchmod(fd, m) C_fix(fchmod(C_unfix(fd), C_unfix(m))) #define C_setuid(id) C_fix(setuid(C_unfix(id))) #define C_setgid(id) C_fix(setgid(C_unfix(id))) #define C_seteuid(id) C_fix(seteuid(C_unfix(id))) diff --git a/posixwin.scm b/posixwin.scm index df26705d..4f37581a 100644 --- a/posixwin.scm +++ b/posixwin.scm @@ -73,7 +73,9 @@ #include <io.h> #include <process.h> #include <signal.h> +#include <stdio.h> #include <utime.h> +#include <windows.h> #include <winsock2.h> #define PIPE_BUF 512 @@ -306,6 +308,28 @@ set_last_errno() return 0; } +static C_word C_fchmod(C_word fd, C_word m) +{ + TCHAR path[MAX_PATH]; + DWORD result; + HANDLE fh = (HANDLE)_get_osfhandle(C_unfix(fd)); + + if (fh == INVALID_HANDLE_VALUE) { + set_last_errno(); + return C_fix(-1); + } + + result = GetFinalPathNameByHandle(fh, path, MAX_PATH, VOLUME_NAME_DOS); + if (result == 0) { + set_last_errno(); + return C_fix(-1); + } else if (result >= MAX_PATH) { /* Shouldn't happen */ + errno = ENOMEM; /* For lack of anything better */ + return C_fix(-1); + } + return C_fix(chmod(path, C_unfix(m))); +} + static int C_fcall process_wait(C_word h, C_word t) { @@ -641,7 +665,7 @@ EOF (module chicken.posix (emergency-exit call-with-input-pipe call-with-output-pipe change-directory - change-directory* change-file-mode change-file-owner close-input-pipe + change-directory* change-file-owner close-input-pipe close-output-pipe create-directory create-fifo create-pipe create-session create-symbolic-link current-directory current-effective-group-id current-effective-user-id @@ -652,7 +676,8 @@ EOF fifo? file-access-time file-change-time file-creation-mode file-close file-control file-execute-access? file-link file-lock file-lock/blocking file-mkstemp - file-modification-time file-open file-owner file-permissions + file-modification-time file-open file-owner + file-permissions set-file-permissions! file-position set-file-position! file-read file-read-access? file-select file-size file-stat file-test-lock file-truncate file-type file-unlock file-write file-write-access? fileno/stderr diff --git a/types.db b/types.db index d46c1e9f..ee326de4 100644 --- a/types.db +++ b/types.db @@ -1925,7 +1925,6 @@ (chicken.posix#call-with-output-pipe (#(procedure #:enforce) chicken.posix#call-with-output-pipe (string (procedure (input-port) . *) #!optional symbol) . *)) (chicken.posix#change-directory (#(procedure #:clean #:enforce) chicken.posix#change-directory (string) string)) (chicken.posix#change-directory* (#(procedure #:clean #:enforce) chicken.posix#change-directory* (fixnum) fixnum)) -(chicken.posix#change-file-mode (#(procedure #:clean #:enforce) chicken.posix#change-file-mode (string fixnum) undefined)) (chicken.posix#change-file-owner (#(procedure #:clean #:enforce) chicken.posix#change-file-owner (string fixnum fixnum) undefined)) (chicken.posix#close-input-pipe (#(procedure #:clean #:enforce) chicken.posix#close-input-pipe (input-port) fixnum)) (chicken.posix#close-output-pipe (#(procedure #:clean #:enforce) chicken.posix#close-output-pipe (output-port) fixnum)) @@ -2048,6 +2047,7 @@ (chicken.posix#seek/set fixnum) (chicken.posix#set-alarm! (#(procedure #:clean #:enforce) chicken.posix#set-alarm! (integer) integer)) (chicken.posix#set-buffering-mode! (#(procedure #:clean #:enforce) chicken.posix#set-buffering-mode! (port symbol #!optional fixnum) undefined)) +(chicken.posix#set-file-permissions! (#(procedure #:clean #:enforce) chicken.posix#set-file-permissions! ((or string fixnum port) fixnum) undefined)) (chicken.posix#set-file-position! (#(procedure #:clean #:enforce) chicken.posix#set-file-position! ((or port fixnum) integer #!optional fixnum) undefined)) (chicken.posix#set-file-times! (#(procedure #:clean #:enforce) chicken.posix#set-file-times! (string #!optional (or false integer) (or false integer)) undefined)) (chicken.posix#set-root-directory! (#(procedure #:clean #:enforce) chicken.posix#set-root-directory! (string) undefined))Trap