X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=libustctl%2Flibustctl.c;h=c781283974035d5ed48b3c42e60ba5f026b46153;hb=686debc34cf055ffcb1f98a06df9fbaf27eeb441;hp=d57e6458b047a1d4c82353b331be4a8ac89fac79;hpb=e005efaa25bb1c65019e147e5290733cf5e0c82d;p=ust.git diff --git a/libustctl/libustctl.c b/libustctl/libustctl.c index d57e645..c781283 100644 --- a/libustctl/libustctl.c +++ b/libustctl/libustctl.c @@ -88,53 +88,180 @@ int ustctl_connect_pid(pid_t pid) return sock; } -pid_t *ustctl_get_online_pids(void) +static int realloc_pid_list(pid_t **pid_list, unsigned int *pid_list_size) { - struct dirent *dirent; - DIR *dir; - unsigned int ret_size = 1 * sizeof(pid_t), i = 0; + pid_t *new_pid_list; + unsigned int new_pid_list_size = 2 * *pid_list_size; - dir = opendir(SOCK_DIR); - if (!dir) { - return NULL; + new_pid_list = realloc(*pid_list, + new_pid_list_size * sizeof(pid_t)); + if (!*new_pid_list) { + return -1; } - pid_t *ret = (pid_t *) malloc(ret_size); + *pid_list = new_pid_list; + *pid_list_size = new_pid_list_size; + + return 0; +} + +static int get_pids_in_dir(DIR *dir, pid_t **pid_list, + unsigned int *pid_list_index, + unsigned int *pid_list_size) +{ + struct dirent *dirent; + long read_pid; while ((dirent = readdir(dir))) { if (!strcmp(dirent->d_name, ".") || - !strcmp(dirent->d_name, "..")) { + !strcmp(dirent->d_name, "..") || + !strcmp(dirent->d_name, "ust-consumer") || + dirent->d_type == DT_DIR) { continue; } - if (dirent->d_type != DT_DIR && - !!strcmp(dirent->d_name, "ust-consumer")) { - - sscanf(dirent->d_name, "%u", (unsigned int *) &ret[i]); - /* FIXME: Here we previously called pid_is_online, which - * always returned 1, now I replaced it with just 1. - * We need to figure out an intelligent way of solving - * this, maybe connect-disconnect. - */ - if (1) { - ret_size += sizeof(pid_t); - ret = (pid_t *) realloc(ret, ret_size); - ++i; + errno = 0; + read_pid = strtol(dirent->d_name, NULL, 10); + if (errno) { + continue; + } + + /* + * FIXME: Here we previously called pid_is_online, which + * always returned 1, now I replaced it with just 1. + * We need to figure out an intelligent way of solving + * this, maybe connect-disconnect. + */ + if (1) { + + (*pid_list)[(*pid_list_index)++] = read_pid; + + if (*pid_list_index == *pid_list_size) { + if (realloc_pid_list(pid_list, pid_list_size)) { + return -1; + } } } } - ret[i] = 0; /* Array end */ + (*pid_list)[*pid_list_index] = 0; /* Array end */ - if (ret[0] == 0) { - /* No PID at all */ - free(ret); + return 0; +} + +static pid_t *get_pids_non_root(void) +{ + char *dir_name; + DIR *dir; + unsigned int pid_list_index = 0, pid_list_size = 1; + pid_t *pid_list = NULL; + + dir_name = ustcomm_user_sock_dir(); + if (!dir_name) { return NULL; } + dir = opendir(dir_name); + if (!dir) { + goto free_dir_name; + } + + pid_list = malloc(pid_list_size * sizeof(pid_t)); + if (!pid_list) { + goto close_dir; + } + + if (get_pids_in_dir(dir, &pid_list, &pid_list_index, &pid_list_size)) { + /* if any errors are encountered, force freeing of the list */ + pid_list[0] = 0; + } + +close_dir: closedir(dir); - return ret; + +free_dir_name: + free(dir_name); + + return pid_list; +} + +static pid_t *get_pids_root(void) +{ + char *dir_name; + DIR *tmp_dir, *dir; + unsigned int pid_list_index = 0, pid_list_size = 1; + pid_t *pid_list = NULL; + struct dirent *dirent; + int result; + + tmp_dir = opendir(USER_TMP_DIR); + if (!tmp_dir) { + return NULL; + } + + pid_list = malloc(pid_list_size * sizeof(pid_t)); + if (!pid_list) { + goto close_tmp_dir; + } + + while ((dirent = readdir(tmp_dir))) { + /* Compare the dir to check for the USER_SOCK_DIR_BASE prefix */ + if (!strncmp(dirent->d_name, USER_SOCK_DIR_BASE, + strlen(USER_SOCK_DIR_BASE))) { + + if (asprintf(&dir_name, USER_TMP_DIR "/%s", + dirent->d_name) < 0) { + goto close_tmp_dir; + } + + dir = opendir(dir_name); + + free(dir_name); + + if (!dir) { + continue; + } + + result = get_pids_in_dir(dir, &pid_list, &pid_list_index, + &pid_list_size); + + closedir(dir); + + if (result) { + /* + * if any errors are encountered, + * force freeing of the list + */ + pid_list[0] = 0; + break; + } + } + } + +close_tmp_dir: + closedir(tmp_dir); + + return pid_list; +} + +pid_t *ustctl_get_online_pids(void) +{ + pid_t *pid_list; + + if (geteuid()) { + pid_list = get_pids_non_root(); + } else { + pid_list = get_pids_root(); + } + + if (pid_list && pid_list[0] == 0) { + /* No PID at all */ + free(pid_list); + pid_list = NULL; + } + + return pid_list; } /**