]> git.itanic.dy.fi Git - scan-pagemap/blob - pidlib.c
Analyzer: Print detailed kpageflag statistics
[scan-pagemap] / pidlib.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <libgen.h>
4 #include <errno.h>
5 #include <string.h>
6
7 #include "pidlib.h"
8
9 char *get_name_by_pid(int pid)
10 {
11         static int last_pid;
12         static char cmdline[128];
13         static char *bname;
14
15         if (last_pid == pid)
16                 return bname;
17
18         if (read_cmdline(pid, pid, cmdline, sizeof(cmdline))) {
19                 bname = NULL;
20                 return NULL;
21         }
22
23         bname = basename(cmdline);
24
25         last_pid = pid;
26         return bname;
27 }
28
29 static int parse_pid(DIR **dir)
30 {
31         struct dirent *dirent;
32         int error;
33
34 restart:
35         dirent = readdir(*dir);
36         if (!dirent) {
37                 if (errno == 0) {
38                         closedir(*dir);
39                         *dir = NULL;
40                         return 0;
41                 }
42                 error = errno;
43                 printf("Failed to read /proc directory: %s\n", strerror(error));
44                 return -1;
45         }
46
47         if (dirent->d_name[0] < '0' || dirent->d_name[0] > '9')
48                 goto restart;
49
50         return atoi(dirent->d_name);
51 }
52
53 static int opendir_check(DIR **dir, const char *path)
54 {
55         int error;
56
57         if (!*dir) {
58                 *dir = opendir(path);
59                 if (!dir) {
60                         error = errno;
61                         fprintf(stderr, "Failed to open %s directory: %s\n",
62                                 path, strerror(error));
63                         return -1;
64                 }
65         }
66
67         return 0;
68 }
69
70 int get_next_tid(int pid, DIR **dir)
71 {
72         if (*dir == NULL) {
73                 char path[64];
74
75                 snprintf(path, sizeof(path), "/proc/%d/task/", pid);
76                 if (opendir_check(dir, path))
77                         return -1;
78         }
79
80         return parse_pid(dir);
81 }
82
83 int get_next_pid(DIR **dir)
84 {
85         if (opendir_check(dir, "/proc"))
86                 return -1;
87
88         return parse_pid(dir);
89 }
90
91 int get_next_pid_by_name(DIR **dir, char *name)
92 {
93         int pid;
94         char *pname;
95
96         if (opendir_check(dir, "/proc"))
97                 return -1;
98
99         while (1) {
100                 pid = parse_pid(dir);
101                 if (pid <= 0)
102                         break;
103
104                 pname = get_name_by_pid(pid);
105                 if (pname == NULL)
106                         continue;
107                 if (strcmp(pname, name))
108                         continue;
109
110                 return pid;
111         }
112
113         return 0;
114 }
115
116 int read_cmdline(int pid, int tid, char *cmdline, size_t len)
117 {
118         FILE *file;
119         char path[512];
120         int ret;
121
122         snprintf(path, sizeof(path), "/proc/%d/task/%d/cmdline", pid, tid);
123         file = fopen(path, "rb");
124
125         if (!file)
126                 return -1;
127
128         ret = fread(cmdline, 1, len, file);
129         if (ret > 0)
130                 cmdline[ret - 1] = 0;
131         fclose(file);
132
133         return ret > 0 ? 0 : -1;
134 }
135