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