Exemple #1
0
int
rpl_linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
{
  if (!flag)
    return linkat (fd1, file1, fd2, file2, flag);
  if (flag & ~AT_SYMLINK_FOLLOW)
    {
      errno = EINVAL;
      return -1;
    }

  /* Cache the information on whether the system call really works.  */
  {
    static int have_follow_really; /* 0 = unknown, 1 = yes, -1 = no */
    if (0 <= have_follow_really)
    {
      int result = linkat (fd1, file1, fd2, file2, flag);
      if (!(result == -1 && errno == EINVAL))
        {
          have_follow_really = 1;
          return result;
        }
      have_follow_really = -1;
    }
  }
  return linkat_follow (fd1, file1, fd2, file2);
}
Exemple #2
0
int
rpl_linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
{
  if (flag & ~AT_SYMLINK_FOLLOW)
    {
      errno = EINVAL;
      return -1;
    }

#if LINKAT_TRAILING_SLASH_BUG
  /* Reject trailing slashes on non-directories.  */
  {
    size_t len1 = strlen (file1);
    size_t len2 = strlen (file2);
    if ((len1 && file1[len1 - 1] == '/')
        || (len2 && file2[len2 - 1] == '/'))
      {
        /* Let linkat() decide whether hard-linking directories is legal.
           If fstatat() fails, then linkat() should fail for the same reason;
           if fstatat() succeeds, require a directory.  */
        struct stat st;
        if (fstatat (fd1, file1, &st, flag ? 0 : AT_SYMLINK_NOFOLLOW))
          return -1;
        if (!S_ISDIR (st.st_mode))
          {
            errno = ENOTDIR;
            return -1;
          }
      }
  }
#endif

  if (!flag)
    return linkat (fd1, file1, fd2, file2, flag);

  /* Cache the information on whether the system call really works.  */
  {
    static int have_follow_really; /* 0 = unknown, 1 = yes, -1 = no */
    if (0 <= have_follow_really)
    {
      int result = linkat (fd1, file1, fd2, file2, flag);
      if (!(result == -1 && errno == EINVAL))
        {
          have_follow_really = 1;
          return result;
        }
      have_follow_really = -1;
    }
  }
  return linkat_follow (fd1, file1, fd2, file2);
}