(root)/
coreutils-9.4/
src/
mkfifo.c
       1  /* mkfifo -- make fifo's (named pipes)
       2     Copyright (C) 1990-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* David MacKenzie <djm@ai.mit.edu>  */
      18  
      19  #include <config.h>
      20  #include <stdio.h>
      21  #include <getopt.h>
      22  #include <sys/types.h>
      23  #include <selinux/label.h>
      24  
      25  #include "system.h"
      26  #include "modechange.h"
      27  #include "quote.h"
      28  #include "selinux.h"
      29  #include "smack.h"
      30  
      31  /* The official name of this program (e.g., no 'g' prefix).  */
      32  #define PROGRAM_NAME "mkfifo"
      33  
      34  #define AUTHORS proper_name ("David MacKenzie")
      35  
      36  static struct option const longopts[] =
      37  {
      38    {GETOPT_SELINUX_CONTEXT_OPTION_DECL},
      39    {"mode", required_argument, nullptr, 'm'},
      40    {GETOPT_HELP_OPTION_DECL},
      41    {GETOPT_VERSION_OPTION_DECL},
      42    {nullptr, 0, nullptr, 0}
      43  };
      44  
      45  void
      46  usage (int status)
      47  {
      48    if (status != EXIT_SUCCESS)
      49      emit_try_help ();
      50    else
      51      {
      52        printf (_("Usage: %s [OPTION]... NAME...\n"), program_name);
      53        fputs (_("\
      54  Create named pipes (FIFOs) with the given NAMEs.\n\
      55  "), stdout);
      56  
      57        emit_mandatory_arg_note ();
      58  
      59        fputs (_("\
      60    -m, --mode=MODE    set file permission bits to MODE, not a=rw - umask\n\
      61  "), stdout);
      62        fputs (_("\
      63    -Z                   set the SELinux security context to default type\n\
      64        --context[=CTX]  like -Z, or if CTX is specified then set the SELinux\n\
      65                           or SMACK security context to CTX\n\
      66  "), stdout);
      67        fputs (HELP_OPTION_DESCRIPTION, stdout);
      68        fputs (VERSION_OPTION_DESCRIPTION, stdout);
      69        emit_ancillary_info (PROGRAM_NAME);
      70      }
      71    exit (status);
      72  }
      73  
      74  int
      75  main (int argc, char **argv)
      76  {
      77    mode_t newmode;
      78    char const *specified_mode = nullptr;
      79    int exit_status = EXIT_SUCCESS;
      80    int optc;
      81    char const *scontext = nullptr;
      82    struct selabel_handle *set_security_context = nullptr;
      83  
      84    initialize_main (&argc, &argv);
      85    set_program_name (argv[0]);
      86    setlocale (LC_ALL, "");
      87    bindtextdomain (PACKAGE, LOCALEDIR);
      88    textdomain (PACKAGE);
      89  
      90    atexit (close_stdout);
      91  
      92    while ((optc = getopt_long (argc, argv, "m:Z", longopts, nullptr)) != -1)
      93      {
      94        switch (optc)
      95          {
      96          case 'm':
      97            specified_mode = optarg;
      98            break;
      99          case 'Z':
     100            if (is_smack_enabled ())
     101              {
     102                /* We don't yet support -Z to restore context with SMACK.  */
     103                scontext = optarg;
     104              }
     105            else if (is_selinux_enabled () > 0)
     106              {
     107                if (optarg)
     108                  scontext = optarg;
     109                else
     110                  {
     111                    set_security_context = selabel_open (SELABEL_CTX_FILE,
     112                                                         nullptr, 0);
     113                    if (! set_security_context)
     114                      error (0, errno, _("warning: ignoring --context"));
     115                  }
     116              }
     117            else if (optarg)
     118              {
     119                error (0, 0,
     120                       _("warning: ignoring --context; "
     121                         "it requires an SELinux/SMACK-enabled kernel"));
     122              }
     123            break;
     124          case_GETOPT_HELP_CHAR;
     125          case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
     126          default:
     127            usage (EXIT_FAILURE);
     128          }
     129      }
     130  
     131    if (optind == argc)
     132      {
     133        error (0, 0, _("missing operand"));
     134        usage (EXIT_FAILURE);
     135      }
     136  
     137    if (scontext)
     138      {
     139        int ret = 0;
     140        if (is_smack_enabled ())
     141          ret = smack_set_label_for_self (scontext);
     142        else
     143          ret = setfscreatecon (scontext);
     144  
     145        if (ret < 0)
     146          error (EXIT_FAILURE, errno,
     147                 _("failed to set default file creation context to %s"),
     148                 quote (scontext));
     149      }
     150  
     151    newmode = MODE_RW_UGO;
     152    if (specified_mode)
     153      {
     154        mode_t umask_value;
     155        struct mode_change *change = mode_compile (specified_mode);
     156        if (!change)
     157          error (EXIT_FAILURE, 0, _("invalid mode"));
     158        umask_value = umask (0);
     159        umask (umask_value);
     160        newmode = mode_adjust (newmode, false, umask_value, change, nullptr);
     161        free (change);
     162        if (newmode & ~S_IRWXUGO)
     163          error (EXIT_FAILURE, 0,
     164                 _("mode must specify only file permission bits"));
     165      }
     166  
     167    for (; optind < argc; ++optind)
     168      {
     169        if (set_security_context)
     170          defaultcon (set_security_context, argv[optind], S_IFIFO);
     171        if (mkfifo (argv[optind], newmode) != 0)
     172          {
     173            error (0, errno, _("cannot create fifo %s"), quoteaf (argv[optind]));
     174            exit_status = EXIT_FAILURE;
     175          }
     176        else if (specified_mode && lchmod (argv[optind], newmode) != 0)
     177          {
     178            error (0, errno, _("cannot set permissions of %s"),
     179                   quoteaf (argv[optind]));
     180            exit_status = EXIT_FAILURE;
     181          }
     182      }
     183  
     184    return exit_status;
     185  }