2 #include "utils/common/common.h"
3 #include "utils_proc_pids.h"
5 #define UTIL_NAME "utils_proc_pids"
7 void pids_list_free(pids_list_t *list) {
10 pids_list_t *current = list;
11 while (current != NULL) {
12 pids_list_t *previous = current;
13 current = current->next;
18 int is_proc_name_valid(const char *name) {
21 unsigned len = strlen(name);
22 if (len > 0 && len <= MAX_PROC_NAME_LEN)
26 ": Process name \'%s\' is too long. Max supported len is %d chars.",
27 name, MAX_PROC_NAME_LEN);
34 int pids_list_add_pid(pids_list_t **list, const pid_t pid) {
37 pids_list_t *new_element = calloc(1, sizeof(*new_element));
39 if (new_element == NULL) {
40 ERROR(UTIL_NAME ": Alloc error\n");
43 new_element->pid = pid;
44 new_element->next = NULL;
46 pids_list_t **current = list;
47 while (*current != NULL) {
48 current = &((*current)->next);
50 *current = new_element;
54 int pids_list_contains_pid(pids_list_t *list, const pid_t pid) {
57 pids_list_t *current = list;
58 while (current != NULL) {
59 if (current->pid == pid)
61 current = current->next;
66 int pids_list_add_pids_list(pids_list_t **dst, pids_list_t *src,
72 pids_list_t *current = src;
75 while (current != NULL) {
76 ret = pids_list_add_pid(dst, current->pid);
81 current = current->next;
87 int read_proc_name(const char *procfs_path, const struct dirent *pid_entry,
88 char *name, const size_t out_size) {
93 memset(name, 0, out_size);
95 const char *comm_file_name = "comm";
97 char *path = ssnprintf_alloc("%s/%s/%s", procfs_path, pid_entry->d_name,
101 FILE *f = fopen(path, "r");
103 ERROR(UTIL_NAME ": Failed to open comm file, error: %d\n", errno);
107 size_t read_length = fread(name, sizeof(char), out_size, f);
108 name[out_size - 1] = '\0';
111 /* strip new line ending */
112 char *newline = strchr(name, '\n');
120 int get_pid_number(struct dirent *entry, pid_t *pid) {
121 char *tmp_end; /* used for strtoul error check*/
123 if (pid == NULL || entry == NULL)
126 if (entry->d_type != DT_DIR)
129 /* trying to get pid number from directory name*/
130 *pid = strtoul(entry->d_name, &tmp_end, 10);
131 if (*tmp_end != '\0') {
132 return -1; /* conversion failed, not proc-pid */
134 /* all checks passed, marking as success */
138 void pids_list_to_array(pid_t *array, pids_list_t *list,
139 const size_t array_length) {
143 assert(array_length > 0);
147 while (list != NULL && current < array_length) {
148 array[current] = list->pid;
154 int initialize_proc_pids(const char **procs_names_array,
155 const size_t procs_names_array_size,
156 proc_pids_t **proc_pids_array) {
158 assert(proc_pids_array);
159 assert(NULL == *proc_pids_array);
161 /* Copy procs names to output array. Initialize pids list with NULL value. */
163 calloc(procs_names_array_size, sizeof(**proc_pids_array));
165 if (NULL == (*proc_pids_array))
168 for (size_t i = 0; i < procs_names_array_size; ++i) {
169 sstrncpy((*proc_pids_array)[i].proccess_name, procs_names_array[i],
170 STATIC_ARRAY_SIZE((*proc_pids_array)[i].proccess_name));
171 (*proc_pids_array)[i].pids = NULL;
177 int fetch_pids_for_procs(const char *procfs_path,
178 const char **procs_names_array,
179 const size_t procs_names_array_size,
180 proc_pids_t **proc_pids_array) {
182 assert(procs_names_array);
183 assert(procs_names_array_size);
185 DIR *proc_dir = opendir(procfs_path);
186 if (proc_dir == NULL) {
187 ERROR(UTIL_NAME ": Could not open %s directory, error: %d", procfs_path,
192 int init_result = initialize_proc_pids(
193 procs_names_array, procs_names_array_size, proc_pids_array);
194 if (0 != init_result)
197 /* Go through procfs and find PIDS and their comms */
198 struct dirent *entry;
199 while ((entry = readdir(proc_dir)) != NULL) {
202 int pid_conversion = get_pid_number(entry, &pid);
203 if (pid_conversion < 0)
208 read_proc_name(procfs_path, entry, comm, sizeof(proc_comm_t));
209 if (read_result <= 0) {
210 ERROR(UTIL_NAME ": Comm file skipped. Read result: %d", read_result);
214 /* Try to find comm in input procs array (proc_pids_array has same names) */
215 for (size_t i = 0; i < procs_names_array_size; ++i) {
216 if (0 == strncmp(comm, (*proc_pids_array)[i].proccess_name,
217 STATIC_ARRAY_SIZE(comm)))
218 pids_list_add_pid(&((*proc_pids_array)[i].pids), pid);
222 int close_result = closedir(proc_dir);
223 if (0 != close_result) {
224 ERROR(UTIL_NAME ": failed to close %s directory, error: %d", procfs_path,
226 sfree((*proc_pids_array));
232 int pids_list_diff(pids_list_t *prev, pids_list_t *curr, pids_list_t **added,
233 size_t *added_num, pids_list_t **removed,
234 size_t *removed_num) {
235 assert(prev || curr);
240 /* append all PIDs from curr to added*/
241 return pids_list_add_pids_list(added, curr, added_num);
242 } else if (NULL == curr) {
243 /* append all PIDs from prev to removed*/
244 return pids_list_add_pids_list(removed, prev, removed_num);
247 pids_list_t *item = prev;
248 while (item != NULL) {
249 if (0 == pids_list_contains_pid(curr, item->pid)) {
250 int add_result = pids_list_add_pid(removed, item->pid);
259 while (item != NULL) {
260 if (0 == pids_list_contains_pid(prev, item->pid)) {
261 int add_result = pids_list_add_pid(added, item->pid);