1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-08-06 00:29:44 +02:00

(<inttypes.h>): Include if HAVE_INTTYPES_H.

("human.h"): Include.
(<limits.h>): Don't include; system.h does it now.
(INT_MAX): Remove.
(longdiff): Remove bogus definition that uses subtraction;
it gives the wrong answer when overflows occur.
(convert_blocks): Remove.
(output_units): New variable;
replaces booleans kilobyte_blocks and megabyte_blocks.
(human_readable_base): New variable.
(long_options, usage): Add -h or --human-readable and -H or --si.
(decode_switches): Adjust to renamed option variables.
Use -H if BLOCKSIZE is SI.  Add -h, -H.
(print_dir): Count blocks using uintmax_t, not int.
(gobble_file): Now returns uintmax_t, not int.
Don't convert blocks to 512 byte units, as this might overflow;
let caller handle the problem.  Deduce what caller will print
by invoking human_readable.
(print_long_format, print_file_name_and_frills): Don't assume
inode number, block count, file size fit in unsigned long.
Use human_readable to do block count conversion and to print
file sizes.
(prep_non_filename_text): Print decimal string for time if
localtime fails due to enormous time_t.
This commit is contained in:
Jim Meyering
1997-11-30 10:25:16 +00:00
parent d08a2b63dc
commit 9c59f1dcc4
+118 -66
View File
@@ -43,6 +43,10 @@
#include <config.h>
#include <sys/types.h>
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_TERMIOS_H
# include <termios.h>
#endif
@@ -56,19 +60,13 @@
#include <pwd.h>
#include <getopt.h>
#if HAVE_LIMITS_H
/* limits.h must come before system.h because limits.h on some systems
undefs PATH_MAX, whereas system.h includes pathmax.h which sets
PATH_MAX. */
# include <limits.h>
#endif
#include "system.h"
#include <fnmatch.h>
#include "obstack.h"
#include "ls.h"
#include "error.h"
#include "human.h"
#include "argmatch.h"
#include "xstrtol.h"
#include "strverscmp.h"
@@ -76,23 +74,13 @@
#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
#ifndef INT_MAX
# define INT_MAX 2147483647
#endif
/* Return an int indicating the result of comparing two integers.
Subtracting doesn't always work, due to overflow. */
#define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b))
/* Return an int indicating the result of comparing two longs. */
#if (INT_MAX <= 65535)
# define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b) ? 1 : 0)
#else
# define longdiff(a, b) ((a) - (b))
#endif
/* 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))
/* The maximum number of digits required to print an inode number
in an unsigned format. */
/* The field width for inode numbers. On some hosts inode numbers are
64 bits, so columns won't line up exactly when a huge inode number
is encountered, but in practice 7 digits is usually enough. */
#ifndef INODE_DIGITS
# define INODE_DIGITS 7
#endif
@@ -181,8 +169,8 @@ static int rev_cmp_version __P ((const struct fileinfo *file2,
const struct fileinfo *file1));
static int decode_switches __P ((int argc, char **argv));
static int file_interesting __P ((const struct dirent *next));
static int gobble_file __P ((const char *name, int explicit_arg,
const char *dirname));
static uintmax_t gobble_file __P ((const char *name, int explicit_arg,
const char *dirname));
static int is_not_dot_or_dotdot __P ((const char *name));
static void print_color_indicator __P ((const char *name, unsigned int mode,
int linkok));
@@ -327,10 +315,9 @@ static int numeric_ids;
static int print_block_size;
/* Nonzero means show file sizes in kilobytes instead of blocks
(the size of which is system-dependent). -k */
/* The units to count blocks in. */
static int kilobyte_blocks;
static int output_units;
/* Precede each line of long output (per file) with a string like `m,n:'
where M is the number of characters after the `:' and before the
@@ -410,6 +397,10 @@ struct col_ext_type *col_ext_list = NULL;
/* Buffer for color sequences */
static char *color_buf;
/* base used for human style output */
static int human_readable_base;
/* Nonzero means mention the inode number of each file. -i */
static int print_inode;
@@ -508,6 +499,7 @@ static struct option const long_options[] =
{"directory", no_argument, 0, 'd'},
{"dired", no_argument, 0, 'D'},
{"full-time", no_argument, &full_time, 1},
{"human-readable", no_argument, 0, 'h'},
{"inode", no_argument, 0, 'i'},
{"kilobytes", no_argument, 0, 'k'},
{"numeric-uid-gid", no_argument, 0, 'n'},
@@ -520,6 +512,7 @@ static struct option const long_options[] =
{"ignore-backups", no_argument, 0, 'B'},
{"classify", no_argument, 0, 'F'},
{"file-type", no_argument, 0, 'F'},
{"si", no_argument, 0, 'H'},
{"ignore", required_argument, 0, 'I'},
{"dereference", no_argument, 0, 'L'},
{"literal", no_argument, 0, 'N'},
@@ -843,7 +836,7 @@ decode_switches (int argc, char **argv)
sort_reverse = 0;
numeric_ids = 0;
print_block_size = 0;
kilobyte_blocks = getenv ("POSIXLY_CORRECT") == 0;
output_units = getenv ("POSIXLY_CORRECT") ? 512 : 1024;
indicator_style = none;
print_inode = 0;
trace_links = 0;
@@ -854,6 +847,12 @@ decode_switches (int argc, char **argv)
ignore_patterns = 0;
quote_as_string = 0;
if ((p = getenv ("BLOCKSIZE"))
&& strncmp (p, "HUMAN", sizeof ("HUMAN") - 1) == 0)
human_readable_base = 1024;
else if (p && strcmp (p, "SI") == 0)
human_readable_base = 1000;
line_length = 80;
if ((p = getenv ("COLUMNS")) && *p)
{
@@ -898,7 +897,7 @@ decode_switches (int argc, char **argv)
}
while ((c = getopt_long (argc, argv,
"abcdfgiklmnopqrstuvw:xABCDFGI:LNQRST:UX1",
"abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
long_options, NULL)) != -1)
{
switch (c)
@@ -941,12 +940,20 @@ decode_switches (int argc, char **argv)
/* No effect. For BSD compatibility. */
break;
case 'h':
human_readable_base = 1024;
break;
case 'H':
human_readable_base = 1000;
break;
case 'i':
print_inode = 1;
break;
case 'k':
kilobyte_blocks = 1;
output_units = 1024;
break;
case 'l':
@@ -1505,7 +1512,7 @@ print_dir (const char *name, const char *realname)
{
register DIR *reading;
register struct dirent *next;
register int total_blocks = 0;
register uintmax_t total_blocks = 0;
errno = 0;
reading = opendir (name);
@@ -1555,11 +1562,16 @@ print_dir (const char *name, const char *realname)
if (format == long_format || print_block_size)
{
char buf[6 + 20 + 1 + 1];
const char *p;
char buf[LONGEST_HUMAN_READABLE + 1];
DIRED_INDENT ();
sprintf (buf, "total %u\n", total_blocks);
FPUTS (buf, stdout, strlen (buf));
p = _("total");
FPUTS (p, stdout, strlen (p));
PUTCHAR (' ');
p = human_readable (total_blocks, buf, ST_NBLOCKSIZE, output_units, 0);
FPUTS (p, stdout, strlen (p));
PUTCHAR ('\n');
}
if (files_index)
@@ -1629,10 +1641,10 @@ clear_files (void)
Verify that the file exists, and print an error message if it does not.
Return the number of blocks that the file occupies. */
static int
static uintmax_t
gobble_file (const char *name, int explicit_arg, const char *dirname)
{
register int blocks;
register uintmax_t blocks;
register int val;
register char *path;
@@ -1741,14 +1753,14 @@ gobble_file (const char *name, int explicit_arg, const char *dirname)
else
files[files_index].filetype = normal;
blocks = convert_blocks (ST_NBLOCKS (files[files_index].stat),
kilobyte_blocks);
if (blocks >= 10000 && block_size_size < 5)
block_size_size = 5;
if (blocks >= 100000 && block_size_size < 6)
block_size_size = 6;
if (blocks >= 1000000 && block_size_size < 7)
block_size_size = 7;
blocks = ST_NBLOCKS (files[files_index].stat);
{
char buf[LONGEST_HUMAN_READABLE + 1];
int len = strlen (human_readable (blocks, buf, ST_NBLOCKSIZE,
output_units, 0));
if (block_size_size < len)
block_size_size = len < 7 ? len : 7;
}
}
else
blocks = 0;
@@ -2091,17 +2103,21 @@ print_long_format (const struct fileinfo *f)
{
char modebuf[11];
/* 7 fields that may (worst case: 64-bit integral values) require 20 bytes,
/* 7 fields that may require LONGEST_HUMAN_READABLE bytes,
1 10-byte mode string,
1 24-byte time string (may be longer in some locales -- see below),
1 24-byte time string (may be longer in some locales -- see below)
or LONGEST_HUMAN_READABLE integer,
9 spaces, one following each of these fields, and
1 trailing NUL byte. */
char init_bigbuf[7 * 20 + 10 + 24 + 9 + 1];
char init_bigbuf[7 * LONGEST_HUMAN_READABLE + 10
+ (LONGEST_HUMAN_READABLE < 24 ? 24 : LONGEST_HUMAN_READABLE)
+ 9 + 1];
char *buf = init_bigbuf;
size_t bufsize = sizeof (init_bigbuf);
size_t s;
char *p;
time_t when;
struct tm *when_local;
const char *fmt;
char *user_name;
@@ -2153,15 +2169,18 @@ print_long_format (const struct fileinfo *f)
if (print_inode)
{
sprintf (p, "%*lu ", INODE_DIGITS, (unsigned long) f->stat.st_ino);
char buf[LONGEST_HUMAN_READABLE + 1];
sprintf (p, "%*s ", INODE_DIGITS,
human_readable ((uintmax_t) f->stat.st_ino, buf, 1, 1, 0));
p += strlen (p);
}
if (print_block_size)
{
sprintf (p, "%*u ", block_size_size,
(unsigned) convert_blocks (ST_NBLOCKS (f->stat),
kilobyte_blocks));
char buf[LONGEST_HUMAN_READABLE + 1];
sprintf (p, "%*s ", block_size_size,
human_readable ((uintmax_t) ST_NBLOCKS (f->stat), buf,
ST_NBLOCKSIZE, output_units, 0));
p += strlen (p);
}
@@ -2191,25 +2210,53 @@ print_long_format (const struct fileinfo *f)
sprintf (p, "%3u, %3u ", (unsigned) major (f->stat.st_rdev),
(unsigned) minor (f->stat.st_rdev));
else
sprintf (p, "%8lu ", (unsigned long) f->stat.st_size);
{
char buf[LONGEST_HUMAN_READABLE + 1];
sprintf (p, "%8s ",
human_readable ((uintmax_t) f->stat.st_size,
buf, 1, 1, human_readable_base));
}
p += strlen (p);
/* Use strftime rather than ctime, because the former can produce
locale-dependent names for the weekday (%a) and month (%b). */
while (! (s = strftime (p, buf + bufsize - p - 1, fmt, localtime (&when))))
if ((when_local = localtime (&when)))
{
char *newbuf = (char *) alloca (bufsize *= 2);
memcpy (newbuf, buf, p - buf);
p = newbuf + (p - buf);
buf = newbuf;
while (! (s = strftime (p, buf + bufsize - p - 1, fmt, when_local)))
{
char *newbuf = (char *) alloca (bufsize *= 2);
memcpy (newbuf, buf, p - buf);
p = newbuf + (p - buf);
buf = newbuf;
}
p += s;
*p++ = ' ';
/* NUL-terminate the string -- fputs (via FPUTS) requires it. */
*p = '\0';
}
else
{
/* The time cannot be represented as a local time;
print it as a huge integer number of seconds. */
char buf[LONGEST_HUMAN_READABLE + 1];
int width = full_time ? 24 : 12;
p += s;
*p++ = ' ';
if (when < 0)
{
const char *num = human_readable (- (uintmax_t) when, buf, 1, 1, 0);
int sign_width = width - strlen (num);
sprintf (p, "%*s%s ", sign_width < 0 ? 0 : sign_width, "-", num);
}
else
sprintf (p, "%*s ", width,
human_readable ((uintmax_t) when, buf, 1, 1, 0));
/* NUL-terminate the string -- fputs (via FPUTS) requires it. */
*p = '\0';
p += strlen (p);
}
DIRED_INDENT ();
FPUTS (buf, stdout, p - buf);
@@ -2414,13 +2461,16 @@ prep_non_filename_text (void)
static void
print_file_name_and_frills (const struct fileinfo *f)
{
char buf[LONGEST_HUMAN_READABLE + 1];
if (print_inode)
printf ("%*lu ", INODE_DIGITS, (unsigned long) f->stat.st_ino);
printf ("%*s ", INODE_DIGITS,
human_readable ((uintmax_t) f->stat.st_ino, buf, 1, 1, 0));
if (print_block_size)
printf ("%*u ", block_size_size,
(unsigned) convert_blocks (ST_NBLOCKS (f->stat),
kilobyte_blocks));
printf ("%*s ", block_size_size,
human_readable ((uintmax_t) ST_NBLOCKS (f->stat), buf,
ST_NBLOCKSIZE, output_units, 0));
print_name_with_quoting (f->name, f->stat.st_mode, f->linkok);
@@ -2914,6 +2964,8 @@ Sort entries alphabetically if none of -cftuSUX nor --sort.\n\
printf (_("\
-g (ignored)\n\
-G, --no-group inhibit display of group information\n\
-h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
-H, --si likewise, but use powers of 1000 not 1024\n\
-i, --inode print index number of each file\n\
-I, --ignore=PATTERN do not list implied entries matching shell PATTERN\n\
-k, --kilobytes use 1024 blocks, not 512 despite POSIXLY_CORRECT\n\