ln.c revision 1.39 1 1.39 kre /* $NetBSD: ln.c,v 1.39 2017/04/22 12:22:31 kre 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.39 kre __RCSID("$NetBSD: ln.c,v 1.39 2017/04/22 12:22:31 kre 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.37 christos "usage: %s [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file [target_file]\n"
362 1.37 christos " %s [-s [-F] | -L | -P] [-f | -i] [-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