bin/122271: [patch] usr.bin/xinstall - Add support for -D option (create parent directories before installing file(s))

Ganael Laplanche ganael.laplanche at martymac.com
Sun Mar 30 13:50:01 PDT 2008


>Number:         122271
>Category:       bin
>Synopsis:       [patch] usr.bin/xinstall - Add support for -D option (create parent directories before installing file(s))
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Mar 30 20:50:00 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Ganael Laplanche
>Release:        7.0-STABLE
>Organization:
http://contribs.martymac.com
>Environment:
FreeBSD home.martymac.com 7.0-STABLE FreeBSD 7.0-STABLE #11: Tue Mar 25 14:32:03 CET 2008     root at home.martymac.com:/usr/obj/usr/src/sys/MYKERNEL  amd64
>Description:
This patch enhances install by bringing support for automatically creating target directory's hierarchy before installing files (-D option).

examples :

install -D foo bar/
Will create directory bar/ and install foo inside.

install -D foo bar
Same behaviour as before : file foo is installed as bar

install -D foo bar baz/abc/
or
install -D foo bar baz/abc
Will create target directory baz/abc and install foo and bar inside.

install -d -D foo bar
Same behaviour as before : directories foo and bar are created

This options is inspired from gnu's install and may simplify porter's work.
I have updated documentation (install.1) to make the new option appear.
>How-To-Repeat:

>Fix:


Patch attached with submission follows:

diff -aur xinstall.orig/install.1 xinstall/install.1
--- xinstall.orig/install.1	2008-03-30 20:14:22.000000000 +0200
+++ xinstall/install.1	2008-03-30 22:29:24.000000000 +0200
@@ -40,7 +40,7 @@
 .Nd install binaries
 .Sh SYNOPSIS
 .Nm
-.Op Fl bCcMpSsv
+.Op Fl bCcDMpSsv
 .Op Fl B Ar suffix
 .Op Fl f Ar flags
 .Op Fl g Ar group
@@ -48,7 +48,7 @@
 .Op Fl o Ar owner
 .Ar file1 file2
 .Nm
-.Op Fl bCcMpSsv
+.Op Fl bCcDMpSsv
 .Op Fl B Ar suffix
 .Op Fl f Ar flags
 .Op Fl g Ar group
@@ -112,6 +112,9 @@
 .It Fl d
 Create directories.
 Missing parent directories are created as required.
+.It Fl D
+If necessary, create target's parent directories before
+installing file(s).
 .It Fl f
 Specify the target's file flags; see
 .Xr chflags 1
diff -aur xinstall.orig/xinstall.c xinstall/xinstall.c
--- xinstall.orig/xinstall.c	2008-03-30 20:14:22.000000000 +0200
+++ xinstall/xinstall.c	2008-03-30 22:16:14.000000000 +0200
@@ -82,7 +82,7 @@
 struct group *gp;
 gid_t gid;
 uid_t uid;
-int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy, verbose;
+int dobackup, docompare, doparentdir, dodir, dopreserve, dostrip, nommap, safecopy, verbose;
 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
 const char *suffix = BACKUP_SUFFIX;
 
@@ -92,6 +92,7 @@
 int	create_tempfile(const char *, char *, size_t);
 void	install(const char *, const char *, u_long, u_int);
 void	install_dir(char *);
+void	install_parentdir(char *);
 u_long	numeric_id(const char *, const char *);
 void	strip(const char *);
 int	trymmap(int);
@@ -110,7 +111,7 @@
 
 	iflags = 0;
 	group = owner = NULL;
-	while ((ch = getopt(argc, argv, "B:bCcdf:g:Mm:o:pSsv")) != -1)
+	while ((ch = getopt(argc, argv, "B:bCcDdf:g:Mm:o:pSsv")) != -1)
 		switch((char)ch) {
 		case 'B':
 			suffix = optarg;
@@ -124,6 +125,9 @@
 		case 'c':
 			/* For backwards compatibility. */
 			break;
+		case 'D':
+			doparentdir = 1;
+			break;
 		case 'd':
 			dodir = 1;
 			break;
@@ -211,6 +215,15 @@
 		/* NOTREACHED */
 	}
 
+	if (doparentdir) {
+		if(argc == 2) install_parentdir(argv[argc - 1]);
+		/*
+		 * more than one file to install :
+		 * destination has to be a directory
+		 */
+		else install_dir(argv[argc - 1]);
+	}
+
 	no_target = stat(to_name = argv[argc - 1], &to_sb);
 	if (!no_target && S_ISDIR(to_sb.st_mode)) {
 		for (; *argv != to_name; ++argv)
@@ -219,8 +232,11 @@
 		/* NOTREACHED */
 	}
 
-	/* can't do file1 file2 directory/file */
-	if (argc != 2) {
+	/*
+	 * can do file1 file2 directory/ only if parent
+	 * directories have been created
+	 */
+	if ((argc != 2) && (!doparentdir)) {
 		if (no_target)
 			warnx("target directory `%s' does not exist", 
 			    argv[argc - 1]);
@@ -767,6 +783,24 @@
 }
 
 /*
+ * install_parentdir --
+ *	build directory hierarchy
+ *  ignoring last non-directory part
+ */
+void
+install_parentdir(char *path)
+{
+	char parentpath[MAXPATHLEN];
+	char *p;
+
+	(void)strncpy(parentpath, path, MAXPATHLEN);
+	if ((p = strrchr(parentpath, '/')) != NULL) {
+		*p = '\0';
+		install_dir(parentpath);
+	}
+}
+
+/*
  * usage --
  *	print a usage message and die
  */
@@ -774,9 +808,9 @@
 usage()
 {
 	(void)fprintf(stderr,
-"usage: install [-bCcpSsv] [-B suffix] [-f flags] [-g group] [-m mode]\n"
+"usage: install [-bCcDpSsv] [-B suffix] [-f flags] [-g group] [-m mode]\n"
 "               [-o owner] file1 file2\n"
-"       install [-bCcpSsv] [-B suffix] [-f flags] [-g group] [-m mode]\n"
+"       install [-bCcDpSsv] [-B suffix] [-f flags] [-g group] [-m mode]\n"
 "               [-o owner] file1 ... fileN directory\n"
 "       install -d [-v] [-g group] [-m mode] [-o owner] directory ...\n");
 	exit(EX_USAGE);


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list