[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] env: add umask support
From: |
user |
Subject: |
[PATCH] env: add umask support |
Date: |
Sat, 26 Oct 2019 00:00:00 +0000 |
* src/env.c: add -M/--umask parameter.
* doc/coreutils.texi: add -M/--umask documentation.
* tests/env/umask.sh: add -M/--umask tests.
---
doc/coreutils.texi | 16 ++++++++++++++++
src/env.c | 42 +++++++++++++++++++++++++++++++++++++++++-
tests/env/umask.sh | 37 +++++++++++++++++++++++++++++++++++++
3 files changed, 94 insertions(+), 1 deletion(-)
create mode 100644 tests/env/umask.sh
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index b552cc105..9e2c0f4b0 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -17243,6 +17243,22 @@ chroot /chroot env --chdir=/srv true
env --chdir=/build FOO=bar timeout 5 true
@end example
+@item -M @var{mask}
+@itemx --umask=@var{mask}
+@opindex -M
+@opindex --umask
+Set the umask used when creating new files or directories to @var{mask}
+before invoking @var{command}. This differs from the shell built-in
+@command{umask} in that it starts @var{command} as a subprocess rather than
+altering the shell's own umask; this allows it to be chained with other
+commands that run commands in a different context. For example:
+
+@example
+# Run 'touch' with 0777 as its umask, FOO=bar in its
+# environment, and a time limit of five seconds.
+env --umask=0777 FOO=bar timeout 5 touch a-file
+@end example
+
@item --default-signal[=@var{sig}]
Unblock and reset signal @var{sig} to its default signal handler.
Without @var{sig} all known signals are unblocked and reset to their defaults.
diff --git a/src/env.c b/src/env.c
index c8161356c..b3d6c01bc 100644
--- a/src/env.c
+++ b/src/env.c
@@ -18,7 +18,9 @@
#include <config.h>
#include <stdio.h>
+#include <stdlib.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <getopt.h>
#include <c-ctype.h>
#include <signal.h>
@@ -73,7 +75,7 @@ static bool sig_mask_changed;
/* Whether to list non default handling. */
static bool report_signal_handling;
-static char const shortopts[] = "+C:iS:u:v0 \t";
+static char const shortopts[] = "+C:iS:M:u:v0 \t";
/* For long options that have no equivalent short option, use a
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
@@ -89,6 +91,7 @@ static struct option const longopts[] =
{
{"ignore-environment", no_argument, NULL, 'i'},
{"null", no_argument, NULL, '0'},
+ {"umask", required_argument, NULL, 'M'},
{"unset", required_argument, NULL, 'u'},
{"chdir", required_argument, NULL, 'C'},
{"default-signal", optional_argument, NULL, DEFAULT_SIGNAL_OPTION},
@@ -129,6 +132,9 @@ Set each NAME to VALUE in the environment and run
COMMAND.\n\
fputs (_("\
-S, --split-string=S process and split S into separate arguments;\n\
used to pass multiple arguments on shebang lines\n\
+"), stdout);
+ fputs (_("\
+ -M, --umask=MASK set MASK as umask\n\
"), stdout);
fputs (_("\
--block-signal[=SIG] block delivery of SIG signal(s) to COMMAND\n\
@@ -622,6 +628,23 @@ parse_signal_action_params (const char* optarg, bool
set_default)
free (optarg_writable);
}
+static mode_t
+parse_umask_param (char const * optarg)
+{
+ char * end = NULL;
+
+ errno = 0;
+ long int res = strtol (optarg, &end, 8);
+
+ if (errno || *end)
+ die (EXIT_CANCELED, errno, _("unable to parse umask: %s"), optarg);
+
+ if (res > 07777 || res < 0)
+ die (EXIT_CANCELED, 0, _("invalid umask: %s"), optarg);
+
+ return (mode_t)res;
+}
+
static void
reset_signal_handlers (void)
{
@@ -801,6 +824,7 @@ main (int argc, char **argv)
bool ignore_environment = false;
bool opt_nul_terminate_output = false;
char const *newdir = NULL;
+ mode_t program_umask = -1;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@@ -820,6 +844,9 @@ main (int argc, char **argv)
case 'i':
ignore_environment = true;
break;
+ case 'M':
+ program_umask = parse_umask_param (optarg);
+ break;
case 'u':
append_unset_var (optarg);
break;
@@ -902,6 +929,12 @@ main (int argc, char **argv)
usage (EXIT_CANCELED);
}
+ if (program_umask >= 0 && ! program_specified)
+ {
+ error (0, 0, _("must specify command with --umask (-M)"));
+ usage (EXIT_CANCELED);
+ }
+
if (newdir && ! program_specified)
{
error (0, 0, _("must specify command with --chdir (-C)"));
@@ -924,6 +957,13 @@ main (int argc, char **argv)
if (report_signal_handling)
list_signal_handling ();
+ if (program_umask)
+ {
+ devmsg ("umask: %o\n", program_umask);
+
+ umask (program_umask);
+ }
+
if (newdir)
{
devmsg ("chdir: %s\n", quoteaf (newdir));
diff --git a/tests/env/umask.sh b/tests/env/umask.sh
new file mode 100644
index 000000000..b2e48fff2
--- /dev/null
+++ b/tests/env/umask.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Test env's -M/--umask option.
+
+# Copyright (C) 2019 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ env
+
+# test getopt setup
+env -M 0777 true || fail=1
+env --umask 0777 true || fail=2
+
+# remove read permission
+env -M 0777 touch out || fail=3
+test -r out && fail=4
+
+# test param handling
+env -M 0777 && fail=5
+env -M a touch out && fail=6
+env -M 9 touch out && fail=7
+env -M 17777 touch out && fail=8
+env -M -1 touch out && fail=9
+
+Exit $fail
--
a
- [PATCH] env: add umask support,
user <=