bug-coreutils
[Top][All Lists]
Advanced

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

ls layout bug with multibyte decimal points and human-readable output


From: Paul Eggert
Subject: ls layout bug with multibyte decimal points and human-readable output
Date: Sun, 26 Sep 2004 00:14:06 -0700
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

I installed this:

2004-09-25  Paul Eggert  <address@hidden>

        * src/ls.c (gobble_file, print_long_format): Don't assume that
        human-readable output has a byte count equal to its column width;
        this isn't always true in locales where the radix character is not
        '.' or ','.
        (format_user_or_group): Revamp code to match the above fix;
        this avoids the (very faint) possibility of integer overflow.
        
Index: ls.c
===================================================================
RCS file: /fetish/cu/src/ls.c,v
retrieving revision 1.361
retrieving revision 1.363
diff -p -u -r1.361 -r1.363
--- ls.c        22 Sep 2004 19:47:38 -0000      1.361
+++ ls.c        26 Sep 2004 07:10:53 -0000      1.363
@@ -2545,8 +2545,9 @@ gobble_file (const char *name, enum file
       blocks = ST_NBLOCKS (f->stat);
       {
        char buf[LONGEST_HUMAN_READABLE + 1];
-       int len = strlen (human_readable (blocks, buf, human_output_opts,
-                                         ST_NBLOCKSIZE, output_block_size));
+       int len = mbswidth (human_readable (blocks, buf, human_output_opts,
+                                           ST_NBLOCKSIZE, output_block_size),
+                           0);
        if (block_size_width < len)
          block_size_width = len;
       }
@@ -2596,8 +2597,9 @@ gobble_file (const char *name, enum file
        {
          char buf[LONGEST_HUMAN_READABLE + 1];
          uintmax_t size = unsigned_file_size (f->stat.st_size);
-         int len = strlen (human_readable (size, buf, human_output_opts,
-                                           1, file_output_block_size));
+         int len = mbswidth (human_readable (size, buf, human_output_opts,
+                                             1, file_output_block_size),
+                             0);
          if (file_size_width < len)
            file_size_width = len;
        }
@@ -3051,17 +3053,14 @@ format_user_or_group (char const *name, 
 
   if (name)
     {
-      /* The output column count may differ from the byte count.
-        Adjust for this, but don't output garbage if integer overflow
-        occurs during adjustment.  */
-      len = strlen (name);
-      width -= mbswidth (name, 0);
-      width += len;
-      if (width < 0)
-       width = 0;
-      printf ("%-*s ", width, name);
-      if (len < width)
-       len = width;
+      int width_gap = width - mbswidth (name, 0);
+      int pad = MAX (0, width_gap);
+      fputs (name, stdout);
+      len = strlen (name) + pad;
+
+      do
+       putchar (' ');
+      while (pad--);
     }
   else
     {
@@ -3184,10 +3183,15 @@ print_long_format (const struct fileinfo
   if (print_block_size)
     {
       char hbuf[LONGEST_HUMAN_READABLE + 1];
-      sprintf (p, "%*s ", block_size_width,
-              human_readable (ST_NBLOCKS (f->stat), hbuf, human_output_opts,
-                              ST_NBLOCKSIZE, output_block_size));
-      p += block_size_width + 1;
+      char const *blocks =
+       human_readable (ST_NBLOCKS (f->stat), hbuf, human_output_opts,
+                       ST_NBLOCKSIZE, output_block_size);
+      int pad;
+      for (pad = block_size_width - mbswidth (blocks, 0); 0 < pad; pad--)
+       *p++ = ' ';
+      while ((*p++ = *blocks++))
+       continue;
+      p[-1] = ' '; 
     }
 
   /* The last byte of the mode string is the POSIX
@@ -3229,18 +3233,22 @@ print_long_format (const struct fileinfo
               umaxtostr (major (f->stat.st_rdev), majorbuf),
               minor_device_number_width,
               umaxtostr (minor (f->stat.st_rdev), minorbuf));
+      p += file_size_width + 1;
     }
   else
     {
       char hbuf[LONGEST_HUMAN_READABLE + 1];
-      uintmax_t size = unsigned_file_size (f->stat.st_size);
-      sprintf (p, "%*s ", file_size_width,
-              human_readable (size, hbuf, human_output_opts,
-                              1, file_output_block_size));
+      char const *size =
+       human_readable (unsigned_file_size (f->stat.st_size),
+                       hbuf, human_output_opts, 1, file_output_block_size);
+      int pad;
+      for (pad = file_size_width - mbswidth (size, 0); 0 < pad; pad--)
+       *p++ = ' ';
+      while ((*p++ = *size++))
+       continue;
+      p[-1] = ' ';
     }
 
-  p += file_size_width + 1;
-
   if ((when_local = localtime (&when)))
     {
       time_t six_months_ago;




reply via email to

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