[project @ 1996-01-08 20:28:12 by partain]
[ghc-hetmet.git] / glafp-utils / scripts / 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, "RCS"))
141                     continue;
142                 if (!strcmp (dp->d_name, "SCCS"))
143                     continue;
144                 if (!silent)
145                     printf ("%s:\n", buf);
146                 if ((stat (dp->d_name, &sc) < 0) && (errno == ENOENT)) {
147                     if (mkdir (dp->d_name, 0777) < 0 ||
148                         stat (dp->d_name, &sc) < 0) {
149                         perror (dp->d_name);
150                         continue;
151                     }
152                 }
153                 if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) {
154                     msg ("%s: is a link instead of a directory\n", dp->d_name);
155                     continue;
156                 }
157                 if (chdir (dp->d_name) < 0) {
158                     perror (dp->d_name);
159                     continue;
160                 }
161                 dodir (buf, &sb, &sc, (buf[0] != '/'));
162                 if (chdir ("..") < 0)
163                     quiterr (1, "..");
164                 continue;
165             }
166         }
167
168         /* non-directory */
169         if (symlink (buf, dp->d_name) < 0) {
170             int saverrno = errno;
171             int symlen;
172             symlen = readlink(dp->d_name, symbuf, sizeof(symbuf) - 1);
173             errno = saverrno;
174             if (symlen > 0)
175                 symbuf[symlen] = '\0';
176             if (symlen < 0 || strcmp(symbuf, buf))
177                 perror (dp->d_name);
178         }
179     }
180
181     closedir (df);
182     return 0;
183 }
184
185 void
186 main (ac, av)
187 int ac;
188 char **av;
189 {
190     char *fn, *tn;
191     struct stat fs, ts;
192
193     silent = 0;
194     if (ac > 1 && !strcmp(av[1], "-silent")) {
195         silent = 1;
196     }
197     if (ac < silent + 2 || ac > silent + 3)
198         quit (1, "usage: %s [-silent] fromdir [todir]", av[0]);
199
200     fn = av[silent + 1];
201     if (ac == silent + 3)
202         tn = av[silent + 2];
203     else
204         tn = ".";
205
206     /* to directory */
207     if (stat (tn, &ts) < 0)
208         quiterr (1, tn);
209     if (!(ts.st_mode & S_IFDIR))
210         quit (2, "%s: Not a directory", tn);
211     if (chdir (tn) < 0)
212         quiterr (1, tn);
213
214     /* from directory */
215     if (stat (fn, &fs) < 0)
216         quiterr (1, fn);
217     if (!(fs.st_mode & S_IFDIR))
218         quit (2, "%s: Not a directory", fn);
219
220     exit (dodir (fn, &fs, &ts, 0));
221 }