scsh-0.5/scsh/fileinfo.scm

116 lines
4.2 KiB
Scheme

;;; Copyright (c) 1993, 1994 by Olin Shivers.
;;; chase? true (the default) means if the file is a symlink, chase the link
;;; and report on the file it references. chase? = #f means check the actual
;;; file itself, even if it's a symlink.
;;; writeable means (1) file exists & is writeable OR (2) file doesn't exist
;;; but directory is writeable.
;;; Return values:
;;; #f Accessible
;;; search-denied Can't stat
;;; permission File exists but is protected
;;; (also for errno/rofs)
;;; no-directory Some directory doesn't exist
;;; nonexistent File itself doesn't exist
;;;
;;; Otherwise, signals an error.
(define (file-not-accessible? perms fd/port/fname . maybe-chase?)
(let ((uid (user-effective-uid)))
(and (not (zero? uid)) ; Root can do what he likes.
(with-errno-handler ((err data)
((errno/acces) 'search-denied)
((errno/noent) 'nonexistent)
((errno/notdir) 'not-directory))
(and (let* ((info (apply file-info fd/port/fname maybe-chase?))
(acc (file-info:mode info)))
(cond ((= (file-info:uid info) (user-effective-uid)) ; User
(zero? (bitwise-and acc (arithmetic-shift perms 6))))
((= (file-info:gid info) (user-effective-gid)) ; Group
(zero? (bitwise-and acc (arithmetic-shift perms 3))))
((memv (file-info:gid info) (user-supplementary-gids))
(zero? (bitwise-and acc (arithmetic-shift perms 3))))
(else ; Other
(zero? (bitwise-and acc perms)))))
'permission)))))
;;;;;;
(define (file-not-readable? fd/port/fname) (file-not-accessible? 4 fd/port/fname))
(define (file-not-writable? fd/port/fname) (file-not-accessible? 2 fd/port/fname))
(define (file-not-executable? fd/port/fname) (file-not-accessible? 1 fd/port/fname))
(define (file-readable? fd/port/fname) (not (file-not-readable? fd/port/fname)))
(define (file-writable? fd/port/fname) (not (file-not-writable? fd/port/fname)))
(define (file-executable? fd/port/fname) (not (file-not-executable? fd/port/fname)))
;;; Spelling corrected.
(define file-not-writeable?
(deprecated-proc file-not-writable? "file-not-writeable?"
"Use file-not-writable? instead"))
(define file-writeable?
(deprecated-proc file-writable? "file-writeable?"
"Use file-writable? instead"))
;;;;;;
;;; Returns
;;; #f exists
;;; #t doesn't exist
;;; 'search-denied can't stat
;;; ...or signals an error
(define (file-not-exists? fd/port/fname . maybe-chase?)
(with-errno-handler
((err data)
((errno/acces) 'search-denied)
((errno/noent errno/notdir) #t))
(apply file-info fd/port/fname maybe-chase?)
#f))
(define (file-exists? fd/port/fname . maybe-chase?)
(not (apply file-not-exists? fd/port/fname maybe-chase?)))
;;;;;;
;;; stat and derived file-{mode,size,owner,group,times,inode,...} ops.
(define-simple-syntax (define-stat-proc proc info-slot)
(define (proc fname/fd/port . maybe-chase?)
(info-slot (apply file-info fname/fd/port maybe-chase?))))
(define-stat-proc file-type file-info:type)
(define-stat-proc file-group file-info:gid)
(define-stat-proc file-inode file-info:inode)
(define-stat-proc file-last-access file-info:atime)
(define-stat-proc file-last-mod file-info:mtime)
(define-stat-proc file-last-status-change file-info:ctime)
(define-stat-proc file-mode file-info:mode)
(define-stat-proc file-nlinks file-info:nlinks)
(define-stat-proc file-owner file-info:uid)
(define-stat-proc file-size file-info:size)
(define (file-directory? fname/fd/port . maybe-chase?)
(eq? 'directory (apply file-type fname/fd/port maybe-chase?)))
(define (file-fifo? fname/fd/port . maybe-chase?)
(eq? 'fifo (apply file-type fname/fd/port maybe-chase?)))
(define (file-regular? fname/fd/port . maybe-chase?)
(eq? 'regular (apply file-type fname/fd/port maybe-chase?)))
(define (file-socket? fname/fd/port . maybe-chase?)
(eq? 'socket (apply file-type fname/fd/port maybe-chase?)))
(define (file-special? fname/fd/port . maybe-chase?)
(let ((type (apply file-type fname/fd/port maybe-chase?)))
(or (eq? 'block-special type) (eq? 'char-special type))))
(define (file-symlink? fname/fd/port) ; No MAYBE-CHASE?, of course.
(eq? 'symlink (file-type fname/fd/port #f)))