| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/coreutils/src/src/ln.c |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /* 'ln' program to create links between files. | - | ||||||||||||||||||
| 2 | Copyright (C) 1986-2018 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 "die.h" | - | ||||||||||||||||||
| 27 | #include "error.h" | - | ||||||||||||||||||
| 28 | #include "filenamecat.h" | - | ||||||||||||||||||
| 29 | #include "file-set.h" | - | ||||||||||||||||||
| 30 | #include "force-link.h" | - | ||||||||||||||||||
| 31 | #include "hash.h" | - | ||||||||||||||||||
| 32 | #include "hash-triple.h" | - | ||||||||||||||||||
| 33 | #include "relpath.h" | - | ||||||||||||||||||
| 34 | #include "same.h" | - | ||||||||||||||||||
| 35 | #include "yesno.h" | - | ||||||||||||||||||
| 36 | #include "canonicalize.h" | - | ||||||||||||||||||
| 37 | - | |||||||||||||||||||
| 38 | /* The official name of this program (e.g., no 'g' prefix). */ | - | ||||||||||||||||||
| 39 | #define PROGRAM_NAME "ln" | - | ||||||||||||||||||
| 40 | - | |||||||||||||||||||
| 41 | #define AUTHORS \ | - | ||||||||||||||||||
| 42 | proper_name ("Mike Parker"), \ | - | ||||||||||||||||||
| 43 | proper_name ("David MacKenzie") | - | ||||||||||||||||||
| 44 | - | |||||||||||||||||||
| 45 | /* FIXME: document */ | - | ||||||||||||||||||
| 46 | static enum backup_type backup_type; | - | ||||||||||||||||||
| 47 | - | |||||||||||||||||||
| 48 | /* If true, make symbolic links; otherwise, make hard links. */ | - | ||||||||||||||||||
| 49 | static bool symbolic_link; | - | ||||||||||||||||||
| 50 | - | |||||||||||||||||||
| 51 | /* If true, make symbolic links relative */ | - | ||||||||||||||||||
| 52 | static bool relative; | - | ||||||||||||||||||
| 53 | - | |||||||||||||||||||
| 54 | /* If true, hard links are logical rather than physical. */ | - | ||||||||||||||||||
| 55 | static bool logical = !!LINK_FOLLOWS_SYMLINKS; | - | ||||||||||||||||||
| 56 | - | |||||||||||||||||||
| 57 | /* If true, ask the user before removing existing files. */ | - | ||||||||||||||||||
| 58 | static bool interactive; | - | ||||||||||||||||||
| 59 | - | |||||||||||||||||||
| 60 | /* If true, remove existing files unconditionally. */ | - | ||||||||||||||||||
| 61 | static bool remove_existing_files; | - | ||||||||||||||||||
| 62 | - | |||||||||||||||||||
| 63 | /* If true, list each file as it is moved. */ | - | ||||||||||||||||||
| 64 | static bool verbose; | - | ||||||||||||||||||
| 65 | - | |||||||||||||||||||
| 66 | /* If true, allow the superuser to *attempt* to make hard links | - | ||||||||||||||||||
| 67 | to directories. However, it appears that this option is not useful | - | ||||||||||||||||||
| 68 | in practice, since even the superuser is prohibited from hard-linking | - | ||||||||||||||||||
| 69 | directories on most existing systems (Solaris being an exception). */ | - | ||||||||||||||||||
| 70 | static bool hard_dir_link; | - | ||||||||||||||||||
| 71 | - | |||||||||||||||||||
| 72 | /* If nonzero, and the specified destination is a symbolic link to a | - | ||||||||||||||||||
| 73 | directory, treat it just as if it were a directory. Otherwise, the | - | ||||||||||||||||||
| 74 | command 'ln --force --no-dereference file symlink-to-dir' deletes | - | ||||||||||||||||||
| 75 | symlink-to-dir before creating the new link. */ | - | ||||||||||||||||||
| 76 | static bool dereference_dest_dir_symlinks = true; | - | ||||||||||||||||||
| 77 | - | |||||||||||||||||||
| 78 | /* This is a set of destination name/inode/dev triples for hard links | - | ||||||||||||||||||
| 79 | created by ln. Use this data structure to avoid data loss via a | - | ||||||||||||||||||
| 80 | sequence of commands like this: | - | ||||||||||||||||||
| 81 | 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 */ | - | ||||||||||||||||||
| 82 | static Hash_table *dest_set; | - | ||||||||||||||||||
| 83 | - | |||||||||||||||||||
| 84 | /* Initial size of the dest_set hash table. */ | - | ||||||||||||||||||
| 85 | enum { DEST_INFO_INITIAL_CAPACITY = 61 }; | - | ||||||||||||||||||
| 86 | - | |||||||||||||||||||
| 87 | static struct option const long_options[] = | - | ||||||||||||||||||
| 88 | { | - | ||||||||||||||||||
| 89 | {"backup", optional_argument, NULL, 'b'}, | - | ||||||||||||||||||
| 90 | {"directory", no_argument, NULL, 'F'}, | - | ||||||||||||||||||
| 91 | {"no-dereference", no_argument, NULL, 'n'}, | - | ||||||||||||||||||
| 92 | {"no-target-directory", no_argument, NULL, 'T'}, | - | ||||||||||||||||||
| 93 | {"force", no_argument, NULL, 'f'}, | - | ||||||||||||||||||
| 94 | {"interactive", no_argument, NULL, 'i'}, | - | ||||||||||||||||||
| 95 | {"suffix", required_argument, NULL, 'S'}, | - | ||||||||||||||||||
| 96 | {"target-directory", required_argument, NULL, 't'}, | - | ||||||||||||||||||
| 97 | {"logical", no_argument, NULL, 'L'}, | - | ||||||||||||||||||
| 98 | {"physical", no_argument, NULL, 'P'}, | - | ||||||||||||||||||
| 99 | {"relative", no_argument, NULL, 'r'}, | - | ||||||||||||||||||
| 100 | {"symbolic", no_argument, NULL, 's'}, | - | ||||||||||||||||||
| 101 | {"verbose", no_argument, NULL, 'v'}, | - | ||||||||||||||||||
| 102 | {GETOPT_HELP_OPTION_DECL}, | - | ||||||||||||||||||
| 103 | {GETOPT_VERSION_OPTION_DECL}, | - | ||||||||||||||||||
| 104 | {NULL, 0, NULL, 0} | - | ||||||||||||||||||
| 105 | }; | - | ||||||||||||||||||
| 106 | - | |||||||||||||||||||
| 107 | /* Return true when the passed ERR implies | - | ||||||||||||||||||
| 108 | that a file does not or could not exist. */ | - | ||||||||||||||||||
| 109 | - | |||||||||||||||||||
| 110 | static bool | - | ||||||||||||||||||
| 111 | errno_nonexisting (int err) | - | ||||||||||||||||||
| 112 | { | - | ||||||||||||||||||
| 113 | return err == ENOENT || err == ENAMETOOLONG || err == ENOTDIR || err == ELOOP; executed 754 times by 1 test: return err == 2 || err == 36 || err == 20 || err == 40 ;Executed by:
| 754 | ||||||||||||||||||
| 114 | } | - | ||||||||||||||||||
| 115 | - | |||||||||||||||||||
| 116 | - | |||||||||||||||||||
| 117 | /* FILE is the last operand of this command. Return true if FILE is a | - | ||||||||||||||||||
| 118 | directory. But report an error if there is a problem accessing FILE, | - | ||||||||||||||||||
| 119 | or if FILE does not exist but would have to refer to an existing | - | ||||||||||||||||||
| 120 | directory if it referred to anything at all. */ | - | ||||||||||||||||||
| 121 | - | |||||||||||||||||||
| 122 | static bool | - | ||||||||||||||||||
| 123 | target_directory_operand (char const *file) | - | ||||||||||||||||||
| 124 | { | - | ||||||||||||||||||
| 125 | char const *b = last_component (file); | - | ||||||||||||||||||
| 126 | size_t blen = strlen (b); | - | ||||||||||||||||||
| 127 | bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));
| 1-775 | ||||||||||||||||||
| 128 | struct stat st; | - | ||||||||||||||||||
| 129 | int stat_result = | - | ||||||||||||||||||
| 130 | (dereference_dest_dir_symlinks ? stat (file, &st) : lstat (file, &st));
| 46-730 | ||||||||||||||||||
| 131 | int err = (stat_result == 0 ? 0 : errno);
| 22-754 | ||||||||||||||||||
| 132 | bool is_a_dir = !err && S_ISDIR (st.st_mode);
| 11-754 | ||||||||||||||||||
| 133 | if (err && ! errno_nonexisting (errno))
| 0-754 | ||||||||||||||||||
| 134 | die (EXIT_FAILURE, err, _("failed to access %s"), quoteaf (file)); never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, err, dcgettext (((void *)0), \"failed to access %s\", 5), quotearg_style (shell_escape_always_quoting_style, file)), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 , e...s_quoting_style, file)), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , err, dcgettext (((void *)0), "failed to access %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))); | 0 | ||||||||||||||||||
| 135 | if (is_a_dir < looks_like_a_dir)
| 1-775 | ||||||||||||||||||
| 136 | die (EXIT_FAILURE, err, _("target %s is not a directory"), executed 1 time by 1 test: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, err, dcgettext (((void *)0), \"target %s is not a directory\", 5), quotearg_style (shell_escape_always_quoting_style, file)), assume (false))" ")"); int _gl_dummy; })) ? ((erro...style, file)), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , err, dcgettext (((void *)0), "target %s is not a directory" , 5) , quotearg_style (shell_escape_always_quoting_style, file)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;Executed by:
| 1 | ||||||||||||||||||
| 137 | quoteaf (file)); executed 1 time by 1 test: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, err, dcgettext (((void *)0), \"target %s is not a directory\", 5), quotearg_style (shell_escape_always_quoting_style, file)), assume (false))" ")"); int _gl_dummy; })) ? ((erro...style, file)), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , err, dcgettext (((void *)0), "target %s is not a directory" , 5) , quotearg_style (shell_escape_always_quoting_style, file)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;Executed by:
| 1 | ||||||||||||||||||
| 138 | return is_a_dir; executed 775 times by 1 test: return is_a_dir;Executed by:
| 775 | ||||||||||||||||||
| 139 | } | - | ||||||||||||||||||
| 140 | - | |||||||||||||||||||
| 141 | /* Return FROM represented as relative to the dir of TARGET. | - | ||||||||||||||||||
| 142 | The result is malloced. */ | - | ||||||||||||||||||
| 143 | - | |||||||||||||||||||
| 144 | static char * | - | ||||||||||||||||||
| 145 | convert_abs_rel (const char *from, const char *target) | - | ||||||||||||||||||
| 146 | { | - | ||||||||||||||||||
| 147 | /* Get dirname to generate paths relative to. We don't resolve | - | ||||||||||||||||||
| 148 | the full TARGET as the last component could be an existing symlink. */ | - | ||||||||||||||||||
| 149 | char *targetdir = dir_name (target); | - | ||||||||||||||||||
| 150 | - | |||||||||||||||||||
| 151 | char *realdest = canonicalize_filename_mode (targetdir, CAN_MISSING); | - | ||||||||||||||||||
| 152 | char *realfrom = canonicalize_filename_mode (from, CAN_MISSING); | - | ||||||||||||||||||
| 153 | - | |||||||||||||||||||
| 154 | char *relative_from = NULL; | - | ||||||||||||||||||
| 155 | if (realdest && realfrom)
| 0-5 | ||||||||||||||||||
| 156 | { | - | ||||||||||||||||||
| 157 | /* Write to a PATH_MAX buffer. */ | - | ||||||||||||||||||
| 158 | relative_from = xmalloc (PATH_MAX); | - | ||||||||||||||||||
| 159 | - | |||||||||||||||||||
| 160 | if (!relpath (realfrom, realdest, relative_from, PATH_MAX))
| 0-4 | ||||||||||||||||||
| 161 | { | - | ||||||||||||||||||
| 162 | free (relative_from); | - | ||||||||||||||||||
| 163 | relative_from = NULL; | - | ||||||||||||||||||
| 164 | } never executed: end of block | 0 | ||||||||||||||||||
| 165 | } executed 4 times by 1 test: end of blockExecuted by:
| 4 | ||||||||||||||||||
| 166 | - | |||||||||||||||||||
| 167 | free (targetdir); | - | ||||||||||||||||||
| 168 | free (realdest); | - | ||||||||||||||||||
| 169 | free (realfrom); | - | ||||||||||||||||||
| 170 | - | |||||||||||||||||||
| 171 | return relative_from ? relative_from : xstrdup (from); executed 5 times by 1 test: return relative_from ? relative_from : xstrdup (from);Executed by:
| 5 | ||||||||||||||||||
| 172 | } | - | ||||||||||||||||||
| 173 | - | |||||||||||||||||||
| 174 | /* Make a link DEST to the (usually) existing file SOURCE. | - | ||||||||||||||||||
| 175 | Symbolic links to nonexistent files are allowed. | - | ||||||||||||||||||
| 176 | Return true if successful. */ | - | ||||||||||||||||||
| 177 | - | |||||||||||||||||||
| 178 | static bool | - | ||||||||||||||||||
| 179 | do_link (const char *source, const char *dest) | - | ||||||||||||||||||
| 180 | { | - | ||||||||||||||||||
| 181 | struct stat source_stats; | - | ||||||||||||||||||
| 182 | struct stat dest_stats; | - | ||||||||||||||||||
| 183 | char *dest_backup = NULL; | - | ||||||||||||||||||
| 184 | char *rel_source = NULL; | - | ||||||||||||||||||
| 185 | bool dest_lstat_ok = false; | - | ||||||||||||||||||
| 186 | bool source_is_dir = false; | - | ||||||||||||||||||
| 187 | - | |||||||||||||||||||
| 188 | if (!symbolic_link)
| 89-691 | ||||||||||||||||||
| 189 | { | - | ||||||||||||||||||
| 190 | /* Which stat to use depends on whether linkat will follow the | - | ||||||||||||||||||
| 191 | symlink. We can't use the shorter | - | ||||||||||||||||||
| 192 | (logical?stat:lstat) (source, &source_stats) | - | ||||||||||||||||||
| 193 | since stat might be a function-like macro. */ | - | ||||||||||||||||||
| 194 | if ((logical ? stat (source, &source_stats)
| 1-88 | ||||||||||||||||||
| 195 | : lstat (source, &source_stats))
| 1-88 | ||||||||||||||||||
| 196 | != 0)
| 1-88 | ||||||||||||||||||
| 197 | { | - | ||||||||||||||||||
| 198 | error (0, errno, _("failed to access %s"), quoteaf (source)); | - | ||||||||||||||||||
| 199 | return false; executed 1 time by 1 test: return 0 ;Executed by:
| 1 | ||||||||||||||||||
| 200 | } | - | ||||||||||||||||||
| 201 | - | |||||||||||||||||||
| 202 | if (S_ISDIR (source_stats.st_mode))
| 2-86 | ||||||||||||||||||
| 203 | { | - | ||||||||||||||||||
| 204 | source_is_dir = true; | - | ||||||||||||||||||
| 205 | if (! hard_dir_link)
| 0-2 | ||||||||||||||||||
| 206 | { | - | ||||||||||||||||||
| 207 | error (0, 0, _("%s: hard link not allowed for directory"), | - | ||||||||||||||||||
| 208 | quotef (source)); | - | ||||||||||||||||||
| 209 | return false; executed 2 times by 1 test: return 0 ;Executed by:
| 2 | ||||||||||||||||||
| 210 | } | - | ||||||||||||||||||
| 211 | } never executed: end of block | 0 | ||||||||||||||||||
| 212 | } executed 86 times by 1 test: end of blockExecuted by:
| 86 | ||||||||||||||||||
| 213 | - | |||||||||||||||||||
| 214 | if (remove_existing_files || interactive || backup_type != no_backups)
| 0-719 | ||||||||||||||||||
| 215 | { | - | ||||||||||||||||||
| 216 | dest_lstat_ok = (lstat (dest, &dest_stats) == 0); | - | ||||||||||||||||||
| 217 | if (!dest_lstat_ok && errno != ENOENT)
| 0-43 | ||||||||||||||||||
| 218 | { | - | ||||||||||||||||||
| 219 | error (0, errno, _("failed to access %s"), quoteaf (dest)); | - | ||||||||||||||||||
| 220 | return false; never executed: return 0 ; | 0 | ||||||||||||||||||
| 221 | } | - | ||||||||||||||||||
| 222 | } executed 60 times by 1 test: end of blockExecuted by:
| 60 | ||||||||||||||||||
| 223 | - | |||||||||||||||||||
| 224 | /* If the current target was created as a hard link to another | - | ||||||||||||||||||
| 225 | source file, then refuse to unlink it. */ | - | ||||||||||||||||||
| 226 | if (dest_lstat_ok
| 17-760 | ||||||||||||||||||
| 227 | && dest_set != NULL
| 1-16 | ||||||||||||||||||
| 228 | && seen_file (dest_set, dest, &dest_stats))
| 0-1 | ||||||||||||||||||
| 229 | { | - | ||||||||||||||||||
| 230 | error (0, 0, | - | ||||||||||||||||||
| 231 | _("will not overwrite just-created %s with %s"), | - | ||||||||||||||||||
| 232 | quoteaf_n (0, dest), quoteaf_n (1, source)); | - | ||||||||||||||||||
| 233 | return false; executed 1 time by 1 test: return 0 ;Executed by:
| 1 | ||||||||||||||||||
| 234 | } | - | ||||||||||||||||||
| 235 | - | |||||||||||||||||||
| 236 | /* If --force (-f) has been specified without --backup, then before | - | ||||||||||||||||||
| 237 | making a link ln must remove the destination file if it exists. | - | ||||||||||||||||||
| 238 | (with --backup, it just renames any existing destination file) | - | ||||||||||||||||||
| 239 | But if the source and destination are the same, don't remove | - | ||||||||||||||||||
| 240 | anything and fail right here. */ | - | ||||||||||||||||||
| 241 | if ((remove_existing_files
| 57-719 | ||||||||||||||||||
| 242 | /* Ensure that "ln --backup f f" fails here, with the | - | ||||||||||||||||||
| 243 | "... same file" diagnostic, below. Otherwise, subsequent | - | ||||||||||||||||||
| 244 | code would give a misleading "file not found" diagnostic. | - | ||||||||||||||||||
| 245 | This case is different than the others handled here, since | - | ||||||||||||||||||
| 246 | the command in question doesn't use --force. */ | - | ||||||||||||||||||
| 247 | || (!symbolic_link && backup_type != no_backups))
| 2-637 | ||||||||||||||||||
| 248 | && dest_lstat_ok
| 16-43 | ||||||||||||||||||
| 249 | /* Allow 'ln -sf --backup k k' to succeed in creating the | - | ||||||||||||||||||
| 250 | self-referential symlink, but don't allow the hard-linking | - | ||||||||||||||||||
| 251 | equivalent: 'ln -f k k' (with or without --backup) to get | - | ||||||||||||||||||
| 252 | beyond this point, because the error message you'd get is | - | ||||||||||||||||||
| 253 | misleading. */ | - | ||||||||||||||||||
| 254 | && (backup_type == no_backups || !symbolic_link)
| 0-12 | ||||||||||||||||||
| 255 | && (!symbolic_link || stat (source, &source_stats) == 0)
| 4-12 | ||||||||||||||||||
| 256 | && SAME_INODE (source_stats, dest_stats)
| 0-5 | ||||||||||||||||||
| 257 | /* The following detects whether removing DEST will also remove | - | ||||||||||||||||||
| 258 | SOURCE. If the file has only one link then both are surely | - | ||||||||||||||||||
| 259 | the same link. Otherwise check whether they point to the same | - | ||||||||||||||||||
| 260 | name in the same directory. */ | - | ||||||||||||||||||
| 261 | && (source_stats.st_nlink == 1 || same_name (source, dest)))
| 0-3 | ||||||||||||||||||
| 262 | { | - | ||||||||||||||||||
| 263 | error (0, 0, _("%s and %s are the same file"), | - | ||||||||||||||||||
| 264 | quoteaf_n (0, source), quoteaf_n (1, dest)); | - | ||||||||||||||||||
| 265 | return false; executed 3 times by 1 test: return 0 ;Executed by:
| 3 | ||||||||||||||||||
| 266 | } | - | ||||||||||||||||||
| 267 | - | |||||||||||||||||||
| 268 | if (dest_lstat_ok)
| 13-760 | ||||||||||||||||||
| 269 | { | - | ||||||||||||||||||
| 270 | if (S_ISDIR (dest_stats.st_mode))
| 0-13 | ||||||||||||||||||
| 271 | { | - | ||||||||||||||||||
| 272 | error (0, 0, _("%s: cannot overwrite directory"), quotef (dest)); | - | ||||||||||||||||||
| 273 | return false; never executed: return 0 ; | 0 | ||||||||||||||||||
| 274 | } | - | ||||||||||||||||||
| 275 | if (interactive)
| 0-13 | ||||||||||||||||||
| 276 | { | - | ||||||||||||||||||
| 277 | fprintf (stderr, _("%s: replace %s? "), program_name, quoteaf (dest)); | - | ||||||||||||||||||
| 278 | if (!yesno ())
| 0 | ||||||||||||||||||
| 279 | return true; never executed: return 1 ; | 0 | ||||||||||||||||||
| 280 | remove_existing_files = true; | - | ||||||||||||||||||
| 281 | } never executed: end of block | 0 | ||||||||||||||||||
| 282 | - | |||||||||||||||||||
| 283 | if (backup_type != no_backups)
| 3-10 | ||||||||||||||||||
| 284 | { | - | ||||||||||||||||||
| 285 | dest_backup = find_backup_file_name (dest, backup_type); | - | ||||||||||||||||||
| 286 | if (rename (dest, dest_backup) != 0)
| 0-3 | ||||||||||||||||||
| 287 | { | - | ||||||||||||||||||
| 288 | int rename_errno = errno; | - | ||||||||||||||||||
| 289 | free (dest_backup); | - | ||||||||||||||||||
| 290 | dest_backup = NULL; | - | ||||||||||||||||||
| 291 | if (rename_errno != ENOENT)
| 0 | ||||||||||||||||||
| 292 | { | - | ||||||||||||||||||
| 293 | error (0, rename_errno, _("cannot backup %s"), | - | ||||||||||||||||||
| 294 | quoteaf (dest)); | - | ||||||||||||||||||
| 295 | return false; never executed: return 0 ; | 0 | ||||||||||||||||||
| 296 | } | - | ||||||||||||||||||
| 297 | } never executed: end of block | 0 | ||||||||||||||||||
| 298 | } executed 3 times by 1 test: end of blockExecuted by:
| 3 | ||||||||||||||||||
| 299 | } executed 13 times by 1 test: end of blockExecuted by:
| 13 | ||||||||||||||||||
| 300 | - | |||||||||||||||||||
| 301 | if (relative)
| 5-768 | ||||||||||||||||||
| 302 | source = rel_source = convert_abs_rel (source, dest); executed 5 times by 1 test: source = rel_source = convert_abs_rel (source, dest);Executed by:
| 5 | ||||||||||||||||||
| 303 | - | |||||||||||||||||||
| 304 | /* If the attempt to create a link fails and we are removing or | - | ||||||||||||||||||
| 305 | backing up destinations, unlink the destination and try again. | - | ||||||||||||||||||
| 306 | - | |||||||||||||||||||
| 307 | On the surface, POSIX describes an algorithm that states that | - | ||||||||||||||||||
| 308 | 'ln -f A B' will call unlink() on B before ever attempting | - | ||||||||||||||||||
| 309 | link() on A. But strictly following this has the counterintuitive | - | ||||||||||||||||||
| 310 | effect of losing the contents of B, if A does not exist. | - | ||||||||||||||||||
| 311 | Fortunately, POSIX 2008 clarified that an application is free | - | ||||||||||||||||||
| 312 | to fail early if it can prove that continuing onwards cannot | - | ||||||||||||||||||
| 313 | succeed, so we are justified in trying link() before blindly | - | ||||||||||||||||||
| 314 | removing B, thus sometimes calling link() a second time during | - | ||||||||||||||||||
| 315 | a successful 'ln -f A B'. | - | ||||||||||||||||||
| 316 | - | |||||||||||||||||||
| 317 | Try to unlink DEST even if we may have backed it up successfully. | - | ||||||||||||||||||
| 318 | In some unusual cases (when DEST and DEST_BACKUP are hard-links | - | ||||||||||||||||||
| 319 | that refer to the same file), rename succeeds and DEST remains. | - | ||||||||||||||||||
| 320 | If we didn't remove DEST in that case, the subsequent symlink or link | - | ||||||||||||||||||
| 321 | call would fail. */ | - | ||||||||||||||||||
| 322 | bool ok_to_remove = remove_existing_files || dest_backup;
| 1-718 | ||||||||||||||||||
| 323 | bool ok = 0 <= (symbolic_link
| 84-689 | ||||||||||||||||||
| 324 | ? force_symlinkat (source, AT_FDCWD, dest, ok_to_remove) | - | ||||||||||||||||||
| 325 | : force_linkat (AT_FDCWD, source, AT_FDCWD, dest, | - | ||||||||||||||||||
| 326 | logical ? AT_SYMLINK_FOLLOW : 0, | - | ||||||||||||||||||
| 327 | ok_to_remove)); | - | ||||||||||||||||||
| 328 | - | |||||||||||||||||||
| 329 | if (ok)
| 5-768 | ||||||||||||||||||
| 330 | { | - | ||||||||||||||||||
| 331 | /* Right after creating a hard link, do this: (note dest name and | - | ||||||||||||||||||
| 332 | source_stats, which are also the just-linked-destinations stats) */ | - | ||||||||||||||||||
| 333 | if (! symbolic_link)
| 82-686 | ||||||||||||||||||
| 334 | record_file (dest_set, dest, &source_stats); executed 82 times by 1 test: record_file (dest_set, dest, &source_stats);Executed by:
| 82 | ||||||||||||||||||
| 335 | - | |||||||||||||||||||
| 336 | if (verbose)
| 1-767 | ||||||||||||||||||
| 337 | { | - | ||||||||||||||||||
| 338 | if (dest_backup)
| 0-1 | ||||||||||||||||||
| 339 | printf ("%s ~ ", quoteaf (dest_backup)); never executed: printf ("%s ~ ", quotearg_style (shell_escape_always_quoting_style, dest_backup)); | 0 | ||||||||||||||||||
| 340 | printf ("%s %c> %s\n", quoteaf_n (0, dest), | - | ||||||||||||||||||
| 341 | (symbolic_link ? '-' : '='), quoteaf_n (1, source)); | - | ||||||||||||||||||
| 342 | } executed 1 time by 1 test: end of blockExecuted by:
| 1 | ||||||||||||||||||
| 343 | } executed 768 times by 1 test: end of blockExecuted by:
| 768 | ||||||||||||||||||
| 344 | else | - | ||||||||||||||||||
| 345 | { | - | ||||||||||||||||||
| 346 | error (0, errno, | - | ||||||||||||||||||
| 347 | (symbolic_link | - | ||||||||||||||||||
| 348 | ? (errno != ENAMETOOLONG && *source | - | ||||||||||||||||||
| 349 | ? _("failed to create symbolic link %s") | - | ||||||||||||||||||
| 350 | : _("failed to create symbolic link %s -> %s")) | - | ||||||||||||||||||
| 351 | : (errno == EMLINK && !source_is_dir | - | ||||||||||||||||||
| 352 | ? _("failed to create hard link to %.0s%s") | - | ||||||||||||||||||
| 353 | : (errno == EDQUOT || errno == EEXIST || errno == ENOSPC | - | ||||||||||||||||||
| 354 | || errno == EROFS) | - | ||||||||||||||||||
| 355 | ? _("failed to create hard link %s") | - | ||||||||||||||||||
| 356 | : _("failed to create hard link %s => %s"))), | - | ||||||||||||||||||
| 357 | quoteaf_n (0, dest), quoteaf_n (1, source)); | - | ||||||||||||||||||
| 358 | - | |||||||||||||||||||
| 359 | if (dest_backup)
| 0-5 | ||||||||||||||||||
| 360 | { | - | ||||||||||||||||||
| 361 | if (rename (dest_backup, dest) != 0)
| 0 | ||||||||||||||||||
| 362 | error (0, errno, _("cannot un-backup %s"), quoteaf (dest)); never executed: error (0, (*__errno_location ()) , dcgettext (((void *)0), "cannot un-backup %s" , 5) , quotearg_style (shell_escape_always_quoting_style, dest)); | 0 | ||||||||||||||||||
| 363 | } never executed: end of block | 0 | ||||||||||||||||||
| 364 | } executed 5 times by 1 test: end of blockExecuted by:
| 5 | ||||||||||||||||||
| 365 | - | |||||||||||||||||||
| 366 | free (dest_backup); | - | ||||||||||||||||||
| 367 | free (rel_source); | - | ||||||||||||||||||
| 368 | return ok; executed 773 times by 1 test: return ok;Executed by:
| 773 | ||||||||||||||||||
| 369 | } | - | ||||||||||||||||||
| 370 | - | |||||||||||||||||||
| 371 | void | - | ||||||||||||||||||
| 372 | usage (int status) | - | ||||||||||||||||||
| 373 | { | - | ||||||||||||||||||
| 374 | if (status != EXIT_SUCCESS)
| 3-28 | ||||||||||||||||||
| 375 | emit_try_help (); executed 3 times by 1 test: end of blockExecuted by:
| 3 | ||||||||||||||||||
| 376 | else | - | ||||||||||||||||||
| 377 | { | - | ||||||||||||||||||
| 378 | printf (_("\ | - | ||||||||||||||||||
| 379 | Usage: %s [OPTION]... [-T] TARGET LINK_NAME (1st form)\n\ | - | ||||||||||||||||||
| 380 | or: %s [OPTION]... TARGET (2nd form)\n\ | - | ||||||||||||||||||
| 381 | or: %s [OPTION]... TARGET... DIRECTORY (3rd form)\n\ | - | ||||||||||||||||||
| 382 | or: %s [OPTION]... -t DIRECTORY TARGET... (4th form)\n\ | - | ||||||||||||||||||
| 383 | "), | - | ||||||||||||||||||
| 384 | program_name, program_name, program_name, program_name); | - | ||||||||||||||||||
| 385 | fputs (_("\ | - | ||||||||||||||||||
| 386 | In the 1st form, create a link to TARGET with the name LINK_NAME.\n\ | - | ||||||||||||||||||
| 387 | In the 2nd form, create a link to TARGET in the current directory.\n\ | - | ||||||||||||||||||
| 388 | In the 3rd and 4th forms, create links to each TARGET in DIRECTORY.\n\ | - | ||||||||||||||||||
| 389 | Create hard links by default, symbolic links with --symbolic.\n\ | - | ||||||||||||||||||
| 390 | By default, each destination (name of new link) should not already exist.\n\ | - | ||||||||||||||||||
| 391 | When creating hard links, each TARGET must exist. Symbolic links\n\ | - | ||||||||||||||||||
| 392 | can hold arbitrary text; if later resolved, a relative link is\n\ | - | ||||||||||||||||||
| 393 | interpreted in relation to its parent directory.\n\ | - | ||||||||||||||||||
| 394 | "), stdout); | - | ||||||||||||||||||
| 395 | - | |||||||||||||||||||
| 396 | emit_mandatory_arg_note (); | - | ||||||||||||||||||
| 397 | - | |||||||||||||||||||
| 398 | fputs (_("\ | - | ||||||||||||||||||
| 399 | --backup[=CONTROL] make a backup of each existing destination file\n\ | - | ||||||||||||||||||
| 400 | -b like --backup but does not accept an argument\n\ | - | ||||||||||||||||||
| 401 | -d, -F, --directory allow the superuser to attempt to hard link\n\ | - | ||||||||||||||||||
| 402 | directories (note: will probably fail due to\n\ | - | ||||||||||||||||||
| 403 | system restrictions, even for the superuser)\n\ | - | ||||||||||||||||||
| 404 | -f, --force remove existing destination files\n\ | - | ||||||||||||||||||
| 405 | "), stdout); | - | ||||||||||||||||||
| 406 | fputs (_("\ | - | ||||||||||||||||||
| 407 | -i, --interactive prompt whether to remove destinations\n\ | - | ||||||||||||||||||
| 408 | -L, --logical dereference TARGETs that are symbolic links\n\ | - | ||||||||||||||||||
| 409 | -n, --no-dereference treat LINK_NAME as a normal file if\n\ | - | ||||||||||||||||||
| 410 | it is a symbolic link to a directory\n\ | - | ||||||||||||||||||
| 411 | -P, --physical make hard links directly to symbolic links\n\ | - | ||||||||||||||||||
| 412 | -r, --relative create symbolic links relative to link location\n\ | - | ||||||||||||||||||
| 413 | -s, --symbolic make symbolic links instead of hard links\n\ | - | ||||||||||||||||||
| 414 | "), stdout); | - | ||||||||||||||||||
| 415 | fputs (_("\ | - | ||||||||||||||||||
| 416 | -S, --suffix=SUFFIX override the usual backup suffix\n\ | - | ||||||||||||||||||
| 417 | -t, --target-directory=DIRECTORY specify the DIRECTORY in which to create\n\ | - | ||||||||||||||||||
| 418 | the links\n\ | - | ||||||||||||||||||
| 419 | -T, --no-target-directory treat LINK_NAME as a normal file always\n\ | - | ||||||||||||||||||
| 420 | -v, --verbose print name of each linked file\n\ | - | ||||||||||||||||||
| 421 | "), stdout); | - | ||||||||||||||||||
| 422 | fputs (HELP_OPTION_DESCRIPTION, stdout); | - | ||||||||||||||||||
| 423 | fputs (VERSION_OPTION_DESCRIPTION, stdout); | - | ||||||||||||||||||
| 424 | emit_backup_suffix_note (); | - | ||||||||||||||||||
| 425 | printf (_("\ | - | ||||||||||||||||||
| 426 | \n\ | - | ||||||||||||||||||
| 427 | Using -s ignores -L and -P. Otherwise, the last option specified controls\n\ | - | ||||||||||||||||||
| 428 | behavior when a TARGET is a symbolic link, defaulting to %s.\n\ | - | ||||||||||||||||||
| 429 | "), LINK_FOLLOWS_SYMLINKS ? "-L" : "-P"); | - | ||||||||||||||||||
| 430 | emit_ancillary_info (PROGRAM_NAME); | - | ||||||||||||||||||
| 431 | } executed 28 times by 1 test: end of blockExecuted by:
| 28 | ||||||||||||||||||
| 432 | exit (status); executed 31 times by 1 test: exit (status);Executed by:
| 31 | ||||||||||||||||||
| 433 | } | - | ||||||||||||||||||
| 434 | - | |||||||||||||||||||
| 435 | int | - | ||||||||||||||||||
| 436 | main (int argc, char **argv) | - | ||||||||||||||||||
| 437 | { | - | ||||||||||||||||||
| 438 | int c; | - | ||||||||||||||||||
| 439 | bool ok; | - | ||||||||||||||||||
| 440 | bool make_backups = false; | - | ||||||||||||||||||
| 441 | char const *backup_suffix = NULL; | - | ||||||||||||||||||
| 442 | char *version_control_string = NULL; | - | ||||||||||||||||||
| 443 | char const *target_directory = NULL; | - | ||||||||||||||||||
| 444 | bool no_target_directory = false; | - | ||||||||||||||||||
| 445 | int n_files; | - | ||||||||||||||||||
| 446 | char **file; | - | ||||||||||||||||||
| 447 | - | |||||||||||||||||||
| 448 | initialize_main (&argc, &argv); | - | ||||||||||||||||||
| 449 | set_program_name (argv[0]); | - | ||||||||||||||||||
| 450 | setlocale (LC_ALL, ""); | - | ||||||||||||||||||
| 451 | bindtextdomain (PACKAGE, LOCALEDIR); | - | ||||||||||||||||||
| 452 | textdomain (PACKAGE); | - | ||||||||||||||||||
| 453 | - | |||||||||||||||||||
| 454 | atexit (close_stdin); | - | ||||||||||||||||||
| 455 | - | |||||||||||||||||||
| 456 | symbolic_link = remove_existing_files = interactive = verbose | - | ||||||||||||||||||
| 457 | = hard_dir_link = false; | - | ||||||||||||||||||
| 458 | - | |||||||||||||||||||
| 459 | while ((c = getopt_long (argc, argv, "bdfinrst:vFLPS:T", long_options, NULL))
| 780-891 | ||||||||||||||||||
| 460 | != -1)
| 780-891 | ||||||||||||||||||
| 461 | { | - | ||||||||||||||||||
| 462 | switch (c) | - | ||||||||||||||||||
| 463 | { | - | ||||||||||||||||||
| 464 | case 'b': executed 6 times by 1 test: case 'b':Executed by:
| 6 | ||||||||||||||||||
| 465 | make_backups = true; | - | ||||||||||||||||||
| 466 | if (optarg)
| 3 | ||||||||||||||||||
| 467 | version_control_string = optarg; executed 3 times by 1 test: version_control_string = optarg;Executed by:
| 3 | ||||||||||||||||||
| 468 | break; executed 6 times by 1 test: break;Executed by:
| 6 | ||||||||||||||||||
| 469 | case 'd': executed 1 time by 1 test: case 'd':Executed by:
| 1 | ||||||||||||||||||
| 470 | case 'F': executed 2 times by 1 test: case 'F':Executed by:
| 2 | ||||||||||||||||||
| 471 | hard_dir_link = true; | - | ||||||||||||||||||
| 472 | break; executed 3 times by 1 test: break;Executed by:
| 3 | ||||||||||||||||||
| 473 | case 'f': executed 59 times by 1 test: case 'f':Executed by:
| 59 | ||||||||||||||||||
| 474 | remove_existing_files = true; | - | ||||||||||||||||||
| 475 | interactive = false; | - | ||||||||||||||||||
| 476 | break; executed 59 times by 1 test: break;Executed by:
| 59 | ||||||||||||||||||
| 477 | case 'i': executed 2 times by 1 test: case 'i':Executed by:
| 2 | ||||||||||||||||||
| 478 | remove_existing_files = false; | - | ||||||||||||||||||
| 479 | interactive = true; | - | ||||||||||||||||||
| 480 | break; executed 2 times by 1 test: break;Executed by:
| 2 | ||||||||||||||||||
| 481 | case 'L': executed 8 times by 1 test: case 'L':Executed by:
| 8 | ||||||||||||||||||
| 482 | logical = true; | - | ||||||||||||||||||
| 483 | break; executed 8 times by 1 test: break;Executed by:
| 8 | ||||||||||||||||||
| 484 | case 'n': executed 48 times by 1 test: case 'n':Executed by:
| 48 | ||||||||||||||||||
| 485 | dereference_dest_dir_symlinks = false; | - | ||||||||||||||||||
| 486 | break; executed 48 times by 1 test: break;Executed by:
| 48 | ||||||||||||||||||
| 487 | case 'P': executed 10 times by 1 test: case 'P':Executed by:
| 10 | ||||||||||||||||||
| 488 | logical = false; | - | ||||||||||||||||||
| 489 | break; executed 10 times by 1 test: break;Executed by:
| 10 | ||||||||||||||||||
| 490 | case 'r': executed 7 times by 1 test: case 'r':Executed by:
| 7 | ||||||||||||||||||
| 491 | relative = true; | - | ||||||||||||||||||
| 492 | break; executed 7 times by 1 test: break;Executed by:
| 7 | ||||||||||||||||||
| 493 | case 's': executed 693 times by 1 test: case 's':Executed by:
| 693 | ||||||||||||||||||
| 494 | symbolic_link = true; | - | ||||||||||||||||||
| 495 | break; executed 693 times by 1 test: break;Executed by:
| 693 | ||||||||||||||||||
| 496 | case 't': executed 3 times by 1 test: case 't':Executed by:
| 3 | ||||||||||||||||||
| 497 | if (target_directory)
| 0-3 | ||||||||||||||||||
| 498 | die (EXIT_FAILURE, 0, _("multiple target directories specified")); never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, 0, dcgettext (((void *)0), \"multiple target directories specified\", 5)), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 , 0, dcgettext (((void *)0), "multiple target directories specified" , 5) ), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , 0, dcgettext (((void *)0), "multiple target directories specified" , 5) ), (( 0 ) ? (void) 0 : __builtin_unreachable ())))); | 0 | ||||||||||||||||||
| 499 | else | - | ||||||||||||||||||
| 500 | { | - | ||||||||||||||||||
| 501 | struct stat st; | - | ||||||||||||||||||
| 502 | if (stat (optarg, &st) != 0)
| 1-2 | ||||||||||||||||||
| 503 | die (EXIT_FAILURE, errno, _("failed to access %s"), executed 2 times by 1 test: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, (*__errno_location ()), dcgettext (((void *)0), \"failed to access %s\", 5), quotearg_style (shell_escape_always_quoting_style, optarg)), assume (false))" ")"); int _gl_dummy; ..., (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , (*__errno_location ()) , dcgettext (((void *)0), "failed to access %s" , 5) , quotearg_style (shell_escape_always_quoting_style, optarg)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;Executed by:
| 2 | ||||||||||||||||||
| 504 | quoteaf (optarg)); executed 2 times by 1 test: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, (*__errno_location ()), dcgettext (((void *)0), \"failed to access %s\", 5), quotearg_style (shell_escape_always_quoting_style, optarg)), assume (false))" ")"); int _gl_dummy; ..., (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , (*__errno_location ()) , dcgettext (((void *)0), "failed to access %s" , 5) , quotearg_style (shell_escape_always_quoting_style, optarg)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;Executed by:
| 2 | ||||||||||||||||||
| 505 | if (! S_ISDIR (st.st_mode))
| 0-1 | ||||||||||||||||||
| 506 | die (EXIT_FAILURE, 0, _("target %s is not a directory"), never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, 0, dcgettext (((void *)0), \"target %s is not a directory\", 5), quotearg_style (shell_escape_always_quoting_style, optarg)), assume (false))" ")"); int _gl_dummy; })) ? ((erro...yle, optarg)), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , 0, dcgettext (((void *)0), "target %s is not a directory" , 5) , quotearg_style (shell_escape_always_quoting_style, optarg)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||
| 507 | quoteaf (optarg)); never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, 0, dcgettext (((void *)0), \"target %s is not a directory\", 5), quotearg_style (shell_escape_always_quoting_style, optarg)), assume (false))" ")"); int _gl_dummy; })) ? ((erro...yle, optarg)), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , 0, dcgettext (((void *)0), "target %s is not a directory" , 5) , quotearg_style (shell_escape_always_quoting_style, optarg)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||
| 508 | } executed 1 time by 1 test: end of blockExecuted by:
| 1 | ||||||||||||||||||
| 509 | target_directory = optarg; | - | ||||||||||||||||||
| 510 | break; executed 1 time by 1 test: break;Executed by:
| 1 | ||||||||||||||||||
| 511 | case 'T': executed 3 times by 1 test: case 'T':Executed by:
| 3 | ||||||||||||||||||
| 512 | no_target_directory = true; | - | ||||||||||||||||||
| 513 | break; executed 3 times by 1 test: break;Executed by:
| 3 | ||||||||||||||||||
| 514 | case 'v': executed 3 times by 1 test: case 'v':Executed by:
| 3 | ||||||||||||||||||
| 515 | verbose = true; | - | ||||||||||||||||||
| 516 | break; executed 3 times by 1 test: break;Executed by:
| 3 | ||||||||||||||||||
| 517 | case 'S': executed 3 times by 1 test: case 'S':Executed by:
| 3 | ||||||||||||||||||
| 518 | make_backups = true; | - | ||||||||||||||||||
| 519 | backup_suffix = optarg; | - | ||||||||||||||||||
| 520 | break; executed 3 times by 1 test: break;Executed by:
| 3 | ||||||||||||||||||
| 521 | case_GETOPT_HELP_CHAR; never executed: break;executed 28 times by 1 test: case GETOPT_HELP_CHAR:Executed by:
| 0-28 | ||||||||||||||||||
| 522 | case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); executed 12 times by 1 test: exit ( 0 );Executed by:
never executed: break;executed 12 times by 1 test: case GETOPT_VERSION_CHAR:Executed by:
| 0-12 | ||||||||||||||||||
| 523 | default: executed 3 times by 1 test: default:Executed by:
| 3 | ||||||||||||||||||
| 524 | usage (EXIT_FAILURE); | - | ||||||||||||||||||
| 525 | break; never executed: break; | 0 | ||||||||||||||||||
| 526 | } | - | ||||||||||||||||||
| 527 | } | - | ||||||||||||||||||
| 528 | - | |||||||||||||||||||
| 529 | n_files = argc - optind; | - | ||||||||||||||||||
| 530 | file = argv + optind; | - | ||||||||||||||||||
| 531 | - | |||||||||||||||||||
| 532 | if (n_files <= 0)
| 0-780 | ||||||||||||||||||
| 533 | { | - | ||||||||||||||||||
| 534 | error (0, 0, _("missing file operand")); | - | ||||||||||||||||||
| 535 | usage (EXIT_FAILURE); | - | ||||||||||||||||||
| 536 | } never executed: end of block | 0 | ||||||||||||||||||
| 537 | - | |||||||||||||||||||
| 538 | if (no_target_directory)
| 1-779 | ||||||||||||||||||
| 539 | { | - | ||||||||||||||||||
| 540 | if (target_directory)
| 0-1 | ||||||||||||||||||
| 541 | die (EXIT_FAILURE, 0, never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, 0, dcgettext (((void *)0), \"cannot combine --target-directory \" \"and --no-target-directory\", 5)), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 , 0, dcgettext (((...ry " "and --no-target-directory" , 5) ), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , 0, dcgettext (((void *)0), "cannot combine --target-directory " "and --no-target-directory" , 5) ), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||
| 542 | _("cannot combine --target-directory " never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, 0, dcgettext (((void *)0), \"cannot combine --target-directory \" \"and --no-target-directory\", 5)), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 , 0, dcgettext (((...ry " "and --no-target-directory" , 5) ), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , 0, dcgettext (((void *)0), "cannot combine --target-directory " "and --no-target-directory" , 5) ), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||
| 543 | "and --no-target-directory")); never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, 0, dcgettext (((void *)0), \"cannot combine --target-directory \" \"and --no-target-directory\", 5)), assume (false))" ")"); int _gl_dummy; })) ? ((error ( 1 , 0, dcgettext (((...ry " "and --no-target-directory" , 5) ), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , 0, dcgettext (((void *)0), "cannot combine --target-directory " "and --no-target-directory" , 5) ), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||
| 544 | if (n_files != 2)
| 0-1 | ||||||||||||||||||
| 545 | { | - | ||||||||||||||||||
| 546 | if (n_files < 2)
| 0 | ||||||||||||||||||
| 547 | error (0, 0, never executed: error (0, 0, dcgettext (((void *)0), "missing destination file operand after %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file[0])); | 0 | ||||||||||||||||||
| 548 | _("missing destination file operand after %s"), never executed: error (0, 0, dcgettext (((void *)0), "missing destination file operand after %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file[0])); | 0 | ||||||||||||||||||
| 549 | quoteaf (file[0])); never executed: error (0, 0, dcgettext (((void *)0), "missing destination file operand after %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file[0])); | 0 | ||||||||||||||||||
| 550 | else | - | ||||||||||||||||||
| 551 | error (0, 0, _("extra operand %s"), quoteaf (file[2])); never executed: error (0, 0, dcgettext (((void *)0), "extra operand %s" , 5) , quotearg_style (shell_escape_always_quoting_style, file[2])); | 0 | ||||||||||||||||||
| 552 | usage (EXIT_FAILURE); | - | ||||||||||||||||||
| 553 | } never executed: end of block | 0 | ||||||||||||||||||
| 554 | } executed 1 time by 1 test: end of blockExecuted by:
| 1 | ||||||||||||||||||
| 555 | else if (!target_directory)
| 1-778 | ||||||||||||||||||
| 556 | { | - | ||||||||||||||||||
| 557 | if (n_files < 2)
| 2-776 | ||||||||||||||||||
| 558 | target_directory = "."; executed 2 times by 1 test: target_directory = ".";Executed by:
| 2 | ||||||||||||||||||
| 559 | else if (2 <= n_files && target_directory_operand (file[n_files - 1]))
| 0-776 | ||||||||||||||||||
| 560 | target_directory = file[--n_files]; executed 11 times by 1 test: target_directory = file[--n_files];Executed by:
| 11 | ||||||||||||||||||
| 561 | else if (2 < n_files)
| 0-764 | ||||||||||||||||||
| 562 | die (EXIT_FAILURE, 0, _("target %s is not a directory"), never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, 0, dcgettext (((void *)0), \"target %s is not a directory\", 5), quotearg_style (shell_escape_always_quoting_style, file[n_files - 1])), assume (false))" ")"); int _gl_dummy; }...)), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , 0, dcgettext (((void *)0), "target %s is not a directory" , 5) , quotearg_style (shell_escape_always_quoting_style, file[n_files - 1])), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||
| 563 | quoteaf (file[n_files - 1])); never executed: ((!!sizeof (struct { _Static_assert ( 1 , "verify_expr (" "1" ", " "(error (1, 0, dcgettext (((void *)0), \"target %s is not a directory\", 5), quotearg_style (shell_escape_always_quoting_style, file[n_files - 1])), assume (false))" ")"); int _gl_dummy; }...)), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error ( 1 , 0, dcgettext (((void *)0), "target %s is not a directory" , 5) , quotearg_style (shell_escape_always_quoting_style, file[n_files - 1])), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ; | 0 | ||||||||||||||||||
| 564 | } executed 777 times by 1 test: end of blockExecuted by:
| 777 | ||||||||||||||||||
| 565 | - | |||||||||||||||||||
| 566 | backup_type = (make_backups
| 4-775 | ||||||||||||||||||
| 567 | ? xget_version (_("backup type"), version_control_string) | - | ||||||||||||||||||
| 568 | : no_backups); | - | ||||||||||||||||||
| 569 | set_simple_backup_suffix (backup_suffix); | - | ||||||||||||||||||
| 570 | - | |||||||||||||||||||
| 571 | if (relative && !symbolic_link)
| 0-774 | ||||||||||||||||||
| 572 | { | - | ||||||||||||||||||
| 573 | die (EXIT_FAILURE, 0, | - | ||||||||||||||||||
| 574 | _("cannot do --relative without --symbolic")); | - | ||||||||||||||||||
| 575 | } never executed: end of block | 0 | ||||||||||||||||||
| 576 | - | |||||||||||||||||||
| 577 | - | |||||||||||||||||||
| 578 | if (target_directory)
| 14-765 | ||||||||||||||||||
| 579 | { | - | ||||||||||||||||||
| 580 | /* Create the data structure we'll use to record which hard links we | - | ||||||||||||||||||
| 581 | create. Used to ensure that ln detects an obscure corner case that | - | ||||||||||||||||||
| 582 | might result in user data loss. Create it only if needed. */ | - | ||||||||||||||||||
| 583 | if (2 <= n_files
| 1-13 | ||||||||||||||||||
| 584 | && remove_existing_files
| 0-1 | ||||||||||||||||||
| 585 | /* Don't bother trying to protect symlinks, since ln clobbering | - | ||||||||||||||||||
| 586 | a just-created symlink won't ever lead to real data loss. */ | - | ||||||||||||||||||
| 587 | && ! symbolic_link
| 0-1 | ||||||||||||||||||
| 588 | /* No destination hard link can be clobbered when making | - | ||||||||||||||||||
| 589 | numbered backups. */ | - | ||||||||||||||||||
| 590 | && backup_type != numbered_backups)
| 0-1 | ||||||||||||||||||
| 591 | - | |||||||||||||||||||
| 592 | { | - | ||||||||||||||||||
| 593 | dest_set = hash_initialize (DEST_INFO_INITIAL_CAPACITY, | - | ||||||||||||||||||
| 594 | NULL, | - | ||||||||||||||||||
| 595 | triple_hash, | - | ||||||||||||||||||
| 596 | triple_compare, | - | ||||||||||||||||||
| 597 | triple_free); | - | ||||||||||||||||||
| 598 | if (dest_set == NULL)
| 0-1 | ||||||||||||||||||
| 599 | xalloc_die (); never executed: xalloc_die (); | 0 | ||||||||||||||||||
| 600 | } executed 1 time by 1 test: end of blockExecuted by:
| 1 | ||||||||||||||||||
| 601 | - | |||||||||||||||||||
| 602 | ok = true; | - | ||||||||||||||||||
| 603 | for (int i = 0; i < n_files; ++i)
| 14-15 | ||||||||||||||||||
| 604 | { | - | ||||||||||||||||||
| 605 | char *dest_base; | - | ||||||||||||||||||
| 606 | char *dest = file_name_concat (target_directory, | - | ||||||||||||||||||
| 607 | last_component (file[i]), | - | ||||||||||||||||||
| 608 | &dest_base); | - | ||||||||||||||||||
| 609 | strip_trailing_slashes (dest_base); | - | ||||||||||||||||||
| 610 | ok &= do_link (file[i], dest); | - | ||||||||||||||||||
| 611 | free (dest); | - | ||||||||||||||||||
| 612 | } executed 15 times by 1 test: end of blockExecuted by:
| 15 | ||||||||||||||||||
| 613 | } executed 14 times by 1 test: end of blockExecuted by:
| 14 | ||||||||||||||||||
| 614 | else | - | ||||||||||||||||||
| 615 | ok = do_link (file[0], file[1]); executed 765 times by 1 test: ok = do_link (file[0], file[1]);Executed by:
| 765 | ||||||||||||||||||
| 616 | - | |||||||||||||||||||
| 617 | return ok ? EXIT_SUCCESS : EXIT_FAILURE; executed 779 times by 1 test: return ok ? 0 : 1 ;Executed by:
| 779 | ||||||||||||||||||
| 618 | } | - | ||||||||||||||||||
| Source code | Switch to Preprocessed file |