static void test_catalog_file_lang(void) { _cleanup_free_ char *lang = NULL, *lang2 = NULL, *lang3 = NULL, *lang4 = 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")); assert_se(catalog_file_lang("/x/y/systemd.catalog", &lang4) == 0); assert_se(lang4 == NULL); assert_se(catalog_file_lang("/x/y/systemd.ru_RU.catalog", &lang4) == 1); assert_se(streq(lang4, "ru_RU")); }
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; _cleanup_free_ char *deflang = NULL, *lang = NULL; bool got_id = false, empty_line = true; int r; assert(h); assert(sb); assert(path); f = fopen(path, "re"); if (!f) return log_error_errno(errno, "Failed to open file %s: %m", path); r = catalog_file_lang(path, &deflang); if (r < 0) log_error_errno(errno, "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; char *t; if (!fgets(line, sizeof(line), f)) { if (feof(f)) break; log_error_errno(errno, "Failed to read file %s: %m", path); return -errno; } n++; truncate_nl(line); if (line[0] == 0) { empty_line = true; continue; } if (strchr(COMMENTS "\n", line[0])) continue; if (empty_line && strlen(line) >= 2+1+32 && line[0] == '-' && line[1] == '-' && line[2] == ' ' && (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'; if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) { if (got_id) { r = finish_item(h, sb, id, lang ?: deflang, payload); if (r < 0) return r; free(lang); lang = NULL; } if (with_language) { t = strstrip(line + 2 + 1 + 32 + 1); r = catalog_entry_lang(path, n, t, deflang, &lang); if (r < 0) return r; } got_id = true; empty_line = false; id = jd; if (payload) payload[0] = '\0'; continue; } } /* Payload */ if (!got_id) { log_error("[%s:%u] Got payload before ID.", path, n); return -EINVAL; } a = payload ? strlen(payload) : 0; b = strlen(line); c = a + (empty_line ? 1 : 0) + b + 1 + 1; t = realloc(payload, c); if (!t) return log_oom(); if (empty_line) { t[a] = '\n'; memcpy(t + a + 1, line, b); t[a+b+1] = '\n'; t[a+b+2] = 0; } else { memcpy(t + a, line, b); t[a+b] = '\n'; t[a+b+1] = 0; } payload = t; empty_line = false; }