On 06/10/2014 05:12 PM, Caleb Cushing wrote:
> my suggestion is that I should be able to write
>
> install -D /path/to/myfile.txt -t /dest/path
The attached patch implements this.
BTW: the Texinfo manual was falsely stating that [g]install
would ignore the -D option when -t was given (instead, it
complained with ENOENT for the target_directory):
`-D'
Create any missing parent directories of DEST, then copy SOURCE to
DEST. This option is ignored if a destination directory is
specified via `--target-directory=DIR'.
Have a nice day,
Berny
>From c24ea15a50fdef0e141cdacd99e49e8fe8fec374 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <[email protected]>
Date: Wed, 11 Jun 2014 00:04:27 +0200
Subject: [PATCH] install: allow options -D and -t to be used together
* src/install.c (install_file_in_file_parents): Factor out the
creation of any parent directories into ...
(mkancesdirs_safe_wd): ... this new function.
(install_file_in_dir): Add the parameter 'mkdir_and_install', and
call the above new function if it evaluates to true.
(main): During parsing of the -t option, move the check whether
the target_directory exists down after the option pparsing loop,
and do not complain about stat(optarg,...) failing if -D was given.
Pass 'mkdir_and_install' to install_file_in_dir().
* doc/coreutils.texi (install invocation): Remove the (false)
restriction that -D would be ignored together with -t.
* src/install/basic-1.sh: Add a test for the now-allowed combination
of the -D and -t options.
* NEWS: Mention the improvement.
---
NEWS | 2 ++
doc/coreutils.texi | 2 --
src/install.c | 49 ++++++++++++++++++++++++++++++++----------------
tests/install/basic-1.sh | 10 ++++++++++
4 files changed, 45 insertions(+), 18 deletions(-)
diff --git a/NEWS b/NEWS
index fa1aab8..2f43da6 100644
--- a/NEWS
+++ b/NEWS
@@ -104,6 +104,8 @@ GNU coreutils NEWS -*- outline -*-
causing name look-up errors. Also look-ups are first done outside the chroot,
in case the look-up within the chroot fails due to library conflicts etc.
+ install now allows the combination of the -D and -t options.
+
numfmt supports zero padding of numbers using the standard printf
syntax of a leading zero, for example --format="%010f".
Also throughput was improved by up to 800% by avoiding redundant processing.
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 243b6d7..bcd2b2e 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -9071,8 +9071,6 @@ Ignored; for compatibility with old Unix versions of @command{install}.
@opindex -D
Create any missing parent directories of @var{dest},
then copy @var{source} to @var{dest}.
-This option is ignored if a destination directory is specified
-via @option{--target-directory=DIR}.
@item -d
@itemx --directory
diff --git a/src/install.c b/src/install.c
index c9bfdae..0b6c44f 100644
--- a/src/install.c
+++ b/src/install.c
@@ -706,8 +706,7 @@ install_file_in_file (const char *from, const char *to,
Return true if successful. */
static bool
-install_file_in_file_parents (char const *from, char *to,
- struct cp_options *x)
+mkancesdirs_safe_wd (char const *from, char *to, struct cp_options *x)
{
bool save_working_directory =
! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to));
@@ -737,8 +736,18 @@ install_file_in_file_parents (char const *from, char *to,
return false;
}
}
+ return status == EXIT_SUCCESS;
+}
+
+/* Copy file FROM onto file TO, creating any missing parent directories of TO.
+ Return true if successful. */
- return (status == EXIT_SUCCESS && install_file_in_file (from, to, x));
+static bool
+install_file_in_file_parents (char const *from, char *to,
+ const struct cp_options *x)
+{
+ return ( mkancesdirs_safe_wd (from, to, (struct cp_options *)x)
+ && install_file_in_file (from, to, x));
}
/* Copy file FROM into directory TO_DIR, keeping its same name,
@@ -747,11 +756,16 @@ install_file_in_file_parents (char const *from, char *to,
static bool
install_file_in_dir (const char *from, const char *to_dir,
- const struct cp_options *x)
+ const struct cp_options *x, bool mkdir_and_install)
{
const char *from_base = last_component (from);
char *to = file_name_concat (to_dir, from_base, NULL);
- bool ret = install_file_in_file (from, to, x);
+ bool ret = true;
+
+ if (mkdir_and_install)
+ ret = mkancesdirs_safe_wd (from, to, (struct cp_options *)x);
+
+ ret = ret && install_file_in_file (from, to, x);
free (to);
return ret;
}
@@ -851,16 +865,6 @@ main (int argc, char **argv)
if (target_directory)
error (EXIT_FAILURE, 0,
_("multiple target directories specified"));
- else
- {
- struct stat st;
- if (stat (optarg, &st) != 0)
- error (EXIT_FAILURE, errno, _("failed to access %s"),
- quote (optarg));
- if (! S_ISDIR (st.st_mode))
- error (EXIT_FAILURE, 0, _("target %s is not a directory"),
- quote (optarg));
- }
target_directory = optarg;
break;
case 'T':
@@ -915,6 +919,18 @@ main (int argc, char **argv)
error (EXIT_FAILURE, 0,
_("target directory not allowed when installing a directory"));
+ if (target_directory)
+ {
+ struct stat st;
+ bool stat_success = stat (target_directory, &st) == 0 ? true : false;
+ if (! mkdir_and_install && ! stat_success)
+ error (EXIT_FAILURE, errno, _("failed to access %s"),
+ quote (target_directory));
+ if (stat_success && ! S_ISDIR (st.st_mode))
+ error (EXIT_FAILURE, 0, _("target %s is not a directory"),
+ quote (target_directory));
+ }
+
if (backup_suffix_string)
simple_backup_suffix = xstrdup (backup_suffix_string);
@@ -1020,7 +1036,8 @@ main (int argc, char **argv)
int i;
dest_info_init (&x);
for (i = 0; i < n_files; i++)
- if (! install_file_in_dir (file[i], target_directory, &x))
+ if (! install_file_in_dir (file[i], target_directory, &x,
+ mkdir_and_install))
exit_status = EXIT_FAILURE;
}
}
diff --git a/tests/install/basic-1.sh b/tests/install/basic-1.sh
index 283426a..5af6a8d 100755
--- a/tests/install/basic-1.sh
+++ b/tests/install/basic-1.sh
@@ -112,4 +112,14 @@ ginstall: creating directory 'sub3/a/b/c'
'file' -> 'sub3/a/b/c/file'
EOF
+# Test -D together with -t (available since coreutils >= 8.23).
+ginstall -t sub4/a/b/c -Dv file >out 2>&1 || fail=1
+compare - out <<\EOF || fail=1
+ginstall: creating directory 'sub4'
+ginstall: creating directory 'sub4/a'
+ginstall: creating directory 'sub4/a/b'
+ginstall: creating directory 'sub4/a/b/c'
+'file' -> 'sub4/a/b/c/file'
+EOF
+
Exit $fail
--
1.8.4.5