LCOV - code coverage report
Current view: top level - home/snorch/criu - proc_parse.c (source / functions) Hit Total Coverage
Test: coverage3.info Lines: 504 615 82.0 %
Date: 2014-04-22 Functions: 27 27 100.0 %
Branches: 352 543 64.8 %

           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 "asm/types.h"
      13                 :            : #include "list.h"
      14                 :            : #include "util.h"
      15                 :            : #include "mount.h"
      16                 :            : #include "mman.h"
      17                 :            : #include "cpu.h"
      18                 :            : #include "file-lock.h"
      19                 :            : #include "pstree.h"
      20                 :            : #include "fsnotify.h"
      21                 :            : #include "posix-timer.h"
      22                 :            : #include "kerndat.h"
      23                 :            : #include "vdso.h"
      24                 :            : #include "vma.h"
      25                 :            : 
      26                 :            : #include "proc_parse.h"
      27                 :            : #include "protobuf.h"
      28                 :            : #include "protobuf/fdinfo.pb-c.h"
      29                 :            : 
      30                 :            : #include <stdlib.h>
      31                 :            : 
      32                 :            : struct buffer {
      33                 :            :         char buf[PAGE_SIZE];
      34                 :            :         char end; /* '\0' */
      35                 :            : };
      36                 :            : 
      37                 :            : static struct buffer __buf;
      38                 :            : static char *buf = __buf.buf;
      39                 :            : 
      40                 :            : #define BUF_SIZE sizeof(__buf.buf)
      41                 :            : 
      42                 :       2804 : int parse_cpuinfo_features(int (*handler)(char *tok))
      43                 :            : {
      44                 :            :         FILE *cpuinfo;
      45                 :            : 
      46                 :       2804 :         cpuinfo = fopen("/proc/cpuinfo", "r");
      47         [ +  - ]:       2804 :         if (!cpuinfo) {
      48                 :          0 :                 pr_perror("Can't open cpuinfo file");
      49                 :          0 :                 return -1;
      50                 :            :         }
      51                 :            : 
      52         [ +  + ]:     294420 :         while (fgets(buf, BUF_SIZE, cpuinfo)) {
      53                 :            :                 char *tok;
      54                 :            : 
      55         [ +  + ]:     291616 :                 if (strncmp(buf, "flags\t\t:", 8))
      56                 :     280400 :                         continue;
      57                 :            : 
      58         [ +  + ]:    1233760 :                 for (tok = strtok(buf, " \t\n"); tok;
      59                 :     942144 :                      tok = strtok(NULL, " \t\n")) {
      60         [ +  - ]:     942144 :                         if (handler(tok) < 0)
      61                 :            :                                 break;
      62                 :            :                 }
      63                 :            :         }
      64                 :            : 
      65                 :       2804 :         fclose(cpuinfo);
      66                 :       2804 :         return 0;
      67                 :            : }
      68                 :            : 
      69                 :            : /* check the @line starts with "%lx-%lx" format */
      70                 :    2489344 : static bool is_vma_range_fmt(char *line)
      71                 :            : {
      72                 :            : #define ____is_vma_addr_char(__c)               \
      73                 :            :         (((__c) <= '9' && (__c) >= '0') ||        \
      74                 :            :         ((__c) <= 'f' && (__c) >= 'a'))
      75                 :            : 
      76 [ +  - ][ +  + ]:    4315200 :         while (*line && ____is_vma_addr_char(*line))
      77                 :    1825856 :                 line++;
      78                 :            : 
      79         [ +  + ]:    2489344 :         if (*line++ != '-')
      80                 :            :                 return false;
      81                 :            : 
      82 [ +  - ][ +  + ]:    1981440 :         while (*line && ____is_vma_addr_char(*line))
      83                 :    1825856 :                 line++;
      84                 :            : 
      85         [ +  - ]:     155584 :         if (*line++ != ' ')
      86                 :            :                 return false;
      87                 :            : 
      88                 :     155584 :         return true;
      89                 :            : #undef ____is_vma_addr_char
      90                 :            : }
      91                 :            : 
      92                 :     311168 : static int parse_vmflags(char *buf, struct vma_area *vma_area)
      93                 :            : {
      94                 :            :         char *tok;
      95                 :            :         bool shared = false;
      96                 :            :         bool maywrite = false;
      97                 :            : 
      98         [ +  - ]:     155584 :         if (!buf[0])
      99                 :            :                 return 0;
     100                 :            : 
     101                 :     155584 :         tok = strtok(buf, " \n");
     102         [ +  - ]:     155584 :         if (!tok)
     103                 :            :                 return 0;
     104                 :            : 
     105                 :            : #define _vmflag_match(_t, _s) (_t[0] == _s[0] && _t[1] == _s[1])
     106                 :            : 
     107                 :            :         do {
     108                 :            :                 /* open() block */
     109 [ +  + ][ +  + ]:     905726 :                 if (_vmflag_match(tok, "sh"))
     110                 :            :                         shared = true;
     111 [ +  + ][ +  + ]:     905206 :                 else if (_vmflag_match(tok, "mw"))
     112                 :            :                         maywrite = true;
     113                 :            : 
     114                 :            :                 /* mmap() block */
     115 [ +  + ][ +  - ]:     905726 :                 if (_vmflag_match(tok, "gd"))
     116                 :       3776 :                         vma_area->e->flags |= MAP_GROWSDOWN;
     117 [ +  + ][ +  - ]:     901950 :                 else if (_vmflag_match(tok, "lo"))
     118                 :         16 :                         vma_area->e->flags |= MAP_LOCKED;
     119 [ +  + ][ +  - ]:     901934 :                 else if (_vmflag_match(tok, "nr"))
     120                 :       1264 :                         vma_area->e->flags |= MAP_NORESERVE;
     121 [ +  + ][ -  + ]:     900670 :                 else if (_vmflag_match(tok, "ht"))
     122                 :          0 :                         vma_area->e->flags |= MAP_HUGETLB;
     123                 :            : 
     124                 :            :                 /* madvise() block */
     125 [ +  + ][ +  + ]:     905726 :                 if (_vmflag_match(tok, "sr"))
     126                 :         16 :                         vma_area->e->madv |= (1ul << MADV_SEQUENTIAL);
     127 [ +  + ][ -  + ]:     905710 :                 else if (_vmflag_match(tok, "rr"))
     128                 :          0 :                         vma_area->e->madv |= (1ul << MADV_RANDOM);
     129 [ +  + ][ +  + ]:     905710 :                 else if (_vmflag_match(tok, "dc"))
     130                 :         16 :                         vma_area->e->madv |= (1ul << MADV_DONTFORK);
     131 [ +  + ][ +  + ]:     905694 :                 else if (_vmflag_match(tok, "dd"))
     132                 :         16 :                         vma_area->e->madv |= (1ul << MADV_DONTDUMP);
     133 [ +  + ][ +  + ]:     905678 :                 else if (_vmflag_match(tok, "mg"))
     134                 :         16 :                         vma_area->e->madv |= (1ul << MADV_MERGEABLE);
     135 [ +  + ][ +  - ]:     905662 :                 else if (_vmflag_match(tok, "hg"))
     136                 :         16 :                         vma_area->e->madv |= (1ul << MADV_HUGEPAGE);
     137 [ +  + ][ -  + ]:     905646 :                 else if (_vmflag_match(tok, "nh"))
     138                 :          0 :                         vma_area->e->madv |= (1ul << MADV_NOHUGEPAGE);
     139                 :            : 
     140                 :            :                 /*
     141                 :            :                  * Anything else is just ignored.
     142                 :            :                  */
     143         [ +  + ]:     905726 :         } while ((tok = strtok(NULL, " \n")));
     144                 :            : 
     145                 :            : #undef _vmflag_match
     146                 :            : 
     147         [ +  + ]:     155584 :         if (shared && maywrite)
     148                 :        520 :                 vma_area->e->fdflags = O_RDWR;
     149                 :            :         else
     150                 :     155064 :                 vma_area->e->fdflags = O_RDONLY;
     151                 :     155584 :         vma_area->e->has_fdflags = true;
     152                 :            : 
     153         [ +  + ]:     155584 :         if (vma_area->e->madv)
     154                 :         80 :                 vma_area->e->has_madv = true;
     155                 :            : 
     156                 :            :         return 0;
     157                 :            : }
     158                 :            : 
     159                 :            : static inline int is_anon_shmem_map(dev_t dev)
     160                 :            : {
     161                 :      15816 :         return kerndat_shmem_dev == dev;
     162                 :            : }
     163                 :            : 
     164                 :            : struct vma_file_info {
     165                 :            :         int dev_maj;
     166                 :            :         int dev_min;
     167                 :            :         unsigned long ino;
     168                 :            :         struct vma_area *vma;
     169                 :            : };
     170                 :            : 
     171                 :            : static inline int vfi_equal(struct vma_file_info *a, struct vma_file_info *b)
     172                 :            : {
     173                 :     303840 :         return ((a->ino ^ b->ino) |
     174                 :     303840 :                         (a->dev_maj ^ b->dev_maj) |
     175                 :     151920 :                         (a->dev_min ^ b->dev_min)) == 0;
     176                 :            : }
     177                 :            : 
     178                 :     155584 : static int vma_get_mapfile(struct vma_area *vma, DIR *mfd,
     179                 :     151920 :                 struct vma_file_info *vfi, struct vma_file_info *prev_vfi)
     180                 :            : {
     181                 :            :         char path[32];
     182                 :            : 
     183         [ +  - ]:     155584 :         if (!mfd)
     184                 :            :                 return 0;
     185                 :            : 
     186 [ +  + ][ +  + ]:     155584 :         if (prev_vfi->vma && vfi_equal(vfi, prev_vfi)) {
     187                 :            :                 struct vma_area *prev = prev_vfi->vma;
     188                 :            : 
     189                 :            :                 /*
     190                 :            :                  * If vfi is equal (!) and negative @vm_file_fd --
     191                 :            :                  * we have nothing to borrow for sure.
     192                 :            :                  */
     193         [ +  + ]:     128912 :                 if (prev->vm_file_fd < 0)
     194                 :            :                         return 0;
     195                 :            : 
     196                 :      23712 :                 pr_debug("vma %"PRIx64" borrows vfi from previous %"PRIx64"\n",
     197                 :            :                                 vma->e->start, prev->e->start);
     198                 :      23712 :                 vma->vm_file_fd = prev->vm_file_fd;
     199         [ -  + ]:      23712 :                 if (prev->e->status & VMA_AREA_SOCKET)
     200                 :          0 :                         vma->e->status |= VMA_AREA_SOCKET | VMA_AREA_REGULAR;
     201                 :      23712 :                 vma->file_borrowed = true;
     202                 :            : 
     203                 :      23712 :                 return 0;
     204                 :            :         }
     205                 :            : 
     206                 :            :         /* Figure out if it's file mapping */
     207                 :      26672 :         snprintf(path, sizeof(path), "%"PRIx64"-%"PRIx64, vma->e->start, vma->e->end);
     208                 :            : 
     209                 :            :         /*
     210                 :            :          * Note that we "open" it in dumper process space
     211                 :            :          * so later we might refer to it via /proc/self/fd/vm_file_fd
     212                 :            :          * if needed.
     213                 :            :          */
     214                 :      26672 :         vma->vm_file_fd = openat(dirfd(mfd), path, O_RDONLY);
     215         [ +  + ]:      26672 :         if (vma->vm_file_fd < 0) {
     216         [ -  + ]:      10856 :                 if (errno == ENXIO) {
     217                 :            :                         struct stat buf;
     218                 :            : 
     219         [ #  # ]:          0 :                         if (fstatat(dirfd(mfd), path, &buf, 0))
     220                 :          0 :                                 return -1;
     221                 :            : 
     222         [ #  # ]:          0 :                         if (!S_ISSOCK(buf.st_mode))
     223                 :            :                                 return -1;
     224                 :            : 
     225                 :          0 :                         pr_info("Found socket %"PRIu64" mapping @%"PRIx64"\n",
     226                 :            :                                         buf.st_ino, vma->e->start);
     227                 :          0 :                         vma->e->status |= VMA_AREA_SOCKET | VMA_AREA_REGULAR;
     228                 :          0 :                         vma->vm_socket_id = buf.st_ino;
     229         [ +  - ]:      10856 :                 } else if (errno != ENOENT)
     230                 :            :                         return -1;
     231                 :            :         }
     232                 :            : 
     233                 :            :         return 0;
     234                 :            : }
     235                 :            : 
     236                 :        347 : int parse_self_maps_lite(struct vm_area_list *vms)
     237                 :            : {
     238                 :            :         FILE *maps;
     239                 :            : 
     240                 :            :         vm_area_list_init(vms);
     241                 :            : 
     242                 :        347 :         maps = fopen("/proc/self/maps", "r");
     243         [ +  - ]:        347 :         if (maps == NULL) {
     244                 :          0 :                 pr_perror("Can't open self maps");
     245                 :          0 :                 return -1;
     246                 :            :         }
     247                 :            : 
     248         [ +  + ]:      37335 :         while (fgets(buf, BUF_SIZE, maps) != NULL) {
     249                 :            :                 struct vma_area *vma;
     250                 :            :                 char *end;
     251                 :            : 
     252                 :      36988 :                 vma = alloc_vma_area();
     253         [ -  + ]:      36988 :                 if (!vma) {
     254                 :          0 :                         fclose(maps);
     255                 :          0 :                         return -1;
     256                 :            :                 }
     257                 :            : 
     258                 :      36988 :                 vma->e->start = strtoul(buf, &end, 16);
     259                 :      36988 :                 vma->e->end = strtoul(end + 1, NULL, 16);
     260                 :      36988 :                 list_add_tail(&vma->list, &vms->h);
     261                 :      36988 :                 vms->nr++;
     262                 :            : 
     263                 :      36988 :                 pr_debug("Parsed %"PRIx64"-%"PRIx64" vma\n", vma->e->start, vma->e->end);
     264                 :            :         }
     265                 :            : 
     266                 :        347 :         fclose(maps);
     267                 :        347 :         return 0;
     268                 :            : }
     269                 :            : 
     270                 :            : static char smaps_buf[PAGE_SIZE];
     271                 :            : 
     272                 :       3664 : int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_files)
     273                 :            : {
     274                 :            :         struct vma_area *vma_area = NULL;
     275                 :            :         unsigned long start, end, pgoff;
     276                 :            :         bool prev_growsdown = false;
     277                 :            :         char r, w, x, s;
     278                 :            :         int ret = -1;
     279                 :            :         struct vma_file_info vfi;
     280                 :       3664 :         struct vma_file_info prev_vfi = {};
     281                 :            : 
     282                 :            :         DIR *map_files_dir = NULL;
     283                 :            :         FILE *smaps = NULL;
     284                 :            : 
     285                 :       3664 :         vma_area_list->nr = 0;
     286                 :       3664 :         vma_area_list->longest = 0;
     287                 :       3664 :         vma_area_list->priv_size = 0;
     288                 :       3664 :         INIT_LIST_HEAD(&vma_area_list->h);
     289                 :            : 
     290 [ -  + ][ +  - ]:       3664 :         smaps = fopen_proc(pid, "smaps");
                 [ -  + ]
     291         [ +  - ]:       3664 :         if (!smaps)
     292                 :            :                 goto err;
     293                 :            : 
     294                 :       3664 :         setvbuf(smaps, smaps_buf, _IOFBF, sizeof(smaps_buf));
     295                 :            : 
     296         [ +  - ]:       3664 :         if (use_map_files) {
     297 [ -  + ][ +  - ]:       3664 :                 map_files_dir = opendir_proc(pid, "map_files");
                 [ -  + ]
     298         [ +  - ]:    2493008 :                 if (!map_files_dir) /* old kernel? */
     299                 :            :                         goto err;
     300                 :            :         }
     301                 :            : 
     302                 :            :         while (1) {
     303                 :            :                 int num;
     304                 :            :                 char file_path[6];
     305                 :            :                 bool eof;
     306                 :            : 
     307                 :    4986016 :                 eof = (fgets(buf, BUF_SIZE, smaps) == NULL);
     308                 :            : 
     309 [ +  + ][ +  + ]:    2493008 :                 if (!eof && !is_vma_range_fmt(buf)) {
     310         [ -  + ]:    2333760 :                         if (!strncmp(buf, "Nonlinear", 9)) {
     311         [ #  # ]:          0 :                                 BUG_ON(!vma_area);
     312                 :          0 :                                 pr_err("Nonlinear mapping found %016"PRIx64"-%016"PRIx64"\n",
     313                 :            :                                        vma_area->e->start, vma_area->e->end);
     314                 :            :                                 /*
     315                 :            :                                  * VMA is already on list and will be
     316                 :            :                                  * freed later as list get destroyed.
     317                 :            :                                  */
     318                 :            :                                 vma_area = NULL;
     319                 :          0 :                                 goto err;
     320         [ +  + ]:    2333760 :                         } else if (!strncmp(buf, "VmFlags: ", 9)) {
     321         [ -  + ]:     155584 :                                 BUG_ON(!vma_area);
     322         [ +  - ]:     155584 :                                 if (parse_vmflags(&buf[9], vma_area))
     323                 :            :                                         goto err;
     324                 :    2337424 :                                 continue;
     325                 :            :                         } else
     326                 :    2178176 :                                 continue;
     327                 :            :                 }
     328                 :            : 
     329         [ +  + ]:     159248 :                 if (vma_area) {
     330                 :            :                         /* If we've split the stack vma, only the lowest one has the guard page. */
     331 [ +  + ][ +  + ]:     155584 :                         if ((vma_area->e->flags & MAP_GROWSDOWN) && !prev_growsdown)
     332                 :       3744 :                                 vma_area->e->start -= PAGE_SIZE; /* Guard page */
     333                 :     155584 :                         prev_growsdown = (bool)(vma_area->e->flags & MAP_GROWSDOWN);
     334                 :            : 
     335                 :     155584 :                         list_add_tail(&vma_area->list, &vma_area_list->h);
     336                 :     155584 :                         vma_area_list->nr++;
     337         [ +  + ]:     155584 :                         if (privately_dump_vma(vma_area)) {
     338                 :            :                                 unsigned long pages;
     339                 :            : 
     340                 :     151400 :                                 pages = vma_area_len(vma_area) / PAGE_SIZE;
     341                 :     151400 :                                 vma_area_list->priv_size += pages;
     342                 :     151400 :                                 vma_area_list->longest = max(vma_area_list->longest, pages);
     343                 :            :                         }
     344                 :            : 
     345                 :     155584 :                         prev_vfi = vfi;
     346                 :     155584 :                         prev_vfi.vma = vma_area;
     347                 :            :                 }
     348                 :            : 
     349         [ +  + ]:     159248 :                 if (eof)
     350                 :            :                         break;
     351                 :            : 
     352                 :     155584 :                 vma_area = alloc_vma_area();
     353         [ +  - ]:     155584 :                 if (!vma_area)
     354                 :            :                         goto err;
     355                 :            : 
     356                 :            :                 memset(file_path, 0, 6);
     357                 :     155584 :                 num = sscanf(buf, "%lx-%lx %c%c%c%c %lx %x:%x %lu %5s",
     358                 :            :                              &start, &end, &r, &w, &x, &s, &pgoff,
     359                 :            :                              &vfi.dev_maj, &vfi.dev_min, &vfi.ino, file_path);
     360         [ -  + ]:     155584 :                 if (num < 10) {
     361                 :          0 :                         pr_err("Can't parse: %s\n", buf);
     362                 :          0 :                         goto err;
     363                 :            :                 }
     364                 :            : 
     365                 :     155584 :                 vma_area->e->start        = start;
     366                 :     155584 :                 vma_area->e->end  = end;
     367                 :     155584 :                 vma_area->e->pgoff        = pgoff;
     368                 :     155584 :                 vma_area->e->prot = PROT_NONE;
     369                 :            : 
     370         [ +  - ]:     155584 :                 if (vma_get_mapfile(vma_area, map_files_dir, &vfi, &prev_vfi))
     371                 :            :                         goto err_bogus_mapfile;
     372                 :            : 
     373         [ +  + ]:     155584 :                 if (r == 'r')
     374                 :     107290 :                         vma_area->e->prot |= PROT_READ;
     375         [ +  + ]:     155584 :                 if (w == 'w')
     376                 :      76907 :                         vma_area->e->prot |= PROT_WRITE;
     377         [ +  + ]:     155584 :                 if (x == 'x')
     378                 :      50777 :                         vma_area->e->prot |= PROT_EXEC;
     379                 :            : 
     380         [ +  + ]:     155584 :                 if (s == 's')
     381                 :        520 :                         vma_area->e->flags = MAP_SHARED;
     382         [ +  - ]:     155064 :                 else if (s == 'p')
     383                 :     155064 :                         vma_area->e->flags = MAP_PRIVATE;
     384                 :            :                 else {
     385                 :          0 :                         pr_err("Unexpected VMA met (%c)\n", s);
     386                 :          0 :                         goto err;
     387                 :            :                 }
     388                 :            : 
     389         [ -  + ]:     155584 :                 if (vma_area->e->status != 0) {
     390                 :          0 :                         continue;
     391 [ +  + ][ -  + ]:     155584 :                 } else if (strstr(buf, "[vsyscall]") || strstr(buf, "[vectors]")) {
     392                 :       3664 :                         vma_area->e->status |= VMA_AREA_VSYSCALL;
     393         [ +  + ]:     151920 :                 } else if (strstr(buf, "[vdso]")) {
     394                 :       3664 :                         vma_area->e->status |= VMA_AREA_REGULAR;
     395         [ +  - ]:       3664 :                         if ((vma_area->e->prot & VDSO_PROT) == VDSO_PROT)
     396                 :       3664 :                                 vma_area->e->status |= VMA_AREA_VDSO;
     397         [ +  + ]:     148256 :                 } else if (strstr(buf, "[heap]")) {
     398                 :       2824 :                         vma_area->e->status |= VMA_AREA_REGULAR | VMA_AREA_HEAP;
     399                 :            :                 } else {
     400                 :     145432 :                         vma_area->e->status = VMA_AREA_REGULAR;
     401                 :            :                 }
     402                 :            : 
     403                 :            :                 /*
     404                 :            :                  * Some mapping hints for restore, we save this on
     405                 :            :                  * disk and restore might need to analyze it.
     406                 :            :                  */
     407         [ +  + ]:     155584 :                 if (vma_area->file_borrowed) {
     408                 :      23712 :                         struct vma_area *prev = prev_vfi.vma;
     409                 :            : 
     410                 :            :                         /*
     411                 :            :                          * Pick-up flags that might be set in the branch below.
     412                 :            :                          * Status is copied as-is as it should be zero here,
     413                 :            :                          * and have full match with the previous.
     414                 :            :                          */
     415                 :      23712 :                         vma_area->e->flags |= (prev->e->flags & MAP_ANONYMOUS);
     416                 :      23712 :                         vma_area->e->status = prev->e->status;
     417                 :      23712 :                         vma_area->e->shmid = prev->e->shmid;
     418                 :      23712 :                         vma_area->st = prev->st;
     419         [ +  + ]:     131872 :                 } else if (vma_area->vm_file_fd >= 0) {
     420                 :            :                         struct stat *st_buf;
     421                 :            : 
     422         [ -  + ]:      15816 :                         st_buf = vma_area->st = xmalloc(sizeof(*st_buf));
     423         [ +  - ]:      15816 :                         if (!st_buf)
     424                 :            :                                 goto err;
     425                 :            : 
     426         [ -  + ]:      15816 :                         if (fstat(vma_area->vm_file_fd, st_buf) < 0) {
     427                 :          0 :                                 pr_perror("Failed fstat on %d's map %lu", pid, start);
     428                 :          0 :                                 goto err;
     429                 :            :                         }
     430                 :            : 
     431 [ -  + ][ #  # ]:      15816 :                         if (!S_ISREG(st_buf->st_mode) &&
     432         [ #  # ]:          0 :                             !(S_ISCHR(st_buf->st_mode) && st_buf->st_rdev == DEVZERO)) {
     433                 :          0 :                                 pr_err("Can't handle non-regular mapping on %d's map %lu\n", pid, start);
     434                 :          0 :                                 goto err;
     435                 :            :                         }
     436                 :            : 
     437                 :            :                         /*
     438                 :            :                          * /dev/zero stands for anon-shared mapping
     439                 :            :                          * otherwise it's some file mapping.
     440                 :            :                          */
     441         [ +  + ]:      15816 :                         if (is_anon_shmem_map(st_buf->st_dev)) {
     442         [ +  - ]:        392 :                                 if (!(vma_area->e->flags & MAP_SHARED))
     443                 :            :                                         goto err_bogus_mapping;
     444                 :        392 :                                 vma_area->e->flags  |= MAP_ANONYMOUS;
     445                 :        392 :                                 vma_area->e->status |= VMA_ANON_SHARED;
     446                 :        392 :                                 vma_area->e->shmid = st_buf->st_ino;
     447                 :            : 
     448         [ +  + ]:        392 :                                 if (!strcmp(file_path, "/SYSV")) {
     449                 :         24 :                                         pr_info("path: %s\n", file_path);
     450                 :         24 :                                         vma_area->e->status |= VMA_AREA_SYSVIPC;
     451                 :            :                                 }
     452                 :            :                         } else {
     453         [ +  + ]:      15424 :                                 if (vma_area->e->flags & MAP_PRIVATE)
     454                 :      15344 :                                         vma_area->e->status |= VMA_FILE_PRIVATE;
     455                 :            :                                 else
     456                 :         80 :                                         vma_area->e->status |= VMA_FILE_SHARED;
     457                 :            :                         }
     458                 :            :                 } else {
     459                 :            :                         /*
     460                 :            :                          * No file but mapping -- anonymous one.
     461                 :            :                          */
     462         [ -  + ]:     116056 :                         if (vma_area->e->flags & MAP_SHARED) {
     463                 :          0 :                                 vma_area->e->status |= VMA_ANON_SHARED;
     464                 :          0 :                                 vma_area->e->shmid = vfi.ino;
     465                 :            :                         } else {
     466                 :     116056 :                                 vma_area->e->status |= VMA_ANON_PRIVATE;
     467                 :            :                         }
     468                 :     155584 :                         vma_area->e->flags  |= MAP_ANONYMOUS;
     469                 :            :                 }
     470                 :            :         }
     471                 :            : 
     472                 :            :         vma_area = NULL;
     473                 :            :         ret = 0;
     474                 :            : 
     475                 :            : err:
     476         [ +  - ]:       3664 :         if (smaps)
     477                 :       3664 :                 fclose(smaps);
     478                 :            : 
     479         [ +  - ]:       3664 :         if (map_files_dir)
     480                 :       3664 :                 closedir(map_files_dir);
     481                 :            : 
     482         [ -  + ]:       3664 :         xfree(vma_area);
     483                 :       3664 :         return ret;
     484                 :            : 
     485                 :            : err_bogus_mapping:
     486                 :          0 :         pr_err("Bogus mapping 0x%"PRIx64"-0x%"PRIx64" (flags: %#x vm_file_fd: %d)\n",
     487                 :            :                vma_area->e->start, vma_area->e->end,
     488                 :            :                vma_area->e->flags, vma_area->vm_file_fd);
     489                 :          0 :         goto err;
     490                 :            : 
     491                 :            : err_bogus_mapfile:
     492                 :          0 :         pr_perror("Can't open %d's mapfile link %lx", pid, start);
     493                 :          0 :         goto err;
     494                 :            : }
     495                 :            : 
     496                 :       5657 : int parse_pid_stat_small(pid_t pid, struct proc_pid_stat_small *s)
     497                 :            : {
     498                 :            :         char *tok, *p;
     499                 :            :         int fd;
     500                 :            :         int n;
     501                 :            : 
     502         [ +  + ]:       5657 :         fd = open_proc(pid, "stat");
     503         [ +  + ]:       5657 :         if (fd < 0)
     504                 :            :                 return -1;
     505                 :            : 
     506                 :      11292 :         n = read(fd, buf, BUF_SIZE);
     507         [ -  + ]:       5646 :         if (n < 1) {
     508                 :          0 :                 pr_err("stat for %d is corrupted\n", pid);
     509                 :          0 :                 close(fd);
     510                 :          0 :                 return -1;
     511                 :            :         }
     512                 :       5646 :         close(fd);
     513                 :            : 
     514                 :            :         memset(s, 0, sizeof(*s));
     515                 :            : 
     516                 :       5646 :         tok = strchr(buf, ' ');
     517         [ +  - ]:       5646 :         if (!tok)
     518                 :            :                 goto err;
     519                 :       5646 :         *tok++ = '\0';
     520         [ +  - ]:       5646 :         if (*tok != '(')
     521                 :            :                 goto err;
     522                 :            : 
     523                 :       5646 :         s->pid = atoi(buf);
     524                 :            : 
     525                 :       5646 :         p = strrchr(tok + 1, ')');
     526         [ +  - ]:       5646 :         if (!p)
     527                 :            :                 goto err;
     528                 :       5646 :         *tok = '\0';
     529                 :       5646 :         *p = '\0';
     530                 :            : 
     531                 :       5646 :         strncpy(s->comm, tok + 1, sizeof(s->comm));
     532                 :            : 
     533                 :       5646 :         n = sscanf(p + 1, " %c %d %d %d", &s->state, &s->ppid, &s->pgid, &s->sid);
     534         [ -  + ]:       5646 :         if (n < 4)
     535                 :            :                 goto err;
     536                 :            : 
     537                 :            :         return 0;
     538                 :            : 
     539                 :            : err:
     540                 :          0 :         pr_err("Parsing %d's stat failed (#fields do not match)\n", pid);
     541                 :          0 :         return -1;
     542                 :            : }
     543                 :            : 
     544                 :        942 : int parse_pid_stat(pid_t pid, struct proc_pid_stat *s)
     545                 :            : {
     546                 :            :         char *tok, *p;
     547                 :            :         int fd;
     548                 :            :         int n;
     549                 :            : 
     550         [ -  + ]:        942 :         fd = open_proc(pid, "stat");
     551         [ +  - ]:        942 :         if (fd < 0)
     552                 :            :                 return -1;
     553                 :            : 
     554                 :       1884 :         n = read(fd, buf, BUF_SIZE);
     555         [ -  + ]:        942 :         if (n < 1) {
     556                 :          0 :                 pr_err("stat for %d is corrupted\n", pid);
     557                 :          0 :                 close(fd);
     558                 :          0 :                 return -1;
     559                 :            :         }
     560                 :        942 :         close(fd);
     561                 :            : 
     562                 :            :         memset(s, 0, sizeof(*s));
     563                 :            : 
     564                 :        942 :         tok = strchr(buf, ' ');
     565         [ +  - ]:        942 :         if (!tok)
     566                 :            :                 goto err;
     567                 :        942 :         *tok++ = '\0';
     568         [ +  - ]:        942 :         if (*tok != '(')
     569                 :            :                 goto err;
     570                 :            : 
     571                 :        942 :         s->pid = atoi(buf);
     572                 :            : 
     573                 :        942 :         p = strrchr(tok + 1, ')');
     574         [ +  - ]:        942 :         if (!p)
     575                 :            :                 goto err;
     576                 :        942 :         *tok = '\0';
     577                 :        942 :         *p = '\0';
     578                 :            : 
     579                 :        942 :         strncpy(s->comm, tok + 1, sizeof(s->comm));
     580                 :            : 
     581                 :        942 :         n = sscanf(p + 1,
     582                 :            :                " %c %d %d %d %d %d %u %lu %lu %lu %lu "
     583                 :            :                "%lu %lu %ld %ld %ld %ld %d %d %llu %lu %ld %lu %lu %lu %lu "
     584                 :            :                "%lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld "
     585                 :            :                "%lu %lu %lu %lu %lu %lu %lu %d",
     586                 :            :                 &s->state,
     587                 :            :                 &s->ppid,
     588                 :            :                 &s->pgid,
     589                 :            :                 &s->sid,
     590                 :            :                 &s->tty_nr,
     591                 :            :                 &s->tty_pgrp,
     592                 :            :                 &s->flags,
     593                 :            :                 &s->min_flt,
     594                 :            :                 &s->cmin_flt,
     595                 :            :                 &s->maj_flt,
     596                 :            :                 &s->cmaj_flt,
     597                 :            :                 &s->utime,
     598                 :            :                 &s->stime,
     599                 :            :                 &s->cutime,
     600                 :            :                 &s->cstime,
     601                 :            :                 &s->priority,
     602                 :            :                 &s->nice,
     603                 :            :                 &s->num_threads,
     604                 :            :                 &s->zero0,
     605                 :            :                 &s->start_time,
     606                 :            :                 &s->vsize,
     607                 :            :                 &s->mm_rss,
     608                 :            :                 &s->rsslim,
     609                 :            :                 &s->start_code,
     610                 :            :                 &s->end_code,
     611                 :            :                 &s->start_stack,
     612                 :            :                 &s->esp,
     613                 :            :                 &s->eip,
     614                 :            :                 &s->sig_pending,
     615                 :            :                 &s->sig_blocked,
     616                 :            :                 &s->sig_ignored,
     617                 :            :                 &s->sig_handled,
     618                 :            :                 &s->wchan,
     619                 :            :                 &s->zero1,
     620                 :            :                 &s->zero2,
     621                 :            :                 &s->exit_signal,
     622                 :            :                 &s->task_cpu,
     623                 :            :                 &s->rt_priority,
     624                 :            :                 &s->policy,
     625                 :            :                 &s->delayacct_blkio_ticks,
     626                 :            :                 &s->gtime,
     627                 :            :                 &s->cgtime,
     628                 :            :                 &s->start_data,
     629                 :            :                 &s->end_data,
     630                 :            :                 &s->start_brk,
     631                 :            :                 &s->arg_start,
     632                 :            :                 &s->arg_end,
     633                 :            :                 &s->env_start,
     634                 :            :                 &s->env_end,
     635                 :            :                 &s->exit_code);
     636         [ -  + ]:        942 :         if (n < 50)
     637                 :            :                 goto err;
     638                 :            : 
     639                 :            :         return 0;
     640                 :            : 
     641                 :            : err:
     642                 :          0 :         pr_err("Parsing %d's stat failed (#fields do not match)\n", pid);
     643                 :          0 :         return -1;
     644                 :            : }
     645                 :            : 
     646                 :       1838 : static int ids_parse(char *str, unsigned int *arr)
     647                 :            : {
     648                 :            :         char *end;
     649                 :            : 
     650                 :       1838 :         arr[0] = strtol(str, &end, 10);
     651                 :       1838 :         arr[1] = strtol(end + 1, &end, 10);
     652                 :       1838 :         arr[2] = strtol(end + 1, &end, 10);
     653                 :       1838 :         arr[3] = strtol(end + 1, &end, 10);
     654         [ +  - ]:       1838 :         if (*end != '\n')
     655                 :            :                 return -1;
     656                 :            :         else
     657                 :       1838 :                 return 0;
     658                 :            : }
     659                 :            : 
     660                 :       3676 : static int cap_parse(char *str, unsigned int *res)
     661                 :            : {
     662                 :            :         int i, ret;
     663                 :            : 
     664         [ +  + ]:      11028 :         for (i = 0; i < PROC_CAP_SIZE; i++) {
     665                 :       7352 :                 ret = sscanf(str, "%08x", &res[PROC_CAP_SIZE - 1 - i]);
     666         [ +  - ]:       7352 :                 if (ret != 1)
     667                 :            :                         return -1;
     668                 :       7352 :                 str += 8;
     669                 :            :         }
     670                 :            : 
     671                 :            :         return 0;
     672                 :            : }
     673                 :            : 
     674                 :        919 : int parse_pid_status(pid_t pid, struct proc_status_creds *cr)
     675                 :            : {
     676                 :            :         int done = 0;
     677                 :            :         FILE *f;
     678                 :            :         char str[64];
     679                 :            : 
     680 [ -  + ][ +  - ]:        919 :         f = fopen_proc(pid, "status");
                 [ -  + ]
     681         [ +  - ]:        919 :         if (f == NULL) {
     682                 :          0 :                 pr_perror("Can't open proc status");
     683                 :          0 :                 return -1;
     684                 :            :         }
     685                 :            : 
     686   [ +  +  +  - ]:      63411 :         while (done < 6 && fgets(str, sizeof(str), f)) {
     687         [ +  + ]:      31246 :                 if (!strncmp(str, "Uid:", 4)) {
     688         [ +  - ]:        919 :                         if (ids_parse(str + 5, cr->uids))
     689                 :            :                                 goto err_parse;
     690                 :            : 
     691                 :        919 :                         done++;
     692                 :            :                 }
     693                 :            : 
     694         [ +  + ]:      31246 :                 if (!strncmp(str, "Gid:", 4)) {
     695         [ +  - ]:        919 :                         if (ids_parse(str + 5, cr->gids))
     696                 :            :                                 goto err_parse;
     697                 :            : 
     698                 :        919 :                         done++;
     699                 :            :                 }
     700                 :            : 
     701         [ +  + ]:      31246 :                 if (!strncmp(str, "CapInh:", 7)) {
     702         [ +  - ]:        919 :                         if (cap_parse(str + 8, cr->cap_inh))
     703                 :            :                                 goto err_parse;
     704                 :            : 
     705                 :        919 :                         done++;
     706                 :            :                 }
     707                 :            : 
     708         [ +  + ]:      31246 :                 if (!strncmp(str, "CapEff:", 7)) {
     709         [ +  - ]:        919 :                         if (cap_parse(str + 8, cr->cap_eff))
     710                 :            :                                 goto err_parse;
     711                 :            : 
     712                 :        919 :                         done++;
     713                 :            :                 }
     714                 :            : 
     715         [ +  + ]:      31246 :                 if (!strncmp(str, "CapPrm:", 7)) {
     716         [ +  - ]:        919 :                         if (cap_parse(str + 8, cr->cap_prm))
     717                 :            :                                 goto err_parse;
     718                 :            : 
     719                 :        919 :                         done++;
     720                 :            :                 }
     721                 :            : 
     722         [ +  + ]:      31246 :                 if (!strncmp(str, "CapBnd:", 7)) {
     723         [ +  - ]:        919 :                         if (cap_parse(str + 8, cr->cap_bnd))
     724                 :            :                                 goto err_parse;
     725                 :            : 
     726                 :       1838 :                         done++;
     727                 :            :                 }
     728                 :            :         }
     729                 :            : 
     730         [ -  + ]:        919 :         if (done != 6) {
     731                 :            : err_parse:
     732                 :          0 :                 pr_err("Error parsing proc status file\n");
     733                 :          0 :                 fclose(f);
     734                 :          0 :                 return -1;
     735                 :            :         }
     736                 :            : 
     737                 :        919 :         fclose(f);
     738                 :        919 :         return 0;
     739                 :            : }
     740                 :            : 
     741                 :            : struct opt2flag {
     742                 :            :         char *opt;
     743                 :            :         unsigned flag;
     744                 :            : };
     745                 :            : 
     746                 :     292008 : static int do_opt2flag(char *opt, unsigned *flags,
     747                 :            :                 const struct opt2flag *opts, char *unknown)
     748                 :            : {
     749                 :            :         int i;
     750                 :            :         char *end;
     751                 :            : 
     752                 :            :         while (1) {
     753                 :     351988 :                 end = strchr(opt, ',');
     754         [ +  + ]:     351988 :                 if (end)
     755                 :     205984 :                         *end = '\0';
     756                 :            : 
     757         [ +  + ]:    1419336 :                 for (i = 0; opts[i].opt != NULL; i++)
     758         [ +  + ]:    1338380 :                         if (!strcmp(opts[i].opt, opt)) {
     759                 :     271032 :                                 (*flags) |= opts[i].flag;
     760                 :     271032 :                                 break;
     761                 :            :                         }
     762                 :            : 
     763         [ +  + ]:     351988 :                 if (opts[i].opt == NULL) {
     764         [ -  + ]:      80956 :                         if (!unknown) {
     765                 :          0 :                                 pr_err("Unknown option [%s]\n", opt);
     766                 :          0 :                                 return -1;
     767                 :            :                         }
     768                 :            : 
     769                 :            :                         strcpy(unknown, opt);
     770                 :      80956 :                         unknown += strlen(opt);
     771                 :      80956 :                         *unknown = ',';
     772                 :      80956 :                         unknown++;
     773                 :            :                 }
     774                 :            : 
     775         [ +  + ]:     351988 :                 if (!end) {
     776         [ +  + ]:     146004 :                         if (unknown)
     777                 :      73002 :                                 *unknown = '\0';
     778                 :            :                         break;
     779                 :            :                 } else
     780                 :     205984 :                         opt = end + 1;
     781                 :     205984 :         }
     782                 :            : 
     783                 :            :         return 0;
     784                 :            : }
     785                 :            : 
     786                 :      73002 : static int parse_mnt_flags(char *opt, unsigned *flags)
     787                 :            : {
     788                 :      73002 :         const struct opt2flag mnt_opt2flag[] = {
     789                 :            :                 { "rw", 0, },
     790                 :            :                 { "ro", MS_RDONLY, },
     791                 :            :                 { "nosuid", MS_NOSUID, },
     792                 :            :                 { "nodev", MS_NODEV, } ,
     793                 :            :                 { "noexec", MS_NOEXEC, },
     794                 :            :                 { "noatime", MS_NOATIME, },
     795                 :            :                 { "nodiratime", MS_NODIRATIME, },
     796                 :            :                 { "relatime", MS_RELATIME, },
     797                 :            :                 { },
     798                 :            :         };
     799                 :            : 
     800                 :      73002 :         return do_opt2flag(opt, flags, mnt_opt2flag, NULL);
     801                 :            : }
     802                 :            : 
     803                 :      73002 : static int parse_sb_opt(char *opt, unsigned *flags, char *uopt)
     804                 :            : {
     805                 :      73002 :         const struct opt2flag sb_opt2flag[] = {
     806                 :            :                 { "rw", 0, },
     807                 :            :                 { "ro", MS_RDONLY, },
     808                 :            :                 { "sync", MS_SYNC, },
     809                 :            :                 { "dirsync", MS_DIRSYNC, },
     810                 :            :                 { "mad", MS_MANDLOCK, },
     811                 :            :                 { },
     812                 :            :         };
     813                 :            : 
     814                 :      73002 :         return do_opt2flag(opt, flags, sb_opt2flag, uopt);
     815                 :            : }
     816                 :            : 
     817                 :     146004 : static int parse_mnt_opt(char *str, struct mount_info *mi, int *off)
     818                 :            : {
     819                 :            :         char *istr = str, *end;
     820                 :            : 
     821                 :            :         while (1) {
     822                 :      73002 :                 end = strchr(str, ' ');
     823         [ -  + ]:      73002 :                 if (!end) {
     824                 :          0 :                         pr_err("Error parsing mount options\n");
     825                 :          0 :                         return -1;
     826                 :            :                 }
     827                 :            : 
     828                 :      73002 :                 *end = '\0';
     829         [ -  + ]:      73002 :                 if (!strncmp(str, "-", 1))
     830                 :            :                         break;
     831         [ #  # ]:          0 :                 else if (!strncmp(str, "shared:", 7)) {
     832                 :          0 :                         mi->flags |= MS_SHARED;
     833                 :          0 :                         mi->shared_id = atoi(str + 7);
     834         [ #  # ]:          0 :                 } else if (!strncmp(str, "master:", 7)) {
     835                 :          0 :                         mi->flags |= MS_SLAVE;
     836                 :          0 :                         mi->master_id = atoi(str + 7);
     837         [ #  # ]:          0 :                 } else if (!strncmp(str, "propagate_from:", 15)) {
     838                 :            :                         /* skip */;
     839         [ #  # ]:          0 :                 } else if (!strncmp(str, "unbindable", 11))
     840                 :          0 :                         mi->flags |= MS_UNBINDABLE;
     841                 :            :                 else {
     842                 :          0 :                         pr_err("Unknown option [%s]\n", str);
     843                 :          0 :                         return -1;
     844                 :            :                 }
     845                 :            : 
     846                 :          0 :                 str = end + 1;
     847                 :          0 :         }
     848                 :            : 
     849                 :      73002 :         *off = end - istr + 1;
     850                 :      73002 :         return 0;
     851                 :            : }
     852                 :            : 
     853                 :      73002 : static int parse_mountinfo_ent(char *str, struct mount_info *new)
     854                 :            : {
     855                 :            :         unsigned int kmaj, kmin;
     856                 :            :         int ret, n;
     857                 :            :         char *opt;
     858                 :            :         char *fstype;
     859                 :            : 
     860         [ -  + ]:      73002 :         new->mountpoint = xmalloc(PATH_MAX);
     861         [ +  - ]:      73002 :         if (new->mountpoint == NULL)
     862                 :            :                 return -1;
     863                 :            : 
     864                 :      73002 :         new->mountpoint[0] = '.';
     865                 :      73002 :         ret = sscanf(str, "%i %i %u:%u %ms %s %ms %n",
     866                 :            :                         &new->mnt_id, &new->parent_mnt_id,
     867                 :      73002 :                         &kmaj, &kmin, &new->root, new->mountpoint + 1,
     868                 :            :                         &opt, &n);
     869         [ -  + ]:      73002 :         if (ret != 7) {
     870         [ #  # ]:          0 :                 xfree(new->mountpoint);
     871                 :            :                 return -1;
     872                 :            :         }
     873                 :            : 
     874         [ -  + ]:      73002 :         new->mountpoint = xrealloc(new->mountpoint, strlen(new->mountpoint) + 1);
     875                 :            : 
     876                 :      73002 :         new->s_dev = MKKDEV(kmaj, kmin);
     877                 :      73002 :         new->flags = 0;
     878         [ +  - ]:      73002 :         if (parse_mnt_flags(opt, &new->flags))
     879                 :            :                 return -1;
     880                 :            : 
     881                 :      73002 :         free(opt); /* after %ms scanf */
     882                 :            : 
     883                 :      73002 :         str += n;
     884         [ +  - ]:      73002 :         if (parse_mnt_opt(str, new, &n))
     885                 :            :                 return -1;
     886                 :            : 
     887                 :      73002 :         str += n;
     888                 :      73002 :         ret = sscanf(str, "%ms %ms %ms", &fstype, &new->source, &opt);
     889         [ +  - ]:      73002 :         if (ret != 3)
     890                 :            :                 return -1;
     891                 :            : 
     892                 :            :         ret = -1;
     893                 :      73002 :         new->fstype = find_fstype_by_name(fstype);
     894                 :            : 
     895         [ -  + ]:      73002 :         new->options = xmalloc(strlen(opt) + 1);
     896         [ +  - ]:      73002 :         if (!new->options)
     897                 :            :                 goto err;
     898                 :            : 
     899         [ +  - ]:      73002 :         if (parse_sb_opt(opt, &new->flags, new->options))
     900                 :            :                 goto err;
     901                 :            : 
     902                 :            :         ret = 0;
     903                 :            : err:
     904                 :      73002 :         free(opt);
     905                 :      73002 :         free(fstype);
     906                 :      73002 :         return ret;
     907                 :            : }
     908                 :            : 
     909                 :       3102 : struct mount_info *parse_mountinfo(pid_t pid, struct ns_id *nsid)
     910                 :            : {
     911                 :            :         struct mount_info *list = NULL;
     912                 :            :         FILE *f;
     913                 :            :         char str[1024];
     914                 :            : 
     915                 :            :         snprintf(str, sizeof(str), "/proc/%d/mountinfo", pid);
     916                 :       3102 :         f = fopen(str, "r");
     917         [ +  - ]:       3102 :         if (!f) {
     918                 :          0 :                 pr_perror("Can't open %d mountinfo", pid);
     919                 :          0 :                 return NULL;
     920                 :            :         }
     921                 :            : 
     922         [ +  + ]:      76104 :         while (fgets(str, sizeof(str), f)) {
     923                 :            :                 struct mount_info *new;
     924                 :            :                 int ret;
     925                 :            : 
     926                 :      73002 :                 new = mnt_entry_alloc();
     927         [ +  - ]:      73002 :                 if (!new)
     928                 :            :                         goto err;
     929                 :            : 
     930                 :      73002 :                 new->nsid = nsid;
     931                 :            : 
     932                 :      73002 :                 new->next = list;
     933                 :            :                 list = new;
     934                 :            : 
     935                 :      73002 :                 ret = parse_mountinfo_ent(str, new);
     936         [ -  + ]:      73002 :                 if (ret < 0) {
     937                 :          0 :                         pr_err("Bad format in %d mountinfo\n", pid);
     938                 :          0 :                         goto err;
     939                 :            :                 }
     940                 :            : 
     941                 :      73002 :                 pr_info("\ttype %s source %s %x %s @ %s flags %x options %s\n",
     942                 :            :                                 new->fstype->name, new->source,
     943                 :            :                                 new->s_dev, new->root, new->mountpoint,
     944                 :            :                                 new->flags, new->options);
     945                 :            : 
     946         [ -  + ]:      73002 :                 if (new->fstype->parse) {
     947                 :          0 :                         ret = new->fstype->parse(new);
     948         [ #  # ]:          0 :                         if (ret) {
     949                 :          0 :                                 pr_err("Failed to parse FS specific data on %s\n",
     950                 :            :                                                 new->mountpoint);
     951                 :      73002 :                                 goto err;
     952                 :            :                         }
     953                 :            :                 }
     954                 :            :         }
     955                 :            : out:
     956                 :       3102 :         fclose(f);
     957                 :       3102 :         return list;
     958                 :            : 
     959                 :            : err:
     960         [ #  # ]:          0 :         while (list) {
     961                 :          0 :                 struct mount_info *next = list->next;
     962                 :          0 :                 mnt_entry_free(list);
     963                 :            :                 list = next;
     964                 :            :         }
     965                 :            :         goto out;
     966                 :            : }
     967                 :            : 
     968                 :            : static char nybble(const char n)
     969                 :            : {
     970 [ +  + ][ +  + ]:        900 :         if (n >= '0' && n <= '9')
     971                 :        566 :                 return n - '0';
     972 [ -  + ][ -  + ]:        334 :         else if (n >= 'A' && n <= 'F')
     973                 :          0 :                 return n - ('A' - 10);
     974 [ +  + ][ +  + ]:        334 :         else if (n >= 'a' && n <= 'f')
     975                 :        234 :                 return n - ('a' - 10);
     976                 :            :         return 0;
     977                 :            : }
     978                 :            : 
     979                 :        100 : static int alloc_fhandle(FhEntry *fh)
     980                 :            : {
     981                 :         50 :         fh->n_handle = FH_ENTRY_SIZES__min_entries;
     982         [ -  + ]:         50 :         fh->handle = xmalloc(pb_repeated_size(fh, handle));
     983                 :            : 
     984         [ +  - ]:         50 :         return fh->handle == NULL ? -1 : 0;
     985                 :            : }
     986                 :            : 
     987                 :            : static void free_fhandle(FhEntry *fh)
     988                 :            : {
     989   [ +  +  +  + ]:         50 :         if (fh->handle)
     990 [ +  - ][ +  - ]:         14 :                 xfree(fh->handle);
     991                 :            : }
     992                 :            : 
     993                 :         50 : static void parse_fhandle_encoded(char *tok, FhEntry *fh)
     994                 :            : {
     995                 :         50 :         char *d = (char *)fh->handle;
     996                 :            :         int i = 0;
     997                 :            : 
     998                 :         50 :         memzero(d, pb_repeated_size(fh, handle));
     999                 :            : 
    1000         [ -  + ]:         50 :         while (*tok == ' ')
    1001                 :          0 :                 tok++;
    1002                 :            : 
    1003         [ +  - ]:        450 :         while (*tok) {
    1004         [ +  - ]:        450 :                 if (i >= pb_repeated_size(fh, handle))
    1005                 :            :                         break;
    1006                 :       1350 :                 d[i++] = (nybble(tok[0]) << 4) | nybble(tok[1]);
    1007         [ +  + ]:        450 :                 if (tok[1])
    1008                 :        400 :                         tok += 2;
    1009                 :            :                 else
    1010                 :            :                         break;
    1011                 :            :         }
    1012                 :         50 : }
    1013                 :            : 
    1014                 :            : #define fdinfo_field(str, field)        !strncmp(str, field":", sizeof(field))
    1015                 :            : 
    1016                 :      16456 : static int parse_fdinfo_pid_s(char *pid, int fd, int type,
    1017                 :            :                 int (*cb)(union fdinfo_entries *e, void *arg), void *arg)
    1018                 :            : {
    1019                 :            :         FILE *f;
    1020                 :            :         char str[256];
    1021                 :            :         bool entry_met = false;
    1022                 :            :         int ret = -1;
    1023                 :            : 
    1024                 :            :         sprintf(str, "/proc/%s/fdinfo/%d", pid, fd);
    1025                 :      16456 :         f = fopen(str, "r");
    1026         [ +  - ]:      16456 :         if (!f) {
    1027                 :          0 :                 pr_perror("Can't open %s to parse", str);
    1028                 :          0 :                 return -1;
    1029                 :            :         }
    1030                 :            : 
    1031         [ +  + ]:      49500 :         while (fgets(str, sizeof(str), f)) {
    1032                 :            :                 union fdinfo_entries entry;
    1033                 :            : 
    1034 [ +  + ][ +  + ]:      33044 :                 if (fdinfo_field(str, "pos") ||
    1035         [ -  + ]:        132 :                     fdinfo_field(str, "flags") ||
    1036                 :        132 :                     fdinfo_field(str, "mnt_id")) {
    1037                 :            :                         unsigned long long val;
    1038                 :            :                         struct fdinfo_common *fdinfo = arg;
    1039                 :            : 
    1040         [ +  + ]:      32912 :                         if (type != FD_TYPES__UND)
    1041                 :      32912 :                                 continue;
    1042                 :      32808 :                         ret = sscanf(str, "%*s %lli", &val);
    1043         [ +  - ]:      32808 :                         if (ret != 1)
    1044                 :            :                                 goto parse_err;
    1045                 :            : 
    1046         [ +  + ]:      32808 :                         if (fdinfo_field(str, "pos"))
    1047                 :      16404 :                                 fdinfo->pos = val;
    1048         [ +  - ]:      16404 :                         else if (fdinfo_field(str, "flags"))
    1049                 :      16404 :                                 fdinfo->flags = val;
    1050         [ #  # ]:          0 :                         else if (fdinfo_field(str, "mnt_id"))
    1051                 :          0 :                                 fdinfo->mnt_id = val;
    1052                 :            : 
    1053                 :            :                         entry_met = true;
    1054                 :      32808 :                         continue;
    1055                 :            :                 }
    1056                 :            : 
    1057         [ +  + ]:        132 :                 if (type == FD_TYPES__UND)
    1058                 :         32 :                         continue;
    1059                 :            : 
    1060         [ +  + ]:        100 :                 if (fdinfo_field(str, "eventfd-count")) {
    1061                 :          6 :                         eventfd_file_entry__init(&entry.efd);
    1062                 :            : 
    1063         [ +  - ]:          6 :                         if (type != FD_TYPES__EVENTFD)
    1064                 :            :                                 goto parse_err;
    1065                 :          6 :                         ret = sscanf(str, "eventfd-count: %"PRIx64,
    1066                 :            :                                         &entry.efd.counter);
    1067         [ +  - ]:          6 :                         if (ret != 1)
    1068                 :            :                                 goto parse_err;
    1069                 :          6 :                         ret = cb(&entry, arg);
    1070         [ +  - ]:          6 :                         if (ret)
    1071                 :            :                                 goto out;
    1072                 :            : 
    1073                 :            :                         entry_met = true;
    1074                 :          6 :                         continue;
    1075                 :            :                 }
    1076         [ +  + ]:         94 :                 if (fdinfo_field(str, "tfd")) {
    1077                 :          6 :                         eventpoll_tfd_entry__init(&entry.epl);
    1078                 :            : 
    1079         [ +  - ]:          6 :                         if (type != FD_TYPES__EVENTPOLL)
    1080                 :            :                                 goto parse_err;
    1081                 :          6 :                         ret = sscanf(str, "tfd: %d events: %x data: %"PRIx64,
    1082                 :            :                                         &entry.epl.tfd, &entry.epl.events, &entry.epl.data);
    1083         [ +  - ]:          6 :                         if (ret != 3)
    1084                 :            :                                 goto parse_err;
    1085                 :          6 :                         ret = cb(&entry, arg);
    1086         [ +  - ]:          6 :                         if (ret)
    1087                 :            :                                 goto out;
    1088                 :            : 
    1089                 :            :                         entry_met = true;
    1090                 :          6 :                         continue;
    1091                 :            :                 }
    1092         [ +  + ]:         88 :                 if (fdinfo_field(str, "sigmask")) {
    1093                 :          6 :                         signalfd_entry__init(&entry.sfd);
    1094                 :            : 
    1095         [ +  - ]:          6 :                         if (type != FD_TYPES__SIGNALFD)
    1096                 :            :                                 goto parse_err;
    1097                 :          6 :                         ret = sscanf(str, "sigmask: %Lx",
    1098                 :            :                                         (unsigned long long *)&entry.sfd.sigmask);
    1099         [ +  - ]:          6 :                         if (ret != 1)
    1100                 :            :                                 goto parse_err;
    1101                 :          6 :                         ret = cb(&entry, arg);
    1102         [ +  - ]:          6 :                         if (ret)
    1103                 :            :                                 goto out;
    1104                 :            : 
    1105                 :            :                         entry_met = true;
    1106                 :          6 :                         continue;
    1107                 :            :                 }
    1108         [ +  + ]:         82 :                 if (fdinfo_field(str, "fanotify flags")) {
    1109                 :            :                         struct fsnotify_params *p = arg;
    1110                 :            : 
    1111         [ +  - ]:         16 :                         if (type != FD_TYPES__FANOTIFY)
    1112                 :            :                                 goto parse_err;
    1113                 :            : 
    1114                 :         16 :                         ret = sscanf(str, "fanotify flags:%x event-flags:%x",
    1115                 :            :                                      &p->faflags, &p->evflags);
    1116         [ +  - ]:         16 :                         if (ret != 2)
    1117                 :            :                                 goto parse_err;
    1118                 :            :                         entry_met = true;
    1119                 :         16 :                         continue;
    1120                 :            :                 }
    1121         [ +  + ]:         66 :                 if (fdinfo_field(str, "fanotify ino")) {
    1122                 :         16 :                         FanotifyInodeMarkEntry ie = FANOTIFY_INODE_MARK_ENTRY__INIT;
    1123                 :         16 :                         FhEntry f_handle = FH_ENTRY__INIT;
    1124                 :            :                         int hoff;
    1125                 :            : 
    1126         [ +  - ]:         16 :                         if (type != FD_TYPES__FANOTIFY)
    1127                 :            :                                 goto parse_err;
    1128                 :            : 
    1129                 :         16 :                         fanotify_mark_entry__init(&entry.ffy);
    1130                 :         16 :                         ie.f_handle = &f_handle;
    1131                 :         16 :                         entry.ffy.ie = &ie;
    1132                 :            : 
    1133                 :         16 :                         ret = sscanf(str,
    1134                 :            :                                      "fanotify ino:%"PRIx64" sdev:%x mflags:%x mask:%x ignored_mask:%x "
    1135                 :            :                                      "fhandle-bytes:%x fhandle-type:%x f_handle: %n",
    1136                 :            :                                      &ie.i_ino, &entry.ffy.s_dev,
    1137                 :            :                                      &entry.ffy.mflags, &entry.ffy.mask, &entry.ffy.ignored_mask,
    1138                 :            :                                      &f_handle.bytes, &f_handle.type,
    1139                 :            :                                      &hoff);
    1140         [ +  - ]:         16 :                         if (ret != 7)
    1141                 :            :                                 goto parse_err;
    1142                 :            : 
    1143         [ +  - ]:         16 :                         if (alloc_fhandle(&f_handle)) {
    1144                 :            :                                 ret = -1;
    1145                 :          0 :                                 goto out;
    1146                 :            :                         }
    1147                 :         16 :                         parse_fhandle_encoded(str + hoff, &f_handle);
    1148                 :            : 
    1149                 :         16 :                         entry.ffy.type = MARK_TYPE__INODE;
    1150                 :         16 :                         ret = cb(&entry, arg);
    1151                 :            : 
    1152                 :         16 :                         free_fhandle(&f_handle);
    1153                 :            : 
    1154         [ +  - ]:         16 :                         if (ret)
    1155                 :            :                                 goto out;
    1156                 :            : 
    1157                 :            :                         entry_met = true;
    1158                 :         16 :                         continue;
    1159                 :            :                 }
    1160         [ +  + ]:         50 :                 if (fdinfo_field(str, "fanotify mnt_id")) {
    1161                 :         16 :                         FanotifyMountMarkEntry me = FANOTIFY_MOUNT_MARK_ENTRY__INIT;
    1162                 :            : 
    1163         [ +  - ]:         16 :                         if (type != FD_TYPES__FANOTIFY)
    1164                 :            :                                 goto parse_err;
    1165                 :            : 
    1166                 :         16 :                         fanotify_mark_entry__init(&entry.ffy);
    1167                 :         16 :                         entry.ffy.me = &me;
    1168                 :            : 
    1169                 :         16 :                         ret = sscanf(str,
    1170                 :            :                                      "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x",
    1171                 :            :                                      &me.mnt_id, &entry.ffy.mflags,
    1172                 :            :                                      &entry.ffy.mask, &entry.ffy.ignored_mask);
    1173         [ +  - ]:         16 :                         if (ret != 4)
    1174                 :            :                                 goto parse_err;
    1175                 :            : 
    1176                 :         16 :                         entry.ffy.type = MARK_TYPE__MOUNT;
    1177                 :         16 :                         ret = cb(&entry, arg);
    1178         [ +  - ]:         16 :                         if (ret)
    1179                 :            :                                 goto out;
    1180                 :            : 
    1181                 :            :                         entry_met = true;
    1182                 :         16 :                         continue;
    1183                 :            :                 }
    1184         [ +  - ]:         34 :                 if (fdinfo_field(str, "inotify wd")) {
    1185                 :         34 :                         FhEntry f_handle = FH_ENTRY__INIT;
    1186                 :            :                         int hoff;
    1187                 :            : 
    1188                 :         34 :                         inotify_wd_entry__init(&entry.ify);
    1189                 :         34 :                         entry.ify.f_handle = &f_handle;
    1190                 :            : 
    1191         [ +  - ]:         34 :                         if (type != FD_TYPES__INOTIFY)
    1192                 :            :                                 goto parse_err;
    1193                 :         34 :                         ret = sscanf(str,
    1194                 :            :                                         "inotify wd:%x ino:%"PRIx64" sdev:%x "
    1195                 :            :                                         "mask:%x ignored_mask:%x "
    1196                 :            :                                         "fhandle-bytes:%x fhandle-type:%x "
    1197                 :            :                                         "f_handle: %n",
    1198                 :            :                                         &entry.ify.wd, &entry.ify.i_ino, &entry.ify.s_dev,
    1199                 :            :                                         &entry.ify.mask, &entry.ify.ignored_mask,
    1200                 :         34 :                                         &entry.ify.f_handle->bytes, &entry.ify.f_handle->type,
    1201                 :            :                                         &hoff);
    1202         [ +  - ]:         34 :                         if (ret != 7)
    1203                 :            :                                 goto parse_err;
    1204                 :            : 
    1205         [ +  - ]:         34 :                         if (alloc_fhandle(&f_handle)) {
    1206                 :            :                                 ret = -1;
    1207                 :      33044 :                                 goto out;
    1208                 :            :                         }
    1209                 :            : 
    1210                 :         34 :                         parse_fhandle_encoded(str + hoff, entry.ify.f_handle);
    1211                 :            : 
    1212                 :         34 :                         ret = cb(&entry, arg);
    1213                 :            : 
    1214                 :         34 :                         free_fhandle(&f_handle);
    1215                 :            : 
    1216         [ +  - ]:         34 :                         if (ret)
    1217                 :            :                                 goto out;
    1218                 :            : 
    1219                 :            :                         entry_met = true;
    1220                 :         34 :                         continue;
    1221                 :            :                 }
    1222                 :            :         }
    1223                 :            : 
    1224                 :            :         ret = 0;
    1225         [ -  + ]:      16456 :         if (entry_met)
    1226                 :            :                 goto out;
    1227                 :            :         /*
    1228                 :            :          * An eventpoll/inotify file may have no target fds set thus
    1229                 :            :          * resulting in no tfd: lines in proc. This is normal.
    1230                 :            :          */
    1231         [ #  # ]:          0 :         if (type == FD_TYPES__EVENTPOLL || type == FD_TYPES__INOTIFY)
    1232                 :            :                 goto out;
    1233                 :            : 
    1234                 :          0 :         pr_err("No records of type %d found in fdinfo file\n", type);
    1235                 :            : parse_err:
    1236                 :            :         ret = -1;
    1237                 :          0 :         pr_perror("%s: error parsing [%s] for %d", __func__, str, type);
    1238                 :            : out:
    1239                 :      16456 :         fclose(f);
    1240                 :      16456 :         return ret;
    1241                 :            : }
    1242                 :            : 
    1243                 :         24 : int parse_fdinfo_pid(int pid, int fd, int type,
    1244                 :            :                 int (*cb)(union fdinfo_entries *e, void *arg), void *arg)
    1245                 :            : {
    1246                 :            :         char pid_s[10];
    1247                 :            : 
    1248                 :            :         sprintf(pid_s, "%d", pid);
    1249                 :         24 :         return parse_fdinfo_pid_s(pid_s, fd, type, cb, arg);
    1250                 :            : }
    1251                 :            : 
    1252                 :      16432 : int parse_fdinfo(int fd, int type,
    1253                 :            :                 int (*cb)(union fdinfo_entries *e, void *arg), void *arg)
    1254                 :            : {
    1255                 :      16432 :         return parse_fdinfo_pid_s("self", fd, type, cb, arg);
    1256                 :            : }
    1257                 :            : 
    1258                 :      17738 : static int parse_file_lock_buf(char *buf, struct file_lock *fl,
    1259                 :            :                                 bool is_blocked)
    1260                 :            : {
    1261                 :            :         int  num;
    1262                 :            : 
    1263         [ -  + ]:      17738 :         if (is_blocked) {
    1264                 :          0 :                 num = sscanf(buf, "%lld: -> %s %s %s %d %x:%x:%ld %lld %s",
    1265                 :          0 :                         &fl->fl_id, fl->fl_flag, fl->fl_type, fl->fl_option,
    1266                 :            :                         &fl->fl_owner, &fl->maj, &fl->min, &fl->i_no,
    1267                 :          0 :                         &fl->start, fl->end);
    1268                 :            :         } else {
    1269                 :      17738 :                 num = sscanf(buf, "%lld:%s %s %s %d %x:%x:%ld %lld %s",
    1270                 :      17738 :                         &fl->fl_id, fl->fl_flag, fl->fl_type, fl->fl_option,
    1271                 :            :                         &fl->fl_owner, &fl->maj, &fl->min, &fl->i_no,
    1272                 :      17738 :                         &fl->start, fl->end);
    1273                 :            :         }
    1274                 :            : 
    1275         [ -  + ]:      17738 :         if (num < 10) {
    1276                 :          0 :                 pr_err("Invalid file lock info (%d): %s", num, buf);
    1277                 :          0 :                 return -1;
    1278                 :            :         }
    1279                 :            : 
    1280                 :            :         return 0;
    1281                 :            : }
    1282                 :            : 
    1283                 :        448 : int parse_file_locks(void)
    1284                 :            : {
    1285                 :            :         struct file_lock *fl;
    1286                 :            : 
    1287                 :            :         FILE    *fl_locks;
    1288                 :            :         int     ret = 0;
    1289                 :            :         bool    is_blocked;
    1290                 :            : 
    1291                 :        448 :         fl_locks = fopen("/proc/locks", "r");
    1292         [ +  - ]:        448 :         if (!fl_locks) {
    1293                 :          0 :                 pr_perror("Can't open file locks file!");
    1294                 :          0 :                 return -1;
    1295                 :            :         }
    1296                 :            : 
    1297         [ +  + ]:      18186 :         while (fgets(buf, BUF_SIZE, fl_locks)) {
    1298                 :      17738 :                 is_blocked = strstr(buf, "->") != NULL;
    1299                 :            : 
    1300                 :      17738 :                 fl = alloc_file_lock();
    1301         [ -  + ]:      17738 :                 if (!fl) {
    1302                 :          0 :                         pr_perror("Alloc file lock failed!");
    1303                 :            :                         ret = -1;
    1304                 :          0 :                         goto err;
    1305                 :            :                 }
    1306                 :            : 
    1307         [ -  + ]:      17738 :                 if (parse_file_lock_buf(buf, fl, is_blocked)) {
    1308         [ #  # ]:          0 :                         xfree(fl);
    1309                 :            :                         ret = -1;
    1310                 :            :                         goto err;
    1311                 :            :                 }
    1312                 :            : 
    1313         [ +  + ]:      17738 :                 if (!pid_in_pstree(fl->fl_owner)) {
    1314                 :            :                         /*
    1315                 :            :                          * We only care about tasks which are taken
    1316                 :            :                          * into dump, so we only collect file locks
    1317                 :            :                          * belong to these tasks.
    1318                 :            :                          */
    1319         [ +  - ]:      17718 :                         xfree(fl);
    1320                 :      17718 :                         continue;
    1321                 :            :                 }
    1322                 :            : 
    1323         [ -  + ]:         20 :                 if (is_blocked) {
    1324                 :            :                         /*
    1325                 :            :                          * Here the task is in the pstree.
    1326                 :            :                          * If it is blocked on a flock, when we try to
    1327                 :            :                          * ptrace-seize it, the kernel will unblock task
    1328                 :            :                          * from flock and will stop it in another place.
    1329                 :            :                          * So in dumping, a blocked file lock should never
    1330                 :            :                          * be here.
    1331                 :            :                          */
    1332                 :          0 :                         pr_perror("We have a blocked file lock!");
    1333                 :            :                         ret = -1;
    1334         [ #  # ]:          0 :                         xfree(fl);
    1335                 :            :                         goto err;
    1336                 :            :                 }
    1337                 :            : 
    1338                 :         20 :                 pr_info("lockinfo: %lld:%s %s %s %d %02x:%02x:%ld %lld %s\n",
    1339                 :            :                         fl->fl_id, fl->fl_flag, fl->fl_type, fl->fl_option,
    1340                 :            :                         fl->fl_owner, fl->maj, fl->min, fl->i_no,
    1341                 :            :                         fl->start, fl->end);
    1342                 :            : 
    1343                 :         20 :                 list_add_tail(&fl->list, &file_lock_list);
    1344                 :            :         }
    1345                 :            : 
    1346                 :            : err:
    1347                 :        448 :         fclose(fl_locks);
    1348                 :        448 :         return ret;
    1349                 :            : }
    1350                 :            : 
    1351                 :        919 : void free_posix_timers(struct proc_posix_timers_stat *st)
    1352                 :            : {
    1353         [ +  + ]:       1846 :         while (!list_empty(&st->timers)) {
    1354                 :            :                 struct proc_posix_timer *timer;
    1355                 :            :                 timer = list_first_entry(&st->timers, struct proc_posix_timer, list);
    1356                 :            :                 list_del(&timer->list);
    1357         [ -  + ]:        927 :                 xfree(timer);
    1358                 :            :         }
    1359                 :        919 : }
    1360                 :            : 
    1361                 :        919 : int parse_posix_timers(pid_t pid, struct proc_posix_timers_stat *args)
    1362                 :            : {
    1363                 :            :         int ret = 0;
    1364                 :            :         int pid_t;
    1365                 :            : 
    1366                 :            :         FILE * file;
    1367                 :            : 
    1368                 :            :         char sigpid[7];
    1369                 :            :         char tidpid[4];
    1370                 :            : 
    1371                 :            :         struct proc_posix_timer *timer = NULL;
    1372                 :            : 
    1373                 :        919 :         INIT_LIST_HEAD(&args->timers);
    1374                 :        919 :         args->timer_n = 0;
    1375                 :            : 
    1376 [ -  + ][ +  - ]:        919 :         file = fopen_proc(pid, "timers");
                 [ -  + ]
    1377         [ +  - ]:        919 :         if (file == NULL) {
    1378                 :          0 :                 pr_perror("Can't open posix timers file!");
    1379                 :          0 :                 return -1;
    1380                 :            :         }
    1381                 :            : 
    1382                 :            :         while (1) {
    1383                 :            :                 char pbuf[17]; /* 16 + eol */
    1384         [ -  + ]:        927 :                 timer = xzalloc(sizeof(struct proc_posix_timer));
    1385         [ +  - ]:        927 :                 if (timer == NULL)
    1386                 :            :                         goto err;
    1387                 :            : 
    1388                 :        927 :                 ret = fscanf(file, "ID: %ld\n"
    1389                 :            :                                    "signal: %d/%16s\n"
    1390                 :            :                                    "notify: %6[a-z]/%3[a-z].%d\n"
    1391                 :            :                                    "ClockID: %d\n",
    1392                 :            :                                 &timer->spt.it_id,
    1393                 :            :                                 &timer->spt.si_signo, pbuf,
    1394                 :            :                                 sigpid, tidpid, &pid_t,
    1395                 :            :                                 &timer->spt.clock_id);
    1396         [ +  + ]:        927 :                 if (ret != 7) {
    1397                 :            :                         ret = 0;
    1398         [ +  - ]:        919 :                         xfree(timer);
    1399         [ -  + ]:        919 :                         if (feof(file))
    1400                 :            :                                 goto out;
    1401                 :            :                         goto err;
    1402                 :            :                 }
    1403                 :            : 
    1404                 :          8 :                 timer->spt.sival_ptr = NULL;
    1405 [ +  + ][ -  + ]:          8 :                 if (sscanf(pbuf, "%p", &timer->spt.sival_ptr) != 1 &&
    1406                 :          4 :                     strcmp(pbuf, "(null)")) {
    1407                 :          0 :                         pr_err("Unable to parse '%s'\n", pbuf);
    1408         [ #  # ]:          0 :                         xfree(timer);
    1409                 :            :                         goto err;
    1410                 :            :                 }
    1411                 :            : 
    1412         [ -  + ]:          8 :                 if ( tidpid[0] == 't') {
    1413                 :          0 :                         timer->spt.it_sigev_notify = SIGEV_THREAD_ID;
    1414                 :            :                 } else {
    1415      [ +  -  - ]:          8 :                         switch (sigpid[0]) {
    1416                 :            :                                 case 's' :
    1417                 :          8 :                                         timer->spt.it_sigev_notify = SIGEV_SIGNAL;
    1418                 :          8 :                                         break;
    1419                 :            :                                 case 't' :
    1420                 :          0 :                                         timer->spt.it_sigev_notify = SIGEV_THREAD;
    1421                 :          0 :                                         break;
    1422                 :            :                                 default :
    1423                 :          0 :                                         timer->spt.it_sigev_notify = SIGEV_NONE;
    1424                 :          0 :                                         break;
    1425                 :            :                         }
    1426                 :            :                 }
    1427                 :            : 
    1428                 :          8 :                 list_add(&timer->list, &args->timers);
    1429                 :            :                 timer = NULL;
    1430                 :          8 :                 args->timer_n++;
    1431                 :          8 :         }
    1432                 :            : err:
    1433                 :          0 :         free_posix_timers(args);
    1434                 :        919 :         pr_perror("Parse error in posix timers proc file!");
    1435                 :            :         ret = -1;
    1436                 :            : out:
    1437                 :        919 :         fclose(file);
    1438                 :        919 :         return ret;
    1439                 :            : }
    1440                 :            : 
    1441                 :       4804 : int parse_threads(int pid, struct pid **_t, int *_n)
    1442                 :            : {
    1443                 :            :         struct dirent *de;
    1444                 :            :         DIR *dir;
    1445                 :            :         struct pid *t = NULL;
    1446                 :            :         int nr = 1;
    1447                 :            : 
    1448         [ +  + ]:       4804 :         if (*_t)
    1449                 :            :                 t = *_t;
    1450                 :            : 
    1451 [ -  + ][ +  - ]:       4804 :         dir = opendir_proc(pid, "task");
                 [ -  + ]
    1452         [ +  - ]:       4804 :         if (!dir)
    1453                 :            :                 return -1;
    1454                 :            : 
    1455         [ +  + ]:      24352 :         while ((de = readdir(dir))) {
    1456                 :            :                 struct pid *tmp;
    1457                 :            : 
    1458                 :            :                 /* We expect numbers only here */
    1459         [ +  + ]:      19548 :                 if (de->d_name[0] == '.')
    1460                 :       9608 :                         continue;
    1461                 :            : 
    1462         [ +  + ]:       9940 :                 if (*_t == NULL) {
    1463         [ -  + ]:       8551 :                         tmp = xrealloc(t, nr * sizeof(struct pid));
    1464         [ -  + ]:       8551 :                         if (!tmp) {
    1465         [ #  # ]:          0 :                                 xfree(t);
    1466                 :            :                                 return -1;
    1467                 :            :                         }
    1468                 :            :                         t = tmp;
    1469                 :       8551 :                         t[nr - 1].virt = -1;
    1470                 :            :                 }
    1471                 :      19880 :                 t[nr - 1].real = atoi(de->d_name);
    1472                 :      19548 :                 nr++;
    1473                 :            :         }
    1474                 :            : 
    1475                 :       4804 :         closedir(dir);
    1476                 :            : 
    1477         [ +  + ]:       4804 :         if (*_t == NULL) {
    1478                 :       3885 :                 *_t = t;
    1479                 :       3885 :                 *_n = nr - 1;
    1480                 :            :         } else
    1481         [ -  + ]:        919 :                 BUG_ON(nr - 1 != *_n);
    1482                 :            : 
    1483                 :            :         return 0;
    1484                 :            : }

Generated by: LCOV version 1.9