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 ebl...@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org
signature.asc
Description: OpenPGP digital signature