(root)/
coreutils-9.4/
src/
ln.c
       1  /* 'ln' program to create links between files.
       2     Copyright (C) 1986-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 Mike Parker and David MacKenzie. */
      18  
      19  #include <config.h>
      20  #include <stdio.h>
      21  #include <sys/types.h>
      22  #include <getopt.h>
      23  
      24  #include "system.h"
      25  #include "backupfile.h"
      26  #include "fcntl-safer.h"
      27  #include "filenamecat.h"
      28  #include "file-set.h"
      29  #include "force-link.h"
      30  #include "hash.h"
      31  #include "hash-triple.h"
      32  #include "priv-set.h"
      33  #include "relpath.h"
      34  #include "same.h"
      35  #include "unlinkdir.h"
      36  #include "yesno.h"
      37  #include "canonicalize.h"
      38  
      39  /* The official name of this program (e.g., no 'g' prefix).  */
      40  #define PROGRAM_NAME "ln"
      41  
      42  #define AUTHORS \
      43    proper_name ("Mike Parker"), \
      44    proper_name ("David MacKenzie")
      45  
      46  /* FIXME: document */
      47  static enum backup_type backup_type;
      48  
      49  /* If true, make symbolic links; otherwise, make hard links.  */
      50  static bool symbolic_link;
      51  
      52  /* If true, make symbolic links relative  */
      53  static bool relative;
      54  
      55  /* If true, hard links are logical rather than physical.  */
      56  static bool logical = !!LINK_FOLLOWS_SYMLINKS;
      57  
      58  /* If true, ask the user before removing existing files.  */
      59  static bool interactive;
      60  
      61  /* If true, remove existing files unconditionally.  */
      62  static bool remove_existing_files;
      63  
      64  /* If true, list each file as it is moved. */
      65  static bool verbose;
      66  
      67  /* If true, allow the superuser to *attempt* to make hard links
      68     to directories.  However, it appears that this option is not useful
      69     in practice, since even the superuser is prohibited from hard-linking
      70     directories on most existing systems (Solaris being an exception).  */
      71  static bool hard_dir_link;
      72  
      73  /* If true, watch out for creating or removing hard links to directories.  */
      74  static bool beware_hard_dir_link;
      75  
      76  /* If nonzero, and the specified destination is a symbolic link to a
      77     directory, treat it just as if it were a directory.  Otherwise, the
      78     command 'ln --force --no-dereference file symlink-to-dir' deletes
      79     symlink-to-dir before creating the new link.  */
      80  static bool dereference_dest_dir_symlinks = true;
      81  
      82  /* This is a set of destination name/inode/dev triples for hard links
      83     created by ln.  Use this data structure to avoid data loss via a
      84     sequence of commands like this:
      85     rm -rf a b c; mkdir a b c; touch a/f b/f; ln -f a/f b/f c && rm -r a b */
      86  static Hash_table *dest_set;
      87  
      88  /* Initial size of the dest_set hash table.  */
      89  enum { DEST_INFO_INITIAL_CAPACITY = 61 };
      90  
      91  static struct option const long_options[] =
      92  {
      93    {"backup", optional_argument, nullptr, 'b'},
      94    {"directory", no_argument, nullptr, 'F'},
      95    {"no-dereference", no_argument, nullptr, 'n'},
      96    {"no-target-directory", no_argument, nullptr, 'T'},
      97    {"force", no_argument, nullptr, 'f'},
      98    {"interactive", no_argument, nullptr, 'i'},
      99    {"suffix", required_argument, nullptr, 'S'},
     100    {"target-directory", required_argument, nullptr, 't'},
     101    {"logical", no_argument, nullptr, 'L'},
     102    {"physical", no_argument, nullptr, 'P'},
     103    {"relative", no_argument, nullptr, 'r'},
     104    {"symbolic", no_argument, nullptr, 's'},
     105    {"verbose", no_argument, nullptr, 'v'},
     106    {GETOPT_HELP_OPTION_DECL},
     107    {GETOPT_VERSION_OPTION_DECL},
     108    {nullptr, 0, nullptr, 0}
     109  };
     110  
     111  /* Return an errno value for a system call that returned STATUS.
     112     This is zero if STATUS is zero, and is errno otherwise.  */
     113  
     114  static int
     115  errnoize (int status)
     116  {
     117    return status < 0 ? errno : 0;
     118  }
     119  
     120  /* Return FROM represented as relative to the dir of TARGET.
     121     The result is malloced.  */
     122  
     123  static char *
     124  convert_abs_rel (char const *from, char const *target)
     125  {
     126    /* Get dirname to generate paths relative to.  We don't resolve
     127       the full TARGET as the last component could be an existing symlink.  */
     128    char *targetdir = dir_name (target);
     129  
     130    char *realdest = canonicalize_filename_mode (targetdir, CAN_MISSING);
     131    char *realfrom = canonicalize_filename_mode (from, CAN_MISSING);
     132  
     133    char *relative_from = nullptr;
     134    if (realdest && realfrom)
     135      {
     136        /* Write to a PATH_MAX buffer.  */
     137        relative_from = xmalloc (PATH_MAX);
     138  
     139        if (!relpath (realfrom, realdest, relative_from, PATH_MAX))
     140          {
     141            free (relative_from);
     142            relative_from = nullptr;
     143          }
     144      }
     145  
     146    free (targetdir);
     147    free (realdest);
     148    free (realfrom);
     149  
     150    return relative_from ? relative_from : xstrdup (from);
     151  }
     152  
     153  /* Link SOURCE to DESTDIR_FD + DEST_BASE atomically.  DESTDIR_FD is
     154     the directory containing DEST_BASE.  Return 0 if successful, a
     155     positive errno value on failure, and -1 if an atomic link cannot be
     156     done.  This handles the common case where the destination does not
     157     already exist and -r is not specified.  */
     158  
     159  static int
     160  atomic_link (char const *source, int destdir_fd, char const *dest_base)
     161  {
     162    return (symbolic_link
     163            ? (relative ? -1
     164               : errnoize (symlinkat (source, destdir_fd, dest_base)))
     165            : beware_hard_dir_link ? -1
     166            : errnoize (linkat (AT_FDCWD, source, destdir_fd, dest_base,
     167                                logical ? AT_SYMLINK_FOLLOW : 0)));
     168  }
     169  
     170  /* Link SOURCE to a directory entry under DESTDIR_FD named DEST_BASE.
     171     DEST is the full name of the destination, useful for diagnostics.
     172     LINK_ERRNO is zero if the link has already been made,
     173     positive if attempting the link failed with errno == LINK_ERRNO,
     174     -1 if no attempt has been made to create the link.
     175     Return true if successful.  */
     176  
     177  static bool
     178  do_link (char const *source, int destdir_fd, char const *dest_base,
     179           char const *dest, int link_errno)
     180  {
     181    struct stat source_stats;
     182    int source_status = 1;
     183    char *backup_base = nullptr;
     184    char *rel_source = nullptr;
     185    int nofollow_flag = logical ? 0 : AT_SYMLINK_NOFOLLOW;
     186    if (link_errno < 0)
     187      link_errno = atomic_link (source, destdir_fd, dest_base);
     188  
     189    /* Get SOURCE_STATS if later code will need it, if only for sharper
     190       diagnostics.  */
     191    if ((link_errno || dest_set) && !symbolic_link)
     192      {
     193        source_status = fstatat (AT_FDCWD, source, &source_stats, nofollow_flag);
     194        if (source_status != 0)
     195          {
     196            error (0, errno, _("failed to access %s"), quoteaf (source));
     197            return false;
     198          }
     199      }
     200  
     201    if (link_errno)
     202      {
     203        if (!symbolic_link && !hard_dir_link && S_ISDIR (source_stats.st_mode))
     204          {
     205            error (0, 0, _("%s: hard link not allowed for directory"),
     206                   quotef (source));
     207            return false;
     208          }
     209  
     210        if (relative)
     211          source = rel_source = convert_abs_rel (source, dest);
     212  
     213        bool force = (remove_existing_files || interactive
     214                      || backup_type != no_backups);
     215        if (force)
     216          {
     217            struct stat dest_stats;
     218            if (fstatat (destdir_fd, dest_base, &dest_stats, AT_SYMLINK_NOFOLLOW)
     219                != 0)
     220              {
     221                if (errno != ENOENT)
     222                  {
     223                    error (0, errno, _("failed to access %s"), quoteaf (dest));
     224                    goto fail;
     225                  }
     226                force = false;
     227              }
     228            else if (S_ISDIR (dest_stats.st_mode))
     229              {
     230                error (0, 0, _("%s: cannot overwrite directory"), quotef (dest));
     231                goto fail;
     232              }
     233            else if (seen_file (dest_set, dest, &dest_stats))
     234              {
     235                /* The current target was created as a hard link to another
     236                   source file.  */
     237                error (0, 0,
     238                       _("will not overwrite just-created %s with %s"),
     239                       quoteaf_n (0, dest), quoteaf_n (1, source));
     240                goto fail;
     241              }
     242            else
     243              {
     244                /* Beware removing DEST if it is the same directory entry as
     245                   SOURCE, because in that case removing DEST can cause the
     246                   subsequent link creation either to fail (for hard links), or
     247                   to replace a non-symlink DEST with a self-loop (for symbolic
     248                   links) which loses the contents of DEST.  So, when backing
     249                   up, worry about creating hard links (since the backups cover
     250                   the symlink case); otherwise, worry about about -f.  */
     251                if (backup_type != no_backups
     252                    ? !symbolic_link
     253                    : remove_existing_files)
     254                  {
     255                    /* Detect whether removing DEST would also remove SOURCE.
     256                       If the file has only one link then both are surely the
     257                       same directory entry.  Otherwise check whether they point
     258                       to the same name in the same directory.  */
     259                    if (source_status != 0)
     260                      source_status = stat (source, &source_stats);
     261                    if (source_status == 0
     262                        && SAME_INODE (source_stats, dest_stats)
     263                        && (source_stats.st_nlink == 1
     264                            || same_nameat (AT_FDCWD, source,
     265                                            destdir_fd, dest_base)))
     266                      {
     267                        error (0, 0, _("%s and %s are the same file"),
     268                               quoteaf_n (0, source), quoteaf_n (1, dest));
     269                        goto fail;
     270                      }
     271                  }
     272  
     273                if (link_errno < 0 || link_errno == EEXIST)
     274                  {
     275                    if (interactive)
     276                      {
     277                        fprintf (stderr, _("%s: replace %s? "),
     278                                 program_name, quoteaf (dest));
     279                        if (!yesno ())
     280                          {
     281                            free (rel_source);
     282                            return false;
     283                          }
     284                      }
     285  
     286                    if (backup_type != no_backups)
     287                      {
     288                        backup_base = find_backup_file_name (destdir_fd,
     289                                                             dest_base,
     290                                                             backup_type);
     291                        if (renameat (destdir_fd, dest_base,
     292                                      destdir_fd, backup_base)
     293                            != 0)
     294                          {
     295                            int rename_errno = errno;
     296                            free (backup_base);
     297                            backup_base = nullptr;
     298                            if (rename_errno != ENOENT)
     299                              {
     300                                error (0, rename_errno, _("cannot backup %s"),
     301                                       quoteaf (dest));
     302                                goto fail;
     303                              }
     304                            force = false;
     305                          }
     306                      }
     307                  }
     308              }
     309          }
     310  
     311        /* If the attempt to create a link fails and we are removing or
     312           backing up destinations, unlink the destination and try again.
     313  
     314           On the surface, POSIX states that 'ln -f A B' unlinks B before trying
     315           to link A to B.  But strictly following this has the counterintuitive
     316           effect of losing the contents of B if A does not exist.  Fortunately,
     317           POSIX 2008 clarified that an application is free to fail early if it
     318           can prove that continuing onward cannot succeed, so we can try to
     319           link A to B before blindly unlinking B, thus sometimes attempting to
     320           link a second time during a successful 'ln -f A B'.
     321  
     322           Try to unlink DEST even if we may have backed it up successfully.
     323           In some unusual cases (when DEST and the backup are hard-links
     324           that refer to the same file), rename succeeds and DEST remains.
     325           If we didn't remove DEST in that case, the subsequent symlink or
     326           link call would fail.  */
     327        link_errno
     328          = (symbolic_link
     329             ? force_symlinkat (source, destdir_fd, dest_base,
     330                                force, link_errno)
     331             : force_linkat (AT_FDCWD, source, destdir_fd, dest_base,
     332                             logical ? AT_SYMLINK_FOLLOW : 0,
     333                             force, link_errno));
     334        /* Until now, link_errno < 0 meant the link has not been tried.
     335           From here on, link_errno < 0 means the link worked but
     336           required removing the destination first.  */
     337      }
     338  
     339    if (link_errno <= 0)
     340      {
     341        /* Right after creating a hard link, do this: (note dest name and
     342           source_stats, which are also the just-linked-destinations stats) */
     343        if (! symbolic_link)
     344          record_file (dest_set, dest, &source_stats);
     345  
     346        if (verbose)
     347          {
     348            char const *quoted_backup = "";
     349            char const *backup_sep = "";
     350            if (backup_base)
     351              {
     352                char *backup = backup_base;
     353                void *alloc = nullptr;
     354                ptrdiff_t destdirlen = dest_base - dest;
     355                if (0 < destdirlen)
     356                  {
     357                    alloc = xmalloc (destdirlen + strlen (backup_base) + 1);
     358                    backup = memcpy (alloc, dest, destdirlen);
     359                    strcpy (backup + destdirlen, backup_base);
     360                  }
     361                quoted_backup = quoteaf_n (2, backup);
     362                backup_sep = " ~ ";
     363                free (alloc);
     364              }
     365            printf ("%s%s%s %c> %s\n", quoted_backup, backup_sep,
     366                    quoteaf_n (0, dest), symbolic_link ? '-' : '=',
     367                    quoteaf_n (1, source));
     368          }
     369      }
     370    else
     371      {
     372        error (0, link_errno,
     373               (symbolic_link
     374                ? (link_errno != ENAMETOOLONG && *source
     375                   ? _("failed to create symbolic link %s")
     376                   : _("failed to create symbolic link %s -> %s"))
     377                : (link_errno == EMLINK
     378                   ? _("failed to create hard link to %.0s%s")
     379                   : (link_errno == EDQUOT || link_errno == EEXIST
     380                      || link_errno == ENOSPC || link_errno == EROFS)
     381                   ? _("failed to create hard link %s")
     382                   : _("failed to create hard link %s => %s"))),
     383               quoteaf_n (0, dest), quoteaf_n (1, source));
     384  
     385        if (backup_base)
     386          {
     387            if (renameat (destdir_fd, backup_base, destdir_fd, dest_base) != 0)
     388              error (0, errno, _("cannot un-backup %s"), quoteaf (dest));
     389          }
     390      }
     391  
     392    free (backup_base);
     393    free (rel_source);
     394    return link_errno <= 0;
     395  
     396  fail:
     397    free (rel_source);
     398    return false;
     399  }
     400  
     401  void
     402  usage (int status)
     403  {
     404    if (status != EXIT_SUCCESS)
     405      emit_try_help ();
     406    else
     407      {
     408        printf (_("\
     409  Usage: %s [OPTION]... [-T] TARGET LINK_NAME\n\
     410    or:  %s [OPTION]... TARGET\n\
     411    or:  %s [OPTION]... TARGET... DIRECTORY\n\
     412    or:  %s [OPTION]... -t DIRECTORY TARGET...\n\
     413  "),
     414                program_name, program_name, program_name, program_name);
     415        fputs (_("\
     416  In the 1st form, create a link to TARGET with the name LINK_NAME.\n\
     417  In the 2nd form, create a link to TARGET in the current directory.\n\
     418  In the 3rd and 4th forms, create links to each TARGET in DIRECTORY.\n\
     419  Create hard links by default, symbolic links with --symbolic.\n\
     420  By default, each destination (name of new link) should not already exist.\n\
     421  When creating hard links, each TARGET must exist.  Symbolic links\n\
     422  can hold arbitrary text; if later resolved, a relative link is\n\
     423  interpreted in relation to its parent directory.\n\
     424  "), stdout);
     425  
     426        emit_mandatory_arg_note ();
     427  
     428        fputs (_("\
     429        --backup[=CONTROL]      make a backup of each existing destination file\n\
     430    -b                          like --backup but does not accept an argument\n\
     431    -d, -F, --directory         allow the superuser to attempt to hard link\n\
     432                                  directories (note: will probably fail due to\n\
     433                                  system restrictions, even for the superuser)\n\
     434    -f, --force                 remove existing destination files\n\
     435  "), stdout);
     436        fputs (_("\
     437    -i, --interactive           prompt whether to remove destinations\n\
     438    -L, --logical               dereference TARGETs that are symbolic links\n\
     439    -n, --no-dereference        treat LINK_NAME as a normal file if\n\
     440                                  it is a symbolic link to a directory\n\
     441    -P, --physical              make hard links directly to symbolic links\n\
     442    -r, --relative              with -s, create links relative to link location\n\
     443    -s, --symbolic              make symbolic links instead of hard links\n\
     444  "), stdout);
     445        fputs (_("\
     446    -S, --suffix=SUFFIX         override the usual backup suffix\n\
     447    -t, --target-directory=DIRECTORY  specify the DIRECTORY in which to create\n\
     448                                  the links\n\
     449    -T, --no-target-directory   treat LINK_NAME as a normal file always\n\
     450    -v, --verbose               print name of each linked file\n\
     451  "), stdout);
     452        fputs (HELP_OPTION_DESCRIPTION, stdout);
     453        fputs (VERSION_OPTION_DESCRIPTION, stdout);
     454        emit_backup_suffix_note ();
     455        printf (_("\
     456  \n\
     457  Using -s ignores -L and -P.  Otherwise, the last option specified controls\n\
     458  behavior when a TARGET is a symbolic link, defaulting to %s.\n\
     459  "), LINK_FOLLOWS_SYMLINKS ? "-L" : "-P");
     460        emit_ancillary_info (PROGRAM_NAME);
     461      }
     462    exit (status);
     463  }
     464  
     465  int
     466  main (int argc, char **argv)
     467  {
     468    int c;
     469    bool ok;
     470    bool make_backups = false;
     471    char const *backup_suffix = nullptr;
     472    char *version_control_string = nullptr;
     473    char const *target_directory = nullptr;
     474    int destdir_fd;
     475    bool no_target_directory = false;
     476    int n_files;
     477    char **file;
     478    int link_errno = -1;
     479  
     480    initialize_main (&argc, &argv);
     481    set_program_name (argv[0]);
     482    setlocale (LC_ALL, "");
     483    bindtextdomain (PACKAGE, LOCALEDIR);
     484    textdomain (PACKAGE);
     485  
     486    atexit (close_stdin);
     487  
     488    symbolic_link = remove_existing_files = interactive = verbose
     489      = hard_dir_link = false;
     490  
     491    while ((c = getopt_long (argc, argv, "bdfinrst:vFLPS:T",
     492                             long_options, nullptr))
     493           != -1)
     494      {
     495        switch (c)
     496          {
     497          case 'b':
     498            make_backups = true;
     499            if (optarg)
     500              version_control_string = optarg;
     501            break;
     502          case 'd':
     503          case 'F':
     504            hard_dir_link = true;
     505            break;
     506          case 'f':
     507            remove_existing_files = true;
     508            interactive = false;
     509            break;
     510          case 'i':
     511            remove_existing_files = false;
     512            interactive = true;
     513            break;
     514          case 'L':
     515            logical = true;
     516            break;
     517          case 'n':
     518            dereference_dest_dir_symlinks = false;
     519            break;
     520          case 'P':
     521            logical = false;
     522            break;
     523          case 'r':
     524            relative = true;
     525            break;
     526          case 's':
     527            symbolic_link = true;
     528            break;
     529          case 't':
     530            if (target_directory)
     531              error (EXIT_FAILURE, 0, _("multiple target directories specified"));
     532            else
     533              {
     534                struct stat st;
     535                if (stat (optarg, &st) != 0)
     536                  error (EXIT_FAILURE, errno, _("failed to access %s"),
     537                         quoteaf (optarg));
     538                if (! S_ISDIR (st.st_mode))
     539                  error (EXIT_FAILURE, 0, _("target %s is not a directory"),
     540                         quoteaf (optarg));
     541              }
     542            target_directory = optarg;
     543            break;
     544          case 'T':
     545            no_target_directory = true;
     546            break;
     547          case 'v':
     548            verbose = true;
     549            break;
     550          case 'S':
     551            make_backups = true;
     552            backup_suffix = optarg;
     553            break;
     554          case_GETOPT_HELP_CHAR;
     555          case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
     556          default:
     557            usage (EXIT_FAILURE);
     558            break;
     559          }
     560      }
     561  
     562    n_files = argc - optind;
     563    file = argv + optind;
     564  
     565    if (n_files <= 0)
     566      {
     567        error (0, 0, _("missing file operand"));
     568        usage (EXIT_FAILURE);
     569      }
     570  
     571    if (relative && !symbolic_link)
     572      error (EXIT_FAILURE, 0, _("cannot do --relative without --symbolic"));
     573  
     574    if (!hard_dir_link)
     575      {
     576        priv_set_remove_linkdir ();
     577        beware_hard_dir_link = !cannot_unlink_dir ();
     578      }
     579  
     580    if (no_target_directory)
     581      {
     582        if (target_directory)
     583          error (EXIT_FAILURE, 0,
     584                 _("cannot combine --target-directory "
     585                   "and --no-target-directory"));
     586        if (n_files != 2)
     587          {
     588            if (n_files < 2)
     589              error (0, 0,
     590                     _("missing destination file operand after %s"),
     591                     quoteaf (file[0]));
     592            else
     593              error (0, 0, _("extra operand %s"), quoteaf (file[2]));
     594            usage (EXIT_FAILURE);
     595          }
     596      }
     597    else if (n_files < 2 && !target_directory)
     598      {
     599        target_directory = ".";
     600        destdir_fd = AT_FDCWD;
     601      }
     602    else
     603      {
     604        if (n_files == 2 && !target_directory)
     605          link_errno = atomic_link (file[0], AT_FDCWD, file[1]);
     606        if (link_errno < 0 || link_errno == EEXIST || link_errno == ENOTDIR
     607            || link_errno == EINVAL)
     608          {
     609            char const *d
     610              = target_directory ? target_directory : file[n_files - 1];
     611            int flags = (O_PATHSEARCH | O_DIRECTORY
     612                         | (dereference_dest_dir_symlinks ? 0 : O_NOFOLLOW));
     613            destdir_fd = openat_safer (AT_FDCWD, d, flags);
     614            int err = errno;
     615            if (!O_DIRECTORY && 0 <= destdir_fd)
     616              {
     617                struct stat st;
     618                err = (fstat (destdir_fd, &st) != 0 ? errno
     619                       : S_ISDIR (st.st_mode) ? 0 : ENOTDIR);
     620                if (err != 0)
     621                  {
     622                    close (destdir_fd);
     623                    destdir_fd = -1;
     624                  }
     625              }
     626            if (0 <= destdir_fd)
     627              {
     628                n_files -= !target_directory;
     629                target_directory = d;
     630              }
     631            else if (! (n_files == 2 && !target_directory))
     632              error (EXIT_FAILURE, err, _("target %s"), quoteaf (d));
     633          }
     634      }
     635  
     636    backup_type = (make_backups
     637                   ? xget_version (_("backup type"), version_control_string)
     638                   : no_backups);
     639    set_simple_backup_suffix (backup_suffix);
     640  
     641  
     642    if (target_directory)
     643      {
     644        /* Create the data structure we'll use to record which hard links we
     645           create.  Used to ensure that ln detects an obscure corner case that
     646           might result in user data loss.  Create it only if needed.  */
     647        if (2 <= n_files
     648            && remove_existing_files
     649            /* Don't bother trying to protect symlinks, since ln clobbering
     650               a just-created symlink won't ever lead to real data loss.  */
     651            && ! symbolic_link
     652            /* No destination hard link can be clobbered when making
     653               numbered backups.  */
     654            && backup_type != numbered_backups)
     655          {
     656            dest_set = hash_initialize (DEST_INFO_INITIAL_CAPACITY,
     657                                        nullptr,
     658                                        triple_hash,
     659                                        triple_compare,
     660                                        triple_free);
     661            if (dest_set == nullptr)
     662              xalloc_die ();
     663          }
     664  
     665        ok = true;
     666        for (int i = 0; i < n_files; ++i)
     667          {
     668            char *dest_base;
     669            char *dest = file_name_concat (target_directory,
     670                                           last_component (file[i]),
     671                                           &dest_base);
     672            strip_trailing_slashes (dest_base);
     673            ok &= do_link (file[i], destdir_fd, dest_base, dest, -1);
     674            free (dest);
     675          }
     676      }
     677    else
     678      ok = do_link (file[0], AT_FDCWD, file[1], file[1], link_errno);
     679  
     680    main_exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
     681  }