[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#55937: [PATCH] touch: create parent directories if needed
From: |
Alan Rosenthal |
Subject: |
bug#55937: [PATCH] touch: create parent directories if needed |
Date: |
Tue, 14 Jun 2022 20:20:40 -0400 |
`touch -p a/b/c/d/e` will now be the same as running:
`mkdir -p a/b/c/d && touch a/b/c/d/e`.
Added an option -p/--create-dirs to create any required directories.
Default behavior remains the same.
---
src/touch.c | 40 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/src/touch.c b/src/touch.c
index 21c247d0b..543f92b41 100644
--- a/src/touch.c
+++ b/src/touch.c
@@ -28,10 +28,12 @@
#include "die.h"
#include "error.h"
#include "fd-reopen.h"
+#include "mkancesdirs.h"
#include "parse-datetime.h"
#include "posixtm.h"
#include "posixver.h"
#include "quote.h"
+#include "savewd.h"
#include "stat-time.h"
#include "utimens.h"
@@ -55,6 +57,9 @@ static int change_times;
/* (-c) If true, don't create if not already there. */
static bool no_create;
+/* (-p) If true, create directories if not already there. */
+static bool create_dirs;
+
/* (-r) If true, use times from a reference file. */
static bool use_ref;
@@ -88,6 +93,7 @@ static struct option const longopts[] =
{"date", required_argument, NULL, 'd'},
{"reference", required_argument, NULL, 'r'},
{"no-dereference", no_argument, NULL, 'h'},
+ {"create-dirs", no_argument, NULL, 'p'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
@@ -116,6 +122,14 @@ get_reldate (struct timespec *result,
die (EXIT_FAILURE, 0, _("invalid date format %s"), quote (flex_date));
}
+/* Create directory, called by mkancesdirs(). */
+
+static int
+make_dir(char const * file, char const * component, void * arg)
+{
+ return mkdir(component, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+}
+
/* Update the time of file FILE according to the options given.
Return true if successful. */
@@ -130,6 +144,25 @@ touch (char const *file)
fd = STDOUT_FILENO;
else if (! (no_create || no_dereference))
{
+ if (create_dirs)
+ {
+ struct savewd wd;
+ savewd_init(&wd);
+ ptrdiff_t ret = mkancesdirs((char*) file, &wd, make_dir, NULL);
+ if (ret == -1)
+ {
+ error (0, open_errno, _("cannot mkdir %s"), quoteaf (file));
+ return false;
+ }
+ int r = savewd_restore(&wd, 0);
+ if (r < 0)
+ {
+ error (0, open_errno, _("cannot mkdir %s"), quoteaf (file));
+ return false;
+ }
+ savewd_finish(&wd);
+ }
+
/* Try to open FILE, creating it if necessary. */
fd = fd_reopen (STDIN_FILENO, file,
O_WRONLY | O_CREAT | O_NONBLOCK | O_NOCTTY,
MODE_RW_UGO);
@@ -240,6 +273,7 @@ change the times of the file associated with standard
output.\n\
-m change only the modification time\n\
"), stdout);
fputs (_("\
+ -p, --create-dirs create any required parent directories\n\
-r, --reference=FILE use this file's times instead of current time\n\
-t STAMP use [[CC]YY]MMDDhhmm[.ss] instead of current
time\n\
--time=WORD change the specified time:\n\
@@ -276,7 +310,7 @@ main (int argc, char **argv)
change_times = 0;
no_create = use_ref = false;
- while ((c = getopt_long (argc, argv, "acd:fhmr:t:", longopts, NULL)) !=
-1)
+ while ((c = getopt_long (argc, argv, "acd:fhmpr:t:", longopts, NULL)) !=
-1)
{
switch (c)
{
@@ -303,6 +337,10 @@ main (int argc, char **argv)
change_times |= CH_MTIME;
break;
+ case 'p':
+ create_dirs = true;
+ break;
+
case 'r':
use_ref = true;
ref_file = optarg;
--
2.20.1
On Mon, Jun 13, 2022 at 7:52 AM Alan Rosenthal <alan.rosenthal@gmail.com>
wrote:
> `touch a/b/c/d/e` will now be the same as running `mkdir -p a/b/c/d &&
> touch a/b/c/d/e`.
> Added an option --no-create-dirs to not create any directories.
> ---
> src/touch.c | 40 +++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 39 insertions(+), 1 deletion(-)
>
> diff --git a/src/touch.c b/src/touch.c
> index 21c247d0b..557530f79 100644
> --- a/src/touch.c
> +++ b/src/touch.c
> @@ -28,10 +28,12 @@
> #include "die.h"
> #include "error.h"
> #include "fd-reopen.h"
> +#include "mkancesdirs.h"
> #include "parse-datetime.h"
> #include "posixtm.h"
> #include "posixver.h"
> #include "quote.h"
> +#include "savewd.h"
> #include "stat-time.h"
> #include "utimens.h"
>
> @@ -55,6 +57,9 @@ static int change_times;
> /* (-c) If true, don't create if not already there. */
> static bool no_create;
>
> +/* (-c) If true, don't create directories if not already there. */
> +static bool no_create_dirs;
> +
> /* (-r) If true, use times from a reference file. */
> static bool use_ref;
>
> @@ -88,6 +93,7 @@ static struct option const longopts[] =
> {"date", required_argument, NULL, 'd'},
> {"reference", required_argument, NULL, 'r'},
> {"no-dereference", no_argument, NULL, 'h'},
> + {"no-create-dirs", no_argument, NULL, 'i'},
> {GETOPT_HELP_OPTION_DECL},
> {GETOPT_VERSION_OPTION_DECL},
> {NULL, 0, NULL, 0}
> @@ -116,6 +122,14 @@ get_reldate (struct timespec *result,
> die (EXIT_FAILURE, 0, _("invalid date format %s"), quote (flex_date));
> }
>
> +/* Create directory, called by mkancesdirs(). */
> +
> +static int
> +make_dir(char const * file, char const * component, void * arg)
> +{
> + return mkdir(component, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH |
> S_IXOTH);
> +}
> +
> /* Update the time of file FILE according to the options given.
> Return true if successful. */
>
> @@ -130,6 +144,25 @@ touch (char const *file)
> fd = STDOUT_FILENO;
> else if (! (no_create || no_dereference))
> {
> + if (! no_create_dirs)
> + {
> + struct savewd wd;
> + savewd_init(&wd);
> + ptrdiff_t ret = mkancesdirs((char*) file, &wd, make_dir, NULL);
> + if (ret == -1)
> + {
> + error (0, open_errno, _("cannot mkdir %s"), quoteaf (file));
> + return false;
> + }
> + int r = savewd_restore(&wd, 0);
> + if (r < 0)
> + {
> + error (0, open_errno, _("cannot mkdir %s"), quoteaf (file));
> + return false;
> + }
> + savewd_finish(&wd);
> + }
> +
> /* Try to open FILE, creating it if necessary. */
> fd = fd_reopen (STDIN_FILENO, file,
> O_WRONLY | O_CREAT | O_NONBLOCK | O_NOCTTY,
> MODE_RW_UGO);
> @@ -234,6 +267,7 @@ change the times of the file associated with standard
> output.\n\
> -f (ignored)\n\
> "), stdout);
> fputs (_("\
> + -i, --no-create-dirs do not create any required parent directories\n\
> -h, --no-dereference affect each symbolic link instead of any
> referenced\n\
> file (useful only on systems that can change
> the\n\
> timestamps of a symlink)\n\
> @@ -276,7 +310,7 @@ main (int argc, char **argv)
> change_times = 0;
> no_create = use_ref = false;
>
> - while ((c = getopt_long (argc, argv, "acd:fhmr:t:", longopts, NULL)) !=
> -1)
> + while ((c = getopt_long (argc, argv, "acd:fhimr:t:", longopts, NULL))
> != -1)
> {
> switch (c)
> {
> @@ -299,6 +333,10 @@ main (int argc, char **argv)
> no_dereference = true;
> break;
>
> + case 'i':
> + no_create_dirs = true;
> + break;
> +
> case 'm':
> change_times |= CH_MTIME;
> break;
> --
> 2.20.1
>
> On Sun, Jun 12, 2022 at 10:05 PM Alan Rosenthal <alan.rosenthal@gmail.com>
> wrote:
>
>> `touch a/b/c/d/e` will now be the same as running `mkdir -p a/b/c/d &&
>> touch a/b/c/d/e`.
>> Added an option --no-create-dirs to not create any directories.
>> ---
>> src/touch.c | 39 ++++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 38 insertions(+), 1 deletion(-)
>>
>> diff --git a/src/touch.c b/src/touch.c
>> index 21c247d0b..9034e8797 100644
>> --- a/src/touch.c
>> +++ b/src/touch.c
>> @@ -28,10 +28,12 @@
>> #include "die.h"
>> #include "error.h"
>> #include "fd-reopen.h"
>> +#include "mkancesdirs.h"
>> #include "parse-datetime.h"
>> #include "posixtm.h"
>> #include "posixver.h"
>> #include "quote.h"
>> +#include "savewd.h"
>> #include "stat-time.h"
>> #include "utimens.h"
>>
>> @@ -55,6 +57,9 @@ static int change_times;
>> /* (-c) If true, don't create if not already there. */
>> static bool no_create;
>>
>> +/* (-c) If true, don't create directories if not already there. */
>> +static bool no_create_dirs;
>> +
>> /* (-r) If true, use times from a reference file. */
>> static bool use_ref;
>>
>> @@ -88,6 +93,7 @@ static struct option const longopts[] =
>> {"date", required_argument, NULL, 'd'},
>> {"reference", required_argument, NULL, 'r'},
>> {"no-dereference", no_argument, NULL, 'h'},
>> + {"no_create_dirs", no_argument, NULL, 'i'},
>> {GETOPT_HELP_OPTION_DECL},
>> {GETOPT_VERSION_OPTION_DECL},
>> {NULL, 0, NULL, 0}
>> @@ -116,6 +122,14 @@ get_reldate (struct timespec *result,
>> die (EXIT_FAILURE, 0, _("invalid date format %s"), quote
>> (flex_date));
>> }
>>
>> +/* Create directory, called by mkancesdirs(). */
>> +
>> +static int
>> +make_dir(char const * file, char const * component, void * arg)
>> +{
>> + return mkdir(component, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH |
>> S_IXOTH);
>> +}
>> +
>> /* Update the time of file FILE according to the options given.
>> Return true if successful. */
>>
>> @@ -130,6 +144,25 @@ touch (char const *file)
>> fd = STDOUT_FILENO;
>> else if (! (no_create || no_dereference))
>> {
>> + if (! no_create_dirs)
>> + {
>> + struct savewd wd;
>> + savewd_init(&wd);
>> + ptrdiff_t ret = mkancesdirs((char*) file, &wd, make_dir, NULL);
>> + if (ret == -1)
>> + {
>> + error (0, open_errno, _("cannot mkdir %s"), quoteaf
>> (file));
>> + return false;
>> + }
>> + int r = savewd_restore(&wd, 0);
>> + if (r < 0)
>> + {
>> + error (0, open_errno, _("cannot mkdir %s"), quoteaf
>> (file));
>> + return false;
>> + }
>> + savewd_finish(&wd);
>> + }
>> +
>> /* Try to open FILE, creating it if necessary. */
>> fd = fd_reopen (STDIN_FILENO, file,
>> O_WRONLY | O_CREAT | O_NONBLOCK | O_NOCTTY,
>> MODE_RW_UGO);
>> @@ -276,7 +309,7 @@ main (int argc, char **argv)
>> change_times = 0;
>> no_create = use_ref = false;
>>
>> - while ((c = getopt_long (argc, argv, "acd:fhmr:t:", longopts, NULL))
>> != -1)
>> + while ((c = getopt_long (argc, argv, "acd:fhimr:t:", longopts, NULL))
>> != -1)
>> {
>> switch (c)
>> {
>> @@ -299,6 +332,10 @@ main (int argc, char **argv)
>> no_dereference = true;
>> break;
>>
>> + case 'i':
>> + no_create_dirs = true;
>> + break;
>> +
>> case 'm':
>> change_times |= CH_MTIME;
>> break;
>> --
>> 2.20.1
>>
>>