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