X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fjournal%2Fcatalog.c;h=2be81aa2f7db37940f810150a745ad87ac5bd0d9;hb=e9174f29c7e3ee45137537b126458718913a3ec5;hp=7681af66299b18370bed94f6e6c324a7170631aa;hpb=d3b6d0c21ea5a0d15ec6dbd8b8d179138b7463bc;p=elogind.git diff --git a/src/journal/catalog.c b/src/journal/catalog.c index 7681af662..2be81aa2f 100644 --- a/src/journal/catalog.c +++ b/src/journal/catalog.c @@ -125,7 +125,10 @@ static int finish_item( return log_oom(); i->id = id; - strscpy(i->language, sizeof(i->language), language); + if (language) { + assert(strlen(language) > 1 && strlen(language) < 32); + strcpy(i->language, language); + } i->offset = htole64((uint64_t) offset); r = hashmap_put(h, i, i); @@ -139,12 +142,34 @@ static int finish_item( return 0; } +int catalog_file_lang(const char* filename, char **lang) { + char *beg, *end, *_lang; + + end = endswith(filename, ".catalog"); + if (!end) + return 0; + + beg = end - 1; + while (beg > filename && *beg != '.') + beg --; + + if (beg <= filename || end <= beg + 1 || end - beg > 32) + return 0; + + _lang = strndup(beg + 1, end - beg - 1); + if (!_lang) + return -ENOMEM; + + *lang = _lang; + return 1; +} + int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *payload = NULL; unsigned n = 0; sd_id128_t id; - char language[32]; + _cleanup_free_ char *deflang = NULL, *lang = NULL; bool got_id = false, empty_line = true; int r; @@ -158,6 +183,12 @@ int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) { return -errno; } + r = catalog_file_lang(path, &deflang); + if (r < 0) + log_error("Failed to determine language for file %s: %m", path); + if (r == 1) + log_debug("File %s has language %s.", path, deflang); + for (;;) { char line[LINE_MAX]; size_t a, b, c; @@ -201,9 +232,12 @@ int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) { if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) { if (got_id) { - r = finish_item(h, sb, id, language, payload); + r = finish_item(h, sb, id, lang ?: deflang, payload); if (r < 0) return r; + + free(lang); + lang = NULL; } if (with_language) { @@ -214,14 +248,21 @@ int catalog_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) - 1) { + if (c > 31) { log_error("[%s:%u] language too long.", path, n); return -EINVAL; } - strscpy(language, sizeof(language), t); - } else - language[0] = '\0'; + if (deflang) { + log_warning("[%s:%u] language %s", path, n, + streq(t, deflang) ? + "specified unnecessarily" : + "differs from default for file"); + lang = strdup(t); + if (!lang) + return -ENOMEM; + } + } got_id = true; empty_line = false; @@ -264,7 +305,7 @@ int catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) { } if (got_id) { - r = finish_item(h, sb, id, language, payload); + r = finish_item(h, sb, id, lang ?: deflang, payload); if (r < 0) return r; } @@ -277,7 +318,7 @@ static long write_catalog(const char *database, Hashmap *h, struct strbuf *sb, CatalogHeader header; _cleanup_fclose_ FILE *w = NULL; int r; - char _cleanup_free_ *d, *p = NULL; + _cleanup_free_ char *d, *p = NULL; size_t k; d = dirname_malloc(database); @@ -399,7 +440,7 @@ int catalog_update(const char* database, const char* root, const char* const* di } assert(n == hashmap_size(h)); - qsort(items, n, sizeof(CatalogItem), catalog_compare_func); + qsort_safe(items, n, sizeof(CatalogItem), catalog_compare_func); r = write_catalog(database, h, sb, items, n); if (r < 0) @@ -627,7 +668,7 @@ int catalog_list_items(FILE *f, const char *database, bool oneline, char **items STRV_FOREACH(item, items) { sd_id128_t id; int k; - char _cleanup_free_ *msg = NULL; + _cleanup_free_ char *msg = NULL; k = sd_id128_from_string(*item, &id); if (k < 0) {