/* 'ln' program to create links between files.                                  This is the ln utility
   Copyright (C) 1986-2018 Free Software Foundation, Inc.                       
                                                                                
   This program is free software: you can redistribute it and/or modify         
   it under the terms of the GNU General Public License as published by         
   the Free Software Foundation, either version 3 of the License, or            
   (at your option) any later version.                                          
                                                                                
   This program is distributed in the hope that it will be useful,              
   but WITHOUT ANY WARRANTY; without even the implied warranty of               
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
   GNU General Public License for more details.                                 
                                                                                
   You should have received a copy of the GNU General Public License            
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */   The GNUv3 license
                                                                                
/* Written by Mike Parker and David MacKenzie. */                               
                                                                                
#include <config.h>                                                             Provides system specific information
#include <stdio.h>                                                              Provides standard I/O capability
#include <sys/types.h>                                                          Provides system data types
#include <getopt.h>                                                             ...!includes auto-comment...
                                                                                
#include "system.h"                                                             ...!includes auto-comment...
#include "backupfile.h"                                                         ...!includes auto-comment...
#include "die.h"                                                                ...!includes auto-comment...
#include "error.h"                                                              ...!includes auto-comment...
#include "filenamecat.h"                                                        ...!includes auto-comment...
#include "file-set.h"                                                           ...!includes auto-comment...
#include "force-link.h"                                                         ...!includes auto-comment...
#include "hash.h"                                                               ...!includes auto-comment...
#include "hash-triple.h"                                                        ...!includes auto-comment...
#include "relpath.h"                                                            ...!includes auto-comment...
#include "same.h"                                                               ...!includes auto-comment...
#include "yesno.h"                                                              ...!includes auto-comment...
#include "canonicalize.h"                                                       ...!includes auto-comment...
                                                                                
/* The official name of this program (e.g., no 'g' prefix).  */                 
#define PROGRAM_NAME "ln"                                                       Line 39
                                                                                
#define AUTHORS \                                                               Line 41
  proper_name ("Mike Parker"), \                                                Line 42
  proper_name ("David MacKenzie")                                               Line 43
                                                                                
/* FIXME: document */                                                           
static enum backup_type backup_type;                                            Line 46
                                                                                
/* If true, make symbolic links; otherwise, make hard links.  */                
static bool symbolic_link;                                                      Line 49
                                                                                
/* If true, make symbolic links relative  */                                    
static bool relative;                                                           Line 52
                                                                                
/* If true, hard links are logical rather than physical.  */                    
static bool logical = !!LINK_FOLLOWS_SYMLINKS;                                  Line 55
                                                                                
/* If true, ask the user before removing existing files.  */                    
static bool interactive;                                                        Line 58
                                                                                
/* If true, remove existing files unconditionally.  */                          
static bool remove_existing_files;                                              Line 61
                                                                                
/* If true, list each file as it is moved. */                                   
static bool verbose;                                                            Line 64
                                                                                
/* If true, allow the superuser to *attempt* to make hard links                 
   to directories.  However, it appears that this option is not useful          
   in practice, since even the superuser is prohibited from hard-linking        
   directories on most existing systems (Solaris being an exception).  */       
static bool hard_dir_link;                                                      Line 70
                                                                                
/* If nonzero, and the specified destination is a symbolic link to a            
   directory, treat it just as if it were a directory.  Otherwise, the          
   command 'ln --force --no-dereference file symlink-to-dir' deletes            
   symlink-to-dir before creating the new link.  */                             
static bool dereference_dest_dir_symlinks = true;                               Line 76
                                                                                
/* This is a set of destination name/inode/dev triples for hard links           
   created by ln.  Use this data structure to avoid data loss via a             
   sequence of commands like this:                                              
   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 */    
static Hash_table *dest_set;                                                    Line 82
                                                                                
/* Initial size of the dest_set hash table.  */                                 
enum { DEST_INFO_INITIAL_CAPACITY = 61 };                                       Line 85
                                                                                
static struct option const long_options[] =                                     Line 87
{                                                                               
  {"backup", optional_argument, NULL, 'b'},                                     Line 89
  {"directory", no_argument, NULL, 'F'},                                        Line 90
  {"no-dereference", no_argument, NULL, 'n'},                                   Line 91
  {"no-target-directory", no_argument, NULL, 'T'},                              Line 92
  {"force", no_argument, NULL, 'f'},                                            Line 93
  {"interactive", no_argument, NULL, 'i'},                                      Line 94
  {"suffix", required_argument, NULL, 'S'},                                     Line 95
  {"target-directory", required_argument, NULL, 't'},                           Line 96
  {"logical", no_argument, NULL, 'L'},                                          Line 97
  {"physical", no_argument, NULL, 'P'},                                         Line 98
  {"relative", no_argument, NULL, 'r'},                                         Line 99
  {"symbolic", no_argument, NULL, 's'},                                         Line 100
  {"verbose", no_argument, NULL, 'v'},                                          Line 101
  {GETOPT_HELP_OPTION_DECL},                                                    Line 102
  {GETOPT_VERSION_OPTION_DECL},                                                 Line 103
  {NULL, 0, NULL, 0}                                                            Line 104
};                                                                              Block 2
                                                                                
/* Return true when the passed ERR implies                                      
   that a file does not or could not exist.  */                                 
                                                                                
static bool                                                                     Line 110
errno_nonexisting (int err)                                                     Line 111
{                                                                               
  return err == ENOENT || err == ENAMETOOLONG || err == ENOTDIR || err == ELOOP;Line 113
}                                                                               Block 3
                                                                                
                                                                                
/* FILE is the last operand of this command.  Return true if FILE is a          
   directory.  But report an error if there is a problem accessing FILE,        
   or if FILE does not exist but would have to refer to an existing             
   directory if it referred to anything at all.  */                             
                                                                                
static bool                                                                     Line 122
target_directory_operand (char const *file)                                     Line 123
{                                                                               
  char const *b = last_component (file);                                        Line 125
  size_t blen = strlen (b);                                                     Line 126
  bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));                 Line 127
  struct stat st;                                                               Line 128
  int stat_result =                                                             Line 129
    (dereference_dest_dir_symlinks ? stat (file, &st) : lstat (file, &st));     Line 130...!syscalls auto-comment...
  int err = (stat_result == 0 ? 0 : errno);                                     Line 131
  bool is_a_dir = !err && S_ISDIR (st.st_mode);                                 Line 132
  if (err && ! errno_nonexisting (errno))                                       Line 133
    die (EXIT_FAILURE, err, _("failed to access %s"), quoteaf (file));          Line 134
  if (is_a_dir < looks_like_a_dir)                                              Line 135
    die (EXIT_FAILURE, err, _("target %s is not a directory"),                  Line 136
         quoteaf (file));                                                       Line 137
  return is_a_dir;                                                              Line 138
}                                                                               Block 4
                                                                                
/* Return FROM represented as relative to the dir of TARGET.                    
   The result is malloced.  */                                                  
                                                                                
static char *                                                                   Line 144
convert_abs_rel (const char *from, const char *target)                          Line 145
{                                                                               
  /* Get dirname to generate paths relative to.  We don't resolve               
     the full TARGET as the last component could be an existing symlink.  */    
  char *targetdir = dir_name (target);                                          Line 149
                                                                                
  char *realdest = canonicalize_filename_mode (targetdir, CAN_MISSING);         Line 151
  char *realfrom = canonicalize_filename_mode (from, CAN_MISSING);              Line 152
                                                                                
  char *relative_from = NULL;                                                   Line 154
  if (realdest && realfrom)                                                     Line 155
    {                                                                           
      /* Write to a PATH_MAX buffer.  */                                        
      relative_from = xmalloc (PATH_MAX);                                       Line 158
                                                                                
      if (!relpath (realfrom, realdest, relative_from, PATH_MAX))               Line 160
        {                                                                       
          free (relative_from);                                                 Line 162
          relative_from = NULL;                                                 Line 163
        }                                                                       
    }                                                                           
                                                                                
  free (targetdir);                                                             Line 167
  free (realdest);                                                              Line 168
  free (realfrom);                                                              Line 169
                                                                                
  return relative_from ? relative_from : xstrdup (from);                        Line 171
}                                                                               
                                                                                
/* Make a link DEST to the (usually) existing file SOURCE.                      
   Symbolic links to nonexistent files are allowed.                             
   Return true if successful.  */                                               
                                                                                
static bool                                                                     Line 178
do_link (const char *source, const char *dest)                                  Line 179...!syscalls auto-comment...
{                                                                               
  struct stat source_stats;                                                     Line 181
  struct stat dest_stats;                                                       Line 182
  char *dest_backup = NULL;                                                     Line 183
  char *rel_source = NULL;                                                      Line 184
  bool dest_lstat_ok = false;                                                   Line 185
  bool source_is_dir = false;                                                   Line 186
                                                                                
  if (!symbolic_link)                                                           Line 188
    {                                                                           
       /* Which stat to use depends on whether linkat will follow the           
          symlink.  We can't use the shorter                                    
          (logical?stat:lstat) (source, &source_stats)                          
          since stat might be a function-like macro.  */                        
      if ((logical ? stat (source, &source_stats)                               Line 194...!syscalls auto-comment...
           : lstat (source, &source_stats))                                     Line 195...!syscalls auto-comment...
          != 0)                                                                 Line 196
        {                                                                       
          error (0, errno, _("failed to access %s"), quoteaf (source));         Line 198
          return false;                                                         Line 199
        }                                                                       
                                                                                
      if (S_ISDIR (source_stats.st_mode))                                       Line 202
        {                                                                       
          source_is_dir = true;                                                 Line 204
          if (! hard_dir_link)                                                  Line 205
            {                                                                   
              error (0, 0, _("%s: hard link not allowed for directory"),        Line 207
                     quotef (source));                                          Line 208
              return false;                                                     Line 209
            }                                                                   
        }                                                                       
    }                                                                           
                                                                                
  if (remove_existing_files || interactive || backup_type != no_backups)        Line 214
    {                                                                           
      dest_lstat_ok = (lstat (dest, &dest_stats) == 0);                         Line 216...!syscalls auto-comment...
      if (!dest_lstat_ok && errno != ENOENT)                                    Line 217
        {                                                                       
          error (0, errno, _("failed to access %s"), quoteaf (dest));           Line 219
          return false;                                                         Line 220
        }                                                                       
    }                                                                           
                                                                                
  /* If the current target was created as a hard link to another                
     source file, then refuse to unlink it.  */                                 
  if (dest_lstat_ok                                                             Line 226
      && dest_set != NULL                                                       Line 227
      && seen_file (dest_set, dest, &dest_stats))                               Line 228
    {                                                                           
      error (0, 0,                                                              Line 230
             _("will not overwrite just-created %s with %s"),                   Line 231
             quoteaf_n (0, dest), quoteaf_n (1, source));                       Line 232
      return false;                                                             Line 233
    }                                                                           
                                                                                
  /* If --force (-f) has been specified without --backup, then before           
     making a link ln must remove the destination file if it exists.            
     (with --backup, it just renames any existing destination file)             
     But if the source and destination are the same, don't remove               
     anything and fail right here.  */                                          
  if ((remove_existing_files                                                    Line 241
       /* Ensure that "ln --backup f f" fails here, with the                    
          "... same file" diagnostic, below.  Otherwise, subsequent             
          code would give a misleading "file not found" diagnostic.             
          This case is different than the others handled here, since            
          the command in question doesn't use --force.  */                      
       || (!symbolic_link && backup_type != no_backups))                        Line 247
      && dest_lstat_ok                                                          Line 248
      /* Allow 'ln -sf --backup k k' to succeed in creating the                 
         self-referential symlink, but don't allow the hard-linking             
         equivalent: 'ln -f k k' (with or without --backup) to get              
         beyond this point, because the error message you'd get is              
         misleading.  */                                                        
      && (backup_type == no_backups || !symbolic_link)                          Line 254
      && (!symbolic_link || stat (source, &source_stats) == 0)                  Line 255...!syscalls auto-comment...
      && SAME_INODE (source_stats, dest_stats)                                  Line 256
      /* The following detects whether removing DEST will also remove           
         SOURCE.  If the file has only one link then both are surely            
         the same link.  Otherwise check whether they point to the same         
         name in the same directory.  */                                        
      && (source_stats.st_nlink == 1 || same_name (source, dest)))              Line 261
    {                                                                           
      error (0, 0, _("%s and %s are the same file"),                            Line 263
             quoteaf_n (0, source), quoteaf_n (1, dest));                       Line 264
      return false;                                                             Line 265
    }                                                                           
                                                                                
  if (dest_lstat_ok)                                                            Line 268
    {                                                                           
      if (S_ISDIR (dest_stats.st_mode))                                         Line 270
        {                                                                       
          error (0, 0, _("%s: cannot overwrite directory"), quotef (dest));     Line 272
          return false;                                                         Line 273
        }                                                                       
      if (interactive)                                                          Line 275
        {                                                                       
          fprintf (stderr, _("%s: replace %s? "), program_name, quoteaf (dest));Line 277
          if (!yesno ())                                                        Line 278
            return true;                                                        Line 279
          remove_existing_files = true;                                         Line 280
        }                                                                       
                                                                                
      if (backup_type != no_backups)                                            Line 283
        {                                                                       
          dest_backup = find_backup_file_name (dest, backup_type);              Line 285
          if (rename (dest, dest_backup) != 0)                                  Line 286
            {                                                                   
              int rename_errno = errno;                                         Line 288
              free (dest_backup);                                               Line 289
              dest_backup = NULL;                                               Line 290
              if (rename_errno != ENOENT)                                       Line 291
                {                                                               
                  error (0, rename_errno, _("cannot backup %s"),                Line 293
                         quoteaf (dest));                                       Line 294
                  return false;                                                 Line 295
                }                                                               
            }                                                                   
        }                                                                       
    }                                                                           
                                                                                
  if (relative)                                                                 Line 301
    source = rel_source = convert_abs_rel (source, dest);                       Line 302
                                                                                
  /* If the attempt to create a link fails and we are removing or               
     backing up destinations, unlink the destination and try again.             
                                                                                
     On the surface, POSIX describes an algorithm that states that              
     'ln -f A B' will call unlink() on B before ever attempting                 
     link() on A.  But strictly following this has the counterintuitive         
     effect of losing the contents of B, if A does not exist.                   
     Fortunately, POSIX 2008 clarified that an application is free              
     to fail early if it can prove that continuing onwards cannot               
     succeed, so we are justified in trying link() before blindly               
     removing B, thus sometimes calling link() a second time during             
     a successful 'ln -f A B'.                                                  
                                                                                
     Try to unlink DEST even if we may have backed it up successfully.          
     In some unusual cases (when DEST and DEST_BACKUP are hard-links            
     that refer to the same file), rename succeeds and DEST remains.            
     If we didn't remove DEST in that case, the subsequent symlink or link      
     call would fail.  */                                                       
  bool ok_to_remove = remove_existing_files || dest_backup;                     Line 322
  bool ok = 0 <= (symbolic_link                                                 Line 323
                  ? force_symlinkat (source, AT_FDCWD, dest, ok_to_remove)      Line 324...!syscalls auto-comment...
                  : force_linkat (AT_FDCWD, source, AT_FDCWD, dest,             Line 325...!syscalls auto-comment...
                                  logical ? AT_SYMLINK_FOLLOW : 0,              Line 326
                                  ok_to_remove));                               Line 327
                                                                                
  if (ok)                                                                       Line 329
    {                                                                           
      /* Right after creating a hard link, do this: (note dest name and         
         source_stats, which are also the just-linked-destinations stats) */    
      if (! symbolic_link)                                                      Line 333
        record_file (dest_set, dest, &source_stats);                            Line 334
                                                                                
      if (verbose)                                                              Line 336
        {                                                                       
          if (dest_backup)                                                      Line 338
            printf ("%s ~ ", quoteaf (dest_backup));                            Line 339
          printf ("%s %c> %s\n", quoteaf_n (0, dest),                           Line 340
                  (symbolic_link ? '-' : '='), quoteaf_n (1, source));          Line 341
        }                                                                       
    }                                                                           
  else                                                                          Line 344
    {                                                                           
      error (0, errno,                                                          Line 346
             (symbolic_link                                                     Line 347
              ? (errno != ENAMETOOLONG && *source                               Line 348
                 ? _("failed to create symbolic link %s")                       Line 349
                 : _("failed to create symbolic link %s -> %s"))                Line 350
              : (errno == EMLINK && !source_is_dir                              Line 351
                 ? _("failed to create hard link to %.0s%s")                    Line 352
                 : (errno == EDQUOT || errno == EEXIST || errno == ENOSPC       Line 353
                    || errno == EROFS)                                          Line 354
                 ? _("failed to create hard link %s")                           Line 355
                 : _("failed to create hard link %s => %s"))),                  Line 356
             quoteaf_n (0, dest), quoteaf_n (1, source));                       Line 357
                                                                                
      if (dest_backup)                                                          Line 359
        {                                                                       
          if (rename (dest_backup, dest) != 0)                                  Line 361
            error (0, errno, _("cannot un-backup %s"), quoteaf (dest));         Line 362
        }                                                                       
    }                                                                           
                                                                                
  free (dest_backup);                                                           Line 366
  free (rel_source);                                                            Line 367
  return ok;                                                                    Line 368
}                                                                               Block 6
                                                                                
void                                                                            Line 371
usage (int status)                                                              Line 372
{                                                                               
  if (status != EXIT_SUCCESS)                                                   Line 374
    emit_try_help ();                                                           ...!common auto-comment...
  else                                                                          Line 376
    {                                                                           
      printf (_("\                                                              Line 378
Usage: %s [OPTION]... [-T] TARGET LINK_NAME\n\                                  Line 379
  or:  %s [OPTION]... TARGET\n\                                                 Line 380
  or:  %s [OPTION]... TARGET... DIRECTORY\n\                                    Line 381
  or:  %s [OPTION]... -t DIRECTORY TARGET...\n\                                 Line 382
"),                                                                             Line 383
              program_name, program_name, program_name, program_name);          Line 384
      fputs (_("\                                                               Line 385
In the 1st form, create a link to TARGET with the name LINK_NAME.\n\            Line 386
In the 2nd form, create a link to TARGET in the current directory.\n\           Line 387
In the 3rd and 4th forms, create links to each TARGET in DIRECTORY.\n\          Line 388
Create hard links by default, symbolic links with --symbolic.\n\                Line 389
By default, each destination (name of new link) should not already exist.\n\    Line 390
When creating hard links, each TARGET must exist.  Symbolic links\n\            Line 391
can hold arbitrary text; if later resolved, a relative link is\n\               Line 392
interpreted in relation to its parent directory.\n\                             Line 393
"), stdout);                                                                    Line 394
                                                                                
      emit_mandatory_arg_note ();                                               ...!common auto-comment...
                                                                                
      fputs (_("\                                                               Line 398
      --backup[=CONTROL]      make a backup of each existing destination file\n\Line 399
  -b                          like --backup but does not accept an argument\n\  Line 400
  -d, -F, --directory         allow the superuser to attempt to hard link\n\    Line 401
                                directories (note: will probably fail due to\n\ Line 402
                                system restrictions, even for the superuser)\n\ Line 403
  -f, --force                 remove existing destination files\n\              Line 404
"), stdout);                                                                    Line 405
      fputs (_("\                                                               Line 406
  -i, --interactive           prompt whether to remove destinations\n\          Line 407
  -L, --logical               dereference TARGETs that are symbolic links\n\    Line 408
  -n, --no-dereference        treat LINK_NAME as a normal file if\n\            Line 409
                                it is a symbolic link to a directory\n\         Line 410
  -P, --physical              make hard links directly to symbolic links\n\     Line 411
  -r, --relative              create symbolic links relative to link location\n\Line 412
  -s, --symbolic              make symbolic links instead of hard links\n\      Line 413
"), stdout);                                                                    Line 414
      fputs (_("\                                                               Line 415
  -S, --suffix=SUFFIX         override the usual backup suffix\n\               Line 416
  -t, --target-directory=DIRECTORY  specify the DIRECTORY in which to create\n\ Line 417
                                the links\n\                                    Line 418
  -T, --no-target-directory   treat LINK_NAME as a normal file always\n\        Line 419
  -v, --verbose               print name of each linked file\n\                 Line 420
"), stdout);                                                                    Line 421
      fputs (HELP_OPTION_DESCRIPTION, stdout);                                  Line 422
      fputs (VERSION_OPTION_DESCRIPTION, stdout);                               Line 423
      emit_backup_suffix_note ();                                               Line 424
      printf (_("\                                                              Line 425
\n\                                                                             
Using -s ignores -L and -P.  Otherwise, the last option specified controls\n\   Line 427
behavior when a TARGET is a symbolic link, defaulting to %s.\n\                 Line 428
"), LINK_FOLLOWS_SYMLINKS ? "-L" : "-P");                                       Line 429
      emit_ancillary_info (PROGRAM_NAME);                                       Line 430
    }                                                                           
  exit (status);                                                                Line 432
}                                                                               Block 7
                                                                                
int                                                                             
main (int argc, char **argv)                                                    Line 436
{                                                                               
  int c;                                                                        Line 438
  bool ok;                                                                      Line 439
  bool make_backups = false;                                                    Line 440
  char const *backup_suffix = NULL;                                             Line 441
  char *version_control_string = NULL;                                          Line 442
  char const *target_directory = NULL;                                          Line 443
  bool no_target_directory = false;                                             Line 444
  int n_files;                                                                  Line 445
  char **file;                                                                  Line 446
                                                                                
  initialize_main (&argc, &argv);                                               VMS-specific entry point handling wildcard expansion
  set_program_name (argv[0]);                                                   Retains program name and discards path
  setlocale (LC_ALL, "");                                                       Sets up internationalization (i18n)
  bindtextdomain (PACKAGE, LOCALEDIR);                                          Assigns i18n directorySets text domain for _() [gettext()] function
  textdomain (PACKAGE);                                                         Sets text domain for _() [gettext()] function
                                                                                
  atexit (close_stdin);                                                         Close stdout on exit (see gnulib)
                                                                                
  symbolic_link = remove_existing_files = interactive = verbose                 Line 456
    = hard_dir_link = false;                                                    Line 457
                                                                                
  while ((c = getopt_long (argc, argv, "bdfinrst:vFLPS:T", long_options, NULL)) Line 459
         != -1)                                                                 Line 460
    {                                                                           
      switch (c)                                                                Line 462
        {                                                                       
        case 'b':                                                               Line 464
          make_backups = true;                                                  Line 465
          if (optarg)                                                           Line 466
            version_control_string = optarg;                                    Line 467
          break;                                                                Line 468
        case 'd':                                                               Line 469
        case 'F':                                                               Line 470
          hard_dir_link = true;                                                 Line 471
          break;                                                                Line 472
        case 'f':                                                               Line 473
          remove_existing_files = true;                                         Line 474
          interactive = false;                                                  Line 475
          break;                                                                Line 476
        case 'i':                                                               Line 477
          remove_existing_files = false;                                        Line 478
          interactive = true;                                                   Line 479
          break;                                                                Line 480
        case 'L':                                                               Line 481
          logical = true;                                                       Line 482
          break;                                                                Line 483
        case 'n':                                                               Line 484
          dereference_dest_dir_symlinks = false;                                Line 485
          break;                                                                Line 486
        case 'P':                                                               Line 487
          logical = false;                                                      Line 488
          break;                                                                Line 489
        case 'r':                                                               Line 490
          relative = true;                                                      Line 491
          break;                                                                Line 492
        case 's':                                                               Line 493
          symbolic_link = true;                                                 Line 494
          break;                                                                Line 495
        case 't':                                                               Line 496
          if (target_directory)                                                 Line 497
            die (EXIT_FAILURE, 0, _("multiple target directories specified"));  Line 498
          else                                                                  Line 499
            {                                                                   
              struct stat st;                                                   Line 501
              if (stat (optarg, &st) != 0)                                      Line 502...!syscalls auto-comment...
                die (EXIT_FAILURE, errno, _("failed to access %s"),             Line 503
                     quoteaf (optarg));                                         Line 504
              if (! S_ISDIR (st.st_mode))                                       Line 505
                die (EXIT_FAILURE, 0, _("target %s is not a directory"),        Line 506
                     quoteaf (optarg));                                         Line 507
            }                                                                   
          target_directory = optarg;                                            Line 509
          break;                                                                Line 510
        case 'T':                                                               Line 511
          no_target_directory = true;                                           Line 512
          break;                                                                Line 513
        case 'v':                                                               Line 514
          verbose = true;                                                       Line 515
          break;                                                                Line 516
        case 'S':                                                               Line 517
          make_backups = true;                                                  Line 518
          backup_suffix = optarg;                                               Line 519
          break;                                                                Line 520
        case_GETOPT_HELP_CHAR;                                                  Line 521
        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);                       Line 522
        default:                                                                Line 523
          usage (EXIT_FAILURE);                                                 Line 524
          break;                                                                Line 525
        }                                                                       
    }                                                                           
                                                                                
  n_files = argc - optind;                                                      Line 529
  file = argv + optind;                                                         Line 530
                                                                                
  if (n_files <= 0)                                                             Line 532
    {                                                                           
      error (0, 0, _("missing file operand"));                                  Line 534
      usage (EXIT_FAILURE);                                                     Line 535
    }                                                                           
                                                                                
  if (no_target_directory)                                                      Line 538
    {                                                                           
      if (target_directory)                                                     Line 540
        die (EXIT_FAILURE, 0,                                                   Line 541
             _("cannot combine --target-directory "                             Line 542
               "and --no-target-directory"));                                   Line 543
      if (n_files != 2)                                                         Line 544
        {                                                                       
          if (n_files < 2)                                                      Line 546
            error (0, 0,                                                        Line 547
                   _("missing destination file operand after %s"),              Line 548
                   quoteaf (file[0]));                                          Line 549
          else                                                                  Line 550
            error (0, 0, _("extra operand %s"), quoteaf (file[2]));             Line 551
          usage (EXIT_FAILURE);                                                 Line 552
        }                                                                       
    }                                                                           
  else if (!target_directory)                                                   Line 555
    {                                                                           
      if (n_files < 2)                                                          Line 557
        target_directory = ".";                                                 Line 558
      else if (2 <= n_files && target_directory_operand (file[n_files - 1]))    Line 559
        target_directory = file[--n_files];                                     Line 560
      else if (2 < n_files)                                                     Line 561
        die (EXIT_FAILURE, 0, _("target %s is not a directory"),                Line 562
             quoteaf (file[n_files - 1]));                                      Line 563
    }                                                                           
                                                                                
  backup_type = (make_backups                                                   Line 566
                 ? xget_version (_("backup type"), version_control_string)      Line 567
                 : no_backups);                                                 Line 568
  set_simple_backup_suffix (backup_suffix);                                     Line 569
                                                                                
  if (relative && !symbolic_link)                                               Line 571
    {                                                                           
        die (EXIT_FAILURE, 0,                                                   Line 573
             _("cannot do --relative without --symbolic"));                     Line 574
    }                                                                           
                                                                                
                                                                                
  if (target_directory)                                                         Line 578
    {                                                                           
      /* Create the data structure we'll use to record which hard links we      
         create.  Used to ensure that ln detects an obscure corner case that    
         might result in user data loss.  Create it only if needed.  */         
      if (2 <= n_files                                                          Line 583
          && remove_existing_files                                              Line 584
          /* Don't bother trying to protect symlinks, since ln clobbering       
             a just-created symlink won't ever lead to real data loss.  */      
          && ! symbolic_link                                                    Line 587
          /* No destination hard link can be clobbered when making              
             numbered backups.  */                                              
          && backup_type != numbered_backups)                                   Line 590
                                                                                
        {                                                                       
          dest_set = hash_initialize (DEST_INFO_INITIAL_CAPACITY,               Line 593
                                      NULL,                                     Line 594
                                      triple_hash,                              Line 595
                                      triple_compare,                           Line 596
                                      triple_free);                             Line 597
          if (dest_set == NULL)                                                 Line 598
            xalloc_die ();                                                      ...!common auto-comment...
        }                                                                       
                                                                                
      ok = true;                                                                Line 602
      for (int i = 0; i < n_files; ++i)                                         Line 603
        {                                                                       
          char *dest_base;                                                      Line 605
          char *dest = file_name_concat (target_directory,                      Line 606
                                         last_component (file[i]),              Line 607
                                         &dest_base);                           Line 608
          strip_trailing_slashes (dest_base);                                   Line 609
          ok &= do_link (file[i], dest);                                        Line 610...!syscalls auto-comment...
          free (dest);                                                          Line 611
        }                                                                       
    }                                                                           
  else                                                                          Line 614
    ok = do_link (file[0], file[1]);                                            Line 615...!syscalls auto-comment...
                                                                                
  return ok ? EXIT_SUCCESS : EXIT_FAILURE;                                      Line 617
}                                                                               Block 8