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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
43 #include <sys/types.h>
50 #include "../gnulib/lib/human.h"
51 #include "../gnulib/lib/pathmax.h"
53 #if HAVE_STRING_H || STDC_HEADERS
66 /* Since major is a function on SVR4, we can't use `ifndef major'. */
68 #include <sys/mkdev.h>
71 #ifdef MAJOR_IN_SYSMACROS
72 #include <sys/sysmacros.h>
76 #ifdef STAT_MACROS_BROKEN
83 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
86 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
88 #if defined(S_IFLNK) && !defined(S_ISLNK)
89 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
96 /* Get or fake the disk device blocksize.
97 Usually defined by sys/param.h (if at all). */
100 # define DEV_BSIZE BSIZE
102 # define DEV_BSIZE 4096
104 #endif /* !DEV_BSIZE */
106 /* Extract or fake data from a `struct stat'.
107 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
108 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
109 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
110 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
111 # define ST_BLKSIZE(statbuf) DEV_BSIZE
112 # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */
113 # define ST_NBLOCKS(statbuf) \
114 (S_ISREG ((statbuf).st_mode) \
115 || S_ISDIR ((statbuf).st_mode) \
116 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
117 # else /* !_POSIX_SOURCE && BSIZE */
118 # define ST_NBLOCKS(statbuf) \
119 (S_ISREG ((statbuf).st_mode) \
120 || S_ISDIR ((statbuf).st_mode) \
121 ? st_blocks ((statbuf).st_size) : 0)
122 # endif /* !_POSIX_SOURCE && BSIZE */
123 #else /* HAVE_STRUCT_STAT_ST_BLOCKS */
124 /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
125 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
126 ? (statbuf).st_blksize : DEV_BSIZE)
127 # if defined(hpux) || defined(__hpux__) || defined(__hpux)
128 /* HP-UX counts st_blocks in 1024-byte units.
129 This loses when mixing HP-UX and BSD filesystems with NFS. */
130 # define ST_NBLOCKSIZE 1024
132 # if defined(_AIX) && defined(_I386)
133 /* AIX PS/2 counts st_blocks in 4K units. */
134 # define ST_NBLOCKSIZE (4 * 1024)
135 # else /* not AIX PS/2 */
137 # define ST_NBLOCKS(statbuf) \
138 (S_ISREG ((statbuf).st_mode) \
139 || S_ISDIR ((statbuf).st_mode) \
140 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
142 # endif /* not AIX PS/2 */
144 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
147 # define ST_NBLOCKS(statbuf) \
148 (S_ISREG ((statbuf).st_mode) \
149 || S_ISDIR ((statbuf).st_mode) \
150 ? (statbuf).st_blocks : 0)
153 #ifndef ST_NBLOCKSIZE
154 # define ST_NBLOCKSIZE 512
157 #ifndef _POSIX_VERSION
158 struct passwd
*getpwuid ();
159 struct group
*getgrgid ();
162 #ifdef major /* Might be defined in sys/types.h. */
166 #define major(dev) (((dev) >> 8) & 0xff)
167 #define minor(dev) ((dev) & 0xff)
175 char *get_link_name ();
178 void print_name_with_quoting ();
180 /* NAME is the name to print.
181 RELNAME is the path to access it from the current directory.
182 STATP is the results of stat or lstat on it.
183 Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
184 Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
186 STREAM is the stdio stream to print on. */
189 list_file (name
, relname
, statp
, current_time
, output_block_size
, stream
)
194 int output_block_size
;
198 struct tm
const *when_local
;
199 char const *user_name
;
200 char const *group_name
;
201 char hbuf
[LONGEST_HUMAN_READABLE
+ 1];
204 /* Cray DMF: look at the file's migrated, not real, status */
205 mode_string (statp
->st_dm_mode
, modebuf
);
207 mode_string (statp
->st_mode
, modebuf
);
211 fprintf (stream
, "%6s ",
212 human_readable ((uintmax_t) statp
->st_ino
, hbuf
,
216 fprintf (stream
, "%4s ",
217 human_readable ((uintmax_t) ST_NBLOCKS (*statp
), hbuf
,
219 ST_NBLOCKSIZE
, output_block_size
));
222 /* The space between the mode and the number of links is the POSIX
223 "optional alternate access method flag". */
224 fprintf (stream
, "%s %3lu ", modebuf
, (unsigned long) statp
->st_nlink
);
226 user_name
= getuser (statp
->st_uid
);
228 fprintf (stream
, "%-8s ", user_name
);
230 fprintf (stream
, "%-8lu ", (unsigned long) statp
->st_uid
);
232 group_name
= getgroup (statp
->st_gid
);
234 fprintf (stream
, "%-8s ", group_name
);
236 fprintf (stream
, "%-8lu ", (unsigned long) statp
->st_gid
);
238 if (S_ISCHR (statp
->st_mode
) || S_ISBLK (statp
->st_mode
))
240 fprintf (stream
, "%3lu, %3lu ",
241 (unsigned long) major (statp
->st_rdev
),
242 (unsigned long) minor (statp
->st_rdev
));
244 fprintf (stream
, " ");
247 fprintf (stream
, "%8s ",
248 human_readable ((uintmax_t) statp
->st_size
, hbuf
,
251 output_block_size
< 0 ? output_block_size
: 1));
253 if ((when_local
= localtime (&statp
->st_mtime
)))
255 char init_bigbuf
[256];
256 char *buf
= init_bigbuf
;
257 size_t bufsize
= sizeof init_bigbuf
;
259 /* Use strftime rather than ctime, because the former can produce
260 locale-dependent names for the month (%b).
262 Output the year if the file is fairly old or in the future.
263 POSIX says the cutoff is 6 months old;
264 approximate this by 6*30 days.
265 Allow a 1 hour slop factor for what is considered "the future",
266 to allow for NFS server/client clock disagreement. */
268 ((current_time
- 6 * 30 * 24 * 60 * 60 <= statp
->st_mtime
269 && statp
->st_mtime
<= current_time
+ 60 * 60)
273 while (!strftime (buf
, bufsize
, fmt
, when_local
))
274 buf
= (char *) alloca (bufsize
*= 2);
276 fprintf (stream
, "%s ", buf
);
280 /* The time cannot be represented as a local time;
281 print it as a huge integer number of seconds. */
284 if (statp
->st_mtime
< 0)
286 char const *num
= human_readable (- (uintmax_t) statp
->st_mtime
,
287 hbuf
, human_ceiling
, 1, 1);
288 int sign_width
= width
- strlen (num
);
289 fprintf (stream
, "%*s%s ",
290 sign_width
< 0 ? 0 : sign_width
, "-", num
);
293 fprintf (stream
, "%*s ", width
,
294 human_readable ((uintmax_t) statp
->st_mtime
, hbuf
,
299 print_name_with_quoting (name
, stream
);
302 if (S_ISLNK (statp
->st_mode
))
304 char *linkname
= get_link_name (name
, relname
);
308 fputs (" -> ", stream
);
309 print_name_with_quoting (linkname
, stream
);
318 print_name_with_quoting (p
, stream
)
322 register unsigned char c
;
324 while ((c
= *p
++) != '\0')
329 fprintf (stream
, "\\\\");
333 fprintf (stream
, "\\n");
337 fprintf (stream
, "\\b");
341 fprintf (stream
, "\\r");
345 fprintf (stream
, "\\t");
349 fprintf (stream
, "\\f");
353 fprintf (stream
, "\\ ");
357 fprintf (stream
, "\\\"");
361 if (c
> 040 && c
< 0177)
364 fprintf (stream
, "\\%03o", (unsigned int) c
);
371 get_link_name (name
, 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';