[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