procfs: implement pid iterator 27/182927/6
authorLukasz Stanislawski <l.stanislaws@samsung.com>
Thu, 28 Jun 2018 17:22:21 +0000 (19:22 +0200)
committerLukasz Stanislawski <l.stanislaws@samsung.com>
Fri, 29 Jun 2018 12:38:39 +0000 (14:38 +0200)
Change-Id: I1fa1db698ba6e71778bee11dc606c9fa3b503f13

src/procfs.c
src/procfs.h

index a7f822d..bbcad07 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <dirent.h>
+#include <stdlib.h>
 
 #include "procfs.h"
 #include "log.h"
 #define STAT_FILEPATH "/proc/stat"
 #define PIDSTAT_FILEPATH "/proc/%d/stat"
 #define SMAPS_FILEPATH "/proc/%d/smaps"
+#define PROC_DIR_PATH "/proc/"
+
+struct procfs_pid_iterator
+{
+       DIR *dir;
+       int current_pid;
+};
 
 int procfs_read_system_load_average(struct procfs_load_average_info *info)
 {
@@ -266,3 +275,78 @@ int procfs_read_cpu_count(int *cpu_count)
 
        return 0;
 }
+
+bool _procfs_dirname_parse_pid(const char *dirname, int *pid)
+{
+       int parsed_pid;
+
+       if (sscanf(dirname, "%d", &parsed_pid) != 1) {
+               return false;
+       }
+       *pid = parsed_pid;
+       return true;
+}
+
+/**
+ * @brief returns true if pid_iterator could successfully read
+ * next pid from /proc directory, false otherwise
+ */
+bool _procfs_pid_iterator_next_internal(procfs_pid_iterator_t *iter)
+{
+       struct dirent *entry;
+       int pid;
+       bool ret = false;
+
+       // According to POSIX docs readdir is not-thread safe.
+       // however in glib recent implementations readdir
+       // is thread safe, so we can avoid using locks here.
+       while ((entry = readdir(iter->dir)) != NULL) {
+               if (_procfs_dirname_parse_pid(entry->d_name, &pid)) {
+                       iter->current_pid = pid;
+                       ret = true;
+                       break;
+               } else {
+                       continue;
+               }
+       }
+
+       return ret;
+}
+
+procfs_pid_iterator_t *procfs_get_pid_iterator()
+{
+       procfs_pid_iterator_t *ret = calloc(1, sizeof(struct procfs_pid_iterator));
+       if (!ret) {
+               ERR("calloc failed.");
+               return NULL;
+       }
+       ret->dir = opendir(PROC_DIR_PATH);
+       if (!ret->dir) {
+               ERR("opendir failed.");
+               procfs_pid_iterator_free(ret);
+               return NULL;
+       }
+       if (!_procfs_pid_iterator_next_internal(ret)) {
+               ERR("_procfs_pid_iterator_next_internal failed");
+               procfs_pid_iterator_free(ret);
+               return NULL;
+       }
+       return ret;
+}
+
+bool procfs_pid_iterator_next(procfs_pid_iterator_t *iterator)
+{
+       return _procfs_pid_iterator_next_internal(iterator);
+}
+
+int procfs_pid_iterator_get_pid(procfs_pid_iterator_t *iterator)
+{
+       return iterator->current_pid;
+}
+
+void procfs_pid_iterator_free(procfs_pid_iterator_t *iterator)
+{
+       if (!iterator) return;
+       if (iterator->dir) closedir(iterator->dir);
+       free(iterator);
+}
index acedc9f..6151d8e 100644 (file)
@@ -18,6 +18,7 @@
 #define __PROCFS_H_
 
 #include <stddef.h>
+#include <stdbool.h>
 
 /**
  * @brief System memory information.
@@ -147,4 +148,44 @@ int procfs_read_uptime(unsigned long *uptime);
  */
 int procfs_read_cpu_count(int *cpu_count);
 
+/**
+ * @brief Iterator over pids in /proc/ directory.
+ */
+typedef struct procfs_pid_iterator procfs_pid_iterator_t;
+
+/**
+ * @brief Move iterator to next entry.
+ *
+ * @param[in]: itearator
+ *
+ * @return returns true if there are more entries available, false otherwise
+ */
+bool procfs_pid_iterator_next(procfs_pid_iterator_t *iterator);
+
+/**
+ * @brief Gets current pid from iterator
+ *
+ * @param[in]: itearator
+ *
+ * @not User should always check validity of pid, since it not guaranteed that
+ * returned pid is still valid after function returns.
+ */
+int procfs_pid_iterator_get_pid(procfs_pid_iterator_t *iterator);
+
+/**
+ * @brief Frees procfs_pid_iterator_t
+ *
+ * @param[in]: itearator
+ */
+void procfs_pid_iterator_free(procfs_pid_iterator_t *iterator);
+
+/**
+ * @brief Gets pid iterator
+ *
+ * @return new procfs_pid_iterator_t or NULL or error or no pids is available.
+ *
+ * @note the returned value should be released wiht procfs_pid_iterator_free
+ */
+procfs_pid_iterator_t *procfs_get_pid_iterator();
+
 #endif