diff options
author | Christian Neukirchen <chneukirchen@gmail.com> | 2014-07-30 18:25:14 +0200 |
---|---|---|
committer | Christian Neukirchen <chneukirchen@gmail.com> | 2014-07-31 16:00:16 +0200 |
commit | d6872925c8b6b13b59a1ece32416aa8ef9c12c70 (patch) | |
tree | f9d4d6c4152241476dbd1eb3c8765908c065b147 /src/usr.bin/lndir | |
download | outils-d6872925c8b6b13b59a1ece32416aa8ef9c12c70.tar.gz outils-d6872925c8b6b13b59a1ece32416aa8ef9c12c70.tar.xz outils-d6872925c8b6b13b59a1ece32416aa8ef9c12c70.zip |
initial import of OpenBSD tools
Diffstat (limited to 'src/usr.bin/lndir')
-rw-r--r-- | src/usr.bin/lndir/Makefile | 5 | ||||
-rw-r--r-- | src/usr.bin/lndir/lndir.1 | 206 | ||||
-rw-r--r-- | src/usr.bin/lndir/lndir.c | 323 |
3 files changed, 534 insertions, 0 deletions
diff --git a/src/usr.bin/lndir/Makefile b/src/usr.bin/lndir/Makefile new file mode 100644 index 0000000..acd7907 --- /dev/null +++ b/src/usr.bin/lndir/Makefile @@ -0,0 +1,5 @@ +# $OpenBSD: Makefile,v 1.1 1996/08/19 05:47:25 downsj Exp $ + +PROG= lndir + +.include <bsd.prog.mk> diff --git a/src/usr.bin/lndir/lndir.1 b/src/usr.bin/lndir/lndir.1 new file mode 100644 index 0000000..70c7afb --- /dev/null +++ b/src/usr.bin/lndir/lndir.1 @@ -0,0 +1,206 @@ +.\" $OpenBSD: lndir.1,v 1.24 2013/08/14 06:32:30 jmc Exp $ +.\" +.\" Copyright (c) 1997, Jason Downs. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS +.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +.\" DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, +.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +.\" CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $XConsortium: lndir.man /main/9 1995/12/15 14:00:35 gildea $ +.\" +.\" Copyright (c) 1993, 1994 X Consortium +.\" +.\" Permission is hereby granted, free of charge, to any person obtaining +.\" a copy of this software and associated documentation files (the +.\" "Software"), to deal in the Software without restriction, including +.\" without limitation the rights to use, copy, modify, merge, publish, +.\" distribute, sublicense, and/or sell copies of the Software, and to +.\" permit persons to whom the Software is furnished to do so, subject to +.\" the following conditions: +.\" +.\" 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 X CONSORTIUM 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 X Consortium 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 X Consortium. +.\" +.Dd $Mdocdate: August 14 2013 $ +.Dt LNDIR 1 +.Os +.Sh NAME +.Nm lndir +.Nd create a shadow directory of symbolic links to another directory tree +.Sh SYNOPSIS +.Nm lndir +.Op Fl is +.Op Fl e Ar exceptfile +.Ar fromdir +.Op Ar todir +.Sh DESCRIPTION +The +.Nm +program makes a shadow copy +.Ar todir +of a directory tree +.Ar fromdir , +except that the shadow is not +populated with real files but instead with symbolic links pointing at +the real files in the +.Ar fromdir +directory tree. +This is usually useful for maintaining source code for +different machine architectures. +You create a shadow directory +containing links to the real source, which you will have usually +mounted from a remote machine. +You can build in the shadow tree, and +the object files will be in the shadow directory, while the +source files in the shadow directory are just symlinks to the real +files. +.Pp +This scheme has the advantage that if you update the source, you need not +propagate the change to the other architectures by hand, since all +source in all shadow directories are symlinks to the real thing: +just change working directory to the shadow directory and recompile away. +.Pp +The +.Ar todir +argument is optional and defaults to the current directory. +The +.Ar fromdir +argument may be relative (e.g.\& +.Pa ../src ) +and is relative to +.Ar todir +(not the current directory). +.Pp +If you add files, simply run +.Nm +again. +New files will be silently added. +Old files will be +checked that they have the correct link. +.Pp +Deleting files is a more painful problem; the symlinks will +just point into never never land. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl e Ar exceptfile +Add the specified file to the list of excluded files/directories. +This is effective in all directories searched by +.Nm . +This option may be specified as many times as needed. +.Pp +The following types of files are excluded by default: +.Pp +.Bl -dash -offset indent -compact +.It +files whose names end in +.Sq ~ +.It +files whose names start with +.Sq .# +.It +RCS, SCCS, CVS, and CVS.adm directories +.El +.It Fl i +If a file in +.Ar fromdir +is a symbolic link, +.Nm +will make the same link in +.Ar todir +rather than making a link back to the (symbolic link) entry in +.Ar fromdir . +The +.Fl i +flag changes that behavior, +i.e. it causes the program to not treat symbolic links in +.Ar fromdir +specially. +The link created in +.Ar todir +will point back to the corresponding (symbolic link) file in +.Ar fromdir . +If the link is to a directory, this is almost certainly the wrong thing. +.Pp +This option exists mostly to emulate the behavior the C version of +.Nm +had in X11R6. +Its use is not recommended. +.It Fl s +Suppresses status messages normally output as +.Nm +descends into each subdirectory. +.El +.Sh DIAGNOSTICS +The program displays the name of each subdirectory it enters, followed +by a colon. +The +.Fl s +option suppresses these messages. +.Pp +A warning message is displayed if the symbolic link cannot be created. +The usual problem is that a regular file of the same name already +exists. +.Pp +If the link already exists but doesn't point to the correct file, the +program prints the link name and the location where it does point. +.Sh SEE ALSO +.Xr find 1 , +.Xr ln 1 , +.Xr patch 1 +.Sh HISTORY +.Nm +was first distributed as part of X11. +.Pp +This version first appeared in +.Ox 1.2 . +.Sh BUGS +The +.Xr patch 1 +program gets upset if it cannot change the files. +You should never run +.Xr patch 1 +from a shadow directory anyway. +.Pp +To clear out all files before you can relink +(if +.Ar fromdir +moved, for instance): +.Bd -literal -offset indent +$ find todir -type l -print0 | xargs -0 -r rm +.Ed +.Pp +Find all files that are not directories: +.Bd -literal -offset indent +$ find . ! -type d -print0 +.Ed diff --git a/src/usr.bin/lndir/lndir.c b/src/usr.bin/lndir/lndir.c new file mode 100644 index 0000000..a6f3044 --- /dev/null +++ b/src/usr.bin/lndir/lndir.c @@ -0,0 +1,323 @@ +/* $OpenBSD: lndir.c,v 1.20 2014/05/20 01:25:23 guenther Exp $ */ +/* $XConsortium: lndir.c /main/15 1995/08/30 10:56:18 gildea $ */ + +/* + * Create shadow link tree (after X11R4 script of the same name) + * Mark Reinhold (mbr@lcs.mit.edu)/3 January 1990 + */ + +/* +Copyright (c) 1990, X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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 +X CONSORTIUM 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 X Consortium 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 X Consortium. + +*/ + +/* From the original /bin/sh script: + + Used to create a copy of the a directory tree that has links for all + non-directories (except those named 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 <sys/param.h> +#include <sys/stat.h> + +#include <dirent.h> +#include <err.h> +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +extern char *__progname; + +int silent; /* -silent */ +int ignore_links; /* -ignorelinks */ + +char *rcurdir; +char *curdir; + +int equivalent(char *, char *); +void addexcept(char *); +int dodir(char *, struct stat *, struct stat *, int); +void usage(void); + +struct except { + char *name; + struct except *next; +}; + +struct except *exceptions; + +int +main(int argc, char *argv[]) +{ + struct stat fs, ts; + char *fn, *tn; + + while (++argv, --argc) { + if ((strcmp(*argv, "-silent") == 0) || + (strcmp(*argv, "-s") == 0)) + silent = 1; + else if ((strcmp(*argv, "-ignorelinks") == 0) || + (strcmp(*argv, "-i") == 0)) + ignore_links = 1; + else if (strcmp(*argv, "-e") == 0) { + ++argv, --argc; + + if (argc < 2) + usage(); + addexcept(*argv); + } else if (strcmp(*argv, "--") == 0) { + ++argv, --argc; + break; + } else + break; + } + + if (argc < 1 || argc > 2) + usage(); + + fn = argv[0]; + if (argc == 2) + tn = argv[1]; + else + tn = "."; + + /* to directory */ + if (stat(tn, &ts) < 0) + err(1, "%s", tn); + if (!(S_ISDIR(ts.st_mode))) + errc(2, ENOTDIR, "%s", tn); + if (chdir(tn) < 0) + err(1, "%s", tn); + + /* from directory */ + if (stat(fn, &fs) < 0) + err(1, "%s", fn); + if (!(S_ISDIR(fs.st_mode))) + errc(2, ENOTDIR, "%s", fn); + + exit(dodir(fn, &fs, &ts, 0)); +} + +int +equivalent(char *lname, char *rname) +{ + char *s, *ns; + + if (strcmp(lname, rname) == 0) + return(1); + for (s = lname; *s && (s = strchr(s, '/')); s++) { + if (s[1] == '/') { + /* collapse multiple slashes in lname */ + for (ns = s + 1; *ns == '/'; ns++) + ; + memmove(s + 1, ns, strlen(ns) + 1); + } + } + return (strcmp(lname, rname) == 0); +} + +void +addexcept(char *name) +{ + struct except *new; + + new = malloc(sizeof(struct except)); + if (new == NULL) + err(1, NULL); + new->name = strdup(name); + if (new->name == NULL) + err(1, NULL); + + new->next = exceptions; + exceptions = new; +} + + +/* + * Recursively create symbolic links from the current directory to the "from" + * directory. Assumes that files described by fs and ts are directories. + */ +#if 0 + char *fn; /* name of "from" directory, either absolute or + relative to cwd */ + struct stat *fs, *ts; /* stats for the "from" directory and cwd */ + int rel; /* if true, prepend "../" to fn before using */ +#endif +int +dodir(char *fn, struct stat *fs, struct stat *ts, int rel) +{ + char buf[MAXPATHLEN + 1], symbuf[MAXPATHLEN + 1]; + char basesym[MAXPATHLEN + 1]; + int n_dirs, symlen, basesymlen = -1; + struct stat sb, sc; + struct except *cur; + struct dirent *dp; + char *ocurdir, *p; + DIR *df; + + if (fs->st_dev == ts->st_dev && fs->st_ino == ts->st_ino) { + warnx("%s: From and to directories are identical!", fn); + return(1); + } + + if (rel) + strlcpy(buf, "../", sizeof(buf)); + else + buf[0] = '\0'; + strlcat(buf, fn, sizeof(buf)); + + if (!(df = opendir(buf))) { + warn("%s: Cannot opendir", buf); + return(1); + } + + p = buf + strlen(buf); + *p++ = '/'; + n_dirs = fs->st_nlink; + while ((dp = readdir(df))) { + if (dp->d_namlen == 0 || dp->d_name[dp->d_namlen - 1] == '~' || + strncmp(dp->d_name, ".#", 2) == 0) + continue; + for (cur = exceptions; cur != NULL; cur = cur->next) { + if (!strcmp(dp->d_name, cur->name)) + goto next; /* can't continue */ + } + strlcpy(p, dp->d_name, buf + sizeof(buf) - p); + + if (n_dirs > 0) { + if (stat(buf, &sb) < 0) { + warn("%s", buf); + continue; + } + + if (S_ISDIR(sb.st_mode)) { + /* directory */ + n_dirs--; + if (dp->d_name[0] == '.' && + (dp->d_name[1] == '\0' || + (dp->d_name[1] == '.' && + dp->d_name[2] == '\0'))) + 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; + ocurdir = rcurdir; + rcurdir = buf; + curdir = silent ? buf : NULL; + 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) { + warn("%s", dp->d_name); + curdir = rcurdir = ocurdir; + continue; + } + } + if (readlink(dp->d_name, symbuf, + sizeof(symbuf) - 1) >= 0) { + fprintf(stderr, + "%s: is a link instead of a " + "directory\n", + dp->d_name); + curdir = rcurdir = ocurdir; + continue; + } + if (chdir(dp->d_name) < 0) { + warn("%s", dp->d_name); + curdir = rcurdir = ocurdir; + continue; + } + dodir(buf, &sb, &sc, (buf[0] != '/')); + if (chdir("..") < 0) + err(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 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)) + fprintf(stderr,"%s: %s\n", dp->d_name, symbuf); + } else { + if (symlink(basesymlen >= 0 ? basesym : buf, + dp->d_name) < 0) + warn("%s", dp->d_name); + } +next: + ; + } + + closedir(df); + return (0); +} + +void +usage(void) +{ + fprintf(stderr, "usage: %s [-is] [-e exceptfile] fromdir [todir]\n", + __progname); + exit(1); +} |