/[coreutils]/coreutils/src/stat.c
ViewVC logotype

Contents of /coreutils/src/stat.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.87 - (show annotations) (download)
Sat May 14 07:58:37 2005 UTC (18 years, 11 months ago) by meyering
Branch: MAIN
Changes since 1.86: +1 -1 lines
File MIME type: text/plain
Update FSF postal mail address.

1 /* stat.c -- display file or file system status
2 Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 Written by Michael Meskes. */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include <pwd.h>
25 #include <grp.h>
26 #if HAVE_SYS_STATVFS_H && HAVE_STRUCT_STATVFS_F_BASETYPE
27 # include <sys/statvfs.h>
28 #elif HAVE_SYS_VFS_H
29 # include <sys/vfs.h>
30 #elif HAVE_SYS_MOUNT_H && HAVE_SYS_PARAM_H
31 /* NOTE: freebsd5.0 needs sys/param.h and sys/mount.h for statfs.
32 It does have statvfs.h, but shouldn't use it, since it doesn't
33 HAVE_STRUCT_STATVFS_F_BASETYPE. So find a clean way to fix it. */
34 /* NetBSD 1.5.2 needs these, for the declaration of struct statfs. */
35 # include <sys/param.h>
36 # include <sys/mount.h>
37 # if HAVE_NETINET_IN_H && HAVE_NFS_NFS_CLNT_H && HAVE_NFS_VFS_H
38 /* Ultrix 4.4 needs these for the declaration of struct statfs. */
39 # include <netinet/in.h>
40 # include <nfs/nfs_clnt.h>
41 # include <nfs/vfs.h>
42 # endif
43 #endif
44
45 #include "system.h"
46
47 #include "error.h"
48 #include "filemode.h"
49 #include "file-type.h"
50 #include "fs.h"
51 #include "getopt.h"
52 #include "inttostr.h"
53 #include "quote.h"
54 #include "quotearg.h"
55 #include "strftime.h"
56 #include "xreadlink.h"
57
58 #define NAMEMAX_FORMAT PRIuMAX
59
60 #if HAVE_STRUCT_STATVFS_F_BASETYPE
61 # define STRUCT_STATVFS struct statvfs
62 # define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATVFS_F_TYPE
63 # if HAVE_STRUCT_STATVFS_F_NAMEMAX
64 # define SB_F_NAMEMAX(S) ((uintmax_t) ((S)->f_namemax))
65 # endif
66 # if STAT_STATVFS
67 # define STATFS statvfs
68 # define STATFS_FRSIZE(S) ((S)->f_frsize)
69 # endif
70 #else
71 # define STRUCT_STATVFS struct statfs
72 # define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATFS_F_TYPE
73 # if HAVE_STRUCT_STATFS_F_NAMELEN
74 # define SB_F_NAMEMAX(S) ((uintmax_t) ((S)->f_namelen))
75 # endif
76 #endif
77
78 #ifndef STATFS
79 # define STATFS statfs
80 # define STATFS_FRSIZE(S) 0
81 #endif
82
83 #ifndef SB_F_NAMEMAX
84 /* NetBSD 1.5.2 has neither f_namemax nor f_namelen. */
85 # define SB_F_NAMEMAX(S) "*"
86 # undef NAMEMAX_FORMAT
87 # define NAMEMAX_FORMAT "s"
88 #endif
89
90 #if HAVE_STRUCT_STATVFS_F_BASETYPE
91 # define STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME f_basetype
92 #else
93 # if HAVE_STRUCT_STATFS_F_FSTYPENAME
94 # define STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME f_fstypename
95 # endif
96 #endif
97
98 #define PROGRAM_NAME "stat"
99
100 #define AUTHORS "Michael Meskes"
101
102 static struct option const long_options[] = {
103 {"link", no_argument, NULL, 'l'}, /* deprecated. FIXME: remove in 2003 */
104 {"dereference", no_argument, NULL, 'L'},
105 {"file-system", no_argument, NULL, 'f'},
106 {"filesystem", no_argument, NULL, 'f'}, /* obsolete and undocumented alias */
107 {"format", required_argument, NULL, 'c'},
108 {"terse", no_argument, NULL, 't'},
109 {GETOPT_HELP_OPTION_DECL},
110 {GETOPT_VERSION_OPTION_DECL},
111 {NULL, 0, NULL, 0}
112 };
113
114 char *program_name;
115
116 /* Return the type of the specified file system.
117 Some systems have statfvs.f_basetype[FSTYPSZ]. (AIX, HP-UX, and Solaris)
118 Others have statfs.f_fstypename[MFSNAMELEN]. (NetBSD 1.5.2)
119 Still others have neither and have to get by with f_type (Linux). */
120 static char const *
121 human_fstype (STRUCT_STATVFS const *statfsbuf)
122 {
123 #ifdef STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME
124 return statfsbuf->STATXFS_FILE_SYSTEM_TYPE_MEMBER_NAME;
125 #else
126 switch (statfsbuf->f_type)
127 {
128 # if defined __linux__
129
130 /* IMPORTANT NOTE: Each of the following `case S_MAGIC_...:'
131 statements must be followed by a hexadecimal constant in
132 a comment. The S_MAGIC_... name and constant are automatically
133 combined to produce the #define directives in fs.h. */
134
135 case S_MAGIC_AFFS: /* 0xADFF */
136 return "affs";
137 case S_MAGIC_DEVPTS: /* 0x1CD1 */
138 return "devpts";
139 case S_MAGIC_EXT: /* 0x137D */
140 return "ext";
141 case S_MAGIC_EXT2_OLD: /* 0xEF51 */
142 return "ext2";
143 case S_MAGIC_EXT2: /* 0xEF53 */
144 return "ext2/ext3";
145 case S_MAGIC_JFS: /* 0x3153464a */
146 return "jfs";
147 case S_MAGIC_XFS: /* 0x58465342 */
148 return "xfs";
149 case S_MAGIC_HPFS: /* 0xF995E849 */
150 return "hpfs";
151 case S_MAGIC_ISOFS: /* 0x9660 */
152 return "isofs";
153 case S_MAGIC_ISOFS_WIN: /* 0x4000 */
154 return "isofs";
155 case S_MAGIC_ISOFS_R_WIN: /* 0x4004 */
156 return "isofs";
157 case S_MAGIC_MINIX: /* 0x137F */
158 return "minix";
159 case S_MAGIC_MINIX_30: /* 0x138F */
160 return "minix (30 char.)";
161 case S_MAGIC_MINIX_V2: /* 0x2468 */
162 return "minix v2";
163 case S_MAGIC_MINIX_V2_30: /* 0x2478 */
164 return "minix v2 (30 char.)";
165 case S_MAGIC_MSDOS: /* 0x4d44 */
166 return "msdos";
167 case S_MAGIC_FAT: /* 0x4006 */
168 return "fat";
169 case S_MAGIC_NCP: /* 0x564c */
170 return "novell";
171 case S_MAGIC_NFS: /* 0x6969 */
172 return "nfs";
173 case S_MAGIC_PROC: /* 0x9fa0 */
174 return "proc";
175 case S_MAGIC_SMB: /* 0x517B */
176 return "smb";
177 case S_MAGIC_XENIX: /* 0x012FF7B4 */
178 return "xenix";
179 case S_MAGIC_SYSV4: /* 0x012FF7B5 */
180 return "sysv4";
181 case S_MAGIC_SYSV2: /* 0x012FF7B6 */
182 return "sysv2";
183 case S_MAGIC_COH: /* 0x012FF7B7 */
184 return "coh";
185 case S_MAGIC_UFS: /* 0x00011954 */
186 return "ufs";
187 case S_MAGIC_XIAFS: /* 0x012FD16D */
188 return "xia";
189 case S_MAGIC_NTFS: /* 0x5346544e */
190 return "ntfs";
191 case S_MAGIC_TMPFS: /* 0x1021994 */
192 return "tmpfs";
193 case S_MAGIC_REISERFS: /* 0x52654973 */
194 return "reiserfs";
195 case S_MAGIC_CRAMFS: /* 0x28cd3d45 */
196 return "cramfs";
197 case S_MAGIC_ROMFS: /* 0x7275 */
198 return "romfs";
199 case S_MAGIC_RAMFS: /* 0x858458f6 */
200 return "ramfs";
201 case S_MAGIC_SQUASHFS: /* 0x73717368 */
202 return "squashfs";
203 case S_MAGIC_SYSFS: /* 0x62656572 */
204 return "sysfs";
205 # elif __GNU__
206 case FSTYPE_UFS:
207 return "ufs";
208 case FSTYPE_NFS:
209 return "nfs";
210 case FSTYPE_GFS:
211 return "gfs";
212 case FSTYPE_LFS:
213 return "lfs";
214 case FSTYPE_SYSV:
215 return "sysv";
216 case FSTYPE_FTP:
217 return "ftp";
218 case FSTYPE_TAR:
219 return "tar";
220 case FSTYPE_AR:
221 return "ar";
222 case FSTYPE_CPIO:
223 return "cpio";
224 case FSTYPE_MSLOSS:
225 return "msloss";
226 case FSTYPE_CPM:
227 return "cpm";
228 case FSTYPE_HFS:
229 return "hfs";
230 case FSTYPE_DTFS:
231 return "dtfs";
232 case FSTYPE_GRFS:
233 return "grfs";
234 case FSTYPE_TERM:
235 return "term";
236 case FSTYPE_DEV:
237 return "dev";
238 case FSTYPE_PROC:
239 return "proc";
240 case FSTYPE_IFSOCK:
241 return "ifsock";
242 case FSTYPE_AFS:
243 return "afs";
244 case FSTYPE_DFS:
245 return "dfs";
246 case FSTYPE_PROC9:
247 return "proc9";
248 case FSTYPE_SOCKET:
249 return "socket";
250 case FSTYPE_MISC:
251 return "misc";
252 case FSTYPE_EXT2FS:
253 return "ext2/ext3";
254 case FSTYPE_HTTP:
255 return "http";
256 case FSTYPE_MEMFS:
257 return "memfs";
258 case FSTYPE_ISO9660:
259 return "iso9660";
260 # endif
261 default:
262 {
263 unsigned long int type = statfsbuf->f_type;
264 static char buf[sizeof "UNKNOWN (0x%lx)" - 3
265 + (sizeof type * CHAR_BIT + 3) / 4];
266 sprintf (buf, "UNKNOWN (0x%lx)", type);
267 return buf;
268 }
269 }
270 #endif
271 }
272
273 static char *
274 human_access (struct stat const *statbuf)
275 {
276 static char modebuf[11];
277 mode_string (statbuf->st_mode, modebuf);
278 modebuf[10] = 0;
279 return modebuf;
280 }
281
282 static char *
283 human_time (time_t t, int t_ns)
284 {
285 static char str[MAX (INT_BUFSIZE_BOUND (intmax_t),
286 (INT_STRLEN_BOUND (int) /* YYYY */
287 + 1 /* because YYYY might equal INT_MAX + 1900 */
288 + sizeof "-MM-DD HH:MM:SS.NNNNNNNNN +ZZZZ"))];
289 struct tm const *tm = localtime (&t);
290 if (tm == NULL)
291 return (TYPE_SIGNED (time_t)
292 ? imaxtostr (t, str)
293 : umaxtostr (t, str));
294 nstrftime (str, sizeof str, "%Y-%m-%d %H:%M:%S.%N %z", tm, 0, t_ns);
295 return str;
296 }
297
298 /* Like strcat, but don't return anything and do check that
299 DEST_BUFSIZE is at least a long as strlen (DEST) + strlen (SRC) + 1.
300 The signature is deliberately different from that of strncat. */
301 static void
302 xstrcat (char *dest, size_t dest_bufsize, char const *src)
303 {
304 size_t dest_len = strlen (dest);
305 size_t src_len = strlen (src);
306 if (dest_bufsize < dest_len + src_len + 1)
307 abort ();
308 memcpy (dest + dest_len, src, src_len + 1);
309 }
310
311 /* print statfs info */
312 static void
313 print_statfs (char *pformat, size_t buf_len, char m, char const *filename,
314 void const *data)
315 {
316 STRUCT_STATVFS const *statfsbuf = data;
317
318 switch (m)
319 {
320 case 'n':
321 xstrcat (pformat, buf_len, "s");
322 printf (pformat, filename);
323 break;
324
325 case 'i':
326 #if HAVE_STRUCT_STATXFS_F_FSID___VAL
327 xstrcat (pformat, buf_len, "x %-8x");
328 printf (pformat, statfsbuf->f_fsid.__val[0], /* u_long */
329 statfsbuf->f_fsid.__val[1]);
330 #else
331 xstrcat (pformat, buf_len, "Lx");
332 printf (pformat, statfsbuf->f_fsid);
333 #endif
334 break;
335
336 case 'l':
337 xstrcat (pformat, buf_len, NAMEMAX_FORMAT);
338 printf (pformat, SB_F_NAMEMAX (statfsbuf));
339 break;
340 case 't':
341 #if HAVE_STRUCT_STATXFS_F_TYPE
342 xstrcat (pformat, buf_len, "lx");
343 printf (pformat,
344 (unsigned long int) (statfsbuf->f_type)); /* no equiv. */
345 #else
346 fputc ('*', stdout);
347 #endif
348 break;
349 case 'T':
350 xstrcat (pformat, buf_len, "s");
351 printf (pformat, human_fstype (statfsbuf));
352 break;
353 case 'b':
354 xstrcat (pformat, buf_len, PRIdMAX);
355 printf (pformat, (intmax_t) (statfsbuf->f_blocks));
356 break;
357 case 'f':
358 xstrcat (pformat, buf_len, PRIdMAX);
359 printf (pformat, (intmax_t) (statfsbuf->f_bfree));
360 break;
361 case 'a':
362 xstrcat (pformat, buf_len, PRIdMAX);
363 printf (pformat, (intmax_t) (statfsbuf->f_bavail));
364 break;
365 case 's':
366 xstrcat (pformat, buf_len, "lu");
367 printf (pformat, (unsigned long int) (statfsbuf->f_bsize));
368 break;
369 case 'S':
370 {
371 unsigned long int frsize = STATFS_FRSIZE (statfsbuf);
372 if (! frsize)
373 frsize = statfsbuf->f_bsize;
374 xstrcat (pformat, buf_len, "lu");
375 printf (pformat, frsize);
376 }
377 break;
378 case 'c':
379 xstrcat (pformat, buf_len, PRIdMAX);
380 printf (pformat, (intmax_t) (statfsbuf->f_files));
381 break;
382 case 'd':
383 xstrcat (pformat, buf_len, PRIdMAX);
384 printf (pformat, (intmax_t) (statfsbuf->f_ffree));
385 break;
386
387 default:
388 xstrcat (pformat, buf_len, "c");
389 printf (pformat, m);
390 break;
391 }
392 }
393
394 /* print stat info */
395 static void
396 print_stat (char *pformat, size_t buf_len, char m,
397 char const *filename, void const *data)
398 {
399 struct stat *statbuf = (struct stat *) data;
400 struct passwd *pw_ent;
401 struct group *gw_ent;
402
403 switch (m)
404 {
405 case 'n':
406 xstrcat (pformat, buf_len, "s");
407 printf (pformat, filename);
408 break;
409 case 'N':
410 xstrcat (pformat, buf_len, "s");
411 if (S_ISLNK (statbuf->st_mode))
412 {
413 char *linkname = xreadlink (filename, statbuf->st_size);
414 if (linkname == NULL)
415 {
416 error (0, errno, _("cannot read symbolic link %s"),
417 quote (filename));
418 return;
419 }
420 /*printf("\"%s\" -> \"%s\"", filename, linkname); */
421 printf (pformat, quote (filename));
422 printf (" -> ");
423 printf (pformat, quote (linkname));
424 }
425 else
426 {
427 printf (pformat, quote (filename));
428 }
429 break;
430 case 'd':
431 xstrcat (pformat, buf_len, PRIuMAX);
432 printf (pformat, (uintmax_t) statbuf->st_dev);
433 break;
434 case 'D':
435 xstrcat (pformat, buf_len, PRIxMAX);
436 printf (pformat, (uintmax_t) statbuf->st_dev);
437 break;
438 case 'i':
439 xstrcat (pformat, buf_len, PRIuMAX);
440 printf (pformat, (uintmax_t) statbuf->st_ino);
441 break;
442 case 'a':
443 xstrcat (pformat, buf_len, "lo");
444 printf (pformat,
445 (unsigned long int) (statbuf->st_mode & CHMOD_MODE_BITS));
446 break;
447 case 'A':
448 xstrcat (pformat, buf_len, "s");
449 printf (pformat, human_access (statbuf));
450 break;
451 case 'f':
452 xstrcat (pformat, buf_len, "lx");
453 printf (pformat, (unsigned long int) statbuf->st_mode);
454 break;
455 case 'F':
456 xstrcat (pformat, buf_len, "s");
457 printf (pformat, file_type (statbuf));
458 break;
459 case 'h':
460 xstrcat (pformat, buf_len, "lu");
461 printf (pformat, (unsigned long int) statbuf->st_nlink);
462 break;
463 case 'u':
464 xstrcat (pformat, buf_len, "lu");
465 printf (pformat, (unsigned long int) statbuf->st_uid);
466 break;
467 case 'U':
468 xstrcat (pformat, buf_len, "s");
469 setpwent ();
470 pw_ent = getpwuid (statbuf->st_uid);
471 printf (pformat, (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN");
472 break;
473 case 'g':
474 xstrcat (pformat, buf_len, "lu");
475 printf (pformat, (unsigned long int) statbuf->st_gid);
476 break;
477 case 'G':
478 xstrcat (pformat, buf_len, "s");
479 setgrent ();
480 gw_ent = getgrgid (statbuf->st_gid);
481 printf (pformat, (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
482 break;
483 case 't':
484 xstrcat (pformat, buf_len, "lx");
485 printf (pformat, (unsigned long int) major (statbuf->st_rdev));
486 break;
487 case 'T':
488 xstrcat (pformat, buf_len, "lx");
489 printf (pformat, (unsigned long int) minor (statbuf->st_rdev));
490 break;
491 case 's':
492 xstrcat (pformat, buf_len, PRIuMAX);
493 printf (pformat, (uintmax_t) (statbuf->st_size));
494 break;
495 case 'B':
496 xstrcat (pformat, buf_len, "lu");
497 printf (pformat, (unsigned long int) ST_NBLOCKSIZE);
498 break;
499 case 'b':
500 xstrcat (pformat, buf_len, PRIuMAX);
501 printf (pformat, (uintmax_t) ST_NBLOCKS (*statbuf));
502 break;
503 case 'o':
504 xstrcat (pformat, buf_len, "lu");
505 printf (pformat, (unsigned long int) statbuf->st_blksize);
506 break;
507 case 'x':
508 xstrcat (pformat, buf_len, "s");
509 printf (pformat, human_time (statbuf->st_atime,
510 TIMESPEC_NS (statbuf->st_atim)));
511 break;
512 case 'X':
513 xstrcat (pformat, buf_len, TYPE_SIGNED (time_t) ? "ld" : "lu");
514 printf (pformat, (unsigned long int) statbuf->st_atime);
515 break;
516 case 'y':
517 xstrcat (pformat, buf_len, "s");
518 printf (pformat, human_time (statbuf->st_mtime,
519 TIMESPEC_NS (statbuf->st_mtim)));
520 break;
521 case 'Y':
522 xstrcat (pformat, buf_len, TYPE_SIGNED (time_t) ? "ld" : "lu");
523 printf (pformat, (unsigned long int) statbuf->st_mtime);
524 break;
525 case 'z':
526 xstrcat (pformat, buf_len, "s");
527 printf (pformat, human_time (statbuf->st_ctime,
528 TIMESPEC_NS (statbuf->st_ctim)));
529 break;
530 case 'Z':
531 xstrcat (pformat, buf_len, TYPE_SIGNED (time_t) ? "ld" : "lu");
532 printf (pformat, (unsigned long int) statbuf->st_ctime);
533 break;
534 default:
535 xstrcat (pformat, buf_len, "c");
536 printf (pformat, m);
537 break;
538 }
539 }
540
541 static void
542 print_it (char const *masterformat, char const *filename,
543 void (*print_func) (char *, size_t, char, char const *, void const *),
544 void const *data)
545 {
546 char *b;
547
548 /* create a working copy of the format string */
549 char *format = xstrdup (masterformat);
550
551 /* Add 2 to accommodate our conversion of the stat `%s' format string
552 to the printf `%llu' one. */
553 size_t n_alloc = strlen (format) + 2 + 1;
554 char *dest = xmalloc (n_alloc);
555
556 b = format;
557 while (b)
558 {
559 char *p = strchr (b, '%');
560 if (p != NULL)
561 {
562 size_t len;
563 *p++ = '\0';
564 fputs (b, stdout);
565
566 len = strspn (p, "#-+.I 0123456789");
567 dest[0] = '%';
568 memcpy (dest + 1, p, len);
569 dest[1 + len] = 0;
570 p += len;
571
572 b = p + 1;
573 switch (*p)
574 {
575 case '\0':
576 b = NULL;
577 /* fall through */
578 case '%':
579 putchar ('%');
580 break;
581 default:
582 print_func (dest, n_alloc, *p, filename, data);
583 break;
584 }
585 }
586 else
587 {
588 fputs (b, stdout);
589 b = NULL;
590 }
591 }
592 free (format);
593 free (dest);
594 }
595
596 /* Stat the file system and print what we find. */
597 static bool
598 do_statfs (char const *filename, bool terse, char const *format)
599 {
600 STRUCT_STATVFS statfsbuf;
601
602 if (STATFS (filename, &statfsbuf) != 0)
603 {
604 error (0, errno, _("cannot read file system information for %s"),
605 quote (filename));
606 return false;
607 }
608
609 if (format == NULL)
610 {
611 format = (terse
612 ? "%n %i %l %t %s %S %b %f %a %c %d\n"
613 : " File: \"%n\"\n"
614 " ID: %-8i Namelen: %-7l Type: %T\n"
615 "Block size: %-10s Fundamental block size: %S\n"
616 "Blocks: Total: %-10b Free: %-10f Available: %a\n"
617 "Inodes: Total: %-10c Free: %d\n");
618 }
619
620 print_it (format, filename, print_statfs, &statfsbuf);
621 return true;
622 }
623
624 /* stat the file and print what we find */
625 static bool
626 do_stat (char const *filename, bool follow_links, bool terse,
627 char const *format)
628 {
629 struct stat statbuf;
630
631 if ((follow_links ? stat : lstat) (filename, &statbuf) != 0)
632 {
633 error (0, errno, _("cannot stat %s"), quote (filename));
634 return false;
635 }
636
637 if (format == NULL)
638 {
639 if (terse)
640 {
641 format = "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\n";
642 }
643 else
644 {
645 /* Temporary hack to match original output until conditional
646 implemented. */
647 if (S_ISBLK (statbuf.st_mode) || S_ISCHR (statbuf.st_mode))
648 {
649 format =
650 " File: %N\n"
651 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
652 "Device: %Dh/%dd\tInode: %-10i Links: %-5h"
653 " Device type: %t,%T\n"
654 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
655 "Access: %x\n" "Modify: %y\n" "Change: %z\n";
656 }
657 else
658 {
659 format =
660 " File: %N\n"
661 " Size: %-10s\tBlocks: %-10b IO Block: %-6o %F\n"
662 "Device: %Dh/%dd\tInode: %-10i Links: %h\n"
663 "Access: (%04a/%10.10A) Uid: (%5u/%8U) Gid: (%5g/%8G)\n"
664 "Access: %x\n" "Modify: %y\n" "Change: %z\n";
665 }
666 }
667 }
668 print_it (format, filename, print_stat, &statbuf);
669 return true;
670 }
671
672 void
673 usage (int status)
674 {
675 if (status != EXIT_SUCCESS)
676 fprintf (stderr, _("Try `%s --help' for more information.\n"),
677 program_name);
678 else
679 {
680 printf (_("Usage: %s [OPTION] FILE...\n"), program_name);
681 fputs (_("\
682 Display file or file system status.\n\
683 \n\
684 -f, --file-system display file system status instead of file status\n\
685 -c --format=FORMAT use the specified FORMAT instead of the default\n\
686 -L, --dereference follow links\n\
687 -t, --terse print the information in terse form\n\
688 "), stdout);
689 fputs (HELP_OPTION_DESCRIPTION, stdout);
690 fputs (VERSION_OPTION_DESCRIPTION, stdout);
691
692 fputs (_("\n\
693 The valid format sequences for files (without --file-system):\n\
694 \n\
695 %a Access rights in octal\n\
696 %A Access rights in human readable form\n\
697 %b Number of blocks allocated (see %B)\n\
698 %B The size in bytes of each block reported by %b\n\
699 "), stdout);
700 fputs (_("\
701 %d Device number in decimal\n\
702 %D Device number in hex\n\
703 %f Raw mode in hex\n\
704 %F File type\n\
705 %g Group ID of owner\n\
706 %G Group name of owner\n\
707 "), stdout);
708 fputs (_("\
709 %h Number of hard links\n\
710 %i Inode number\n\
711 %n File name\n\
712 %N Quoted file name with dereference if symbolic link\n\
713 %o I/O block size\n\
714 %s Total size, in bytes\n\
715 %t Major device type in hex\n\
716 %T Minor device type in hex\n\
717 "), stdout);
718 fputs (_("\
719 %u User ID of owner\n\
720 %U User name of owner\n\
721 %x Time of last access\n\
722 %X Time of last access as seconds since Epoch\n\
723 %y Time of last modification\n\
724 %Y Time of last modification as seconds since Epoch\n\
725 %z Time of last change\n\
726 %Z Time of last change as seconds since Epoch\n\
727 \n\
728 "), stdout);
729
730 fputs (_("\
731 Valid format sequences for file systems:\n\
732 \n\
733 %a Free blocks available to non-superuser\n\
734 %b Total data blocks in file system\n\
735 %c Total file nodes in file system\n\
736 %d Free file nodes in file system\n\
737 %f Free blocks in file system\n\
738 "), stdout);
739 fputs (_("\
740 %i File System ID in hex\n\
741 %l Maximum length of filenames\n\
742 %n File name\n\
743 %s Block size (for faster transfers)\n\
744 %S Fundamental block size (for block counts)\n\
745 %t Type in hex\n\
746 %T Type in human readable form\n\
747 "), stdout);
748 printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
749 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
750 }
751 exit (status);
752 }
753
754 int
755 main (int argc, char *argv[])
756 {
757 int c;
758 int i;
759 bool follow_links = false;
760 bool fs = false;
761 bool terse = false;
762 char *format = NULL;
763 bool ok = true;
764
765 initialize_main (&argc, &argv);
766 program_name = argv[0];
767 setlocale (LC_ALL, "");
768 bindtextdomain (PACKAGE, LOCALEDIR);
769 textdomain (PACKAGE);
770
771 atexit (close_stdout);
772
773 while ((c = getopt_long (argc, argv, "c:fLlt", long_options, NULL)) != -1)
774 {
775 switch (c)
776 {
777 case 'c':
778 format = optarg;
779 break;
780
781 case 'l': /* deprecated */
782 error (0, 0, _("Warning: `-l' is deprecated; use `-L' instead"));
783 /* fall through */
784 case 'L':
785 follow_links = true;
786 break;
787
788 case 'f':
789 fs = true;
790 break;
791
792 case 't':
793 terse = true;
794 break;
795
796 case_GETOPT_HELP_CHAR;
797
798 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
799
800 default:
801 usage (EXIT_FAILURE);
802 }
803 }
804
805 if (argc == optind)
806 {
807 error (0, 0, _("missing operand"));
808 usage (EXIT_FAILURE);
809 }
810
811 for (i = optind; i < argc; i++)
812 ok &= (fs
813 ? do_statfs (argv[i], terse, format)
814 : do_stat (argv[i], follow_links, terse, format));
815
816 exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
817 }

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26