LCOV - code coverage report
Current view: top level - basic - util.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 77 143 53.8 %
Date: 2019-08-23 13:36:53 Functions: 7 11 63.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 62 158 39.2 %

           Branch data     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                 :      39372 : int prot_from_flags(int flags) {
      64                 :            : 
      65   [ +  -  +  - ]:      39372 :         switch (flags & O_ACCMODE) {
      66                 :            : 
      67                 :      39268 :         case O_RDONLY:
      68                 :      39268 :                 return PROT_READ;
      69                 :            : 
      70                 :          0 :         case O_WRONLY:
      71                 :          0 :                 return PROT_WRITE;
      72                 :            : 
      73                 :        104 :         case O_RDWR:
      74                 :        104 :                 return PROT_READ|PROT_WRITE;
      75                 :            : 
      76                 :          0 :         default:
      77                 :          0 :                 return -EINVAL;
      78                 :            :         }
      79                 :            : }
      80                 :            : 
      81                 :       5198 : bool in_initrd(void) {
      82                 :            :         struct statfs s;
      83                 :            :         int r;
      84                 :            : 
      85         [ +  + ]:       5198 :         if (saved_in_initrd >= 0)
      86                 :       3628 :                 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                 :       1570 :         r = getenv_bool_secure("SYSTEMD_IN_INITRD");
      99   [ +  -  -  + ]:       1570 :         if (r < 0 && r != -ENXIO)
     100         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
     101                 :            : 
     102         [ -  + ]:       1570 :         if (r >= 0)
     103                 :          0 :                 saved_in_initrd = r > 0;
     104                 :            :         else
     105         [ #  # ]:       3140 :                 saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
     106         [ -  + ]:       1570 :                                   statfs("/", &s) >= 0 &&
     107         [ #  # ]:          0 :                                   is_temporary_fs(&s);
     108                 :            : 
     109                 :       1570 :         return saved_in_initrd;
     110                 :            : }
     111                 :            : 
     112                 :         16 : void in_initrd_force(bool value) {
     113                 :         16 :         saved_in_initrd = value;
     114                 :         16 : }
     115                 :            : 
     116                 :         24 : int on_ac_power(void) {
     117                 :         24 :         bool found_offline = false, found_online = false;
     118                 :         24 :         _cleanup_closedir_ DIR *d = NULL;
     119                 :            :         struct dirent *de;
     120                 :            : 
     121                 :         24 :         d = opendir("/sys/class/power_supply");
     122         [ -  + ]:         24 :         if (!d)
     123         [ #  # ]:          0 :                 return errno == ENOENT ? true : -errno;
     124                 :            : 
     125   [ -  +  #  #  :        120 :         FOREACH_DIRENT(de, d, return -errno) {
                   +  + ]
     126   [ -  +  -  +  :        144 :                 _cleanup_close_ int fd = -1, device = -1;
             -  +  -  + ]
     127                 :            :                 char contents[6];
     128                 :            :                 ssize_t n;
     129                 :            : 
     130                 :         72 :                 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
     131         [ -  + ]:         72 :                 if (device < 0) {
     132   [ #  #  #  # ]:          0 :                         if (IN_SET(errno, ENOENT, ENOTDIR))
     133                 :          0 :                                 continue;
     134                 :            : 
     135                 :          0 :                         return -errno;
     136                 :            :                 }
     137                 :            : 
     138                 :         72 :                 fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
     139         [ -  + ]:         72 :                 if (fd < 0) {
     140         [ #  # ]:          0 :                         if (errno == ENOENT)
     141                 :          0 :                                 continue;
     142                 :            : 
     143                 :          0 :                         return -errno;
     144                 :            :                 }
     145                 :            : 
     146                 :         72 :                 n = read(fd, contents, sizeof(contents));
     147         [ -  + ]:         72 :                 if (n < 0)
     148                 :          0 :                         return -errno;
     149                 :            : 
     150   [ +  -  +  + ]:         72 :                 if (n != 6 || memcmp(contents, "Mains\n", 6))
     151                 :         48 :                         continue;
     152                 :            : 
     153                 :         24 :                 safe_close(fd);
     154                 :         24 :                 fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
     155         [ -  + ]:         24 :                 if (fd < 0) {
     156         [ #  # ]:          0 :                         if (errno == ENOENT)
     157                 :          0 :                                 continue;
     158                 :            : 
     159                 :          0 :                         return -errno;
     160                 :            :                 }
     161                 :            : 
     162                 :         24 :                 n = read(fd, contents, sizeof(contents));
     163         [ -  + ]:         24 :                 if (n < 0)
     164                 :          0 :                         return -errno;
     165                 :            : 
     166   [ +  -  -  + ]:         24 :                 if (n != 2 || contents[1] != '\n')
     167                 :          0 :                         return -EIO;
     168                 :            : 
     169         [ +  - ]:         24 :                 if (contents[0] == '1') {
     170                 :         24 :                         found_online = true;
     171                 :         24 :                         break;
     172         [ #  # ]:          0 :                 } else if (contents[0] == '0')
     173                 :          0 :                         found_offline = true;
     174                 :            :                 else
     175                 :          0 :                         return -EIO;
     176                 :            :         }
     177                 :            : 
     178   [ -  +  #  # ]:         24 :         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                 :       2088 : static bool is_digit(int c) {
     230   [ +  +  +  + ]:       2088 :         return c >= '0' && c <= '9';
     231                 :            : }
     232                 :            : 
     233                 :        360 : static int c_order(int c) {
     234   [ +  -  -  + ]:        360 :         if (c == 0 || is_digit(c))
     235                 :          0 :                 return 0;
     236                 :            : 
     237   [ +  +  +  - ]:        360 :         if ((c >= 'a') && (c <= 'z'))
     238                 :        120 :                 return c;
     239                 :            : 
     240                 :        240 :         return c + 0x10000;
     241                 :            : }
     242                 :            : 
     243                 :         76 : int str_verscmp(const char *s1, const char *s2) {
     244                 :            :         const char *os1, *os2;
     245                 :            : 
     246         [ -  + ]:         76 :         assert(s1);
     247         [ -  + ]:         76 :         assert(s2);
     248                 :            : 
     249                 :         76 :         os1 = s1;
     250                 :         76 :         os2 = s2;
     251                 :            : 
     252   [ +  +  -  + ]:        216 :         while (*s1 || *s2) {
     253                 :            :                 int first;
     254                 :            : 
     255   [ +  -  +  +  :        376 :                 while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) {
             +  -  -  + ]
     256                 :            :                         int order;
     257                 :            : 
     258                 :        180 :                         order = c_order(*s1) - c_order(*s2);
     259         [ -  + ]:        180 :                         if (order != 0)
     260                 :          0 :                                 return order;
     261                 :        180 :                         s1++;
     262                 :        180 :                         s2++;
     263                 :            :                 }
     264                 :            : 
     265         [ -  + ]:        196 :                 while (*s1 == '0')
     266                 :          0 :                         s1++;
     267         [ +  + ]:        228 :                 while (*s2 == '0')
     268                 :         32 :                         s2++;
     269                 :            : 
     270                 :        196 :                 first = 0;
     271   [ +  +  +  + ]:        480 :                 while (is_digit(*s1) && is_digit(*s2)) {
     272         [ +  - ]:        284 :                         if (first == 0)
     273                 :        284 :                                 first = *s1 - *s2;
     274                 :        284 :                         s1++;
     275                 :        284 :                         s2++;
     276                 :            :                 }
     277                 :            : 
     278         [ +  + ]:        196 :                 if (is_digit(*s1))
     279                 :         32 :                         return 1;
     280         [ +  + ]:        164 :                 if (is_digit(*s2))
     281                 :         20 :                         return -1;
     282                 :            : 
     283         [ +  + ]:        144 :                 if (first != 0)
     284                 :          4 :                         return first;
     285                 :            :         }
     286                 :            : 
     287                 :         20 :         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