home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / unix_c / filemgmt / stat.c < prev    next >
C/C++ Source or Header  |  1989-03-21  |  8KB  |  298 lines

  1. 28-Dec-85 04:10:43-MST,7958;000000000001
  2. Return-Path: <unix-sources-request@BRL.ARPA>
  3. Received: from BRL-TGR.ARPA by SIMTEL20.ARPA with TCP; Sat 28 Dec 85 04:10:33-MST
  4. Received: from usenet by TGR.BRL.ARPA id a020626; 28 Dec 85 5:43 EST
  5. From: Wombat <rsk@pucc-j.ARPA>
  6. Newsgroups: net.sources
  7. Subject: Updated version of stat.c
  8. Message-ID: <680@pucc-j>
  9. Date: 27 Dec 85 19:48:29 GMT
  10. Keywords: stat, inode, ls
  11. To:       unix-sources@BRL-TGR.ARPA
  12.  
  13. This is a revision of an earlier posting; it incorporates several improvements
  14. and bug fixes as noted in the opening comments.  Additional bug fixes and
  15. changes *to the author*, please.
  16.  
  17. /*
  18.  *    Stat.c        Dump out inode info in nice form.   pur-ee!rsk
  19.  *            Original version by someone at Purdue in the days of v6;
  20.  *            this one by Rsk for modern times. (4.2, V)
  21.  *
  22.  *            Bug fix for setuid bit misplacement, and modifications
  23.  *            for System V by Bill Stoll, whuxlm!wws.
  24.  *
  25.  *            Masscomp (and system V) mods by Stan Barber, neuro1!sob.
  26.  *
  27.  *            Bug fix for setuid bit and flag mods, and for
  28.  *            misplaced include of time.h, okstate!zap.
  29.  *            Note: I left SINCE as a compile-time option; it
  30.  *            probably shouldn't even be there. ---Rsk
  31.  *
  32.  *            (void)'s added to make lint happy, pur-ee!rsk.
  33.  *
  34.  *            Still doesn't run under 2.9; to be fixed soon.
  35.  *
  36.  *
  37.  *    Vanilla version is for system V.
  38.  *     Define BSD42 for 4.2bsd version.
  39.  *    Define SINCE for "elapsed time" since inode times.
  40.  *    Define MASSCOMP for those machines; this implies system V.
  41.  */
  42.  
  43. #ifdef MASSCOMP
  44. #undef BSD42
  45. #endif MASSCOMP
  46.  
  47. #include    <stdio.h>
  48. #include    <sys/time.h>
  49. #include    <sys/types.h>
  50. #include    <ctype.h>
  51. #include    <sys/stat.h>
  52. #include    <pwd.h>
  53. #include    <grp.h>
  54.  
  55. #define    FAIL    -1        /* Failure return code from call */    
  56. #define OKAY    0        /* Success return code from call */
  57.  
  58. struct     stat    Sbuf;        /* for return values from stat() call */
  59. char    *ctime();        /* Time conversion    */
  60. struct    passwd    *getpwuid();    /* User entry */
  61. struct    passwd    *pwent;        /* User structure */
  62. struct    group    *getgrgid();    /* Group entry */
  63. struct    group    *grent;        /* Group structure */
  64.  
  65. char    Mode[10];    /* File protection mode */
  66.  
  67. #define    LBUFSIZ    256    /* Length for symbolic link translation buffer */
  68. char    Lbuf[LBUFSIZ];    /* Symbolic link translation buffer */
  69.  
  70. main(argc, argv)
  71. int argc;
  72. char *argv[];
  73. {
  74.     int i;
  75.  
  76.     i = 1;
  77.  
  78.     if(argc == 1) {
  79.         (void) fprintf(stderr,"Usage: stat file1 [file2 ...]\n");
  80.         exit(1);
  81.     }
  82.  
  83.     do {
  84.  
  85.         (void) stat_it(argv[i]);
  86.  
  87.         if(  (argc > 1) && (i < (argc-1)) )
  88.             (void) printf("\n");
  89.     }
  90.     while(++i < argc);
  91.  
  92.     exit(0);
  93. }
  94.  
  95. /*
  96.  * stat_it() - Actually stat and format results from file.
  97.  *        exit -    OKAY if no problems encountered
  98.  *              FAIL if couldn't open or other nastiness
  99.  *
  100.  */
  101. stat_it(filename)
  102. char    *filename;
  103. {
  104.     int    count;
  105.  
  106. #ifdef BSD42
  107.     if( lstat(filename,&Sbuf) == FAIL) {
  108.         (void) fprintf(stderr,"Can't lstat %s\n",filename); 
  109.         return(FAIL);
  110.     }
  111. #else BSD42
  112.     if( stat(filename,&Sbuf) == FAIL) {
  113.         (void) fprintf(stderr,"Can't stat %s\n",filename); 
  114.         return(FAIL);
  115.     }
  116. #endif BSD42
  117.  
  118. #ifdef BSD42
  119.     if( (Sbuf.st_mode & S_IFMT) == S_IFLNK) {
  120.         if( (count=readlink(filename,Lbuf,LBUFSIZ)) == FAIL) {
  121.             (void) fprintf(stderr,"Can't readlink %s\n", filename);
  122.             return(FAIL);
  123.         }
  124.         if( count < LBUFSIZ)
  125.             Lbuf[count] = '\0';
  126.         (void) printf("  File: \"%s\" -> \"%s\"\n",filename,Lbuf);
  127.     }
  128.     else
  129. #endif BSD42
  130.         (void) printf("  File: \"%s\"\n", filename);
  131.  
  132.     (void) printf("  Size: %-10d", Sbuf.st_size);
  133. #ifdef BSD42
  134.      (void) printf("   Allocated Blocks: %-10ld", Sbuf.st_blocks);
  135. #endif BSD42
  136.  
  137.     (void) printf("   Filetype: ");
  138.     switch( Sbuf.st_mode & S_IFMT) {
  139.         case    S_IFDIR:    (void) printf("Directory\n");
  140.                     break;
  141.         case    S_IFCHR:    (void) printf("Character Device\n");
  142.                     break;
  143.         case    S_IFBLK:    (void) printf("Block Device\n");
  144.                     break;
  145.         case    S_IFREG:    (void) printf("Regular File\n");
  146.                     break;
  147. #ifdef BSD42
  148.         case    S_IFLNK:    (void) printf("Symbolic Link\n");
  149.                     break;
  150.         case    S_IFSOCK:    (void) printf("Socket\n");
  151.                     break;
  152. #else BSD42
  153.         case    S_IFIFO:    (void) printf("Fifo File\n");
  154.                     break;
  155. #endif BSD42
  156. #ifdef MASSCOMP
  157.         case    S_IFCTG:    (void) printf("Contiguous File\n");
  158.                     break;
  159. #endif MASSCOMP
  160.         default        :    (void) printf("Unknown\n");
  161.     }
  162.  
  163.     (void) strcpy(Mode,"----------");
  164.     if(Sbuf.st_mode & (S_IEXEC>>6))        /* Other execute */
  165.         Mode[9] = 'x';
  166.     if(Sbuf.st_mode & (S_IWRITE>>6))    /* Other write */
  167.         Mode[8] = 'w';
  168.     if(Sbuf.st_mode & (S_IREAD>>6))        /* Other read */
  169.         Mode[7] = 'r';
  170.     if(Sbuf.st_mode & (S_IEXEC>>3))        /* Group execute */
  171.         Mode[6] = 'x';
  172.     if(Sbuf.st_mode & (S_IWRITE>>3))    /* Group write */
  173.         Mode[5] = 'w';
  174.     if(Sbuf.st_mode & (S_IREAD>>3))        /* Group read */
  175.         Mode[4] = 'r';
  176.     if(Sbuf.st_mode & S_IEXEC)        /* User execute */
  177.         Mode[3] = 'x';
  178.     if(Sbuf.st_mode & S_IWRITE)        /* User write */
  179.         Mode[2] = 'w';
  180.     if(Sbuf.st_mode & S_IREAD)        /* User read */
  181.         Mode[1] = 'r';
  182.     if(Sbuf.st_mode & S_ISVTX)        /* Sticky bit */
  183.         Mode[9] = 't';
  184.     if(Sbuf.st_mode & S_ISGID)        /* Set group id */
  185.         Mode[6] = 's';
  186.     if(Sbuf.st_mode & S_ISUID)        /* Set user id */
  187.         Mode[3] = 's';
  188.     switch( Sbuf.st_mode & S_IFMT) {
  189.         case    S_IFDIR:    Mode[0] = 'd';
  190.                     break;
  191.         case    S_IFCHR:    Mode[0] = 'c';
  192.                     break;
  193.         case    S_IFBLK:    Mode[0] = 'b';
  194.                     break;
  195.         case    S_IFREG:    Mode[0] = '-';
  196.                     break;
  197. #ifdef BSD42
  198.         case    S_IFLNK:    Mode[0] = 'l';
  199.                     break;
  200.         case    S_IFSOCK:    Mode[0] = 's';
  201.                     break;
  202. #else BSD42
  203.         case    S_IFIFO:    Mode[0] = 'f';
  204.                     break;
  205. #endif BSD42
  206. #ifdef MASSCOMP
  207.         case    S_IFCTG:    Mode[0] = 'C';
  208.                     break;
  209. #endif MASSCOMP
  210.         default        :    Mode[0] = '?';
  211.     }
  212.     (void) printf("  Mode: (%04o/%s)", Sbuf.st_mode&07777,Mode);
  213.  
  214.  
  215.     (void) setpwent();
  216.     if( (pwent = getpwuid(Sbuf.st_uid)) == NULL) {
  217.         (void) fprintf(stderr,"getpwuid() failed\n");
  218.         exit(1);
  219.     }
  220.     (void) printf("         Uid: (%5d/%8s)", Sbuf.st_uid, pwent->pw_name);
  221.  
  222.     (void) setgrent();
  223.     if( (grent = getgrgid(Sbuf.st_gid)) == NULL) {
  224.         (void) fprintf(stderr,"getgrgid() failed\n");
  225.         exit(1);
  226.     }
  227.     (void) printf("  Gid: (%5d/%8s)\n", Sbuf.st_gid, grent->gr_name);
  228.  
  229.  
  230.     (void) printf("Device: %-5d", Sbuf.st_dev);
  231.     (void) printf("  Inode: %-10d", Sbuf.st_ino);
  232.     (void) printf("Links: %-5d", Sbuf.st_nlink);
  233.  
  234.     /* Only meaningful if file is device */
  235.  
  236.     if(  ( (Sbuf.st_mode & S_IFMT) == S_IFCHR)
  237.         || ( (Sbuf.st_mode & S_IFMT) == S_IFBLK) )
  238.         (void) printf("     Device type: %d\n",Sbuf.st_rdev);
  239.     else
  240.         (void) printf("\n");
  241.  
  242.     /* The %.24s strips the newline from the ctime() string */
  243.  
  244. #ifdef SINCE
  245.     (void) printf("Access: %.24s",ctime(&Sbuf.st_atime));
  246.     (void) tsince(Sbuf.st_atime);
  247.     (void) printf("Modify: %.24s",ctime(&Sbuf.st_mtime));
  248.     (void) tsince(Sbuf.st_mtime);
  249.     (void) printf("Change: %.24s",ctime(&Sbuf.st_ctime));
  250.     (void) tsince(Sbuf.st_ctime);
  251. #else SINCE
  252.     (void) printf("Access: %s",ctime(&Sbuf.st_atime));
  253.     (void) printf("Modify: %s",ctime(&Sbuf.st_mtime));
  254.     (void) printf("Change: %s",ctime(&Sbuf.st_ctime));
  255. #endif SINCE
  256.  
  257. /*
  258. *     Should I put this in somewhere?  No.
  259. *
  260. *     printf("Optimal Blocksize: %ld\n", Sbuf.st_blksize);
  261. */
  262.  
  263.     return(OKAY);
  264. }
  265.  
  266. #ifdef SINCE
  267. tsince(time_sec)
  268. long    time_sec;
  269. {
  270.     long    time_buf;
  271.     long    d_since;    /* days elapsed since time */
  272.     long    h_since;    /* hours elapsed since time */
  273.     long    m_since;    /* minutes elapsed since time */
  274.     long    s_since;    /* seconds elapsed since time */
  275.  
  276.     (void) time(&time_buf);
  277.  
  278.     if(time_sec > time_buf) {
  279.         (void) fprintf(stderr,"Time going backwards\n");
  280.         exit(1);
  281.     }
  282.  
  283.     s_since = time_buf - time_sec;
  284.     d_since = s_since / 86400l ;
  285.     s_since -= d_since * 86400l ;
  286.     h_since = s_since / 3600l ;
  287.     s_since -= h_since * 3600l ;
  288.     m_since = s_since / 60l ;
  289.     s_since -= m_since * 60l ;
  290.  
  291.     (void) printf("(%05ld.%02ld:%02ld:%02ld)\n",d_since,h_since,m_since,s_since);
  292.  
  293.     return(OKAY);
  294. }
  295. #endif SINCE
  296. -- 
  297. Rich Kulawiec pur-ee!rsk purdue-!rsk rsk@purdue-asc.arpa rsk@asc.purdue.edu
  298.