Re: ls: match historic behavior listing empty directories

2020-10-07 Thread Klemens Nanni
On Sat, Oct 03, 2020 at 09:21:21AM -0600, Todd C. Miller wrote:
> This is adapted from FreeBSD revs 130236 and 130237 which have the
> following log message:
> 
> If we are asked to print the total number of blocks, do so even if we
> have no entries to print (either due to an empty directory or an
> error).  This makes the -l and -s options more consistent, like
> Solaris and (Debian) Linux.  To make this happen, tweak two
> optimizations on the second call to display():
> 
> - Don't skip display() altogether, even if list == NULL.
> - Don't skip the call to the printfn in display() if we
>   need to print the total.
> 
> I've verified that both historic AT&T ls and GNU ls behave this
> way.
OK kn



Re: ls: match historic behavior listing empty directories

2020-10-07 Thread Todd C . Miller
Anyone?

 - todd

> This is adapted from FreeBSD revs 130236 and 130237 which have the
> following log message:
>
> If we are asked to print the total number of blocks, do so even if we
> have no entries to print (either due to an empty directory or an
> error).  This makes the -l and -s options more consistent, like
> Solaris and (Debian) Linux.  To make this happen, tweak two
> optimizations on the second call to display():
>
> - Don't skip display() altogether, even if list == NULL.
> - Don't skip the call to the printfn in display() if we
>   need to print the total.
>
> I've verified that both historic AT&T ls and GNU ls behave this
> way.
>
>  - todd
>
> Index: bin/ls/ls.c
> ===
> RCS file: /cvs/src/bin/ls/ls.c,v
> retrieving revision 1.53
> diff -u -p -u -r1.53 ls.c
> --- bin/ls/ls.c   6 Jul 2020 00:55:05 -   1.53
> +++ bin/ls/ls.c   3 Oct 2020 15:18:01 -
> @@ -355,7 +355,13 @@ traverse(int argc, char *argv[], int opt
>   fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL)
>   err(1, NULL);
>  
> - display(NULL, fts_children(ftsp, 0));
> + /*
> +  * We ignore errors from fts_children here since they will be
> +  * replicated and signalled on the next call to fts_read() below.
> +  */
> + chp = fts_children(ftsp, 0);
> + if (chp != NULL)
> + display(NULL, chp);
>   if (f_listdir)
>   return;
>  
> @@ -438,16 +444,6 @@ display(FTSENT *p, FTSENT *list)
>   char buf[21];   /* 64 bits == 20 digits */
>   char *flags = NULL;
>  
> - /*
> -  * If list is NULL there are two possibilities: that the parent
> -  * directory p has no children, or that fts_children() returned an
> -  * error.  We ignore the error case since it will be replicated
> -  * on the next call to fts_read() on the post-order visit to the
> -  * directory p, and will be signalled in traverse().
> -  */
> - if (list == NULL)
> - return;
> -
>   needstats = f_inode || f_longform || f_size;
>   flen = 0;
>   btotal = maxblock = maxinode = maxlen = maxnlink = 0;
> @@ -542,7 +538,13 @@ display(FTSENT *p, FTSENT *list)
>   ++entries;
>   }
>  
> - if (!entries)
> + /*
> +  * If there are no entries to display, we normally stop right
> +  * here.  However, we must continue if we have to display the
> +  * total block count.  In this case, we display the total only
> +  * on the second (p != NULL) pass.
> +  */
> + if (!entries && (!(f_longform || f_size) || p == NULL))
>   return;
>  
>   d.list = list;
> Index: bin/ls/print.c
> ===
> RCS file: /cvs/src/bin/ls/print.c,v
> retrieving revision 1.38
> diff -u -p -u -r1.38 print.c
> --- bin/ls/print.c5 Feb 2019 02:17:32 -   1.38
> +++ bin/ls/print.c3 Oct 2020 15:13:14 -
> @@ -87,7 +87,8 @@ printlong(DISPLAY *dp)
>   NAMES *np;
>   char buf[20];
>  
> - if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
> + if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
> + (f_longform || f_size))
>   (void)printf("total %llu\n", howmany(dp->btotal, blocksize));
>  
>   for (p = dp->list; p; p = p->fts_link) {
> @@ -198,7 +199,8 @@ printcol(DISPLAY *dp)
>   if (num % numcols)
>   ++numrows;
>  
> - if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
> + if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
> + (f_longform || f_size))
>   (void)printf("total %llu\n", howmany(dp->btotal, blocksize));
>   for (row = 0; row < numrows; ++row) {
>   for (base = row, col = 0;;) {
> @@ -271,7 +273,8 @@ printacol(DISPLAY *dp)
>   if ( (colwidth = compute_columns(dp, &numcols)) == 0)
>   return;
>  
> - if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
> + if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
> + (f_longform || f_size))
>   (void)printf("total %llu\n", howmany(dp->btotal, blocksize));
>   col = 0;
>   for (p = dp->list; p; p = p->fts_link) {
>



ls: match historic behavior listing empty directories

2020-10-03 Thread Todd C . Miller
This is adapted from FreeBSD revs 130236 and 130237 which have the
following log message:

If we are asked to print the total number of blocks, do so even if we
have no entries to print (either due to an empty directory or an
error).  This makes the -l and -s options more consistent, like
Solaris and (Debian) Linux.  To make this happen, tweak two
optimizations on the second call to display():

- Don't skip display() altogether, even if list == NULL.
- Don't skip the call to the printfn in display() if we
  need to print the total.

I've verified that both historic AT&T ls and GNU ls behave this
way.

 - todd

Index: bin/ls/ls.c
===
RCS file: /cvs/src/bin/ls/ls.c,v
retrieving revision 1.53
diff -u -p -u -r1.53 ls.c
--- bin/ls/ls.c 6 Jul 2020 00:55:05 -   1.53
+++ bin/ls/ls.c 3 Oct 2020 15:18:01 -
@@ -355,7 +355,13 @@ traverse(int argc, char *argv[], int opt
fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL)
err(1, NULL);
 
-   display(NULL, fts_children(ftsp, 0));
+   /*
+* We ignore errors from fts_children here since they will be
+* replicated and signalled on the next call to fts_read() below.
+*/
+   chp = fts_children(ftsp, 0);
+   if (chp != NULL)
+   display(NULL, chp);
if (f_listdir)
return;
 
@@ -438,16 +444,6 @@ display(FTSENT *p, FTSENT *list)
char buf[21];   /* 64 bits == 20 digits */
char *flags = NULL;
 
-   /*
-* If list is NULL there are two possibilities: that the parent
-* directory p has no children, or that fts_children() returned an
-* error.  We ignore the error case since it will be replicated
-* on the next call to fts_read() on the post-order visit to the
-* directory p, and will be signalled in traverse().
-*/
-   if (list == NULL)
-   return;
-
needstats = f_inode || f_longform || f_size;
flen = 0;
btotal = maxblock = maxinode = maxlen = maxnlink = 0;
@@ -542,7 +538,13 @@ display(FTSENT *p, FTSENT *list)
++entries;
}
 
-   if (!entries)
+   /*
+* If there are no entries to display, we normally stop right
+* here.  However, we must continue if we have to display the
+* total block count.  In this case, we display the total only
+* on the second (p != NULL) pass.
+*/
+   if (!entries && (!(f_longform || f_size) || p == NULL))
return;
 
d.list = list;
Index: bin/ls/print.c
===
RCS file: /cvs/src/bin/ls/print.c,v
retrieving revision 1.38
diff -u -p -u -r1.38 print.c
--- bin/ls/print.c  5 Feb 2019 02:17:32 -   1.38
+++ bin/ls/print.c  3 Oct 2020 15:13:14 -
@@ -87,7 +87,8 @@ printlong(DISPLAY *dp)
NAMES *np;
char buf[20];
 
-   if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
+   if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
+   (f_longform || f_size))
(void)printf("total %llu\n", howmany(dp->btotal, blocksize));
 
for (p = dp->list; p; p = p->fts_link) {
@@ -198,7 +199,8 @@ printcol(DISPLAY *dp)
if (num % numcols)
++numrows;
 
-   if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
+   if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
+   (f_longform || f_size))
(void)printf("total %llu\n", howmany(dp->btotal, blocksize));
for (row = 0; row < numrows; ++row) {
for (base = row, col = 0;;) {
@@ -271,7 +273,8 @@ printacol(DISPLAY *dp)
if ( (colwidth = compute_columns(dp, &numcols)) == 0)
return;
 
-   if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
+   if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
+   (f_longform || f_size))
(void)printf("total %llu\n", howmany(dp->btotal, blocksize));
col = 0;
for (p = dp->list; p; p = p->fts_link) {