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
65 /* The presence of unistd.h is assumed by gnulib these days, so we
66 * might as well assume it too.
68 #include <unistd.h> /* for readlink() */
78 /* Since major is a function on SVR4, we can't use `ifndef major'. */
80 #include <sys/mkdev.h>
83 #ifdef MAJOR_IN_SYSMACROS
84 #include <sys/sysmacros.h>
88 #ifdef STAT_MACROS_BROKEN
95 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
98 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
100 #if defined(S_IFLNK) && !defined(S_ISLNK)
101 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
104 /* Get or fake the disk device blocksize.
105 Usually defined by sys/param.h (if at all). */
108 # define DEV_BSIZE BSIZE
110 # define DEV_BSIZE 4096
112 #endif /* !DEV_BSIZE */
114 /* Extract or fake data from a `struct stat'.
115 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
116 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
117 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
118 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
119 # define ST_BLKSIZE(statbuf) DEV_BSIZE
120 # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */
121 # define ST_NBLOCKS(statbuf) \
122 (S_ISREG ((statbuf).st_mode) \
123 || S_ISDIR ((statbuf).st_mode) \
124 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
125 # else /* !_POSIX_SOURCE && BSIZE */
126 # define ST_NBLOCKS(statbuf) \
127 (S_ISREG ((statbuf).st_mode) \
128 || S_ISDIR ((statbuf).st_mode) \
129 ? st_blocks ((statbuf).st_size) : 0)
130 # endif /* !_POSIX_SOURCE && BSIZE */
131 #else /* HAVE_STRUCT_STAT_ST_BLOCKS */
132 /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
133 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
134 ? (statbuf).st_blksize : DEV_BSIZE)
135 # if defined(hpux) || defined(__hpux__) || defined(__hpux)
136 /* HP-UX counts st_blocks in 1024-byte units.
137 This loses when mixing HP-UX and BSD filesystems with NFS. */
138 # define ST_NBLOCKSIZE 1024
140 # if defined(_AIX) && defined(_I386)
141 /* AIX PS/2 counts st_blocks in 4K units. */
142 # define ST_NBLOCKSIZE (4 * 1024)
143 # else /* not AIX PS/2 */
145 # define ST_NBLOCKS(statbuf) \
146 (S_ISREG ((statbuf).st_mode) \
147 || S_ISDIR ((statbuf).st_mode) \
148 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
150 # endif /* not AIX PS/2 */
152 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
155 # define ST_NBLOCKS(statbuf) \
156 (S_ISREG ((statbuf).st_mode) \
157 || S_ISDIR ((statbuf).st_mode) \
158 ? (statbuf).st_blocks : 0)
161 #ifndef ST_NBLOCKSIZE
162 # define ST_NBLOCKSIZE 512
165 #ifndef _POSIX_VERSION
166 struct passwd
*getpwuid ();
167 struct group
*getgrgid ();
170 #ifdef major /* Might be defined in sys/types.h. */
174 #define major(dev) (((dev) >> 8) & 0xff)
175 #define minor(dev) ((dev) & 0xff)
180 static void print_name (register char *p
, FILE *stream
, int literal_control_chars
);
182 extern char * getgroup (gid_t gid
);
183 extern char * getuser (uid_t uid
);
188 file_blocksize(const struct stat
*p
)
190 return ST_NBLOCKSIZE
;
195 /* NAME is the name to print.
196 RELNAME is the path to access it from the current directory.
197 STATP is the results of stat or lstat on it.
198 Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
199 Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
201 STREAM is the stdio stream to print on. */
204 list_file (char *name
,
208 int output_block_size
,
209 int literal_control_chars
,
213 struct tm
const *when_local
;
214 char const *user_name
;
215 char const *group_name
;
216 char hbuf
[LONGEST_HUMAN_READABLE
+ 1];
219 /* Cray DMF: look at the file's migrated, not real, status */
220 strmode (statp
->st_dm_mode
, modebuf
);
222 strmode (statp
->st_mode
, modebuf
);
226 fprintf (stream
, "%6s ",
227 human_readable ((uintmax_t) statp
->st_ino
, hbuf
,
231 fprintf (stream
, "%4s ",
232 human_readable ((uintmax_t) ST_NBLOCKS (*statp
), hbuf
,
234 ST_NBLOCKSIZE
, output_block_size
));
237 /* The space between the mode and the number of links is the POSIX
238 "optional alternate access method flag". */
239 fprintf (stream
, "%s %3lu ", modebuf
, (unsigned long) statp
->st_nlink
);
241 user_name
= getuser (statp
->st_uid
);
243 fprintf (stream
, "%-8s ", user_name
);
245 fprintf (stream
, "%-8lu ", (unsigned long) statp
->st_uid
);
247 group_name
= getgroup (statp
->st_gid
);
249 fprintf (stream
, "%-8s ", group_name
);
251 fprintf (stream
, "%-8lu ", (unsigned long) statp
->st_gid
);
253 if (S_ISCHR (statp
->st_mode
) || S_ISBLK (statp
->st_mode
))
255 fprintf (stream
, "%3lu, %3lu ",
256 (unsigned long) major (statp
->st_rdev
),
257 (unsigned long) minor (statp
->st_rdev
));
259 fprintf (stream
, " ");
262 fprintf (stream
, "%8s ",
263 human_readable ((uintmax_t) statp
->st_size
, hbuf
,
266 output_block_size
< 0 ? output_block_size
: 1));
268 if ((when_local
= localtime (&statp
->st_mtime
)))
270 char init_bigbuf
[256];
271 char *buf
= init_bigbuf
;
272 size_t bufsize
= sizeof init_bigbuf
;
274 /* Use strftime rather than ctime, because the former can produce
275 locale-dependent names for the month (%b).
277 Output the year if the file is fairly old or in the future.
278 POSIX says the cutoff is 6 months old;
279 approximate this by 6*30 days.
280 Allow a 1 hour slop factor for what is considered "the future",
281 to allow for NFS server/client clock disagreement. */
283 ((current_time
- 6 * 30 * 24 * 60 * 60 <= statp
->st_mtime
284 && statp
->st_mtime
<= current_time
+ 60 * 60)
288 while (!strftime (buf
, bufsize
, fmt
, when_local
))
289 buf
= (char *) alloca (bufsize
*= 2);
291 fprintf (stream
, "%s ", buf
);
295 /* The time cannot be represented as a local time;
296 print it as a huge integer number of seconds. */
299 if (statp
->st_mtime
< 0)
301 char const *num
= human_readable (- (uintmax_t) statp
->st_mtime
,
302 hbuf
, human_ceiling
, 1, 1);
303 int sign_width
= width
- strlen (num
);
304 fprintf (stream
, "%*s%s ",
305 sign_width
< 0 ? 0 : sign_width
, "-", num
);
308 fprintf (stream
, "%*s ", width
,
309 human_readable ((uintmax_t) statp
->st_mtime
, hbuf
,
314 print_name (name
, stream
, literal_control_chars
);
317 if (S_ISLNK (statp
->st_mode
))
319 char *linkname
= get_link_name (name
, relname
);
323 fputs (" -> ", stream
);
324 print_name (linkname
, stream
, literal_control_chars
);
334 print_name_without_quoting (char *p
, FILE *stream
)
336 fprintf(stream
, "%s", p
);
341 print_name_with_quoting (register char *p
, FILE *stream
)
343 register unsigned char c
;
345 while ((c
= *p
++) != '\0')
350 fprintf (stream
, "\\\\");
354 fprintf (stream
, "\\n");
358 fprintf (stream
, "\\b");
362 fprintf (stream
, "\\r");
366 fprintf (stream
, "\\t");
370 fprintf (stream
, "\\f");
374 fprintf (stream
, "\\ ");
378 fprintf (stream
, "\\\"");
382 if (c
> 040 && c
< 0177)
385 fprintf (stream
, "\\%03o", (unsigned int) c
);
390 static void print_name (register char *p
, FILE *stream
, int literal_control_chars
)
392 if (literal_control_chars
)
393 print_name_without_quoting(p
, stream
);
395 print_name_with_quoting(p
, stream
);
400 get_link_name (const char *name
, char *relname
)
402 register char *linkname
;
403 register int linklen
;
405 /* st_size is wrong for symlinks on AIX, and on
406 mount points with some automounters.
407 So allocate a pessimistic PATH_MAX + 1 bytes. */
408 #define LINK_BUF PATH_MAX
409 linkname
= (char *) xmalloc (LINK_BUF
+ 1);
410 linklen
= readlink (relname
, linkname
, LINK_BUF
);
413 error (0, errno
, "%s", name
);
417 linkname
[linklen
] = '\0';