coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [coreutils] RFC for adding file creation mode feature into touch uti


From: Eric Blake
Subject: Re: [coreutils] RFC for adding file creation mode feature into touch utility.
Date: Fri, 07 Jan 2011 08:23:45 -0700
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101209 Fedora/3.1.7-0.35.b3pre.fc14 Lightning/1.0b3pre Mnenhy/0.8.3 Thunderbird/3.1.7

On 01/07/2011 02:01 AM, Rakib Mullick wrote:
> Hello list,
> 
> This is a Request For Comment for adding a new feature into touch
> utility. touch is basically an utility to modify a file's timestamps
> and it is also used for file creation vastly. We can create a file by
> just doing 'touch filename'. There are lot of cases where we need to
> change file's permission after creation. To do that we need to
> separately do 'chmod -/+ mode filename'. Now, my proposal is to adding
> mode changing feature to the touch utility, it will help us to create
> a file by just doing 'touch --mode xxx filename'. It will create a
> file with specified mode.
> 
> Hope to get some response.

Hmm - mkdir already supports -m/--mode, so it does sound like making
touch support the same option might be a useful enhancement.  Of course,
if the file exists, the --mode option would be ignored.  And POSIX
requires that if the --mode option is not provided but a file is
created, that the file have mode 0666 as modified by umask.  We can't
use -m, though (POSIX already requires it for mtime).

Oops - that means I found a (slightly-related) existing bug - touch's
-a, -m, and -t have no long-option counterpart, which is a violation of
GNU Coding Standards.

I'm 70:30 for adding this idea, and it's rather simple to do, as well
(would still need doc, NEWS, and test additions).

Note that 'touch -r a b' must still use mode 0666-umask for b, rather
than copying a's permissions, because -r is mandated by POSIX; but
'touch -r a -M + b' is a great way to create b with the same permissions
as a (assuming b didn't exist).

diff --git i/src/touch.c w/src/touch.c
index 49be961..c327f53 100644
--- i/src/touch.c
+++ w/src/touch.c
@@ -28,6 +28,7 @@
 #include "argmatch.h"
 #include "error.h"
 #include "fd-reopen.h"
+#include "modechange.h"
 #include "parse-datetime.h"
 #include "posixtm.h"
 #include "posixver.h"
@@ -86,8 +87,9 @@ static struct option const longopts[] =
   {"time", required_argument, NULL, TIME_OPTION},
   {"no-create", no_argument, NULL, 'c'},
   {"date", required_argument, NULL, 'd'},
-  {"reference", required_argument, NULL, 'r'},
   {"no-dereference", no_argument, NULL, 'h'},
+  {"mode", required_argument, NULL, 'M'},
+  {"reference", required_argument, NULL, 'r'},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -120,7 +122,7 @@ get_reldate (struct timespec *result,
    Return true if successful.  */

 static bool
-touch (const char *file)
+touch (const char *file, mode_t mode)
 {
   bool ok;
   int fd = -1;
@@ -132,11 +134,9 @@ touch (const char *file)
   else if (! (no_create || no_dereference))
     {
       /* Try to open FILE, creating it if necessary.  */
-      int default_permissions =
-        S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
       fd = fd_reopen (STDIN_FILENO, file,
                       O_WRONLY | O_CREAT | O_NONBLOCK | O_NOCTTY,
-                      default_permissions);
+                      mode);

       /* Don't save a copy of errno if it's EISDIR, since that would lead
          touch to give a bogus diagnostic for e.g., `touch /' (assuming
@@ -239,6 +239,7 @@ Mandatory arguments to long options are mandatory
for short options too.\n\
                          file (useful only on systems that can change
the\n\
                          timestamps of a symlink)\n\
   -m                     change only the modification time\n\
+  -M, --mode=MODE        set file mode (as in chmod), not a=rw - umask\n\
 "), stdout);
       fputs (_("\
   -r, --reference=FILE   use this file's times instead of current time\n\
@@ -265,6 +266,8 @@ main (int argc, char **argv)
   bool date_set = false;
   bool ok = true;
   char const *flex_date = NULL;
+  const char *specified_mode = NULL;
+  mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;

   initialize_main (&argc, &argv);
   set_program_name (argv[0]);
@@ -277,7 +280,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:fhmM:r:t:", longopts,
NULL)) != -1)
     {
       switch (c)
         {
@@ -304,6 +307,10 @@ main (int argc, char **argv)
           change_times |= CH_MTIME;
           break;

+        case 'M':
+          specified_mode = optarg;
+          break;
+
         case 'r':
           use_ref = true;
           ref_file = optarg;
@@ -361,6 +368,8 @@ main (int argc, char **argv)
           if (change_times & CH_MTIME)
             get_reldate (&newtime[1], flex_date, &newtime[1]);
         }
+      if (specified_mode)
+        mode = ref_stats.st_mode;
     }
   else
     {
@@ -424,6 +433,17 @@ main (int argc, char **argv)
         newtime[1].tv_nsec = newtime[0].tv_nsec = UTIME_NOW;
     }

+  if (specified_mode)
+    {
+      mode_t umask_value = umask (0);
+      struct mode_change *change = mode_compile (specified_mode);
+      if (!change)
+        error (EXIT_FAILURE, 0, _("invalid mode %s"),
+               quote (specified_mode));
+      mode = mode_adjust (mode, false, umask_value, change, NULL);
+      free (change);
+    }
+
   if (optind == argc)
     {
       error (0, 0, _("missing file operand"));
@@ -431,7 +451,7 @@ main (int argc, char **argv)
     }

   for (; optind < argc; ++optind)
-    ok &= touch (argv[optind]);
+    ok &= touch (argv[optind], mode);

   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
 }


-- 
Eric Blake   address@hidden    +1-801-349-2682
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]