xref: /illumos-gate/usr/src/ucbcmd/ln/ln.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
16 
17 /*
18  * ln
19  */
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <sys/param.h>
23 #include <sys/stat.h>
24 #include <errno.h>
25 #include <unistd.h>
26 
27 struct	stat stb;
28 int	fflag;		/* force flag set? */
29 int	sflag;
30 
31 int linkit(char *, char *);
32 void Perror(char *);
33 
34 int
35 main(int argc, char **argv)
36 {
37 	int i, r;
38 
39 	argc--, argv++;
40 again:
41 	if (argc && strcmp(argv[0], "-f") == 0) {
42 		fflag++;
43 		argv++;
44 		argc--;
45 	}
46 	if (argc && strcmp(argv[0], "-s") == 0) {
47 		sflag++;
48 		argv++;
49 		argc--;
50 	}
51 	if (argc == 0)
52 		goto usage;
53 	else if (argc == 1) {
54 		argv[argc] = ".";
55 		argc++;
56 	}
57 	if (argc > 2) {
58 		if (stat(argv[argc-1], &stb) < 0)
59 			goto usage;
60 		if ((stb.st_mode&S_IFMT) != S_IFDIR)
61 			goto usage;
62 	}
63 	r = 0;
64 	for (i = 0; i < argc-1; i++)
65 		r |= linkit(argv[i], argv[argc-1]);
66 	exit(r);
67 usage:
68 	(void) fprintf(stderr,
69 	    "Usage: ln [-f] [-s] f1\n\
70        ln [-f] [-s] f1 f2\n\
71        ln [-f] [-s] f1 ... fn d1\n");
72 	return (1);
73 }
74 
75 int
76 linkit(char *from, char *to)
77 {
78 	char destname[MAXPATHLEN + 1];
79 	char *tail;
80 	int (*linkf)() = sflag ? symlink : link;
81 	char *strrchr();
82 
83 	/* is target a directory? */
84 	if (sflag == 0 && fflag == 0 && stat(from, &stb) >= 0 &&
85 	    (stb.st_mode&S_IFMT) == S_IFDIR) {
86 		printf("%s is a directory\n", from);
87 		return (1);
88 	}
89 	if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR) {
90 		tail = strrchr(from, '/');
91 		if (tail == 0)
92 			tail = from;
93 		else
94 			tail++;
95 		if (strlen(to) + strlen(tail) >= sizeof (destname) - 1) {
96 			(void) fprintf(stderr, "ln: %s/%s: Name too long\n",
97 			    to, tail);
98 			return (1);
99 		}
100 		(void) sprintf(destname, "%s/%s", to, tail);
101 		to = destname;
102 	}
103 	if ((*linkf)(from, to) < 0) {
104 		if (errno == EEXIST || sflag)
105 			Perror(to);
106 		else if (access(from, 0) < 0)
107 			Perror(from);
108 		else
109 			Perror(to);
110 		return (1);
111 	}
112 	return (0);
113 }
114 
115 void
116 Perror(char *s)
117 {
118 	(void) fprintf(stderr, "ln: ");
119 	perror(s);
120 }
121