~ruther/guix-local

4ce3a53ae5ee832aa92e0345f15780bc7da060d7 — Romain GARBAGE 5 months ago 228d687
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>
1 files changed, 16 insertions(+), 6 deletions(-)

M gnu/packages/aux-files/run-in-namespace.c
M gnu/packages/aux-files/run-in-namespace.c => gnu/packages/aux-files/run-in-namespace.c +16 -6
@@ 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];