;;AUTOLOAD: file-info
;;AUTODOC: file-info "verbose listing of stats of a file"
;;(file-info file [do-not-follow-link])
;;
;;Prints in an human readable form all the caracteristic of a file
;;Example:
;;? (file-info "/tmp")
;;    file: /tmp size 1024 (2 blocks of 65536 bytes)
;;    device: 9460 (raw 0) inode: 2779156 links: 1 uid: 0 gid: 0
;;    dates: a: 763595389 m: 763595389 c: 763595389
;;    file is a directory
;;    -rwxrwxrwx
;;If a second non-nil argument is provided, give info on the symbolic link 
;;itself, and not the filke pointed to (default) if file is a symbolic link

(defun file-info (file &optional do-not-follow-link &aux
    modes
    (stat (file-stats file do-not-follow-link))
  )
  (if (not stat) (progn
      (print-format () "No such file: %0\n" file)
      ()
    )
    (progn
      (print-format () "file: %0 size %1 (%2 blocks of %3 bytes)\n"
	file (getn stat 'size) (getn stat 'blocks) (getn stat 'blksize)
      )
      (print-format () "device: %0 (raw %5) inode: %1 links: %2 uid: %3 gid: %4\n"
	(getn stat 'dev) (getn stat 'ino) (getn stat 'nlink)
	(getn stat 'uid) (getn stat 'gid) (getn stat 'rdev)
      )
      (print-format () "dates: a: %0 m: %1 c: %2\n"
	(getn stat 'atime) (getn stat 'mtime) (getn stat 'ctime)
      )
      (setq modes (getn stat 'mode))
      (setq filemodes (logand S_IFMT modes))
      (map ()
	(lambda (flags)
	  (if (= filemodes (getn flags 0))
	    (print-format () "file is a %0\n" (getn flags 1)
	  ))
	)
	`(
	  (,S_IFDIR "directory")
	  (,S_IFCHR "character special file")
	  (,S_IFBLK "block special file")
	  (,S_IFREG "regular file")
	  (,S_IFLNK "symbolic link")
	  (,S_IFSOCK "socket")
	  (,S_IFIFO "fifo")
      ))
      (map () (lambda (flags)
	  (if (/= 0(logand (get flags 0) modes))
	    (write (get flags 1))
	    (if (getn flags 2)
	      (if (/= 0 (logand (get flags 2) modes))
		(write (get flags 3))
		(write "-")
	      )
	      (write "-")
	)))
	`(
	  (,S_ISVTX "t")
	  (,S_IREAD "r")
	  (,S_IWRITE "w")
	  (,S_ISUID "s" ,S_IEXEC "x")
	  (,S_IGREAD "r")
	  (,S_IGWRITE "w")
	  (,S_ISGID "s" ,S_IGEXEC "x")
	  (,S_IOREAD "r")
	  (,S_IOWRITE "w")
	  (,S_IOEXEC "x")
      ))
      (write "\n")
    )
    file
))
    
