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)
42 /* Since major is a function on SVR4, we can't use `ifndef major'. */
44 #include <sys/mkdev.h>
47 #ifdef MAJOR_IN_SYSMACROS
48 #include <sys/sysmacros.h>
52 #ifdef STAT_MACROS_BROKEN
59 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
62 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
64 #if defined(S_IFLNK) && !defined(S_ISLNK)
65 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
69 /* Extract or fake data from a `struct stat'.
70 ST_NBLOCKS: Number of 512-byte blocks in the file
71 (including indirect blocks).
72 HP-UX, perhaps uniquely, counts st_blocks in 1024-byte units.
73 This workaround loses when mixing HP-UX and 4BSD filesystems, though. */
75 # define ST_NBLOCKS(statp) (((statp)->st_size + 512 - 1) / 512)
77 # ifndef HAVE_ST_BLOCKS
78 # define ST_NBLOCKS(statp) (st_blocks ((statp)->st_size))
80 # if defined(hpux) || defined(__hpux__)
81 # define ST_NBLOCKS(statp) ((statp)->st_blocks * 2)
83 # define ST_NBLOCKS(statp) ((statp)->st_blocks)
88 /* Convert B 512-byte blocks to kilobytes if K is nonzero,
89 otherwise return it unchanged. */
90 #define convert_blocks(b, k) ((k) ? ((b) + 1) / 2 : (b))
92 #ifndef _POSIX_VERSION
93 struct passwd
*getpwuid ();
94 struct group
*getgrgid ();
97 #ifdef major /* Might be defined in sys/types.h. */
101 #define major(dev) (((dev) >> 8) & 0xff)
102 #define minor(dev) ((dev) & 0xff)
110 char *get_link_name ();
113 void print_name_with_quoting ();
115 /* NAME is the name to print.
116 RELNAME is the path to access it from the current directory.
117 STATP is the results of stat or lstat on it.
118 STREAM is the stdio stream to print on. */
121 list_file (name
, relname
, statp
, stream
)
127 static int kilobytes
= -1; /* -1 = uninitialized, 0 = 512, 1 = 1024. */
130 time_t current_time
= time ((time_t *) 0);
133 kilobytes
= getenv ("POSIXLY_CORRECT") == 0;
135 mode_string (statp
->st_mode
, modebuf
);
138 strcpy (timebuf
, ctime (&statp
->st_mtime
));
139 if (current_time
> statp
->st_mtime
+ 6L * 30L * 24L * 60L * 60L /* Old. */
140 || current_time
< statp
->st_mtime
- 60L * 60L) /* In the future. */
142 /* The file is fairly old or in the future.
143 POSIX says the cutoff is 6 months old;
144 approximate this by 6*30 days.
145 Allow a 1 hour slop factor for what is considered "the future",
146 to allow for NFS server/client clock disagreement.
147 Show the year instead of the time of day. */
148 strcpy (timebuf
+ 11, timebuf
+ 19);
152 fprintf (stream
, "%6lu ", statp
->st_ino
);
154 fprintf (stream
, "%4lu ", convert_blocks (ST_NBLOCKS (statp
), kilobytes
));
156 /* The space between the mode and the number of links is the POSIX
157 "optional alternate access method flag". */
158 fprintf (stream
, "%s %3u ", modebuf
, statp
->st_nlink
);
160 fprintf (stream
, "%-8.8s ", getuser (statp
->st_uid
));
162 fprintf (stream
, "%-8.8s ", getgroup (statp
->st_gid
));
164 if (S_ISCHR (statp
->st_mode
) || S_ISBLK (statp
->st_mode
))
166 fprintf (stream
, "%3u, %3u ", major (statp
->st_rdev
), minor (statp
->st_rdev
));
168 fprintf (stream
, " ");
171 fprintf (stream
, "%8lu ", statp
->st_size
);
173 fprintf (stream
, "%s ", timebuf
+ 4);
175 print_name_with_quoting (name
, stream
);
178 if (S_ISLNK (statp
->st_mode
))
180 char *linkname
= get_link_name (name
, relname
);
184 fputs (" -> ", stream
);
185 print_name_with_quoting (linkname
, stream
);
194 print_name_with_quoting (p
, stream
)
198 register unsigned char c
;
200 while ((c
= *p
++) != '\0')
205 fprintf (stream
, "\\\\");
209 fprintf (stream
, "\\n");
213 fprintf (stream
, "\\b");
217 fprintf (stream
, "\\r");
221 fprintf (stream
, "\\t");
225 fprintf (stream
, "\\f");
229 fprintf (stream
, "\\ ");
233 fprintf (stream
, "\\\"");
237 if (c
> 040 && c
< 0177)
240 fprintf (stream
, "\\%03o", (unsigned int) c
);
247 get_link_name (name
, relname
)
251 register char *linkname
;
252 register int linklen
;
254 /* st_size is wrong for symlinks on AIX, and on
255 mount points with some automounters.
256 So allocate a pessimistic PATH_MAX + 1 bytes. */
257 #define LINK_BUF PATH_MAX
258 linkname
= (char *) xmalloc (LINK_BUF
+ 1);
259 linklen
= readlink (relname
, linkname
, LINK_BUF
);
262 error (0, errno
, "%s", name
);
266 linkname
[linklen
] = '\0';