int
main ()
{
  static char const *const tests[][3] =
    {
      {"a", "b",   "a/b"},
      {"a/", "b",  "a/b"},
      {"a/", "/b", "a/b"},
      {"a", "/b",  "a/b"},

      {"/", "b",  "/b"},
      {"/", "/b", "/b"},
      {"/", "/",  "/"},
      {"a", "/",  "a/"},   /* this might deserve a diagnostic */
      {"/a", "/", "/a/"},  /* this might deserve a diagnostic */
      {"a", "//b",  "a/b"},
    };
  size_t i;
  bool fail = false;
  for (i = 0; i < sizeof tests / sizeof tests[0]; i++)
    {
      char *base_in_result;
      char const *const *t = tests[i];
      char *res = file_name_concat (t[0], t[1], &base_in_result);
      if (strcmp (res, t[2]) != 0)
	{
	  printf ("got %s, expected %s\n", res, t[2]);
	  fail = true;
	}
    }
  exit (fail ? EXIT_FAILURE : EXIT_SUCCESS);
}
Ejemplo n.º 2
0
char *
find_dir_file_pathname (char const *dir, char const *file)
{
  /* The 'IF_LINT (volatile)' works around what appears to be a bug in
     gcc 4.8.0 20120825; see
     <http://lists.gnu.org/archive/html/bug-diffutils/2012-08/msg00007.html>.
     */
  char const * IF_LINT (volatile) match = file;

  char *val;
  struct dirdata dirdata;
  dirdata.names = NULL;
  dirdata.data = NULL;

  if (ignore_file_name_case)
    {
      struct file_data filedata;
      filedata.name = dir;
      filedata.desc = 0;

      if (dir_read (&filedata, &dirdata))
	{
	  locale_specific_sorting = true;
	  if (setjmp (failed_locale_specific_sorting))
	    match = file; /* longjmp may mess up MATCH.  */
	  else
	    {
	      for (char const **p = dirdata.names; *p; p++)
		if (compare_names (*p, file) == 0)
		  {
		    if (file_name_cmp (*p, file) == 0)
		      {
			match = *p;
			break;
		      }
		    if (match == file)
		      match = *p;
		  }
	    }
	}
    }

  val = file_name_concat (dir, match, NULL);
  free (dirdata.names);
  free (dirdata.data);
  return val;
}
Ejemplo n.º 3
0
int
main (int argc, char *argv[])
{
  static char const *const tests[][3] =
    {
      {"a", "b",   "a/b"},
      {"a/", "b",  "a/b"},
      {"a/", "/b", "a/b"},
      {"a", "/b",  "a/b"},

      {"/", "b",  "/b"},
      {"/", "/b", "/b"},
      {"/", "/",  "/"},
      {"a", "/",  "a/"},   /* this might deserve a diagnostic */
      {"/a", "/", "/a/"},  /* this might deserve a diagnostic */
      {"a", "//b",  "a/b"},
      {"", "a", "a"},  /* this might deserve a diagnostic */
    };
  unsigned int i;
  bool fail = false;

  set_program_name (argv[0]);

  for (i = 0; i < sizeof tests / sizeof tests[0]; i++)
    {
      char *base_in_result;
      char const *const *t = tests[i];
      char *res = file_name_concat (t[0], t[1], &base_in_result);
      if (strcmp (res, t[2]) != 0)
	{
	  fprintf (stderr, "test #%u: got %s, expected %s\n", i, res, t[2]);
	  fail = true;
	}
    }
  exit (fail ? EXIT_FAILURE : EXIT_SUCCESS);
}
Ejemplo n.º 4
0
int
main ()
{
  int i;
  int dfd;
  char *cwd;
  int result;

  /* Clean up any trash from prior testsuite runs.  */
  ASSERT (system ("rm -rf " BASE "*") == 0);

  /* Test basic link functionality, without mentioning symlinks.  */
  result = test_link (do_link, false);
  dfd1 = open (".", O_RDONLY);
  ASSERT (0 <= dfd1);
  ASSERT (test_link (do_link, false) == result);
  dfd2 = dfd1;
  ASSERT (test_link (do_link, false) == result);
  dfd1 = AT_FDCWD;
  ASSERT (test_link (do_link, false) == result);
  flag = 0;
  ASSERT (test_link (do_link, false) == result);
  dfd1 = dfd2;
  ASSERT (test_link (do_link, false) == result);
  dfd2 = AT_FDCWD;
  ASSERT (test_link (do_link, false) == result);
  ASSERT (close (dfd1) == 0);
  dfd1 = AT_FDCWD;
  ASSERT (test_link (do_link, false) == result);

  /* Create locations to manipulate.  */
  ASSERT (mkdir (BASE "sub1", 0700) == 0);
  ASSERT (mkdir (BASE "sub2", 0700) == 0);
  ASSERT (close (creat (BASE "00", 0600)) == 0);
  cwd = xgetcwd ();

  dfd = open (BASE "sub1", O_RDONLY);
  ASSERT (0 <= dfd);
  ASSERT (chdir (BASE "sub2") == 0);

  /* There are 16 possible scenarios, based on whether an fd is
     AT_FDCWD or real, whether a file is absolute or relative, coupled
     with whether flag is set for 32 iterations.

     To ensure that we test all of the code paths (rather than
     triggering early normalization optimizations), we use a loop to
     repeatedly rename a file in the parent directory, use an fd open
     on subdirectory 1, all while executing in subdirectory 2; all
     relative names are thus given with a leading "../".  Finally, the
     last scenario (two relative paths given, neither one AT_FDCWD)
     has two paths, based on whether the two fds are equivalent, so we
     do the other variant after the loop.  */
  for (i = 0; i < 32; i++)
    {
      int flag = (i & 0x10 ? AT_SYMLINK_FOLLOW : 0);
      int fd1 = (i & 8) ? dfd : AT_FDCWD;
      char *file1 = file_name_concat ((i & 4) ? ".." : cwd, BASE "xx", NULL);
      int fd2 = (i & 2) ? dfd : AT_FDCWD;
      char *file2 = file_name_concat ((i & 1) ? ".." : cwd, BASE "xx", NULL);

      ASSERT (sprintf (strchr (file1, '\0') - 2, "%02d", i) == 2);
      ASSERT (sprintf (strchr (file2, '\0') - 2, "%02d", i + 1) == 2);
      ASSERT (linkat (fd1, file1, fd2, file2, flag) == 0);
      ASSERT (unlinkat (fd1, file1, 0) == 0);
      free (file1);
      free (file2);
    }
  dfd2 = open ("..", O_RDONLY);
  ASSERT (0 <= dfd2);
  ASSERT (linkat (dfd, "../" BASE "32", dfd2, BASE "33", 0) == 0);
  ASSERT (linkat (dfd, "../" BASE "33", dfd2, BASE "34",
                  AT_SYMLINK_FOLLOW) == 0);
  ASSERT (close (dfd2) == 0);

  /* Now we change back to the parent directory, and set dfd to ".",
     in order to test behavior on symlinks.  */
  ASSERT (chdir ("..") == 0);
  ASSERT (close (dfd) == 0);
  if (symlink (BASE "sub1", BASE "link1"))
    {
      ASSERT (unlink (BASE "32") == 0);
      ASSERT (unlink (BASE "33") == 0);
      ASSERT (unlink (BASE "34") == 0);
      ASSERT (rmdir (BASE "sub1") == 0);
      ASSERT (rmdir (BASE "sub2") == 0);
      free (cwd);
      fputs ("skipping test: symlinks not supported on this filesystem\n",
             stderr);
      return result;
    }
  dfd = open (".", O_RDONLY);
  ASSERT (0 <= dfd);
  ASSERT (symlink (BASE "34", BASE "link2") == 0);
  ASSERT (symlink (BASE "link3", BASE "link3") == 0);
  ASSERT (symlink (BASE "nowhere", BASE "link4") == 0);

  /* Link cannot overwrite existing files.  */
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "sub1", 0) == -1);
  ASSERT (errno == EEXIST);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1/", dfd, BASE "sub1", 0) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "sub1/", 0) == -1);
  ASSERT (errno == EEXIST);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "sub1",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1/", dfd, BASE "sub1",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "sub1/",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link2", 0) == -1);
  ASSERT (errno == EEXIST);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link2",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link3", 0) == -1);
  ASSERT (errno == EEXIST || errno == ELOOP);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link3",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES
          || errno == ELOOP);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link2", dfd, BASE "link3", 0) == -1);
  ASSERT (errno == EEXIST || errno == ELOOP);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link2", dfd, BASE "link3",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == ELOOP);

  /* AT_SYMLINK_FOLLOW only follows first argument, not second.  */
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link4", 0) == -1);
  ASSERT (errno == EEXIST);
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link4",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST || errno == EPERM || errno == EACCES);
  errno = 0;
  ASSERT (linkat (dfd, BASE "34", dfd, BASE "link4", 0) == -1);
  ASSERT (errno == EEXIST);
  errno = 0;
  ASSERT (linkat (dfd, BASE "34", dfd, BASE "link4", AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EEXIST);

  /* Trailing slash handling.  */
  errno = 0;
  ASSERT (linkat (dfd, BASE "link2/", dfd, BASE "link5", 0) == -1);
  ASSERT (errno == ENOTDIR);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link2/", dfd, BASE "link5",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ENOTDIR);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link3/", dfd, BASE "link5", 0) == -1);
  ASSERT (errno == ELOOP);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link3/", dfd, BASE "link5",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ELOOP);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link4/", dfd, BASE "link5", 0) == -1);
  ASSERT (errno == ENOENT);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link4/", dfd, BASE "link5",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ENOENT);

  /* Check for hard links to symlinks.  */
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link5", 0) == 0);
  check_same_link (BASE "link1", BASE "link5");
  ASSERT (unlink (BASE "link5") == 0);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link1", dfd, BASE "link5",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == EPERM || errno == EACCES);
  ASSERT (linkat (dfd, BASE "link2", dfd, BASE "link5", 0) == 0);
  check_same_link (BASE "link2", BASE "link5");
  ASSERT (unlink (BASE "link5") == 0);
  ASSERT (linkat (dfd, BASE "link2", dfd, BASE "file", AT_SYMLINK_FOLLOW) == 0);
  errno = 0;
  ASSERT (areadlink (BASE "file") == NULL);
  ASSERT (errno == EINVAL);
  ASSERT (unlink (BASE "file") == 0);
  ASSERT (linkat (dfd, BASE "link3", dfd, BASE "link5", 0) == 0);
  check_same_link (BASE "link3", BASE "link5");
  ASSERT (unlink (BASE "link5") == 0);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link3", dfd, BASE "link5",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ELOOP);
  ASSERT (linkat (dfd, BASE "link4", dfd, BASE "link5", 0) == 0);
  check_same_link (BASE "link4", BASE "link5");
  ASSERT (unlink (BASE "link5") == 0);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link4", dfd, BASE "link5",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ENOENT);

  /* Check that symlink to symlink to file is followed all the way.  */
  ASSERT (symlink (BASE "link2", BASE "link5") == 0);
  ASSERT (linkat (dfd, BASE "link5", dfd, BASE "link6", 0) == 0);
  check_same_link (BASE "link5", BASE "link6");
  ASSERT (unlink (BASE "link6") == 0);
  ASSERT (linkat (dfd, BASE "link5", dfd, BASE "file", AT_SYMLINK_FOLLOW) == 0);
  errno = 0;
  ASSERT (areadlink (BASE "file") == NULL);
  ASSERT (errno == EINVAL);
  ASSERT (unlink (BASE "file") == 0);
  ASSERT (unlink (BASE "link5") == 0);
  ASSERT (symlink (BASE "link3", BASE "link5") == 0);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link5", dfd, BASE "file",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ELOOP);
  ASSERT (unlink (BASE "link5") == 0);
  ASSERT (symlink (BASE "link4", BASE "link5") == 0);
  errno = 0;
  ASSERT (linkat (dfd, BASE "link5", dfd, BASE "file",
                  AT_SYMLINK_FOLLOW) == -1);
  ASSERT (errno == ENOENT);

  /* Now for some real fun with directory crossing.  */
  ASSERT (symlink (cwd, BASE "sub1/link") == 0);
  ASSERT (symlink (".././/" BASE "sub1/link/" BASE "link2",
                   BASE "sub2/link") == 0);
  ASSERT (close (dfd) == 0);
  dfd = open (BASE "sub1", O_RDONLY);
  ASSERT (0 <= dfd);
  dfd2 = open (BASE "sub2", O_RDONLY);
  ASSERT (0 < dfd2);
  ASSERT (linkat (dfd, "../" BASE "sub2/link", dfd2, "./..//" BASE "sub1/file",
              AT_SYMLINK_FOLLOW) == 0);
  errno = 0;
  ASSERT (areadlink (BASE "sub1/file") == NULL);
  ASSERT (errno == EINVAL);

  /* Cleanup.  */
  ASSERT (close (dfd) == 0);
  ASSERT (close (dfd2) == 0);
  ASSERT (unlink (BASE "sub1/file") == 0);
  ASSERT (unlink (BASE "sub1/link") == 0);
  ASSERT (unlink (BASE "sub2/link") == 0);
  ASSERT (unlink (BASE "32") == 0);
  ASSERT (unlink (BASE "33") == 0);
  ASSERT (unlink (BASE "34") == 0);
  ASSERT (rmdir (BASE "sub1") == 0);
  ASSERT (rmdir (BASE "sub2") == 0);
  ASSERT (unlink (BASE "link1") == 0);
  ASSERT (unlink (BASE "link2") == 0);
  ASSERT (unlink (BASE "link3") == 0);
  ASSERT (unlink (BASE "link4") == 0);
  ASSERT (unlink (BASE "link5") == 0);
  free (cwd);
  return result;
}
int
main (void)
{
  int i;
  int dfd;
  char *cwd;
  int result;

  /* Clean up any trash from prior testsuite runs.  */
  ignore_value (system ("rm -rf " BASE "*"));

  /* Test behaviour for invalid file descriptors.  */
  {
    errno = 0;
    ASSERT (renameat (-1, "foo", AT_FDCWD, "bar") == -1);
    ASSERT (errno == EBADF);
  }
  {
    errno = 0;
    ASSERT (renameat (99, "foo", AT_FDCWD, "bar") == -1);
    ASSERT (errno == EBADF);
  }
  ASSERT (close (creat (BASE "oo", 0600)) == 0);
  {
    errno = 0;
    ASSERT (renameat (AT_FDCWD, BASE "oo", -1, "bar") == -1);
    ASSERT (errno == EBADF);
  }
  {
    errno = 0;
    ASSERT (renameat (AT_FDCWD, BASE "oo", 99, "bar") == -1);
    ASSERT (errno == EBADF);
  }
  ASSERT (unlink (BASE "oo") == 0);

  /* Test basic rename functionality, using current directory.  */
  result = test_rename (do_rename, false);
  dfd1 = open (".", O_RDONLY);
  ASSERT (0 <= dfd1);
  ASSERT (test_rename (do_rename, false) == result);
  dfd2 = dfd1;
  ASSERT (test_rename (do_rename, false) == result);
  dfd1 = AT_FDCWD;
  ASSERT (test_rename (do_rename, false) == result);
  ASSERT (close (dfd2) == 0);

  /* Create locations to manipulate.  */
  ASSERT (mkdir (BASE "sub1", 0700) == 0);
  ASSERT (mkdir (BASE "sub2", 0700) == 0);
  dfd = creat (BASE "00", 0600);
  ASSERT (0 <= dfd);
  ASSERT (close (dfd) == 0);
  cwd = getcwd (NULL, 0);
  ASSERT (cwd);

  dfd = open (BASE "sub1", O_RDONLY);
  ASSERT (0 <= dfd);
  ASSERT (chdir (BASE "sub2") == 0);

  /* There are 16 possible scenarios, based on whether an fd is
     AT_FDCWD or real, and whether a file is absolute or relative.

     To ensure that we test all of the code paths (rather than
     triggering early normalization optimizations), we use a loop to
     repeatedly rename a file in the parent directory, use an fd open
     on subdirectory 1, all while executing in subdirectory 2; all
     relative names are thus given with a leading "../".  Finally, the
     last scenario (two relative paths given, neither one AT_FDCWD)
     has two paths, based on whether the two fds are equivalent, so we
     do the other variant after the loop.  */
  for (i = 0; i < 16; i++)
    {
      int fd1 = (i & 8) ? dfd : AT_FDCWD;
      char *file1 = file_name_concat ((i & 4) ? ".." : cwd, BASE "xx", NULL);
      int fd2 = (i & 2) ? dfd : AT_FDCWD;
      char *file2 = file_name_concat ((i & 1) ? ".." : cwd, BASE "xx", NULL);

      ASSERT (sprintf (strchr (file1, '\0') - 2, "%02d", i) == 2);
      ASSERT (sprintf (strchr (file2, '\0') - 2, "%02d", i + 1) == 2);
      ASSERT (renameat (fd1, file1, fd2, file2) == 0);
      free (file1);
      free (file2);
    }
  dfd2 = open ("..", O_RDONLY);
  ASSERT (0 <= dfd2);
  ASSERT (renameat (dfd, "../" BASE "16", dfd2, BASE "17") == 0);
  ASSERT (close (dfd2) == 0);

  /* Now we change back to the parent directory, and set dfd to ".";
     using dfd in remaining tests will expose any bugs if emulation
     via /proc/self/fd doesn't check for empty names.  */
  ASSERT (chdir ("..") == 0);
  ASSERT (close (dfd) == 0);
  dfd = open (".", O_RDONLY);
  ASSERT (0 <= dfd);

  ASSERT (close (creat (BASE "sub2/file", 0600)) == 0);
  errno = 0;
  ASSERT (renameat (dfd, BASE "sub1", dfd, BASE "sub2") == -1);
  ASSERT (errno == EEXIST || errno == ENOTEMPTY);
  ASSERT (unlink (BASE "sub2/file") == 0);
  errno = 0;
  ASSERT (renameat (dfd, BASE "sub2", dfd, BASE "sub1/.") == -1);
  ASSERT (errno == EINVAL || errno == EISDIR || errno == EBUSY
          || errno == ENOTEMPTY || errno == EEXIST);
  errno = 0;
  ASSERT (renameat (dfd, BASE "sub2/.", dfd, BASE "sub1") == -1);
  ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST);
  errno = 0;
  ASSERT (renameat (dfd, BASE "17", dfd, BASE "sub1") == -1);
  ASSERT (errno == EISDIR);
  errno = 0;
  ASSERT (renameat (dfd, BASE "nosuch", dfd, BASE "18") == -1);
  ASSERT (errno == ENOENT);
  errno = 0;
  ASSERT (renameat (dfd, "", dfd, BASE "17") == -1);
  ASSERT (errno == ENOENT);
  errno = 0;
  ASSERT (renameat (dfd, BASE "17", dfd, "") == -1);
  ASSERT (errno == ENOENT);
  errno = 0;
  ASSERT (renameat (dfd, BASE "sub2", dfd, BASE "17") == -1);
  ASSERT (errno == ENOTDIR);
  errno = 0;
  ASSERT (renameat (dfd, BASE "17/", dfd, BASE "18") == -1);
  ASSERT (errno == ENOTDIR);
  errno = 0;
  ASSERT (renameat (dfd, BASE "17", dfd, BASE "18/") == -1);
  ASSERT (errno == ENOTDIR || errno == ENOENT);

  /* Finally, make sure we can overwrite existing files.  */
  ASSERT (close (creat (BASE "sub2/file", 0600)) == 0);
  errno = 0;
  ASSERT (renameat (dfd, BASE "sub2", dfd, BASE "sub1") == 0);
  ASSERT (renameat (dfd, BASE "sub1/file", dfd, BASE "17") == 0);

  /* Cleanup.  */
  ASSERT (close (dfd) == 0);
  errno = 0;
  ASSERT (unlink (BASE "sub1/file") == -1);
  ASSERT (errno == ENOENT);
  ASSERT (unlink (BASE "17") == 0);
  ASSERT (rmdir (BASE "sub1") == 0);
  errno = 0;
  ASSERT (rmdir (BASE "sub2") == -1);
  ASSERT (errno == ENOENT);
  free (cwd);

  if (result)
    fputs ("skipping test: symlinks not supported on this file system\n",
           stderr);
  return result;
}
Ejemplo n.º 6
0
Archivo: path.c Proyecto: Distrotech/m4
/* Search for FILENAME according to -B options, `.', -I options, then
   M4PATH environment.  If successful, return the open file, and if
   RESULT is not NULL, set *RESULT to a malloc'd string that
   represents the file found with respect to the current working
   directory.  Otherwise, return NULL, and errno reflects the failure
   from searching `.' (regardless of what else was searched).  */
char *
m4_path_search (m4 *context, const char *filename, const char **suffixes)
{
  m4__search_path *incl;
  char *filepath;		/* buffer for constructed name */
  size_t max_suffix_len = 0;
  int i, e = 0;

  /* Reject empty file.  */
  if (*filename == '\0')
    {
      errno = ENOENT;
      return NULL;
    }

  /* Use no suffixes by default.  */
  if (suffixes == NULL)
    suffixes = NO_SUFFIXES;

  /* Find the longest suffix, so that we will always allocate enough
     memory for a filename with suffix.  */
  for (i = 0; suffixes && suffixes[i]; ++i)
    {
      size_t len = strlen (suffixes[i]);
      if (len > max_suffix_len)
        max_suffix_len = len;
    }

  /* If file is absolute, or if we are not searching a path, a single
     lookup will do the trick.  */
  if (IS_ABSOLUTE_FILE_NAME (filename))
    {
      size_t mem = strlen (filename);

      /* Try appending each of the suffixes we were given.  */
      filepath = strncpy (xmalloc (mem + max_suffix_len +1), filename, mem +1);
#if TRUNCATE_FILENAME
      filepath = path_truncate (filepath);
      mem = strlen (filepath); /* recalculate length after truncation */
#endif
      for (i = 0; suffixes && suffixes[i]; ++i)
        {
          strcpy (filepath + mem, suffixes[i]);
          if (access (filepath, R_OK) == 0)
	    return filepath;

          /* If search fails, we'll use the error we got from the first
	     access (usually with no suffix).  */
	  if (i == 0)
	    e = errno;
        }
      free (filepath);

      /* No such file.  */
      errno = e;
      return NULL;
    }

  for (incl = m4__get_search_path (context)->list;
       incl != NULL; incl = incl->next)
    {
      char *pathname = file_name_concat (incl->dir, filename, NULL);
      size_t mem = strlen (pathname);

#ifdef DEBUG_INCL
      xfprintf (stderr, "path_search (%s) -- trying %s\n", filename, pathname);
#endif

      if (access (pathname, R_OK) == 0)
        {
          m4_debug_message (context, M4_DEBUG_TRACE_PATH,
                            _("path search for %s found %s"),
                            quotearg_style (locale_quoting_style, filename),
                            quotearg_n_style (1, locale_quoting_style, pathname));
          return pathname;
        }
      else if (!incl->len)
	/* Capture errno only when searching `.'.  */
	e = errno;

      filepath = strncpy (xmalloc (mem + max_suffix_len +1), pathname, mem +1);
      free (pathname);
#if TRUNCATE_FILENAME
      filepath = path_truncate (filepath);
      mem = strlen (filepath); /* recalculate length after truncation */
#endif
 
      for (i = 0; suffixes && suffixes[i]; ++i)
        {
          strcpy (filepath + mem, suffixes[i]);
          if (access (filepath, R_OK) == 0)
            return filepath;
        }
      free (filepath);
    }

  errno = e;
  return NULL;
}
Ejemplo n.º 7
0
char *
canonicalize_file_name (const char *name)
{
# if HAVE_RESOLVEPATH

  char *resolved, *extra_buf = NULL;
  size_t resolved_size;
  ssize_t resolved_len;

  if (name == NULL)
    {
      __set_errno (EINVAL);
      return NULL;
    }

  if (name[0] == '\0')
    {
      __set_errno (ENOENT);
      return NULL;
    }

  /* All known hosts with resolvepath (e.g. Solaris 7) don't turn
     relative names into absolute ones, so prepend the working
     directory if the file name is not absolute.  */
  if (name[0] != '/')
    {
      char *wd;

      if (!(wd = xgetcwd ()))
	return NULL;

      extra_buf = file_name_concat (wd, name, NULL);
      name = extra_buf;
      free (wd);
    }

  resolved_size = strlen (name);
  while (1)
    {
      resolved_size = 2 * resolved_size + 1;
      resolved = xmalloc (resolved_size);
      resolved_len = resolvepath (name, resolved, resolved_size);
      if (resolved_len < 0)
	{
	  free (resolved);
	  free (extra_buf);
	  return NULL;
	}
      if (resolved_len < resolved_size)
	break;
      free (resolved);
    }

  free (extra_buf);

  /* NUL-terminate the resulting name.  */
  resolved[resolved_len] = '\0';

  return resolved;

# else

  return canonicalize_filename_mode (name, CAN_EXISTING);

# endif /* !HAVE_RESOLVEPATH */
}