~ chicken-core (chicken-5) 1491b55d1aca1b6a533b3f6170d185fd8db340fb
commit 1491b55d1aca1b6a533b3f6170d185fd8db340fb Author: Peter Bex <peter@more-magic.net> AuthorDate: Sun Aug 13 17:45:52 2017 +0200 Commit: Evan Hanson <evhan@foldling.org> CommitDate: Fri Sep 1 15:57:32 2017 -0400 Stub fchdir() on Windows to simplify change-directory[*] This implements fchdir() in Windows, by abstracting out the file descriptor->path mapping first introduced with fchmod(). Windows won't in fact actually allow you to "open" a directory so you won't be able to obtain a file handle to a directory using file-open, but at least this allows us to use the exact same code on Windows and Unix, thus reducing code duplication. In any case, abstracting the fd to path function can prove helpful in other situations too. Signed-off-by: Evan Hanson <evhan@foldling.org> diff --git a/posix-common.scm b/posix-common.scm index da68a48c..e07dd5af 100644 --- a/posix-common.scm +++ b/posix-common.scm @@ -494,6 +494,20 @@ EOF ;;; Set or get current directory: +(define change-directory + (lambda (name) + (##sys#check-string name 'change-directory) + (let ((sname (##sys#make-c-string name 'change-directory))) + (unless (fx= 0 (##core#inline "C_chdir" sname)) + (posix-error #:file-error 'change-directory "cannot change current directory" name)) + name))) + +(define (change-directory* fd) + (##sys#check-fixnum fd 'change-directory*) + (unless (fx= 0 (##core#inline "C_fchdir" fd)) + (posix-error #:file-error 'change-directory* "cannot change current directory" fd)) + fd) + (define (current-directory #!optional dir) (if dir (change-directory dir) diff --git a/posixunix.scm b/posixunix.scm index 170e6494..d5224be2 100644 --- a/posixunix.scm +++ b/posixunix.scm @@ -560,23 +560,6 @@ static C_word C_i_fifo_p(C_word name) (and fdsw (if (fixnum? fdsw) (and (memq fdsw wl) fdsw) wl))))))))) -;;; Directory stuff: - -(define change-directory - (lambda (name) - (##sys#check-string name 'change-directory) - (let ((sname (##sys#make-c-string name 'change-directory))) - (unless (fx= 0 (##core#inline "C_chdir" sname)) - (posix-error #:file-error 'change-directory "cannot change current directory" name) ) - name))) - -(define (change-directory* fd) - (##sys#check-fixnum fd 'change-directory*) - (unless (fx= 0 (##core#inline "C_fchdir" fd)) - (posix-error #:file-error 'change-directory* "cannot change current directory" fd) ) - fd) - - ;;; Pipes: (define open-input-pipe) diff --git a/posixwin.scm b/posixwin.scm index fca18f99..704b2689 100644 --- a/posixwin.scm +++ b/posixwin.scm @@ -33,7 +33,6 @@ ; symbolic-link? ; set-signal-mask! signal-mask signal-masked? signal-mask! signal-unmask! ; user-information -; change-directory* ; change-file-owner ; current-user-id current-group-id current-effective-user-id current-effective-group-id ; current-effective-user-name @@ -305,26 +304,40 @@ set_last_errno() return 0; } -static C_word C_fchmod(C_word fd, C_word m) +static int fd_to_path(C_word fd, TCHAR path[]) { - 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); + return -1; } result = GetFinalPathNameByHandle(fh, path, MAX_PATH, VOLUME_NAME_DOS); if (result == 0) { set_last_errno(); - return C_fix(-1); + return -1; } else if (result >= MAX_PATH) { /* Shouldn't happen */ errno = ENOMEM; /* For lack of anything better */ - return C_fix(-1); + return -1; + } else { + return 0; } - return C_fix(chmod(path, C_unfix(m))); +} + +static C_word C_fchmod(C_word fd, C_word m) +{ + TCHAR path[MAX_PATH]; + if (fd_to_path(fd, path) == -1) return C_fix(-1); + else return C_fix(chmod(path, C_unfix(m))); +} + +static C_word C_fchdir(C_word fd) +{ + TCHAR path[MAX_PATH]; + if (fd_to_path(fd, path) == -1) return C_fix(-1); + else return C_fix(chdir(path)); } static int C_fcall @@ -725,19 +738,6 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime) (posix-error #:file-error 'file-mkstemp "cannot create temporary file" template)) (values fd tmpl))))))) -;;; Directory stuff: - -(define change-directory - (lambda (name) - (##sys#check-string name 'change-directory) - (let ((sname (##sys#make-c-string name 'change-directory))) - (unless (fx= 0 (##core#inline "C_chdir" sname)) - (##sys#update-errno) - (##sys#signal-hook - #:file-error 'change-directory "cannot change current directory" name) ) - name))) - - ;;; Pipes: (define open-input-pipe) @@ -1145,7 +1145,6 @@ static int set_file_mtime(char *filename, C_word atime, C_word mtime) ;;; unimplemented stuff: -(define-unimplemented change-directory*) (define-unimplemented chown) ; covers set-file-group! and set-file-owner! (define-unimplemented create-fifo) (define-unimplemented create-session)Trap