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);