From c7332b0844e28d9b70c3c763b929f105c1056fe8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Mon, 2 Dec 2013 21:35:31 -0500 Subject: [PATCH] catalog: determine language from the filename --- TODO | 5 ---- src/journal/catalog.c | 57 ++++++++++++++++++++++++++++++++------ src/journal/catalog.h | 1 + src/journal/test-catalog.c | 24 ++++++++++++++++ 4 files changed, 74 insertions(+), 13 deletions(-) diff --git a/TODO b/TODO index 20a9a0726..6773604c3 100644 --- a/TODO +++ b/TODO @@ -217,11 +217,6 @@ Features: * think about window-manager-run-as-user-service problem: exit 0 → activate shutdown.target; exit != 0 → restart service -* msgcatalog determine default language of entries from the catalog - file name. i.e. foobar.de_DE.catalog would set the default entry - name for the entries to de_DE if they aren't explicitly suffixed - individually. - * use "log level" rather than "log priority" everywhere * timedate: have global on/off switches for auto-time (NTP), and auto-timezone that connman can subscribe to. diff --git a/src/journal/catalog.c b/src/journal/catalog.c index 90ca00806..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; } diff --git a/src/journal/catalog.h b/src/journal/catalog.h index 24a2d0b55..5e15b99ac 100644 --- a/src/journal/catalog.h +++ b/src/journal/catalog.h @@ -34,4 +34,5 @@ int catalog_update(const char* database, const char* root, const char* const* di int catalog_get(const char* database, sd_id128_t id, char **data); int catalog_list(FILE *f, const char* database, bool oneline); int catalog_list_items(FILE *f, const char* database, bool oneline, char **items); +int catalog_file_lang(const char *filename, char **lang); extern const char * const catalog_file_dirs[]; diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c index 5db5bed8d..863b9f4b5 100644 --- a/src/journal/test-catalog.c +++ b/src/journal/test-catalog.c @@ -120,6 +120,28 @@ static void test_catalog_update(void) { assert(r >= 0); } +static void test_catalog_file_lang(void) { + _cleanup_free_ char *lang = NULL, *lang2 = NULL, *lang3 = NULL; + + assert_se(catalog_file_lang("systemd.de_DE.catalog", &lang) == 1); + assert_se(streq(lang, "de_DE")); + + assert_se(catalog_file_lang("systemd..catalog", &lang2) == 0); + assert_se(lang2 == NULL); + + assert_se(catalog_file_lang("systemd.fr.catalog", &lang2) == 1); + assert_se(streq(lang2, "fr")); + + assert_se(catalog_file_lang("systemd.fr.catalog.gz", &lang3) == 0); + assert_se(lang3 == NULL); + + assert_se(catalog_file_lang("systemd.01234567890123456789012345678901.catalog", &lang3) == 0); + assert_se(lang3 == NULL); + + assert_se(catalog_file_lang("systemd.0123456789012345678901234567890.catalog", &lang3) == 1); + assert_se(streq(lang3, "0123456789012345678901234567890")); +} + int main(int argc, char *argv[]) { _cleanup_free_ char *text = NULL; int r; @@ -144,5 +166,7 @@ int main(int argc, char *argv[]) { if (database) unlink(database); + test_catalog_file_lang(); + return 0; } -- 2.30.2