dump_systemstate config: add `order` config entry 67/227067/2
authorMichal Bloch <m.bloch@samsung.com>
Fri, 6 Mar 2020 13:21:45 +0000 (14:21 +0100)
committerKarol Lewandowski <k.lewandowsk@samsung.com>
Mon, 9 Mar 2020 13:40:22 +0000 (14:40 +0100)
Sort thereby

Change-Id: I1bfe5484a50763297048924d98374b0eaee66cf6
Signed-off-by: Michal Bloch <m.bloch@samsung.com>
src/dump_systemstate/extras.c

index 2d8fcb9..016acf6 100644 (file)
@@ -33,6 +33,7 @@
 
 // C
 #include <assert.h>
+#include <limits.h>
 #include <stdbool.h>
 
 static inline void cleanup_dictionary(dictionary **ini)
@@ -59,12 +60,25 @@ static const char *const INI_KEYS[COUNT_INI_FIELDS] = {
        [INI_FIELD_ARGS]  = "args",
        [INI_FIELD_ENV]   = "env",
        [INI_FIELD_FLAG]  = "cmdflag",
+       // non-string field: "order"
 };
 static const size_t MAX_INI_KEY_LEN = 7;
 
 struct extra_dump_item {
        // not separate named fields, for convenient iteration
-       const char *fields[COUNT_INI_FIELDS];
+       char *fields[COUNT_INI_FIELDS];
+       int order;
+};
+
+void cleanup_extra_dump_item(struct extra_dump_item *edi)
+{
+       for (size_t i = 0; i < ARRAY_SIZE(edi->fields); ++i)
+               free(edi->fields[i]);
+}
+
+struct extra_items_vector {
+       size_t size;
+       struct extra_dump_item *data;
 };
 
 bool check_cmdflag(const char *const flag, int argc, char **argv)
@@ -153,13 +167,12 @@ int handle_extra_file(int out_fd, struct extra_dump_item *item, int argc, char *
 
 typedef int (*handle_ini_section_t)(int out_fd, struct extra_dump_item *, int argc, char **argv);
 
-static int handle_ini_Nth_section(int out_fd, const dictionary *ini, int n, handle_ini_section_t handle_ini_section, int argc, char **argv)
+static int handle_ini_Nth_section(struct extra_dump_item *item, const dictionary *ini, int n)
 {
-       assert(out_fd >= 0);
+       assert(item);
        assert(ini);
        assert(n >= 0);
        assert(n < iniparser_getnsec(ini));
-       assert(handle_ini_section);
 
        const char *const secname = iniparser_getsecname(ini, n);
        assert(secname); // can only be NULL if `ini` is NULL or `n` is outta bounds
@@ -169,21 +182,34 @@ static int handle_ini_Nth_section(int out_fd, const dictionary *ini, int n, hand
        memcpy(key_buf, secname, secname_len);
        key_buf[secname_len] = ':';
 
+       int ret = 0;
        char *const key_suffix_ptr = key_buf + secname_len + 1;
-       struct extra_dump_item item;
-       for (size_t i = 0; i < ARRAY_SIZE(item.fields); ++i) {
+       for (size_t i = 0; i < ARRAY_SIZE(item->fields); ++i) {
                strcpy(key_suffix_ptr, INI_KEYS[i]);
-               item.fields[i] = iniparser_getstring(ini, key_buf, NULL);
+
+               const char *tmp = iniparser_getstring(ini, key_buf, NULL);
+               if (!tmp) {
+                       item->fields[i] = NULL;
+                       continue;
+               }
+
+               item->fields[i] = strdup(tmp);
+               if (!item->fields[i])
+                       ret |= EXIT_ERR;
        }
 
-       return handle_ini_section(out_fd, &item, argc, argv);
+       strcpy(key_suffix_ptr, "order");
+       const char *tmp = iniparser_getstring(ini, key_buf, NULL);
+       item->order = tmp ? atoi(tmp) : INT_MAX;
+
+       return ret;
 }
 
-static int handle_extra_ini(int out_fd, const char *ini_path, handle_ini_section_t handle_ini_section, int argc, char **argv)
+static int handle_extra_ini(int out_fd, struct extra_items_vector *eiv, const char *ini_path)
 {
        assert(out_fd >= 0);
+       assert(eiv);
        assert(ini_path);
-       assert(handle_ini_section);
 
        __attribute__((cleanup(cleanup_dictionary))) dictionary *ini = iniparser_load(ini_path);
        if (!ini) {
@@ -194,9 +220,16 @@ static int handle_extra_ini(int out_fd, const char *ini_path, handle_ini_section
        const int nsec = iniparser_getnsec(ini);
        assert(nsec >= 0); // can only be -1 when ini is NULL
 
+       const size_t prev_size = eiv->size;
+       struct extra_dump_item *const temp = realloc(eiv->data, (eiv->size + nsec) * sizeof *eiv->data);
+       if (!temp)
+               return EXIT_ERR;
+       eiv->data = temp;
+       eiv->size += nsec;
+
        int ret = 0;
        for (int i = 0; i < nsec; ++i)
-               ret |= handle_ini_Nth_section(out_fd, ini, i, handle_ini_section, argc, argv);
+               ret |= handle_ini_Nth_section(eiv->data + prev_size + i, ini, i);
        return ret;
 }
 
@@ -206,6 +239,26 @@ static int config_entry_filter(const struct dirent *de)
        return de->d_type == DT_REG && string_ends_with(de->d_name, ".conf");
 }
 
+int handle_items_vector(struct extra_items_vector *eiv, int out_fd, handle_ini_section_t handle_ini_section, int argc, char **argv)
+{
+       inline int cmp(const void *a, const void *b) {
+               return ((struct extra_dump_item *)a)->order - ((struct extra_dump_item *)b)->order;
+       }
+       qsort(eiv->data, eiv->size, sizeof *eiv->data, cmp);
+
+       int ret = 0;
+       for (size_t i = 0; i < eiv->size; ++i)
+               ret |= handle_ini_section(out_fd, eiv->data + i, argc, argv);
+       return ret;
+}
+
+void free_items_vector(struct extra_items_vector *eiv)
+{
+       for (size_t i = 0; i < eiv->size; ++i)
+               cleanup_extra_dump_item(eiv->data + i);
+       free(eiv->data);
+}
+
 int handle_extra_dir(int out_fd, char *dir_path, handle_ini_section_t handle_ini_section, int argc, char **argv)
 {
        assert(out_fd >= 0);
@@ -226,6 +279,11 @@ int handle_extra_dir(int out_fd, char *dir_path, handle_ini_section_t handle_ini
                return EXIT_ERR;
        }
 
+       __attribute__((cleanup(free_items_vector))) struct extra_items_vector eiv = {
+               .size = 0,
+               .data = NULL,
+       };
+
        int ret = 0;
        for (int i = 0; i < entry_count; ++i) {
                struct dirent *const de = entries[i];
@@ -238,8 +296,10 @@ int handle_extra_dir(int out_fd, char *dir_path, handle_ini_section_t handle_ini
                snprintf(ini_path, sizeof ini_path, "%s/%s", dir_path, de->d_name);
                free(de);
 
-               ret |= handle_extra_ini(out_fd, ini_path, handle_ini_section, argc, argv);
+               ret |= handle_extra_ini(out_fd, &eiv, ini_path);
        }
+       ret |= handle_items_vector(&eiv, out_fd, handle_ini_section, argc, argv);
+
        free(entries);
        close(dir_fd);
        return ret;