]> git.itanic.dy.fi Git - scan-pagemap/blobdiff - parse.c
parser: Free pidlist entries after removed from the list
[scan-pagemap] / parse.c
diff --git a/parse.c b/parse.c
index 76b0eec7c81ccf54f81542eab9ed78acf47afc23..e21935f4543c753ce0b4194e4d9ffe61f8d60a95 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -1,13 +1,11 @@
-#include <sys/types.h>
-#include <dirent.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <libgen.h>
 
 #include "parse.h"
 #include "pagemap.h"
+#include "pidlib.h"
 
 static struct maps_list *alloc_maplist(void)
 {
@@ -77,11 +75,6 @@ static struct maps *parse_maps(FILE *file, int pid, int tid)
        return the_map;
 }
 
-static void clear_pageframe(struct pageframe *pf)
-{
-       memset(pf, 0, sizeof(*pf));
-}
-
 static struct pageframe *alloc_pageframe(void)
 {
        struct pageframe *pageframe;
@@ -91,7 +84,6 @@ static struct pageframe *alloc_pageframe(void)
                goto err;
 
        clear_pageframe(pageframe);
-       INIT_LIST_HEAD(&pageframe->ml);
 err:
        return pageframe;
 }
@@ -109,60 +101,18 @@ struct bintree_ops pageframe_ops = {
        .compare = compare_pageframe,
 };
 
-static int read_cmdline(int pid, int tid, char *cmdline, size_t len)
-{
-       FILE *file;
-       char path[512];
-       int ret;
-
-       snprintf(path, sizeof(path), "/proc/%d/task/%d/cmdline", pid, tid);
-       file = fopen(path, "rb");
-
-       if (!file)
-               return -1;
-
-       ret = fread(cmdline, 1, len, file);
-       if (ret > 0)
-               cmdline[ret - 1] = 0;
-       fclose(file);
-
-       return ret > 0 ? 0 : -1;
-}
-
-static char *get_name_by_pid(int pid)
-{
-       static int last_pid;
-       static char cmdline[128];
-       static char *bname;
-
-       if (last_pid == pid)
-               return bname;
-
-       if (read_cmdline(pid, pid, cmdline, sizeof(cmdline))) {
-               bname = NULL;
-               return NULL;
-       }
-
-       bname = basename(cmdline);
-
-       last_pid = pid;
-       return bname;
-}
-
 static int should_scan_process(struct parse_opts *opts, struct process *process)
 {
+       struct pidlist *pid;
        int match = 0;
-       char *name;
-
-       if (is_parse_option(opts, PARSE_PROCESS_NAME)) {
-               name = get_name_by_pid(process->pid);
-               if (!strcmp(opts->name, name ? name : ""))
-                       match = 1;
-       }
 
        if (is_parse_option(opts, PARSE_PID)) {
-               if (opts->pid == process->pid)
-                       match = 1;
+               list_for_each_entry(pid, &opts->pidlist, list) {
+                       if (pid->pid == process->pid) {
+                               match = 1;
+                               break;
+                       }
+               }
        }
 
        if (is_parse_option(opts, PARSE_MAP_NAME))
@@ -179,7 +129,7 @@ static int should_scan_mapping(struct parse_opts *opts, struct maps *map)
        int match = 0;
 
        if (is_parse_option(opts, PARSE_MAP_NAME)) {
-               if (!strcmp(opts->name, map->name))
+               if (strstr(map->name, opts->name))
                        match = 1;
 
                if (is_parse_option(opts, PARSE_NOADD_TREE))
@@ -295,6 +245,7 @@ static int read_pageframe(int pid, int tid, struct pageframe *pageframe,
 {
        struct maps *maps;
        struct process *process;
+       struct pidlist *pidl, *n;
        FILE *file;
        char path[512];
 
@@ -346,91 +297,16 @@ static int read_pageframe(int pid, int tid, struct pageframe *pageframe,
 free:
        free(process);
 
-       return 0;
-}
-
-static int parse_pid(DIR **dir)
-{
-       struct dirent *dirent;
-       int error;
-
-restart:
-       dirent = readdir(*dir);
-       if (!dirent) {
-               if (errno == 0) {
-                       closedir(*dir);
-                       *dir = NULL;
-                       return 0;
-               }
-               error = errno;
-               printf("Failed to read /proc directory: %s\n", strerror(error));
-               return -1;
-       }
-
-       if (dirent->d_name[0] < '0' || dirent->d_name[0] > '9')
-               goto restart;
-
-       return atoi(dirent->d_name);
-}
-
-static int opendir_check(DIR **dir, const char *path)
-{
-       int error;
-
-       if (!*dir) {
-               *dir = opendir(path);
-               if (!dir) {
-                       error = errno;
-                       fprintf(stderr, "Failed to open %s directory: %s\n",
-                               path, strerror(error));
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-static int get_next_tid(int pid, DIR **dir)
-{
-       if (*dir == NULL) {
-               char path[64];
-
-               snprintf(path, sizeof(path), "/proc/%d/task/", pid);
-               if (opendir_check(dir, path))
-                       return -1;
-       }
-
-       return parse_pid(dir);
-}
-
-static int get_next_pid(DIR **dir)
-{
-       if (opendir_check(dir, "/proc"))
-               return -1;
-
-       return parse_pid(dir);
-}
-
-static int get_next_pid_by_name(DIR **dir, char *name)
-{
-       int pid;
-       char *pname;
-
-       if (opendir_check(dir, "/proc"))
-               return -1;
-
-       while (1) {
-               pid = parse_pid(dir);
-               if (pid <= 0)
+       /*
+        * Remove the pid from the list. It is no longer an
+        * interesting pid, since we can't access its data
+        */
+       list_for_each_entry_safe(pidl, n, &opts->pidlist, list) {
+               if (pidl->pid == pid) {
+                       list_del(&pidl->list);
+                       free(pidl);
                        break;
-
-               pname = get_name_by_pid(pid);
-               if (pname == NULL)
-                       continue;
-               if (strcmp(pname, name))
-                       continue;
-
-               return pid;
+               }
        }
 
        return 0;
@@ -467,23 +343,18 @@ static int read_pageframe_with_threads(int pid,
 int scan_all_pids(struct pageframe *pf, struct process *process_list,
                struct parse_opts *opts)
 {
+       struct pidlist *pidlist, *n;
        DIR *dir = NULL;
        int pid;
        int count = 0;
 
-       if (is_parse_option(opts, PARSE_PROCESS_NAME)) {
-               while ((pid = get_next_pid_by_name(&dir, opts->name))) {
-                       count += read_pageframe_with_threads(pid, pf,
-                                                       process_list,
-                                                       opts);
+       if (is_parse_option(opts, PARSE_PID)) {
+               list_for_each_entry_safe(pidlist, n, &opts->pidlist, list) {
+                       count += read_pageframe_with_threads(pidlist->pid, pf,
+                                                       process_list, opts);
                }
-               dir = NULL;
        }
 
-       if (is_parse_option(opts, PARSE_PID))
-               count = read_pageframe_with_threads(opts->pid, pf, process_list,
-                                               opts);
-
        if ((count == 0) && !(is_parse_option(opts, PARSE_MAP_NAME))) {
                printf("Failed to find any matching processes "
                        "with given arguments\n");