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--, 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
linkit(char * from,char * to)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
Perror(char * s)114 Perror(char *s)
115 {
116 (void) fprintf(stderr, "ln: ");
117 perror(s);
118 }
119