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 defined(HAVE_STRING_H) || defined(STDC_HEADERS)
43 /* Since major is a function on SVR4, we can't use `ifndef major'. */
45 #include <sys/mkdev.h>
48 #ifdef MAJOR_IN_SYSMACROS
49 #include <sys/sysmacros.h>
53 #ifdef STAT_MACROS_BROKEN
60 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
63 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
65 #if defined(S_IFLNK) && !defined(S_ISLNK)
66 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
73 /* Extract or fake data from a `struct stat'.
74 ST_NBLOCKS: Number of 512-byte blocks in the file
75 (including indirect blocks).
76 HP-UX, perhaps uniquely, counts st_blocks in 1024-byte units.
77 This workaround loses when mixing HP-UX and 4BSD filesystems, though. */
79 # define ST_NBLOCKS(statp) (((statp)->st_size + 512 - 1) / 512)
81 # ifndef HAVE_ST_BLOCKS
82 # define ST_NBLOCKS(statp) (st_blocks ((statp)->st_size))
84 # if defined(hpux) || defined(__hpux__)
85 # define ST_NBLOCKS(statp) ((statp)->st_blocks * 2)
87 # define ST_NBLOCKS(statp) ((statp)->st_blocks)
92 /* Convert B 512-byte blocks to kilobytes if K is nonzero,
93 otherwise return it unchanged. */
94 #define convert_blocks(b, k) ((k) ? ((b) + 1) / 2 : (b))
96 #ifndef _POSIX_VERSION
97 struct passwd
*getpwuid ();
98 struct group
*getgrgid ();
101 #ifdef major /* Might be defined in sys/types.h. */
105 #define major(dev) (((dev) >> 8) & 0xff)
106 #define minor(dev) ((dev) & 0xff)
114 char *get_link_name ();
117 void print_name_with_quoting ();
119 /* NAME is the name to print.
120 RELNAME is the path to access it from the current directory.
121 STATP is the results of stat or lstat on it.
122 STREAM is the stdio stream to print on. */
125 list_file (name
, relname
, statp
, stream
)
131 static int kilobytes
= -1; /* -1 = uninitialized, 0 = 512, 1 = 1024. */
134 time_t current_time
= time ((time_t *) 0);
137 kilobytes
= getenv ("POSIXLY_CORRECT") == 0;
139 mode_string (statp
->st_mode
, modebuf
);
142 strcpy (timebuf
, ctime (&statp
->st_mtime
));
143 if (current_time
> statp
->st_mtime
+ 6L * 30L * 24L * 60L * 60L /* Old. */
144 || current_time
< statp
->st_mtime
- 60L * 60L) /* In the future. */
146 /* The file is fairly old or in the future.
147 POSIX says the cutoff is 6 months old;
148 approximate this by 6*30 days.
149 Allow a 1 hour slop factor for what is considered "the future",
150 to allow for NFS server/client clock disagreement.
151 Show the year instead of the time of day. */
152 strcpy (timebuf
+ 11, timebuf
+ 19);
156 fprintf (stream
, "%6lu ", statp
->st_ino
);
158 fprintf (stream
, "%4u ", convert_blocks (ST_NBLOCKS (statp
), kilobytes
));
160 /* The space between the mode and the number of links is the POSIX
161 "optional alternate access method flag". */
162 fprintf (stream
, "%s %3u ", modebuf
, statp
->st_nlink
);
164 fprintf (stream
, "%-8.8s ", getuser (statp
->st_uid
));
166 fprintf (stream
, "%-8.8s ", getgroup (statp
->st_gid
));
168 if (S_ISCHR (statp
->st_mode
) || S_ISBLK (statp
->st_mode
))
170 fprintf (stream
, "%3u, %3u ", major (statp
->st_rdev
), minor (statp
->st_rdev
));
172 fprintf (stream
, " ");
175 fprintf (stream
, "%8lu ", statp
->st_size
);
177 fprintf (stream
, "%s ", timebuf
+ 4);
179 print_name_with_quoting (name
, stream
);
182 if (S_ISLNK (statp
->st_mode
))
184 char *linkname
= get_link_name (name
, relname
);
188 fputs (" -> ", stream
);
189 print_name_with_quoting (linkname
, stream
);
198 print_name_with_quoting (p
, stream
)
202 register unsigned char c
;
204 while ((c
= *p
++) != '\0')
209 fprintf (stream
, "\\\\");
213 fprintf (stream
, "\\n");
217 fprintf (stream
, "\\b");
221 fprintf (stream
, "\\r");
225 fprintf (stream
, "\\t");
229 fprintf (stream
, "\\f");
233 fprintf (stream
, "\\ ");
237 fprintf (stream
, "\\\"");
241 if (c
> 040 && c
< 0177)
244 fprintf (stream
, "\\%03o", (unsigned int) c
);
251 get_link_name (name
, relname
)
255 register char *linkname
;
256 register int linklen
;
258 /* st_size is wrong for symlinks on AIX, and on
259 mount points with some automounters.
260 So allocate a pessimistic PATH_MAX + 1 bytes. */
261 #define LINK_BUF PATH_MAX
262 linkname
= (char *) xmalloc (LINK_BUF
+ 1);
263 linklen
= readlink (relname
, linkname
, LINK_BUF
);
266 error (0, errno
, "%s", name
);
270 linkname
[linklen
] = '\0';