1 /* listfile.c -- display a long listing of a file
2 Copyright (C) 1991, 1993, 2000 Free Software Foundation, Inc.
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)
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
43 #include <sys/types.h>
58 #if HAVE_STRING_H || STDC_HEADERS
66 #include <unistd.h> /* for readlink() */
76 /* Since major is a function on SVR4, we can't use `ifndef major'. */
78 #include <sys/mkdev.h>
81 #ifdef MAJOR_IN_SYSMACROS
82 #include <sys/sysmacros.h>
86 #ifdef STAT_MACROS_BROKEN
93 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
96 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
98 #if defined(S_IFLNK) && !defined(S_ISLNK)
99 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
102 /* Get or fake the disk device blocksize.
103 Usually defined by sys/param.h (if at all). */
106 # define DEV_BSIZE BSIZE
108 # define DEV_BSIZE 4096
110 #endif /* !DEV_BSIZE */
112 /* Extract or fake data from a `struct stat'.
113 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
114 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
115 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
116 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
117 # define ST_BLKSIZE(statbuf) DEV_BSIZE
118 # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */
119 # define ST_NBLOCKS(statbuf) \
120 (S_ISREG ((statbuf).st_mode) \
121 || S_ISDIR ((statbuf).st_mode) \
122 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
123 # else /* !_POSIX_SOURCE && BSIZE */
124 # define ST_NBLOCKS(statbuf) \
125 (S_ISREG ((statbuf).st_mode) \
126 || S_ISDIR ((statbuf).st_mode) \
127 ? st_blocks ((statbuf).st_size) : 0)
128 # endif /* !_POSIX_SOURCE && BSIZE */
129 #else /* HAVE_STRUCT_STAT_ST_BLOCKS */
130 /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
131 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
132 ? (statbuf).st_blksize : DEV_BSIZE)
133 # if defined(hpux) || defined(__hpux__) || defined(__hpux)
134 /* HP-UX counts st_blocks in 1024-byte units.
135 This loses when mixing HP-UX and BSD filesystems with NFS. */
136 # define ST_NBLOCKSIZE 1024
138 # if defined(_AIX) && defined(_I386)
139 /* AIX PS/2 counts st_blocks in 4K units. */
140 # define ST_NBLOCKSIZE (4 * 1024)
141 # else /* not AIX PS/2 */
143 # define ST_NBLOCKS(statbuf) \
144 (S_ISREG ((statbuf).st_mode) \
145 || S_ISDIR ((statbuf).st_mode) \
146 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
148 # endif /* not AIX PS/2 */
150 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
153 # define ST_NBLOCKS(statbuf) \
154 (S_ISREG ((statbuf).st_mode) \
155 || S_ISDIR ((statbuf).st_mode) \
156 ? (statbuf).st_blocks : 0)
159 #ifndef ST_NBLOCKSIZE
160 # define ST_NBLOCKSIZE 512
163 #ifndef _POSIX_VERSION
164 struct passwd
*getpwuid ();
165 struct group
*getgrgid ();
168 #ifdef major /* Might be defined in sys/types.h. */
172 #define major(dev) (((dev) >> 8) & 0xff)
173 #define minor(dev) ((dev) & 0xff)
178 char * get_link_name (char *name
, char *relname
);
179 static void print_name_with_quoting (register char *p
, FILE *stream
);
181 extern char * getgroup (gid_t gid
);
182 extern char * getuser (uid_t uid
);
185 /* NAME is the name to print.
186 RELNAME is the path to access it from the current directory.
187 STATP is the results of stat or lstat on it.
188 Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
189 Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
191 STREAM is the stdio stream to print on. */
194 list_file (char *name
,
198 int output_block_size
,
202 struct tm
const *when_local
;
203 char const *user_name
;
204 char const *group_name
;
205 char hbuf
[LONGEST_HUMAN_READABLE
+ 1];
208 /* Cray DMF: look at the file's migrated, not real, status */
209 mode_string (statp
->st_dm_mode
, modebuf
);
211 mode_string (statp
->st_mode
, modebuf
);
215 fprintf (stream
, "%6s ",
216 human_readable ((uintmax_t) statp
->st_ino
, hbuf
,
220 fprintf (stream
, "%4s ",
221 human_readable ((uintmax_t) ST_NBLOCKS (*statp
), hbuf
,
223 ST_NBLOCKSIZE
, output_block_size
));
226 /* The space between the mode and the number of links is the POSIX
227 "optional alternate access method flag". */
228 fprintf (stream
, "%s %3lu ", modebuf
, (unsigned long) statp
->st_nlink
);
230 user_name
= getuser (statp
->st_uid
);
232 fprintf (stream
, "%-8s ", user_name
);
234 fprintf (stream
, "%-8lu ", (unsigned long) statp
->st_uid
);
236 group_name
= getgroup (statp
->st_gid
);
238 fprintf (stream
, "%-8s ", group_name
);
240 fprintf (stream
, "%-8lu ", (unsigned long) statp
->st_gid
);
242 if (S_ISCHR (statp
->st_mode
) || S_ISBLK (statp
->st_mode
))
244 fprintf (stream
, "%3lu, %3lu ",
245 (unsigned long) major (statp
->st_rdev
),
246 (unsigned long) minor (statp
->st_rdev
));
248 fprintf (stream
, " ");
251 fprintf (stream
, "%8s ",
252 human_readable ((uintmax_t) statp
->st_size
, hbuf
,
255 output_block_size
< 0 ? output_block_size
: 1));
257 if ((when_local
= localtime (&statp
->st_mtime
)))
259 char init_bigbuf
[256];
260 char *buf
= init_bigbuf
;
261 size_t bufsize
= sizeof init_bigbuf
;
263 /* Use strftime rather than ctime, because the former can produce
264 locale-dependent names for the month (%b).
266 Output the year if the file is fairly old or in the future.
267 POSIX says the cutoff is 6 months old;
268 approximate this by 6*30 days.
269 Allow a 1 hour slop factor for what is considered "the future",
270 to allow for NFS server/client clock disagreement. */
272 ((current_time
- 6 * 30 * 24 * 60 * 60 <= statp
->st_mtime
273 && statp
->st_mtime
<= current_time
+ 60 * 60)
277 while (!strftime (buf
, bufsize
, fmt
, when_local
))
278 buf
= (char *) alloca (bufsize
*= 2);
280 fprintf (stream
, "%s ", buf
);
284 /* The time cannot be represented as a local time;
285 print it as a huge integer number of seconds. */
288 if (statp
->st_mtime
< 0)
290 char const *num
= human_readable (- (uintmax_t) statp
->st_mtime
,
291 hbuf
, human_ceiling
, 1, 1);
292 int sign_width
= width
- strlen (num
);
293 fprintf (stream
, "%*s%s ",
294 sign_width
< 0 ? 0 : sign_width
, "-", num
);
297 fprintf (stream
, "%*s ", width
,
298 human_readable ((uintmax_t) statp
->st_mtime
, hbuf
,
303 print_name_with_quoting (name
, stream
);
306 if (S_ISLNK (statp
->st_mode
))
308 char *linkname
= get_link_name (name
, relname
);
312 fputs (" -> ", stream
);
313 print_name_with_quoting (linkname
, stream
);
322 print_name_with_quoting (register char *p
, FILE *stream
)
324 register unsigned char c
;
326 while ((c
= *p
++) != '\0')
331 fprintf (stream
, "\\\\");
335 fprintf (stream
, "\\n");
339 fprintf (stream
, "\\b");
343 fprintf (stream
, "\\r");
347 fprintf (stream
, "\\t");
351 fprintf (stream
, "\\f");
355 fprintf (stream
, "\\ ");
359 fprintf (stream
, "\\\"");
363 if (c
> 040 && c
< 0177)
366 fprintf (stream
, "\\%03o", (unsigned int) c
);
373 get_link_name (char *name
, char *relname
)
375 register char *linkname
;
376 register int linklen
;
378 /* st_size is wrong for symlinks on AIX, and on
379 mount points with some automounters.
380 So allocate a pessimistic PATH_MAX + 1 bytes. */
381 #define LINK_BUF PATH_MAX
382 linkname
= (char *) xmalloc (LINK_BUF
+ 1);
383 linklen
= readlink (relname
, linkname
, LINK_BUF
);
386 error (0, errno
, "%s", name
);
390 linkname
[linklen
] = '\0';