| 175 | Return true if successful. */ |
| 176 | |
| 177 | static bool |
| 178 | do_link (char const *source, int destdir_fd, char const *dest_base, |
| 179 | char const *dest, int link_errno) |
| 180 | { |
| 181 | struct stat source_stats; |
| 182 | int source_status = 1; |
| 183 | char *backup_base = NULL; |
| 184 | char *rel_source = NULL; |
| 185 | int nofollow_flag = logical ? 0 : AT_SYMLINK_NOFOLLOW; |
| 186 | if (link_errno < 0) |
| 187 | link_errno = atomic_link (source, destdir_fd, dest_base); |
| 188 | |
| 189 | /* Get SOURCE_STATS if later code will need it, if only for sharper |
| 190 | diagnostics. */ |
| 191 | if ((link_errno || dest_set) && !symbolic_link) |
| 192 | { |
| 193 | source_status = fstatat (AT_FDCWD, source, &source_stats, nofollow_flag); |
| 194 | if (source_status != 0) |
| 195 | { |
| 196 | error (0, errno, _("failed to access %s"), quoteaf (source)); |
| 197 | return false; |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | if (link_errno) |
| 202 | { |
| 203 | if (!symbolic_link && !hard_dir_link && S_ISDIR (source_stats.st_mode)) |
| 204 | { |
| 205 | error (0, 0, _("%s: hard link not allowed for directory"), |
| 206 | quotef (source)); |
| 207 | return false; |
| 208 | } |
| 209 | |
| 210 | if (relative) |
| 211 | source = rel_source = convert_abs_rel (source, dest); |
| 212 | |
| 213 | bool force = (remove_existing_files || interactive |
| 214 | || backup_type != no_backups); |
| 215 | if (force) |
| 216 | { |
| 217 | struct stat dest_stats; |
| 218 | if (fstatat (destdir_fd, dest_base, &dest_stats, AT_SYMLINK_NOFOLLOW) |
| 219 | != 0) |
| 220 | { |
| 221 | if (errno != ENOENT) |
| 222 | { |
| 223 | error (0, errno, _("failed to access %s"), quoteaf (dest)); |
| 224 | goto fail; |
| 225 | } |
| 226 | force = false; |
| 227 | } |
| 228 | else if (S_ISDIR (dest_stats.st_mode)) |
| 229 | { |
| 230 | error (0, 0, _("%s: cannot overwrite directory"), quotef (dest)); |
| 231 | goto fail; |
| 232 | } |
| 233 | else if (seen_file (dest_set, dest, &dest_stats)) |
| 234 | { |
no test coverage detected