Bash  5.0-beta2
Bash - Bourne Again shell
finfo.c
Go to the documentation of this file.
1 /*
2  * finfo - print file info
3  *
4  * Chet Ramey
5  * chet@po.cwru.edu
6  */
7 
8 /*
9  Copyright (C) 1999-2009 Free Software Foundation, Inc.
10 
11  This file is part of GNU Bash.
12  Bash is free software: you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation, either version 3 of the License, or
15  (at your option) any later version.
16 
17  Bash is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with Bash. If not, see <http://www.gnu.org/licenses/>.
24 */
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #include <sys/types.h>
31 #include "posixstat.h"
32 #include <stdio.h>
33 #include <pwd.h>
34 #include <grp.h>
35 #include <errno.h>
36 #include "posixtime.h"
37 
38 #include "bashansi.h"
39 #include "shell.h"
40 #include "builtins.h"
41 #include "common.h"
42 #include "getopt.h"
43 
44 #ifndef errno
45 extern int errno;
46 #endif
47 
48 extern char **make_builtin_argv ();
49 
50 static void perms();
51 static int printst();
52 static int printsome();
53 static void printmode();
54 static int printfinfo();
55 static int finfo_main();
56 
57 extern int sh_optind;
58 extern char *sh_optarg;
59 extern char *this_command_name;
60 
61 static char *prog;
62 static int pmask;
63 
64 #define OPT_UID 0x00001
65 #define OPT_GID 0x00002
66 #define OPT_DEV 0x00004
67 #define OPT_INO 0x00008
68 #define OPT_PERM 0x00010
69 #define OPT_LNKNAM 0x00020
70 #define OPT_FID 0x00040
71 #define OPT_NLINK 0x00080
72 #define OPT_RDEV 0x00100
73 #define OPT_SIZE 0x00200
74 #define OPT_ATIME 0x00400
75 #define OPT_MTIME 0x00800
76 #define OPT_CTIME 0x01000
77 #define OPT_BLKSIZE 0x02000
78 #define OPT_BLKS 0x04000
79 #define OPT_FTYPE 0x08000
80 #define OPT_PMASK 0x10000
81 #define OPT_OPERM 0x20000
82 
83 #define OPT_ASCII 0x1000000
84 
85 #define OPTIONS "acdgiflmnopsuACGMP:U"
86 
87 static int
89 char *s;
90 {
91  int r;
92 
93  r = *s - '0';
94  while (*++s >= '0' && *s <= '7')
95  r = (r * 8) + (*s - '0');
96  return r;
97 }
98 
99 static int
101 int argc;
102 char **argv;
103 {
104  register int i;
105  int mode, flags, opt;
106 
107  sh_optind = 0; /* XXX */
108  prog = base_pathname(argv[0]);
109  if (argc == 1) {
110  builtin_usage();
111  return(1);
112  }
113  flags = 0;
114  while ((opt = sh_getopt(argc, argv, OPTIONS)) != EOF) {
115  switch(opt) {
116  case 'a': flags |= OPT_ATIME; break;
117  case 'A': flags |= OPT_ATIME|OPT_ASCII; break;
118  case 'c': flags |= OPT_CTIME; break;
119  case 'C': flags |= OPT_CTIME|OPT_ASCII; break;
120  case 'd': flags |= OPT_DEV; break;
121  case 'i': flags |= OPT_INO; break;
122  case 'f': flags |= OPT_FID; break;
123  case 'g': flags |= OPT_GID; break;
124  case 'G': flags |= OPT_GID|OPT_ASCII; break;
125  case 'l': flags |= OPT_LNKNAM; break;
126  case 'm': flags |= OPT_MTIME; break;
127  case 'M': flags |= OPT_MTIME|OPT_ASCII; break;
128  case 'n': flags |= OPT_NLINK; break;
129  case 'o': flags |= OPT_OPERM; break;
130  case 'p': flags |= OPT_PERM; break;
131  case 'P': flags |= OPT_PMASK; pmask = octal(sh_optarg); break;
132  case 's': flags |= OPT_SIZE; break;
133  case 'u': flags |= OPT_UID; break;
134  case 'U': flags |= OPT_UID|OPT_ASCII; break;
135  default: builtin_usage (); return(1);
136  }
137  }
138 
139  argc -= sh_optind;
140  argv += sh_optind;
141 
142  if (argc == 0) {
143  builtin_usage();
144  return(1);
145  }
146 
147  for (i = 0; i < argc; i++)
148  opt = flags ? printsome (argv[i], flags) : printfinfo(argv[i]);
149 
150  return(opt);
151 }
152 
153 static struct stat *
155 char *f;
156 {
157  static struct stat st;
158  int fd, r;
159  intmax_t lfd;
160 
161  if (strncmp(f, "/dev/fd/", 8) == 0) {
162  if ((legal_number(f + 8, &lfd) == 0) || (int)lfd != lfd) {
163  builtin_error("%s: invalid fd", f + 8);
164  return ((struct stat *)0);
165  }
166  fd = lfd;
167  r = fstat(fd, &st);
168  } else
169 #ifdef HAVE_LSTAT
170  r = lstat(f, &st);
171 #else
172  r = stat(f, &st);
173 #endif
174  if (r < 0) {
175  builtin_error("%s: cannot stat: %s", f, strerror(errno));
176  return ((struct stat *)0);
177  }
178  return (&st);
179 }
180 
181 static int
183 char *f;
184 {
185  struct stat *st;
186 
187  st = getstat(f);
188  return (st ? printst(st) : 1);
189 }
190 
191 static int
193 int m;
194 {
195  return (m & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID));
196 }
197 
198 static void
200 int m;
201 {
202  char ubits[4], gbits[4], obits[4]; /* u=rwx,g=rwx,o=rwx */
203  int i;
204 
205  i = 0;
206  if (m & S_IRUSR)
207  ubits[i++] = 'r';
208  if (m & S_IWUSR)
209  ubits[i++] = 'w';
210  if (m & S_IXUSR)
211  ubits[i++] = 'x';
212  ubits[i] = '\0';
213 
214  i = 0;
215  if (m & S_IRGRP)
216  gbits[i++] = 'r';
217  if (m & S_IWGRP)
218  gbits[i++] = 'w';
219  if (m & S_IXGRP)
220  gbits[i++] = 'x';
221  gbits[i] = '\0';
222 
223  i = 0;
224  if (m & S_IROTH)
225  obits[i++] = 'r';
226  if (m & S_IWOTH)
227  obits[i++] = 'w';
228  if (m & S_IXOTH)
229  obits[i++] = 'x';
230  obits[i] = '\0';
231 
232  if (m & S_ISUID)
233  ubits[2] = (m & S_IXUSR) ? 's' : 'S';
234  if (m & S_ISGID)
235  gbits[2] = (m & S_IXGRP) ? 's' : 'S';
236  if (m & S_ISVTX)
237  obits[2] = (m & S_IXOTH) ? 't' : 'T';
238 
239  printf ("u=%s,g=%s,o=%s", ubits, gbits, obits);
240 }
241 
242 static void
244 int mode;
245 {
246  if (S_ISBLK(mode))
247  printf("S_IFBLK ");
248  if (S_ISCHR(mode))
249  printf("S_IFCHR ");
250  if (S_ISDIR(mode))
251  printf("S_IFDIR ");
252  if (S_ISREG(mode))
253  printf("S_IFREG ");
254  if (S_ISFIFO(mode))
255  printf("S_IFIFO ");
256  if (S_ISLNK(mode))
257  printf("S_IFLNK ");
258  if (S_ISSOCK(mode))
259  printf("S_IFSOCK ");
260 #ifdef S_ISWHT
261  if (S_ISWHT(mode))
262  printf("S_ISWHT ");
263 #endif
264  perms(getperm(mode));
265  printf("\n");
266 }
267 
268 static int
270 struct stat *st;
271 {
272  struct passwd *pw;
273  struct group *gr;
274  char *owner;
275  int ma, mi, d;
276 
277  ma = major (st->st_rdev);
278  mi = minor (st->st_rdev);
279 #if defined (makedev)
280  d = makedev (ma, mi);
281 #else
282  d = st->st_rdev & 0xFF;
283 #endif
284  printf("Device (major/minor): %d (%d/%d)\n", d, ma, mi);
285 
286  printf("Inode: %d\n", (int) st->st_ino);
287  printf("Mode: (%o) ", (int) st->st_mode);
288  printmode((int) st->st_mode);
289  printf("Link count: %d\n", (int) st->st_nlink);
290  pw = getpwuid(st->st_uid);
291  owner = pw ? pw->pw_name : "unknown";
292  printf("Uid of owner: %d (%s)\n", (int) st->st_uid, owner);
293  gr = getgrgid(st->st_gid);
294  owner = gr ? gr->gr_name : "unknown";
295  printf("Gid of owner: %d (%s)\n", (int) st->st_gid, owner);
296  printf("Device type: %d\n", (int) st->st_rdev);
297  printf("File size: %ld\n", (long) st->st_size);
298  printf("File last access time: %s", ctime (&st->st_atime));
299  printf("File last modify time: %s", ctime (&st->st_mtime));
300  printf("File last status change time: %s", ctime (&st->st_ctime));
301  fflush(stdout);
302  return(0);
303 }
304 
305 static int
307 char *f;
308 int flags;
309 {
310  struct stat *st;
311  struct passwd *pw;
312  struct group *gr;
313  int p;
314  char *b;
315 
316  st = getstat(f);
317  if (st == NULL)
318  return (1);
319 
320  /* Print requested info */
321  if (flags & OPT_ATIME) {
322  if (flags & OPT_ASCII)
323  printf("%s", ctime(&st->st_atime));
324  else
325  printf("%ld\n", st->st_atime);
326  } else if (flags & OPT_MTIME) {
327  if (flags & OPT_ASCII)
328  printf("%s", ctime(&st->st_mtime));
329  else
330  printf("%ld\n", st->st_mtime);
331  } else if (flags & OPT_CTIME) {
332  if (flags & OPT_ASCII)
333  printf("%s", ctime(&st->st_ctime));
334  else
335  printf("%ld\n", st->st_ctime);
336  } else if (flags & OPT_DEV)
337  printf("%d\n", st->st_dev);
338  else if (flags & OPT_INO)
339  printf("%d\n", st->st_ino);
340  else if (flags & OPT_FID)
341  printf("%d:%ld\n", st->st_dev, st->st_ino);
342  else if (flags & OPT_NLINK)
343  printf("%d\n", st->st_nlink);
344  else if (flags & OPT_LNKNAM) {
345 #ifdef S_ISLNK
346  b = xmalloc(4096);
347  p = readlink(f, b, 4096);
348  if (p >= 0 && p < 4096)
349  b[p] = '\0';
350  else {
351  p = errno;
352  strcpy(b, prog);
353  strcat(b, ": ");
354  strcat(b, strerror(p));
355  }
356  printf("%s\n", b);
357  free(b);
358 #else
359  printf("%s\n", f);
360 #endif
361  } else if (flags & OPT_PERM) {
362  perms(st->st_mode);
363  printf("\n");
364  } else if (flags & OPT_OPERM)
365  printf("%o\n", getperm(st->st_mode));
366  else if (flags & OPT_PMASK)
367  printf("%o\n", getperm(st->st_mode) & pmask);
368  else if (flags & OPT_UID) {
369  pw = getpwuid(st->st_uid);
370  if (flags & OPT_ASCII)
371  printf("%s\n", pw ? pw->pw_name : "unknown");
372  else
373  printf("%d\n", st->st_uid);
374  } else if (flags & OPT_GID) {
375  gr = getgrgid(st->st_gid);
376  if (flags & OPT_ASCII)
377  printf("%s\n", gr ? gr->gr_name : "unknown");
378  else
379  printf("%d\n", st->st_gid);
380  } else if (flags & OPT_SIZE)
381  printf("%ld\n", (long) st->st_size);
382 
383  return (0);
384 }
385 
386 #ifndef NOBUILTIN
387 int
389  WORD_LIST *list;
390 {
391  int c, r;
392  char **v;
393  WORD_LIST *l;
394 
395  v = make_builtin_argv (list, &c);
396  r = finfo_main (c, v);
397  free (v);
398 
399  return r;
400 }
401 
402 static char *finfo_doc[] = {
403  "Display information about file attributes.",
404  "",
405  "Display information about each FILE. Only single operators should",
406  "be supplied. If no options are supplied, a summary of the info",
407  "available about each FILE is printed. If FILE is of the form",
408  "/dev/fd/XX, file descriptor XX is described. Operators, if supplied,",
409  "have the following meanings:",
410  "",
411  " -a last file access time",
412  " -A last file access time in ctime format",
413  " -c last file status change time",
414  " -C last file status change time in ctime format",
415  " -m last file modification time",
416  " -M last file modification time in ctime format",
417  " -d device",
418  " -i inode",
419  " -f composite file identifier (device:inode)",
420  " -g gid of owner",
421  " -G group name of owner",
422  " -l name of file pointed to by symlink",
423  " -n link count",
424  " -o permissions in octal",
425  " -p permissions in ascii",
426  " -P mask permissions ANDed with MASK (like with umask)",
427  " -s file size in bytes",
428  " -u uid of owner",
429  " -U user name of owner",
430  (char *)0
431 };
432 
434  "finfo",
437  finfo_doc,
438  "finfo [-acdgiflmnopsuACGMPU] file [file...]",
439  0
440 };
441 #endif
442 
443 #ifdef NOBUILTIN
444 #if defined (PREFER_STDARG)
445 # include <stdarg.h>
446 #else
447 # if defined (PREFER_VARARGS)
448 # include <varargs.h>
449 # endif
450 #endif
451 
452 char *this_command_name;
453 
454 main(argc, argv)
455 int argc;
456 char **argv;
457 {
458  this_command_name = argv[0];
460 }
461 
462 void
464 {
465  fprintf(stderr, "%s: usage: %s [-%s] [file ...]\n", prog, prog, OPTIONS);
466 }
467 
468 #ifndef HAVE_STRERROR
469 char *
470 strerror(e)
471 int e;
472 {
473  static char ebuf[40];
474  extern int sys_nerr;
475  extern char *sys_errlist[];
476 
477  if (e < 0 || e > sys_nerr) {
478  sprintf(ebuf,"Unknown error code %d", e);
479  return (&ebuf[0]);
480  }
481  return (sys_errlist[e]);
482 }
483 #endif
484 
485 char *
486 xmalloc(s)
487 size_t s;
488 {
489  char *ret;
490  extern char *malloc();
491 
492  ret = malloc(s);
493  if (ret)
494  return (ret);
495  fprintf(stderr, "%s: cannot malloc %d bytes\n", prog, s);
496  exit(1);
497 }
498 
499 char *
501 char *p;
502 {
503  char *t;
504 
505  if (t = strrchr(p, '/'))
506  return(++t);
507  return(p);
508 }
509 
510 int
511 legal_number (string, result)
512  char *string;
513  long *result;
514 {
515  int sign;
516  long value;
517 
518  sign = 1;
519  value = 0;
520 
521  if (result)
522  *result = 0;
523 
524  /* Skip leading whitespace characters. */
525  while (whitespace (*string))
526  string++;
527 
528  if (!*string)
529  return (0);
530 
531  /* We allow leading `-' or `+'. */
532  if (*string == '-' || *string == '+')
533  {
534  if (!digit (string[1]))
535  return (0);
536 
537  if (*string == '-')
538  sign = -1;
539 
540  string++;
541  }
542 
543  while (digit (*string))
544  {
545  if (result)
546  value = (value * 10) + digit_value (*string);
547  string++;
548  }
549 
550  /* Skip trailing whitespace, if any. */
551  while (whitespace (*string))
552  string++;
553 
554  /* Error if not at end of string. */
555  if (*string)
556  return (0);
557 
558  if (result)
559  *result = value * sign;
560 
561  return (1);
562 }
563 
564 int sh_optind;
565 char *sh_optarg;
566 int sh_opterr;
567 
568 extern int optind;
569 extern char *optarg;
570 
571 int
572 sh_getopt(c, v, o)
573 int c;
574 char **v, *o;
575 {
576  int r;
577 
578  r = getopt(c, v, o);
579  sh_optind = optind;
580  sh_optarg = optarg;
581  return r;
582 }
583 
584 #if defined (USE_VARARGS)
585 void
586 #if defined (PREFER_STDARG)
587 builtin_error (const char *format, ...)
588 #else
589 builtin_error (format, va_alist)
590  const char *format;
591  va_dcl
592 #endif
593 {
594  va_list args;
595 
597  fprintf (stderr, "%s: ", this_command_name);
598 
599 #if defined (PREFER_STDARG)
600  va_start (args, format);
601 #else
602  va_start (args);
603 #endif
604 
605  vfprintf (stderr, format, args);
606  va_end (args);
607  fprintf (stderr, "\n");
608 }
609 #else
610 void
611 builtin_error (format, arg1, arg2, arg3, arg4, arg5)
612  char *format, *arg1, *arg2, *arg3, *arg4, *arg5;
613 {
615  fprintf (stderr, "%s: ", this_command_name);
616 
617  fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
618  fprintf (stderr, "\n");
619  fflush (stderr);
620 }
621 #endif /* !USE_VARARGS */
622 
623 #endif
int sh_opterr
Definition: getopt.c:72
#define S_IXUSR
Definition: posixstat.h:121
static int printst()
static char ** argv
Definition: test.c:110
struct passwd * getpwuid()
#define S_IRGRP
Definition: posixstat.h:123
list
Definition: subst.c:10212
#define OPT_DEV
Definition: finfo.c:66
#define OPT_CTIME
Definition: finfo.c:76
char * strerror()
struct group * getgrgid()
int CHAR * string
Definition: gm_loop.c:46
#define S_IWOTH
Definition: posixstat.h:128
#define OPT_INO
Definition: finfo.c:67
#define OPT_OPERM
Definition: finfo.c:81
static int printfinfo()
char * this_command_name
Definition: execute_cmd.c:202
#define OPT_ATIME
Definition: finfo.c:74
static char * prog
Definition: finfo.c:61
int finfo_builtin(WORD_LIST *list)
Definition: finfo.c:388
register GCHAR c
Definition: glob_loop.c:26
#define OPT_ASCII
Definition: finfo.c:83
static struct stat * getstat(char *f)
Definition: finfo.c:154
static int pmask
Definition: finfo.c:62
char * strrchr()
int errno
char * sh_optarg
Definition: getopt.c:39
static nls_uint32 nls_uint32 i
Definition: gettextP.h:74
p
Definition: glob_loop.c:31
void builtin_error(char *format, va_alist) const
Definition: common.c:106
#define S_IROTH
Definition: posixstat.h:127
#define S_IXOTH
Definition: posixstat.h:129
void builtin_usage()
Definition: common.c:145
#define OPT_UID
Definition: finfo.c:64
int sh_getopt(int argc, char *const *argv, const char *optstring)
Definition: getopt.c:114
#define S_IRWXO
Definition: posixstat.h:134
int t
Definition: gm_loop.c:77
static int getperm(int m)
Definition: finfo.c:192
#define OPT_GID
Definition: finfo.c:65
#define whitespace(c)
Definition: gen-helpfiles.c:78
char * strcpy()
#define BUILTIN_ENABLED
Definition: builtins.h:41
void exit()
static void printmode()
#define OPTIONS
Definition: finfo.c:85
char ** make_builtin_argv()
void free()
int sys_nerr
#define S_IXGRP
Definition: posixstat.h:125
struct builtin finfo_struct
Definition: finfo.c:433
static int finfo_main()
char * optarg
static int argc
Definition: test.c:109
#define OPT_PMASK
Definition: finfo.c:80
#define OPT_PERM
Definition: finfo.c:68
#define OPT_FID
Definition: finfo.c:70
#define NULL
Definition: general.h:53
static char * finfo_doc[]
Definition: finfo.c:402
#define S_ISDIR(m)
Definition: posixstat.h:88
int flags
Definition: gm_loop.c:47
#define S_IRUSR
Definition: posixstat.h:119
int main(int argc, char **argv)
#define OPT_LNKNAM
Definition: finfo.c:69
static int octal(char *s)
Definition: finfo.c:88
#define lstat
Definition: getcwd.c:64
#define S_IWGRP
Definition: posixstat.h:124
#define OPT_SIZE
Definition: finfo.c:73
#define S_IRWXG
Definition: posixstat.h:133
char * base_pathname(char *string)
Definition: general.c:765
static void perms()
#define OPT_NLINK
Definition: finfo.c:71
#define S_IRWXU
Definition: posixstat.h:132
#define S_IWUSR
Definition: posixstat.h:120
int legal_number(char *string, intmax_t *result) const
Definition: general.c:175
static char * xmalloc()
int sh_optind
Definition: getopt.c:54
int optind
static int printsome()
#define malloc
Definition: alloca.c:79
#define OPT_MTIME
Definition: finfo.c:75