1 /* listfile.c -- display a long listing of a file
2 Copyright (C) 1991, 1993, 2000, 2004, 2005, 2007, 2008, 2010, 2011
3 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/>.
18 /* config.h must be included first. */
33 #include <sys/types.h>
35 #include <unistd.h> /* for readlink() */
38 #include "areadlink.h"
44 #include "stat-size.h"
50 /* Since major is a function on SVR4, we can't use `ifndef major'. */
52 #include <sys/mkdev.h>
55 #ifdef MAJOR_IN_SYSMACROS
56 #include <sys/sysmacros.h>
60 #ifdef major /* Might be defined in sys/types.h. */
64 #define major(dev) (((dev) >> 8) & 0xff)
65 #define minor(dev) ((dev) & 0xff)
71 # define _(Text) gettext (Text)
76 # define N_(String) gettext_noop (String)
78 /* See locate.c for explanation as to why not use (String) */
79 # define N_(String) String
82 static bool print_name (register const char *p, FILE *stream, int literal_control_chars);
85 /* NAME is the name to print.
86 RELNAME is the path to access it from the current directory.
87 STATP is the results of stat or lstat on it.
88 Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
89 Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
91 STREAM is the stdio stream to print on. */
94 list_file (const char *name,
97 const struct stat *statp,
99 int output_block_size,
100 int literal_control_chars,
104 struct tm const *when_local;
105 char const *user_name;
106 char const *group_name;
107 char hbuf[LONGEST_HUMAN_READABLE + 1];
108 bool output_good = true;
112 /* Cray DMF: look at the file's migrated, not real, status */
113 strmode (statp->st_dm_mode, modebuf);
115 strmode (statp->st_mode, modebuf);
118 if (fprintf (stream, "%6s ",
119 human_readable ((uintmax_t) statp->st_ino, hbuf,
129 if (fprintf (stream, "%4s ",
130 human_readable ((uintmax_t) ST_NBLOCKS (*statp), hbuf,
132 ST_NBLOCKSIZE, output_block_size)) < 0)
141 /* modebuf includes the space between the mode and the number of links,
142 as the POSIX "optional alternate access method flag". */
143 if (fprintf (stream, "%s%3lu ", modebuf, (unsigned long) statp->st_nlink) < 0)
152 user_name = getuser (statp->st_uid);
155 output_good = (fprintf (stream, "%-8s ", user_name) >= 0);
161 output_good = (fprintf (stream, "%-8lu ", (unsigned long) statp->st_uid) >= 0);
169 group_name = getgroup (statp->st_gid);
172 output_good = (fprintf (stream, "%-8s ", group_name) >= 0);
178 output_good = (fprintf (stream, "%-8lu ", (unsigned long) statp->st_gid) >= 0);
186 if (S_ISCHR (statp->st_mode) || S_ISBLK (statp->st_mode))
188 #ifdef HAVE_STRUCT_STAT_ST_RDEV
189 if (fprintf (stream, "%3lu, %3lu ",
190 (unsigned long) major (statp->st_rdev),
191 (unsigned long) minor (statp->st_rdev)) < 0)
197 if (fprintf (stream, " ") < 0)
206 if (fprintf (stream, "%8s ",
207 human_readable ((uintmax_t) statp->st_size, hbuf,
210 output_block_size < 0 ? output_block_size : 1)) < 0)
220 if ((when_local = localtime (&statp->st_mtime)))
222 char init_bigbuf[256];
223 char *buf = init_bigbuf;
224 size_t bufsize = sizeof init_bigbuf;
226 /* Use strftime rather than ctime, because the former can produce
227 locale-dependent names for the month (%b).
229 Output the year if the file is fairly old or in the future.
230 POSIX says the cutoff is 6 months old;
231 approximate this by 6*30 days.
232 Allow a 1 hour slop factor for what is considered "the future",
233 to allow for NFS server/client clock disagreement. */
235 ((current_time - 6 * 30 * 24 * 60 * 60 <= statp->st_mtime
236 && statp->st_mtime <= current_time + 60 * 60)
240 while (!strftime (buf, bufsize, fmt, when_local))
241 buf = alloca (bufsize *= 2);
243 if (fprintf (stream, "%s ", buf) < 0)
251 /* The time cannot be represented as a local time;
252 print it as a huge integer number of seconds. */
255 if (statp->st_mtime < 0)
257 char const *num = human_readable (- (uintmax_t) statp->st_mtime,
258 hbuf, human_ceiling, 1, 1);
259 int sign_width = width - strlen (num);
260 if (fprintf (stream, "%*s%s ",
261 sign_width < 0 ? 0 : sign_width, "-", num) < 0)
269 if (fprintf (stream, "%*s ", width,
270 human_readable ((uintmax_t) statp->st_mtime, hbuf,
283 output_good = print_name (name, stream, literal_control_chars);
292 if (S_ISLNK (statp->st_mode))
294 char *linkname = areadlinkat (dir_fd, relname);
297 if (fputs (" -> ", stream) < 0)
304 output_good = print_name (linkname, stream, literal_control_chars);
313 /* POSIX requires in the case of find that if we issue a
314 * diagnostic we should have a nonzero status. However,
315 * this function doesn't have a way of telling the caller to
316 * do that. However, since this function is only used when
317 * processing "-ls", we're already using an extension.
319 error (0, errno, "%s", name);
325 if (EOF == putc ('\n', stream))
337 error (EXIT_FAILURE, errno, _("Failed to write output (at stage %d)"), failed_at);
343 print_name_without_quoting (const char *p, FILE *stream)
345 return (fprintf (stream, "%s", p) >= 0);
350 print_name_with_quoting (register const char *p, FILE *stream)
352 register unsigned char c;
354 while ((c = *p++) != '\0')
356 int fprintf_result = -1;
360 fprintf_result = fprintf (stream, "\\\\");
364 fprintf_result = fprintf (stream, "\\n");
368 fprintf_result = fprintf (stream, "\\b");
372 fprintf_result = fprintf (stream, "\\r");
376 fprintf_result = fprintf (stream, "\\t");
380 fprintf_result = fprintf (stream, "\\f");
384 fprintf_result = fprintf (stream, "\\ ");
388 fprintf_result = fprintf (stream, "\\\"");
392 if (c > 040 && c < 0177)
394 if (EOF == putc (c, stream))
396 fprintf_result = 1; /* otherwise it's used uninitialized. */
400 fprintf_result = fprintf (stream, "\\%03o", (unsigned int) c);
403 if (fprintf_result < 0)
409 static bool print_name (register const char *p, FILE *stream, int literal_control_chars)
411 if (literal_control_chars)
412 return print_name_without_quoting (p, stream);
414 return print_name_with_quoting (p, stream);