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:
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 .
.