1 /* listfile.c -- display a long listing of a file
2 Copyright (C) 1991, 1993, 2000, 2004, 2005, 2007 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,
24 #include <sys/types.h>
34 #include <unistd.h> /* for readlink() */
42 #include "dircallback.h"
46 /* Since major is a function on SVR4, we can't use `ifndef major'. */
48 #include <sys/mkdev.h>
51 #ifdef MAJOR_IN_SYSMACROS
52 #include <sys/sysmacros.h>
66 # define _(Text) gettext (Text)
69 #define textdomain(Domain)
70 #define bindtextdomain(Package, Directory)
73 # define N_(String) gettext_noop (String)
75 /* See locate.c for explanation as to why not use (String) */
76 # define N_(String) String
81 #ifdef STAT_MACROS_BROKEN
88 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
91 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
93 #if defined S_IFLNK && !defined S_ISLNK
94 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
97 /* Get or fake the disk device blocksize.
98 Usually defined by sys/param.h (if at all). */
101 # define DEV_BSIZE BSIZE
103 # define DEV_BSIZE 4096
105 #endif /* !DEV_BSIZE */
107 /* Extract or fake data from a `struct stat'.
108 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
109 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
110 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
111 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
112 # define ST_BLKSIZE(statbuf) DEV_BSIZE
113 # if defined _POSIX_SOURCE || !defined BSIZE /* fileblocks.c uses BSIZE. */
114 # define ST_NBLOCKS(statbuf) \
115 (S_ISREG ((statbuf).st_mode) \
116 || S_ISDIR ((statbuf).st_mode) \
117 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
118 # else /* !_POSIX_SOURCE && BSIZE */
119 # define ST_NBLOCKS(statbuf) \
120 (S_ISREG ((statbuf).st_mode) \
121 || S_ISDIR ((statbuf).st_mode) \
122 ? st_blocks ((statbuf).st_size) : 0)
123 # endif /* !_POSIX_SOURCE && BSIZE */
124 #else /* HAVE_STRUCT_STAT_ST_BLOCKS */
125 /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
126 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
127 ? (statbuf).st_blksize : DEV_BSIZE)
128 # if defined hpux || defined __hpux__ || defined __hpux
129 /* HP-UX counts st_blocks in 1024-byte units.
130 This loses when mixing HP-UX and BSD filesystems with NFS. */
131 # define ST_NBLOCKSIZE 1024
133 # if defined _AIX && defined _I386
134 /* AIX PS/2 counts st_blocks in 4K units. */
135 # define ST_NBLOCKSIZE (4 * 1024)
136 # else /* not AIX PS/2 */
138 # define ST_NBLOCKS(statbuf) \
139 (S_ISREG ((statbuf).st_mode) \
140 || S_ISDIR ((statbuf).st_mode) \
141 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
143 # endif /* not AIX PS/2 */
145 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
148 # define ST_NBLOCKS(statbuf) \
149 (S_ISREG ((statbuf).st_mode) \
150 || S_ISDIR ((statbuf).st_mode) \
151 ? (statbuf).st_blocks : 0)
154 #ifndef ST_NBLOCKSIZE
155 # define ST_NBLOCKSIZE 512
158 #ifdef major /* Might be defined in sys/types.h. */
162 #define major(dev) (((dev) >> 8) & 0xff)
163 #define minor(dev) ((dev) & 0xff)
168 static void print_name (register const char *p
, FILE *stream
, int literal_control_chars
);
170 extern char * getgroup (gid_t gid
);
171 extern char * getuser (uid_t uid
);
176 file_blocksize(const struct stat
*p
)
178 return ST_NBLOCKSIZE
;
183 /* NAME is the name to print.
184 RELNAME is the path to access it from the current directory.
185 STATP is the results of stat or lstat on it.
186 Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
187 Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
189 STREAM is the stdio stream to print on. */
192 list_file (const char *name
,
195 const struct stat
*statp
,
197 int output_block_size
,
198 int literal_control_chars
,
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 strmode (statp
->st_dm_mode
, modebuf
);
211 strmode (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
= 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 (name
, stream
, literal_control_chars
);
306 if (S_ISLNK (statp
->st_mode
))
308 char *linkname
= get_link_name_at (name
, dirfd
, relname
);
312 fputs (" -> ", stream
);
313 print_name (linkname
, stream
, literal_control_chars
);
323 print_name_without_quoting (const char *p
, FILE *stream
)
325 fprintf(stream
, "%s", p
);
330 print_name_with_quoting (register const char *p
, FILE *stream
)
332 register unsigned char c
;
334 while ((c
= *p
++) != '\0')
339 fprintf (stream
, "\\\\");
343 fprintf (stream
, "\\n");
347 fprintf (stream
, "\\b");
351 fprintf (stream
, "\\r");
355 fprintf (stream
, "\\t");
359 fprintf (stream
, "\\f");
363 fprintf (stream
, "\\ ");
367 fprintf (stream
, "\\\"");
371 if (c
> 040 && c
< 0177)
374 fprintf (stream
, "\\%03o", (unsigned int) c
);
379 static void print_name (register const char *p
, FILE *stream
, int literal_control_chars
)
381 if (literal_control_chars
)
382 print_name_without_quoting(p
, stream
);
384 print_name_with_quoting(p
, stream
);
389 get_link_name (const char *name
, char *relname
)
391 register char *linkname
;
392 register int linklen
;
394 /* st_size is wrong for symlinks on AIX, and on
395 mount points with some automounters.
396 So allocate a pessimistic PATH_MAX + 1 bytes. */
397 #define LINK_BUF PATH_MAX
398 linkname
= xmalloc (LINK_BUF
+ 1);
399 linklen
= readlink (relname
, linkname
, LINK_BUF
);
402 error (0, errno
, "%s", name
);
406 linkname
[linklen
] = '\0';
410 struct link_name_args
418 get_link_name_cb(void *context
)
420 struct link_name_args
*args
= context
;
421 args
->result
= get_link_name(args
->name
, args
->relname
);
426 get_link_name_at (const char *name
, int dirfd
, char *relname
)
428 struct link_name_args args
;
431 args
.relname
= relname
;
432 if (0 == run_in_dir(dirfd
, get_link_name_cb
, &args
))