GNU bug report logs - #55937
[PATCH] touch: create parent directories if needed

Previous Next

Package: coreutils;

Reported by: Alan Rosenthal <alan.rosenthal <at> gmail.com>

Date: Mon, 13 Jun 2022 04:33:01 UTC

Severity: normal

Tags: patch

Full log


View this message in rfc822 format

From: Alan Rosenthal <alan.rosenthal <at> gmail.com>
To: 55937 <at> debbugs.gnu.org
Subject: bug#55937: [PATCH] touch: create parent directories if needed
Date: Sun, 12 Jun 2022 22:05:40 -0400
[Message part 1 (text/plain, inline)]
`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
[Message part 2 (text/html, inline)]

This bug report was last modified 3 years and 8 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.