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