[project @ 1996-11-15 17:29:21 by sof]
[ghc-hetmet.git] / glafp-utils / lndir / lndir.c
1 /* $XConsortium: lndir.c,v 1.5 91/07/21 15:52:11 rws Exp $ */
2 /* Create shadow link tree (after X11R4 script of the same name)
3    Mark Reinhold (mbr@lcs.mit.edu)/3 January 1990 */
4
5 /* Copyright 1990, Massachusetts Institute of Technology
6
7    Permission to use, copy, modify, and distribute this program for any purpose
8    and without fee is hereby granted, provided that this copyright and
9    permission notice appear on all copies and supporting documentation, that
10    the name of MIT not be used in advertising or publicity pertaining to
11    distribution of this program without specific prior permission, and that
12    notice be given in supporting documentation that copying and distribution is
13    by permission of MIT.  MIT makes no representations about the suitability of
14    this software for any purpose.  It is provided "as is" without expressed or
15    implied warranty.
16 */
17
18 /* From the original /bin/sh script:
19
20    Used to create a copy of the a directory tree that has links for all
21    non-directories (except those named RCS or SCCS).  If you are
22    building the distribution on more than one machine, you should use
23    this script.
24
25    If your master sources are located in /usr/local/src/X and you would like
26    your link tree to be in /usr/local/src/new-X, do the following:
27
28         %  mkdir /usr/local/src/new-X
29         %  cd /usr/local/src/new-X
30         %  lndir ../X
31 */
32
33 #include "lndir-Xos.h"
34 #include <stdio.h>
35 #include <sys/stat.h>
36 #include <sys/param.h>
37 #include <errno.h>
38
39 #ifndef X_NOT_POSIX
40 #include <dirent.h>
41 #else
42 #ifdef SYSV
43 #include <dirent.h>
44 #else
45 #ifdef USG
46 #include <dirent.h>
47 #else
48 #include <sys/dir.h>
49 #ifndef dirent
50 #define dirent direct
51 #endif
52 #endif
53 #endif
54 #endif
55
56 extern int errno;
57 int silent;
58
59 void
60 quit (code, fmt, a1, a2, a3)
61 char *fmt;
62 int code, a1, a2, a3; /* partain */
63 {
64     fprintf (stderr, fmt, a1, a2, a3);
65     putc ('\n', stderr);
66     exit (code);
67 }
68
69 void
70 quiterr (code, s)
71 char *s;
72 int code; /* partain */
73 {
74     perror (s);
75     exit (code);
76 }
77
78 void
79 msg (fmt, a1, a2, a3)
80 char *fmt;
81 int a1, a2, a3; /* partain */
82 {
83     fprintf (stderr, fmt, a1, a2, a3);
84     putc ('\n', stderr);
85 }
86
87
88 /* Recursively create symbolic links from the current directory to the "from"
89    directory.  Assumes that files described by fs and ts are directories. */
90
91 int
92 dodir (fn, fs, ts, rel)
93 char *fn;                       /* name of "from" directory, either absolute or
94                                    relative to cwd */
95 struct stat *fs, *ts;           /* stats for the "from" directory and cwd */
96 int rel;                        /* if true, prepend "../" to fn before using */
97 {
98     DIR *df;
99     struct dirent *dp;
100     char buf[MAXPATHLEN + 1], *p;
101     char symbuf[MAXPATHLEN + 1];
102     struct stat sb, sc;
103     int n_dirs;
104
105     if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino)) {
106         msg ("%s: From and to directories are identical!", fn);
107         return 1;
108     }
109
110     if (rel)
111         strcpy (buf, "../");
112     else
113         buf[0] = '\0';
114     strcat (buf, fn);
115     
116     if (!(df = opendir (buf))) {
117         msg ("%s: Cannot opendir", buf);
118         return 1;
119     }
120
121     p = buf + strlen (buf);
122     *p++ = '/';
123     n_dirs = fs->st_nlink;
124     while (dp = readdir (df)) {
125         strcpy (p, dp->d_name);
126
127         if (n_dirs > 0) {
128             if (stat (buf, &sb) < 0) {
129                 perror (buf);
130                 continue;
131             }
132
133             if (sb.st_mode & S_IFDIR) {
134                 /* directory */
135                 n_dirs--;
136                 if (dp->d_name[0] == '.' &&
137                     (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' &&
138                                                dp->d_name[2] == '\0')))
139                     continue;
140                 if (!strcmp (dp->d_name, "CVS")) /* partain */
141                     continue;
142                 if (!strcmp (dp->d_name, "RCS"))
143                     continue;
144                 if (!strcmp (dp->d_name, "SCCS"))
145                     continue;
146                 if (!silent)
147                     printf ("%s:\n", buf);
148                 if ((stat (dp->d_name, &sc) < 0) && (errno == ENOENT)) {
149                     if (mkdir (dp->d_name, 0777) < 0 ||
150                         stat (dp->d_name, &sc) < 0) {
151                         perror (dp->d_name);
152                         continue;
153                     }
154                 }
155                 if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) {
156                     msg ("%s: is a link instead of a directory\n", dp->d_name);
157                     continue;
158                 }
159                 if (chdir (dp->d_name) < 0) {
160                     perror (dp->d_name);
161                     continue;
162                 }
163                 dodir (buf, &sb, &sc, (buf[0] != '/'));
164                 if (chdir ("..") < 0)
165                     quiterr (1, "..");
166                 continue;
167             }
168         }
169
170         /* non-directory */
171         if (symlink (buf, dp->d_name) < 0) {
172             int saverrno = errno;
173             int symlen;
174             symlen = readlink(dp->d_name, symbuf, sizeof(symbuf) - 1);
175             errno = saverrno;
176             if (symlen > 0)
177                 symbuf[symlen] = '\0';
178             if (symlen < 0 || strcmp(symbuf, buf))
179                 perror (dp->d_name);
180         }
181     }
182
183     closedir (df);
184     return 0;
185 }
186
187 void
188 main (ac, av)
189 int ac;
190 char **av;
191 {
192     char *fn, *tn;
193     struct stat fs, ts;
194
195     silent = 0;
196     if (ac > 1 && !strcmp(av[1], "-silent")) {
197         silent = 1;
198     }
199     if (ac < silent + 2 || ac > silent + 3)
200         quit (1, "usage: %s [-silent] fromdir [todir]", av[0]);
201
202     fn = av[silent + 1];
203     if (ac == silent + 3)
204         tn = av[silent + 2];
205     else
206         tn = ".";
207
208     /* to directory */
209     if (stat (tn, &ts) < 0)
210         quiterr (1, tn);
211     if (!(ts.st_mode & S_IFDIR))
212         quit (2, "%s: Not a directory", tn);
213     if (chdir (tn) < 0)
214         quiterr (1, tn);
215
216     /* from directory */
217     if (stat (fn, &fs) < 0)
218         quiterr (1, fn);
219     if (!(fs.st_mode & S_IFDIR))
220         quit (2, "%s: Not a directory", fn);
221
222     exit (dodir (fn, &fs, &ts, 0));
223 }