(root)/
tar-1.35/
gnu/
linkat.c
       1  /* Create a hard link relative to open directories.
       2     Copyright (C) 2009-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* written by Eric Blake */
      18  
      19  #include <config.h>
      20  
      21  #include <unistd.h>
      22  
      23  #include <errno.h>
      24  #include <fcntl.h>
      25  #include <limits.h>
      26  #include <stdlib.h>
      27  #include <string.h>
      28  #include <sys/stat.h>
      29  
      30  #include "areadlink.h"
      31  #include "dirname.h"
      32  #include "eloop-threshold.h"
      33  #include "filenamecat.h"
      34  #include "openat-priv.h"
      35  
      36  #if !HAVE_LINKAT || LINKAT_SYMLINK_NOTSUP
      37  
      38  /* Create a link.  If FILE1 is a symlink, either create a hardlink to
      39     that symlink, or fake it by creating an identical symlink.  */
      40  # if LINK_FOLLOWS_SYMLINKS == 0
      41  #  define link_immediate link
      42  # else
      43  static int
      44  link_immediate (char const *file1, char const *file2)
      45  {
      46    char *target = areadlink (file1);
      47    if (target)
      48      {
      49        /* A symlink cannot be modified in-place.  Therefore, creating
      50           an identical symlink behaves like a hard link to a symlink,
      51           except for incorrect st_ino and st_nlink.  However, we must
      52           be careful of EXDEV.  */
      53        struct stat st1;
      54        struct stat st2;
      55        char *dir = mdir_name (file2);
      56        if (!dir)
      57          {
      58            free (target);
      59            errno = ENOMEM;
      60            return -1;
      61          }
      62        if (lstat (file1, &st1) == 0 && stat (dir, &st2) == 0)
      63          {
      64            if (st1.st_dev == st2.st_dev)
      65              {
      66                int result = symlink (target, file2);
      67                free (target);
      68                free (dir);
      69                return result;
      70              }
      71            free (target);
      72            free (dir);
      73            errno = EXDEV;
      74            return -1;
      75          }
      76        free (target);
      77        free (dir);
      78      }
      79    if (errno == ENOMEM)
      80      return -1;
      81    return link (file1, file2);
      82  }
      83  # endif /* LINK_FOLLOWS_SYMLINKS == 0 */
      84  
      85  /* Create a link.  If FILE1 is a symlink, create a hardlink to the
      86     canonicalized file.  */
      87  # if 0 < LINK_FOLLOWS_SYMLINKS
      88  #  define link_follow link
      89  # else
      90  static int
      91  link_follow (char const *file1, char const *file2)
      92  {
      93    char *name = (char *) file1;
      94    char *target;
      95    int result;
      96    int i = __eloop_threshold ();
      97  
      98    /* Using realpath or canonicalize_file_name is too heavy-handed: we
      99       don't need an absolute name, and we don't need to resolve
     100       intermediate symlinks, just the basename of each iteration.  */
     101    while (i-- && (target = areadlink (name)))
     102      {
     103        if (IS_ABSOLUTE_FILE_NAME (target))
     104          {
     105            if (name != file1)
     106              free (name);
     107            name = target;
     108          }
     109        else
     110          {
     111            char *dir = mdir_name (name);
     112            if (name != file1)
     113              free (name);
     114            if (!dir)
     115              {
     116                free (target);
     117                errno = ENOMEM;
     118                return -1;
     119              }
     120            name = mfile_name_concat (dir, target, NULL);
     121            free (dir);
     122            free (target);
     123            if (!name)
     124              {
     125                errno = ENOMEM;
     126                return -1;
     127              }
     128          }
     129      }
     130    if (i < 0)
     131      {
     132        target = NULL;
     133        errno = ELOOP;
     134      }
     135    if (!target && errno != EINVAL)
     136      {
     137        if (name != file1)
     138          free (name);
     139        return -1;
     140      }
     141    result = link (name, file2);
     142    if (name != file1)
     143      free (name);
     144    return result;
     145  }
     146  # endif /* 0 < LINK_FOLLOWS_SYMLINKS */
     147  
     148  /* On Solaris, link() doesn't follow symlinks by default, but does so as soon
     149     as a library or executable takes part in the program that has been compiled
     150     with "c99" or "cc -xc99=all" or "cc ... /usr/lib/values-xpg4.o ...".  */
     151  # if LINK_FOLLOWS_SYMLINKS == -1
     152  
     153  /* Reduce the penalty of link_immediate and link_follow by incorporating the
     154     knowledge that link()'s behaviour depends on the __xpg4 variable.  */
     155  extern int __xpg4;
     156  
     157  static int
     158  solaris_optimized_link_immediate (char const *file1, char const *file2)
     159  {
     160    if (__xpg4 == 0)
     161      return link (file1, file2);
     162    return link_immediate (file1, file2);
     163  }
     164  
     165  static int
     166  solaris_optimized_link_follow (char const *file1, char const *file2)
     167  {
     168    if (__xpg4 != 0)
     169      return link (file1, file2);
     170    return link_follow (file1, file2);
     171  }
     172  
     173  #  define link_immediate solaris_optimized_link_immediate
     174  #  define link_follow solaris_optimized_link_follow
     175  
     176  # endif
     177  
     178  #endif /* !HAVE_LINKAT || LINKAT_SYMLINK_NOTSUP  */
     179  
     180  #if !HAVE_LINKAT
     181  
     182  /* Create a link to FILE1, in the directory open on descriptor FD1, to FILE2,
     183     in the directory open on descriptor FD2.  If FILE1 is a symlink, FLAG
     184     controls whether to dereference FILE1 first.  If possible, do it without
     185     changing the working directory.  Otherwise, resort to using
     186     save_cwd/fchdir, then rename/restore_cwd.  If either the save_cwd or
     187     the restore_cwd fails, then give a diagnostic and exit nonzero.  */
     188  
     189  int
     190  linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
     191  {
     192    if (flag & ~AT_SYMLINK_FOLLOW)
     193      {
     194        errno = EINVAL;
     195        return -1;
     196      }
     197    return at_func2 (fd1, file1, fd2, file2,
     198                     flag ? link_follow : link_immediate);
     199  }
     200  
     201  #else /* HAVE_LINKAT */
     202  
     203  # undef linkat
     204  
     205  /* Create a link.  If FILE1 is a symlink, create a hardlink to the
     206     canonicalized file.  */
     207  
     208  static int
     209  linkat_follow (int fd1, char const *file1, int fd2, char const *file2)
     210  {
     211    char *name = (char *) file1;
     212    char *target;
     213    int result;
     214    int i = __eloop_threshold ();
     215  
     216    /* There is no realpathat.  */
     217    while (i-- && (target = areadlinkat (fd1, name)))
     218      {
     219        if (IS_ABSOLUTE_FILE_NAME (target))
     220          {
     221            if (name != file1)
     222              free (name);
     223            name = target;
     224          }
     225        else
     226          {
     227            char *dir = mdir_name (name);
     228            if (name != file1)
     229              free (name);
     230            if (!dir)
     231              {
     232                free (target);
     233                errno = ENOMEM;
     234                return -1;
     235              }
     236            name = mfile_name_concat (dir, target, NULL);
     237            free (dir);
     238            free (target);
     239            if (!name)
     240              {
     241                errno = ENOMEM;
     242                return -1;
     243              }
     244          }
     245      }
     246    if (i < 0)
     247      {
     248        target = NULL;
     249        errno = ELOOP;
     250      }
     251    if (!target && errno != EINVAL)
     252      {
     253        if (name != file1)
     254          free (name);
     255        return -1;
     256      }
     257    result = linkat (fd1, name, fd2, file2, 0);
     258    if (name != file1)
     259      free (name);
     260    return result;
     261  }
     262  
     263  
     264  /* Like linkat, but guarantee that AT_SYMLINK_FOLLOW works even on
     265     older Linux kernels.  */
     266  
     267  int
     268  rpl_linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
     269  {
     270    if (flag & ~AT_SYMLINK_FOLLOW)
     271      {
     272        errno = EINVAL;
     273        return -1;
     274      }
     275  
     276  # if LINKAT_TRAILING_SLASH_BUG
     277    /* Reject trailing slashes on non-directories.  */
     278    {
     279      size_t len1 = strlen (file1);
     280      size_t len2 = strlen (file2);
     281      if ((len1 && file1[len1 - 1] == '/')
     282          || (len2 && file2[len2 - 1] == '/'))
     283        {
     284          /* Let linkat() decide whether hard-linking directories is legal.
     285             If fstatat() fails, then linkat() should fail for the same reason;
     286             if fstatat() succeeds, require a directory.  */
     287          struct stat st;
     288          if (fstatat (fd1, file1, &st, flag ? 0 : AT_SYMLINK_NOFOLLOW))
     289            return -1;
     290          if (!S_ISDIR (st.st_mode))
     291            {
     292              errno = ENOTDIR;
     293              return -1;
     294            }
     295        }
     296    }
     297  # endif
     298  
     299    if (!flag)
     300      {
     301        int result = linkat (fd1, file1, fd2, file2, flag);
     302  # if LINKAT_SYMLINK_NOTSUP
     303        /* OS X 10.10 has linkat() but it doesn't support
     304           hardlinks to symlinks.  Fallback to our emulation
     305           in that case.  */
     306        if (result == -1 && (errno == ENOTSUP || errno == EOPNOTSUPP))
     307          return at_func2 (fd1, file1, fd2, file2, link_immediate);
     308  # endif
     309        return result;
     310      }
     311  
     312    /* Cache the information on whether the system call really works.  */
     313    {
     314      static int have_follow_really; /* 0 = unknown, 1 = yes, -1 = no */
     315      if (0 <= have_follow_really)
     316      {
     317        int result = linkat (fd1, file1, fd2, file2, flag);
     318        if (!(result == -1 && errno == EINVAL))
     319          {
     320            have_follow_really = 1;
     321            return result;
     322          }
     323        have_follow_really = -1;
     324      }
     325    }
     326    return linkat_follow (fd1, file1, fd2, file2);
     327  }
     328  
     329  #endif /* HAVE_LINKAT */