1 /* listfile.c -- display a long listing of a file
2 Copyright (C) 1991, 1993, 2000, 2004, 2005, 2007,
3 2008, 2010 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/types.h>
33 #include <unistd.h> /* for readlink() */
42 #include "areadlink.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>
58 /* Get or fake the disk device blocksize.
59 Usually defined by sys/param.h (if at all). */
62 # define DEV_BSIZE BSIZE
64 # define DEV_BSIZE 4096
66 #endif /* !DEV_BSIZE */
68 /* Extract or fake data from a `struct stat'.
69 ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
70 ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
71 ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
72 #ifndef HAVE_STRUCT_STAT_ST_BLOCKS
73 # define ST_BLKSIZE(statbuf) DEV_BSIZE
74 # if defined _POSIX_SOURCE || !defined BSIZE /* fileblocks.c uses BSIZE. */
75 # define ST_NBLOCKS(statbuf) \
76 (S_ISREG ((statbuf).st_mode) \
77 || S_ISDIR ((statbuf).st_mode) \
78 ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
79 # else /* !_POSIX_SOURCE && BSIZE */
80 # define ST_NBLOCKS(statbuf) \
81 (S_ISREG ((statbuf).st_mode) \
82 || S_ISDIR ((statbuf).st_mode) \
83 ? st_blocks ((statbuf).st_size) : 0)
84 # endif /* !_POSIX_SOURCE && BSIZE */
85 #else /* HAVE_STRUCT_STAT_ST_BLOCKS */
86 /* Some systems, like Sequents, return st_blksize of 0 on pipes. */
87 # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
88 ? (statbuf).st_blksize : DEV_BSIZE)
89 # if defined hpux || defined __hpux__ || defined __hpux
90 /* HP-UX counts st_blocks in 1024-byte units.
91 This loses when mixing HP-UX and BSD filesystems with NFS. */
92 # define ST_NBLOCKSIZE 1024
94 # if defined _AIX && defined _I386
95 /* AIX PS/2 counts st_blocks in 4K units. */
96 # define ST_NBLOCKSIZE (4 * 1024)
97 # else /* not AIX PS/2 */
99 # define ST_NBLOCKS(statbuf) \
100 (S_ISREG ((statbuf).st_mode) \
101 || S_ISDIR ((statbuf).st_mode) \
102 ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
104 # endif /* not AIX PS/2 */
106 #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
109 # define ST_NBLOCKS(statbuf) \
110 (S_ISREG ((statbuf).st_mode) \
111 || S_ISDIR ((statbuf).st_mode) \
112 ? (statbuf).st_blocks : 0)
115 #ifndef ST_NBLOCKSIZE
116 # define ST_NBLOCKSIZE 512
119 #ifdef major /* Might be defined in sys/types.h. */
123 #define major(dev) (((dev) >> 8) & 0xff)
124 #define minor(dev) ((dev) & 0xff)
129 static void print_name (register const char *p, FILE *stream, int literal_control_chars);
133 file_blocksize (const struct stat *p)
135 return ST_NBLOCKSIZE;
140 /* NAME is the name to print.
141 RELNAME is the path to access it from the current directory.
142 STATP is the results of stat or lstat on it.
143 Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
144 Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
146 STREAM is the stdio stream to print on. */
149 list_file (const char *name,
152 const struct stat *statp,
154 int output_block_size,
155 int literal_control_chars,
159 struct tm const *when_local;
160 char const *user_name;
161 char const *group_name;
162 char hbuf[LONGEST_HUMAN_READABLE + 1];
165 /* Cray DMF: look at the file's migrated, not real, status */
166 strmode (statp->st_dm_mode, modebuf);
168 strmode (statp->st_mode, modebuf);
171 fprintf (stream, "%6s ",
172 human_readable ((uintmax_t) statp->st_ino, hbuf,
176 fprintf (stream, "%4s ",
177 human_readable ((uintmax_t) ST_NBLOCKS (*statp), hbuf,
179 ST_NBLOCKSIZE, output_block_size));
182 /* modebuf includes the space between the mode and the number of links,
183 as the POSIX "optional alternate access method flag". */
184 fprintf (stream, "%s%3lu ", modebuf, (unsigned long) statp->st_nlink);
186 user_name = getuser (statp->st_uid);
188 fprintf (stream, "%-8s ", user_name);
190 fprintf (stream, "%-8lu ", (unsigned long) statp->st_uid);
192 group_name = getgroup (statp->st_gid);
194 fprintf (stream, "%-8s ", group_name);
196 fprintf (stream, "%-8lu ", (unsigned long) statp->st_gid);
198 if (S_ISCHR (statp->st_mode) || S_ISBLK (statp->st_mode))
200 fprintf (stream, "%3lu, %3lu ",
201 (unsigned long) major (statp->st_rdev),
202 (unsigned long) minor (statp->st_rdev));
204 fprintf (stream, " ");
207 fprintf (stream, "%8s ",
208 human_readable ((uintmax_t) statp->st_size, hbuf,
211 output_block_size < 0 ? output_block_size : 1));
213 if ((when_local = localtime (&statp->st_mtime)))
215 char init_bigbuf[256];
216 char *buf = init_bigbuf;
217 size_t bufsize = sizeof init_bigbuf;
219 /* Use strftime rather than ctime, because the former can produce
220 locale-dependent names for the month (%b).
222 Output the year if the file is fairly old or in the future.
223 POSIX says the cutoff is 6 months old;
224 approximate this by 6*30 days.
225 Allow a 1 hour slop factor for what is considered "the future",
226 to allow for NFS server/client clock disagreement. */
228 ((current_time - 6 * 30 * 24 * 60 * 60 <= statp->st_mtime
229 && statp->st_mtime <= current_time + 60 * 60)
233 while (!strftime (buf, bufsize, fmt, when_local))
234 buf = alloca (bufsize *= 2);
236 fprintf (stream, "%s ", buf);
240 /* The time cannot be represented as a local time;
241 print it as a huge integer number of seconds. */
244 if (statp->st_mtime < 0)
246 char const *num = human_readable (- (uintmax_t) statp->st_mtime,
247 hbuf, human_ceiling, 1, 1);
248 int sign_width = width - strlen (num);
249 fprintf (stream, "%*s%s ",
250 sign_width < 0 ? 0 : sign_width, "-", num);
253 fprintf (stream, "%*s ", width,
254 human_readable ((uintmax_t) statp->st_mtime, hbuf,
259 print_name (name, stream, literal_control_chars);
261 if (S_ISLNK (statp->st_mode))
263 char *linkname = areadlinkat (dir_fd, relname);
266 fputs (" -> ", stream);
267 print_name (linkname, stream, literal_control_chars);
271 /* POSIX requires in the case of find that if we issue a
272 * diagnostic we should have a nonzero status. However,
273 * this function doesn't have a way of telling the caller to
274 * do that. However, since this function is only used when
275 * processing "-ls", we're already using an extension.
277 error (0, errno, "%s", name);
286 print_name_without_quoting (const char *p, FILE *stream)
288 fprintf (stream, "%s", p);
293 print_name_with_quoting (register const char *p, FILE *stream)
295 register unsigned char c;
297 while ((c = *p++) != '\0')
302 fprintf (stream, "\\\\");
306 fprintf (stream, "\\n");
310 fprintf (stream, "\\b");
314 fprintf (stream, "\\r");
318 fprintf (stream, "\\t");
322 fprintf (stream, "\\f");
326 fprintf (stream, "\\ ");
330 fprintf (stream, "\\\"");
334 if (c > 040 && c < 0177)
337 fprintf (stream, "\\%03o", (unsigned int) c);
342 static void print_name (register const char *p, FILE *stream, int literal_control_chars)
344 if (literal_control_chars)
345 print_name_without_quoting (p, stream);
347 print_name_with_quoting (p, stream);