Hi Crystal,

Crystal Kolipe wrote on Tue, Oct 03, 2023 at 06:47:42PM -0300:

> Two display format bugs seems to have crept in to ls due to the
> addition of scaled human readable values and large minor numbers.

I think you are right that the current situation isn't good.
Thank you for bringing this up.

In general, ls(1) strives to dynamically determine the required
column width.  It already does that for the file size column.
Given that device numbers use the same column, i think the solution
that is cleanest, most robust, most aesthetically pleasing, least
wasteful with respect to space, and easiest to maintain is simply
doing the same for device numbers, see the patch below.

Two remarks:
 * The reason for keeping the local variable "bcfile" is that
   (0, 0) represents a valid device (console).  There is no
   good reason why it should be in the DISPLAY struct, though.
 * The line "d.s_major = d.s_minor = 3;" is likely redundant because
   with bcfile == 0, nothing is supposed to use these fields.
   While local variables should only be initialized when needed, i
   think defensive programming recommends keeping data that is used
   by (even internal) APIs initialized to reasonable values rather
   than having random memory content lying around.  That reduces
   the risk of future code changes in *other* modules accidentally
   accessing random data, if developers get confused regarding
   which invariants the internal API guarantees or requires.

OK?
  Ingo


   $ cd /dev
   $ ls -l MAKEDEV *vid*                                          
  -r-xr-xr-x  1 root  wheel  12254 Oct  3 07:07 MAKEDEV
  lrwxr-xr-x  1 root  wheel      6 Aug 29  2016 video -> video0
  crw-------  1 root  wheel  44, 0 Oct  3 13:34 video0
  crw-------  1 root  wheel  44, 1 Oct  3 13:34 video1
   $ ls -lh MAKEDEV *vid*
  -r-xr-xr-x  1 root  wheel  12.0K Oct  3 07:07 MAKEDEV
  lrwxr-xr-x  1 root  wheel     6B Aug 29  2016 video -> video0
  crw-------  1 root  wheel  44, 0 Oct  3 13:34 video0
  crw-------  1 root  wheel  44, 1 Oct  3 13:34 video1
   $ ls -l null
  crw-rw-rw-  1 root  wheel  2, 2 Oct  5 00:32 null
   $ ls -l cua00  
  crw-rw----  1 root  dialer  8, 128 Oct  3 13:34 cua00


Index: ls.c
===================================================================
RCS file: /cvs/src/bin/ls/ls.c,v
retrieving revision 1.54
diff -u -p -r1.54 ls.c
--- ls.c        7 Oct 2020 21:03:09 -0000       1.54
+++ ls.c        5 Oct 2023 14:47:37 -0000
@@ -436,6 +436,7 @@ display(FTSENT *p, FTSENT *list)
        unsigned long long btotal;
        blkcnt_t maxblock;
        ino_t maxinode;
+       unsigned int maxmajor, maxminor;
        int bcfile, flen, glen, ulen, maxflags, maxgroup, maxuser, maxlen;
        int entries, needstats;
        int width;
@@ -449,6 +450,7 @@ display(FTSENT *p, FTSENT *list)
        btotal = maxblock = maxinode = maxlen = maxnlink = 0;
        bcfile = 0;
        maxuser = maxgroup = maxflags = 0;
+       maxmajor = maxminor = 0;
        maxsize = 0;
        for (cur = list, entries = 0; cur != NULL; cur = cur->fts_link) {
                if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) {
@@ -523,9 +525,13 @@ display(FTSENT *p, FTSENT *list)
                                (void)strlcpy(np->group, group, glen + 1);
 
                                if (S_ISCHR(sp->st_mode) ||
-                                   S_ISBLK(sp->st_mode))
+                                   S_ISBLK(sp->st_mode)) {
                                        bcfile = 1;
-
+                                       if (maxmajor < major(sp->st_rdev))
+                                               maxmajor = major(sp->st_rdev);
+                                       if (maxminor < minor(sp->st_rdev))
+                                               maxminor = minor(sp->st_rdev);
+                               }
                                if (f_flags) {
                                        np->flags = &np->data[ulen + 1 + glen + 
1];
                                        (void)strlcpy(np->flags, flags, flen + 
1);
@@ -551,7 +557,6 @@ display(FTSENT *p, FTSENT *list)
        d.entries = entries;
        d.maxlen = maxlen;
        if (needstats) {
-               d.bcfile = bcfile;
                d.btotal = btotal;
                (void)snprintf(buf, sizeof(buf), "%llu",
                    (unsigned long long)maxblock);
@@ -570,6 +575,17 @@ display(FTSENT *p, FTSENT *list)
                        d.s_size = strlen(buf);
                } else
                        d.s_size = FMT_SCALED_STRSIZE-2; /* no - or '\0' */
+               d.s_major = d.s_minor = 3;
+               if (bcfile) {
+                       (void)snprintf(buf, sizeof(buf), "%u", maxmajor);
+                       d.s_major = strlen(buf);
+                       (void)snprintf(buf, sizeof(buf), "%u", maxminor);
+                       d.s_minor = strlen(buf);
+                       if (d.s_size <= d.s_major + 2 + d.s_minor)
+                               d.s_size = d.s_major + 2 + d.s_minor;
+                       else
+                               d.s_major = d.s_size - 2 - d.s_minor;
+               }
                d.s_user = maxuser;
        }
 
Index: ls.h
===================================================================
RCS file: /cvs/src/bin/ls/ls.h,v
retrieving revision 1.9
diff -u -p -r1.9 ls.h
--- ls.h        30 May 2013 16:34:32 -0000      1.9
+++ ls.h        5 Oct 2023 14:47:37 -0000
@@ -55,7 +55,6 @@ extern int f_typedir;         /* add type chara
 typedef struct {
        FTSENT *list;
        unsigned long long btotal;
-       int bcfile;
        int entries;
        int maxlen;
        int s_block;
@@ -64,6 +63,8 @@ typedef struct {
        int s_inode;
        int s_nlink;
        int s_size;
+       int s_major;
+       int s_minor;
        int s_user;
 } DISPLAY;
 
Index: print.c
===================================================================
RCS file: /cvs/src/bin/ls/print.c,v
retrieving revision 1.39
diff -u -p -r1.39 print.c
--- print.c     7 Oct 2020 21:03:09 -0000       1.39
+++ print.c     5 Oct 2023 14:47:37 -0000
@@ -110,12 +110,9 @@ printlong(DISPLAY *dp)
                if (f_flags)
                        (void)printf("%-*s ", dp->s_flags, np->flags);
                if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
-                       (void)printf("%3u, %3u ",
-                           major(sp->st_rdev), minor(sp->st_rdev));
-               else if (dp->bcfile)
-                       (void)printf("%*s%*lld ",
-                           8 - dp->s_size, "", dp->s_size,
-                           (long long)sp->st_size);
+                       (void)printf("%*u, %*u ",
+                           dp->s_major, major(sp->st_rdev),
+                           dp->s_minor, minor(sp->st_rdev));
                else
                        printsize(dp->s_size, sp->st_size);
                if (f_accesstime)

Reply via email to