1 /* $TOG: lndir.c /main/17 1998/02/06 11:23:50 kaleb $ */
2 /* Create shadow link tree (after X11R4 script of the same name)
3 Mark Reinhold (mbr@lcs.mit.edu)/3 January 1990 */
6 Copyright (c) 1990, 1998 The Open Group
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
17 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 Except as contained in this notice, the name of The Open Group shall not be
21 used in advertising or otherwise to promote the sale, use or other dealings
22 in this Software without prior written authorization from The Open Group.
26 /* From the original /bin/sh script:
28 Used to create a copy of the a directory tree that has links for all
29 non-directories (except those named RCS, SCCS or CVS.adm). If you are
30 building the distribution on more than one machine, you should use
33 If your master sources are located in /usr/local/src/X and you would like
34 your link tree to be in /usr/local/src/new-X, do the following:
36 % mkdir /usr/local/src/new-X
37 % cd /usr/local/src/new-X
42 #include <X11/Xfuncproto.h>
45 #include <sys/param.h>
65 #define MAXPATHLEN 2048
68 #if NeedVarargsPrototypes
75 int silent = 0; /* -silent */
76 int ignore_links = 0; /* -ignorelinks */
83 #if NeedVarargsPrototypes
84 int code, char * fmt, ...)
86 code, fmt, a1, a2, a3)
90 #if NeedVarargsPrototypes
93 vfprintf (stderr, fmt, args);
96 fprintf (stderr, fmt, a1, a2, a3);
112 #if NeedVarargsPrototypes
119 #if NeedVarargsPrototypes
123 fprintf (stderr, "%s:\n", curdir);
126 #if NeedVarargsPrototypes
128 vfprintf (stderr, fmt, args);
131 fprintf (stderr, fmt, a1, a2, a3);
141 fprintf (stderr, "%s:\n", curdir);
148 int equivalent(lname, rname)
154 if (!strcmp(lname, rname))
156 for (s = lname; *s && (s = strchr(s, '/')); s++) {
160 return !strcmp(lname, rname);
164 /* Recursively create symbolic links from the current directory to the "from"
165 directory. Assumes that files described by fs and ts are directories. */
167 dodir (fn, fs, ts, rel)
168 char *fn; /* name of "from" directory, either absolute or
170 struct stat *fs, *ts; /* stats for the "from" directory and cwd */
171 int rel; /* if true, prepend "../" to fn before using */
175 char buf[MAXPATHLEN + 1], *p;
176 char symbuf[MAXPATHLEN + 1];
177 char basesym[MAXPATHLEN + 1];
184 if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino)) {
185 msg ("%s: From and to directories are identical!", fn);
195 if (!(df = opendir (buf))) {
196 msg ("%s: Cannot opendir", buf);
200 p = buf + strlen (buf);
202 n_dirs = fs->st_nlink;
203 while (dp = readdir (df)) {
204 if (dp->d_name[strlen(dp->d_name) - 1] == '~')
206 strcpy (p, dp->d_name);
209 if (stat (buf, &sb) < 0) {
215 if(S_ISDIR(sb.st_mode))
217 if (sb.st_mode & S_IFDIR)
222 if (dp->d_name[0] == '.' &&
223 (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' &&
224 dp->d_name[2] == '\0')))
226 if (!strcmp (dp->d_name, "RCS"))
228 if (!strcmp (dp->d_name, "SCCS"))
230 if (!strcmp (dp->d_name, "CVS"))
232 if (!strcmp (dp->d_name, "CVS.adm"))
236 curdir = silent ? buf : (char *)0;
238 printf ("%s:\n", buf);
239 if ((stat (dp->d_name, &sc) < 0) && (errno == ENOENT)) {
240 if (mkdir (dp->d_name, 0777) < 0 ||
241 stat (dp->d_name, &sc) < 0) {
242 mperror (dp->d_name);
243 curdir = rcurdir = ocurdir;
247 if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) {
248 msg ("%s: is a link instead of a directory", dp->d_name);
249 curdir = rcurdir = ocurdir;
252 if (chdir (dp->d_name) < 0) {
253 mperror (dp->d_name);
254 curdir = rcurdir = ocurdir;
257 dodir (buf, &sb, &sc, (buf[0] != '/'));
258 if (chdir ("..") < 0)
260 curdir = rcurdir = ocurdir;
266 symlen = readlink (dp->d_name, symbuf, sizeof(symbuf) - 1);
268 symbuf[symlen] = '\0';
270 /* The option to ignore links exists mostly because
271 checking for them slows us down by 10-20%.
272 But it is off by default because this really is a useful check. */
274 /* see if the file in the base tree was a symlink */
275 basesymlen = readlink(buf, basesym, sizeof(basesym) - 1);
277 basesym[basesymlen] = '\0';
281 /* Link exists in new tree. Print message if it doesn't match. */
282 if (!equivalent (basesymlen>=0 ? basesym : buf, symbuf))
283 msg ("%s: %s", dp->d_name, symbuf);
285 if (symlink (basesymlen>=0 ? basesym : buf, dp->d_name) < 0)
286 mperror (dp->d_name);
299 char *prog_name = av[0];
304 if (strcmp(*av, "-silent") == 0)
306 else if (strcmp(*av, "-ignorelinks") == 0)
308 else if (strcmp(*av, "--") == 0) {
316 if (ac < 1 || ac > 2)
317 quit (1, "usage: %s [-silent] [-ignorelinks] fromdir [todir]",
327 if (stat (tn, &ts) < 0)
330 if (!(S_ISDIR(ts.st_mode)))
332 if (!(ts.st_mode & S_IFDIR))
334 quit (2, "%s: Not a directory", tn);
339 if (stat (fn, &fs) < 0)
342 if (!(S_ISDIR(fs.st_mode)))
344 if (!(fs.st_mode & S_IFDIR))
346 quit (2, "%s: Not a directory", fn);
348 exit (dodir (fn, &fs, &ts, 0));