stat.c

Go to the documentation of this file.
00001 /* stat.c Feb 1987 - main, printit, statit
00002  *
00003  * stat - a program to perform what the stat(2) call does.  
00004  *
00005  * usage: stat [-] [-all] -<field> [-<field> ...] [file1 file2 file3 ...]
00006  *
00007  * where   <field> is one of the struct stat fields without the leading "st_".
00008  *         The three times can be printed out as human times by requesting
00009  *         -Ctime instead of -ctime (upper case 1st letter).
00010  *         - means take the file names from stdin.
00011  *         -0.. means fd0..
00012  *         no files means all fds.
00013  *
00014  * output: if only one field is specified, that fields' contents are printed.
00015  *         if more than one field is specified, the output is
00016  *         file filed1: f1val, field2: f2val, etc
00017  *
00018  * written: Larry McVoy, (mcvoy@rsch.wisc.edu)  
00019  */
00020 
00021 # define        ALLDEF          /* Make -all default. (kjb) */
00022 
00023 # include       <sys/types.h>
00024 # include       <errno.h>
00025 # include       <limits.h>
00026 # include       <stdio.h>
00027 # include       <stdlib.h>
00028 # include       <unistd.h>
00029 # include       <string.h>
00030 # include       <time.h>
00031 # include       <sys/stat.h>
00032 # define        addr(x)         ((void*) &sbuf.x)
00033 # define        size(x)         sizeof(sbuf.x)
00034 # define        equal(s, t)     (strcmp(s, t) == 0)
00035 # ifndef PATH_MAX
00036 #  define       PATH_MAX        1024
00037 # endif
00038 # undef         LS_ADDS_SPACE   /* AT&T Unix PC, ls prints "file[* /]" */
00039                                 /* This makes stat fail. */
00040 
00041 # ifndef _MINIX                 /* All but Minix have u_* and st_blocks */
00042 #  define BSD
00043 # endif
00044 
00045 # ifndef S_IREAD
00046 #  define S_IREAD       S_IRUSR
00047 #  define S_IWRITE      S_IWUSR
00048 #  define S_IEXEC       S_IXUSR
00049 # endif
00050 
00051 char *      arg0;
00052 struct stat sbuf;
00053 extern int  errno;
00054 int         first_file= 1;
00055 #ifndef S_IFLNK
00056 #define lstat   stat
00057 #endif
00058 
00059 struct field {
00060     char* f_name;       /* field name in stat */
00061     u_char* f_addr;     /* address of the field in sbuf */
00062     u_short f_size;     /* size of the object, needed for pointer arith */
00063     u_short f_print;    /* show this field? */
00064 } fields[] = {
00065     { "dev",            addr(st_dev),           size(st_dev),           0 },
00066     { "ino",            addr(st_ino),           size(st_ino),           0 },
00067     { "mode",           addr(st_mode),          size(st_mode),          0 },
00068     { "nlink",          addr(st_nlink),         size(st_nlink),         0 },
00069     { "uid",            addr(st_uid),           size(st_uid),           0 },
00070     { "gid",            addr(st_gid),           size(st_gid),           0 },
00071     { "rdev",           addr(st_rdev),          size(st_rdev),          0 },
00072     { "size",           addr(st_size),          size(st_size),          0 },
00073     { "Atime",          addr(st_atime),         size(st_atime),         0 },
00074     { "atime",          addr(st_atime),         size(st_atime),         0 },
00075     { "Mtime",          addr(st_mtime),         size(st_mtime),         0 },
00076     { "mtime",          addr(st_mtime),         size(st_mtime),         0 },
00077     { "Ctime",          addr(st_ctime),         size(st_ctime),         0 },
00078     { "ctime",          addr(st_ctime),         size(st_ctime),         0 },
00079 # ifdef BSD
00080     { "blksize",        addr(st_blksize),       size(st_blksize),       0 },
00081     { "blocks",         addr(st_blocks),        size(st_blocks),        0 },
00082 # endif
00083     { NULL,             0,                      0,                      0 },
00084 };
00085     
00086 void printstat(struct stat *sbuf, int nprint);
00087 void printit(struct stat* sb, struct field* f, int n);
00088 void rwx(mode_t mode, char *bit);
00089 void usage(void);
00090 
00091 int do_readlink=0;
00092 
00093 int main(int ac, char** av)
00094 {
00095     int      i, j, nprint = 0, files = 0;
00096     char     buf[PATH_MAX], *check;
00097     int      sym=0, ret=0, from_stdin = 0;
00098     int      err;
00099     u_long   fd;
00100 
00101     if ((arg0 = strrchr(av[0], '/')) == NULL) arg0 = av[0]; else arg0++;
00102 #ifdef S_IFLNK
00103     if (equal(arg0, "lstat")) sym = 1;
00104     if (equal(arg0, "readlink")) do_readlink = 1;
00105 #endif
00106 
00107     if (ac > 1 && equal(av[i = 1], "-"))
00108         i++, from_stdin++;
00109 
00110     for (i= 1; i<ac; i++)  {
00111         if (av[i][0] == '-')  {
00112             if (equal(av[i], "-")) {
00113                 from_stdin= 1;
00114                 files++;
00115                 continue;
00116             }
00117             if (equal("-all", av[i])) {
00118                 for (j=0; fields[j].f_name; j++)
00119                     nprint++, fields[j].f_print++;
00120                 continue;
00121             }
00122             if (equal("-s", av[i])) {
00123 #ifdef S_IFLNK
00124                 sym=1;
00125 #endif
00126                 continue;
00127             }
00128             fd = strtoul(av[i]+1, &check, 0);
00129             if (check != av[i]+1 && *check == '\0')
00130             {
00131                 files++;
00132                 continue;
00133             }
00134             for (j=0; fields[j].f_name; j++) 
00135                 if (equal(fields[j].f_name, &av[i][1])) {
00136                     nprint++, fields[j].f_print++;
00137                     break;
00138                 }
00139             if (!fields[j].f_name) {
00140                 if (!equal("-?", av[i])) {
00141                     fprintf(stderr, "stat: %s: bad field\n", av[i]);
00142                 }
00143                 usage();
00144             }
00145         }
00146         else 
00147             files++;
00148     }
00149     if (!nprint) {
00150 # ifndef ALLDEF
00151         usage();
00152 # else
00153         for (j=0; fields[j].f_name; j++)
00154             nprint++, fields[j].f_print++;
00155 # endif
00156     }
00157 
00158     if (from_stdin)
00159         files++;        /* We don't know how many files come from stdin. */
00160 
00161     if (files == 0) {   /* Stat all file descriptors. */
00162         if(do_readlink) return 0;
00163         for (i= 0; i<OPEN_MAX; i++) {
00164             err= fstat(i, &sbuf);
00165             if (err == -1 && errno == EBADF)
00166                 continue;
00167             if (err == 0) {
00168                 if (!first_file) fputc('\n', stdout);
00169                 printf("fd %d:\n", i);
00170                 printstat(&sbuf, nprint);
00171             }
00172             else {
00173                 fprintf(stderr, "%s: fd %d: %s\n", arg0, i, strerror(errno));
00174                 ret= 1;
00175             }
00176         }
00177         exit(ret);
00178     }
00179                 
00180     for (i=1; i<ac; i++) {
00181         if (equal(av[i], "-")) {
00182             while (fgets(buf, sizeof(buf), stdin)) {
00183                 char *p= strchr(buf, '\n');
00184                 if (p) *p= 0;
00185 #ifdef S_IFLNK
00186                 if(do_readlink) {
00187                         char sbuf[300];
00188                         int n;
00189                         if((n=readlink(buf, sbuf, sizeof(sbuf)-1)) < 0) {
00190                                 perror(buf);
00191                                 continue;
00192                         }
00193                         sbuf[n] = '\0';
00194                         printf("%s: %s\n", buf, sbuf);
00195                         continue;
00196                 }
00197 #endif
00198                 if (!sym) err= stat(av[i], &sbuf);
00199                 if (sym || (err != 0 && errno == ENOENT)) {
00200                     err= lstat(av[i], &sbuf);
00201                 }
00202                 if (err == -1) {
00203                     fprintf(stderr, "%s: %s: %s\n",
00204                         arg0, av[i], strerror(errno));
00205                     ret= 1;
00206                 }
00207                 else {
00208                     if (!first_file) fputc('\n', stdout);
00209                     printf("%s:\n", buf);
00210                     printstat(&sbuf, nprint);
00211                 }
00212             }
00213             continue;
00214         }
00215         if (av[i][0] == '-') {
00216             fd= strtoul(av[i]+1, &check, 10);
00217             if (check == av[i]+1 || *check != '\0') continue;
00218             if (fd >= INT_MAX) {
00219                 err= -1;
00220                 errno= EBADF;
00221             }
00222             else {
00223                 err= fstat((int) fd, &sbuf);
00224             }
00225             if (err != -1) {
00226                 if (!first_file) fputc('\n', stdout);
00227                 if (files != 1) printf("fd %lu:\n", fd);
00228                 printstat(&sbuf, nprint);
00229             }
00230             else {
00231                 fprintf(stderr, "fd %lu: %s\n", fd, strerror(errno));
00232                 ret= 1;
00233             }
00234             continue;
00235         }
00236         if(do_readlink) {
00237                 char sbuf[300];
00238                 int n;
00239                 if((n=err=readlink(av[i], sbuf, sizeof(sbuf)-1)) < 0) {
00240                         perror(av[i]);
00241                         continue;
00242                 }
00243                 sbuf[n] = '\0';
00244                 printf("%s: %s\n", av[i], sbuf);
00245                 continue;
00246         }
00247         if (!sym) err= stat(av[i], &sbuf);
00248         if (sym || (err != 0 && errno == ENOENT)) err= lstat(av[i], &sbuf);
00249         if (err != -1) {
00250             if (!first_file) fputc('\n', stdout);
00251             if (files != 1) printf("%s:\n", av[i]);
00252             printstat(&sbuf, nprint);
00253         }
00254         else {
00255             fprintf(stderr, "%s: %s: %s\n", arg0, av[i], strerror(errno));
00256             ret= 1;
00257         }
00258     }
00259     exit(ret);
00260 }
00261 
00262 /*------------------------------------------------------------------30/Jan/87-*
00263  * printstat(file, nprint) - do the work
00264  *----------------------------------------------------------------larry mcvoy-*/
00265 void printstat(struct stat *sbuf, int nprint)
00266 {
00267     int      j;
00268     int      first_field= 1;
00269 
00270     for (j=0; fields[j].f_name; j++) {
00271         if (fields[j].f_print) {
00272             if (!first_field) fputc('\n', stdout);
00273             printit(sbuf, &fields[j], nprint);
00274             first_field= 0;
00275         }
00276     }
00277     fputc('\n', stdout);
00278     first_file= 0;
00279 }
00280 
00281 /*------------------------------------------------------------------30/Jan/87-*
00282  * printit(sb, f, n) - print the field
00283  *
00284  * Inputs    -> (struct stat*), (struct field*), (int)
00285  *
00286  * Results   -> Displays the field, with special handling of weird fields like
00287  *              mode and mtime.  The mode field is dumped in octal, followed
00288  *              by one or more of the S_IF<X> and/or S_I<X> values.
00289  *----------------------------------------------------------------larry mcvoy-*/
00290 void printit(struct stat* sb, struct field* f, int n)
00291 {
00292     if (n > 1)
00293         printf("%s: ", f->f_name);
00294     if (equal(f->f_name, "mode")) {
00295                 /* This lot changed to my personal liking. (kjb) */
00296         char bit[11];
00297 
00298         printf("%07lo, ", (u_long) sb->st_mode);
00299 
00300         strcpy(bit, "----------");
00301 
00302         switch (sb->st_mode&S_IFMT) {
00303         case S_IFDIR:   bit[0]='d';     break;
00304 # ifdef S_IFFIFO
00305         case S_IFFIFO:  bit[0]='p';     break;
00306 # endif
00307         case S_IFCHR:   bit[0]='c';     break;
00308         case S_IFBLK:   bit[0]='b';     break;
00309 # ifdef S_IFSOCK
00310         case S_IFSOCK:  bit[0]='S';     break;
00311 # endif
00312 # ifdef S_IFMPC
00313         case S_IFMPC:   bit[0]='C';     break;
00314 # endif
00315 # ifdef S_IFMPB
00316         case S_IFMPB:   bit[0]='B';     break;
00317 # endif
00318 # ifdef S_IFLNK
00319         case S_IFLNK:   bit[0]='l';     break;
00320 # endif
00321         }
00322         rwx(sb->st_mode, bit+1);
00323         rwx(sb->st_mode<<3, bit+4);
00324         rwx(sb->st_mode<<6, bit+7);
00325         if (sb->st_mode&S_ISUID)        bit[3]='s';
00326         if (sb->st_mode&S_ISGID)        bit[6]='s';
00327         if (sb->st_mode&S_ISVTX)        bit[9]='t';
00328         printf("\"%s\"", bit);
00329     }
00330     /* times in human form, uppercase first letter */
00331     else if (equal("Ctime", f->f_name)) {
00332         printf("%.24s (%lu)", ctime(&sb->st_ctime), (u_long) sb->st_ctime);
00333         f[1].f_print= 0;
00334     }
00335     else if (equal("Mtime", f->f_name)) {
00336         printf("%.24s (%lu)", ctime(&sb->st_mtime), (u_long) sb->st_mtime);
00337         f[1].f_print= 0;
00338     }
00339     else if (equal("Atime", f->f_name)) {
00340         printf("%.24s (%lu)", ctime(&sb->st_atime), (u_long) sb->st_atime);
00341         f[1].f_print= 0;
00342     }
00343     else if (equal("ctime", f->f_name)) {
00344         printf("%lu", (u_long) sb->st_ctime);
00345     }
00346     else if (equal("mtime", f->f_name)) {
00347         printf("%lu", (u_long) sb->st_mtime);
00348     }
00349     else if (equal("atime", f->f_name)) {
00350         printf("%lu", (u_long) sb->st_atime);
00351     }
00352     else {
00353         switch (f->f_size) {
00354         case sizeof(char):
00355             printf("%d", * (u_char *) f->f_addr);
00356             break;
00357         case sizeof(short):
00358             printf("%u", (u_int) * (u_short *) f->f_addr);
00359             break;
00360 #if INT_MAX != SHRT_MAX
00361         case sizeof(int):
00362             printf("%u", * (u_int *) f->f_addr);
00363             break;
00364 #endif
00365 #if LONG_MAX != INT_MAX && LONG_MAX != SHRT_MAX
00366         case sizeof(long):
00367             printf("%lu", * (u_long *) f->f_addr);
00368             break;
00369 #endif
00370         default:
00371             fprintf(stderr, "\nProgram error: bad '%s' field size %d\n", 
00372                             f->f_name, f->f_size);
00373             break;
00374         }
00375     }
00376 }
00377 
00378 void rwx(mode_t mode, char *bit)
00379 {
00380         if (mode&S_IREAD)       bit[0]='r';
00381         if (mode&S_IWRITE)      bit[1]='w';
00382         if (mode&S_IEXEC)       bit[2]='x';
00383 }
00384 
00385 void usage(void)
00386 {
00387     fprintf(stderr,
00388         "Usage: %s [-] [-fd] [-all] [-s] [-field ...] [file1 ...]\n", 
00389         arg0);
00390     exit(1);
00391 }

Generated on Fri Apr 14 22:57:11 2006 for minix by  doxygen 1.4.6