1 /* listfile.c -- display a long listing of a file
2 Copyright (C) 1991, 1993 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 #include <sys/types.h>
31 #if HAVE_STRING_H || STDC_HEADERS
44 /* Since major is a function on SVR4, we can't use `ifndef major'. */
46 #include <sys/mkdev.h>
49 #ifdef MAJOR_IN_SYSMACROS
50 #include <sys/sysmacros.h>
54 #ifdef STAT_MACROS_BROKEN
61 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
64 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
66 #if defined(S_IFLNK) && !defined(S_ISLNK)
67 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
74 /* Extract or fake data from a `struct stat'.
75 ST_NBLOCKS: Number of 512-byte blocks in the file
76 (including indirect blocks).
77 HP-UX, perhaps uniquely, counts st_blocks in 1024-byte units.
78 This workaround loses when mixing HP-UX and 4BSD filesystems, though. */
80 # define ST_NBLOCKS(statp) (((statp)->st_size + 512 - 1) / 512)
82 # ifndef HAVE_ST_BLOCKS
83 # define ST_NBLOCKS(statp) (st_blocks ((statp)->st_size))
85 # if defined(hpux) || defined(__hpux__)
86 # define ST_NBLOCKS(statp) ((statp)->st_blocks * 2)
88 # define ST_NBLOCKS(statp) ((statp)->st_blocks)
93 /* Convert NUMBER 512-byte blocks to kilobytes if KILOFLAG is nonzero,
94 otherwise return it unchanged. */
95 #define convert_blocks(Number, Kiloflag) \
96 ((Kiloflag) ? ((Number) + 1) / 2 : (Number))
98 #ifndef _POSIX_VERSION
99 struct passwd
*getpwuid ();
100 struct group
*getgrgid ();
103 #ifdef major /* Might be defined in sys/types.h. */
107 #define major(dev) (((dev) >> 8) & 0xff)
108 #define minor(dev) ((dev) & 0xff)
116 char *get_link_name ();
119 void print_name_with_quoting ();
121 /* NAME is the name to print.
122 RELNAME is the path to access it from the current directory.
123 STATP is the results of stat or lstat on it.
124 STREAM is the stdio stream to print on. */
127 list_file (name
, relname
, statp
, stream
)
133 static int kilobytes
= -1; /* -1 = uninitialized, 0 = 512, 1 = 1024. */
136 time_t current_time
= time ((time_t *) 0);
139 kilobytes
= getenv ("POSIXLY_CORRECT") == 0;
141 mode_string (statp
->st_mode
, modebuf
);
144 strcpy (timebuf
, ctime (&statp
->st_mtime
));
145 if (current_time
> statp
->st_mtime
+ 6L * 30L * 24L * 60L * 60L /* Old. */
146 || current_time
< statp
->st_mtime
- 60L * 60L) /* In the future. */
148 /* The file is fairly old or in the future.
149 POSIX says the cutoff is 6 months old;
150 approximate this by 6*30 days.
151 Allow a 1 hour slop factor for what is considered "the future",
152 to allow for NFS server/client clock disagreement.
153 Show the year instead of the time of day. */
154 strcpy (timebuf
+ 11, timebuf
+ 19);
158 fprintf (stream
, "%6lu ", statp
->st_ino
);
160 fprintf (stream
, "%4lu ",
161 (long) convert_blocks (ST_NBLOCKS (statp
), kilobytes
));
163 /* The space between the mode and the number of links is the POSIX
164 "optional alternate access method flag". */
165 fprintf (stream
, "%s %3u ", modebuf
, statp
->st_nlink
);
167 fprintf (stream
, "%-8.8s ", getuser (statp
->st_uid
));
169 fprintf (stream
, "%-8.8s ", getgroup (statp
->st_gid
));
171 if (S_ISCHR (statp
->st_mode
) || S_ISBLK (statp
->st_mode
))
173 fprintf (stream
, "%3u, %3u ", major (statp
->st_rdev
), minor (statp
->st_rdev
));
175 fprintf (stream
, " ");
178 fprintf (stream
, "%8lu ", statp
->st_size
);
180 fprintf (stream
, "%s ", timebuf
+ 4);
182 print_name_with_quoting (name
, stream
);
185 if (S_ISLNK (statp
->st_mode
))
187 char *linkname
= get_link_name (name
, relname
);
191 fputs (" -> ", stream
);
192 print_name_with_quoting (linkname
, stream
);
201 print_name_with_quoting (p
, stream
)
205 register unsigned char c
;
207 while ((c
= *p
++) != '\0')
212 fprintf (stream
, "\\\\");
216 fprintf (stream
, "\\n");
220 fprintf (stream
, "\\b");
224 fprintf (stream
, "\\r");
228 fprintf (stream
, "\\t");
232 fprintf (stream
, "\\f");
236 fprintf (stream
, "\\ ");
240 fprintf (stream
, "\\\"");
244 if (c
> 040 && c
< 0177)
247 fprintf (stream
, "\\%03o", (unsigned int) c
);
254 get_link_name (name
, relname
)
258 register char *linkname
;
259 register int linklen
;
261 /* st_size is wrong for symlinks on AIX, and on
262 mount points with some automounters.
263 So allocate a pessimistic PATH_MAX + 1 bytes. */
264 #define LINK_BUF PATH_MAX
265 linkname
= (char *) xmalloc (LINK_BUF
+ 1);
266 linklen
= readlink (relname
, linkname
, LINK_BUF
);
269 error (0, errno
, "%s", name
);
273 linkname
[linklen
] = '\0';