2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: lndir.c /main/17 1998/02/06 11:23:50 kaleb $ */
24 /* Create shadow link tree (after X11R4 script of the same name)
25 Mark Reinhold (mbr@lcs.mit.edu)/3 January 1990 */
28 Copyright (c) 1990, 1998 The Open Group
32 The above copyright notice and this permission notice shall be included in
33 all copies or substantial portions of the Software.
35 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
39 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
40 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 Except as contained in this notice, the name of The Open Group shall not be
43 used in advertising or otherwise to promote the sale, use or other dealings
44 in this Software without prior written authorization from The Open Group.
48 /* From the original /bin/sh script:
50 Used to create a copy of the a directory tree that has links for all
51 non-directories (except those named RCS, SCCS or CVS.adm). If you are
52 building the distribution on more than one machine, you should use
55 If your master sources are located in /usr/local/src/X and you would like
56 your link tree to be in /usr/local/src/new-X, do the following:
58 % mkdir /usr/local/src/new-X
59 % cd /usr/local/src/new-X
64 #include <X11/Xfuncproto.h>
67 #include <sys/param.h>
87 #define MAXPATHLEN 2048
90 #if NeedVarargsPrototypes
97 int silent = 0; /* -silent */
98 int ignore_links = 0; /* -ignorelinks */
105 #if NeedVarargsPrototypes
106 int code, char * fmt, ...)
108 code, fmt, a1, a2, a3)
112 #if NeedVarargsPrototypes
115 vfprintf (stderr, fmt, args);
118 fprintf (stderr, fmt, a1, a2, a3);
134 #if NeedVarargsPrototypes
141 #if NeedVarargsPrototypes
145 fprintf (stderr, "%s:\n", curdir);
148 #if NeedVarargsPrototypes
150 vfprintf (stderr, fmt, args);
153 fprintf (stderr, fmt, a1, a2, a3);
163 fprintf (stderr, "%s:\n", curdir);
170 int equivalent(lname, rname)
176 if (!strcmp(lname, rname))
178 for (s = lname; *s && (s = strchr(s, '/')); s++) {
182 return !strcmp(lname, rname);
186 /* Recursively create symbolic links from the current directory to the "from"
187 directory. Assumes that files described by fs and ts are directories. */
189 dodir (fn, fs, ts, rel)
190 char *fn; /* name of "from" directory, either absolute or
192 struct stat *fs, *ts; /* stats for the "from" directory and cwd */
193 int rel; /* if true, prepend "../" to fn before using */
197 char buf[MAXPATHLEN + 1], *p;
198 char symbuf[MAXPATHLEN + 1];
199 char basesym[MAXPATHLEN + 1];
206 if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino)) {
207 msg ("%s: From and to directories are identical!", fn);
217 if (!(df = opendir (buf))) {
218 msg ("%s: Cannot opendir", buf);
222 p = buf + strlen (buf);
224 n_dirs = fs->st_nlink;
225 while (dp = readdir (df)) {
226 if (dp->d_name[strlen(dp->d_name) - 1] == '~')
228 strcpy (p, dp->d_name);
231 if (stat (buf, &sb) < 0) {
237 if(S_ISDIR(sb.st_mode))
239 if (sb.st_mode & S_IFDIR)
244 if (dp->d_name[0] == '.' &&
245 (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' &&
246 dp->d_name[2] == '\0')))
248 if (!strcmp (dp->d_name, "RCS"))
250 if (!strcmp (dp->d_name, "SCCS"))
252 if (!strcmp (dp->d_name, "CVS"))
254 if (!strcmp (dp->d_name, "CVS.adm"))
258 curdir = silent ? buf : (char *)0;
260 printf ("%s:\n", buf);
261 if ((stat (dp->d_name, &sc) < 0) && (errno == ENOENT)) {
262 if (mkdir (dp->d_name, 0777) < 0 ||
263 stat (dp->d_name, &sc) < 0) {
264 mperror (dp->d_name);
265 curdir = rcurdir = ocurdir;
269 if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) {
270 msg ("%s: is a link instead of a directory", dp->d_name);
271 curdir = rcurdir = ocurdir;
274 if (chdir (dp->d_name) < 0) {
275 mperror (dp->d_name);
276 curdir = rcurdir = ocurdir;
279 dodir (buf, &sb, &sc, (buf[0] != '/'));
280 if (chdir ("..") < 0)
282 curdir = rcurdir = ocurdir;
288 symlen = readlink (dp->d_name, symbuf, sizeof(symbuf) - 1);
290 symbuf[symlen] = '\0';
292 /* The option to ignore links exists mostly because
293 checking for them slows us down by 10-20%.
294 But it is off by default because this really is a useful check. */
296 /* see if the file in the base tree was a symlink */
297 basesymlen = readlink(buf, basesym, sizeof(basesym) - 1);
299 basesym[basesymlen] = '\0';
303 /* Link exists in new tree. Print message if it doesn't match. */
304 if (!equivalent (basesymlen>=0 ? basesym : buf, symbuf))
305 msg ("%s: %s", dp->d_name, symbuf);
307 if (symlink (basesymlen>=0 ? basesym : buf, dp->d_name) < 0)
308 mperror (dp->d_name);
321 char *prog_name = av[0];
326 if (strcmp(*av, "-silent") == 0)
328 else if (strcmp(*av, "-ignorelinks") == 0)
330 else if (strcmp(*av, "--") == 0) {
338 if (ac < 1 || ac > 2)
339 quit (1, "usage: %s [-silent] [-ignorelinks] fromdir [todir]",
349 if (stat (tn, &ts) < 0)
352 if (!(S_ISDIR(ts.st_mode)))
354 if (!(ts.st_mode & S_IFDIR))
356 quit (2, "%s: Not a directory", tn);
361 if (stat (fn, &fs) < 0)
364 if (!(S_ISDIR(fs.st_mode)))
366 if (!(fs.st_mode & S_IFDIR))
368 quit (2, "%s: Not a directory", fn);
370 exit (dodir (fn, &fs, &ts, 0));