- Fixed errno-error calls to include the syscall's args. This should greatly
improve the quality of the error messages.
- Fixed file-match so that if a filter procedure raises an error condition,
  it is caught and treated as a match failure (as if the procedure returned
  #f). This means you no longer get blown out of the water by
    (file-match "." #f file-directory?)
  if the cwd contains a dangling symlink, for example.
- Added set-file-times (utime).
- Caught a bug in an unused arm of the define-errno-syscall macros (rest arg
  case).
- Perhaps one or two other minor tweaks.
			
			
This commit is contained in:
		
							parent
							
								
									241344c36b
								
							
						
					
					
						commit
						3e52c5100b
					
				|  | @ -32,6 +32,13 @@ | |||
| ;;; Return:	list of matching file names (strings) | ||||
| ;;;             The matcher never considers "." or "..". | ||||
| 
 | ||||
| ;;; Subtle point: | ||||
| ;;;   If a file-match predicate raises an error condition, it is caught by | ||||
| ;;;   FILE-MATCH, and the file under consideration is not matched. This | ||||
| ;;;   means that (file-match "." #f file-directory?) doesn't error out | ||||
| ;;;   if you happen to run it in a directory containing a dangling symlink | ||||
| ;;;   when FILE-DIRECTORY? is applied to the bogus symlink. | ||||
| 
 | ||||
| (define (file-match root dot-files? . patterns) | ||||
|   (let ((patterns (apply append (map split-pat patterns)))) | ||||
|     (let recur ((root root) | ||||
|  | @ -43,11 +50,26 @@ | |||
| 		 (matcher (cond ((string? pattern) | ||||
| 				 (let ((re (make-regexp pattern))) | ||||
| 				   (lambda (f) (regexp-exec re f)))) | ||||
| 
 | ||||
| 				;; This arm makes a file-matcher using | ||||
| 				;; predicate PATTERN. If PATTERN signals | ||||
| 				;; an error condition while it is being | ||||
| 				;; run, our matcher catches it and returns | ||||
| 				;; #f. | ||||
| 				((procedure? pattern) | ||||
| 				 (lambda (f) | ||||
| 				   (pattern (string-append dir f)))) | ||||
| 				   (call-with-current-continuation | ||||
| 				    (lambda (abort) | ||||
| 				      (with-handler (lambda (condition more) | ||||
| 						      (if (error? condition) | ||||
| 							  (abort #f) | ||||
| 							  (more))) | ||||
| 				        (lambda () | ||||
| 					  (pattern (string-append dir f)))))))) | ||||
| 
 | ||||
| 				(else | ||||
| 				 (error "Bad file-match pattern" pattern)))) | ||||
| 
 | ||||
| 		 (candidates (maybe-directory-files root dot-files?)) | ||||
| 		 (winners (filter matcher candidates))) | ||||
| 	    (apply append (map (lambda (fn) (recur (string-append dir fn) | ||||
|  |  | |||
|  | @ -106,7 +106,7 @@ | |||
| (define (get-lock-region fdes lock) | ||||
|   (receive (err type whence start len pid) | ||||
|            (call-lock-region %get-lock fcntl/get-record-lock fdes lock) | ||||
|     (if err (errno-error err get-lock-region) | ||||
|     (if err (errno-error err get-lock-region fdes lock) | ||||
| 	(and (not (= type lock/release)) | ||||
| 	     (make-%lock-region (= type lock/write) start len whence pid))))) | ||||
| 
 | ||||
|  |  | |||
|  | @ -82,7 +82,7 @@ | |||
| (define (dbm-open file flags mode) | ||||
|   (receive (err dbm) (%dbm-open file flags mode) | ||||
| 	   (if err | ||||
| 	       (errno-error err dbm-open) | ||||
| 	       (errno-error err dbm-open file flags mode) | ||||
| 	       dbm))) | ||||
| 
 | ||||
| (define-foreign dbm-close (database_close ((C DBM*) dbm)) | ||||
|  |  | |||
|  | @ -118,7 +118,7 @@ | |||
| 		   -1)) | ||||
| 	 (policy (if (zero? size) bufpol/none policy)) | ||||
| 	 (err (%fdport-set-buffering/errno port policy size))) | ||||
|     (if err (errno-error err set-port-buffering)))) | ||||
|     (if err (errno-error err set-port-buffering port policy size)))) | ||||
| 
 | ||||
| 
 | ||||
| ;;; Open & Close | ||||
|  |  | |||
|  | @ -222,7 +222,7 @@ | |||
|     (receive (err pid status) (%wait-pid/errno pid flags) | ||||
|       (if err | ||||
| 	  (if (= err errno/intr) (lp) | ||||
| 	      (errno-error err %wait-pid)) | ||||
| 	      (errno-error err %wait-pid pid flags)) | ||||
| 	  (and (not (zero? pid)) status)))))	; pid=0 => none ready. | ||||
| 
 | ||||
| 
 | ||||
|  | @ -231,7 +231,7 @@ | |||
|     (receive (err pid status) (%wait-pid/errno -1 flags) | ||||
|       (cond (err (cond ((= err errno/child) (values #f #t))	; No more. | ||||
| 		       ((= err errno/intr)  (lp)) | ||||
| 		       (else (errno-error err %wait-any)))) | ||||
| 		       (else (errno-error err %wait-any flags)))) | ||||
| 	    ((zero? pid) (values #f #f))			; None ready. | ||||
| 	    (else (values pid status)))))) | ||||
| 
 | ||||
|  |  | |||
|  | @ -205,6 +205,7 @@ | |||
| 	  set-file-mode | ||||
| 	  set-file-owner | ||||
| 	  set-file-group | ||||
| 	  set-file-times | ||||
| 	  truncate-file | ||||
| 
 | ||||
| 	  read-symlink			; Not POSIX. | ||||
|  |  | |||
|  | @ -443,6 +443,30 @@ scheme_value df_rmdir(long nargs, scheme_value *args) | |||
|     return ret1; | ||||
|     } | ||||
| 
 | ||||
| scheme_value df_scm_utime(long nargs, scheme_value *args) | ||||
| { | ||||
|     extern int scm_utime(const char *, int , int , int , int ); | ||||
|     scheme_value ret1; | ||||
|     int r1; | ||||
| 
 | ||||
|     cig_check_nargs(5, nargs, "scm_utime"); | ||||
|     r1 = scm_utime(cig_string_body(args[4]), EXTRACT_FIXNUM(args[3]), EXTRACT_FIXNUM(args[2]), EXTRACT_FIXNUM(args[1]), EXTRACT_FIXNUM(args[0])); | ||||
|     ret1 = errno_or_false(r1); | ||||
|     return ret1; | ||||
|     } | ||||
| 
 | ||||
| scheme_value df_scm_utime_now(long nargs, scheme_value *args) | ||||
| { | ||||
|     extern int scm_utime_now(const char *); | ||||
|     scheme_value ret1; | ||||
|     int r1; | ||||
| 
 | ||||
|     cig_check_nargs(1, nargs, "scm_utime_now"); | ||||
|     r1 = scm_utime_now(cig_string_body(args[0])); | ||||
|     ret1 = errno_or_false(r1); | ||||
|     return ret1; | ||||
|     } | ||||
| 
 | ||||
| scheme_value df_scheme_stat(long nargs, scheme_value *args) | ||||
| { | ||||
|     extern int scheme_stat(const char *, scheme_value , int ); | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ | |||
| ;;; | ||||
| ;;; (define (SYSCALL . ARGS) | ||||
| ;;;   (receive (err . RET-VALS) (SYSCALL/ERRNO . ARGS) | ||||
| ;;;     (if err (errno-error err SYSCALL) | ||||
| ;;;     (if err (errno-error err SYSCALL . ARGS) | ||||
| ;;;     	(values . RET-VALS)))) | ||||
|      | ||||
| (define-syntax define-errno-syscall | ||||
|  | @ -44,7 +44,7 @@ | |||
|        ret-val ...) | ||||
|      (define (syscall arg ...) | ||||
|        (receive (err ret-val ...) (syscall/errno arg ...) | ||||
|          (if err (errno-error err syscall) | ||||
|          (if err (errno-error err syscall arg ...) | ||||
|              (values ret-val ...))))) | ||||
| 
 | ||||
|     ;;; This case handles rest args | ||||
|  | @ -52,7 +52,7 @@ | |||
|        ret-val ...) | ||||
|      (define (syscall . args) | ||||
|        (receive (err ret-val ...) (apply syscall/errno . args) | ||||
|          (if err (errno-error err syscall) | ||||
|          (if err (apply errno-error err syscall args) | ||||
|              (values ret-val ...))))))) | ||||
| 
 | ||||
| ;;; DEFINE-SIMPLE-ERRNO-SYSCALL is for the simple case of a system call | ||||
|  | @ -63,21 +63,21 @@ | |||
| ;;; | ||||
| ;;; (define (SYSCALL . ARGS) | ||||
| ;;;   (cond ((SYSCALL/ERRNO . ARGS) =>  | ||||
| ;;;          (lambda (err) (errno-error err SYSCALL))))) | ||||
| ;;;          (lambda (err) (errno-error err SYSCALL . ARGS))))) | ||||
| 
 | ||||
| (define-syntax define-simple-errno-syscall | ||||
|   (syntax-rules () | ||||
|     ((define-simple-errno-syscall (syscall arg ...) syscall/errno) | ||||
|      (define (syscall arg ...) | ||||
|        (cond ((syscall/errno arg ...) =>  | ||||
|               (lambda (err) (errno-error err syscall)))))) | ||||
|               (lambda (err) (errno-error err syscall arg ...)))))) | ||||
| 
 | ||||
| 
 | ||||
|     ;; This case handles rest args | ||||
|     ((define-simple-errno-syscall (syscall . args) syscall/errno) | ||||
|      (define (syscall . args) | ||||
|        (cond ((apply syscall/errno . args) =>  | ||||
|               (lambda (err) (errno-error err syscall)))))))) | ||||
|     ;; This case handles a single rest arg. | ||||
|     ((define-simple-errno-syscall (syscall . rest) syscall/errno) | ||||
|      (define (syscall . rest) | ||||
|        (cond ((apply syscall/errno rest) =>  | ||||
|               (lambda (err) (apply errno-error err syscall rest)))))))) | ||||
| 
 | ||||
| 
 | ||||
| ;;; Process | ||||
|  | @ -90,7 +90,7 @@ | |||
|   integer) | ||||
| 
 | ||||
| (define (%%exec prog argv env) | ||||
|   (errno-error (%%exec/errno prog argv env) %exec)) ; cute. | ||||
|   (errno-error (%%exec/errno prog argv env) %exec prog argv env)) ; cute. | ||||
| 
 | ||||
| (define (%exec prog arg-list env) | ||||
|   (let ((argv (mapv! stringify (list->vector arg-list))) | ||||
|  | @ -342,7 +342,8 @@ | |||
|   (let ((mode (optional-arg maybe-mode #o777)) | ||||
| 	(fname (ensure-file-name-is-nondirectory path))) | ||||
|     (cond ((create-directory/errno fname mode) => | ||||
|            (lambda (err) (if err (errno-error err create-directory))))))) | ||||
|            (lambda (err) | ||||
| 	     (if err (errno-error err create-directory path mode))))))) | ||||
| 
 | ||||
| 
 | ||||
| (define-foreign read-symlink/errno (scm_readlink (string path)) | ||||
|  | @ -368,6 +369,31 @@ | |||
| (define-simple-errno-syscall (delete-directory path) delete-directory/errno) | ||||
| 
 | ||||
| 
 | ||||
| (define-foreign %utime/errno (scm_utime (string path) | ||||
| 					(integer ac_hi) (integer ac_lo) | ||||
| 					(integer m_hi)  (integer m_lo)) | ||||
|   (to-scheme integer errno_or_false)) | ||||
| 
 | ||||
| (define-foreign %utime-now/errno (scm_utime_now (string path)) | ||||
|   (to-scheme integer errno_or_false)) | ||||
| 					 | ||||
| 
 | ||||
| ;;; (SET-FILE-TIMES/ERRNO path [access-time mod-time]) | ||||
| 
 | ||||
| (define (set-file-times/errno path . maybe-times) | ||||
|   (if (pair? maybe-times) | ||||
|       (let ((access-time (car maybe-times)) | ||||
| 	    (mod-time (if (pair? (cddr maybe-times)) | ||||
| 			  (error "Too many arguments to set-file-times/errno" | ||||
| 				 (cons path maybe-times)) | ||||
| 			  (cadr maybe-times)))) | ||||
| 	(%utime/errno path (hi8 access-time) (lo24 access-time) | ||||
| 		           (hi8 mod-time)    (lo24 mod-time))) | ||||
|       (%utime-now/errno path))) | ||||
|    | ||||
| (define-simple-errno-syscall (set-file-times . args) set-file-times/errno) | ||||
| 
 | ||||
| 
 | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
| ;;; STAT | ||||
| 
 | ||||
|  | @ -436,10 +462,10 @@ | |||
| 						      (vector-ref ans-vec 13)))))))) | ||||
| 		 | ||||
| (define (file-info fd/port/fname . maybe-chase?) | ||||
|   (receive (err info) (file-info/errno fd/port/fname  | ||||
| 				       (optional-arg maybe-chase? #t)) | ||||
|     (if err (errno-error err file-info) | ||||
| 	info))) | ||||
|   (let ((chase? (optional-arg maybe-chase? #t))) | ||||
|     (receive (err info) (file-info/errno fd/port/fname chase?) | ||||
|       (if err (errno-error err file-info fd/port/fname chase?) | ||||
| 	  info)))) | ||||
| 
 | ||||
| 
 | ||||
| (define file-attributes | ||||
|  | @ -540,18 +566,19 @@ | |||
| (define seek/end 2) | ||||
| 
 | ||||
| (define (seek fd/port offset . maybe-whence) | ||||
|   (receive (err offset)   | ||||
|       ((if (integer? fd/port) %fd-seek/errno %fdport-seek/errno) | ||||
|        fd/port | ||||
|        offset | ||||
|        (optional-arg maybe-whence seek/set)) | ||||
|     (if err (errno-error err seek) offset))) | ||||
|   (let ((whence (optional-arg maybe-whence seek/set))) | ||||
|     (receive (err cursor)   | ||||
| 	((if (integer? fd/port) %fd-seek/errno %fdport-seek/errno) | ||||
| 	 fd/port | ||||
| 	 offset | ||||
| 	 whence) | ||||
|       (if err (errno-error err seek fd/port offset whence) cursor)))) | ||||
| 
 | ||||
| (define (tell fd/port) | ||||
|   (receive (err offset) (if (integer? fd/port) | ||||
| 			    (%fd-seek/errno fd/port 0 seek/delta) ; seek(fd) | ||||
| 			    (%fdport-tell/errno fd/port))	  ; ftell(f) | ||||
|     (if err (errno-error err tell) offset))) | ||||
|     (if err (errno-error err tell fd/port) offset))) | ||||
| 
 | ||||
| 
 | ||||
| (define-foreign %char-ready-fdes?/errno | ||||
|  | @ -601,7 +628,7 @@ | |||
| 
 | ||||
| (define (read-fdes-char fd) | ||||
|   (let ((c (%read-fdes-char fd))) | ||||
|     (if (integer? c) (errno-error c read-fdes-char) c))) | ||||
|     (if (integer? c) (errno-error c read-fdes-char fd) c))) | ||||
| 
 | ||||
| 
 | ||||
| (define-foreign write-fdes-char/errno (write_fdes_char (char char) (integer fd)) | ||||
|  | @ -797,7 +824,7 @@ | |||
|     (check-arg string? dir directory-files) | ||||
|     (receive (err cvec numfiles) | ||||
| 	     (%open-dir (ensure-file-name-is-nondirectory dir)) | ||||
|       (if err (errno-error err directory-files)) | ||||
|       (if err (errno-error err directory-files dir dotfiles?)) | ||||
|       (%sort-file-vector cvec numfiles) | ||||
|       (let ((files (vector->list (C-string-vec->Scheme&free cvec numfiles)))) | ||||
| 	(if dotfiles? files | ||||
|  | @ -816,7 +843,7 @@ | |||
|     (check-arg string? dir match-files) | ||||
|     (receive (err cvec numfiles) | ||||
| 	     (%open-dir (ensure-file-name-is-nondirectory dir)) | ||||
|       (if err (errno-error err match-files)) | ||||
|       (if err (errno-error err match-files regexp dir)) | ||||
|       (receive (err numfiles) (%filter-C-strings! regexp cvec) | ||||
| 	(if (not (equal? err "")) (error err match-files)) | ||||
| 	(%sort-file-vector cvec numfiles) | ||||
|  | @ -922,7 +949,7 @@ | |||
| 
 | ||||
| (define (%fdport*-read-char data) | ||||
|   (let ((c (%fdport*-read-char/errno data))) | ||||
|     (if (integer? c) (errno-error c %fdport*-read-char) | ||||
|     (if (integer? c) (errno-error c %fdport*-read-char data) | ||||
| 	(or c eof-object)))) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -932,7 +959,7 @@ | |||
| 
 | ||||
| (define (%fdport*-char-ready? data) | ||||
|   (let ((val (%fdport*-char-ready?/errno data))) | ||||
|     (if (integer? val) (errno-error val %fdport*-char-ready?) | ||||
|     (if (integer? val) (errno-error val %fdport*-char-ready? data) | ||||
| 	val))) | ||||
| 
 | ||||
| (define-foreign %fdport*-write-char/errno | ||||
|  |  | |||
|  | @ -19,12 +19,19 @@ | |||
| #include <sys/wait.h> | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
| #include <utime.h> | ||||
| 
 | ||||
| #include "cstuff.h" | ||||
| 
 | ||||
| extern int errno; | ||||
| extern char **environ; | ||||
| 
 | ||||
| /* Sux because it's dependent on 32-bitness. */ | ||||
| #define hi8(i)  (((i)>>24) & 0xff) | ||||
| #define lo24(i) ((i) & 0xffffff) | ||||
| #define comp8_24(hi, lo) (((hi)<<24) + (lo)) | ||||
| 
 | ||||
| 
 | ||||
| /* Process stuff
 | ||||
| ******************************************************************************* | ||||
| ** wait, exec | ||||
|  | @ -121,6 +128,22 @@ char *scm_readlink(char *path) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Scheme interfaces to utime(). 
 | ||||
| ** Complicated by need to pass real 32-bit quantities. | ||||
| */ | ||||
| 
 | ||||
| int scm_utime(char const *path, int ac_hi, int ac_lo, int mod_hi, int mod_lo) | ||||
| { | ||||
|     struct utimbuf t; | ||||
|     t.actime = comp8_24(ac_hi, ac_lo); | ||||
|     t.modtime = comp8_24(mod_hi, mod_lo); | ||||
|     return utime(path, &t); | ||||
|     } | ||||
| 
 | ||||
| int scm_utime_now(char const *path) {return utime(path, 0);} | ||||
| 
 | ||||
| 
 | ||||
| /* Two versions of CWD
 | ||||
| ******************************************************************************* | ||||
| */ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 shivers
						shivers