home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / find-3.8-src.lha / src / amiga / find-3.8 / lib / listfile.c < prev    next >
C/C++ Source or Header  |  1992-12-13  |  6KB  |  255 lines

  1. /* listfile.c -- display a long listing of a file
  2.    Copyright (C) 1985, 1988, 1991 Free Software Foundation, Inc.
  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
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #ifndef S_ISCHR
  22. #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
  23. #endif
  24. #ifndef S_ISBLK
  25. #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
  26. #endif
  27. #if defined(S_IFLNK) && !defined(S_ISLNK)
  28. #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
  29. #endif
  30.  
  31. /* Extract or fake data from a `struct stat'.
  32.    ST_NBLOCKS: Number of 512-byte blocks in the file
  33.    (including indirect blocks). */
  34. #ifdef _POSIX_SOURCE
  35. #define ST_NBLOCKS(statp) (((statp)->st_size + 512 - 1) / 512)
  36. #else /* !_POSIX_SOURCE */
  37. #ifndef HAVE_ST_BLOCKS
  38. #define ST_NBLOCKS(statp) (st_blocks ((statp)->st_size))
  39. #else /* HAVE_ST_BLOCKS */
  40. #if defined(hpux) || defined(__hpux__)
  41. /* HP-UX, perhaps uniquely, counts st_blocks in 1024-byte units.
  42.    This loses when mixing HP-UX and 4BSD filesystems, though. */
  43. #define ST_NBLOCKS(statp) ((statp)->st_blocks * 2)
  44. #else /* !hpux */
  45. #define ST_NBLOCKS(statp) ((statp)->st_blocks)
  46. #endif /* hpux */
  47. #endif /* HAVE_ST_BLOCKS */
  48. #endif /* _POSIX_SOURCE */
  49.  
  50. /* Convert B 512-byte blocks to kilobytes if K is nonzero,
  51.    otherwise return it unchanged. */
  52. #define convert_blocks(b, k) ((k) ? ((b) + 1) / 2 : (b))
  53.  
  54. #ifdef HAVE_UNISTD_H
  55. #include <unistd.h>
  56. #endif
  57.  
  58. #include <pwd.h>
  59. #include <grp.h>
  60. #ifndef _POSIX_VERSION
  61. struct passwd *getpwuid ();
  62. struct group *getgrgid ();
  63. #endif
  64.  
  65. #include <time.h>
  66.  
  67. #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
  68. #include <string.h>
  69. #else
  70. #include <strings.h>
  71. #endif
  72.  
  73. /* Since major is a function on SVR4, we can't use `ifndef major'.  */
  74. #ifdef MAJOR_IN_MKDEV
  75. #include <sys/mkdev.h>
  76. #define HAVE_MAJOR
  77. #endif
  78. #ifdef MAJOR_IN_SYSMACROS
  79. #include <sys/sysmacros.h>
  80. #define HAVE_MAJOR
  81. #endif
  82. #ifdef major            /* Might be defined in sys/types.h.  */
  83. #define HAVE_MAJOR
  84. #endif
  85.  
  86. #ifndef HAVE_MAJOR
  87. #define major(dev)  (((dev) >> 8) & 0xff)
  88. #define minor(dev)  ((dev) & 0xff)
  89. #endif
  90. #undef HAVE_MAJOR
  91.  
  92. #include <errno.h>
  93. #ifdef STDC_HEADERS
  94. #include <stdlib.h>
  95. #else
  96. char *getenv ();
  97. extern int errno;
  98. #endif
  99.  
  100. #if defined(S_ISLNK)
  101. int readlink ();
  102. #endif
  103.  
  104. char *xmalloc ();
  105. void error ();
  106. void mode_string ();
  107.  
  108. char *get_link_name ();
  109. char *getgroup ();
  110. char *getuser ();
  111. void print_name_with_quoting ();
  112.  
  113. void
  114. list_file (name, statp)
  115.      char *name;
  116.      struct stat *statp;
  117. {
  118.   static int kilobytes = -1;    /* -1 = uninitialized, 0 = 512, 1 = 1024. */
  119.   char modebuf[20];
  120.   char timebuf[40];
  121.   time_t current_time = time ((time_t *) 0);
  122.  
  123.   if (kilobytes == -1)
  124.     kilobytes = getenv ("POSIXLY_CORRECT") == 0;
  125.  
  126.   mode_string (statp->st_mode, modebuf);
  127.   modebuf[10] = '\0';
  128.  
  129.   strcpy (timebuf, ctime (&statp->st_mtime));
  130.   if (current_time > statp->st_mtime + 6L * 30L * 24L * 60L * 60L /* Old. */
  131.       || current_time < statp->st_mtime - 60L * 60L) /* In the future. */
  132.     {
  133.       /* The file is fairly old or in the future.
  134.      POSIX says the cutoff is 6 months old;
  135.      approximate this by 6*30 days.
  136.      Allow a 1 hour slop factor for what is considered "the future",
  137.      to allow for NFS server/client clock disagreement.
  138.      Show the year instead of the time of day.  */
  139.       strcpy (timebuf + 11, timebuf + 19);
  140.     }
  141.   timebuf[16] = 0;
  142.  
  143.   printf ("%6u ", statp->st_ino);
  144.  
  145.   printf ("%4u ", convert_blocks (ST_NBLOCKS (statp), kilobytes));
  146.  
  147.   /* The space between the mode and the number of links is the POSIX
  148.      "optional alternate access method flag". */
  149.   printf ("%s %3u ", modebuf, statp->st_nlink);
  150.  
  151.   printf ("%-8.8s ", getuser (statp->st_uid));
  152.  
  153.   printf ("%-8.8s ", getgroup (statp->st_gid));
  154.  
  155.   if (S_ISCHR (statp->st_mode) || S_ISBLK (statp->st_mode))
  156. #ifdef HAVE_ST_RDEV
  157.     printf ("%3u, %3u ", major (statp->st_rdev), minor (statp->st_rdev));
  158. #else
  159.     printf ("         ");
  160. #endif
  161.   else
  162.     printf ("%8lu ", statp->st_size);
  163.  
  164.   printf ("%s ", timebuf + 4);
  165.  
  166.   print_name_with_quoting (name);
  167.  
  168. #ifdef S_IFLNK
  169.   if (S_ISLNK (statp->st_mode))
  170.     {
  171.       char *linkname = get_link_name (name, statp);
  172.  
  173.       if (linkname)
  174.     {
  175.       fputs (" -> ", stdout);
  176.       print_name_with_quoting (linkname);
  177.       free (linkname);
  178.     }
  179.     }
  180. #endif
  181.   putchar ('\n');
  182. }
  183.  
  184. void
  185. print_name_with_quoting (p)
  186.      register char *p;
  187. {
  188.   register unsigned char c;
  189.  
  190.   while ((c = *p++) != '\0')
  191.     {
  192.       switch (c)
  193.     {
  194.     case '\\':
  195.       printf ("\\\\");
  196.       break;
  197.  
  198.     case '\n':
  199.       printf ("\\n");
  200.       break;
  201.  
  202.     case '\b':
  203.       printf ("\\b");
  204.       break;
  205.  
  206.     case '\r':
  207.       printf ("\\r");
  208.       break;
  209.  
  210.     case '\t':
  211.       printf ("\\t");
  212.       break;
  213.  
  214.     case '\f':
  215.       printf ("\\f");
  216.       break;
  217.  
  218.     case ' ':
  219.       printf ("\\ ");
  220.       break;
  221.  
  222.     case '"':
  223.       printf ("\\\"");
  224.       break;
  225.  
  226.     default:
  227.       if (c > 040 && c < 0177)
  228.         putchar (c);
  229.       else
  230.         printf ("\\%03o", (unsigned int) c);
  231.     }
  232.     }
  233. }
  234.  
  235. #ifdef S_IFLNK
  236. char *
  237. get_link_name (filename, statp)
  238.      char *filename;
  239.      struct stat *statp;
  240. {
  241.   register char *linkbuf;
  242.   register int bufsiz = statp->st_size;
  243.  
  244.   linkbuf = (char *) xmalloc (bufsiz + 1);
  245.   linkbuf[bufsiz] = 0;
  246.   if (readlink (filename, linkbuf, bufsiz) < 0)
  247.     {
  248.       error (0, errno, "%s", filename);
  249.       free (linkbuf);
  250.       return 0;
  251.     }
  252.   return linkbuf;
  253. }
  254. #endif
  255.