logo

utils-std

Collection of commonly available Unix tools
commit: ec528af528237b2aa13ccaf6dbaf24e6caff7524
parent 4468dddb752819e9498dfd99c6b23193d0674c3d
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Mon, 13 May 2024 02:02:45 +0200

cmd/install: Add support for -D option

Diffstat:

Mcmd/install.114+++++++++++++-
Mcmd/install.c26++++++++++++++++++++++++--
Mtest-cmd/install.t20++++++++++++++++++++
3 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/cmd/install.1 b/cmd/install.1 @@ -9,7 +9,7 @@ .Nd install binairies .Sh SYNOPSIS .Nm -.Op Fl cp +.Op Fl cDp .Op Fl g Ar group .Op Fl m Ar mode .Op Fl o Ar owner @@ -44,6 +44,18 @@ is specified. Copy the file, default behavior in all modern implementations. .It Fl d Create directories, including their parents. +.It Fl D +Create parent directories for +.Ar destination . +.br +Note that this option isn't portable, as +.Fx +and +.Nx +implementation of +.Nm +takes an argument like so: +.Fl D Ar destdir .It Fl g Ar group Sets group ownership. .It Fl m Ar mode diff --git a/cmd/install.c b/cmd/install.c @@ -14,6 +14,7 @@ #include <assert.h> #include <errno.h> #include <fcntl.h> // linkat, AT_SYMLINK_FOLLOW +#include <libgen.h> // dirname #include <limits.h> // PATH_MAX #include <stdbool.h> #include <stdio.h> // fprintf @@ -186,7 +187,7 @@ static void usage() { fprintf(stderr, "\ -Usage: install [-cp] [-g group] [-m mode] [-o owner] source... destination\n\ +Usage: install [-cDp] [-g group] [-m mode] [-o owner] source... destination\n\ install -d [-c] [-g group] [-m mode] [-o owner] directory...\n\ "); } @@ -195,18 +196,22 @@ int main(int argc, char *argv[]) { const char *errstr = NULL; + bool create_parents = false; mkdir_parents_filemask = umask(0); umask(mkdir_parents_filemask); int c = -1; - while((c = getopt(argc, argv, ":cdpg:m:o:")) != -1) + while((c = getopt(argc, argv, ":cDdpg:m:o:")) != -1) { switch(c) { case 'c': // ignore, modern default behavior break; + case 'D': + create_parents = true; + break; case 'd': create_directories = true; break; @@ -277,6 +282,23 @@ main(int argc, char *argv[]) char *dest = argv[argc - 1]; bool multi_src = argc > 2; + if(create_parents) + { + char *destdir = dest; + // Same as in mkdir_parents + mode_t parent_mode = (S_IWUSR | S_IXUSR | ~mkdir_parents_filemask) & 0777; + + if(!multi_src) + { + char path_dup[PATH_MAX] = ""; + strncpy(path_dup, dest, PATH_MAX); + + destdir = dirname(path_dup); + } + + if(mkdir_parents(destdir, parent_mode) != 0) return 1; + } + for(int i = 0; i < argc - 1; i++) { char *src = argv[i]; diff --git a/test-cmd/install.t b/test-cmd/install.t @@ -49,6 +49,26 @@ install -d chmod: Permissions already set to 00755/drwxr-xr-x for 'dest.d' $ rm -fr dest.d +install -D, single src + $ test ! -e gramps + $ touch FooD + $ install -D FooD gramps/parent/child + $ test -d gramps/parent + $ test -f gramps/parent/child + $ test -e FooD + $ rm -r FooD gramps + +install -D, multi src + $ test ! -e gran + $ touch sis bro + $ install -D sis bro gran/dad + $ test -f sis + $ test -f bro + $ test -d gran/dad + $ test -f gran/dad/sis + $ test -f gran/dad/bro + $ rm -r sis bro gran + No files should be left $ find . .