bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: stat signed/unsigned


From: Pádraig Brady
Subject: Re: stat signed/unsigned
Date: Fri, 9 Jan 2009 11:12:29 +0000
User-agent: Thunderbird 2.0.0.6 (X11/20071008)

Paul Eggert wrote:
> Pádraig Brady <address@hidden> 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?= <address@hidden>
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 <address@hidden>, 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






reply via email to

[Prev in Thread] Current Thread [Next in Thread]