Whamcloud - gitweb
landing b_cmobd_merge on HEAD
[fs/lustre-release.git] / lustre / tests / stat.c
1 #include <stdio.h>
2 #include <sys/stat.h>
3 #include <sys/sysmacros.h>
4 #include <pwd.h>
5 #include <grp.h>
6 #include <unistd.h>
7 #include <time.h>
8 #include <sys/vfs.h>
9 #include <string.h>
10 #include <malloc.h>
11 #include <ctype.h>
12 #include <stdlib.h>
13
14 #ifdef FLASK_LINUX
15 #include <selinux/fs_secure.h>
16 #include <linux/flask/security.h>
17 #include <selinux/flask_util.h>           /* for is_flask_enabled() */
18 #define SECURITY_ID_T security_id_t
19 #else
20 #define SECURITY_ID_T int
21 #endif
22
23 #include "stat_fs.h"
24
25 void print_human_type(unsigned short mode)
26 {
27   switch (mode & S_IFMT)
28     {
29     case S_IFDIR:
30       printf ("Directory");
31       break;
32     case S_IFCHR:
33       printf ("Character Device");
34       break;
35     case S_IFBLK:
36       printf ("Block Device");
37       break;
38     case S_IFREG:
39       printf ("Regular File");
40       break;
41     case S_IFLNK:
42       printf ("Symbolic Link");
43       break;
44     case S_IFSOCK:
45       printf ("Socket");
46       break;
47     case S_IFIFO:
48       printf ("Fifo File");
49       break;
50     default:
51       printf ("Unknown");
52     }
53 }
54
55 void print_human_fstype(struct statfs *statfsbuf)
56 {
57   char *type;
58   
59   switch (statfsbuf->f_type)
60 #if defined (__linux__)
61   {
62         case S_MAGIC_AFFS:
63           type = strdup("affs");
64           break;
65         case S_MAGIC_EXT:
66           type = strdup("ext");
67           break;
68         case S_MAGIC_EXT2_OLD:
69           type = strdup("ext2");
70           break;
71         case S_MAGIC_EXT2:
72           type = strdup("ext2/ext3");
73           break;
74         case S_MAGIC_HPFS:
75           type = strdup("hpfs");
76           break;
77         case S_MAGIC_ISOFS:
78           type = strdup("isofs");
79           break;
80         case S_MAGIC_ISOFS_WIN:
81           type = strdup("isofs");
82           break;
83         case S_MAGIC_ISOFS_R_WIN:
84           type = strdup("isofs");
85           break;
86         case S_MAGIC_MINIX:
87           type = strdup("minix");
88         case S_MAGIC_MINIX_30:
89           type = strdup("minix (30 char.)");
90           break;
91         case S_MAGIC_MINIX_V2:
92           type = strdup("minix v2");
93           break;
94         case S_MAGIC_MINIX_V2_30:
95           type = strdup("minix v2 (30 char.)");
96           break;
97         case S_MAGIC_MSDOS:
98           type = strdup("msdos");
99           break;
100         case S_MAGIC_FAT:
101           type = strdup("fat");
102           break;
103         case S_MAGIC_NCP:
104           type = strdup("novell");
105           break;
106         case S_MAGIC_NFS:
107           type = strdup("nfs");
108           break;
109         case S_MAGIC_PROC:
110           type = strdup("proc");
111           break;
112         case S_MAGIC_SMB:
113           type = strdup("smb");
114           break;
115         case S_MAGIC_XENIX:
116           type = strdup("xenix");
117           break;
118         case S_MAGIC_SYSV4:
119           type = strdup("sysv4");
120           break;
121         case S_MAGIC_SYSV2:
122           type = strdup("sysv2");
123           break;
124         case S_MAGIC_COH:
125           type = strdup("coh");
126           break;
127         case S_MAGIC_UFS:
128           type = strdup("ufs");
129           break;
130         case S_MAGIC_XIAFS:
131           type = strdup("xia");
132           break;
133         case S_MAGIC_NTFS:
134           type = strdup("ntfs");
135           break;
136         case S_MAGIC_TMPFS:
137           type = strdup("tmpfs");
138           break;
139         case S_MAGIC_REISERFS:
140           type = strdup("reiserfs");
141           break;
142         case S_MAGIC_CRAMFS:
143           type = strdup("cramfs");
144           break;
145         case S_MAGIC_ROMFS:
146           type = strdup("romfs");
147           break;
148         case S_MAGIC_LUSTRE:
149           type = strdup("lustre");
150           break;
151 #elif __GNU__
152         case FSTYPE_UFS:
153           type = strdup("ufs");
154           break;
155         case FSTYPE_NFS:
156           type = strdup("nfs");
157           break;
158         case FSTYPE_GFS:
159           type = strdup("gfs");
160           break;
161         case FSTYPE_LFS:
162           type = strdup("lfs");
163           break;
164         case FSTYPE_SYSV:
165           type = strdup("sysv");
166           break;
167         case FSTYPE_FTP:
168           type = strdup("ftp");
169           break;
170         case FSTYPE_TAR:
171           type = strdup("tar");
172           break;
173         case FSTYPE_AR:
174           type = strdup("ar");
175           break;
176         case FSTYPE_CPIO:
177           type = strdup("cpio");
178           break;
179         case FSTYPE_MSLOSS:
180           type = strdup("msloss");
181           break;
182         case FSTYPE_CPM:
183           type = strdup("cpm");
184           break;
185         case FSTYPE_HFS:
186           type = strdup("hfs");
187           break;
188         case FSTYPE_DTFS:
189           type = strdup("dtfs");
190           break;
191         case FSTYPE_GRFS:
192           type = strdup("grfs");
193           break;
194         case FSTYPE_TERM:
195           type = strdup("term");
196           break;
197         case FSTYPE_DEV:
198           type = strdup("dev");
199           break;
200         case FSTYPE_PROC:
201           type = strdup("proc");
202           break;
203         case FSTYPE_IFSOCK:
204           type = strdup("ifsock");
205           break;
206         case FSTYPE_AFS:
207           type = strdup("afs");
208           break;
209         case FSTYPE_DFS:
210           type = strdup("dfs");
211           break;
212         case FSTYPE_PROC9:
213           type = strdup("proc9");
214           break;
215         case FSTYPE_SOCKET:
216           type = strdup("socket");
217           break;
218         case FSTYPE_MISC:
219           type = strdup("misc");
220           break;
221         case FSTYPE_EXT2FS:
222           type = strdup("ext2/ext3");
223           break;
224         case FSTYPE_HTTP:
225           type = strdup("http");
226           break;
227         case FSTYPE_MEMFS:
228           type = strdup("memfs");
229           break;
230         case FSTYPE_ISO9660:
231           type = strdup("iso9660");
232           break;
233 #endif
234         default:
235           if ((type = (char*)malloc(30 * sizeof(char))) == NULL) {
236                 perror("malloc error");
237                 return;
238           }
239           sprintf (type, "UNKNOWN (0x%x)\n", (int)statfsbuf->f_type);
240   }
241
242   printf("%s", type);
243   free(type);
244 }
245
246 void print_human_access(struct stat *statbuf)
247 {
248   char access[11];
249
250   access[10] = 0;
251   access[9] = (statbuf->st_mode & S_IXOTH) ?
252     ((statbuf->st_mode & S_ISVTX) ? 't' : 'x') :
253     ((statbuf->st_mode & S_ISVTX) ? 'T' : '-');
254   access[8] = (statbuf->st_mode & S_IWOTH) ? 'w' : '-';
255   access[7] = (statbuf->st_mode & S_IROTH) ? 'r' : '-';
256   access[6] = (statbuf->st_mode & S_IXGRP) ?
257     ((statbuf->st_mode & S_ISGID) ? 's' : 'x') :
258     ((statbuf->st_mode & S_ISGID) ? 'S' : '-');
259   access[5] = (statbuf->st_mode & S_IWGRP) ? 'w' : '-';
260   access[4] = (statbuf->st_mode & S_IRGRP) ? 'r' : '-';
261   access[3] = (statbuf->st_mode & S_IXUSR) ?
262     ((statbuf->st_mode & S_ISUID) ? 's' : 'x') :
263     ((statbuf->st_mode & S_ISUID) ? 'S' : '-');
264   access[2] = (statbuf->st_mode & S_IWUSR) ? 'w' : '-';
265   access[1] = (statbuf->st_mode & S_IRUSR) ? 'r' : '-';
266
267   switch (statbuf->st_mode & S_IFMT)
268     {
269     case S_IFDIR:
270       access[0] = 'd';
271       break;
272     case S_IFCHR:
273       access[0] = 'c';
274       break;
275     case S_IFBLK:
276       access[0] = 'b';
277       break;
278     case S_IFREG:
279       access[0] = '-';
280       break;
281     case S_IFLNK:
282       access[0] = 'l';
283       break;
284     case S_IFSOCK:
285       access[0] = 's';
286       break;
287     case S_IFIFO:
288       access[0] = 'p';
289       break;
290     default:
291       access[0] = '?';
292     }
293     printf (access);
294 }
295
296 /* trick gcc into being unable to recognize the %c format so it doesn't
297  * issue its inane warning about %c and two-digit year representations. */
298 static size_t strftime_wrapper(char *s, size_t max, const char *fmt,
299                                struct tm *tm) {
300         return strftime(s, max, fmt, tm);
301 }
302
303 void print_human_time(time_t *t)
304 {
305   char str[40];
306
307   if (strftime_wrapper(str, 40, "%c", localtime(t)) > 0)
308           printf(str);
309   else
310           printf("Cannot calculate human readable time, sorry");
311 }
312
313 /* print statfs info */
314 void print_statfs(char *pformat, char m, char *filename, void *data, SECURITY_ID_T sid)
315 {
316     struct statfs *statfsbuf = (struct statfs*)data;
317 #ifdef FLASK_LINUX
318     char sbuf[256];
319     int rv;
320     unsigned int sbuflen = sizeof(sbuf);
321 #endif
322
323     switch(m) {
324         case 'n':
325             strcat(pformat, "s");
326             printf(pformat, filename);
327             break;
328 #if !defined(__linux__) && defined (__GNU__)
329         case 'i':
330             strcat(pformat, "Lx");
331             printf(pformat, statfsbuf->f_fsid);
332             break;
333 #else
334         case 'i':
335             strcat(pformat, "x %-8x");
336             printf(pformat, statfsbuf->f_fsid.__val[0], statfsbuf->f_fsid.__val[1]);
337             break;
338 #endif
339
340         case 'l':
341 #ifdef __USE_FILE_OFFSET64
342             strcat(pformat, "lu");
343 #else
344             strcat(pformat, "d");
345 #endif
346             printf(pformat, statfsbuf->f_namelen);
347             break;
348         case 't':
349 #ifdef __USE_FILE_OFFSET64
350             strcat(pformat, "lx");
351 #else
352             strcat(pformat, "x");
353 #endif
354             printf(pformat, statfsbuf->f_type);
355             break;
356         case 'T':
357 /*          print_human_fstype(statfsbuf, pformat);*/
358             print_human_fstype(statfsbuf);
359             break;
360         case 'b':
361 #ifdef __USE_FILE_OFFSET64
362             strcat(pformat, "lld");
363 #else
364 #if !defined(__linux__) && defined (__GNU__)
365             strcat(pformat, "d");
366 #else
367             strcat(pformat, "ld");
368 #endif
369 #endif
370             printf(pformat, statfsbuf->f_blocks);
371             break;
372         case 'f':
373 #ifdef __USE_FILE_OFFSET64
374             strcat(pformat, "lld");
375 #else
376 #if !defined(__linux__) && defined (__GNU__)
377             strcat(pformat, "d");
378 #else
379             strcat(pformat, "ld");
380 #endif
381 #endif
382             printf(pformat, statfsbuf->f_bfree);
383             break;
384         case 'a':
385 #ifdef __USE_FILE_OFFSET64
386             strcat(pformat, "lld");
387 #else
388 #if !defined(__linux__) && defined (__GNU__)
389             strcat(pformat, "d");
390 #else
391             strcat(pformat, "ld");
392 #endif
393 #endif
394             printf(pformat, statfsbuf->f_bavail);
395             break;
396         case 's':
397 #ifdef __USE_FILE_OFFSET64
398             strcat(pformat, "ld");
399 #else
400             strcat(pformat, "d");
401 #endif
402             printf(pformat, statfsbuf->f_bsize);
403             break;
404         case 'c':
405 #ifdef __USE_FILE_OFFSET64
406             strcat(pformat, "lld");
407 #else
408 #if !defined(__linux__) && defined (__GNU__)
409             strcat(pformat, "d");
410 #else
411             strcat(pformat, "ld");
412 #endif
413 #endif
414             printf(pformat, statfsbuf->f_files);
415             break;
416         case 'd':
417 #ifdef __USE_FILE_OFFSET64
418             strcat(pformat, "lld");
419 #else
420 #if !defined(__linux__) && defined (__GNU__)
421             strcat(pformat, "d");
422 #else
423             strcat(pformat, "ld");
424 #endif
425 #endif
426             printf(pformat, statfsbuf->f_ffree);
427             break;
428 #ifdef FLASK_LINUX
429         case 'S':
430             strcat(pformat, "d");
431             printf(pformat, sid);
432             break;
433         case 'C':
434             rv = security_sid_to_context(sid, (security_context_t *) &sbuf, &sbuflen);
435             if ( rv < 0 )
436                 sprintf(sbuf, "<error finding security context %d>", sid);
437             printf(sbuf);
438             break;
439 #endif
440         default:
441             strcat(pformat, "c");
442             printf(pformat, m);
443             break;
444     }
445 }
446
447 /* print stat info */
448 void print_stat(char *pformat, char m, char *filename, void *data, SECURITY_ID_T sid)
449 {
450     char linkname[256];
451     int i;
452     struct stat *statbuf = (struct stat*)data;
453     struct passwd *pw_ent;
454     struct group *gw_ent;
455 #ifdef FLASK_LINUX
456     char sbuf[256];
457     int rv;
458     unsigned int sbuflen = sizeof(sbuf);
459 #endif
460
461     switch(m) {
462         case 'n':
463             strcat(pformat, "s");
464             printf(pformat, filename);
465             break;
466         case 'N':
467             strcat(pformat, "s");
468             if ((statbuf->st_mode & S_IFMT) == S_IFLNK) {
469                 if ((i = readlink(filename, linkname, 256)) == -1) {
470                     perror(filename);
471                     return;
472                 }
473                 linkname[(i >= 256) ? 255 : i] = '\0';
474                 /*printf("\"%s\" -> \"%s\"", filename, linkname);*/
475                 printf("\"");
476                 printf(pformat, filename);
477                 printf("\" -> \"");
478                 printf(pformat, linkname);
479                 printf("\"");
480             } else {
481                 printf("\"");
482                 printf(pformat, filename);
483                 printf("\"");
484             }
485             break;
486         case 'd':
487             strcat(pformat, "d");
488             printf(pformat, (int)statbuf->st_dev);
489             break;
490         case 'D':
491             strcat(pformat, "x");
492             printf(pformat, (int)statbuf->st_dev);
493             break;
494         case 'i':
495             strcat(pformat, "d");
496             printf(pformat, (int)statbuf->st_ino);
497             break;
498         case 'a':
499             strcat(pformat, "o");
500             printf(pformat, statbuf->st_mode & 07777);
501             break;
502         case 'A':
503             print_human_access(statbuf);
504             break;
505         case 'f':
506             strcat(pformat, "x");
507             printf(pformat, statbuf->st_mode);
508             break;
509         case 'F':
510             print_human_type(statbuf->st_mode);
511             break;
512         case 'h':
513             strcat(pformat, "d");
514             printf(pformat, (int)statbuf->st_nlink);
515             break;
516 #ifdef FLASK_LINUX
517         case 'S':
518             strcat(pformat, "d");
519             printf(pformat, sid);
520             break;
521         case 'C':
522             rv = security_sid_to_context(sid, (security_context_t *) &sbuf, &sbuflen);
523             if ( rv < 0 )
524                 sprintf(sbuf, "<error finding security context %d>", sid);
525             printf(sbuf);
526             break;
527 #endif
528         case 'u':
529             strcat(pformat, "d");
530             printf(pformat, statbuf->st_uid);
531             break;
532         case 'U':
533             strcat(pformat, "s");
534             setpwent();
535             pw_ent = getpwuid(statbuf->st_uid);
536             printf(pformat,
537                 (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN");
538             break;
539         case 'g':
540             strcat(pformat, "d");
541             printf(pformat, statbuf->st_gid);
542             break;
543         case 'G':
544             strcat(pformat, "s");
545             setgrent();
546             gw_ent = getgrgid(statbuf->st_gid);
547             printf(pformat,
548                 (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
549             break;
550         case 't':
551             strcat(pformat, "x");
552             printf(pformat, major(statbuf->st_rdev));
553             break;
554         case 'T':
555             strcat(pformat, "x");
556             printf(pformat, minor(statbuf->st_rdev));
557             break;
558         case 's':
559 #ifdef __USE_FILE_OFFSET64
560             strcat(pformat, "llu");
561             printf(pformat, (unsigned long long)statbuf->st_size);
562 #else
563             strcat(pformat, "u");
564             printf(pformat, (unsigned int)statbuf->st_size);
565 #endif
566             break;
567         case 'b':
568             strcat(pformat, "u");
569             printf(pformat, (unsigned int)statbuf->st_blocks);
570             break;
571         case 'o':
572             strcat(pformat, "d");
573             printf(pformat, (int)statbuf->st_blksize);
574             break;
575         case 'x':
576             print_human_time(&(statbuf->st_atime));
577             break;
578         case 'X':
579             strcat(pformat, "d");
580             printf(pformat, (int)statbuf->st_atime);
581             break;
582         case 'y':
583             print_human_time(&(statbuf->st_mtime));
584             break;
585         case 'Y':
586             strcat(pformat, "d");
587             printf(pformat, (int)statbuf->st_mtime);
588             break;
589         case 'z':
590             print_human_time(&(statbuf->st_ctime));
591             break;
592         case 'Z':
593             strcat(pformat, "d");
594             printf(pformat, (int)statbuf->st_ctime);
595             break;
596         default:
597             strcat(pformat, "c");
598             printf(pformat, m);
599             break;
600     }
601 }
602
603 void print_it(char *masterformat, char *filename,
604     void (*print_func)(char*, char, char*, void*, SECURITY_ID_T), void *data, SECURITY_ID_T sid)
605 {
606     char *m, *b, *format;
607     char pformat[65];
608
609     /* create a working copy of the format string */
610     format = strdup(masterformat);
611     if (!format) {
612         perror(filename);
613         return;
614     }
615
616     b = format;
617     while (b)
618     {
619         if ((m = strchr(b, (int)'%')) != NULL)
620         {
621             strcpy (pformat, "%");
622             *m++ = '\0';
623             printf(b);
624
625             /* copy all format specifiers to our format string */
626             while (isdigit(*m) || strchr("#0-+. I", *m))
627             {
628                 char copy[2]="a";
629
630                 *copy = *m;
631                 /* make sure the format specifier is not too long */
632                 if (strlen (pformat) > 63)
633                         fprintf(stderr, "Warning: Format specifier too long, truncating: %s\n", pformat);
634                 else
635                         strcat (pformat, copy);
636                 m++;
637             }
638
639             switch(*m) {
640                 case '\0':
641                 case '%':
642                     printf("%%");
643                     break;
644                 default:
645                     print_func(pformat, *m, filename, data, sid);
646                     break;
647             }
648             b = m + 1;
649         }
650         else
651         {
652             printf(b);
653             b = NULL;
654         }
655     }
656     free(format);
657     printf("\n");
658 }
659
660 /* stat the filesystem and print what we find */
661 void
662 do_statfs (char *filename, int terse, int secure, char *format)
663 {
664   struct statfs statfsbuf;
665   SECURITY_ID_T sid = -1;
666   int i;
667
668 #ifdef FLASK_LINUX
669   if(!is_flask_enabled())
670     secure = 0;
671   if(secure)
672     i = statfs_secure(filename, &statfsbuf, &sid);
673   else
674 #endif
675     i = statfs(filename, &statfsbuf);
676   if(i == -1)
677     {
678       perror (filename);
679       return;
680     }
681
682   if (format == NULL)
683     {
684         if (terse != 0)
685           {
686 #ifdef FLASK_LINUX
687                 if(secure)
688                         format = "%n %i %l %t %b %f %a %s %c %d %S %C";
689                 else
690 #endif
691                         format = "%n %i %l %t %b %f %a %s %c %d";
692           }
693         else
694           {
695 #ifdef FLASK_LINUX
696                 if(secure)
697                     format = "  File: \"%n\"\n"
698                          "    ID: %-8i Namelen: %-7l Type: %T\n"
699                          "Blocks: Total: %-10b Free: %-10f Available: %-10a Size: %s\n"
700                          "Inodes: Total: %-10c Free: %-10d\n"
701                          "   SID: %-14S  S_Context: %C\n";
702                 else
703 #endif
704                     format = "  File: \"%n\"\n"
705                          "    ID: %-8i Namelen: %-7l Type: %T\n"
706                          "Blocks: Total: %-10b Free: %-10f Available: %-10a Size: %s\n"
707                          "Inodes: Total: %-10c Free: %-10d";
708           }
709     }
710
711     print_it(format, filename, print_statfs, &statfsbuf, sid);
712 }
713
714 /* stat the file and print what we find */
715 void
716 do_stat (char *filename, int link, int terse, int secure, char *format)
717 {
718   struct stat statbuf;
719   int i;
720   SECURITY_ID_T sid = -1;
721   
722 #ifdef FLASK_LINUX
723   if(!is_flask_enabled())
724     secure = 0;
725   if(secure)
726     i = (link == 1) ? stat_secure(filename, &statbuf, &sid) : lstat_secure(filename, &statbuf, &sid);
727   else
728 #endif
729   i = (link == 1) ? stat(filename, &statbuf) : lstat(filename, &statbuf);
730
731   if (i == -1)
732     {
733       perror (filename);
734       return;
735     }
736
737    if (format == NULL)
738     {
739        if (terse != 0)
740        {
741 #ifdef FLASK_LINUX
742            if (secure)
743                   format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o %S %C";
744            else
745 #endif
746                   format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o";
747        }
748        else
749        {
750            /* tmp hack to match orignal output until conditional implemented */
751           i = statbuf.st_mode & S_IFMT;
752           if (i == S_IFCHR || i == S_IFBLK) {
753 #ifdef FLASK_LINUX
754                 if (secure)
755                         format =
756                            "  File: %N\n"
757                            "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
758                            "Device: %Dh/%dd\tInode: %-10i  Links: %-5h"
759                            " Device type: %t,%T\n"
760                            "Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\n"
761                            "   SID: %-14S  S_Context: %C\n"
762                            "Access: %x\n"
763                            "Modify: %y\n"
764                            "Change: %z\n";
765                 else
766 #endif
767                         format =           
768                            "  File: %N\n"
769                            "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
770                            "Device: %Dh/%dd\tInode: %-10i  Links: %-5h"
771                            " Device type: %t,%T\n"
772                            "Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\n"
773                            "Access: %x\n"
774                            "Modify: %y\n"
775                            "Change: %z\n";
776            }
777            else
778            {
779 #ifdef FLASK_LINUX
780                 if (secure)
781                        format =
782                            "  File: %N\n"
783                            "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
784                            "Device: %Dh/%dd\tInode: %-10i  Links: %-5h\n"
785                            "Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\n"
786                            "   SID: %-14S  S_Context: %C\n"
787                            "Access: %x\n"
788                            "Modify: %y\n"
789                            "Change: %z\n";
790                 else
791 #endif
792                       format =
793                            "  File: %N\n"
794                            "  Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
795                            "Device: %Dh/%dd\tInode: %-10i  Links: %-5h\n"
796                            "Access: (%04a/%10.10A)  Uid: (%5u/%8U)   Gid: (%5g/%8G)\n"
797                            "Access: %x\n"
798                            "Modify: %y\n"
799                            "Change: %z\n";
800           }
801        }
802     }
803     print_it(format, filename, print_stat, &statbuf, sid);
804 }
805
806 void
807 usage (char *progname)
808 {
809   fprintf (stderr, "Usage: %s [-l] [-f] [-s] [-v] [-h] [-t] [-c format] file1 [file2 ...]\n", progname);
810   exit (1);
811 }
812
813 void verbose_usage(char *progname)
814 {
815     fprintf(stderr, "Usage: %s [-l] [-f] [-s] [-v] [-h] [-t] [-c format] file1 [file2 ...]\n", progname);
816     fprintf(stderr, "\tformat interpreted sequences for file stat are:\n");
817     fprintf(stderr, "\t\t%%n - File name\n");
818     fprintf(stderr, "\t\t%%N - Quoted File name with dereference if symbolic link\n");
819     fprintf(stderr, "\t\t%%d - Device number in decimal\n");
820     fprintf(stderr, "\t\t%%D - Device number in hex\n");
821     fprintf(stderr, "\t\t%%i - Inode number\n");
822     fprintf(stderr, "\t\t%%a - Access rights in octal\n");
823     fprintf(stderr, "\t\t%%A - Access rights in human readable form\n");
824     fprintf(stderr, "\t\t%%f - raw mode in hex\n");
825     fprintf(stderr, "\t\t%%F - File type\n");
826     fprintf(stderr, "\t\t%%h - Number of hard links\n");
827     fprintf(stderr, "\t\t%%u - User Id of owner\n");
828     fprintf(stderr, "\t\t%%U - User name of owner\n");
829     fprintf(stderr, "\t\t%%g - Group Id of owner\n");
830     fprintf(stderr, "\t\t%%G - Group name of owner\n");
831     fprintf(stderr, "\t\t%%t - Major device type in hex\n");
832     fprintf(stderr, "\t\t%%T - Minor device type in hex\n");
833     fprintf(stderr, "\t\t%%s - Total size, in bytes\n");
834     fprintf(stderr, "\t\t%%b - Number of blocks allocated\n");
835     fprintf(stderr, "\t\t%%o - IO block size\n");
836     fprintf(stderr, "\t\t%%x - Time of last access\n");
837     fprintf(stderr, "\t\t%%X - Time of last access as seconds since Epoch\n");
838     fprintf(stderr, "\t\t%%y - Time of last modification\n");
839     fprintf(stderr, "\t\t%%Y - Time of last modification as seconds since Epoch\n");
840     fprintf(stderr, "\t\t%%z - Time of last change\n");
841     fprintf(stderr, "\t\t%%Z - Time of last change as seconds since Epoch\n");
842     fprintf(stderr, "\t\t%%S - Security ID in SE-Linux\n");
843     fprintf(stderr, "\t\t%%C - Security context in SE-Linux\n");
844     fprintf(stderr, "\tformat interpreted sequences for filesystem stat are:\n");
845     fprintf(stderr, "\t\t%%n - File name\n");
846     fprintf(stderr, "\t\t%%i - File System id in hex\n");
847     fprintf(stderr, "\t\t%%l - Maximum length of filenames\n");
848     fprintf(stderr, "\t\t%%t - Type in hex\n");
849     fprintf(stderr, "\t\t%%T - Type in human readable form\n");
850     fprintf(stderr, "\t\t%%b - Total data blocks in file system\n");
851     fprintf(stderr, "\t\t%%f - Free blocks in file system\n");
852     fprintf(stderr, "\t\t%%a - Free blocks available to non-superuser\n");
853     fprintf(stderr, "\t\t%%s - Optimal transfer block size\n");
854     fprintf(stderr, "\t\t%%c - Total file nodes in file system\n");
855     fprintf(stderr, "\t\t%%S - Security ID in SE-Linux\n");
856     fprintf(stderr, "\t\t%%C - Security context in SE-Linux\n");
857     fprintf(stderr, "\t\t%%d - Free file nodes in file system\n");
858     exit(1);
859 }
860   
861
862 int
863 main (int argc, char *argv[])
864 {
865   int c, i, link = 0, fs = 0, terse = 0, secure = 0;
866   char *format = NULL;
867   
868   while ((c = getopt (argc, argv, "lsfvthc:")) != EOF)
869     {
870       switch (c)
871         {
872         case 'l':
873           link = 1;
874           break;
875         case 's':
876           secure = 1;
877           break;
878         case 'f':
879           fs = 1;
880           break;
881         case 't':
882           terse = 1;
883           break;
884         case 'c':
885           format = optarg;
886           break;
887         case 'h':
888           printf ("stat version: 3.0\n");
889           verbose_usage(argv[0]);
890           break;
891         case 'v':
892           printf ("stat version: 3.0\n");
893         default:
894           usage (argv[0]);
895         }
896     }
897   if (argc == optind)
898     usage (argv[0]);
899
900   for (i = optind; i < argc; i++)
901     (fs == 0) ? do_stat (argv[i], link, terse, secure, format) :
902                 do_statfs (argv[i], terse, secure, format);
903
904   return (0);
905 }