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., 675 Mass Ave, Cambridge, MA 02139, USA. */
41 #include <sys/types.h>
51 #if HAVE_STRING_H || STDC_HEADERS
64 /* Since major is a function on SVR4, we can't use `ifndef major'. */
66 #include <sys/mkdev.h>
69 #ifdef MAJOR_IN_SYSMACROS
70 #include <sys/sysmacros.h>
74 #ifdef STAT_MACROS_BROKEN
81 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
84 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
86 #if defined(S_IFLNK) && !defined(S_ISLNK)
87 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
94 /* Get or fake the disk device blocksize.
95 Usually defined by sys/param.h (if at all). */
98 # define DEV_BSIZE BSIZE
100 # define DEV_BSIZE 4096
102 #endif /* !DEV_BSIZE */
104 /* Extract or fake data from a `struct stat'.
105 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
106 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
107 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
108 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
109 # define ST_BLKSIZE(statbuf) DEV_BSIZE
110 # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */
111 # define ST_NBLOCKS(statbuf) \
112 (S_ISREG ((statbuf).st_mode) \
113 || S_ISDIR ((statbuf).st_mode) \
114 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
115 # else /* !_POSIX_SOURCE && BSIZE */
116 # define ST_NBLOCKS(statbuf) \
117 (S_ISREG ((statbuf).st_mode) \
118 || S_ISDIR ((statbuf).st_mode) \
119 ? st_blocks ((statbuf).st_size) : 0)
120 # endif /* !_POSIX_SOURCE && BSIZE */
121 #else /* HAVE_STRUCT_STAT_ST_BLOCKS */
122 /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
123 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
124 ? (statbuf).st_blksize : DEV_BSIZE)
125 # if defined(hpux) || defined(__hpux__) || defined(__hpux)
126 /* HP-UX counts st_blocks in 1024-byte units.
127 This loses when mixing HP-UX and BSD filesystems with NFS. */
128 # define ST_NBLOCKSIZE 1024
130 # if defined(_AIX) && defined(_I386)
131 /* AIX PS/2 counts st_blocks in 4K units. */
132 # define ST_NBLOCKSIZE (4 * 1024)
133 # else /* not AIX PS/2 */
135 # define ST_NBLOCKS(statbuf) \
136 (S_ISREG ((statbuf).st_mode) \
137 || S_ISDIR ((statbuf).st_mode) \
138 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
140 # endif /* not AIX PS/2 */
142 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
145 # define ST_NBLOCKS(statbuf) \
146 (S_ISREG ((statbuf).st_mode) \
147 || S_ISDIR ((statbuf).st_mode) \
148 ? (statbuf).st_blocks : 0)
151 #ifndef ST_NBLOCKSIZE
152 # define ST_NBLOCKSIZE 512
155 #ifndef _POSIX_VERSION
156 struct passwd
*getpwuid ();
157 struct group
*getgrgid ();
160 #ifdef major /* Might be defined in sys/types.h. */
164 #define major(dev) (((dev) >> 8) & 0xff)
165 #define minor(dev) ((dev) & 0xff)
173 char *get_link_name ();
176 void print_name_with_quoting ();
178 /* NAME is the name to print.
179 RELNAME is the path to access it from the current directory.
180 STATP is the results of stat or lstat on it.
181 Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
182 Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
184 STREAM is the stdio stream to print on. */
187 list_file (name
, relname
, statp
, current_time
, output_block_size
, stream
)
192 int output_block_size
;
196 struct tm
const *when_local
;
197 char const *user_name
;
198 char const *group_name
;
199 char hbuf
[LONGEST_HUMAN_READABLE
+ 1];
202 /* Cray DMF: look at the file's migrated, not real, status */
203 mode_string (statp
->st_dm_mode
, modebuf
);
205 mode_string (statp
->st_mode
, modebuf
);
209 fprintf (stream
, "%6s ",
210 human_readable ((uintmax_t) statp
->st_ino
, hbuf
, 1, 1));
212 fprintf (stream
, "%4s ",
213 human_readable ((uintmax_t) ST_NBLOCKS (*statp
), hbuf
,
214 ST_NBLOCKSIZE
, output_block_size
));
216 /* The space between the mode and the number of links is the POSIX
217 "optional alternate access method flag". */
218 fprintf (stream
, "%s %3lu ", modebuf
, (unsigned long) statp
->st_nlink
);
220 user_name
= getuser (statp
->st_uid
);
222 fprintf (stream
, "%-8.8s ", user_name
);
224 fprintf (stream
, "%-8lu ", (unsigned long) statp
->st_uid
);
226 group_name
= getgroup (statp
->st_gid
);
228 fprintf (stream
, "%-8.8s ", group_name
);
230 fprintf (stream
, "%-8lu ", (unsigned long) statp
->st_gid
);
232 if (S_ISCHR (statp
->st_mode
) || S_ISBLK (statp
->st_mode
))
234 fprintf (stream
, "%3lu, %3lu ",
235 (unsigned long) major (statp
->st_rdev
),
236 (unsigned long) minor (statp
->st_rdev
));
238 fprintf (stream
, " ");
241 fprintf (stream
, "%8s ",
242 human_readable ((uintmax_t) statp
->st_size
, hbuf
, 1,
243 output_block_size
< 0 ? output_block_size
: 1));
245 if ((when_local
= localtime (&statp
->st_mtime
)))
247 char init_bigbuf
[256];
248 char *buf
= init_bigbuf
;
249 size_t bufsize
= sizeof init_bigbuf
;
251 /* Use strftime rather than ctime, because the former can produce
252 locale-dependent names for the month (%b).
254 Output the year if the file is fairly old or in the future.
255 POSIX says the cutoff is 6 months old;
256 approximate this by 6*30 days.
257 Allow a 1 hour slop factor for what is considered "the future",
258 to allow for NFS server/client clock disagreement. */
260 ((current_time
- 6 * 30 * 24 * 60 * 60 <= statp
->st_mtime
261 && statp
->st_mtime
<= current_time
+ 60 * 60)
265 while (!strftime (buf
, bufsize
, fmt
, when_local
))
266 buf
= (char *) alloca (bufsize
*= 2);
268 fprintf (stream
, "%s ", buf
);
272 /* The time cannot be represented as a local time;
273 print it as a huge integer number of seconds. */
276 if (statp
->st_mtime
< 0)
278 char const *num
= human_readable (- (uintmax_t) statp
->st_mtime
,
280 int sign_width
= width
- strlen (num
);
281 fprintf (stream
, "%*s%s ",
282 sign_width
< 0 ? 0 : sign_width
, "-", num
);
285 fprintf (stream
, "%*s ", width
,
286 human_readable ((uintmax_t) statp
->st_mtime
, hbuf
, 1, 1));
289 print_name_with_quoting (name
, stream
);
292 if (S_ISLNK (statp
->st_mode
))
294 char *linkname
= get_link_name (name
, relname
);
298 fputs (" -> ", stream
);
299 print_name_with_quoting (linkname
, stream
);
308 print_name_with_quoting (p
, stream
)
312 register unsigned char c
;
314 while ((c
= *p
++) != '\0')
319 fprintf (stream
, "\\\\");
323 fprintf (stream
, "\\n");
327 fprintf (stream
, "\\b");
331 fprintf (stream
, "\\r");
335 fprintf (stream
, "\\t");
339 fprintf (stream
, "\\f");
343 fprintf (stream
, "\\ ");
347 fprintf (stream
, "\\\"");
351 if (c
> 040 && c
< 0177)
354 fprintf (stream
, "\\%03o", (unsigned int) c
);
361 get_link_name (name
, relname
)
365 register char *linkname
;
366 register int linklen
;
368 /* st_size is wrong for symlinks on AIX, and on
369 mount points with some automounters.
370 So allocate a pessimistic PATH_MAX + 1 bytes. */
371 #define LINK_BUF PATH_MAX
372 linkname
= (char *) xmalloc (LINK_BUF
+ 1);
373 linklen
= readlink (relname
, linkname
, LINK_BUF
);
376 error (0, errno
, "%s", name
);
380 linkname
[linklen
] = '\0';