* lib/fts.c (fts_read, fts_build): When enter_dir or setup_dir
fails, report its errno value back to the user.
(internal_function): Preserve errno.
* modules/fts (Depends-on): Add calloc-posix, free-posix,
malloc-posix, and realloc-posix, for better errno handling
on allocation failures.
---
 ChangeLog   |  8 ++++++++
 lib/fts.c   | 12 ++++++------
 modules/fts |  4 ++++
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3a03afaea1..ae6a1b08f4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2023-08-13  Paul Eggert  <egg...@cs.ucla.edu>
 
+       fts: improve memory-allocation errno handling
+       * lib/fts.c (fts_read, fts_build): When enter_dir or setup_dir
+       fails, report its errno value back to the user.
+       (internal_function): Preserve errno.
+       * modules/fts (Depends-on): Add calloc-posix, free-posix,
+       malloc-posix, and realloc-posix, for better errno handling
+       on allocation failures.
+
        hash: set errno on failure
        * lib/hash.c: Include errno.h.
        (compute_bucket_size, hash_initialize, hash_rehash)
diff --git a/lib/fts.c b/lib/fts.c
index 875fe05793..faeb4b20a5 100644
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -981,7 +981,6 @@ next:   tmp = p;
                         fts_load(sp, p);
                         if (! setup_dir(sp)) {
                                 free_dir(sp);
-                                __set_errno (ENOMEM);
                                 return (NULL);
                         }
                         goto check_for_dir;
@@ -1028,10 +1027,7 @@ check_for_dir:
                       sp->fts_dev = p->fts_statp->st_dev;
                     Dprintf (("  entering: %s\n", p->fts_path));
                     if (! enter_dir (sp, p))
-                      {
-                        __set_errno (ENOMEM);
-                        return NULL;
-                      }
+                      return NULL;
                   }
                 return p;
         }
@@ -1348,8 +1344,9 @@ fts_build (register FTS *sp, int type)
                   cur->fts_info = FTS_D;
                 else if (! enter_dir (sp, cur))
                   {
+                    int err = errno;
                     closedir_and_clear (cur->fts_dirp);
-                    __set_errno (ENOMEM);
+                    __set_errno (err);
                     return NULL;
                   }
               }
@@ -1937,6 +1934,7 @@ internal_function
 fts_lfree (register FTSENT *head)
 {
         register FTSENT *p;
+        int err = errno;
 
         /* Free a linked list of structures. */
         while ((p = head)) {
@@ -1945,6 +1943,8 @@ fts_lfree (register FTSENT *head)
                         closedir (p->fts_dirp);
                 free(p);
         }
+
+        __set_errno (err);
 }
 
 /*
diff --git a/modules/fts b/modules/fts
index fe56bae6e0..b754e0f572 100644
--- a/modules/fts
+++ b/modules/fts
@@ -11,6 +11,7 @@ Depends-on:
 alignasof
 attribute
 c99
+calloc-posix
 closedir
 cycle-check
 d-ino
@@ -19,16 +20,19 @@ fchdir
 fcntl
 fcntl-h
 flexmember
+free-posix
 fstat
 hash
 i-ring
 lstat
+malloc-posix
 memmove
 open
 openat-h
 opendir
 opendirat
 readdir
+realloc-posix
 stdbool
 stddef
 stdint
-- 
2.39.2


Reply via email to