LCOV - code coverage report
Current view: top level - crtools - proc_parse.c (source / functions) Hit Total Coverage
Test: crtools.info Lines: 352 414 85.0 %
Date: 2012-12-28 Functions: 18 18 100.0 %
Branches: 250 376 66.5 %

           Branch data     Line data    Source code
       1                 :            : #include <stdio.h>
       2                 :            : #include <unistd.h>
       3                 :            : #include <fcntl.h>
       4                 :            : #include <sys/mman.h>
       5                 :            : #include <sys/types.h>
       6                 :            : #include <dirent.h>
       7                 :            : #include <errno.h>
       8                 :            : #include <sys/stat.h>
       9                 :            : #include <string.h>
      10                 :            : #include <linux/fs.h>
      11                 :            : 
      12                 :            : #include "types.h"
      13                 :            : #include "list.h"
      14                 :            : #include "util.h"
      15                 :            : #include "crtools.h"
      16                 :            : #include "mount.h"
      17                 :            : #include "cpu.h"
      18                 :            : 
      19                 :            : #include "proc_parse.h"
      20                 :            : #include "protobuf.h"
      21                 :            : #include "protobuf/fdinfo.pb-c.h"
      22                 :            : 
      23                 :            : #include <stdlib.h>
      24                 :            : 
      25                 :            : struct buffer {
      26                 :            :         char buf[PAGE_SIZE];
      27                 :            :         char end; /* '\0' */
      28                 :            : };
      29                 :            : 
      30                 :            : static struct buffer __buf;
      31                 :            : static char *buf = __buf.buf;
      32                 :            : 
      33                 :            : #define BUF_SIZE sizeof(__buf.buf)
      34                 :            : 
      35                 :        546 : int parse_cpuinfo_features(void)
      36                 :            : {
      37                 :            :         FILE *cpuinfo;
      38                 :            : 
      39                 :        546 :         cpuinfo = fopen("/proc/cpuinfo", "r");
      40         [ +  - ]:        546 :         if (!cpuinfo) {
      41                 :          0 :                 pr_perror("Can't open cpuinfo file");
      42                 :          0 :                 return -1;
      43                 :            :         }
      44                 :            : 
      45         [ +  + ]:      22386 :         while (fgets(buf, BUF_SIZE, cpuinfo)) {
      46                 :            :                 char *tok;
      47                 :            : 
      48         [ +  + ]:      21840 :                 if (strncmp(buf, "flags\t\t:", 8))
      49                 :      20748 :                         continue;
      50                 :            : 
      51         [ +  + ]:      70980 :                 for (tok = strtok(buf, " \t\n"); tok;
      52                 :      49140 :                      tok = strtok(NULL, " \t\n")) {
      53         [ +  + ]:      49140 :                         if (!strcmp(tok, x86_cap_flags[X86_FEATURE_FXSR]))
      54                 :       1092 :                                 cpu_set_feature(X86_FEATURE_FXSR);
      55         [ -  + ]:      48048 :                         else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_XSAVE]))
      56                 :          0 :                                 cpu_set_feature(X86_FEATURE_XSAVE);
      57         [ +  + ]:      48048 :                         else if (!strcmp(tok, x86_cap_flags[X86_FEATURE_FPU]))
      58                 :       1092 :                                 cpu_set_feature(X86_FEATURE_FPU);
      59                 :            :                 }
      60                 :            :         }
      61                 :            : 
      62                 :        546 :         fclose(cpuinfo);
      63                 :        546 :         return 0;
      64                 :            : }
      65                 :            : 
      66                 :            : /* check the @line starts with "%lx-%lx" format */
      67                 :     416720 : static bool is_vma_range_fmt(char *line)
      68                 :            : {
      69 [ +  - ][ +  + ]:     774634 :         while (*line && is_hex_digit(*line))
                 [ +  + ]
      70                 :     357914 :                 line++;
      71                 :            : 
      72         [ +  + ]:     416720 :         if (*line++ != '-')
      73                 :            :                 return false;
      74                 :            : 
      75 [ +  - ][ +  + ]:     331869 :         while (*line && is_hex_digit(*line))
                 [ -  + ]
      76                 :     305824 :                 line++;
      77                 :            : 
      78         [ +  - ]:      26045 :         if (*line++ != ' ')
      79                 :            :                 return false;
      80                 :            : 
      81                 :     416720 :         return true;
      82                 :            : }
      83                 :            : 
      84                 :      26045 : static int parse_vmflags(char *buf, struct vma_area *vma_area)
      85                 :            : {
      86                 :            :         char *tok;
      87                 :            : 
      88         [ +  - ]:      26045 :         if (!buf[0])
      89                 :            :                 return 0;
      90                 :            : 
      91                 :      26045 :         tok = strtok(buf, " \n");
      92         [ +  - ]:      26045 :         if (!tok)
      93                 :            :                 return 0;
      94                 :            : 
      95                 :            : #define _vmflag_match(_t, _s) (_t[0] == _s[0] && _t[1] == _s[1])
      96                 :            : 
      97                 :            :         do {
      98                 :            :                 /* mmap() block */
      99 [ +  + ][ +  - ]:     149840 :                 if (_vmflag_match(tok, "gd"))
     100                 :       1245 :                         vma_area->vma.flags |= MAP_GROWSDOWN;
     101 [ +  + ][ +  - ]:     148595 :                 else if (_vmflag_match(tok, "lo"))
     102                 :          4 :                         vma_area->vma.flags |= MAP_LOCKED;
     103 [ +  + ][ +  - ]:     148591 :                 else if (_vmflag_match(tok, "nr"))
     104                 :         60 :                         vma_area->vma.flags |= MAP_NORESERVE;
     105 [ +  + ][ -  + ]:     148531 :                 else if (_vmflag_match(tok, "ht"))
     106                 :          0 :                         vma_area->vma.flags |= MAP_HUGETLB;
     107                 :            : 
     108                 :            :                 /* madvise() block */
     109 [ +  + ][ +  + ]:     149840 :                 if (_vmflag_match(tok, "sr"))
     110                 :          2 :                         vma_area->vma.madv |= (1ul << MADV_SEQUENTIAL);
     111 [ +  + ][ -  + ]:     149838 :                 else if (_vmflag_match(tok, "rr"))
     112                 :          0 :                         vma_area->vma.madv |= (1ul << MADV_RANDOM);
     113 [ +  + ][ +  + ]:     149838 :                 else if (_vmflag_match(tok, "dc"))
     114                 :          2 :                         vma_area->vma.madv |= (1ul << MADV_DONTFORK);
     115 [ +  + ][ +  + ]:     149836 :                 else if (_vmflag_match(tok, "dd"))
     116                 :          2 :                         vma_area->vma.madv |= (1ul << MADV_DONTDUMP);
     117 [ +  + ][ +  + ]:     149834 :                 else if (_vmflag_match(tok, "mg"))
     118                 :          2 :                         vma_area->vma.madv |= (1ul << MADV_MERGEABLE);
     119 [ +  + ][ +  - ]:     149832 :                 else if (_vmflag_match(tok, "hg"))
     120                 :          2 :                         vma_area->vma.madv |= (1ul << MADV_HUGEPAGE);
     121 [ +  + ][ -  + ]:     149830 :                 else if (_vmflag_match(tok, "nh"))
     122                 :          0 :                         vma_area->vma.madv |= (1ul << MADV_NOHUGEPAGE);
     123                 :            : 
     124                 :            :                 /*
     125                 :            :                  * Anything else is just ignored.
     126                 :            :                  */
     127         [ +  + ]:     149840 :         } while ((tok = strtok(NULL, " \n")));
     128                 :            : 
     129                 :            : #undef _vmflag_match
     130                 :            : 
     131         [ +  + ]:      26045 :         if (vma_area->vma.madv)
     132                 :      26045 :                 vma_area->vma.has_madv = true;
     133                 :            : 
     134                 :            :         return 0;
     135                 :            : }
     136                 :            : 
     137                 :       3326 : static int is_anon_shmem_map(dev_t dev)
     138                 :            : {
     139                 :            :         static dev_t shmem_dev = 0;
     140                 :            : 
     141         [ +  + ]:       3326 :         if (!shmem_dev) {
     142                 :            :                 void *map;
     143                 :            :                 char maps[128];
     144                 :            :                 struct stat buf;
     145                 :            : 
     146                 :        166 :                 map = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
     147                 :            :                                 MAP_SHARED | MAP_ANONYMOUS, 0, 0);
     148         [ -  + ]:        166 :                 if (map == MAP_FAILED) {
     149                 :          0 :                         pr_perror("Can't mmap piggie");
     150                 :            :                         return -1;
     151                 :            :                 }
     152                 :            : 
     153                 :        166 :                 sprintf(maps, "/proc/%d/map_files/%lx-%lx",
     154                 :            :                                 getpid(), (unsigned long)map,
     155                 :        166 :                                 (unsigned long)map + PAGE_SIZE);
     156         [ -  + ]:        166 :                 if (stat(maps, &buf) < 0) {
     157                 :          0 :                         pr_perror("Can't stat piggie");
     158                 :            :                         return -1;
     159                 :            :                 }
     160                 :            : 
     161                 :        166 :                 munmap(map, PAGE_SIZE);
     162                 :            : 
     163                 :        166 :                 shmem_dev = buf.st_dev;
     164                 :        166 :                 pr_info("Found anon-shmem piggie at %lx\n", shmem_dev);
     165                 :            :         }
     166                 :            : 
     167                 :       3326 :         return shmem_dev == dev;
     168                 :            : }
     169                 :            : 
     170                 :        698 : int parse_smaps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
     171                 :            : {
     172                 :        698 :         struct vma_area *vma_area = NULL;
     173                 :            :         u64 start, end, pgoff;
     174                 :            :         unsigned long ino;
     175                 :            :         char r, w, x, s;
     176                 :            :         int dev_maj, dev_min;
     177                 :        698 :         int ret = -1, nr = 0;
     178                 :            : 
     179                 :        698 :         DIR *map_files_dir = NULL;
     180                 :        698 :         FILE *smaps = NULL;
     181                 :            : 
     182 [ -  + ][ +  - ]:        698 :         smaps = fopen_proc(pid, "smaps");
                 [ -  + ]
     183         [ +  - ]:        698 :         if (!smaps)
     184                 :            :                 goto err;
     185                 :            : 
     186         [ +  + ]:       1047 :         if (use_map_files) {
     187 [ -  + ][ +  - ]:        349 :                 map_files_dir = opendir_proc(pid, "map_files");
                 [ -  + ]
     188         [ +  - ]:        349 :                 if (!map_files_dir) /* old kernel? */
     189                 :            :                         goto err;
     190                 :            :         }
     191                 :            : 
     192         [ +  + ]:     417418 :         while (fgets(buf, BUF_SIZE, smaps)) {
     193                 :            :                 int num;
     194                 :            :                 char file_path[6];
     195                 :            : 
     196         [ +  + ]:     416720 :                 if (!is_vma_range_fmt(buf)) {
     197         [ -  + ]:     390675 :                         if (!strncmp(buf, "Nonlinear", 9)) {
     198         [ #  # ]:          0 :                                 BUG_ON(!vma_area);
     199                 :          0 :                                 pr_err("Nonlinear mapping found %016lx-%016lx\n",
     200                 :            :                                        vma_area->vma.start, vma_area->vma.end);
     201                 :            :                                 /*
     202                 :            :                                  * VMA is already on list and will be
     203                 :            :                                  * freed later as list get destroyed.
     204                 :            :                                  */
     205                 :          0 :                                 vma_area = NULL;
     206                 :            :                                 goto err;
     207         [ +  + ]:     390675 :                         } else if (!strncmp(buf, "VmFlags: ", 9)) {
     208         [ -  + ]:      26045 :                                 BUG_ON(!vma_area);
     209         [ +  - ]:      26045 :                                 if (parse_vmflags(&buf[9], vma_area))
     210                 :            :                                         goto err;
     211                 :      26045 :                                 continue;
     212                 :            :                         } else
     213                 :     364630 :                                 continue;
     214                 :            :                 }
     215                 :            : 
     216 [ -  + ][ +  - ]:      26045 :                 vma_area = alloc_vma_area();
     217         [ +  - ]:      26045 :                 if (!vma_area)
     218                 :            :                         goto err;
     219                 :            : 
     220                 :      26045 :                 memset(file_path, 0, 6);
     221                 :      26045 :                 num = sscanf(buf, "%lx-%lx %c%c%c%c %lx %02x:%02x %lu %5s",
     222                 :            :                              &start, &end, &r, &w, &x, &s, &pgoff, &dev_maj,
     223                 :            :                              &dev_min, &ino, file_path);
     224         [ -  + ]:      26045 :                 if (num < 10) {
     225                 :          0 :                         pr_err("Can't parse: %s\n", buf);
     226                 :            :                         goto err;
     227                 :            :                 }
     228                 :            : 
     229         [ +  + ]:      26045 :                 if (map_files_dir) {
     230                 :            :                         char path[32];
     231                 :            : 
     232                 :            :                         /* Figure out if it's file mapping */
     233                 :       6055 :                         snprintf(path, sizeof(path), "%lx-%lx", start, end);
     234                 :            : 
     235                 :            :                         /*
     236                 :            :                          * Note that we "open" it in dumper process space
     237                 :            :                          * so later we might refer to it via /proc/self/fd/vm_file_fd
     238                 :            :                          * if needed.
     239                 :            :                          */
     240                 :       6055 :                         vma_area->vm_file_fd = openat(dirfd(map_files_dir), path, O_RDONLY);
     241         [ +  + ]:       6055 :                         if (vma_area->vm_file_fd < 0) {
     242         [ -  + ]:       2729 :                                 if (errno == ENXIO) {
     243                 :            :                                         struct stat buf;
     244                 :            : 
     245         [ #  # ]:          0 :                                         if (fstatat(dirfd(map_files_dir), path, &buf, 0))
     246                 :            :                                                 goto err_bogus_mapfile;
     247                 :            : 
     248         [ #  # ]:          0 :                                         if (!S_ISSOCK(buf.st_mode))
     249                 :            :                                                 goto err_bogus_mapfile;
     250                 :            : 
     251                 :          0 :                                         pr_info("Found socket %lu mapping @%lx\n", buf.st_ino, start);
     252                 :          0 :                                         vma_area->vma.status |= VMA_AREA_SOCKET | VMA_AREA_REGULAR;
     253                 :          0 :                                         vma_area->vm_socket_id = buf.st_ino;
     254         [ +  - ]:       6055 :                                 } else if (errno != ENOENT)
     255                 :            :                                         goto err_bogus_mapfile;
     256                 :            :                         }
     257                 :            :                 }
     258                 :            : 
     259                 :      26045 :                 vma_area->vma.start  = start;
     260                 :      26045 :                 vma_area->vma.end    = end;
     261                 :      26045 :                 vma_area->vma.pgoff  = pgoff;
     262                 :      26045 :                 vma_area->vma.prot   = PROT_NONE;
     263                 :            : 
     264         [ +  + ]:      26045 :                 if (r == 'r')
     265                 :      23584 :                         vma_area->vma.prot |= PROT_READ;
     266         [ +  + ]:      26045 :                 if (w == 'w')
     267                 :      17142 :                         vma_area->vma.prot |= PROT_WRITE;
     268         [ +  + ]:      26045 :                 if (x == 'x')
     269                 :       6821 :                         vma_area->vma.prot |= PROT_EXEC;
     270                 :            : 
     271         [ +  + ]:      26045 :                 if (s == 's')
     272                 :       1116 :                         vma_area->vma.flags = MAP_SHARED;
     273         [ +  - ]:      24929 :                 else if (s == 'p')
     274                 :      24929 :                         vma_area->vma.flags = MAP_PRIVATE;
     275                 :            :                 else {
     276                 :          0 :                         pr_err("Unexpected VMA met (%c)\n", s);
     277                 :            :                         goto err;
     278                 :            :                 }
     279                 :            : 
     280         [ +  - ]:      26045 :                 if (vma_area->vma.status != 0) {
     281                 :            :                         goto done;
     282         [ +  + ]:      26045 :                 } else if (strstr(buf, "[vsyscall]")) {
     283                 :        698 :                         vma_area->vma.status |= VMA_AREA_VSYSCALL;
     284         [ +  + ]:      25347 :                 } else if (strstr(buf, "[vdso]")) {
     285                 :        698 :                         vma_area->vma.status |= VMA_AREA_REGULAR | VMA_AREA_VDSO;
     286         [ +  + ]:      24649 :                 } else if (strstr(buf, "[heap]")) {
     287                 :        632 :                         vma_area->vma.status |= VMA_AREA_REGULAR | VMA_AREA_HEAP;
     288                 :            :                 } else {
     289                 :      24017 :                         vma_area->vma.status = VMA_AREA_REGULAR;
     290                 :            :                 }
     291                 :            : 
     292                 :            :                 /*
     293                 :            :                  * Some mapping hints for restore, we save this on
     294                 :            :                  * disk and restore might need to analyze it.
     295                 :            :                  */
     296         [ +  + ]:      26045 :                 if (vma_area->vm_file_fd >= 0) {
     297                 :            :                         struct stat st_buf;
     298                 :            : 
     299         [ -  + ]:       3326 :                         if (fstat(vma_area->vm_file_fd, &st_buf) < 0) {
     300                 :          0 :                                 pr_perror("Failed fstat on %d's map %lu", pid, start);
     301                 :            :                                 goto err;
     302                 :            :                         }
     303         [ -  + ]:       3326 :                         if (!S_ISREG(st_buf.st_mode)) {
     304                 :          0 :                                 pr_err("Can't handle non-regular mapping on %d's map %lu\n", pid, start);
     305                 :            :                                 goto err;
     306                 :            :                         }
     307                 :            : 
     308                 :            :                         /*
     309                 :            :                          * /dev/zero stands for anon-shared mapping
     310                 :            :                          * otherwise it's some file mapping.
     311                 :            :                          */
     312         [ +  + ]:       3326 :                         if (is_anon_shmem_map(st_buf.st_dev)) {
     313         [ +  - ]:         49 :                                 if (!(vma_area->vma.flags & MAP_SHARED))
     314                 :            :                                         goto err_bogus_mapping;
     315                 :         49 :                                 vma_area->vma.flags  |= MAP_ANONYMOUS;
     316                 :         49 :                                 vma_area->vma.status |= VMA_ANON_SHARED;
     317                 :         49 :                                 vma_area->vma.shmid = st_buf.st_ino;
     318                 :            : 
     319         [ +  + ]:         49 :                                 if (!strcmp(file_path, "/SYSV")) {
     320                 :          5 :                                         pr_info("path: %s\n", file_path);
     321                 :          5 :                                         vma_area->vma.status |= VMA_AREA_SYSVIPC;
     322                 :            :                                 }
     323                 :            :                         } else {
     324         [ +  + ]:       3277 :                                 if (vma_area->vma.flags & MAP_PRIVATE)
     325                 :       3269 :                                         vma_area->vma.status |= VMA_FILE_PRIVATE;
     326                 :            :                                 else
     327                 :       3326 :                                         vma_area->vma.status |= VMA_FILE_SHARED;
     328                 :            :                         }
     329                 :            :                 } else {
     330                 :            :                         /*
     331                 :            :                          * No file but mapping -- anonymous one.
     332                 :            :                          */
     333         [ +  + ]:      22719 :                         if (vma_area->vma.flags & MAP_SHARED) {
     334                 :       1059 :                                 vma_area->vma.status |= VMA_ANON_SHARED;
     335                 :       1059 :                                 vma_area->vma.shmid = ino;
     336                 :            :                         } else {
     337                 :      21660 :                                 vma_area->vma.status |= VMA_ANON_PRIVATE;
     338                 :            :                         }
     339                 :      22719 :                         vma_area->vma.flags  |= MAP_ANONYMOUS;
     340                 :            :                 }
     341                 :            : done:
     342                 :      26045 :                 list_add_tail(&vma_area->list, vma_area_list);
     343                 :     416720 :                 nr++;
     344                 :            :         }
     345                 :            : 
     346                 :            :         vma_area = NULL;
     347                 :            :         ret = nr;
     348                 :            : 
     349                 :            : err:
     350         [ +  - ]:        698 :         if (smaps)
     351                 :        698 :                 fclose(smaps);
     352                 :            : 
     353         [ +  + ]:        698 :         if (map_files_dir)
     354                 :        349 :                 closedir(map_files_dir);
     355                 :            : 
     356         [ -  + ]:        698 :         xfree(vma_area);
     357                 :        698 :         return ret;
     358                 :            : 
     359                 :            : err_bogus_mapping:
     360                 :          0 :         pr_err("Bogus mapping 0x%lx-0x%lx (flags: %#x vm_file_fd: %d)\n",
     361                 :            :                vma_area->vma.start, vma_area->vma.end,
     362                 :            :                vma_area->vma.flags, vma_area->vm_file_fd);
     363                 :          0 :         goto err;
     364                 :            : 
     365                 :            : err_bogus_mapfile:
     366                 :          0 :         pr_perror("Can't open %d's mapfile link %lx", pid, start);
     367                 :          0 :         goto err;
     368                 :            : }
     369                 :            : 
     370                 :        391 : int parse_pid_stat_small(pid_t pid, struct proc_pid_stat_small *s)
     371                 :            : {
     372                 :            :         char *tok, *p;
     373                 :            :         int fd;
     374                 :            :         int n;
     375                 :            : 
     376         [ -  + ]:        391 :         fd = open_proc(pid, "stat");
     377         [ +  - ]:        391 :         if (fd < 0)
     378                 :            :                 return -1;
     379                 :            : 
     380                 :        391 :         n = read(fd, buf, BUF_SIZE);
     381         [ -  + ]:        391 :         if (n < 1) {
     382                 :          0 :                 pr_err("stat for %d is corrupted\n", pid);
     383                 :          0 :                 close(fd);
     384                 :          0 :                 return -1;
     385                 :            :         }
     386                 :        391 :         close(fd);
     387                 :            : 
     388                 :        391 :         memset(s, 0, sizeof(*s));
     389                 :            : 
     390                 :        391 :         tok = strchr(buf, ' ');
     391         [ +  - ]:        391 :         if (!tok)
     392                 :            :                 goto err;
     393                 :        391 :         *tok++ = '\0';
     394         [ +  - ]:        391 :         if (*tok != '(')
     395                 :            :                 goto err;
     396                 :            : 
     397                 :        782 :         s->pid = atoi(buf);
     398                 :            : 
     399                 :        391 :         p = strrchr(tok + 1, ')');
     400         [ +  - ]:        391 :         if (!p)
     401                 :            :                 goto err;
     402                 :        391 :         *tok = '\0';
     403                 :        391 :         *p = '\0';
     404                 :            : 
     405                 :        391 :         strncpy(s->comm, tok + 1, sizeof(s->comm));
     406                 :            : 
     407                 :        391 :         n = sscanf(p + 1, " %c %d %d %d", &s->state, &s->ppid, &s->pgid, &s->sid);
     408         [ -  + ]:        391 :         if (n < 4)
     409                 :            :                 goto err;
     410                 :            : 
     411                 :            :         return 0;
     412                 :            : 
     413                 :            : err:
     414                 :          0 :         pr_err("Parsing %d's stat failed (#fields do not match)\n", pid);
     415                 :        391 :         return -1;
     416                 :            : }
     417                 :            : 
     418                 :        360 : int parse_pid_stat(pid_t pid, struct proc_pid_stat *s)
     419                 :            : {
     420                 :            :         char *tok, *p;
     421                 :            :         int fd;
     422                 :            :         int n;
     423                 :            : 
     424         [ -  + ]:        360 :         fd = open_proc(pid, "stat");
     425         [ +  - ]:        360 :         if (fd < 0)
     426                 :            :                 return -1;
     427                 :            : 
     428                 :        360 :         n = read(fd, buf, BUF_SIZE);
     429         [ -  + ]:        360 :         if (n < 1) {
     430                 :          0 :                 pr_err("stat for %d is corrupted\n", pid);
     431                 :          0 :                 close(fd);
     432                 :          0 :                 return -1;
     433                 :            :         }
     434                 :        360 :         close(fd);
     435                 :            : 
     436                 :        360 :         memset(s, 0, sizeof(*s));
     437                 :            : 
     438                 :        360 :         tok = strchr(buf, ' ');
     439         [ +  - ]:        360 :         if (!tok)
     440                 :            :                 goto err;
     441                 :        360 :         *tok++ = '\0';
     442         [ +  - ]:        360 :         if (*tok != '(')
     443                 :            :                 goto err;
     444                 :            : 
     445                 :        720 :         s->pid = atoi(buf);
     446                 :            : 
     447                 :        360 :         p = strrchr(tok + 1, ')');
     448         [ +  - ]:        360 :         if (!p)
     449                 :            :                 goto err;
     450                 :        360 :         *tok = '\0';
     451                 :        360 :         *p = '\0';
     452                 :            : 
     453                 :        360 :         strncpy(s->comm, tok + 1, sizeof(s->comm));
     454                 :            : 
     455                 :        360 :         n = sscanf(p + 1,
     456                 :            :                " %c %d %d %d %d %d %u %lu %lu %lu %lu "
     457                 :            :                "%lu %lu %ld %ld %ld %ld %d %d %llu %lu %ld %lu %lu %lu %lu "
     458                 :            :                "%lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld "
     459                 :            :                "%lu %lu %lu %lu %lu %lu %lu %d",
     460                 :            :                 &s->state,
     461                 :            :                 &s->ppid,
     462                 :            :                 &s->pgid,
     463                 :            :                 &s->sid,
     464                 :            :                 &s->tty_nr,
     465                 :            :                 &s->tty_pgrp,
     466                 :            :                 &s->flags,
     467                 :            :                 &s->min_flt,
     468                 :            :                 &s->cmin_flt,
     469                 :            :                 &s->maj_flt,
     470                 :            :                 &s->cmaj_flt,
     471                 :            :                 &s->utime,
     472                 :            :                 &s->stime,
     473                 :            :                 &s->cutime,
     474                 :            :                 &s->cstime,
     475                 :            :                 &s->priority,
     476                 :            :                 &s->nice,
     477                 :            :                 &s->num_threads,
     478                 :            :                 &s->zero0,
     479                 :            :                 &s->start_time,
     480                 :            :                 &s->vsize,
     481                 :            :                 &s->mm_rss,
     482                 :            :                 &s->rsslim,
     483                 :            :                 &s->start_code,
     484                 :            :                 &s->end_code,
     485                 :            :                 &s->start_stack,
     486                 :            :                 &s->esp,
     487                 :            :                 &s->eip,
     488                 :            :                 &s->sig_pending,
     489                 :            :                 &s->sig_blocked,
     490                 :            :                 &s->sig_ignored,
     491                 :            :                 &s->sig_handled,
     492                 :            :                 &s->wchan,
     493                 :            :                 &s->zero1,
     494                 :            :                 &s->zero2,
     495                 :            :                 &s->exit_signal,
     496                 :            :                 &s->task_cpu,
     497                 :            :                 &s->rt_priority,
     498                 :            :                 &s->policy,
     499                 :            :                 &s->delayacct_blkio_ticks,
     500                 :            :                 &s->gtime,
     501                 :            :                 &s->cgtime,
     502                 :            :                 &s->start_data,
     503                 :            :                 &s->end_data,
     504                 :            :                 &s->start_brk,
     505                 :            :                 &s->arg_start,
     506                 :            :                 &s->arg_end,
     507                 :            :                 &s->env_start,
     508                 :            :                 &s->env_end,
     509                 :            :                 &s->exit_code);
     510         [ -  + ]:        360 :         if (n < 50)
     511                 :            :                 goto err;
     512                 :            : 
     513                 :            :         return 0;
     514                 :            : 
     515                 :            : err:
     516                 :          0 :         pr_err("Parsing %d's stat failed (#fields do not match)\n", pid);
     517                 :        360 :         return -1;
     518                 :            : }
     519                 :            : 
     520                 :        698 : static int ids_parse(char *str, unsigned int *arr)
     521                 :            : {
     522                 :            :         char *end;
     523                 :            : 
     524                 :        698 :         arr[0] = strtol(str, &end, 10);
     525                 :        698 :         arr[1] = strtol(end + 1, &end, 10);
     526                 :        698 :         arr[2] = strtol(end + 1, &end, 10);
     527                 :        698 :         arr[3] = strtol(end + 1, &end, 10);
     528         [ +  - ]:        698 :         if (*end != '\n')
     529                 :            :                 return -1;
     530                 :            :         else
     531                 :            :                 return 0;
     532                 :            : }
     533                 :            : 
     534                 :       1396 : static int cap_parse(char *str, unsigned int *res)
     535                 :            : {
     536                 :            :         int i, ret;
     537                 :            : 
     538         [ +  + ]:       4188 :         for (i = 0; i < PROC_CAP_SIZE; i++) {
     539                 :       2792 :                 ret = sscanf(str, "%08x", &res[PROC_CAP_SIZE - 1 - i]);
     540         [ +  - ]:       2792 :                 if (ret != 1)
     541                 :            :                         return -1;
     542                 :       2792 :                 str += 8;
     543                 :            :         }
     544                 :            : 
     545                 :            :         return 0;
     546                 :            : }
     547                 :            : 
     548                 :        349 : int parse_pid_status(pid_t pid, struct proc_status_creds *cr)
     549                 :            : {
     550                 :        349 :         int done = 0;
     551                 :            :         FILE *f;
     552                 :            :         char str[64];
     553                 :            : 
     554 [ -  + ][ +  - ]:        349 :         f = fopen_proc(pid, "status");
                 [ -  + ]
     555         [ +  - ]:        349 :         if (f == NULL) {
     556                 :          0 :                 pr_perror("Can't open proc status");
     557                 :            :                 return -1;
     558                 :            :         }
     559                 :            : 
     560 [ +  + ][ +  - ]:      11866 :         while (done < 6 && fgets(str, sizeof(str), f)) {
     561         [ +  + ]:      11517 :                 if (!strncmp(str, "Uid:", 4)) {
     562         [ +  - ]:        349 :                         if (ids_parse(str + 5, cr->uids))
     563                 :            :                                 goto err_parse;
     564                 :            : 
     565                 :        349 :                         done++;
     566                 :            :                 }
     567                 :            : 
     568         [ +  + ]:      11517 :                 if (!strncmp(str, "Gid:", 4)) {
     569         [ +  - ]:        349 :                         if (ids_parse(str + 5, cr->gids))
     570                 :            :                                 goto err_parse;
     571                 :            : 
     572                 :        349 :                         done++;
     573                 :            :                 }
     574                 :            : 
     575         [ +  + ]:      11517 :                 if (!strncmp(str, "CapInh:", 7)) {
     576         [ +  - ]:        349 :                         if (cap_parse(str + 8, cr->cap_inh))
     577                 :            :                                 goto err_parse;
     578                 :            : 
     579                 :        349 :                         done++;
     580                 :            :                 }
     581                 :            : 
     582         [ +  + ]:      11517 :                 if (!strncmp(str, "CapEff:", 7)) {
     583         [ +  - ]:        349 :                         if (cap_parse(str + 8, cr->cap_eff))
     584                 :            :                                 goto err_parse;
     585                 :            : 
     586                 :        349 :                         done++;
     587                 :            :                 }
     588                 :            : 
     589         [ +  + ]:      11517 :                 if (!strncmp(str, "CapPrm:", 7)) {
     590         [ +  - ]:        349 :                         if (cap_parse(str + 8, cr->cap_prm))
     591                 :            :                                 goto err_parse;
     592                 :            : 
     593                 :        349 :                         done++;
     594                 :            :                 }
     595                 :            : 
     596         [ +  + ]:      11517 :                 if (!strncmp(str, "CapBnd:", 7)) {
     597         [ +  - ]:        349 :                         if (cap_parse(str + 8, cr->cap_bnd))
     598                 :            :                                 goto err_parse;
     599                 :            : 
     600                 :        698 :                         done++;
     601                 :            :                 }
     602                 :            :         }
     603                 :            : 
     604         [ -  + ]:        349 :         if (done != 6) {
     605                 :            : err_parse:
     606                 :          0 :                 pr_err("Error parsing proc status file\n");
     607                 :          0 :                 fclose(f);
     608                 :            :                 return -1;
     609                 :            :         }
     610                 :            : 
     611                 :        349 :         fclose(f);
     612                 :            :         return 0;
     613                 :            : }
     614                 :            : 
     615                 :            : struct opt2flag {
     616                 :            :         char *opt;
     617                 :            :         unsigned flag;
     618                 :            : };
     619                 :            : 
     620                 :      10932 : static int do_opt2flag(char *opt, unsigned *flags,
     621                 :            :                 const struct opt2flag *opts, char *unknown)
     622                 :            : {
     623                 :            :         int i;
     624                 :            :         char *end;
     625                 :            : 
     626                 :            :         while (1) {
     627                 :      32252 :                 end = strchr(opt, ',');
     628         [ +  + ]:      32252 :                 if (end)
     629                 :      21320 :                         *end = '\0';
     630                 :            : 
     631         [ +  + ]:     126452 :                 for (i = 0; opts[i].opt != NULL; i++)
     632         [ +  + ]:     120231 :                         if (!strcmp(opts[i].opt, opt)) {
     633                 :      26031 :                                 (*flags) |= opts[i].flag;
     634                 :      26031 :                                 break;
     635                 :            :                         }
     636                 :            : 
     637         [ +  + ]:      32252 :                 if (opts[i].opt == NULL) {
     638         [ -  + ]:       6221 :                         if (!unknown) {
     639                 :          0 :                                 pr_err("Unknown option [%s]\n", opt);
     640                 :      10932 :                                 return -1;
     641                 :            :                         }
     642                 :            : 
     643                 :       6221 :                         strcpy(unknown, opt);
     644                 :       6221 :                         unknown += strlen(opt);
     645                 :       6221 :                         *unknown = ',';
     646                 :       6221 :                         unknown++;
     647                 :            :                 }
     648                 :            : 
     649         [ +  + ]:      32252 :                 if (!end) {
     650         [ +  + ]:      10932 :                         if (unknown)
     651                 :       5466 :                                 *unknown = '\0';
     652                 :            :                         break;
     653                 :            :                 } else
     654                 :      21320 :                         opt = end + 1;
     655                 :      21320 :         }
     656                 :            : 
     657                 :            :         return 0;
     658                 :            : }
     659                 :            : 
     660                 :       5466 : static int parse_mnt_flags(char *opt, unsigned *flags)
     661                 :            : {
     662                 :       5466 :         const struct opt2flag mnt_opt2flag[] = {
     663                 :            :                 { "rw", 0, },
     664                 :            :                 { "ro", MS_RDONLY, },
     665                 :            :                 { "nosuid", MS_NOSUID, },
     666                 :            :                 { "nodev", MS_NODEV, } ,
     667                 :            :                 { "noexec", MS_NOEXEC, },
     668                 :            :                 { "noatime", MS_NOATIME, },
     669                 :            :                 { "nodiratime", MS_NODIRATIME, },
     670                 :            :                 { "relatime", MS_RELATIME, },
     671                 :            :                 { },
     672                 :            :         };
     673                 :            : 
     674                 :       5466 :         return do_opt2flag(opt, flags, mnt_opt2flag, NULL);
     675                 :            : }
     676                 :            : 
     677                 :       5466 : static int parse_sb_opt(char *opt, unsigned *flags, char *uopt)
     678                 :            : {
     679                 :       5466 :         const struct opt2flag sb_opt2flag[] = {
     680                 :            :                 { "rw", 0, },
     681                 :            :                 { "ro", MS_RDONLY, },
     682                 :            :                 { "sync", MS_SYNC, },
     683                 :            :                 { "dirsync", MS_DIRSYNC, },
     684                 :            :                 { "mad", MS_MANDLOCK, },
     685                 :            :                 { },
     686                 :            :         };
     687                 :            : 
     688                 :       5466 :         return do_opt2flag(opt, flags, sb_opt2flag, uopt);
     689                 :            : }
     690                 :            : 
     691                 :       5466 : static int parse_mnt_opt(char *str, struct mount_info *mi, int *off)
     692                 :            : {
     693                 :       5466 :         char *istr = str, *end;
     694                 :            : 
     695                 :            :         while (1) {
     696                 :       5466 :                 end = strchr(str, ' ');
     697         [ -  + ]:       5466 :                 if (!end) {
     698                 :          0 :                         pr_err("Error parsing mount options\n");
     699                 :          0 :                         return -1;
     700                 :            :                 }
     701                 :            : 
     702                 :       5466 :                 *end = '\0';
     703         [ -  + ]:       5466 :                 if (!strncmp(str, "-", 1))
     704                 :            :                         break;
     705         [ #  # ]:          0 :                 else if (!strncmp(str, "shared:", 7)) {
     706                 :          0 :                         mi->flags |= MS_SHARED;
     707                 :          0 :                         mi->shared_id = atoi(str + 7);
     708         [ #  # ]:          0 :                 } else if (!strncmp(str, "master:", 7)) {
     709                 :          0 :                         mi->flags |= MS_SLAVE;
     710                 :          0 :                         mi->master_id = atoi(str + 7);
     711         [ #  # ]:          0 :                 } else if (!strncmp(str, "propagate_from:", 15)) {
     712                 :            :                         /* skip */;
     713         [ #  # ]:          0 :                 } else if (!strncmp(str, "unbindable", 11))
     714                 :          0 :                         mi->flags |= MS_UNBINDABLE;
     715                 :            :                 else {
     716                 :          0 :                         pr_err("Unknown option [%s]\n", str);
     717                 :          0 :                         return -1;
     718                 :            :                 }
     719                 :            : 
     720                 :          0 :                 str = end + 1;
     721                 :          0 :         }
     722                 :            : 
     723                 :       5466 :         *off = end - istr + 1;
     724                 :       5466 :         return 0;
     725                 :            : }
     726                 :            : 
     727                 :       5466 : static int parse_mountinfo_ent(char *str, struct mount_info *new)
     728                 :            : {
     729                 :            :         unsigned int kmaj, kmin;
     730                 :            :         int ret, n;
     731                 :            :         char *opt;
     732                 :            :         char *fstype;
     733                 :            : 
     734                 :       5466 :         ret = sscanf(str, "%i %i %u:%u %ms %ms %ms %n",
     735                 :            :                         &new->mnt_id, &new->parent_mnt_id,
     736                 :            :                         &kmaj, &kmin, &new->root, &new->mountpoint,
     737                 :            :                         &opt, &n);
     738         [ +  - ]:       5466 :         if (ret != 7)
     739                 :            :                 return -1;
     740                 :            : 
     741                 :       5466 :         new->s_dev = MKKDEV(kmaj, kmin);
     742                 :       5466 :         new->flags = 0;
     743         [ +  - ]:       5466 :         if (parse_mnt_flags(opt, &new->flags))
     744                 :            :                 return -1;
     745                 :            : 
     746                 :       5466 :         free(opt); /* after %ms scanf */
     747                 :            : 
     748                 :       5466 :         str += n;
     749         [ +  - ]:       5466 :         if (parse_mnt_opt(str, new, &n))
     750                 :            :                 return -1;
     751                 :            : 
     752                 :       5466 :         str += n;
     753                 :       5466 :         ret = sscanf(str, "%ms %ms %ms", &fstype, &new->source, &opt);
     754         [ +  - ]:       5466 :         if (ret != 3)
     755                 :            :                 return -1;
     756                 :            : 
     757                 :       5466 :         new->fstype = find_fstype_by_name(fstype);
     758                 :       5466 :         free(fstype);
     759                 :            : 
     760         [ -  + ]:       5466 :         new->options = xmalloc(strlen(opt));
     761         [ +  - ]:       5466 :         if (!new->options)
     762                 :            :                 return -1;
     763                 :            : 
     764         [ +  - ]:       5466 :         if (parse_sb_opt(opt, &new->flags, new->options))
     765                 :            :                 return -1;
     766                 :            : 
     767                 :       5466 :         free(opt);
     768                 :            : 
     769                 :            :         return 0;
     770                 :            : }
     771                 :            : 
     772                 :        291 : struct mount_info *parse_mountinfo(pid_t pid)
     773                 :            : {
     774                 :        291 :         struct mount_info *list = NULL;
     775                 :            :         FILE *f;
     776                 :            :         char str[1024];
     777                 :            : 
     778                 :        291 :         snprintf(str, sizeof(str), "/proc/%d/mountinfo", pid);
     779                 :        291 :         f = fopen(str, "r");
     780         [ +  - ]:        291 :         if (!f) {
     781                 :          0 :                 pr_perror("Can't open %d mountinfo", pid);
     782                 :            :                 return NULL;
     783                 :            :         }
     784                 :            : 
     785         [ +  + ]:       5757 :         while (fgets(str, sizeof(str), f)) {
     786                 :            :                 struct mount_info *new;
     787                 :            :                 int ret;
     788                 :            : 
     789         [ -  + ]:       5466 :                 new = xmalloc(sizeof(*new));
     790         [ +  - ]:       5466 :                 if (!new)
     791                 :            :                         goto err;
     792                 :            : 
     793                 :            :                 mnt_entry_init(new);
     794                 :            : 
     795                 :       5466 :                 ret = parse_mountinfo_ent(str, new);
     796         [ -  + ]:       5466 :                 if (ret < 0) {
     797                 :          0 :                         pr_err("Bad format in %d mountinfo\n", pid);
     798                 :          0 :                         goto err;
     799                 :            :                 }
     800                 :            : 
     801                 :       5466 :                 pr_info("\ttype %s source %s %x %s @ %s flags %x options %s\n",
     802                 :            :                                 new->fstype->name, new->source,
     803                 :            :                                 new->s_dev, new->root, new->mountpoint,
     804                 :            :                                 new->flags, new->options);
     805                 :            : 
     806                 :       5466 :                 new->next = list;
     807                 :       5466 :                 list = new;
     808                 :            :         }
     809                 :            : out:
     810                 :        291 :         fclose(f);
     811                 :            :         return list;
     812                 :            : 
     813                 :            : err:
     814         [ #  # ]:        291 :         while (list) {
     815                 :          0 :                 struct mount_info *next = list->next;
     816         [ #  # ]:          0 :                 xfree(list);
     817                 :          0 :                 list = next;
     818                 :            :         }
     819                 :            :         goto out;
     820                 :            : }
     821                 :            : 
     822                 :            : static char nybble(const char n)
     823                 :            : {
     824 [ +  + ][ +  + ]:         90 :         if (n >= '0' && n <= '9')
     825                 :         61 :                 return n - '0';
     826 [ -  + ][ -  + ]:         29 :         else if (n >= 'A' && n <= 'F')
     827                 :          0 :                 return n - ('A' - 10);
     828 [ +  + ][ +  + ]:         29 :         else if (n >= 'a' && n <= 'f')
     829                 :         19 :                 return n - ('a' - 10);
     830                 :            :         return 0;
     831                 :            : }
     832                 :            : 
     833                 :          5 : static void parse_fhandle_encoded(char *tok, FhEntry *fh)
     834                 :            : {
     835                 :          5 :         char *d = (char *)fh->handle;
     836                 :          5 :         int i = 0;
     837                 :            : 
     838                 :          5 :         memzero(d, pb_repeated_size(fh, handle));
     839                 :            : 
     840         [ -  + ]:          5 :         while (*tok == ' ')
     841                 :          0 :                 tok++;
     842                 :            : 
     843         [ +  - ]:         45 :         while (*tok) {
     844         [ +  - ]:         45 :                 if (i >= pb_repeated_size(fh, handle))
     845                 :            :                         break;
     846                 :        135 :                 d[i++] = (nybble(tok[0]) << 4) | nybble(tok[1]);
     847         [ +  + ]:         45 :                 if (tok[1])
     848                 :         40 :                         tok += 2;
     849                 :            :                 else
     850                 :            :                         break;
     851                 :            :         }
     852                 :          5 : }
     853                 :            : 
     854                 :            : #define fdinfo_field(str, field)        !strncmp(str, field":", sizeof(field))
     855                 :            : 
     856                 :         12 : int parse_fdinfo(int fd, int type,
     857                 :            :                 int (*cb)(union fdinfo_entries *e, void *arg), void *arg)
     858                 :            : {
     859                 :            :         FILE *f;
     860                 :            :         char str[256];
     861                 :         12 :         bool entry_met = false;
     862                 :            : 
     863                 :         12 :         sprintf(str, "/proc/self/fdinfo/%d", fd);
     864                 :         12 :         f = fopen(str, "r");
     865         [ +  - ]:         12 :         if (!f) {
     866                 :          0 :                 pr_perror("Can't open fdinfo to parse");
     867                 :            :                 return -1;
     868                 :            :         }
     869                 :            : 
     870         [ +  + ]:         50 :         while (fgets(str, sizeof(str), f)) {
     871                 :            :                 int ret;
     872                 :            :                 union fdinfo_entries entry;
     873                 :            : 
     874 [ +  + ][ -  + ]:         38 :                 if (fdinfo_field(str, "pos") || fdinfo_field(str, "counter"))
     875                 :         12 :                         continue;
     876                 :            : 
     877         [ +  + ]:         26 :                 if (fdinfo_field(str, "eventfd-count")) {
     878                 :          3 :                         eventfd_file_entry__init(&entry.efd);
     879                 :            : 
     880         [ +  - ]:          3 :                         if (type != FD_TYPES__EVENTFD)
     881                 :            :                                 goto parse_err;
     882                 :          3 :                         ret = sscanf(str, "eventfd-count: %lx",
     883                 :            :                                         &entry.efd.counter);
     884         [ +  - ]:          3 :                         if (ret != 1)
     885                 :            :                                 goto parse_err;
     886                 :          3 :                         ret = cb(&entry, arg);
     887         [ +  - ]:          3 :                         if (ret)
     888                 :            :                                 return ret;
     889                 :            : 
     890                 :          3 :                         entry_met = true;
     891                 :          3 :                         continue;
     892                 :            :                 }
     893         [ +  + ]:         23 :                 if (fdinfo_field(str, "tfd")) {
     894                 :          3 :                         eventpoll_tfd_entry__init(&entry.epl);
     895                 :            : 
     896         [ +  - ]:          3 :                         if (type != FD_TYPES__EVENTPOLL)
     897                 :            :                                 goto parse_err;
     898                 :          3 :                         ret = sscanf(str, "tfd: %d events: %x data: %lx",
     899                 :            :                                         &entry.epl.tfd, &entry.epl.events, &entry.epl.data);
     900         [ +  - ]:          3 :                         if (ret != 3)
     901                 :            :                                 goto parse_err;
     902                 :          3 :                         ret = cb(&entry, arg);
     903         [ +  - ]:          3 :                         if (ret)
     904                 :            :                                 return ret;
     905                 :            : 
     906                 :          3 :                         entry_met = true;
     907                 :          3 :                         continue;
     908                 :            :                 }
     909         [ +  + ]:         20 :                 if (fdinfo_field(str, "sigmask")) {
     910                 :          3 :                         signalfd_entry__init(&entry.sfd);
     911                 :            : 
     912         [ +  - ]:          3 :                         if (type != FD_TYPES__SIGNALFD)
     913                 :            :                                 goto parse_err;
     914                 :          3 :                         ret = sscanf(str, "sigmask: %Lx",
     915                 :            :                                         (unsigned long long *)&entry.sfd.sigmask);
     916         [ +  - ]:          3 :                         if (ret != 1)
     917                 :            :                                 goto parse_err;
     918                 :          3 :                         ret = cb(&entry, arg);
     919         [ +  - ]:          3 :                         if (ret)
     920                 :            :                                 return ret;
     921                 :            : 
     922                 :          3 :                         entry_met = true;
     923                 :          3 :                         continue;
     924                 :            :                 }
     925         [ +  + ]:         17 :                 if (fdinfo_field(str, "inotify wd")) {
     926                 :          5 :                         FhEntry f_handle = FH_ENTRY__INIT;
     927                 :            :                         int hoff;
     928                 :            : 
     929                 :          5 :                         inotify_wd_entry__init(&entry.ify);
     930                 :          5 :                         entry.ify.f_handle = &f_handle;
     931                 :            : 
     932         [ +  - ]:          5 :                         if (type != FD_TYPES__INOTIFY)
     933                 :            :                                 goto parse_err;
     934                 :          5 :                         ret = sscanf(str,
     935                 :            :                                         "inotify wd:%x ino:%lx sdev:%x "
     936                 :            :                                         "mask:%x ignored_mask:%x "
     937                 :            :                                         "fhandle-bytes:%x fhandle-type:%x "
     938                 :            :                                         "f_handle: %n",
     939                 :            :                                         &entry.ify.wd, &entry.ify.i_ino, &entry.ify.s_dev,
     940                 :            :                                         &entry.ify.mask, &entry.ify.ignored_mask,
     941                 :            :                                         &entry.ify.f_handle->bytes, &entry.ify.f_handle->type,
     942                 :            :                                         &hoff);
     943         [ +  - ]:          5 :                         if (ret != 7)
     944                 :            :                                 goto parse_err;
     945                 :            : 
     946                 :          5 :                         f_handle.n_handle = FH_ENTRY_SIZES__min_entries;
     947         [ -  + ]:          5 :                         f_handle.handle = xmalloc(pb_repeated_size(&f_handle, handle));
     948         [ +  - ]:          5 :                         if (!f_handle.handle)
     949                 :            :                                 return -1;
     950                 :            : 
     951                 :          5 :                         parse_fhandle_encoded(str + hoff, entry.ify.f_handle);
     952                 :            : 
     953                 :          5 :                         ret = cb(&entry, arg);
     954                 :            : 
     955         [ +  - ]:          5 :                         xfree(f_handle.handle);
     956                 :            : 
     957         [ +  - ]:          5 :                         if (ret)
     958                 :            :                                 return ret;
     959                 :            : 
     960                 :          5 :                         entry_met = true;
     961                 :         38 :                         continue;
     962                 :            :                 }
     963                 :            :         }
     964                 :            : 
     965                 :         12 :         fclose(f);
     966                 :            : 
     967         [ -  + ]:         12 :         if (entry_met)
     968                 :            :                 return 0;
     969                 :            :         /*
     970                 :            :          * An eventpoll/inotify file may have no target fds set thus
     971                 :            :          * resulting in no tfd: lines in proc. This is normal.
     972                 :            :          */
     973         [ #  # ]:          0 :         if (type == FD_TYPES__EVENTPOLL || type == FD_TYPES__INOTIFY)
     974                 :            :                 return 0;
     975                 :            : 
     976                 :          0 :         pr_err("No records of type %d found in fdinfo file\n", type);
     977                 :            : parse_err:
     978                 :         12 :         pr_perror("%s: error parsing [%s] for %d\n", __func__, str, type);
     979                 :            :         return -1;
     980                 :         10 : }

Generated by: LCOV version 1.9