xref: /illumos-gate/usr/src/ucbcmd/ln/ln.c (revision dd72704bd9e794056c558153663c739e2012d721)
1 /*
2  * Copyright 1991 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
7 /*	  All Rights Reserved  	*/
8 
9 /*
10  * Copyright (c) 1980 Regents of the University of California.
11  * All rights reserved. The Berkeley software License Agreement
12  * specifies the terms and conditions for redistribution.
13  */
14 
15 /*
16  * ln
17  */
18 #include <stdio.h>
19 #include <sys/types.h>
20 #include <sys/param.h>
21 #include <sys/stat.h>
22 #include <errno.h>
23 #include <unistd.h>
24 
25 struct	stat stb;
26 int	fflag;		/* force flag set? */
27 int	sflag;
28 
29 int linkit(char *, char *);
30 void Perror(char *);
31 
32 int
33 main(int argc, char **argv)
34 {
35 	int i, r;
36 
37 	argc--, argv++;
38 again:
39 	if (argc && strcmp(argv[0], "-f") == 0) {
40 		fflag++;
41 		argv++;
42 		argc--;
43 	}
44 	if (argc && strcmp(argv[0], "-s") == 0) {
45 		sflag++;
46 		argv++;
47 		argc--;
48 	}
49 	if (argc == 0)
50 		goto usage;
51 	else if (argc == 1) {
52 		argv[argc] = ".";
53 		argc++;
54 	}
55 	if (argc > 2) {
56 		if (stat(argv[argc-1], &stb) < 0)
57 			goto usage;
58 		if ((stb.st_mode&S_IFMT) != S_IFDIR)
59 			goto usage;
60 	}
61 	r = 0;
62 	for (i = 0; i < argc-1; i++)
63 		r |= linkit(argv[i], argv[argc-1]);
64 	exit(r);
65 usage:
66 	(void) fprintf(stderr,
67 	    "Usage: ln [-f] [-s] f1\n\
68        ln [-f] [-s] f1 f2\n\
69        ln [-f] [-s] f1 ... fn d1\n");
70 	return (1);
71 }
72 
73 int
74 linkit(char *from, char *to)
75 {
76 	char destname[MAXPATHLEN + 1];
77 	char *tail;
78 	int (*linkf)() = sflag ? symlink : link;
79 	char *strrchr();
80 
81 	/* is target a directory? */
82 	if (sflag == 0 && fflag == 0 && stat(from, &stb) >= 0 &&
83 	    (stb.st_mode&S_IFMT) == S_IFDIR) {
84 		printf("%s is a directory\n", from);
85 		return (1);
86 	}
87 	if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR) {
88 		tail = strrchr(from, '/');
89 		if (tail == 0)
90 			tail = from;
91 		else
92 			tail++;
93 		if (strlen(to) + strlen(tail) >= sizeof (destname) - 1) {
94 			(void) fprintf(stderr, "ln: %s/%s: Name too long\n",
95 			    to, tail);
96 			return (1);
97 		}
98 		(void) sprintf(destname, "%s/%s", to, tail);
99 		to = destname;
100 	}
101 	if ((*linkf)(from, to) < 0) {
102 		if (errno == EEXIST || sflag)
103 			Perror(to);
104 		else if (access(from, 0) < 0)
105 			Perror(from);
106 		else
107 			Perror(to);
108 		return (1);
109 	}
110 	return (0);
111 }
112 
113 void
114 Perror(char *s)
115 {
116 	(void) fprintf(stderr, "ln: ");
117 	perror(s);
118 }
119