diff options
| author | Romain GARBAGE <romain.garbage@inria.fr> | 2025-09-12 16:57:59 +0200 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2025-10-17 12:23:54 +0200 |
| commit | 4ce3a53ae5ee832aa92e0345f15780bc7da060d7 (patch) | |
| tree | 58c31f7bd40591dc75c3738d2564af3d4cea3b6e | |
| parent | 228d687fbe60aa61945f69733fefcfb56a592756 (diff) | |
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 <ludo@gnu.org>
| -rw-r--r-- | gnu/packages/aux-files/run-in-namespace.c | 22 |
1 files 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 074befde461..0ba017cec38 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]; |
