*** empty log message ***
[platform/upstream/coreutils.git] / src / stat.c
1 #include <config.h>
2 #include <stdio.h>
3 #include <sys/stat.h>
4 #ifdef HAVE_SYS_SYSMACROS_H
5 # include <sys/sysmacros.h>
6 #endif
7 #include <pwd.h>
8 #include <grp.h>
9 #include <unistd.h>
10 #include <time.h>
11 #include <sys/vfs.h>
12
13 #include <getopt.h>
14 #include "error.h"
15 #include "filemode.h"
16 #include "gs.h"
17 #include "quotearg.h"
18 #include "system.h"
19 #include "xreadlink.h"
20
21 #define PROGRAM_NAME "stat"
22
23 #define AUTHORS "Michael Meskes"
24
25 static struct option const long_options[] = {
26   {"link", no_argument, 0, 'l'},
27   {"filesystem", no_argument, 0, 'f'},
28   {"terse", no_argument, 0, 't'},
29   {GETOPT_HELP_OPTION_DECL},
30   {GETOPT_VERSION_OPTION_DECL},
31   {NULL, 0, NULL, 0}
32 };
33
34 static char *program_name;
35
36 /* stat the filesystem and print what we find */
37 static void
38 do_statfs (char const *filename, int terse)
39 {
40   struct statfs statfsbuf;
41   char const *name;
42
43   if (statfs (filename, &statfsbuf) == -1)
44     {
45       error (0, errno, "%s", quotearg_colon (filename));
46       return;
47     }
48
49   if (terse != 0)
50     {
51 #ifdef __USE_FILE_OFFSET64
52 # define STATFSFMT "%s %x %x %lu %lx %lld %lld %lld %ld %lld %lld\n"
53 #else
54 # define STATFSFMT "%s %x %x %d %x %ld %ld %ld %d %ld %ld\n"
55 #endif
56       printf (STATFSFMT,
57               filename,
58               statfsbuf.f_fsid.__val[0],
59               statfsbuf.f_fsid.__val[1],
60               statfsbuf.f_namelen,
61               statfsbuf.f_type,
62               statfsbuf.f_blocks,
63               statfsbuf.f_bfree,
64               statfsbuf.f_bavail,
65               statfsbuf.f_bsize, statfsbuf.f_files, statfsbuf.f_ffree);
66
67       return;
68     }
69
70   printf ("  File: \"%s\"\n", filename);
71 #ifdef __USE_FILE_OFFSET64
72   printf ("    ID: %-8x %-8x Namelen: %-7ld Type: ",
73           statfsbuf.f_fsid.__val[0],
74           statfsbuf.f_fsid.__val[1], statfsbuf.f_namelen);
75 #else
76   printf ("    ID: %-8x %-8x Namelen: %-7d Type: ",
77           statfsbuf.f_fsid.__val[0],
78           statfsbuf.f_fsid.__val[1], statfsbuf.f_namelen);
79 #endif
80
81   name = fs_name (statfsbuf.f_type);
82   if (name)
83     printf ("%s\n", name);
84   else
85     printf ("UNKNOWN (0x%lx)\n", (long) statfsbuf.f_type);
86
87 #ifdef __USE_FILE_OFFSET64
88   printf
89     ("Blocks: Total: %-10lld Free: %-10lld Available: %-10lld Size:%ld \n",
90      statfsbuf.f_blocks, statfsbuf.f_bfree, statfsbuf.f_bavail,
91      statfsbuf.f_bsize);
92   printf ("Inodes: Total: %-10lld Free: %-10lld\n", statfsbuf.f_files,
93           statfsbuf.f_ffree);
94 #else
95   printf ("Blocks: Total: %-10ld Free: %-10ld Available: %-10ld  Size:%d\n",
96           statfsbuf.f_blocks,
97           statfsbuf.f_bfree, statfsbuf.f_bavail, statfsbuf.f_bsize);
98   printf ("Inodes: Total: %-10ld Free: %-10ld\n",
99           statfsbuf.f_files, statfsbuf.f_ffree);
100 #endif
101 }
102
103 /* stat the file and print what we find */
104 static void
105 do_stat (char const *filename, int follow_links, int terse)
106 {
107   struct stat statbuf;
108   int err = (follow_links
109              ? stat (filename, &statbuf)
110              : lstat (filename, &statbuf));
111   char modebuf[11];
112   struct passwd *pw_ent;
113   struct group *gw_ent;
114
115   if (err == -1)
116     {
117       error (0, errno, "%s", quotearg_colon (filename));
118       return;
119     }
120
121   if (terse != 0)
122     {
123       printf ("%s %u %u %x %d %d %x %d %d %x %x %d %d %d %d\n",
124               filename,
125               (unsigned int) statbuf.st_size,
126               (unsigned int) statbuf.st_blocks,
127               statbuf.st_mode,
128               statbuf.st_uid,
129               statbuf.st_gid,
130               (int) statbuf.st_dev,
131               (int) statbuf.st_ino,
132               (int) statbuf.st_nlink,
133               major (statbuf.st_rdev),
134               minor (statbuf.st_rdev),
135               (int) statbuf.st_atime,
136               (int) statbuf.st_mtime,
137               (int) statbuf.st_ctime, (int) statbuf.st_blksize);
138       return;
139     }
140
141   if (S_ISLNK (statbuf.st_mode))
142     {
143       char *linkname = xreadlink (filename);
144       if (linkname)
145         printf ("  File: \"%s\" -> \"%s\"\n", filename, linkname);
146
147       free (linkname);
148       if (linkname == NULL)
149         {
150           error (0, errno, _("cannot read symbolic link %s"),
151                  quotearg_colon (filename));
152           return;
153         }
154
155     }
156   else
157     printf ("  File: \"%s\"\n", filename);
158
159   printf ("  Size: %-10u\tBlocks: %-10u IO Block: %-6d ",
160           (unsigned int) statbuf.st_size,
161           (unsigned int) statbuf.st_blocks, (int) statbuf.st_blksize);
162
163   switch (statbuf.st_mode & S_IFMT)
164     {
165     case S_IFDIR:
166       printf ("Directory\n");
167       break;
168     case S_IFCHR:
169       printf ("Character Device\n");
170       break;
171     case S_IFBLK:
172       printf ("Block Device\n");
173       break;
174     case S_IFREG:
175       printf ("Regular File\n");
176       break;
177     case S_IFLNK:
178       printf ("Symbolic Link\n");
179       break;
180     case S_IFSOCK:
181       printf ("Socket\n");
182       break;
183     case S_IFIFO:
184       printf ("Fifo File\n");
185       break;
186     default:
187       printf ("Unknown\n");
188     }
189
190   printf ("Device: %xh/%dd\tInode: %-10d  Links: %-5d",
191           (int) statbuf.st_dev,
192           (int) statbuf.st_dev, (int) statbuf.st_ino, (int) statbuf.st_nlink);
193
194   if (S_ISBLK (statbuf.st_mode) || S_ISCHR (statbuf.st_mode))
195     printf (" Device type: %x,%x\n",
196             major (statbuf.st_rdev), minor (statbuf.st_rdev));
197   else
198     printf ("\n");
199
200   mode_string (statbuf.st_mode, modebuf);
201   modebuf[10] = 0;
202   printf ("Access: (%04o/%10.10s)", statbuf.st_mode & 07777, modebuf);
203
204   setpwent ();
205   setgrent ();
206   pw_ent = getpwuid (statbuf.st_uid);
207   gw_ent = getgrgid (statbuf.st_gid);
208   printf ("  Uid: (%5d/%8s)   Gid: (%5d/%8s)\n",
209           statbuf.st_uid,
210           (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN",
211           statbuf.st_gid, (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
212
213   printf ("Access: %s", ctime (&statbuf.st_atime));
214   printf ("Modify: %s", ctime (&statbuf.st_mtime));
215   printf ("Change: %s\n", ctime (&statbuf.st_ctime));
216 }
217
218 void
219 usage (int status)
220 {
221   if (status != 0)
222     fprintf (stderr, _("Try %s --help' for more information.\n"),
223              program_name);
224   else
225     {
226       printf (_("Usage: %s [OPTION] FILE...\n"), program_name);
227       fputs (_("\
228 Display file or filesystem status.\n\
229 \n\
230   -l, --link            follow links\n\
231   -f, --filesystem      display filesystem status instead of file status\n\
232   -t, --terse           print the information in terse form\n\
233 "), stdout);
234       fputs (HELP_OPTION_DESCRIPTION, stdout);
235       fputs (VERSION_OPTION_DESCRIPTION, stdout);
236       puts (_("\nReport bugs to <bug-fileutils@gnu.org>."));
237     }
238   exit (status);
239 }
240
241 int
242 main (int argc, char **argv)
243 {
244   int c;
245   int i;
246   int follow_links = 0;
247   int fs = 0;
248   int terse = 0;
249
250   program_name = argv[0];
251   setlocale (LC_ALL, "");
252   bindtextdomain (PACKAGE, LOCALEDIR);
253   textdomain (PACKAGE);
254
255   atexit (close_stdout);
256   while ((c = getopt_long (argc, argv, "lft", long_options, NULL)) != -1)
257     {
258       switch (c)
259         {
260         case 'l':
261           follow_links = 1;
262           break;
263         case 'f':
264           fs = 1;
265           break;
266         case 't':
267           terse = 1;
268           break;
269           case_GETOPT_HELP_CHAR;
270
271           case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
272
273         default:
274           usage (EXIT_FAILURE);
275         }
276     }
277
278   if (argc == optind)
279     {
280       error (0, 0, _("too few arguments"));
281       usage (EXIT_FAILURE);
282     }
283
284   for (i = optind; i < argc; i++)
285     {
286       if (fs == 0)
287         do_stat (argv[i], follow_links, terse);
288       else
289         do_statfs (argv[i], terse);
290     }
291
292   exit (EXIT_SUCCESS);
293 }