ln.c revision 1.37 1 1.37 christos /* $NetBSD: ln.c,v 1.37 2017/04/21 11:28:35 christos 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.36 christos * 4. 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.37 christos __RCSID("$NetBSD: ln.c,v 1.37 2017/04/21 11:28:35 christos 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.36 christos exit(linkit(argv[0], argv[1], 0));
100 1.36 christos }
101 1.33 christos
102 1.36 christos while ((ch = getopt(argc, argv, "FLPfhinsvw")) != -1)
103 1.9 mycroft switch (ch) {
104 1.36 christos case 'F':
105 1.36 christos Fflag = 1;
106 1.36 christos break;
107 1.36 christos case 'L':
108 1.36 christos Pflag = 0;
109 1.36 christos break;
110 1.36 christos case 'P':
111 1.36 christos Pflag = 1;
112 1.36 christos break;
113 1.5 jtc case 'f':
114 1.9 mycroft fflag = 1;
115 1.31 elad iflag = 0;
116 1.36 christos wflag = 0;
117 1.1 cgd break;
118 1.12 mycroft case 'h':
119 1.12 mycroft case 'n':
120 1.12 mycroft hflag = 1;
121 1.12 mycroft break;
122 1.31 elad case 'i':
123 1.31 elad iflag = 1;
124 1.31 elad fflag = 0;
125 1.31 elad break;
126 1.1 cgd case 's':
127 1.1 cgd sflag = 1;
128 1.1 cgd break;
129 1.36 christos case 'v':
130 1.27 jschauma vflag = 1;
131 1.27 jschauma break;
132 1.36 christos case 'w':
133 1.36 christos wflag = 1;
134 1.36 christos break;
135 1.1 cgd case '?':
136 1.1 cgd default:
137 1.1 cgd usage();
138 1.1 cgd }
139 1.1 cgd
140 1.1 cgd argv += optind;
141 1.1 cgd argc -= optind;
142 1.1 cgd
143 1.36 christos linkch = sflag ? '-' : '=';
144 1.36 christos if (sflag == 0)
145 1.36 christos Fflag = 0;
146 1.36 christos if (Fflag == 1 && iflag == 0) {
147 1.36 christos fflag = 1;
148 1.36 christos wflag = 0; /* Implied when fflag != 0 */
149 1.21 jrf }
150 1.1 cgd
151 1.1 cgd switch(argc) {
152 1.1 cgd case 0:
153 1.1 cgd usage();
154 1.14 cgd /* NOTREACHED */
155 1.36 christos case 1: /* ln source */
156 1.1 cgd exit(linkit(argv[0], ".", 1));
157 1.36 christos case 2: /* ln source target */
158 1.1 cgd exit(linkit(argv[0], argv[1], 0));
159 1.36 christos default:
160 1.36 christos ;
161 1.1 cgd }
162 1.36 christos /* ln source1 source2 directory */
163 1.36 christos targetdir = argv[argc - 1];
164 1.36 christos if (hflag && lstat(targetdir, &sb) == 0 && S_ISLNK(sb.st_mode)) {
165 1.36 christos /*
166 1.36 christos * We were asked not to follow symlinks, but found one at
167 1.36 christos * the target--simulate "not a directory" error
168 1.36 christos */
169 1.11 jtk errno = ENOTDIR;
170 1.36 christos err(1, "%s", targetdir);
171 1.11 jtk }
172 1.36 christos if (stat(targetdir, &sb))
173 1.36 christos err(1, "%s", targetdir);
174 1.36 christos if (!S_ISDIR(sb.st_mode))
175 1.36 christos usage();
176 1.36 christos for (exitval = 0; *argv != targetdir; ++argv)
177 1.36 christos exitval |= linkit(*argv, targetdir, 1);
178 1.36 christos exit(exitval);
179 1.36 christos }
180 1.36 christos
181 1.36 christos /*
182 1.36 christos * Two pathnames refer to the same directory entry if the directories match
183 1.36 christos * and the final components' names match.
184 1.36 christos */
185 1.36 christos static int
186 1.36 christos samedirent(const char *path1, const char *path2)
187 1.36 christos {
188 1.36 christos const char *file1, *file2;
189 1.36 christos char pathbuf[PATH_MAX];
190 1.36 christos struct stat sb1, sb2;
191 1.36 christos
192 1.36 christos if (strcmp(path1, path2) == 0)
193 1.36 christos return 1;
194 1.36 christos file1 = strrchr(path1, '/');
195 1.36 christos if (file1 != NULL)
196 1.36 christos file1++;
197 1.36 christos else
198 1.36 christos file1 = path1;
199 1.36 christos file2 = strrchr(path2, '/');
200 1.36 christos if (file2 != NULL)
201 1.36 christos file2++;
202 1.36 christos else
203 1.36 christos file2 = path2;
204 1.36 christos if (strcmp(file1, file2) != 0)
205 1.36 christos return 0;
206 1.36 christos if (file1 - path1 >= PATH_MAX || file2 - path2 >= PATH_MAX)
207 1.36 christos return 0;
208 1.36 christos if (file1 == path1)
209 1.36 christos memcpy(pathbuf, ".", 2);
210 1.36 christos else {
211 1.36 christos memcpy(pathbuf, path1, file1 - path1);
212 1.36 christos pathbuf[file1 - path1] = '\0';
213 1.22 jschauma }
214 1.36 christos if (stat(pathbuf, &sb1) != 0)
215 1.36 christos return 0;
216 1.36 christos if (file2 == path2)
217 1.36 christos memcpy(pathbuf, ".", 2);
218 1.36 christos else {
219 1.36 christos memcpy(pathbuf, path2, file2 - path2);
220 1.36 christos pathbuf[file2 - path2] = '\0';
221 1.22 jschauma }
222 1.36 christos if (stat(pathbuf, &sb2) != 0)
223 1.36 christos return 0;
224 1.36 christos return sb1.st_dev == sb2.st_dev && sb1.st_ino == sb2.st_ino;
225 1.1 cgd }
226 1.1 cgd
227 1.35 joerg static int
228 1.36 christos linkit(const char *source, const char *target, int isdir)
229 1.1 cgd {
230 1.9 mycroft struct stat sb;
231 1.30 christos const char *p;
232 1.31 elad int ch, exists, first;
233 1.36 christos char path[PATH_MAX];
234 1.36 christos char wbuf[PATH_MAX];
235 1.36 christos char bbuf[PATH_MAX];
236 1.1 cgd
237 1.1 cgd if (!sflag) {
238 1.36 christos /* If source doesn't exist, quit now. */
239 1.36 christos if ((Pflag ? lstat : stat)(source, &sb)) {
240 1.36 christos warn("%s", source);
241 1.36 christos return (1);
242 1.36 christos }
243 1.36 christos /* Only symbolic links to directories. */
244 1.36 christos if (S_ISDIR(sb.st_mode)) {
245 1.36 christos errno = EISDIR;
246 1.36 christos warn("%s", source);
247 1.9 mycroft return (1);
248 1.1 cgd }
249 1.1 cgd }
250 1.1 cgd
251 1.36 christos /*
252 1.36 christos * If the target is a directory (and not a symlink if hflag),
253 1.36 christos * append the source's name.
254 1.36 christos */
255 1.11 jtk if (isdir ||
256 1.36 christos (lstat(target, &sb) == 0 && S_ISDIR(sb.st_mode)) ||
257 1.36 christos (!hflag && stat(target, &sb) == 0 && S_ISDIR(sb.st_mode))) {
258 1.36 christos if (strlcpy(bbuf, source, sizeof(bbuf)) >= sizeof(bbuf) ||
259 1.36 christos (p = basename(bbuf)) == NULL ||
260 1.36 christos snprintf(path, sizeof(path), "%s/%s", target, p) >=
261 1.36 christos (ssize_t)sizeof(path)) {
262 1.36 christos errno = ENAMETOOLONG;
263 1.36 christos warn("%s", source);
264 1.36 christos return (1);
265 1.36 christos }
266 1.36 christos target = path;
267 1.5 jtc }
268 1.5 jtc
269 1.36 christos /*
270 1.36 christos * If the link source doesn't exist, and a symbolic link was
271 1.36 christos * requested, and -w was specified, give a warning.
272 1.36 christos */
273 1.36 christos if (sflag && wflag) {
274 1.36 christos if (*source == '/') {
275 1.36 christos /* Absolute link source. */
276 1.36 christos if (stat(source, &sb) != 0)
277 1.36 christos warn("warning: %s inaccessible", source);
278 1.36 christos } else {
279 1.36 christos /*
280 1.36 christos * Relative symlink source. Try to construct the
281 1.36 christos * absolute path of the source, by appending `source'
282 1.36 christos * to the parent directory of the target.
283 1.36 christos */
284 1.36 christos strlcpy(bbuf, target, sizeof(bbuf));
285 1.36 christos p = dirname(bbuf);
286 1.36 christos if (p != NULL) {
287 1.36 christos (void)snprintf(wbuf, sizeof(wbuf), "%s/%s",
288 1.36 christos p, source);
289 1.36 christos if (stat(wbuf, &sb) != 0)
290 1.36 christos warn("warning: %s", source);
291 1.36 christos }
292 1.36 christos }
293 1.36 christos }
294 1.31 elad
295 1.9 mycroft /*
296 1.36 christos * If the file exists, first check it is not the same directory entry.
297 1.36 christos */
298 1.36 christos exists = !lstat(target, &sb);
299 1.36 christos if (exists) {
300 1.36 christos if (!sflag && samedirent(source, target)) {
301 1.36 christos warnx("%s and %s are the same directory entry",
302 1.36 christos source, target);
303 1.36 christos return (1);
304 1.36 christos }
305 1.36 christos }
306 1.36 christos /*
307 1.36 christos * Then unlink it forcibly if -f was specified
308 1.31 elad * and interactively if -i was specified.
309 1.9 mycroft */
310 1.31 elad if (fflag && exists) {
311 1.36 christos if (Fflag && S_ISDIR(sb.st_mode)) {
312 1.36 christos if (rmdir(target)) {
313 1.36 christos warn("%s", target);
314 1.36 christos return (1);
315 1.36 christos }
316 1.36 christos } else if (unlink(target)) {
317 1.36 christos warn("%s", target);
318 1.31 elad return (1);
319 1.31 elad }
320 1.31 elad } else if (iflag && exists) {
321 1.31 elad fflush(stdout);
322 1.36 christos fprintf(stderr, "replace %s? ", target);
323 1.31 elad
324 1.31 elad first = ch = getchar();
325 1.36 christos while(ch != '\n' && ch != EOF)
326 1.31 elad ch = getchar();
327 1.31 elad if (first != 'y' && first != 'Y') {
328 1.36 christos fprintf(stderr, "not replaced\n");
329 1.31 elad return (1);
330 1.31 elad }
331 1.31 elad
332 1.36 christos if (Fflag && S_ISDIR(sb.st_mode)) {
333 1.36 christos if (rmdir(target)) {
334 1.36 christos warn("%s", target);
335 1.36 christos return (1);
336 1.36 christos }
337 1.36 christos } else if (unlink(target)) {
338 1.36 christos warn("%s", target);
339 1.31 elad return (1);
340 1.31 elad }
341 1.31 elad }
342 1.31 elad
343 1.31 elad /* Attempt the link. */
344 1.36 christos if (sflag ? symlink(source, target) :
345 1.36 christos linkat(AT_FDCWD, source, AT_FDCWD, target,
346 1.36 christos Pflag ? 0 : AT_SYMLINK_FOLLOW)) {
347 1.36 christos warn("%s", target);
348 1.5 jtc return (1);
349 1.1 cgd }
350 1.21 jrf if (vflag)
351 1.36 christos (void)printf("%s %c> %s\n", target, linkch, source);
352 1.9 mycroft return (0);
353 1.1 cgd }
354 1.1 cgd
355 1.37 christos static __dead void
356 1.19 wiz usage(void)
357 1.1 cgd {
358 1.37 christos (void)fprintf(stderr,
359 1.37 christos "usage: %s [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file [target_file]\n"
360 1.37 christos " %s [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file ... target_dir\n"
361 1.37 christos " link source_file target_file\n", getprogname(), getprogname());
362 1.1 cgd exit(1);
363 1.1 cgd }
364