X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmkdir.c;h=5f49395cd0dd5438f1db4ce6bae4692ee2c33ae2;hb=77da73c75432f3c5b4beebae7b0797a1e33160bc;hp=447cafc566fd6f2f807f2b1cb95b9b317a6bb49a;hpb=76b12f000534e588e65a6d8b4a152e9e382d4f85;p=platform%2Fupstream%2Fcoreutils.git diff --git a/src/mkdir.c b/src/mkdir.c index 447cafc..5f49395 100644 --- a/src/mkdir.c +++ b/src/mkdir.c @@ -1,10 +1,10 @@ /* mkdir -- make directories - Copyright (C) 90, 1995-2002, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1990-2013 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + 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 2, or (at your option) - any later version. + 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 @@ -12,8 +12,7 @@ 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* David MacKenzie */ @@ -21,25 +20,24 @@ #include #include #include +#include #include "system.h" -#include "dirname.h" #include "error.h" -#include "lchmod.h" #include "mkdir-p.h" #include "modechange.h" +#include "prog-fprintf.h" #include "quote.h" +#include "savewd.h" -/* The official name of this program (e.g., no `g' prefix). */ +/* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "mkdir" -#define AUTHORS "David MacKenzie" - -/* The name this program was run with. */ -char *program_name; +#define AUTHORS proper_name ("David MacKenzie") static struct option const longopts[] = { + {GETOPT_SELINUX_CONTEXT_OPTION_DECL}, {"mode", required_argument, NULL, 'm'}, {"parents", no_argument, NULL, 'p'}, {"verbose", no_argument, NULL, 'v'}, @@ -52,11 +50,10 @@ void usage (int status) { if (status != EXIT_SUCCESS) - fprintf (stderr, _("Try `%s --help' for more information.\n"), - program_name); + emit_try_help (); else { - printf (_("Usage: %s [OPTION] DIRECTORY...\n"), program_name); + printf (_("Usage: %s [OPTION]... DIRECTORY...\n"), program_name); fputs (_("\ Create the DIRECTORY(ies), if they do not already exist.\n\ \n\ @@ -68,20 +65,32 @@ Mandatory arguments to long options are mandatory for short options too.\n\ -m, --mode=MODE set file mode (as in chmod), not a=rwx - umask\n\ -p, --parents no error if existing, make parent directories as needed\n\ -v, --verbose print a message for each created directory\n\ + -Z, --context=CTX set the SELinux security context of each created\n\ + directory to CTX\n\ "), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); - printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); + emit_ancillary_info (); } exit (status); } -/* Options for announce_mkdir and make_ancestor. */ +/* Options passed to subsidiary functions. */ struct mkdir_options { + /* Function to make an ancestor, or NULL if ancestors should not be + made. */ + int (*make_ancestor_function) (char const *, char const *, void *); + /* Mode for ancestor directory. */ mode_t ancestor_mode; + /* Mode for directory itself. */ + mode_t mode; + + /* File mode bits affected by MODE. */ + mode_t mode_bits; + /* If not null, format to use when reporting newly made directories. */ char const *created_directory_format; }; @@ -92,58 +101,81 @@ announce_mkdir (char const *dir, void *options) { struct mkdir_options const *o = options; if (o->created_directory_format) - error (0, 0, o->created_directory_format, quote (dir)); + prog_fprintf (stdout, o->created_directory_format, quote (dir)); } -/* Make ancestor directory DIR, with options OPTIONS. */ +/* Make ancestor directory DIR, whose last component is COMPONENT, + with options OPTIONS. Assume the working directory is COMPONENT's + parent. Return 0 if successful and the resulting directory is + readable, 1 if successful but the resulting directory is not + readable, -1 (setting errno) otherwise. */ static int -make_ancestor (char const *dir, void *options) +make_ancestor (char const *dir, char const *component, void *options) { struct mkdir_options const *o = options; - int r = mkdir (dir, o->ancestor_mode); + int r = mkdir (component, o->ancestor_mode); if (r == 0) - announce_mkdir (dir, options); + { + r = ! (o->ancestor_mode & S_IRUSR); + announce_mkdir (dir, options); + } return r; } +/* Process a command-line file name. */ +static int +process_dir (char *dir, struct savewd *wd, void *options) +{ + struct mkdir_options const *o = options; + return (make_dir_parents (dir, wd, o->make_ancestor_function, options, + o->mode, announce_mkdir, + o->mode_bits, (uid_t) -1, (gid_t) -1, true) + ? EXIT_SUCCESS + : EXIT_FAILURE); +} + int main (int argc, char **argv) { - mode_t mode = S_IRWXUGO; - mode_t mode_bits = 0; - int (*make_ancestor_function) (char const *, void *) = NULL; const char *specified_mode = NULL; - int exit_status = EXIT_SUCCESS; int optc; + security_context_t scontext = NULL; struct mkdir_options options; + + options.make_ancestor_function = NULL; + options.mode = S_IRWXUGO; + options.mode_bits = 0; options.created_directory_format = NULL; initialize_main (&argc, &argv); - program_name = argv[0]; + set_program_name (argv[0]); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); atexit (close_stdout); - while ((optc = getopt_long (argc, argv, "pm:v", longopts, NULL)) != -1) + while ((optc = getopt_long (argc, argv, "pm:vZ:", longopts, NULL)) != -1) { switch (optc) - { - case 'p': - make_ancestor_function = make_ancestor; - break; - case 'm': - specified_mode = optarg; - break; - case 'v': /* --verbose */ - options.created_directory_format = _("created directory %s"); - break; - case_GETOPT_HELP_CHAR; - case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); - default: - usage (EXIT_FAILURE); - } + { + case 'p': + options.make_ancestor_function = make_ancestor; + break; + case 'm': + specified_mode = optarg; + break; + case 'v': /* --verbose */ + options.created_directory_format = _("created directory %s"); + break; + case 'Z': + scontext = optarg; + break; + case_GETOPT_HELP_CHAR; + case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); + default: + usage (EXIT_FAILURE); + } } if (optind == argc) @@ -152,31 +184,31 @@ main (int argc, char **argv) usage (EXIT_FAILURE); } - if (make_ancestor_function || specified_mode) + if (scontext && setfscreatecon (scontext) < 0) + error (EXIT_FAILURE, errno, + _("failed to set default file creation context to %s"), + quote (scontext)); + + if (options.make_ancestor_function || specified_mode) { mode_t umask_value = umask (0); options.ancestor_mode = (S_IRWXUGO & ~umask_value) | (S_IWUSR | S_IXUSR); if (specified_mode) - { - struct mode_change *change = mode_compile (specified_mode); - if (!change) - error (EXIT_FAILURE, 0, _("invalid mode %s"), - quote (specified_mode)); - mode = mode_adjust (S_IRWXUGO, true, umask_value, change, - &mode_bits); - free (change); - } + { + struct mode_change *change = mode_compile (specified_mode); + if (!change) + error (EXIT_FAILURE, 0, _("invalid mode %s"), + quote (specified_mode)); + options.mode = mode_adjust (S_IRWXUGO, true, umask_value, change, + &options.mode_bits); + free (change); + } else - mode &= ~umask_value; + options.mode = S_IRWXUGO & ~umask_value; } - for (; optind < argc; ++optind) - if (! make_dir_parents (argv[optind], make_ancestor_function, &options, - mode, announce_mkdir, - mode_bits, (uid_t) -1, (gid_t) -1, true)) - exit_status = EXIT_FAILURE; - - exit (exit_status); + exit (savewd_process_files (argc - optind, argv + optind, + process_dir, &options)); }