diff options
Diffstat (limited to 'nx-X11/config/util/lndir.c')
-rw-r--r-- | nx-X11/config/util/lndir.c | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/nx-X11/config/util/lndir.c b/nx-X11/config/util/lndir.c new file mode 100644 index 000000000..cd1d983b0 --- /dev/null +++ b/nx-X11/config/util/lndir.c @@ -0,0 +1,391 @@ +/* $Xorg: lndir.c,v 1.5 2001/02/09 02:03:17 xorgcvs Exp $ */ +/* Create shadow link tree (after X11R4 script of the same name) + Mark Reinhold (mbr@lcs.mit.edu)/3 January 1990 */ + +/* +Copyright (c) 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* $XFree86: xc/config/util/lndir.c,v 3.18 2003/06/24 15:44:45 eich Exp $ */ + +/* From the original /bin/sh script: + + Used to create a copy of the a directory tree that has links for all + non-directories (except, by default, those named BitKeeper, RCS, SCCS + or CVS.adm). If you are building the distribution on more than one + machine, you should use this technique. + + If your master sources are located in /usr/local/src/X and you would like + your link tree to be in /usr/local/src/new-X, do the following: + + % mkdir /usr/local/src/new-X + % cd /usr/local/src/new-X + % lndir ../X +*/ + +#include <X11/Xos.h> +#include <X11/Xfuncproto.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#if !defined(MINIX) && !defined(Lynx) +#include <sys/param.h> +#endif +#include <errno.h> + +#ifndef X_NOT_POSIX +#include <dirent.h> +#else +#ifdef SYSV +#include <dirent.h> +#else +#ifdef USG +#include <dirent.h> +#else +#include <sys/dir.h> +#ifndef dirent +#define dirent direct +#endif +#endif +#endif +#endif +#ifndef MAXPATHLEN +#define MAXPATHLEN 2048 +#endif + +#include <stdarg.h> + +int silent = 0; /* -silent */ +int ignore_links = 0; /* -ignorelinks */ +int with_revinfo = 0; /* -withrevinfo */ + +char *rcurdir; +char *curdir; + +static void +quit (int code, char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf (stderr, fmt, args); + va_end(args); + putc ('\n', stderr); + exit (code); +} + +static void +quiterr (int code, char *s) +{ + perror (s); + exit (code); +} + +static void +msg (char * fmt, ...) +{ + va_list args; + if (curdir) { + fprintf (stderr, "%s:\n", curdir); + curdir = 0; + } + va_start(args, fmt); + vfprintf (stderr, fmt, args); + va_end(args); + putc ('\n', stderr); +} + +static void +mperror (char *s) +{ + if (curdir) { + fprintf (stderr, "%s:\n", curdir); + curdir = 0; + } + perror (s); +} + + +static int +equivalent(char *lname, char *rname, char **p) +{ + char *s; + + if (!strcmp(lname, rname)) + return 1; + for (s = lname; *s && (s = strchr(s, '/')); s++) { + while (s[1] == '/') { + strcpy(s+1, s+2); + if (*p) (*p)--; + } + } + return !strcmp(lname, rname); +} + + +/* Recursively create symbolic links from the current directory to the "from" + directory. Assumes that files described by fs and ts are directories. */ +static int +dodir (char *fn, /* name of "from" directory, either absolute or + relative to cwd */ + struct stat *fs, + struct stat *ts, /* stats for the "from" directory and cwd */ + int rel) /* if true, prepend "../" to fn before using */ +{ + DIR *df; + struct dirent *dp; + char buf[MAXPATHLEN + 1], *p; + char symbuf[MAXPATHLEN + 1]; + char basesym[MAXPATHLEN + 1]; + struct stat sb, sc; + int n_dirs; + int symlen; + int basesymlen = -1; + char *ocurdir; + + if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino)) { + msg ("%s: From and to directories are identical!", fn); + return 1; + } + + if (rel) + strcpy (buf, "../"); + else + buf[0] = '\0'; + strcat (buf, fn); + + if (!(df = opendir (buf))) { + msg ("%s: Cannot opendir", buf); + return 1; + } + + p = buf + strlen (buf); + if (*(p - 1) != '/') + *p++ = '/'; + n_dirs = fs->st_nlink; + while ((dp = readdir (df))) { + if (dp->d_name[strlen(dp->d_name) - 1] == '~') + continue; +#ifdef __DARWIN__ + /* Ignore these Mac OS X Finder data files */ + if (!strcmp(dp->d_name, ".DS_Store") || + !strcmp(dp->d_name, "._.DS_Store")) + continue; +#endif + strcpy (p, dp->d_name); + + if (n_dirs > 0) { + if (lstat (buf, &sb) < 0) { + mperror (buf); + continue; + } + +#ifdef S_ISDIR + if(S_ISDIR(sb.st_mode)) +#else + if ((sb.st_mode & S_IFMT) == S_IFDIR) +#endif + { + /* directory */ + n_dirs--; + if (dp->d_name[0] == '.' && + (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' && + dp->d_name[2] == '\0'))) + continue; + if (!with_revinfo) { + if (!strcmp (dp->d_name, "BitKeeper")) + continue; + if (!strcmp (dp->d_name, "RCS")) + continue; + if (!strcmp (dp->d_name, "SCCS")) + continue; + if (!strcmp (dp->d_name, "CVS")) + continue; + if (!strcmp (dp->d_name, "CVS.adm")) + continue; + if (!strcmp (dp->d_name, ".svn")) + continue; + } + ocurdir = rcurdir; + rcurdir = buf; + curdir = silent ? buf : (char *)0; + if (!silent) + printf ("%s:\n", buf); + if ((stat (dp->d_name, &sc) < 0) && (errno == ENOENT)) { + if (mkdir (dp->d_name, 0777) < 0 || + stat (dp->d_name, &sc) < 0) { + mperror (dp->d_name); + curdir = rcurdir = ocurdir; + continue; + } + } + if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) { + msg ("%s: is a link instead of a directory", dp->d_name); + curdir = rcurdir = ocurdir; + continue; + } + if (chdir (dp->d_name) < 0) { + mperror (dp->d_name); + curdir = rcurdir = ocurdir; + continue; + } + dodir (buf, &sb, &sc, (buf[0] != '/')); + if (chdir ("..") < 0) + quiterr (1, ".."); + curdir = rcurdir = ocurdir; + continue; + } + } + + /* non-directory */ + symlen = readlink (dp->d_name, symbuf, sizeof(symbuf) - 1); + if (symlen >= 0) + symbuf[symlen] = '\0'; + + /* The option to ignore links exists mostly because + checking for them slows us down by 10-20%. + But it is off by default because this really is a useful check. */ + if (!ignore_links) { + /* see if the file in the base tree was a symlink */ + basesymlen = readlink(buf, basesym, sizeof(basesym) - 1); + if (basesymlen >= 0) + basesym[basesymlen] = '\0'; + } + + if (symlen >= 0) { + /* Link exists in new tree. Print message if it doesn't match. */ + if (!equivalent (basesymlen>=0 ? basesym : buf, symbuf, + basesymlen>=0 ? (char **) 0 : &p)) + msg ("%s: %s", dp->d_name, symbuf); + } else { + char *sympath; + + if (basesymlen>=0) { + if ((buf[0] == '.') && (buf[1] == '.') && (buf[2] == '/') && + (basesym[0] == '.') && (basesym[1] == '.') && + (basesym[2] == '/')) { + /* It becomes very tricky here. We have + ../../bar/foo symlinked to ../xxx/yyy. We + can't just use ../xxx/yyy. We have to use + ../../bar/foo/../xxx/yyy. */ + + int i; + char *start, *end; + + strcpy (symbuf, buf); + /* Find the first char after "../" in symbuf. */ + start = symbuf; + do { + start += 3; + } while ((start[0] == '.') && (start[1] == '.') && + (start[2] == '/')); + + /* Then try to eliminate "../"s in basesym. */ + i = 0; + end = strrchr (symbuf, '/'); + if (start < end) { + do { + i += 3; + end--; + while ((*end != '/') && (end != start)) + end--; + if (end == start) + break; + } while ((basesym[i] == '.') && + (basesym[i + 1] == '.') && + (basesym[i + 2] == '/')); + } + if (*end == '/') + end++; + strcpy (end, &basesym[i]); + sympath = symbuf; + } + else + sympath = basesym; + } + else + sympath = buf; + if (symlink (sympath, dp->d_name) < 0) + mperror (dp->d_name); + } + } + + closedir (df); + return 0; +} + +int +main (int ac, char *av[]) +{ + char *prog_name = av[0]; + char *fn, *tn; + struct stat fs, ts; + + while (++av, --ac) { + if (strcmp(*av, "-silent") == 0) + silent = 1; + else if (strcmp(*av, "-ignorelinks") == 0) + ignore_links = 1; + else if (strcmp(*av, "-withrevinfo") == 0) + with_revinfo = 1; + else if (strcmp(*av, "--") == 0) { + ++av, --ac; + break; + } + else + break; + } + + if (ac < 1 || ac > 2) + quit (1, "usage: %s [-silent] [-ignorelinks] fromdir [todir]", + prog_name); + + fn = av[0]; + if (ac == 2) + tn = av[1]; + else + tn = "."; + + /* to directory */ + if (stat (tn, &ts) < 0) + quiterr (1, tn); +#ifdef S_ISDIR + if (!(S_ISDIR(ts.st_mode))) +#else + if (!(ts.st_mode & S_IFMT) == S_IFDIR) +#endif + quit (2, "%s: Not a directory", tn); + if (chdir (tn) < 0) + quiterr (1, tn); + + /* from directory */ + if (stat (fn, &fs) < 0) + quiterr (1, fn); +#ifdef S_ISDIR + if (!(S_ISDIR(fs.st_mode))) +#else + if (!(fs.st_mode & S_IFMT) == S_IFDIR) +#endif + quit (2, "%s: Not a directory", fn); + + exit (dodir (fn, &fs, &ts, 0)); +} |