chiark / gitweb /
catalog: make sure strings are terminated
[elogind.git] / src / journal / catalog.c
index 3735ad9213d041712a7da91a56baf98b2ba4b799..b2c684ac2d130e02613e91cb712c2cd8e64be4a0 100644 (file)
@@ -34,6 +34,7 @@
 #include "hashmap.h"
 #include "strv.h"
 #include "strbuf.h"
+#include "strxcpyx.h"
 #include "conf-files.h"
 #include "mkdir.h"
 #include "catalog.h"
@@ -96,7 +97,7 @@ static int catalog_compare_func(const void *a, const void *b) {
                         return 1;
         }
 
-        return strncmp(i->language, j->language, sizeof(i->language));
+        return strcmp(i->language, j->language);
 }
 
 static int finish_item(
@@ -123,12 +124,13 @@ static int finish_item(
                 return log_oom();
 
         i->id = id;
-        strncpy(i->language, language, sizeof(i->language));
+        strscpy(i->language, sizeof(i->language), language);
         i->offset = htole64((uint64_t) offset);
 
         r = hashmap_put(h, i, i);
         if (r == EEXIST) {
-                log_warning("Duplicate entry for " SD_ID128_FORMAT_STR ".%s, ignoring.", SD_ID128_FORMAT_VAL(id), language ? language : "C");
+                log_warning("Duplicate entry for " SD_ID128_FORMAT_STR ".%s, ignoring.",
+                            SD_ID128_FORMAT_VAL(id), language ? language : "C");
                 free(i);
                 return 0;
         }
@@ -185,15 +187,15 @@ static int import_file(Hashmap *h, struct strbuf *sb, const char *path) {
                     line[0] == '-' &&
                     line[1] == '-' &&
                     line[2] == ' ' &&
-                    (line[2+1+32] == ' ' || line[2+1+32] == 0)) {
+                    (line[2+1+32] == ' ' || line[2+1+32] == '\0')) {
 
                         bool with_language;
                         sd_id128_t jd;
 
                         /* New entry */
 
-                        with_language = line[2+1+32] != 0;
-                        line[2+1+32] = 0;
+                        with_language = line[2+1+32] != '\0';
+                        line[2+1+32] = '\0';
 
                         if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) {
 
@@ -211,21 +213,21 @@ static int import_file(Hashmap *h, struct strbuf *sb, const char *path) {
                                                 log_error("[%s:%u] Language too short.", path, n);
                                                 return -EINVAL;
                                         }
-                                        if (c > sizeof(language)) {
+                                        if (c > sizeof(language) - 1) {
                                                 log_error("[%s:%u] language too long.", path, n);
                                                 return -EINVAL;
                                         }
 
-                                        strncpy(language, t, sizeof(language));
+                                        strscpy(language, sizeof(language), t);
                                 } else
-                                        zero(language);
+                                        language[0] = '\0';
 
                                 got_id = true;
                                 empty_line = false;
                                 id = jd;
 
                                 if (payload)
-                                        payload[0] = 0;
+                                        payload[0] = '\0';
 
                                 continue;
                         }
@@ -296,7 +298,7 @@ int catalog_update(void) {
                 goto finish;
         }
 
-        r = conf_files_list_strv(&files, ".catalog", (const char **) conf_file_dirs);
+        r = conf_files_list_strv(&files, ".catalog", NULL, (const char **) conf_file_dirs);
         if (r < 0) {
                 log_error("Failed to get catalog files: %s", strerror(-r));
                 goto finish;
@@ -324,7 +326,9 @@ int catalog_update(void) {
 
         n = 0;
         HASHMAP_FOREACH(i, h, j) {
-                log_debug("Found " SD_ID128_FORMAT_STR ", language %s", SD_ID128_FORMAT_VAL(i->id), isempty(i->language) ? "C" : i->language);
+                log_debug("Found " SD_ID128_FORMAT_STR ", language %s",
+                          SD_ID128_FORMAT_VAL(i->id),
+                          isempty(i->language) ? "C" : i->language);
                 items[n++] = *i;
         }
 
@@ -551,7 +555,23 @@ static char *find_header(const char *s, const char *header) {
         }
 }
 
-int catalog_list(FILE *f) {
+static void dump_catalog_entry(FILE *f, sd_id128_t id, const char *s, bool oneline) {
+        if (oneline) {
+                _cleanup_free_ char *subject = NULL, *defined_by = NULL;
+
+                subject = find_header(s, "Subject:");
+                defined_by = find_header(s, "Defined-By:");
+
+                fprintf(f, SD_ID128_FORMAT_STR " %s: %s\n",
+                        SD_ID128_FORMAT_VAL(id),
+                        strna(defined_by), strna(subject));
+        } else
+                fprintf(f, "-- " SD_ID128_FORMAT_STR "\n%s\n",
+                        SD_ID128_FORMAT_VAL(id), s);
+}
+
+
+int catalog_list(FILE *f, bool oneline) {
         _cleanup_close_ int fd = -1;
         void *p = NULL;
         struct stat st;
@@ -571,17 +591,13 @@ int catalog_list(FILE *f) {
 
         for (n = 0; n < le64toh(h->n_items); n++) {
                 const char *s;
-                _cleanup_free_ char *subject = NULL, *defined_by = NULL;
 
                 if (last_id_set && sd_id128_equal(last_id, items[n].id))
                         continue;
 
                 assert_se(s = find_id(p, items[n].id));
 
-                subject = find_header(s, "Subject:");
-                defined_by = find_header(s, "Defined-By:");
-
-                fprintf(f, SD_ID128_FORMAT_STR " %s: %s\n", SD_ID128_FORMAT_VAL(items[n].id), strna(defined_by), strna(subject));
+                dump_catalog_entry(f, items[n].id, s, oneline);
 
                 last_id_set = true;
                 last_id = items[n].id;
@@ -591,3 +607,37 @@ int catalog_list(FILE *f) {
 
         return 0;
 }
+
+int catalog_list_items(FILE *f, bool oneline, char **items) {
+        char **item;
+        int r = 0;
+
+        STRV_FOREACH(item, items) {
+                sd_id128_t id;
+                int k;
+                char _cleanup_free_ *msg = NULL;
+
+                k = sd_id128_from_string(*item, &id);
+                if (k < 0) {
+                        log_error("Failed to parse id128 '%s': %s",
+                                  *item, strerror(-k));
+                        if (r == 0)
+                                r = k;
+                        continue;
+                }
+
+                k = catalog_get(id, &msg);
+                if (k < 0) {
+                        log_full(k == -ENOENT ? LOG_NOTICE : LOG_ERR,
+                                 "Failed to retrieve catalog entry for '%s': %s",
+                                  *item, strerror(-k));
+                        if (r == 0)
+                                r = k;
+                        continue;
+                }
+
+                dump_catalog_entry(f, id, msg, oneline);
+        }
+
+        return r;
+}