LCOV - code coverage report
Current view: top level - basic - util.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 77 143 53.8 %
Date: 2019-08-22 15:41:25 Functions: 7 11 63.6 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <alloca.h>
       4             : #include <errno.h>
       5             : #include <fcntl.h>
       6             : #include <sched.h>
       7             : #include <signal.h>
       8             : #include <stdarg.h>
       9             : #include <stdio.h>
      10             : #include <stdlib.h>
      11             : #include <string.h>
      12             : #include <sys/mman.h>
      13             : #include <sys/prctl.h>
      14             : #include <sys/statfs.h>
      15             : #include <sys/sysmacros.h>
      16             : #include <sys/types.h>
      17             : #include <unistd.h>
      18             : 
      19             : #include "alloc-util.h"
      20             : #include "btrfs-util.h"
      21             : #include "build.h"
      22             : #include "def.h"
      23             : #include "device-nodes.h"
      24             : #include "dirent-util.h"
      25             : #include "env-file.h"
      26             : #include "env-util.h"
      27             : #include "fd-util.h"
      28             : #include "fileio.h"
      29             : #include "format-util.h"
      30             : #include "hashmap.h"
      31             : #include "hostname-util.h"
      32             : #include "log.h"
      33             : #include "macro.h"
      34             : #include "missing.h"
      35             : #include "parse-util.h"
      36             : #include "path-util.h"
      37             : #include "process-util.h"
      38             : #include "procfs-util.h"
      39             : #include "set.h"
      40             : #include "signal-util.h"
      41             : #include "stat-util.h"
      42             : #include "string-util.h"
      43             : #include "strv.h"
      44             : #include "time-util.h"
      45             : #include "umask-util.h"
      46             : #include "user-util.h"
      47             : #include "util.h"
      48             : #include "virt.h"
      49             : 
      50             : int saved_argc = 0;
      51             : char **saved_argv = NULL;
      52             : static int saved_in_initrd = -1;
      53             : 
      54           0 : bool kexec_loaded(void) {
      55           0 :        _cleanup_free_ char *s = NULL;
      56             : 
      57           0 :        if (read_one_line_file("/sys/kernel/kexec_loaded", &s) < 0)
      58           0 :                return false;
      59             : 
      60           0 :        return s[0] == '1';
      61             : }
      62             : 
      63        9843 : int prot_from_flags(int flags) {
      64             : 
      65        9843 :         switch (flags & O_ACCMODE) {
      66             : 
      67        9817 :         case O_RDONLY:
      68        9817 :                 return PROT_READ;
      69             : 
      70           0 :         case O_WRONLY:
      71           0 :                 return PROT_WRITE;
      72             : 
      73          26 :         case O_RDWR:
      74          26 :                 return PROT_READ|PROT_WRITE;
      75             : 
      76           0 :         default:
      77           0 :                 return -EINVAL;
      78             :         }
      79             : }
      80             : 
      81        1301 : bool in_initrd(void) {
      82             :         struct statfs s;
      83             :         int r;
      84             : 
      85        1301 :         if (saved_in_initrd >= 0)
      86         908 :                 return saved_in_initrd;
      87             : 
      88             :         /* We make two checks here:
      89             :          *
      90             :          * 1. the flag file /etc/initrd-release must exist
      91             :          * 2. the root file system must be a memory file system
      92             :          *
      93             :          * The second check is extra paranoia, since misdetecting an
      94             :          * initrd can have bad consequences due the initrd
      95             :          * emptying when transititioning to the main systemd.
      96             :          */
      97             : 
      98         393 :         r = getenv_bool_secure("SYSTEMD_IN_INITRD");
      99         393 :         if (r < 0 && r != -ENXIO)
     100           0 :                 log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
     101             : 
     102         393 :         if (r >= 0)
     103           0 :                 saved_in_initrd = r > 0;
     104             :         else
     105         786 :                 saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
     106         393 :                                   statfs("/", &s) >= 0 &&
     107           0 :                                   is_temporary_fs(&s);
     108             : 
     109         393 :         return saved_in_initrd;
     110             : }
     111             : 
     112           4 : void in_initrd_force(bool value) {
     113           4 :         saved_in_initrd = value;
     114           4 : }
     115             : 
     116           6 : int on_ac_power(void) {
     117           6 :         bool found_offline = false, found_online = false;
     118           6 :         _cleanup_closedir_ DIR *d = NULL;
     119             :         struct dirent *de;
     120             : 
     121           6 :         d = opendir("/sys/class/power_supply");
     122           6 :         if (!d)
     123           0 :                 return errno == ENOENT ? true : -errno;
     124             : 
     125          30 :         FOREACH_DIRENT(de, d, return -errno) {
     126          36 :                 _cleanup_close_ int fd = -1, device = -1;
     127             :                 char contents[6];
     128             :                 ssize_t n;
     129             : 
     130          18 :                 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
     131          18 :                 if (device < 0) {
     132           0 :                         if (IN_SET(errno, ENOENT, ENOTDIR))
     133           0 :                                 continue;
     134             : 
     135           0 :                         return -errno;
     136             :                 }
     137             : 
     138          18 :                 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
     139          18 :                 if (fd < 0) {
     140           0 :                         if (errno == ENOENT)
     141           0 :                                 continue;
     142             : 
     143           0 :                         return -errno;
     144             :                 }
     145             : 
     146          18 :                 n = read(fd, contents, sizeof(contents));
     147          18 :                 if (n < 0)
     148           0 :                         return -errno;
     149             : 
     150          18 :                 if (n != 6 || memcmp(contents, "Mains\n", 6))
     151          12 :                         continue;
     152             : 
     153           6 :                 safe_close(fd);
     154           6 :                 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
     155           6 :                 if (fd < 0) {
     156           0 :                         if (errno == ENOENT)
     157           0 :                                 continue;
     158             : 
     159           0 :                         return -errno;
     160             :                 }
     161             : 
     162           6 :                 n = read(fd, contents, sizeof(contents));
     163           6 :                 if (n < 0)
     164           0 :                         return -errno;
     165             : 
     166           6 :                 if (n != 2 || contents[1] != '\n')
     167           0 :                         return -EIO;
     168             : 
     169           6 :                 if (contents[0] == '1') {
     170           6 :                         found_online = true;
     171           6 :                         break;
     172           0 :                 } else if (contents[0] == '0')
     173           0 :                         found_offline = true;
     174             :                 else
     175           0 :                         return -EIO;
     176             :         }
     177             : 
     178           6 :         return found_online || !found_offline;
     179             : }
     180             : 
     181           0 : int container_get_leader(const char *machine, pid_t *pid) {
     182           0 :         _cleanup_free_ char *s = NULL, *class = NULL;
     183             :         const char *p;
     184             :         pid_t leader;
     185             :         int r;
     186             : 
     187           0 :         assert(machine);
     188           0 :         assert(pid);
     189             : 
     190           0 :         if (streq(machine, ".host")) {
     191           0 :                 *pid = 1;
     192           0 :                 return 0;
     193             :         }
     194             : 
     195           0 :         if (!machine_name_is_valid(machine))
     196           0 :                 return -EINVAL;
     197             : 
     198           0 :         p = strjoina("/run/systemd/machines/", machine);
     199           0 :         r = parse_env_file(NULL, p,
     200             :                            "LEADER", &s,
     201             :                            "CLASS", &class);
     202           0 :         if (r == -ENOENT)
     203           0 :                 return -EHOSTDOWN;
     204           0 :         if (r < 0)
     205           0 :                 return r;
     206           0 :         if (!s)
     207           0 :                 return -EIO;
     208             : 
     209           0 :         if (!streq_ptr(class, "container"))
     210           0 :                 return -EIO;
     211             : 
     212           0 :         r = parse_pid(s, &leader);
     213           0 :         if (r < 0)
     214           0 :                 return r;
     215           0 :         if (leader <= 1)
     216           0 :                 return -EIO;
     217             : 
     218           0 :         *pid = leader;
     219           0 :         return 0;
     220             : }
     221             : 
     222           0 : int version(void) {
     223           0 :         puts("systemd " STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")\n"
     224             :              SYSTEMD_FEATURES);
     225           0 :         return 0;
     226             : }
     227             : 
     228             : /* This is a direct translation of str_verscmp from boot.c */
     229         522 : static bool is_digit(int c) {
     230         522 :         return c >= '0' && c <= '9';
     231             : }
     232             : 
     233          90 : static int c_order(int c) {
     234          90 :         if (c == 0 || is_digit(c))
     235           0 :                 return 0;
     236             : 
     237          90 :         if ((c >= 'a') && (c <= 'z'))
     238          30 :                 return c;
     239             : 
     240          60 :         return c + 0x10000;
     241             : }
     242             : 
     243          19 : int str_verscmp(const char *s1, const char *s2) {
     244             :         const char *os1, *os2;
     245             : 
     246          19 :         assert(s1);
     247          19 :         assert(s2);
     248             : 
     249          19 :         os1 = s1;
     250          19 :         os2 = s2;
     251             : 
     252          54 :         while (*s1 || *s2) {
     253             :                 int first;
     254             : 
     255          94 :                 while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) {
     256             :                         int order;
     257             : 
     258          45 :                         order = c_order(*s1) - c_order(*s2);
     259          45 :                         if (order != 0)
     260           0 :                                 return order;
     261          45 :                         s1++;
     262          45 :                         s2++;
     263             :                 }
     264             : 
     265          49 :                 while (*s1 == '0')
     266           0 :                         s1++;
     267          57 :                 while (*s2 == '0')
     268           8 :                         s2++;
     269             : 
     270          49 :                 first = 0;
     271         120 :                 while (is_digit(*s1) && is_digit(*s2)) {
     272          71 :                         if (first == 0)
     273          71 :                                 first = *s1 - *s2;
     274          71 :                         s1++;
     275          71 :                         s2++;
     276             :                 }
     277             : 
     278          49 :                 if (is_digit(*s1))
     279           8 :                         return 1;
     280          41 :                 if (is_digit(*s2))
     281           5 :                         return -1;
     282             : 
     283          36 :                 if (first != 0)
     284           1 :                         return first;
     285             :         }
     286             : 
     287           5 :         return strcmp(os1, os2);
     288             : }
     289             : 
     290             : /* Turn off core dumps but only if we're running outside of a container. */
     291           0 : void disable_coredumps(void) {
     292             :         int r;
     293             : 
     294           0 :         if (detect_container() > 0)
     295           0 :                 return;
     296             : 
     297           0 :         r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", WRITE_STRING_FILE_DISABLE_BUFFER);
     298           0 :         if (r < 0)
     299           0 :                 log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m");
     300             : }

Generated by: LCOV version 1.14