[Midnightbsd-cvs] src: src/usr.bin: Add lndir.
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Wed Mar 12 17:34:42 EDT 2008
Log Message:
-----------
Add lndir.
Modified Files:
--------------
src/usr.bin:
Makefile (r1.12 -> r1.13)
Added Files:
-----------
src/usr.bin/lndir:
Makefile (r1.1)
lndir.1 (r1.1)
lndir.c (r1.1)
-------------- next part --------------
Index: Makefile
===================================================================
RCS file: /home/cvs/src/usr.bin/Makefile,v
retrieving revision 1.12
retrieving revision 1.13
diff -L usr.bin/Makefile -L usr.bin/Makefile -u -r1.12 -r1.13
--- usr.bin/Makefile
+++ usr.bin/Makefile
@@ -102,6 +102,7 @@
lesskey \
${_lex} \
limits \
+ lndir \
locale \
locate \
lock \
--- /dev/null
+++ usr.bin/lndir/lndir.c
@@ -0,0 +1,317 @@
+/* $MidnightBSD: src/usr.bin/lndir/lndir.c,v 1.1 2008/03/12 21:34:42 laffer1 Exp $ */
+/* $OpenBSD: lndir.c,v 1.18 2006/11/15 22:23:11 miod 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 at 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 = 0; /* -silent */
+int ignore_links = 0; /* -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 = (struct except *)NULL;
+
+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)))
+ errx(2, "%s: %s", tn, strerror(ENOTDIR));
+ 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)))
+ errx(2, "%s: %s", fn, strerror(ENOTDIR));
+
+ 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 = (struct except *)malloc(sizeof(struct except));
+ if (new == (struct except *)NULL)
+ err(1, NULL);
+ new->name = strdup(name);
+ if (new->name == (char *)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], 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 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))
+ 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)
+{
+ (void)fprintf(stderr, "usage: %s [-is] [-e exceptfile] fromdir [todir]\n",
+ __progname);
+ exit(1);
+}
--- /dev/null
+++ usr.bin/lndir/lndir.1
@@ -0,0 +1,207 @@
+.\" $MidnightBSD: src/usr.bin/lndir/lndir.1,v 1.1 2008/03/12 21:34:42 laffer1 Exp $
+.\" $OpenBSD: lndir.1,v 1.23 2008/01/11 20:16:02 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: May 31 2007 $
+.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
--- /dev/null
+++ usr.bin/lndir/Makefile
@@ -0,0 +1,5 @@
+# $MidnightBSD: src/usr.bin/lndir/Makefile,v 1.1 2008/03/12 21:34:42 laffer1 Exp $
+
+PROG= lndir
+
+.include <bsd.prog.mk>
More information about the Midnightbsd-cvs
mailing list