summaryrefslogtreecommitdiff
path: root/lib/listfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/listfile.c')
-rw-r--r--lib/listfile.c370
1 files changed, 105 insertions, 265 deletions
diff --git a/lib/listfile.c b/lib/listfile.c
index 9b4ed20d..7e32079f 100644
--- a/lib/listfile.c
+++ b/lib/listfile.c
@@ -1,46 +1,44 @@
/* listfile.c -- display a long listing of a file
- Copyright (C) 1991, 1993, 2000, 2004, 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1993 Free Software Foundation, Inc.
- This program is free software: you can redistribute it and/or modify
+ This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+#ifdef HAVE_CONFIG_H
#include <config.h>
-
-#include <alloca.h>
+#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
-#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h> /* for readlink() */
-#include <openat.h>
-
-#include "human.h"
-#include "xalloc.h"
#include "pathmax.h"
-#include "error.h"
-#include "filemode.h"
-#include "dircallback.h"
-#include "idcache.h"
-#include "listfile.h"
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+char *getenv ();
+extern int errno;
+#endif
/* Since major is a function on SVR4, we can't use `ifndef major'. */
#ifdef MAJOR_IN_MKDEV
@@ -52,31 +50,6 @@
#define HAVE_MAJOR
#endif
-
-
-
-
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif
-
-#if ENABLE_NLS
-# include <libintl.h>
-# define _(Text) gettext (Text)
-#else
-# define _(Text) Text
-#define textdomain(Domain)
-#define bindtextdomain(Package, Directory)
-#endif
-#ifdef gettext_noop
-# define N_(String) gettext_noop (String)
-#else
-/* See locate.c for explanation as to why not use (String) */
-# define N_(String) String
-#endif
-
-
-
#ifdef STAT_MACROS_BROKEN
#undef S_ISCHR
#undef S_ISBLK
@@ -89,69 +62,40 @@
#ifndef S_ISBLK
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#endif
-#if defined S_IFLNK && !defined S_ISLNK
+#if defined(S_IFLNK) && !defined(S_ISLNK)
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
-/* Get or fake the disk device blocksize.
- Usually defined by sys/param.h (if at all). */
-#ifndef DEV_BSIZE
-# ifdef BSIZE
-# define DEV_BSIZE BSIZE
-# else /* !BSIZE */
-# define DEV_BSIZE 4096
-# endif /* !BSIZE */
-#endif /* !DEV_BSIZE */
+#if defined(S_ISLNK)
+int readlink ();
+#endif
/* Extract or fake data from a `struct stat'.
- ST_BLKSIZE: Preferred I/O blocksize for the file, in bytes.
- ST_NBLOCKS: Number of blocks in the file, including indirect blocks.
- ST_NBLOCKSIZE: Size of blocks used when calculating ST_NBLOCKS. */
-#ifndef HAVE_STRUCT_STAT_ST_BLOCKS
-# define ST_BLKSIZE(statbuf) DEV_BSIZE
-# if defined _POSIX_SOURCE || !defined BSIZE /* fileblocks.c uses BSIZE. */
-# define ST_NBLOCKS(statbuf) \
- (S_ISREG ((statbuf).st_mode) \
- || S_ISDIR ((statbuf).st_mode) \
- ? (statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0) : 0)
-# else /* !_POSIX_SOURCE && BSIZE */
-# define ST_NBLOCKS(statbuf) \
- (S_ISREG ((statbuf).st_mode) \
- || S_ISDIR ((statbuf).st_mode) \
- ? st_blocks ((statbuf).st_size) : 0)
-# endif /* !_POSIX_SOURCE && BSIZE */
-#else /* HAVE_STRUCT_STAT_ST_BLOCKS */
-/* Some systems, like Sequents, return st_blksize of 0 on pipes. */
-# define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \
- ? (statbuf).st_blksize : DEV_BSIZE)
-# if defined hpux || defined __hpux__ || defined __hpux
-/* HP-UX counts st_blocks in 1024-byte units.
- This loses when mixing HP-UX and BSD filesystems with NFS. */
-# define ST_NBLOCKSIZE 1024
-# else /* !hpux */
-# if defined _AIX && defined _I386
-/* AIX PS/2 counts st_blocks in 4K units. */
-# define ST_NBLOCKSIZE (4 * 1024)
-# else /* not AIX PS/2 */
-# if defined _CRAY
-# define ST_NBLOCKS(statbuf) \
- (S_ISREG ((statbuf).st_mode) \
- || S_ISDIR ((statbuf).st_mode) \
- ? (statbuf).st_blocks * ST_BLKSIZE(statbuf)/ST_NBLOCKSIZE : 0)
-# endif /* _CRAY */
-# endif /* not AIX PS/2 */
-# endif /* !hpux */
-#endif /* HAVE_STRUCT_STAT_ST_BLOCKS */
-
-#ifndef ST_NBLOCKS
-# define ST_NBLOCKS(statbuf) \
- (S_ISREG ((statbuf).st_mode) \
- || S_ISDIR ((statbuf).st_mode) \
- ? (statbuf).st_blocks : 0)
+ ST_NBLOCKS: Number of 512-byte blocks in the file
+ (including indirect blocks).
+ HP-UX, perhaps uniquely, counts st_blocks in 1024-byte units.
+ This workaround loses when mixing HP-UX and 4BSD filesystems, though. */
+#ifdef _POSIX_SOURCE
+# define ST_NBLOCKS(statp) (((statp)->st_size + 512 - 1) / 512)
+#else
+# ifndef HAVE_ST_BLOCKS
+# define ST_NBLOCKS(statp) (st_blocks ((statp)->st_size))
+# else
+# if defined(hpux) || defined(__hpux__)
+# define ST_NBLOCKS(statp) ((statp)->st_blocks * 2)
+# else
+# define ST_NBLOCKS(statp) ((statp)->st_blocks)
+# endif
+# endif
#endif
-#ifndef ST_NBLOCKSIZE
-# define ST_NBLOCKSIZE 512
+/* Convert B 512-byte blocks to kilobytes if K is nonzero,
+ otherwise return it unchanged. */
+#define convert_blocks(b, k) ((k) ? ((b) + 1) / 2 : (b))
+
+#ifndef _POSIX_VERSION
+struct passwd *getpwuid ();
+struct group *getgrgid ();
#endif
#ifdef major /* Might be defined in sys/types.h. */
@@ -163,148 +107,86 @@
#endif
#undef HAVE_MAJOR
+char *xmalloc ();
+void error ();
+void mode_string ();
-static void print_name (register const char *p, FILE *stream, int literal_control_chars);
-
-
-size_t
-file_blocksize(const struct stat *p)
-{
- return ST_NBLOCKSIZE;
-}
-
-
+char *get_link_name ();
+char *getgroup ();
+char *getuser ();
+void print_name_with_quoting ();
/* NAME is the name to print.
RELNAME is the path to access it from the current directory.
STATP is the results of stat or lstat on it.
- Use CURRENT_TIME to decide whether to print yyyy or hh:mm.
- Use OUTPUT_BLOCK_SIZE to determine how to print file block counts
- and sizes.
STREAM is the stdio stream to print on. */
void
-list_file (const char *name,
- int dirfd,
- char *relname,
- const struct stat *statp,
- time_t current_time,
- int output_block_size,
- int literal_control_chars,
- FILE *stream)
+list_file (name, relname, statp, stream)
+ char *name;
+ char *relname;
+ struct stat *statp;
+ FILE *stream;
{
- char modebuf[12];
- struct tm const *when_local;
- char const *user_name;
- char const *group_name;
- char hbuf[LONGEST_HUMAN_READABLE + 1];
-
-#if HAVE_ST_DM_MODE
- /* Cray DMF: look at the file's migrated, not real, status */
- strmode (statp->st_dm_mode, modebuf);
-#else
- strmode (statp->st_mode, modebuf);
-#endif
+ static int kilobytes = -1; /* -1 = uninitialized, 0 = 512, 1 = 1024. */
+ char modebuf[20];
+ char timebuf[40];
+ time_t current_time = time ((time_t *) 0);
- fprintf (stream, "%6s ",
- human_readable ((uintmax_t) statp->st_ino, hbuf,
- human_ceiling,
- 1, 1));
+ if (kilobytes == -1)
+ kilobytes = getenv ("POSIXLY_CORRECT") == 0;
+
+ mode_string (statp->st_mode, modebuf);
+ modebuf[10] = '\0';
+
+ strcpy (timebuf, ctime (&statp->st_mtime));
+ if (current_time > statp->st_mtime + 6L * 30L * 24L * 60L * 60L /* Old. */
+ || current_time < statp->st_mtime - 60L * 60L) /* In the future. */
+ {
+ /* The file is fairly old or in the future.
+ POSIX says the cutoff is 6 months old;
+ approximate this by 6*30 days.
+ Allow a 1 hour slop factor for what is considered "the future",
+ to allow for NFS server/client clock disagreement.
+ Show the year instead of the time of day. */
+ strcpy (timebuf + 11, timebuf + 19);
+ }
+ timebuf[16] = 0;
- fprintf (stream, "%4s ",
- human_readable ((uintmax_t) ST_NBLOCKS (*statp), hbuf,
- human_ceiling,
- ST_NBLOCKSIZE, output_block_size));
+ fprintf (stream, "%6lu ", statp->st_ino);
+ fprintf (stream, "%4u ", convert_blocks (ST_NBLOCKS (statp), kilobytes));
- /* modebuf includes the space between the mode and the number of links,
- as the POSIX "optional alternate access method flag". */
- fprintf (stream, "%s%3lu ", modebuf, (unsigned long) statp->st_nlink);
+ /* The space between the mode and the number of links is the POSIX
+ "optional alternate access method flag". */
+ fprintf (stream, "%s %3u ", modebuf, statp->st_nlink);
- user_name = getuser (statp->st_uid);
- if (user_name)
- fprintf (stream, "%-8s ", user_name);
- else
- fprintf (stream, "%-8lu ", (unsigned long) statp->st_uid);
+ fprintf (stream, "%-8.8s ", getuser (statp->st_uid));
- group_name = getgroup (statp->st_gid);
- if (group_name)
- fprintf (stream, "%-8s ", group_name);
- else
- fprintf (stream, "%-8lu ", (unsigned long) statp->st_gid);
+ fprintf (stream, "%-8.8s ", getgroup (statp->st_gid));
if (S_ISCHR (statp->st_mode) || S_ISBLK (statp->st_mode))
#ifdef HAVE_ST_RDEV
- fprintf (stream, "%3lu, %3lu ",
- (unsigned long) major (statp->st_rdev),
- (unsigned long) minor (statp->st_rdev));
+ fprintf (stream, "%3u, %3u ", major (statp->st_rdev), minor (statp->st_rdev));
#else
fprintf (stream, " ");
#endif
else
- fprintf (stream, "%8s ",
- human_readable ((uintmax_t) statp->st_size, hbuf,
- human_ceiling,
- 1,
- output_block_size < 0 ? output_block_size : 1));
+ fprintf (stream, "%8lu ", statp->st_size);
- if ((when_local = localtime (&statp->st_mtime)))
- {
- char init_bigbuf[256];
- char *buf = init_bigbuf;
- size_t bufsize = sizeof init_bigbuf;
+ fprintf (stream, "%s ", timebuf + 4);
- /* Use strftime rather than ctime, because the former can produce
- locale-dependent names for the month (%b).
-
- Output the year if the file is fairly old or in the future.
- POSIX says the cutoff is 6 months old;
- approximate this by 6*30 days.
- Allow a 1 hour slop factor for what is considered "the future",
- to allow for NFS server/client clock disagreement. */
- char const *fmt =
- ((current_time - 6 * 30 * 24 * 60 * 60 <= statp->st_mtime
- && statp->st_mtime <= current_time + 60 * 60)
- ? "%b %e %H:%M"
- : "%b %e %Y");
-
- while (!strftime (buf, bufsize, fmt, when_local))
- buf = alloca (bufsize *= 2);
-
- fprintf (stream, "%s ", buf);
- }
- else
- {
- /* The time cannot be represented as a local time;
- print it as a huge integer number of seconds. */
- int width = 12;
-
- if (statp->st_mtime < 0)
- {
- char const *num = human_readable (- (uintmax_t) statp->st_mtime,
- hbuf, human_ceiling, 1, 1);
- int sign_width = width - strlen (num);
- fprintf (stream, "%*s%s ",
- sign_width < 0 ? 0 : sign_width, "-", num);
- }
- else
- fprintf (stream, "%*s ", width,
- human_readable ((uintmax_t) statp->st_mtime, hbuf,
- human_ceiling,
- 1, 1));
- }
-
- print_name (name, stream, literal_control_chars);
+ print_name_with_quoting (name, stream);
#ifdef S_ISLNK
if (S_ISLNK (statp->st_mode))
{
- char *linkname = get_link_name_at (name, dirfd, relname);
+ char *linkname = get_link_name (name, relname);
if (linkname)
{
fputs (" -> ", stream);
- print_name (linkname, stream, literal_control_chars);
+ print_name_with_quoting (linkname, stream);
free (linkname);
}
}
@@ -312,16 +194,10 @@ list_file (const char *name,
putc ('\n', stream);
}
-
-static void
-print_name_without_quoting (const char *p, FILE *stream)
-{
- fprintf(stream, "%s", p);
-}
-
-
-static void
-print_name_with_quoting (register const char *p, FILE *stream)
+void
+print_name_with_quoting (p, stream)
+ register char *p;
+ FILE *stream;
{
register unsigned char c;
@@ -370,17 +246,11 @@ print_name_with_quoting (register const char *p, FILE *stream)
}
}
-static void print_name (register const char *p, FILE *stream, int literal_control_chars)
-{
- if (literal_control_chars)
- print_name_without_quoting(p, stream);
- else
- print_name_with_quoting(p, stream);
-}
-
#ifdef S_ISLNK
-static char *
-get_link_name (const char *name, char *relname)
+char *
+get_link_name (name, relname)
+ char *name;
+ char *relname;
{
register char *linkname;
register int linklen;
@@ -389,7 +259,7 @@ get_link_name (const char *name, char *relname)
mount points with some automounters.
So allocate a pessimistic PATH_MAX + 1 bytes. */
#define LINK_BUF PATH_MAX
- linkname = xmalloc (LINK_BUF + 1);
+ linkname = (char *) xmalloc (LINK_BUF + 1);
linklen = readlink (relname, linkname, LINK_BUF);
if (linklen < 0)
{
@@ -400,34 +270,4 @@ get_link_name (const char *name, char *relname)
linkname[linklen] = '\0';
return linkname;
}
-
-struct link_name_args
-{
- const char *name;
- char *relname;
- char *result;
-};
-
-static int
-get_link_name_cb(void *context)
-{
- struct link_name_args *args = context;
- args->result = get_link_name(args->name, args->relname);
- return 0;
-}
-
-char *
-get_link_name_at (const char *name, int dirfd, char *relname)
-{
- struct link_name_args args;
- args.result = NULL;
- args.name = name;
- args.relname = relname;
- if (0 == run_in_dir(dirfd, get_link_name_cb, &args))
- return args.result;
- else
- return NULL;
-}
-
-
#endif