bug-gnulib
[Top][All Lists]
Advanced

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

[PATCH 2/6] fts: nlink_t signedness fixups


From: Paul Eggert
Subject: [PATCH 2/6] fts: nlink_t signedness fixups
Date: Tue, 25 Jul 2017 00:28:02 -0700

* lib/fts.c (fts_open): Set rootparent n_dirs_remaining to -1
so that root need not be a special case later.
(fts_read): Remove now-redundant test for fts_level.
Do not assume that nlink_t is signed.
(fts_build): Remove useless decrement of nlinks.
(fts_stat): Avoid unlikely signed integer overflow later, if
nlink_t is signed.
---
 ChangeLog  |  9 +++++++++
 lib/fts.c  | 26 +++++++++-----------------
 lib/fts_.h |  6 +++++-
 3 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 05ac15d93..da1fda1ad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2017-07-24  Paul Eggert  <address@hidden>
 
+       fts: nlink_t signedness fixups
+       * lib/fts.c (fts_open): Set rootparent n_dirs_remaining to -1
+       so that root need not be a special case later.
+       (fts_read): Remove now-redundant test for fts_level.
+       Do not assume that nlink_t is signed.
+       (fts_build): Remove useless decrement of nlinks.
+       (fts_stat): Avoid unlikely signed integer overflow later, if
+       nlink_t is signed.
+
        fts-tests: new module
        * modules/fts-tests, tests/test-fts.c: New files.
 
diff --git a/lib/fts.c b/lib/fts.c
index 3bac3244e..d5fc051a0 100644
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -479,6 +479,7 @@ fts_open (char * const *argv,
                 if ((parent = fts_alloc(sp, "", 0)) == NULL)
                         goto mem2;
                 parent->fts_level = FTS_ROOTPARENTLEVEL;
+                parent->fts_n_dirs_remaining = -1;
           }
 
         /* The classic fts implementation would call fts_stat with
@@ -1024,10 +1025,7 @@ check_for_dir:
                     if (p->fts_statp->st_size == FTS_STAT_REQUIRED)
                       {
                         FTSENT *parent = p->fts_parent;
-                        if (FTS_ROOTLEVEL < p->fts_level
-                            /* ->fts_n_dirs_remaining is not valid
-                               for command-line-specified names.  */
-                            && parent->fts_n_dirs_remaining == 0
+                        if (parent->fts_n_dirs_remaining == 0
                             && ISSET(FTS_NOSTAT)
                             && ISSET(FTS_PHYSICAL)
                             && link_count_optimize_ok (parent))
@@ -1039,7 +1037,8 @@ check_for_dir:
                             p->fts_info = fts_stat(sp, p, false);
                             if (S_ISDIR(p->fts_statp->st_mode)
                                 && p->fts_level != FTS_ROOTLEVEL
-                                && parent->fts_n_dirs_remaining)
+                                && 0 < parent->fts_n_dirs_remaining
+                                && parent->fts_n_dirs_remaining != (nlink_t) 
-1)
                                   parent->fts_n_dirs_remaining--;
                           }
                       }
@@ -1468,7 +1467,6 @@ fts_build (register FTS *sp, int type)
         tail = NULL;
         nitems = 0;
         while (cur->fts_dirp) {
-                bool is_dir;
                 size_t d_namelen;
                 __set_errno (0);
                 struct dirent *dp = readdir(cur->fts_dirp);
@@ -1569,19 +1567,10 @@ mem1:                           saved_errno = errno;
                            to caller, when possible.  */
                         set_stat_type (p->fts_statp, D_TYPE (dp));
                         fts_set_stat_required(p, !skip_stat);
-                        is_dir = (ISSET(FTS_PHYSICAL)
-                                  && DT_MUST_BE(dp, DT_DIR));
                 } else {
                         p->fts_info = fts_stat(sp, p, false);
-                        is_dir = (p->fts_info == FTS_D
-                                  || p->fts_info == FTS_DC
-                                  || p->fts_info == FTS_DOT);
                 }
 
-                /* Decrement link count if applicable. */
-                if (nlinks > 0 && is_dir)
-                        nlinks -= nostat;
-
                 /* We walk in directory order so "ls -f" doesn't get upset. */
                 p->fts_link = NULL;
                 if (head == NULL)
@@ -1844,8 +1833,11 @@ err:            memset(sbp, 0, sizeof(struct stat));
         }
 
         if (S_ISDIR(sbp->st_mode)) {
-                p->fts_n_dirs_remaining = (sbp->st_nlink
-                                           - (ISSET(FTS_SEEDOT) ? 0 : 2));
+                p->fts_n_dirs_remaining
+                  = ((sbp->st_nlink < 2
+                      || p->fts_level <= FTS_ROOTLEVEL)
+                     ? -1
+                     : sbp->st_nlink - (ISSET (FTS_SEEDOT) ? 0 : 2));
                 if (ISDOT(p->fts_name)) {
                         /* Command-line "." and ".." are real directories. */
                         return (p->fts_level == FTS_ROOTLEVEL ? FTS_D : 
FTS_DOT);
diff --git a/lib/fts_.h b/lib/fts_.h
index 46fd0df52..e8346dafb 100644
--- a/lib/fts_.h
+++ b/lib/fts_.h
@@ -220,7 +220,11 @@ typedef struct _ftsent {
         ptrdiff_t fts_level;            /* depth (-1 to N) */
 
         size_t fts_namelen;             /* strlen(fts_name) */
-        nlink_t fts_n_dirs_remaining;   /* count down from st_nlink */
+
+        /* If not (nlink_t) -1, an upper bound on the number of
+           remaining subdirectories of interest.  If this becomes
+           zero, some work can be avoided.  */
+        nlink_t fts_n_dirs_remaining;
 
 # define FTS_D           1              /* preorder directory */
 # define FTS_DC          2              /* directory that causes cycles */
-- 
2.13.3




reply via email to

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