LCOV - code coverage report
Current view: top level - binfmt - binfmt.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 20 101 19.8 %
Date: 2019-08-23 13:36:53 Functions: 4 7 57.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 7 92 7.6 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <getopt.h>
       5                 :            : #include <limits.h>
       6                 :            : #include <stdbool.h>
       7                 :            : #include <stdio.h>
       8                 :            : #include <stdlib.h>
       9                 :            : #include <string.h>
      10                 :            : #include <sys/stat.h>
      11                 :            : #include <sys/types.h>
      12                 :            : 
      13                 :            : #include "alloc-util.h"
      14                 :            : #include "conf-files.h"
      15                 :            : #include "def.h"
      16                 :            : #include "fd-util.h"
      17                 :            : #include "fileio.h"
      18                 :            : #include "log.h"
      19                 :            : #include "main-func.h"
      20                 :            : #include "pager.h"
      21                 :            : #include "path-util.h"
      22                 :            : #include "pretty-print.h"
      23                 :            : #include "string-util.h"
      24                 :            : #include "strv.h"
      25                 :            : 
      26                 :            : static bool arg_cat_config = false;
      27                 :            : static PagerFlags arg_pager_flags = 0;
      28                 :            : 
      29                 :          0 : static int delete_rule(const char *rule) {
      30                 :          0 :         _cleanup_free_ char *x = NULL, *fn = NULL;
      31                 :            :         char *e;
      32                 :            : 
      33         [ #  # ]:          0 :         assert(rule);
      34         [ #  # ]:          0 :         assert(rule[0]);
      35                 :            : 
      36                 :          0 :         x = strdup(rule);
      37         [ #  # ]:          0 :         if (!x)
      38                 :          0 :                 return log_oom();
      39                 :            : 
      40                 :          0 :         e = strchrnul(x+1, x[0]);
      41                 :          0 :         *e = 0;
      42                 :            : 
      43         [ #  # ]:          0 :         if (!filename_is_valid(x + 1))
      44         [ #  # ]:          0 :                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
      45                 :            :                                        "Rule file name '%s' is not valid, refusing.", x + 1);
      46                 :            : 
      47                 :          0 :         fn = path_join("/proc/sys/fs/binfmt_misc", x+1);
      48         [ #  # ]:          0 :         if (!fn)
      49                 :          0 :                 return log_oom();
      50                 :            : 
      51                 :          0 :         return write_string_file(fn, "-1", WRITE_STRING_FILE_DISABLE_BUFFER);
      52                 :            : }
      53                 :            : 
      54                 :          0 : static int apply_rule(const char *rule) {
      55                 :            :         int r;
      56                 :            : 
      57                 :          0 :         (void) delete_rule(rule);
      58                 :            : 
      59                 :          0 :         r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, WRITE_STRING_FILE_DISABLE_BUFFER);
      60         [ #  # ]:          0 :         if (r < 0)
      61         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to add binary format: %m");
      62                 :            : 
      63                 :          0 :         return 0;
      64                 :            : }
      65                 :            : 
      66                 :          0 : static int apply_file(const char *path, bool ignore_enoent) {
      67                 :          0 :         _cleanup_fclose_ FILE *f = NULL;
      68                 :            :         int r;
      69                 :            : 
      70         [ #  # ]:          0 :         assert(path);
      71                 :            : 
      72                 :          0 :         r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f);
      73         [ #  # ]:          0 :         if (r < 0) {
      74   [ #  #  #  # ]:          0 :                 if (ignore_enoent && r == -ENOENT)
      75                 :          0 :                         return 0;
      76                 :            : 
      77         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to open file '%s': %m", path);
      78                 :            :         }
      79                 :            : 
      80         [ #  # ]:          0 :         log_debug("apply: %s", path);
      81                 :          0 :         for (;;) {
      82   [ #  #  #  # ]:          0 :                 _cleanup_free_ char *line = NULL;
      83                 :            :                 char *p;
      84                 :            :                 int k;
      85                 :            : 
      86                 :          0 :                 k = read_line(f, LONG_LINE_MAX, &line);
      87         [ #  # ]:          0 :                 if (k < 0)
      88         [ #  # ]:          0 :                         return log_error_errno(k, "Failed to read file '%s': %m", path);
      89         [ #  # ]:          0 :                 if (k == 0)
      90                 :          0 :                         break;
      91                 :            : 
      92                 :          0 :                 p = strstrip(line);
      93         [ #  # ]:          0 :                 if (isempty(p))
      94                 :          0 :                         continue;
      95         [ #  # ]:          0 :                 if (strchr(COMMENTS, p[0]))
      96                 :          0 :                         continue;
      97                 :            : 
      98                 :          0 :                 k = apply_rule(p);
      99   [ #  #  #  # ]:          0 :                 if (k < 0 && r == 0)
     100                 :          0 :                         r = k;
     101                 :            :         }
     102                 :            : 
     103                 :          0 :         return r;
     104                 :            : }
     105                 :            : 
     106                 :         12 : static int help(void) {
     107                 :         12 :         _cleanup_free_ char *link = NULL;
     108                 :            :         int r;
     109                 :            : 
     110                 :         12 :         r = terminal_urlify_man("systemd-binfmt.service", "8", &link);
     111         [ -  + ]:         12 :         if (r < 0)
     112                 :          0 :                 return log_oom();
     113                 :            : 
     114                 :         12 :         printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
     115                 :            :                "Registers binary formats with the kernel.\n\n"
     116                 :            :                "  -h --help             Show this help\n"
     117                 :            :                "     --version          Show package version\n"
     118                 :            :                "     --cat-config       Show configuration files\n"
     119                 :            :                "     --no-pager         Do not pipe output into a pager\n"
     120                 :            :                "\nSee the %s for details.\n"
     121                 :            :                , program_invocation_short_name
     122                 :            :                , link
     123                 :            :         );
     124                 :            : 
     125                 :         12 :         return 0;
     126                 :            : }
     127                 :            : 
     128                 :         16 : static int parse_argv(int argc, char *argv[]) {
     129                 :            :         enum {
     130                 :            :                 ARG_VERSION = 0x100,
     131                 :            :                 ARG_CAT_CONFIG,
     132                 :            :                 ARG_NO_PAGER,
     133                 :            :         };
     134                 :            : 
     135                 :            :         static const struct option options[] = {
     136                 :            :                 { "help",       no_argument, NULL, 'h'            },
     137                 :            :                 { "version",    no_argument, NULL, ARG_VERSION    },
     138                 :            :                 { "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
     139                 :            :                 { "no-pager",   no_argument, NULL, ARG_NO_PAGER   },
     140                 :            :                 {}
     141                 :            :         };
     142                 :            : 
     143                 :            :         int c;
     144                 :            : 
     145         [ -  + ]:         16 :         assert(argc >= 0);
     146         [ -  + ]:         16 :         assert(argv);
     147                 :            : 
     148         [ +  - ]:         16 :         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
     149                 :            : 
     150   [ +  -  -  -  :         16 :                 switch (c) {
                   +  - ]
     151                 :            : 
     152                 :         12 :                 case 'h':
     153                 :         12 :                         return help();
     154                 :            : 
     155                 :          0 :                 case ARG_VERSION:
     156                 :          0 :                         return version();
     157                 :            : 
     158                 :          0 :                 case ARG_CAT_CONFIG:
     159                 :          0 :                         arg_cat_config = true;
     160                 :          0 :                         break;
     161                 :            : 
     162                 :          0 :                 case ARG_NO_PAGER:
     163                 :          0 :                         arg_pager_flags |= PAGER_DISABLE;
     164                 :          0 :                         break;
     165                 :            : 
     166                 :          4 :                 case '?':
     167                 :          4 :                         return -EINVAL;
     168                 :            : 
     169                 :          0 :                 default:
     170                 :          0 :                         assert_not_reached("Unhandled option");
     171                 :            :                 }
     172                 :            : 
     173   [ #  #  #  # ]:          0 :         if (arg_cat_config && argc > optind)
     174         [ #  # ]:          0 :                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     175                 :            :                                        "Positional arguments are not allowed with --cat-config");
     176                 :            : 
     177                 :          0 :         return 1;
     178                 :            : }
     179                 :            : 
     180                 :         16 : static int run(int argc, char *argv[]) {
     181                 :            :         int r, k;
     182                 :            : 
     183                 :         16 :         r = parse_argv(argc, argv);
     184         [ +  - ]:         16 :         if (r <= 0)
     185                 :         16 :                 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
     186                 :            : 
     187                 :          0 :         log_setup_service();
     188                 :            : 
     189                 :          0 :         umask(0022);
     190                 :            : 
     191                 :          0 :         r = 0;
     192                 :            : 
     193         [ #  # ]:          0 :         if (argc > optind) {
     194                 :            :                 int i;
     195                 :            : 
     196         [ #  # ]:          0 :                 for (i = optind; i < argc; i++) {
     197                 :          0 :                         k = apply_file(argv[i], false);
     198   [ #  #  #  # ]:          0 :                         if (k < 0 && r == 0)
     199                 :          0 :                                 r = k;
     200                 :            :                 }
     201                 :            :         } else {
     202         [ #  # ]:          0 :                 _cleanup_strv_free_ char **files = NULL;
     203                 :            :                 char **f;
     204                 :            : 
     205                 :          0 :                 r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("binfmt.d"));
     206         [ #  # ]:          0 :                 if (r < 0)
     207         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to enumerate binfmt.d files: %m");
     208                 :            : 
     209         [ #  # ]:          0 :                 if (arg_cat_config) {
     210                 :          0 :                         (void) pager_open(arg_pager_flags);
     211                 :            : 
     212                 :          0 :                         return cat_files(NULL, files, 0);
     213                 :            :                 }
     214                 :            : 
     215                 :            :                 /* Flush out all rules */
     216                 :          0 :                 (void) write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", WRITE_STRING_FILE_DISABLE_BUFFER);
     217                 :            : 
     218   [ #  #  #  # ]:          0 :                 STRV_FOREACH(f, files) {
     219                 :          0 :                         k = apply_file(*f, true);
     220   [ #  #  #  # ]:          0 :                         if (k < 0 && r == 0)
     221                 :          0 :                                 r = k;
     222                 :            :                 }
     223                 :            :         }
     224                 :            : 
     225                 :          0 :         return r;
     226                 :            : }
     227                 :            : 
     228                 :         16 : DEFINE_MAIN_FUNCTION(run);

Generated by: LCOV version 1.14