guix_mirror_bot pushed a commit to branch master
in repository guix.

commit 4ce3a53ae5ee832aa92e0345f15780bc7da060d7
Author: Romain GARBAGE <[email protected]>
AuthorDate: Fri Sep 12 16:57:59 2025 +0200

    pack: Address DT_UNKNOWN case for exotic filesystems.
    
    In some filesystems, the d_type field in the dirent struct returned by
    readdir(3) is not properly filled. According to readdir(3), "All 
applications
    must properly handle a return of DT_UNKNOWN". This patch addresses the 
issue.
    
    * gnu/packages/aux-files/run-in-namespace.c: Handle DT_UNKNOWN case.
    
    Change-Id: I128b0b88add1e9990e4fbf316ee03c3d19d4e0fc
    Signed-off-by: Ludovic Courtès <[email protected]>
---
 gnu/packages/aux-files/run-in-namespace.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/gnu/packages/aux-files/run-in-namespace.c 
b/gnu/packages/aux-files/run-in-namespace.c
index 074befde46..0ba017cec3 100644
--- a/gnu/packages/aux-files/run-in-namespace.c
+++ b/gnu/packages/aux-files/run-in-namespace.c
@@ -160,24 +160,34 @@ mirror_directory (const char *source, const char *target,
                  int (* firmlink) (const char *, const struct dirent *,
                                    const char *))
 {
-  DIR *stream = opendir (source);
+  int dir_fd = open (source, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
+  DIR *stream = fdopendir (dir_fd);
 
   for (struct dirent *entry = readdir (stream);
        entry != NULL;
        entry = readdir (stream))
     {
-      /* XXX: Some file systems may not report a useful 'd_type'.  Ignore them
-        for now.  */
-      assert (entry->d_type != DT_UNKNOWN);
-
       if (strcmp (entry->d_name, ".") == 0
          || strcmp (entry->d_name, "..") == 0)
        continue;
 
+      int is_link = 0;
+      if (entry->d_type == DT_UNKNOWN)
+        {
+          struct stat statbuf;
+          if (fstatat (dir_fd, entry->d_name, &statbuf,
+                       AT_SYMLINK_NOFOLLOW) < 0)
+            assert_perror (errno);
+          if ((statbuf.st_mode & S_IFMT) == S_IFLNK)
+            is_link = 1;
+        }
+      else if (entry->d_type == DT_LNK)
+        is_link = 1;
+
       char *abs_source = concat (source, entry->d_name);
       char *new_entry = concat (target, entry->d_name);
 
-      if (entry->d_type == DT_LNK)
+      if (is_link)
        {
          char target[PATH_MAX];
 

Reply via email to