Paul Eggert wrote: > Pádraig Brady <p...@draigbrady.com> writes: > >>> It's guaranteed that st_size's type is signed, since off_t is signed. >> What I meant is that it assumes that st_size will never overflow. > > POSIX allows st_size to have negative values for files that are neither > regular files nor symbolic links, and I don't think coreutils should > assume that these negative values necessarily represent overflow.
Perhaps I should use an equivalent of unsigned_file_size() (which you can see removed in the patch below) instead of ST_SIZE? That would make it explicit, and we can use .st_size directly in the very few places that require that. > I'm leery of assuming that st_blksize should be interpreted as an > unsigned value. If it's (say) -1, and we interpret it as (say) 2**64 - > 1, we're likely to crash with a memory allocation issue. Well we'd have to add explicit checks for < 0, but I agree. > I'm leery of using 'unsigned int' values to store print widths used by > 'printf'. The C standard says they're supposed to be 'int'. Keeping > them 'int' is more likely to catch overflow bugs (if compiled with > arithmetic overflow checking turned on, admittedly unlikely....). true, mutter... > Better than using 'assert', 'du' should report a size overflow and > continue. I just changed that. > > I'm with Jim that we shouldn't contort the code merely to pacify GCC's > overly enthusiastic sign compare warnings. I might maintain contentious parts of the patch like src/c99-to-c89.diff ? > Gotta run, but these are my thoughts for now.... thanks! latest patch follows. I've tested with _FILE_OFFSET_BITS = 32 and 64 but I've not tested on 64 bit yet. Also there are a couple of places in gnulib that are giving warnings with this enabled. >From b50bb4f05efafd0187be3123350e35520babafff Mon Sep 17 00:00:00 2001 From: =?utf-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com> Date: Mon, 5 Jan 2009 19:13:24 +0000 Subject: [PATCH] build: enable and avoid -Wsign-compare warnings * configure.ac: allow --enable-gcc-warnings to include -Wsign-compare, which is included as part of -Wextra. * gl/lib/mgetgroups.c: refactor with the side affect of avoiding signed comparison warning. * src/system.h: Assume st_size, st_blksize, st_blocks of stat struct are always to be interpreted as positive values, so cast to uintmax_t in the corresponding extraction macros. A new macro ST_SIZE was added to do this cast for the st_size member. * src/copy.c: Use ST_SIZE macro to get an unsigned value. Use already assigned unsigned variable n, rather than signed n_read in unsigned comparison. * src/dd.c: Split out ternary conditional to avoid warning about * gl/lib/argv-iter.c: ditto the use of signed and unsigned in the expression. Copy lseek return to a uintmax_t as it's compared against unsigned. * src/du.c: Store st_size in uintmax_t explicitly to avoid warning. Also print an error for the improbable overflow condition. * src/group-list.c: Use int rather than size_t as variable is used in signed comparisons. * src/id.c: ditto. * src/ls.c: Use unsigned variables for always positive widths. Refactor common code to a new format_number_width() function. Remove unsigned_file_size() and use new ST_SIZE macro instead. Rename longdiff() macro to the more accurate numcmp(). * src/od.c: Use unsigned widths as always positive. Use ST_SIZE macro to remove an existing cast. * src/pathchk.c: Compare pathconf limits to signed MAX constants, as pathconf returns signed values. * src/pr.c: Use unsigned variables in unsigned comparisons. * src/shuf.c: ditto. * src/ptx.c: Removing existing (redundant) casts of st_size, and use ST_SIZE on all references to st_size. * src/shred.c: Use already assigned signed variable sizeof_r, rather than the unsigned sizeof(r). Don't use signed integer overflow check that contemporary compilers may remove. * src/sort.c: Use unsigned file_size in unsigned comparisions. * src/tac.c: Store lseek return in uintmax_t as it's used in various unsigned comparisions. Cast to off_t only in error check. Remove redundant (off_t) casts. * src/tail.c: Use ST_SIZE on all references to st_size. * src/test.c: ditto. * src/wc.c: ditto. --- configure.ac | 1 - gl/lib/argv-iter.c | 7 +++- gl/lib/mgetgroups.c | 56 +++++++++++------------------ src/copy.c | 16 ++++---- src/dd.c | 19 ++++++---- src/du.c | 20 ++++++++--- src/group-list.c | 4 +- src/id.c | 4 +- src/ls.c | 98 ++++++++++++++++++++++++--------------------------- src/od.c | 12 +++--- src/pathchk.c | 6 ++-- src/pr.c | 8 ++-- src/ptx.c | 10 +++--- src/shred.c | 6 ++-- src/shuf.c | 6 ++-- src/sort.c | 6 ++-- src/stat.c | 4 +- src/system.h | 18 +++++---- src/tac.c | 10 +++--- src/tail.c | 12 +++--- src/test.c | 2 +- src/wc.c | 6 ++-- 22 files changed, 165 insertions(+), 166 deletions(-) diff --git a/configure.ac b/configure.ac index 6163db7..a13e4b5 100644 --- a/configure.ac +++ b/configure.ac @@ -61,7 +61,6 @@ if test "$gl_gcc_warnings" = yes; then gl_WARN_ADD([-Wall]) gl_WARN_ADD([-Wextra]) gl_WARN_ADD([-Wshadow]) - gl_WARN_ADD([-Wno-sign-compare]) gl_WARN_ADD([-Wformat]) gl_WARN_ADD([-Wformat-security]) gl_WARN_ADD([-Wcast-align]) diff --git a/gl/lib/argv-iter.c b/gl/lib/argv-iter.c index 4c79b10..9a98076 100644 --- a/gl/lib/argv-iter.c +++ b/gl/lib/argv-iter.c @@ -1,5 +1,5 @@ /* Iterate over arguments from argv or --files0-from=FILE - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008-2009 Free Software Foundation, Inc. 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 @@ -99,7 +99,10 @@ argv_iter (struct argv_iterator *ai, enum argv_iter_err *err) size_t argv_iter_n_args (struct argv_iterator const *ai) { - return ai->fp ? ai->item_idx : ai->p - ai->arg_list; + if (ai->fp) + return ai->item_idx; + else + return ai->p - ai->arg_list; } void diff --git a/gl/lib/mgetgroups.c b/gl/lib/mgetgroups.c index ad1fd4f..9ff21a5 100644 --- a/gl/lib/mgetgroups.c +++ b/gl/lib/mgetgroups.c @@ -1,6 +1,6 @@ /* mgetgroups.c -- return a list of the groups a user is in - Copyright (C) 2007-2008 Free Software Foundation, Inc. + Copyright (C) 2007-2009 Free Software Foundation, Inc. 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 @@ -33,16 +33,16 @@ #include "xalloc.h" -static void * -allocate_groupbuf (int size) +static GETGROUPS_T * +realloc_groupbuf (GETGROUPS_T *g, size_t num) { - if (xalloc_oversized (size, sizeof (GETGROUPS_T))) + if (xalloc_oversized (num, sizeof *g)) { errno = ENOMEM; return NULL; } - return malloc (size * sizeof (GETGROUPS_T)); + return realloc (g, num * sizeof *g); } /* Like getugroups, but store the result in malloc'd storage. @@ -62,48 +62,30 @@ mgetgroups (char const *username, gid_t gid, GETGROUPS_T **groups) #if HAVE_GETGROUPLIST /* We prefer to use getgrouplist if available, because it has better - performance characteristics. + performance characteristics. */ - In glibc 2.3.2, getgrouplist is buggy. If you pass a zero as the - size of the output buffer, getgrouplist will still write to the - buffer. Contrary to what some versions of the getgrouplist - manpage say, this doesn't happen with nonzero buffer sizes. - Therefore our usage here just avoids a zero sized buffer. */ if (username) { + /* In glibc 2.3.2, getgrouplist is buggy. If you pass a zero as the + length of the output buffer, getgrouplist will still write to the + buffer. Contrary to what some versions of the getgrouplist + manpage say, this doesn't happen with nonzero buffer sizes. + Therefore our usage here just avoids a zero sized buffer. */ enum { N_GROUPS_INIT = 10 }; - GETGROUPS_T smallbuf[N_GROUPS_INIT]; - max_n_groups = N_GROUPS_INIT; - ng = getgrouplist (username, gid, smallbuf, &max_n_groups); - g = allocate_groupbuf (max_n_groups); + g = realloc_groupbuf (NULL, max_n_groups); if (g == NULL) return -1; - if (max_n_groups <= N_GROUPS_INIT) - { - /* smallbuf was big enough, so we already have our data */ - memcpy (g, smallbuf, max_n_groups * sizeof *g); - *groups = g; - return max_n_groups; - } - while (1) { GETGROUPS_T *h; - ng = getgrouplist (username, gid, g, &max_n_groups); - if (0 <= ng) - { - *groups = g; - return ng; - } - /* When getgrouplist fails, it guarantees that - max_n_groups reflects the new number of groups. */ + /* getgrouplist updates max_n_groups to num required. */ + ng = getgrouplist (username, gid, g, &max_n_groups); - if (xalloc_oversized (max_n_groups, sizeof *h) - || (h = realloc (g, max_n_groups * sizeof *h)) == NULL) + if ((h = realloc_groupbuf (g, max_n_groups)) == NULL) { int saved_errno = errno; free (g); @@ -111,6 +93,12 @@ mgetgroups (char const *username, gid_t gid, GETGROUPS_T **groups) return -1; } g = h; + + if (ng >= 0) + { + *groups = g; + return ng; + } } } /* else no username, so fall through and use getgroups. */ @@ -125,7 +113,7 @@ mgetgroups (char const *username, gid_t gid, GETGROUPS_T **groups) if (max_n_groups < 0) max_n_groups = 5; - g = allocate_groupbuf (max_n_groups); + g = realloc_groupbuf (NULL, max_n_groups); if (g == NULL) return -1; diff --git a/src/copy.c b/src/copy.c index c9c79a1..96e1865 100644 --- a/src/copy.c +++ b/src/copy.c @@ -1,5 +1,5 @@ /* copy.c -- core functions for copying files and directories - Copyright (C) 89, 90, 91, 1995-2008 Free Software Foundation, Inc. + Copyright (C) 89, 90, 91, 1995-2009 Free Software Foundation, Inc. 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 @@ -501,7 +501,7 @@ copy_reg (char const *src_name, char const *dst_name, needed for a file of its size, then at least one of the blocks in the file is a hole. */ if (x->sparse_mode == SPARSE_AUTO && S_ISREG (src_open_sb.st_mode) - && ST_NBLOCKS (src_open_sb) < src_open_sb.st_size / ST_NBLOCKSIZE) + && ST_NBLOCKS (src_open_sb) < ST_SIZE (src_open_sb) / ST_NBLOCKSIZE) make_holes = true; #endif } @@ -527,8 +527,8 @@ copy_reg (char const *src_name, char const *dst_name, /* Do not bother with a buffer larger than the input file, plus one byte to make sure the file has not grown while reading it. */ - if (S_ISREG (src_open_sb.st_mode) && src_open_sb.st_size < buf_size) - buf_size = src_open_sb.st_size + 1; + if (S_ISREG (src_open_sb.st_mode) && ST_SIZE (src_open_sb) < buf_size) + buf_size = ST_SIZE (src_open_sb) + 1; /* However, stick with a block size that is a positive multiple of blcm, overriding the above adjustments. Watch out for @@ -620,7 +620,7 @@ copy_reg (char const *src_name, char const *dst_name, last_write_made_hole = false; /* A short read on a regular file means EOF. */ - if (n_read != buf_size && S_ISREG (src_open_sb.st_mode)) + if (n != buf_size && S_ISREG (src_open_sb.st_mode)) break; } } @@ -1858,7 +1858,7 @@ copy_internal (char const *src_name, char const *dst_name, } else if (S_ISLNK (src_mode)) { - char *src_link_val = areadlink_with_size (src_name, src_sb.st_size); + char *src_link_val = areadlink_with_size (src_name, ST_SIZE (src_sb)); if (src_link_val == NULL) { error (0, errno, _("cannot read symbolic link %s"), quote (src_name)); @@ -1872,14 +1872,14 @@ copy_internal (char const *src_name, char const *dst_name, int saved_errno = errno; bool same_link = false; if (x->update && !new_dst && S_ISLNK (dst_sb.st_mode) - && dst_sb.st_size == strlen (src_link_val)) + && ST_SIZE (dst_sb) == strlen (src_link_val)) { /* See if the destination is already the desired symlink. FIXME: This behavior isn't documented, and seems wrong in some cases, e.g., if the destination symlink has the wrong ownership, permissions, or time stamps. */ char *dest_link_val = - areadlink_with_size (dst_name, dst_sb.st_size); + areadlink_with_size (dst_name, ST_SIZE (dst_sb)); if (dest_link_val && STREQ (dest_link_val, src_link_val)) same_link = true; free (dest_link_val); diff --git a/src/dd.c b/src/dd.c index d683c5d..af4d148 100644 --- a/src/dd.c +++ b/src/dd.c @@ -1,5 +1,5 @@ /* dd -- convert a file while copying it. - Copyright (C) 85, 90, 91, 1995-2008 Free Software Foundation, Inc. + Copyright (C) 85, 90, 91, 1995-2009 Free Software Foundation, Inc. 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 @@ -910,7 +910,11 @@ parse_symbols (char const *str, struct symbol_value const *table, { if (! entry->symbol[0]) { - size_t slen = strcomma ? strcomma - str : strlen (str); + size_t slen; + if (strcomma) + slen = strcomma - str; + else + slen = strlen (str); error (0, 0, "%s: %s", _(error_msgid), quotearg_n_style_mem (0, locale_quoting_style, str, slen)); usage (EXIT_FAILURE); @@ -1313,7 +1317,7 @@ advance_input_after_read_error (size_t nbytes) } else { - off_t offset; + uintmax_t offset; advance_input_offset (nbytes); input_offset_overflow |= (OFF_T_MAX < input_offset); if (input_offset_overflow) @@ -1323,13 +1327,12 @@ advance_input_after_read_error (size_t nbytes) return false; } offset = lseek (STDIN_FILENO, 0, SEEK_CUR); - if (0 <= offset) + if (0 <= (off_t) offset) { - off_t diff; - if (offset == input_offset) + off_t diff = input_offset - offset; + if (diff == 0) return true; - diff = input_offset - offset; - if (! (0 <= diff && diff <= nbytes)) + if (diff < 0 || (size_t) diff > nbytes) error (0, 0, _("warning: invalid file offset after failed read")); if (0 <= skip_via_lseek (input_file, STDIN_FILENO, diff, SEEK_CUR)) return true; diff --git a/src/du.c b/src/du.c index 860e8fe..63891e1 100644 --- a/src/du.c +++ b/src/du.c @@ -1,5 +1,5 @@ /* du -- summarize disk usage - Copyright (C) 1988-1991, 1995-2008 Free Software Foundation, Inc. + Copyright (C) 1988-1991, 1995-2009 Free Software Foundation, Inc. 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 @@ -129,7 +129,7 @@ struct dulevel static bool opt_all = false; /* If true, rather than using the disk usage of each file, - use the apparent size (a la stat.st_size). */ + use the apparent size (a la ST_SIZE(stat)). */ static bool apparent_size = false; /* If true, count each hard link of files with multiple links. */ @@ -524,10 +524,20 @@ process_file (FTS *fts, FTSENT *ent) } else { + uintmax_t size = ST_SIZE (*sb); + if (!apparent_size) + { + uintmax_t blocks = ST_NBLOCKS (*sb); + if (blocks > (UINTMAX_MAX / ST_NBLOCKSIZE)) + { + error (0, 0, _("size overflow for %s with %" PRIuMAX " blocks"), + quote (file), blocks); + return false; + } + size = blocks * ST_NBLOCKSIZE; + } duinfo_set (&dui, - (apparent_size - ? sb->st_size - : (uintmax_t) ST_NBLOCKS (*sb) * ST_NBLOCKSIZE), + size, (time_type == time_mtime ? get_stat_mtime (sb) : time_type == time_atime ? get_stat_atime (sb) : get_stat_ctime (sb))); diff --git a/src/group-list.c b/src/group-list.c index 3547ed6..46895b4 100644 --- a/src/group-list.c +++ b/src/group-list.c @@ -1,5 +1,5 @@ /* group-list.c --Print a list of group IDs or names. - Copyright (C) 1989-2008 Free Software Foundation, Inc. + Copyright (C) 1989-2009 Free Software Foundation, Inc. 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 @@ -57,7 +57,7 @@ print_group_list (const char *username, #if HAVE_GETGROUPS { GETGROUPS_T *groups; - size_t i; + int i; int n_groups = mgetgroups (username, (pwd ? pwd->pw_gid : (gid_t) -1), &groups); diff --git a/src/id.c b/src/id.c index 156b066..05ad2d8 100644 --- a/src/id.c +++ b/src/id.c @@ -1,5 +1,5 @@ /* id -- print real and effective UIDs and GIDs - Copyright (C) 1989-2008 Free Software Foundation, Inc. + Copyright (C) 1989-2009 Free Software Foundation, Inc. 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 @@ -294,7 +294,7 @@ print_full_info (const char *username) #if HAVE_GETGROUPS { GETGROUPS_T *groups; - size_t i; + int i; int n_groups = mgetgroups (username, (pwd ? pwd->pw_gid : (gid_t) -1), &groups); diff --git a/src/ls.c b/src/ls.c index b03aebc..c41aec9 100644 --- a/src/ls.c +++ b/src/ls.c @@ -1,5 +1,5 @@ /* `dir', `vdir' and `ls' directory listing programs for GNU. - Copyright (C) 85, 88, 90, 91, 1995-2008 Free Software Foundation, Inc. + Copyright (C) 85, 88, 90, 91, 1995-2009 Free Software Foundation, Inc. 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 @@ -117,9 +117,8 @@ #define obstack_chunk_alloc malloc #define obstack_chunk_free free -/* 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)) +/* strcmp like macro for scalars or pointers. */ +#define numcmp(a, b) ((a) < (b) ? -1 : (a) > (b)) #if ! HAVE_STRUCT_STAT_ST_AUTHOR # define st_author st_uid @@ -233,8 +232,11 @@ static void print_dir (char const *name, char const *realname, bool command_line_arg); static void print_file_name_and_frills (const struct fileinfo *f); static void print_horizontal (void); -static int format_user_width (uid_t u); -static int format_group_width (gid_t g); +static unsigned int format_user_width (uid_t u); +static unsigned int format_group_width (gid_t g); +static unsigned int format_number_width (uintmax_t number, + uintmax_t from_blksize, + uintmax_t to_blksize); static void print_long_format (const struct fileinfo *f); static void print_many_per_line (void); static void print_name_with_quoting (const char *p, mode_t mode, @@ -331,16 +333,16 @@ static bool any_has_acl; block sizes, link counts, owners, groups, authors, major device numbers, minor device numbers, and file sizes, respectively. */ -static int inode_number_width; -static int block_size_width; -static int nlink_width; -static int scontext_width; -static int owner_width; -static int group_width; -static int author_width; -static int major_device_number_width; -static int minor_device_number_width; -static int file_size_width; +static unsigned int inode_number_width; +static unsigned int block_size_width; +static unsigned int nlink_width; +static unsigned int scontext_width; +static unsigned int owner_width; +static unsigned int group_width; +static unsigned int author_width; +static unsigned int major_device_number_width; +static unsigned int minor_device_number_width; +static unsigned int file_size_width; /* Option flags */ @@ -2528,16 +2530,6 @@ file_ignored (char const *name) || patterns_match (ignore_patterns, name)); } -/* POSIX requires that a file size be printed without a sign, even - when negative. Assume the typical case where negative sizes are - actually positive values that have wrapped around. */ - -static uintmax_t -unsigned_file_size (off_t size) -{ - return size + (size < 0) * ((uintmax_t) OFF_T_MAX - OFF_T_MIN + 1); -} - /* Enter and remove entries in the table `cwd_file'. */ /* Empty the table of files. */ @@ -2798,10 +2790,8 @@ gobble_file (char const *name, enum filetype type, ino_t inode, blocks = ST_NBLOCKS (f->stat); if (format == long_format || print_block_size) { - char buf[LONGEST_HUMAN_READABLE + 1]; - int len = mbswidth (human_readable (blocks, buf, human_output_opts, - ST_NBLOCKSIZE, output_block_size), - 0); + unsigned int len; + len = format_number_width (blocks, ST_NBLOCKSIZE, output_block_size); if (block_size_width < len) block_size_width = len; } @@ -2810,21 +2800,21 @@ gobble_file (char const *name, enum filetype type, ino_t inode, { if (print_owner) { - int len = format_user_width (f->stat.st_uid); + unsigned int len = format_user_width (f->stat.st_uid); if (owner_width < len) owner_width = len; } if (print_group) { - int len = format_group_width (f->stat.st_gid); + unsigned int len = format_group_width (f->stat.st_gid); if (group_width < len) group_width = len; } if (print_author) { - int len = format_user_width (f->stat.st_author); + unsigned int len = format_user_width (f->stat.st_author); if (author_width < len) author_width = len; } @@ -2832,7 +2822,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode, if (print_scontext) { - int len = strlen (f->scontext); + size_t len = strlen (f->scontext); if (scontext_width < len) scontext_width = len; } @@ -2840,14 +2830,15 @@ gobble_file (char const *name, enum filetype type, ino_t inode, if (format == long_format) { char b[INT_BUFSIZE_BOUND (uintmax_t)]; - int b_len = strlen (umaxtostr (f->stat.st_nlink, b)); + size_t b_len = strlen (umaxtostr (f->stat.st_nlink, b)); if (nlink_width < b_len) nlink_width = b_len; if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode)) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; - int len = strlen (umaxtostr (major (f->stat.st_rdev), buf)); + unsigned int len; + len = strlen (umaxtostr (major (f->stat.st_rdev), buf)); if (major_device_number_width < len) major_device_number_width = len; len = strlen (umaxtostr (minor (f->stat.st_rdev), buf)); @@ -2859,11 +2850,9 @@ gobble_file (char const *name, enum filetype type, ino_t inode, } else { - char buf[LONGEST_HUMAN_READABLE + 1]; - uintmax_t size = unsigned_file_size (f->stat.st_size); - int len = mbswidth (human_readable (size, buf, human_output_opts, - 1, file_output_block_size), - 0); + uintmax_t size = ST_SIZE (f->stat); + unsigned int len; + len = format_number_width (size, 1, file_output_block_size); if (file_size_width < len) file_size_width = len; } @@ -2873,7 +2862,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode, if (print_inode) { char buf[INT_BUFSIZE_BOUND (uintmax_t)]; - int len = strlen (umaxtostr (f->stat.st_ino, buf)); + size_t len = strlen (umaxtostr (f->stat.st_ino, buf)); if (inode_number_width < len) inode_number_width = len; } @@ -2898,7 +2887,7 @@ is_directory (const struct fileinfo *f) static void get_link_name (char const *filename, struct fileinfo *f, bool command_line_arg) { - f->linkname = areadlink_with_size (filename, f->stat.st_size); + f->linkname = areadlink_with_size (filename, ST_SIZE (f->stat)); if (f->linkname == NULL) file_failure (command_line_arg, _("cannot read symbolic link %s"), filename); @@ -3104,7 +3093,7 @@ static inline int cmp_size (struct fileinfo const *a, struct fileinfo const *b, int (*cmp) (char const *, char const *)) { - int diff = longdiff (b->stat.st_size, a->stat.st_size); + int diff = numcmp (ST_SIZE (b->stat), ST_SIZE (a->stat)); return diff ? diff : cmp (a->name, b->name); } @@ -3396,14 +3385,11 @@ format_group (gid_t g, int width, bool stat_ok) /* Return the number of columns that format_user_or_group will print. */ -static int +static unsigned int format_user_or_group_width (char const *name, unsigned long int id) { if (name) - { - int len = mbswidth (name, 0); - return MAX (0, len); - } + return mbswidth (name, 0); /* >=0 when flags=0. */ else { char buf[INT_BUFSIZE_BOUND (unsigned long int)]; @@ -3414,7 +3400,7 @@ format_user_or_group_width (char const *name, unsigned long int id) /* Return the number of columns that format_user will print. */ -static int +static unsigned int format_user_width (uid_t u) { return format_user_or_group_width (numeric_ids ? NULL : getuser (u), u); @@ -3422,12 +3408,20 @@ format_user_width (uid_t u) /* Likewise, for groups. */ -static int +static unsigned int format_group_width (gid_t g) { return format_user_or_group_width (numeric_ids ? NULL : getgroup (g), g); } +static unsigned int +format_number_width (uintmax_t number, uintmax_t from_blksize, uintmax_t to_blksize) +{ + char buf[LONGEST_HUMAN_READABLE + 1]; + return mbswidth (human_readable (number, buf, human_output_opts, + from_blksize, to_blksize), + 0); /* flags=0 => len>=0. */ +} /* Print information about F in long format. */ @@ -3565,7 +3559,7 @@ print_long_format (const struct fileinfo *f) char const *size = (! f->stat_ok ? "?" - : human_readable (unsigned_file_size (f->stat.st_size), + : human_readable (ST_SIZE (f->stat), hbuf, human_output_opts, 1, file_output_block_size)); int pad; for (pad = file_size_width - mbswidth (size, 0); 0 < pad; pad--) diff --git a/src/od.c b/src/od.c index 2dcb398..90b7353 100644 --- a/src/od.c +++ b/src/od.c @@ -1,5 +1,5 @@ /* od -- dump files in octal and other formats - Copyright (C) 92, 1995-2008 Free Software Foundation, Inc. + Copyright (C) 92, 1995-2009 Free Software Foundation, Inc. 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 @@ -119,7 +119,7 @@ struct tspec char const *fmt, int width, int pad); char fmt_string[FMT_BYTES_ALLOCATED]; /* Of the style "%*d". */ bool hexl_mode_trailer; - int field_width; /* Minimum width of a field, excluding leading space. */ + unsigned int field_width; /* Minimum width, excluding leading space. */ int pad_width; /* Total padding to be divided among fields. */ }; @@ -991,10 +991,10 @@ skip (uintmax_t n_skip) and go on to the next file. Skip this optimization also when st_size is 0, because some kernels report that nonempty files in /proc have st_size == 0. */ - if (S_ISREG (file_stats.st_mode) && 0 < file_stats.st_size) + if (S_ISREG (file_stats.st_mode) && ST_SIZE (file_stats)) { - if ((uintmax_t) file_stats.st_size < n_skip) - n_skip -= file_stats.st_size; + if (ST_SIZE (file_stats) < n_skip) + n_skip -= ST_SIZE (file_stats); else { if (fseeko (in_stream, n_skip, SEEK_CUR) != 0) @@ -1883,7 +1883,7 @@ it must be one character from [doxn]"), for (i = 0; i < n_specs; i++) { int fields_per_block = bytes_per_block / width_bytes[spec[i].size]; - int block_width = (spec[i].field_width + 1) * fields_per_block; + unsigned int block_width = (spec[i].field_width + 1) * fields_per_block; if (width_per_block < block_width) width_per_block = block_width; } diff --git a/src/pathchk.c b/src/pathchk.c index 5dbc7da..5261345 100644 --- a/src/pathchk.c +++ b/src/pathchk.c @@ -1,5 +1,5 @@ /* pathchk -- check whether file names are valid or portable - Copyright (C) 1991-2008 Free Software Foundation, Inc. + Copyright (C) 1991-2009 Free Software Foundation, Inc. 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 @@ -323,7 +323,7 @@ validate_file_name (char *file, bool check_basic_portability, dir); return false; } - maxsize = MIN (size, SIZE_MAX); + maxsize = MIN (size, SSIZE_MAX); } if (maxsize <= filelen) @@ -385,7 +385,7 @@ validate_file_name (char *file, bool check_basic_portability, len = pathconf (dir, _PC_NAME_MAX); *start = c; if (0 <= len) - name_max = MIN (len, SIZE_MAX); + name_max = MIN (len, SSIZE_MAX); else switch (errno) { diff --git a/src/pr.c b/src/pr.c index d2b6714..308a025 100644 --- a/src/pr.c +++ b/src/pr.c @@ -1,5 +1,5 @@ /* pr -- convert text files for printing. - Copyright (C) 88, 91, 1995-2008 Free Software Foundation, Inc. + Copyright (C) 88, 91, 1995-2009 Free Software Foundation, Inc. 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 @@ -455,7 +455,7 @@ static char *buff; /* Index of the position in buff where the next character will be stored. */ -static int buff_current; +static unsigned int buff_current; /* The number of characters in buff. Used for allocation of buff and to detect overflow of buff. */ @@ -1944,8 +1944,8 @@ static void store_columns (void) { int i, j; - int line = 0; - int buff_start; + unsigned int line = 0; + unsigned int buff_start; int last_col; /* The rightmost column which will be saved in buff */ COLUMN *p; diff --git a/src/ptx.c b/src/ptx.c index c04c90c..8818c03 100644 --- a/src/ptx.c +++ b/src/ptx.c @@ -1,5 +1,5 @@ /* Permuted index for GNU, with keywords in their context. - Copyright (C) 1990, 1991, 1993, 1998-2008 Free Software Foundation, Inc. + Copyright (C) 1990, 1991, 1993, 1998-2009 Free Software Foundation, Inc. François Pinard <pin...@iro.umontreal.ca>, 1988. This program is free software: you can redistribute it and/or modify @@ -541,11 +541,11 @@ swallow_file_in_memory (const char *file_name, BLOCK *block) { size_t in_memory_size; - block->start = xmalloc ((size_t) stat_block.st_size); + block->start = xmalloc (ST_SIZE (stat_block)); if ((in_memory_size = read (file_handle, - block->start, (size_t) stat_block.st_size)) - != stat_block.st_size) + block->start, ST_SIZE (stat_block))) + != ST_SIZE (stat_block)) { #if MSDOS /* On MSDOS, in memory size may be smaller than the file @@ -554,7 +554,7 @@ swallow_file_in_memory (const char *file_name, BLOCK *block) minimum is when all lines are empty and terminated by CR+LF. */ if (in_memory_size != (size_t)-1 - && in_memory_size >= stat_block.st_size / 2) + && in_memory_size >= ST_SIZE (stat_block) / 2) block->start = xrealloc (block->start, in_memory_size); else #endif /* not MSDOS */ diff --git a/src/shred.c b/src/shred.c index 1e7bffb..224f671 100644 --- a/src/shred.c +++ b/src/shred.c @@ -1,6 +1,6 @@ /* shred.c - overwrite files and devices to make it harder to recover data - Copyright (C) 1999-2008 Free Software Foundation, Inc. + Copyright (C) 1999-2009 Free Software Foundation, Inc. Copyright (C) 1997, 1998, 1999 Colin Plumb. This program is free software: you can redistribute it and/or modify @@ -399,7 +399,7 @@ dopass (int fd, char const *qname, off_t *sizep, int type, /* Constant fill patterns need only be set up once. */ if (type >= 0) { - lim = (0 <= size && size < sizeof_r ? size : sizeof r); + lim = (0 <= size && size < sizeof_r ? size : sizeof_r); fillpattern (type, r.u, lim); passname (r.u, pass_string); } @@ -488,7 +488,7 @@ dopass (int fd, char const *qname, off_t *sizep, int type, /* Okay, we have written "soff" bytes. */ - if (offset + soff < offset) + if (offset > OFF_T_MAX - (off_t) soff) { error (0, 0, _("%s: file too large"), qname); return -1; diff --git a/src/shuf.c b/src/shuf.c index 977eedc..0c9c562 100644 --- a/src/shuf.c +++ b/src/shuf.c @@ -1,6 +1,6 @@ /* Shuffle lines of text. - Copyright (C) 2006, 2007-2008 Free Software Foundation, Inc. + Copyright (C) 2006, 2007-2009 Free Software Foundation, Inc. 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 @@ -160,11 +160,11 @@ read_input (FILE *in, char eolbyte, char ***pline) if (fstat (fileno (in), &instat) == 0 && S_ISREG (instat.st_mode)) { - off_t file_size = instat.st_size; + off_t file_size = ST_SIZE (instat); off_t current_offset = ftello (in); if (0 <= current_offset) { - off_t remaining_size = + uintmax_t remaining_size = (current_offset < file_size ? file_size - current_offset : 0); if (SIZE_MAX - 2 < remaining_size) xalloc_die (); diff --git a/src/sort.c b/src/sort.c index f438563..df466e9 100644 --- a/src/sort.c +++ b/src/sort.c @@ -1,5 +1,5 @@ /* sort - sort lines of text (with all kinds of options). - Copyright (C) 1988, 1991-2008 Free Software Foundation, Inc. + Copyright (C) 1988, 1991-2009 Free Software Foundation, Inc. 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 @@ -1281,7 +1281,7 @@ sort_buffer_size (FILE *const *fps, size_t nfps, for (i = 0; i < nfiles; i++) { struct stat st; - off_t file_size; + uintmax_t file_size; size_t worst_case; if ((i < nfps ? fstat (fileno (fps[i]), &st) @@ -1291,7 +1291,7 @@ sort_buffer_size (FILE *const *fps, size_t nfps, die (_("stat failed"), files[i]); if (S_ISREG (st.st_mode)) - file_size = st.st_size; + file_size = ST_SIZE (st); else { /* The file has unknown size. If the user specified a sort diff --git a/src/stat.c b/src/stat.c index feea4b7..e084b18 100644 --- a/src/stat.c +++ b/src/stat.c @@ -573,7 +573,7 @@ print_stat (char *pformat, size_t prefix_len, char m, out_string (pformat, prefix_len, quote (filename)); if (S_ISLNK (statbuf->st_mode)) { - char *linkname = areadlink_with_size (filename, statbuf->st_size); + char *linkname = areadlink_with_size (filename, ST_SIZE (*statbuf)); if (linkname == NULL) { error (0, errno, _("cannot read symbolic link %s"), @@ -633,7 +633,7 @@ print_stat (char *pformat, size_t prefix_len, char m, out_uint_x (pformat, prefix_len, minor (statbuf->st_rdev)); break; case 's': - out_uint (pformat, prefix_len, statbuf->st_size); + out_uint (pformat, prefix_len, ST_SIZE (*statbuf)); break; case 'B': out_uint (pformat, prefix_len, ST_NBLOCKSIZE); diff --git a/src/system.h b/src/system.h index 020f83b..0d97082 100644 --- a/src/system.h +++ b/src/system.h @@ -1,5 +1,5 @@ /* system-dependent definitions for coreutils - Copyright (C) 1989, 1991-2008 Free Software Foundation, Inc. + Copyright (C) 1989, 1991-2009 Free Software Foundation, Inc. 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 @@ -172,20 +172,22 @@ enum # define DEV_BSIZE 4096 #endif -/* Extract or fake data from a `struct stat'. +/* Extract or fake unsigned data from a `struct stat'. + ST_SIZE: Number of bytes in the file, assumed >= 0. 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. */ +#define ST_SIZE(statbuf) ((uintmax_t) (statbuf).st_size) #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) \ - ((statbuf).st_size / ST_NBLOCKSIZE + ((statbuf).st_size % ST_NBLOCKSIZE != 0)) + (ST_SIZE(statbuf) / ST_NBLOCKSIZE + (ST_SIZE(statbuf) % ST_NBLOCKSIZE != 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) + ? (uintmax_t) st_blocks (ST_SIZE(statbuf)) : 0) # endif /* !_POSIX_SOURCE && BSIZE */ #else /* HAVE_STRUCT_STAT_ST_BLOCKS */ /* Some systems, like Sequents, return st_blksize of 0 on pipes. @@ -197,9 +199,9 @@ enum suffice, since "cat" sometimes multiplies the result by 4.) If anyone knows of a system for which this limit is too small, please report it as a bug in this code. */ -# define ST_BLKSIZE(statbuf) ((0 < (statbuf).st_blksize \ - && (statbuf).st_blksize <= SIZE_MAX / 8 + 1) \ - ? (statbuf).st_blksize : DEV_BSIZE) +# define ST_BLKSIZE(statbuf) (((statbuf).st_blksize && (uintmax_t) \ + (statbuf).st_blksize <= SIZE_MAX / 8 + 1) \ + ? (uintmax_t) (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 file systems with NFS. */ @@ -220,7 +222,7 @@ enum #endif /* HAVE_STRUCT_STAT_ST_BLOCKS */ #ifndef ST_NBLOCKS -# define ST_NBLOCKS(statbuf) ((statbuf).st_blocks) +# define ST_NBLOCKS(statbuf) ((uintmax_t) (statbuf).st_blocks) #endif #ifndef ST_NBLOCKSIZE diff --git a/src/tac.c b/src/tac.c index be8f3ab..7b19c16 100644 --- a/src/tac.c +++ b/src/tac.c @@ -1,5 +1,5 @@ /* tac - concatenate and print files in reverse - Copyright (C) 1988-1991, 1995-2006, 2008 Free Software Foundation, Inc. + Copyright (C) 1988-1991, 1995-2006, 2009 Free Software Foundation, Inc. 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 @@ -205,7 +205,7 @@ tac_seekable (int input_fd, const char *file) size_t saved_record_size; /* Offset in the file of the next read. */ - off_t file_pos; + uintmax_t file_pos; /* True if `output' has not been called yet for any file. Only used when the separator is attached to the preceding record. */ @@ -215,8 +215,8 @@ tac_seekable (int input_fd, const char *file) size_t match_length1 = match_length - 1; /* Speed optimization, non-regexp. */ /* Find the size of the input file. */ - file_pos = lseek (input_fd, (off_t) 0, SEEK_END); - if (file_pos < 1) + file_pos = lseek (input_fd, 0, SEEK_END); + if ((off_t) file_pos < 1) return true; /* It's an empty file. */ /* Arrange for the first read to lop off enough to leave the rest of the @@ -546,7 +546,7 @@ tac_file (const char *filename) } } - file_size = lseek (fd, (off_t) 0, SEEK_END); + file_size = lseek (fd, 0, SEEK_END); ok = (file_size < 0 || isatty (fd) ? tac_nonseekable (fd, filename) diff --git a/src/tail.c b/src/tail.c index fe34600..b092db4 100644 --- a/src/tail.c +++ b/src/tail.c @@ -100,7 +100,7 @@ struct File_spec int fd; /* Attributes of the file the last time we checked. */ - off_t size; + uintmax_t size; struct timespec mtime; dev_t dev; ino_t ino; @@ -1040,7 +1040,7 @@ tail_forever (struct File_spec *f, int nfiles, double sleep_interval) } if (f[i].mode == stats.st_mode - && (! S_ISREG (stats.st_mode) || f[i].size == stats.st_size) + && (! S_ISREG (stats.st_mode) || f[i].size == ST_SIZE (stats)) && timespec_cmp (f[i].mtime, get_stat_mtime (&stats)) == 0) { if ((max_n_unchanged_stats_between_opens @@ -1062,12 +1062,12 @@ tail_forever (struct File_spec *f, int nfiles, double sleep_interval) /* reset counter */ f[i].n_unchanged_stats = 0; - if (S_ISREG (mode) && stats.st_size < f[i].size) + if (S_ISREG (mode) && ST_SIZE (stats) < f[i].size) { error (0, 0, _("%s: file truncated"), name); last = i; - xlseek (fd, stats.st_size, SEEK_SET, name); - f[i].size = stats.st_size; + xlseek (fd, ST_SIZE (stats), SEEK_SET, name); + f[i].size = ST_SIZE (stats); continue; } @@ -1336,7 +1336,7 @@ tail_file (struct File_spec *f, uintmax_t n_units) } else { - /* Note: we must use read_pos here, not stats.st_size, + /* Note: we must use read_pos here, not ST_SIZE(stats), to avoid a race condition described by Ken Raeburn: http://mail.gnu.org/archive/html/bug-textutils/2003-05/msg00007.html */ record_open_fd (f, fd, read_pos, &stats, (is_stdin ? -1 : 1)); diff --git a/src/test.c b/src/test.c index 14d20fd..1f6355e 100644 --- a/src/test.c +++ b/src/test.c @@ -435,7 +435,7 @@ unary_operator (void) case 's': /* File has something in it? */ unary_advance (); return (stat (argv[pos - 1], &stat_buf) == 0 - && 0 < stat_buf.st_size); + && ST_SIZE (stat_buf)); case 'S': /* File is a socket? */ unary_advance (); diff --git a/src/wc.c b/src/wc.c index b1afe14..d82a2b2 100644 --- a/src/wc.c +++ b/src/wc.c @@ -214,7 +214,7 @@ wc (int fd, char const *file_x, struct fstatus *fstatus) overhead. If FD is a `regular' Unix file, using lseek is enough to get its `size' in bytes. Otherwise, read blocks of BUFFER_SIZE bytes at a time until EOF. Note that the `size' (number of bytes) - that wc reports is smaller than stats.st_size when the file is not + that wc reports is smaller than ST_SIZE(stats) when the file is not positioned at its beginning. That's why the lseek calls below are necessary. For example the command `(dd ibs=99k skip=1 count=0; ./wc -c) < /etc/group' @@ -564,7 +564,7 @@ compute_number_width (int nfiles, struct fstatus const *fstatus) if (! fstatus[i].failed) { if (S_ISREG (fstatus[i].st.st_mode)) - regular_total += fstatus[i].st.st_size; + regular_total += ST_SIZE (fstatus[i].st); else minimum_width = 7; } @@ -672,7 +672,7 @@ main (int argc, char **argv) struct stat st; if (fstat (fileno (stream), &st) == 0 && S_ISREG (st.st_mode) - && st.st_size <= MIN (10 * 1024 * 1024, physmem_available () / 2)) + && ST_SIZE (st) <= MIN (10 * 1024 * 1024, physmem_available () / 2)) { read_tokens = true; readtokens0_init (&tok); -- 1.5.3.6 _______________________________________________ Bug-coreutils mailing list Bug-coreutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-coreutils