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., 9 Temple Place - Suite 330, Boston, MA 02111-1307,
21 # include <gnulib/config.h>
23 # undef PACKAGE_VERSION
24 # undef PACKAGE_TARNAME
25 # undef PACKAGE_STRING
50 #include <sys/types.h>
60 #if HAVE_STRING_H || STDC_HEADERS
73 /* Since major is a function on SVR4, we can't use `ifndef major'. */
75 #include <sys/mkdev.h>
78 #ifdef MAJOR_IN_SYSMACROS
79 #include <sys/sysmacros.h>
83 #ifdef STAT_MACROS_BROKEN
90 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
93 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
95 #if defined(S_IFLNK) && !defined(S_ISLNK)
96 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
103 /* Get or fake the disk device blocksize.
104 Usually defined by sys/param.h (if at all). */
107 # define DEV_BSIZE BSIZE
109 # define DEV_BSIZE 4096
111 #endif /* !DEV_BSIZE */
113 /* Extract or fake data from a `struct stat'.
114 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
115 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
116 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
117 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
118 # define ST_BLKSIZE(statbuf) DEV_BSIZE
119 # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */
120 # define ST_NBLOCKS(statbuf) \
121 (S_ISREG ((statbuf).st_mode) \
122 || S_ISDIR ((statbuf).st_mode) \
123 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
124 # else /* !_POSIX_SOURCE && BSIZE */
125 # define ST_NBLOCKS(statbuf) \
126 (S_ISREG ((statbuf).st_mode) \
127 || S_ISDIR ((statbuf).st_mode) \
128 ? st_blocks ((statbuf).st_size) : 0)
129 # endif /* !_POSIX_SOURCE && BSIZE */
130 #else /* HAVE_STRUCT_STAT_ST_BLOCKS */
131 /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
132 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
133 ? (statbuf).st_blksize : DEV_BSIZE)
134 # if defined(hpux) || defined(__hpux__) || defined(__hpux)
135 /* HP-UX counts st_blocks in 1024-byte units.
136 This loses when mixing HP-UX and BSD filesystems with NFS. */
137 # define ST_NBLOCKSIZE 1024
139 # if defined(_AIX) && defined(_I386)
140 /* AIX PS/2 counts st_blocks in 4K units. */
141 # define ST_NBLOCKSIZE (4 * 1024)
142 # else /* not AIX PS/2 */
144 # define ST_NBLOCKS(statbuf) \
145 (S_ISREG ((statbuf).st_mode) \
146 || S_ISDIR ((statbuf).st_mode) \
147 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
149 # endif /* not AIX PS/2 */
151 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
154 # define ST_NBLOCKS(statbuf) \
155 (S_ISREG ((statbuf).st_mode) \
156 || S_ISDIR ((statbuf).st_mode) \
157 ? (statbuf).st_blocks : 0)
160 #ifndef ST_NBLOCKSIZE
161 # define ST_NBLOCKSIZE 512
164 #ifndef _POSIX_VERSION
165 struct passwd
*getpwuid ();
166 struct group
*getgrgid ();
169 #ifdef major /* Might be defined in sys/types.h. */
173 #define major(dev) (((dev) >> 8) & 0xff)
174 #define minor(dev) ((dev) & 0xff)
182 char *get_link_name ();
185 void print_name_with_quoting ();
187 /* NAME is the name to print.
188 RELNAME is the path to access it from the current directory.
189 STATP is the results of stat or lstat on it.
190 Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
191 Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
193 STREAM is the stdio stream to print on. */
196 list_file (name
, relname
, statp
, current_time
, output_block_size
, stream
)
201 int output_block_size
;
205 struct tm
const *when_local
;
206 char const *user_name
;
207 char const *group_name
;
208 char hbuf
[LONGEST_HUMAN_READABLE
+ 1];
211 /* Cray DMF: look at the file's migrated, not real, status */
212 mode_string (statp
->st_dm_mode
, modebuf
);
214 mode_string (statp
->st_mode
, modebuf
);
218 fprintf (stream
, "%6s ",
219 human_readable ((uintmax_t) statp
->st_ino
, hbuf
, human_ceiling
,
222 fprintf (stream
, "%4s ",
223 human_readable ((uintmax_t) ST_NBLOCKS (*statp
), hbuf
,
225 ST_NBLOCKSIZE
, output_block_size
));
227 /* The space between the mode and the number of links is the POSIX
228 "optional alternate access method flag". */
229 fprintf (stream
, "%s %3lu ", modebuf
, (unsigned long) statp
->st_nlink
);
231 user_name
= getuser (statp
->st_uid
);
233 fprintf (stream
, "%-8.8s ", user_name
);
235 fprintf (stream
, "%-8lu ", (unsigned long) statp
->st_uid
);
237 group_name
= getgroup (statp
->st_gid
);
239 fprintf (stream
, "%-8.8s ", group_name
);
241 fprintf (stream
, "%-8lu ", (unsigned long) statp
->st_gid
);
243 if (S_ISCHR (statp
->st_mode
) || S_ISBLK (statp
->st_mode
))
245 fprintf (stream
, "%3lu, %3lu ",
246 (unsigned long) major (statp
->st_rdev
),
247 (unsigned long) minor (statp
->st_rdev
));
249 fprintf (stream
, " ");
252 fprintf (stream
, "%8s ",
253 human_readable ((uintmax_t) statp
->st_size
, hbuf
, human_ceiling
,
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 (p
, stream
)
326 register unsigned char c
;
328 while ((c
= *p
++) != '\0')
333 fprintf (stream
, "\\\\");
337 fprintf (stream
, "\\n");
341 fprintf (stream
, "\\b");
345 fprintf (stream
, "\\r");
349 fprintf (stream
, "\\t");
353 fprintf (stream
, "\\f");
357 fprintf (stream
, "\\ ");
361 fprintf (stream
, "\\\"");
365 if (c
> 040 && c
< 0177)
368 fprintf (stream
, "\\%03o", (unsigned int) c
);
375 get_link_name (name
, relname
)
379 register char *linkname
;
380 register int linklen
;
382 /* st_size is wrong for symlinks on AIX, and on
383 mount points with some automounters.
384 So allocate a pessimistic PATH_MAX + 1 bytes. */
385 #define LINK_BUF PATH_MAX
386 linkname
= (char *) xmalloc (LINK_BUF
+ 1);
387 linklen
= readlink (relname
, linkname
, LINK_BUF
);
390 error (0, errno
, "%s", name
);
394 linkname
[linklen
] = '\0';