LCOV - code coverage report
Current view: top level - binfmt - binfmt.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 20 101 19.8 %
Date: 2019-08-22 15:41:25 Functions: 4 7 57.1 %

          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           3 : static int help(void) {
     107           3 :         _cleanup_free_ char *link = NULL;
     108             :         int r;
     109             : 
     110           3 :         r = terminal_urlify_man("systemd-binfmt.service", "8", &link);
     111           3 :         if (r < 0)
     112           0 :                 return log_oom();
     113             : 
     114           3 :         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           3 :         return 0;
     126             : }
     127             : 
     128           4 : 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           4 :         assert(argc >= 0);
     146           4 :         assert(argv);
     147             : 
     148           4 :         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
     149             : 
     150           4 :                 switch (c) {
     151             : 
     152           3 :                 case 'h':
     153           3 :                         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           1 :                 case '?':
     167           1 :                         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           4 : static int run(int argc, char *argv[]) {
     181             :         int r, k;
     182             : 
     183           4 :         r = parse_argv(argc, argv);
     184           4 :         if (r <= 0)
     185           4 :                 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           4 : DEFINE_MAIN_FUNCTION(run);

Generated by: LCOV version 1.14