catalog.c revision b826ab586c9e0a9c0d438a75c28cf3a8ab485929
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer/***
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer This file is part of systemd.
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Copyright 2012 Lennart Poettering
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer systemd is free software; you can redistribute it and/or modify it
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer under the terms of the GNU Lesser General Public License as published by
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt the Free Software Foundation; either version 2.1 of the License, or
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt (at your option) any later version.
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt systemd is distributed in the hope that it will be useful, but
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt WITHOUT ANY WARRANTY; without even the implied warranty of
4be4833ece2856e0cacc09f8f8b2c02b320751faMartin Pitt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier Lesser General Public License for more details.
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier You should have received a copy of the GNU Lesser General Public License
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier along with systemd; If not, see <http://www.gnu.org/licenses/>.
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier***/
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <fcntl.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <stdio.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <unistd.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <errno.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <string.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <sys/mman.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <locale.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "util.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "log.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "sparse-endian.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "sd-id128.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "hashmap.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "strv.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "strbuf.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "conf-files.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "mkdir.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "catalog.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "siphash24.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalierconst char * const catalog_file_dirs[] = {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier "/usr/local/lib/systemd/catalog/",
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier "/usr/lib/systemd/catalog/",
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier NULL
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier};
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#define CATALOG_SIGNATURE (uint8_t[]) { 'R', 'H', 'H', 'H', 'K', 'S', 'L', 'P' }
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevaliertypedef struct CatalogHeader {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier uint8_t signature[8]; /* "RHHHKSLP" */
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier le32_t compatible_flags;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier le32_t incompatible_flags;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier le64_t header_size;
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt le64_t n_items;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier le64_t catalog_item_size;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier} CatalogHeader;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevaliertypedef struct CatalogItem {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier sd_id128_t id;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier char language[32];
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier le64_t offset;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier} CatalogItem;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalierstatic void catalog_hash_func(const void *p, struct siphash *state) {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier const CatalogItem *i = p;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier siphash24_compress(&i->id, sizeof(i->id), state);
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier siphash24_compress(i->language, strlen(i->language), state);
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier}
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalierstatic int catalog_compare_func(const void *a, const void *b) {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier const CatalogItem *i = a, *j = b;
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek unsigned k;
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier for (k = 0; k < ELEMENTSOF(j->id.bytes); k++) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (i->id.bytes[k] < j->id.bytes[k])
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -1;
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek if (i->id.bytes[k] > j->id.bytes[k])
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt return 1;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return strcmp(i->language, j->language);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierconst struct hash_ops catalog_hash_ops = {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier .hash = catalog_hash_func,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier .compare = catalog_compare_func
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier};
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int finish_item(
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier Hashmap *h,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier struct strbuf *sb,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier sd_id128_t id,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier const char *language,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier const char *payload) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier ssize_t offset;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _cleanup_free_ CatalogItem *i = NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(h);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(sb);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(payload);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier offset = strbuf_add_string(sb, payload, strlen(payload));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (offset < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return log_oom();
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier i = new0(CatalogItem, 1);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!i)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return log_oom();
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier i->id = id;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (language) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(strlen(language) > 1 && strlen(language) < 32);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier strcpy(i->language, language);
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier i->offset = htole64((uint64_t) offset);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = hashmap_put(h, i, i);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r == -EEXIST) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_warning("Duplicate entry for " SD_ID128_FORMAT_STR ".%s, ignoring.",
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier SD_ID128_FORMAT_VAL(id), language ? language : "C");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier } else if (r < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier i = NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierint catalog_file_lang(const char* filename, char **lang) {
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek char *beg, *end, *_lang;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
b8667ee4162cd2510363602b417cecede9fd2ccaZbigniew Jędrzejewski-Szmek end = endswith(filename, ".catalog");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!end)
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
b8667ee4162cd2510363602b417cecede9fd2ccaZbigniew Jędrzejewski-Szmek beg = end - 1;
b8667ee4162cd2510363602b417cecede9fd2ccaZbigniew Jędrzejewski-Szmek while (beg > filename && *beg != '.' && *beg != '/' && end - beg < 32)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier beg --;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (*beg != '.' || end <= beg + 1)
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _lang = strndup(beg + 1, end - beg - 1);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!_lang)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -ENOMEM;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier *lang = _lang;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 1;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int catalog_entry_lang(const char* filename, int line,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier const char* t, const char* deflang, char **lang) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier size_t c;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier c = strlen(t);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (c == 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("[%s:%u] Language too short.", filename, line);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -EINVAL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (c > 31) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("[%s:%u] language too long.", filename, line);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -EINVAL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (deflang) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (streq(t, deflang)) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_warning("[%s:%u] language specified unnecessarily",
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier filename, line);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier } else
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_warning("[%s:%u] language differs from default for file",
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier filename, line);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier *lang = strdup(t);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!*lang)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -ENOMEM;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierint catalog_import_file(Hashmap *h, struct strbuf *sb, const char *path) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _cleanup_fclose_ FILE *f = NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _cleanup_free_ char *payload = NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier unsigned n = 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier sd_id128_t id;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _cleanup_free_ char *deflang = NULL, *lang = NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier bool got_id = false, empty_line = true;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(h);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(sb);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(path);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier f = fopen(path, "re");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!f)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return log_error_errno(errno, "Failed to open file %s: %m", path);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = catalog_file_lang(path, &deflang);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error_errno(errno, "Failed to determine language for file %s: %m", path);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r == 1)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_debug("File %s has language %s.", path, deflang);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier for (;;) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier char line[LINE_MAX];
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier size_t a, b, c;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier char *t;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!fgets(line, sizeof(line), f)) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (feof(f))
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier break;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error_errno(errno, "Failed to read file %s: %m", path);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier n++;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier truncate_nl(line);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (line[0] == 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier empty_line = true;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier continue;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (strchr(COMMENTS "\n", line[0]))
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier continue;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (empty_line &&
4be4833ece2856e0cacc09f8f8b2c02b320751faMartin Pitt strlen(line) >= 2+1+32 &&
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier line[0] == '-' &&
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier line[1] == '-' &&
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier line[2] == ' ' &&
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier (line[2+1+32] == ' ' || line[2+1+32] == '\0')) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier bool with_language;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier sd_id128_t jd;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
cffae62bcb6912fbaf1b7b282d9d170c9d308897Martin Pitt /* New entry */
cffae62bcb6912fbaf1b7b282d9d170c9d308897Martin Pitt
cffae62bcb6912fbaf1b7b282d9d170c9d308897Martin Pitt with_language = line[2+1+32] != '\0';
cffae62bcb6912fbaf1b7b282d9d170c9d308897Martin Pitt line[2+1+32] = '\0';
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt if (got_id) {
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt r = finish_item(h, sb, id, lang ?: deflang, payload);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier lang = mfree(lang);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (with_language) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier t = strstrip(line + 2 + 1 + 32 + 1);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = catalog_entry_lang(path, n, t, deflang, &lang);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier got_id = true;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier empty_line = false;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier id = jd;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (payload)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier payload[0] = '\0';
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier continue;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* Payload */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!got_id) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("[%s:%u] Got payload before ID.", path, n);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -EINVAL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
25b47f96d9601ff566257b2a31bfb5f4bd25d661Marko Myllynen a = payload ? strlen(payload) : 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier b = strlen(line);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier c = a + (empty_line ? 1 : 0) + b + 1 + 1;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier t = realloc(payload, c);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!t)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return log_oom();
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (empty_line) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier t[a] = '\n';
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier memcpy(t + a + 1, line, b);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier t[a+b+1] = '\n';
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier t[a+b+2] = 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier } else {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier memcpy(t + a, line, b);
53d90f9582f96208b3674da823ad1a3d2c3b1aa4Martin Pitt t[a+b] = '\n';
53d90f9582f96208b3674da823ad1a3d2c3b1aa4Martin Pitt t[a+b+1] = 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier payload = t;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier empty_line = false;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (got_id) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = finish_item(h, sb, id, lang ?: deflang, payload);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic long write_catalog(const char *database, Hashmap *h, struct strbuf *sb,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier CatalogItem *items, size_t n) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer CatalogHeader header;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _cleanup_fclose_ FILE *w = NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _cleanup_free_ char *d, *p = NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier size_t k;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer d = dirname_malloc(database);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!d)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return log_oom();
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = mkdir_p(d, 0775);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return log_error_errno(r, "Recursive mkdir %s: %m", d);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = fopen_temporary(database, &w, &p);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return log_error_errno(r, "Failed to open database for writing: %s: %m",
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer database);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer zero(header);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer memcpy(header.signature, CATALOG_SIGNATURE, sizeof(header.signature));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer header.header_size = htole64(ALIGN_TO(sizeof(CatalogHeader), 8));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer header.catalog_item_size = htole64(sizeof(CatalogItem));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer header.n_items = htole64(hashmap_size(h));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = -EIO;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer k = fwrite(&header, 1, sizeof(header), w);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (k != sizeof(header)) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("%s: failed to write header.", p);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto error;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer k = fwrite(items, 1, n * sizeof(CatalogItem), w);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (k != n * sizeof(CatalogItem)) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("%s: failed to write database.", p);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto error;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer k = fwrite(sb->buf, 1, sb->len, w);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (k != sb->len) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("%s: failed to write strings.", p);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto error;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = fflush_and_check(w);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error_errno(r, "%s: failed to write database: %m", p);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto error;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer fchmod(fileno(w), 0644);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (rename(p, database) < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = log_error_errno(errno, "rename (%s -> %s) failed: %m", p, database);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier goto error;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return ftell(w);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyererror:
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer (void) unlink(p);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint catalog_update(const char* database, const char* root, const char* const* dirs) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _cleanup_strv_free_ char **files = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char **f;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer struct strbuf *sb = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _cleanup_hashmap_free_free_ Hashmap *h = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _cleanup_free_ CatalogItem *items = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer CatalogItem *i;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Iterator j;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unsigned n;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer long r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer h = hashmap_new(&catalog_hash_ops);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sb = strbuf_new();
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!h || !sb) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = log_oom();
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto finish;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = conf_files_list_strv(&files, ".catalog", root, dirs);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error_errno(r, "Failed to get catalog files: %m");
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto finish;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer STRV_FOREACH(f, files) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_debug("Reading file '%s'", *f);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = catalog_import_file(h, sb, *f);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error_errno(r, "Failed to import file '%s': %m", *f);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto finish;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (hashmap_size(h) <= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_info("No items in catalog.");
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto finish;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer } else
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_debug("Found %u items in catalog.", hashmap_size(h));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer strbuf_complete(sb);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer items = new(CatalogItem, hashmap_size(h));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!items) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = log_oom();
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto finish;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer n = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer HASHMAP_FOREACH(i, h, j) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_debug("Found " SD_ID128_FORMAT_STR ", language %s",
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SD_ID128_FORMAT_VAL(i->id),
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer isempty(i->language) ? "C" : i->language);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer items[n++] = *i;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(n == hashmap_size(h));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer qsort_safe(items, n, sizeof(CatalogItem), catalog_compare_func);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = write_catalog(database, h, sb, items, n);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error_errno(r, "Failed to write %s: %m", database);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer else
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_debug("%s: wrote %u items, with %zu bytes of strings, %ld total size.",
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer database, n, sb->len, r);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerfinish:
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (sb)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer strbuf_cleanup(sb);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r < 0 ? r : 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const CatalogHeader *h;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int fd;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer void *p;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer struct stat st;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(_fd);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(_st);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(_p);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer fd = open(database, O_RDONLY|O_CLOEXEC);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (fd < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (fstat(fd, &st) < 0) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer safe_close(fd);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -errno;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (st.st_size < (off_t) sizeof(CatalogHeader)) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer safe_close(fd);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -EINVAL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer p = mmap(NULL, PAGE_ALIGN(st.st_size), PROT_READ, MAP_SHARED, fd, 0);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (p == MAP_FAILED) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer safe_close(fd);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer h = p;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (memcmp(h->signature, CATALOG_SIGNATURE, sizeof(h->signature)) != 0 ||
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer le64toh(h->header_size) < sizeof(CatalogHeader) ||
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer le64toh(h->catalog_item_size) < sizeof(CatalogItem) ||
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer h->incompatible_flags != 0 ||
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer le64toh(h->n_items) <= 0 ||
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer st.st_size < (off_t) (le64toh(h->header_size) + le64toh(h->catalog_item_size) * le64toh(h->n_items))) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer safe_close(fd);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer munmap(p, st.st_size);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -EBADMSG;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer *_fd = fd;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer *_st = st;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer *_p = p;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic const char *find_id(void *p, sd_id128_t id) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer CatalogItem key, *f = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const CatalogHeader *h = p;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const char *loc;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer zero(key);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer key.id = id;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer loc = setlocale(LC_MESSAGES, NULL);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (loc && loc[0] && !streq(loc, "C") && !streq(loc, "POSIX")) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer strncpy(key.language, loc, sizeof(key.language));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer key.language[strcspn(key.language, ".@")] = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), catalog_compare_func);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!f) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char *e;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer e = strchr(key.language, '_');
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (e) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer *e = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), catalog_compare_func);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!f) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer zero(key.language);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), catalog_compare_func);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!f)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return (const char*) p +
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer le64toh(h->header_size) +
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer le64toh(h->n_items) * le64toh(h->catalog_item_size) +
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer le64toh(f->offset);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint catalog_get(const char* database, sd_id128_t id, char **_text) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _cleanup_close_ int fd = -1;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer void *p = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer struct stat st = {};
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char *text = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const char *s;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(_text);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = open_mmap(database, &fd, &st, &p);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer s = find_id(p, id);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!s) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = -ENOENT;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto finish;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer text = strdup(s);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!text) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = -ENOMEM;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer goto finish;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer *_text = text;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerfinish:
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (p)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer munmap(p, st.st_size);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic char *find_header(const char *s, const char *header) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer for (;;) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const char *v, *e;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer v = startswith(s, header);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (v) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer v += strspn(v, WHITESPACE);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return strndup(v, strcspn(v, NEWLINE));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* End of text */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer e = strchr(s, '\n');
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!e)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* End of header */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (e == s)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer s = e + 1;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic void dump_catalog_entry(FILE *f, sd_id128_t id, const char *s, bool oneline) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (oneline) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _cleanup_free_ char *subject = NULL, *defined_by = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer subject = find_header(s, "Subject:");
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer defined_by = find_header(s, "Defined-By:");
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer fprintf(f, SD_ID128_FORMAT_STR " %s: %s\n",
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SD_ID128_FORMAT_VAL(id),
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer strna(defined_by), strna(subject));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer } else
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer fprintf(f, "-- " SD_ID128_FORMAT_STR "\n%s\n",
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer SD_ID128_FORMAT_VAL(id), s);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint catalog_list(FILE *f, const char *database, bool oneline) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _cleanup_close_ int fd = -1;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer void *p = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer struct stat st;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const CatalogHeader *h;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const CatalogItem *items;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unsigned n;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sd_id128_t last_id;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer bool last_id_set = false;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = open_mmap(database, &fd, &st, &p);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer h = p;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer items = (const CatalogItem*) ((const uint8_t*) p + le64toh(h->header_size));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer for (n = 0; n < le64toh(h->n_items); n++) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const char *s;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (last_id_set && sd_id128_equal(last_id, items[n].id))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer continue;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert_se(s = find_id(p, items[n].id));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer dump_catalog_entry(f, items[n].id, s, oneline);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer last_id_set = true;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer last_id = items[n].id;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer munmap(p, st.st_size);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint catalog_list_items(FILE *f, const char *database, bool oneline, char **items) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char **item;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int r = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer STRV_FOREACH(item, items) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sd_id128_t id;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int k;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _cleanup_free_ char *msg = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer k = sd_id128_from_string(*item, &id);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (k < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error_errno(k, "Failed to parse id128 '%s': %m", *item);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r == 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = k;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer continue;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer k = catalog_get(database, id, &msg);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (k < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_full_errno(k == -ENOENT ? LOG_NOTICE : LOG_ERR, k,
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer "Failed to retrieve catalog entry for '%s': %m", *item);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r == 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = k;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer continue;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer dump_catalog_entry(f, id, msg, oneline);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer