summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRomain GARBAGE <romain.garbage@inria.fr>2025-09-12 16:57:59 +0200
committerLudovic Courtès <ludo@gnu.org>2025-10-17 12:23:54 +0200
commit4ce3a53ae5ee832aa92e0345f15780bc7da060d7 (patch)
tree58c31f7bd40591dc75c3738d2564af3d4cea3b6e
parent228d687fbe60aa61945f69733fefcfb56a592756 (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.c22
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,
160 int (* firmlink) (const char *, const struct dirent *, 160 int (* firmlink) (const char *, const struct dirent *,
161 const char *)) 161 const char *))
162{ 162{
163 DIR *stream = opendir (source); 163 int dir_fd = open (source, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
164 DIR *stream = fdopendir (dir_fd);
164 165
165 for (struct dirent *entry = readdir (stream); 166 for (struct dirent *entry = readdir (stream);
166 entry != NULL; 167 entry != NULL;
167 entry = readdir (stream)) 168 entry = readdir (stream))
168 { 169 {
169 /* XXX: Some file systems may not report a useful 'd_type'. Ignore them
170 for now. */
171 assert (entry->d_type != DT_UNKNOWN);
172
173 if (strcmp (entry->d_name, ".") == 0 170 if (strcmp (entry->d_name, ".") == 0
174 || strcmp (entry->d_name, "..") == 0) 171 || strcmp (entry->d_name, "..") == 0)
175 continue; 172 continue;
176 173
174 int is_link = 0;
175 if (entry->d_type == DT_UNKNOWN)
176 {
177 struct stat statbuf;
178 if (fstatat (dir_fd, entry->d_name, &statbuf,
179 AT_SYMLINK_NOFOLLOW) < 0)
180 assert_perror (errno);
181 if ((statbuf.st_mode & S_IFMT) == S_IFLNK)
182 is_link = 1;
183 }
184 else if (entry->d_type == DT_LNK)
185 is_link = 1;
186
177 char *abs_source = concat (source, entry->d_name); 187 char *abs_source = concat (source, entry->d_name);
178 char *new_entry = concat (target, entry->d_name); 188 char *new_entry = concat (target, entry->d_name);
179 189
180 if (entry->d_type == DT_LNK) 190 if (is_link)
181 { 191 {
182 char target[PATH_MAX]; 192 char target[PATH_MAX];
183 193