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