1 1.40 sevan /* $NetBSD: ln.c,v 1.40 2018/08/26 23:01:06 sevan Exp $ */ 2 1.10 cgd 3 1.36 christos /*- 4 1.9 mycroft * Copyright (c) 1987, 1993, 1994 5 1.9 mycroft * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.38 szptvlfn * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.36 christos #if 0 33 1.1 cgd #ifndef lint 34 1.36 christos static char const copyright[] = 35 1.36 christos "@(#) Copyright (c) 1987, 1993, 1994\n\ 36 1.36 christos The Regents of the University of California. All rights reserved.\n"; 37 1.1 cgd #endif /* not lint */ 38 1.1 cgd 39 1.1 cgd #ifndef lint 40 1.10 cgd static char sccsid[] = "@(#)ln.c 8.2 (Berkeley) 3/31/94"; 41 1.36 christos #endif /* not lint */ 42 1.36 christos #endif 43 1.36 christos #include <sys/cdefs.h> 44 1.36 christos #ifdef __FBSDID 45 1.36 christos __FBSDID("$FreeBSD: head/bin/ln/ln.c 251261 2013-06-02 17:55:00Z eadler $"); 46 1.10 cgd #endif 47 1.40 sevan __RCSID("$NetBSD: ln.c,v 1.40 2018/08/26 23:01:06 sevan Exp $"); 48 1.1 cgd 49 1.1 cgd #include <sys/param.h> 50 1.1 cgd #include <sys/stat.h> 51 1.9 mycroft 52 1.9 mycroft #include <err.h> 53 1.9 mycroft #include <errno.h> 54 1.36 christos #include <fcntl.h> 55 1.36 christos #include <libgen.h> 56 1.36 christos #include <limits.h> 57 1.1 cgd #include <stdio.h> 58 1.9 mycroft #include <stdlib.h> 59 1.1 cgd #include <string.h> 60 1.1 cgd #include <unistd.h> 61 1.1 cgd 62 1.36 christos static int fflag; /* Unlink existing files. */ 63 1.36 christos static int Fflag; /* Remove empty directories also. */ 64 1.36 christos static int hflag; /* Check new name for symlink first. */ 65 1.36 christos static int iflag; /* Interactive mode. */ 66 1.36 christos static int Pflag; /* Create hard links to symlinks. */ 67 1.36 christos static int sflag; /* Symbolic, not hard, link. */ 68 1.36 christos static int vflag; /* Verbose output. */ 69 1.36 christos static int wflag; /* Warn if symlink target does not 70 1.36 christos * exist, and -f is not enabled. */ 71 1.36 christos static char linkch; 72 1.9 mycroft 73 1.35 joerg static int linkit(const char *, const char *, int); 74 1.37 christos static __dead void usage(void); 75 1.1 cgd 76 1.6 jtc int 77 1.19 wiz main(int argc, char *argv[]) 78 1.1 cgd { 79 1.9 mycroft struct stat sb; 80 1.36 christos char *p, *targetdir; 81 1.6 jtc int ch, exitval; 82 1.1 cgd 83 1.36 christos /* 84 1.36 christos * Test for the special case where the utility is called as 85 1.36 christos * "link", for which the functionality provided is greatly 86 1.36 christos * simplified. 87 1.36 christos */ 88 1.36 christos if ((p = strrchr(argv[0], '/')) == NULL) 89 1.36 christos p = argv[0]; 90 1.36 christos else 91 1.36 christos ++p; 92 1.36 christos if (strcmp(p, "link") == 0) { 93 1.36 christos while (getopt(argc, argv, "") != -1) 94 1.36 christos usage(); 95 1.36 christos argc -= optind; 96 1.36 christos argv += optind; 97 1.36 christos if (argc != 2) 98 1.36 christos usage(); 99 1.39 kre if (link(argv[0], argv[1]) == -1) 100 1.39 kre err(EXIT_FAILURE, NULL); 101 1.39 kre exit(EXIT_SUCCESS); 102 1.36 christos } 103 1.33 christos 104 1.36 christos while ((ch = getopt(argc, argv, "FLPfhinsvw")) != -1) 105 1.9 mycroft switch (ch) { 106 1.36 christos case 'F': 107 1.36 christos Fflag = 1; 108 1.36 christos break; 109 1.36 christos case 'L': 110 1.36 christos Pflag = 0; 111 1.36 christos break; 112 1.36 christos case 'P': 113 1.36 christos Pflag = 1; 114 1.36 christos break; 115 1.5 jtc case 'f': 116 1.9 mycroft fflag = 1; 117 1.31 elad iflag = 0; 118 1.36 christos wflag = 0; 119 1.1 cgd break; 120 1.12 mycroft case 'h': 121 1.12 mycroft case 'n': 122 1.12 mycroft hflag = 1; 123 1.12 mycroft break; 124 1.31 elad case 'i': 125 1.31 elad iflag = 1; 126 1.31 elad fflag = 0; 127 1.31 elad break; 128 1.1 cgd case 's': 129 1.1 cgd sflag = 1; 130 1.1 cgd break; 131 1.36 christos case 'v': 132 1.27 jschauma vflag = 1; 133 1.27 jschauma break; 134 1.36 christos case 'w': 135 1.36 christos wflag = 1; 136 1.36 christos break; 137 1.1 cgd case '?': 138 1.1 cgd default: 139 1.1 cgd usage(); 140 1.1 cgd } 141 1.1 cgd 142 1.1 cgd argv += optind; 143 1.1 cgd argc -= optind; 144 1.1 cgd 145 1.36 christos linkch = sflag ? '-' : '='; 146 1.36 christos if (sflag == 0) 147 1.36 christos Fflag = 0; 148 1.36 christos if (Fflag == 1 && iflag == 0) { 149 1.36 christos fflag = 1; 150 1.36 christos wflag = 0; /* Implied when fflag != 0 */ 151 1.21 jrf } 152 1.1 cgd 153 1.1 cgd switch(argc) { 154 1.1 cgd case 0: 155 1.1 cgd usage(); 156 1.14 cgd /* NOTREACHED */ 157 1.36 christos case 1: /* ln source */ 158 1.1 cgd exit(linkit(argv[0], ".", 1)); 159 1.36 christos case 2: /* ln source target */ 160 1.1 cgd exit(linkit(argv[0], argv[1], 0)); 161 1.36 christos default: 162 1.36 christos ; 163 1.1 cgd } 164 1.36 christos /* ln source1 source2 directory */ 165 1.36 christos targetdir = argv[argc - 1]; 166 1.36 christos if (hflag && lstat(targetdir, &sb) == 0 && S_ISLNK(sb.st_mode)) { 167 1.36 christos /* 168 1.36 christos * We were asked not to follow symlinks, but found one at 169 1.36 christos * the target--simulate "not a directory" error 170 1.36 christos */ 171 1.11 jtk errno = ENOTDIR; 172 1.36 christos err(1, "%s", targetdir); 173 1.11 jtk } 174 1.36 christos if (stat(targetdir, &sb)) 175 1.36 christos err(1, "%s", targetdir); 176 1.36 christos if (!S_ISDIR(sb.st_mode)) 177 1.36 christos usage(); 178 1.36 christos for (exitval = 0; *argv != targetdir; ++argv) 179 1.36 christos exitval |= linkit(*argv, targetdir, 1); 180 1.36 christos exit(exitval); 181 1.36 christos } 182 1.36 christos 183 1.36 christos /* 184 1.36 christos * Two pathnames refer to the same directory entry if the directories match 185 1.36 christos * and the final components' names match. 186 1.36 christos */ 187 1.36 christos static int 188 1.36 christos samedirent(const char *path1, const char *path2) 189 1.36 christos { 190 1.36 christos const char *file1, *file2; 191 1.36 christos char pathbuf[PATH_MAX]; 192 1.36 christos struct stat sb1, sb2; 193 1.36 christos 194 1.36 christos if (strcmp(path1, path2) == 0) 195 1.36 christos return 1; 196 1.36 christos file1 = strrchr(path1, '/'); 197 1.36 christos if (file1 != NULL) 198 1.36 christos file1++; 199 1.36 christos else 200 1.36 christos file1 = path1; 201 1.36 christos file2 = strrchr(path2, '/'); 202 1.36 christos if (file2 != NULL) 203 1.36 christos file2++; 204 1.36 christos else 205 1.36 christos file2 = path2; 206 1.36 christos if (strcmp(file1, file2) != 0) 207 1.36 christos return 0; 208 1.36 christos if (file1 - path1 >= PATH_MAX || file2 - path2 >= PATH_MAX) 209 1.36 christos return 0; 210 1.36 christos if (file1 == path1) 211 1.36 christos memcpy(pathbuf, ".", 2); 212 1.36 christos else { 213 1.36 christos memcpy(pathbuf, path1, file1 - path1); 214 1.36 christos pathbuf[file1 - path1] = '\0'; 215 1.22 jschauma } 216 1.36 christos if (stat(pathbuf, &sb1) != 0) 217 1.36 christos return 0; 218 1.36 christos if (file2 == path2) 219 1.36 christos memcpy(pathbuf, ".", 2); 220 1.36 christos else { 221 1.36 christos memcpy(pathbuf, path2, file2 - path2); 222 1.36 christos pathbuf[file2 - path2] = '\0'; 223 1.22 jschauma } 224 1.36 christos if (stat(pathbuf, &sb2) != 0) 225 1.36 christos return 0; 226 1.36 christos return sb1.st_dev == sb2.st_dev && sb1.st_ino == sb2.st_ino; 227 1.1 cgd } 228 1.1 cgd 229 1.35 joerg static int 230 1.36 christos linkit(const char *source, const char *target, int isdir) 231 1.1 cgd { 232 1.9 mycroft struct stat sb; 233 1.30 christos const char *p; 234 1.31 elad int ch, exists, first; 235 1.36 christos char path[PATH_MAX]; 236 1.36 christos char wbuf[PATH_MAX]; 237 1.36 christos char bbuf[PATH_MAX]; 238 1.1 cgd 239 1.1 cgd if (!sflag) { 240 1.36 christos /* If source doesn't exist, quit now. */ 241 1.36 christos if ((Pflag ? lstat : stat)(source, &sb)) { 242 1.36 christos warn("%s", source); 243 1.36 christos return (1); 244 1.36 christos } 245 1.36 christos /* Only symbolic links to directories. */ 246 1.36 christos if (S_ISDIR(sb.st_mode)) { 247 1.36 christos errno = EISDIR; 248 1.36 christos warn("%s", source); 249 1.9 mycroft return (1); 250 1.1 cgd } 251 1.1 cgd } 252 1.1 cgd 253 1.36 christos /* 254 1.36 christos * If the target is a directory (and not a symlink if hflag), 255 1.36 christos * append the source's name. 256 1.36 christos */ 257 1.11 jtk if (isdir || 258 1.36 christos (lstat(target, &sb) == 0 && S_ISDIR(sb.st_mode)) || 259 1.36 christos (!hflag && stat(target, &sb) == 0 && S_ISDIR(sb.st_mode))) { 260 1.36 christos if (strlcpy(bbuf, source, sizeof(bbuf)) >= sizeof(bbuf) || 261 1.36 christos (p = basename(bbuf)) == NULL || 262 1.36 christos snprintf(path, sizeof(path), "%s/%s", target, p) >= 263 1.36 christos (ssize_t)sizeof(path)) { 264 1.36 christos errno = ENAMETOOLONG; 265 1.36 christos warn("%s", source); 266 1.36 christos return (1); 267 1.36 christos } 268 1.36 christos target = path; 269 1.5 jtc } 270 1.5 jtc 271 1.36 christos /* 272 1.36 christos * If the link source doesn't exist, and a symbolic link was 273 1.36 christos * requested, and -w was specified, give a warning. 274 1.36 christos */ 275 1.36 christos if (sflag && wflag) { 276 1.36 christos if (*source == '/') { 277 1.36 christos /* Absolute link source. */ 278 1.36 christos if (stat(source, &sb) != 0) 279 1.36 christos warn("warning: %s inaccessible", source); 280 1.36 christos } else { 281 1.36 christos /* 282 1.36 christos * Relative symlink source. Try to construct the 283 1.36 christos * absolute path of the source, by appending `source' 284 1.36 christos * to the parent directory of the target. 285 1.36 christos */ 286 1.36 christos strlcpy(bbuf, target, sizeof(bbuf)); 287 1.36 christos p = dirname(bbuf); 288 1.36 christos if (p != NULL) { 289 1.36 christos (void)snprintf(wbuf, sizeof(wbuf), "%s/%s", 290 1.36 christos p, source); 291 1.36 christos if (stat(wbuf, &sb) != 0) 292 1.36 christos warn("warning: %s", source); 293 1.36 christos } 294 1.36 christos } 295 1.36 christos } 296 1.31 elad 297 1.9 mycroft /* 298 1.36 christos * If the file exists, first check it is not the same directory entry. 299 1.36 christos */ 300 1.36 christos exists = !lstat(target, &sb); 301 1.36 christos if (exists) { 302 1.36 christos if (!sflag && samedirent(source, target)) { 303 1.36 christos warnx("%s and %s are the same directory entry", 304 1.36 christos source, target); 305 1.36 christos return (1); 306 1.36 christos } 307 1.36 christos } 308 1.36 christos /* 309 1.36 christos * Then unlink it forcibly if -f was specified 310 1.31 elad * and interactively if -i was specified. 311 1.9 mycroft */ 312 1.31 elad if (fflag && exists) { 313 1.36 christos if (Fflag && S_ISDIR(sb.st_mode)) { 314 1.36 christos if (rmdir(target)) { 315 1.36 christos warn("%s", target); 316 1.36 christos return (1); 317 1.36 christos } 318 1.36 christos } else if (unlink(target)) { 319 1.36 christos warn("%s", target); 320 1.31 elad return (1); 321 1.31 elad } 322 1.31 elad } else if (iflag && exists) { 323 1.31 elad fflush(stdout); 324 1.36 christos fprintf(stderr, "replace %s? ", target); 325 1.31 elad 326 1.31 elad first = ch = getchar(); 327 1.36 christos while(ch != '\n' && ch != EOF) 328 1.31 elad ch = getchar(); 329 1.31 elad if (first != 'y' && first != 'Y') { 330 1.36 christos fprintf(stderr, "not replaced\n"); 331 1.31 elad return (1); 332 1.31 elad } 333 1.31 elad 334 1.36 christos if (Fflag && S_ISDIR(sb.st_mode)) { 335 1.36 christos if (rmdir(target)) { 336 1.36 christos warn("%s", target); 337 1.36 christos return (1); 338 1.36 christos } 339 1.36 christos } else if (unlink(target)) { 340 1.36 christos warn("%s", target); 341 1.31 elad return (1); 342 1.31 elad } 343 1.31 elad } 344 1.31 elad 345 1.31 elad /* Attempt the link. */ 346 1.36 christos if (sflag ? symlink(source, target) : 347 1.36 christos linkat(AT_FDCWD, source, AT_FDCWD, target, 348 1.36 christos Pflag ? 0 : AT_SYMLINK_FOLLOW)) { 349 1.36 christos warn("%s", target); 350 1.5 jtc return (1); 351 1.1 cgd } 352 1.21 jrf if (vflag) 353 1.36 christos (void)printf("%s %c> %s\n", target, linkch, source); 354 1.9 mycroft return (0); 355 1.1 cgd } 356 1.1 cgd 357 1.37 christos static __dead void 358 1.19 wiz usage(void) 359 1.1 cgd { 360 1.37 christos (void)fprintf(stderr, 361 1.40 sevan "usage: %s [-L | -P | -s [-F]] [-f | -iw] [-hnv] source_file [target_file]\n" 362 1.40 sevan " %s [-L | -P | -s [-F]] [-f | -iw] [-hnv] source_file ... target_dir\n" 363 1.37 christos " link source_file target_file\n", getprogname(), getprogname()); 364 1.1 cgd exit(1); 365 1.1 cgd } 366