catalog.c revision 54b7254c1fa629937f92fd6fa34bdf127b696a00
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/***
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering This file is part of systemd.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Copyright 2012 Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (at your option) any later version.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is distributed in the hope that it will be useful, but
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Lesser General Public License for more details.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering***/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <fcntl.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <stdio.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <unistd.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <errno.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <string.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <sys/mman.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <locale.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "util.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "log.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "sparse-endian.h"
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack#include "sd-id128.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "hashmap.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "strv.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "strbuf.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "conf-files.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "mkdir.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "catalog.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic const char * const conf_file_dirs[] = {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering "/usr/local/lib/systemd/catalog/",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "/usr/lib/systemd/catalog/",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering NULL
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering};
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#define CATALOG_SIGNATURE (uint8_t[]) { 'R', 'H', 'H', 'H', 'K', 'S', 'L', 'P' }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringtypedef struct CatalogHeader {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uint8_t signature[8]; /* "RHHHKSLP" */
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering le32_t compatible_flags;
4f10118016f9b2fd7e1d26c9ef7d91eb33fba694Lennart Poettering le32_t incompatible_flags;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering le64_t header_size;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering le64_t n_items;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering le64_t catalog_item_size;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering} CatalogHeader;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringtypedef struct CatalogItem {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_id128_t id;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering char language[32];
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering le64_t offset;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering} CatalogItem;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic unsigned catalog_hash_func(const void *p) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering const CatalogItem *i = p;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert_cc(sizeof(unsigned) == sizeof(uint8_t)*4);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return (((unsigned) i->id.bytes[0] << 24) |
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((unsigned) i->id.bytes[1] << 16) |
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((unsigned) i->id.bytes[2] << 8) |
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((unsigned) i->id.bytes[3])) ^
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering (((unsigned) i->id.bytes[4] << 24) |
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((unsigned) i->id.bytes[5] << 16) |
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((unsigned) i->id.bytes[6] << 8) |
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((unsigned) i->id.bytes[7])) ^
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering (((unsigned) i->id.bytes[8] << 24) |
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((unsigned) i->id.bytes[9] << 16) |
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((unsigned) i->id.bytes[10] << 8) |
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((unsigned) i->id.bytes[11])) ^
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering (((unsigned) i->id.bytes[12] << 24) |
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((unsigned) i->id.bytes[13] << 16) |
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((unsigned) i->id.bytes[14] << 8) |
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ((unsigned) i->id.bytes[15])) ^
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering string_hash_func(i->language);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int catalog_compare_func(const void *a, const void *b) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering const CatalogItem *i = a, *j = b;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unsigned k;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering for (k = 0; k < ELEMENTSOF(j->id.bytes); k++) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (i->id.bytes[k] < j->id.bytes[k])
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -1;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (i->id.bytes[k] > j->id.bytes[k])
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 1;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return strncmp(i->language, j->language, sizeof(i->language));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int finish_item(
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Hashmap *h,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering struct strbuf *sb,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_id128_t id,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering const char *language,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering const char *payload) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ssize_t offset;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering CatalogItem *i;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(h);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(sb);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(payload);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering offset = strbuf_add_string(sb, payload, strlen(payload));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (offset < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return log_oom();
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering i = new0(CatalogItem, 1);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!i)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return log_oom();
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering i->id = id;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering strncpy(i->language, language, sizeof(i->language));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering i->offset = htole64((uint64_t) offset);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = hashmap_put(h, i, i);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r == EEXIST) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_warning("Duplicate entry for " SD_ID128_FORMAT_STR ".%s, ignoring.", SD_ID128_FORMAT_VAL(id), language ? language : "C");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(i);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int import_file(Hashmap *h, struct strbuf *sb, const char *path) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_free_ char *payload = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unsigned n = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_id128_t id;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char language[32];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bool got_id = false, empty_line = true;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(h);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(sb);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(path);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering f = fopen(path, "re");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!f) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Failed to open file %s: %m", path);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -errno;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering for (;;) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char line[LINE_MAX];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering size_t a, b, c;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char *t;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!fgets(line, sizeof(line), f)) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (feof(f))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack log_error("Failed to read file %s: %m", path);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return -errno;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack n++;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack truncate_nl(line);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (line[0] == 0) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack empty_line = true;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack continue;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (strchr(COMMENTS, line[0]))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering continue;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (empty_line &&
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering strlen(line) >= 2+1+32 &&
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering line[0] == '-' &&
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering line[1] == '-' &&
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering line[2] == ' ' &&
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (line[2+1+32] == ' ' || line[2+1+32] == 0)) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bool with_language;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_id128_t jd;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* New entry */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering with_language = line[2+1+32] != 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering line[2+1+32] = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (got_id) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = finish_item(h, sb, id, language, payload);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (with_language) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering t = strstrip(line + 2 + 1 + 32 + 1);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering c = strlen(t);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (c <= 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("[%s:%u] Language too short.", path, n);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (c > sizeof(language)) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("[%s:%u] language too long.", path, n);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering strncpy(language, t, sizeof(language));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering zero(language);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering got_id = true;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering empty_line = false;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering id = jd;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (payload)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering payload[0] = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering continue;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Payload */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!got_id) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("[%s:%u] Got payload before ID.", path, n);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering a = payload ? strlen(payload) : 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering b = strlen(line);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering c = a + (empty_line ? 1 : 0) + b + 1 + 1;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack t = realloc(payload, c);
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering if (!t)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return log_oom();
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering if (empty_line) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack t[a] = '\n';
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering memcpy(t + a + 1, line, b);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering t[a+b+1] = '\n';
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering t[a+b+2] = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering } else {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering memcpy(t + a, line, b);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering t[a+b] = '\n';
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering t[a+b+1] = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering payload = t;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering empty_line = false;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (got_id) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = finish_item(h, sb, id, language, payload);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#define CATALOG_DATABASE CATALOG_PATH "/database"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint catalog_update(void) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_strv_free_ char **files = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_fclose_ FILE *w = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_free_ char *p = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char **f;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Hashmap *h;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering struct strbuf *sb = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_free_ CatalogItem *items = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering CatalogItem *i;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering CatalogHeader header;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering size_t k;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Iterator j;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unsigned n;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering h = hashmap_new(catalog_hash_func, catalog_compare_func);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!h)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -ENOMEM;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek sb = strbuf_new();
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek if (!sb) {
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek r = log_oom();
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto finish;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = conf_files_list_strv(&files, ".catalog", NULL, (const char **) conf_file_dirs);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0) {
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek log_error("Failed to get catalog files: %s", strerror(-r));
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek goto finish;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek STRV_FOREACH(f, files) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("reading file '%s'", *f);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering import_file(h, sb, *f);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (hashmap_size(h) <= 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_info("No items in catalog.");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto finish;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("Found %u items in catalog.", hashmap_size(h));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering strbuf_complete(sb);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering items = new(CatalogItem, hashmap_size(h));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!items) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = log_oom();
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto finish;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering n = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering HASHMAP_FOREACH(i, h, j) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_debug("Found " SD_ID128_FORMAT_STR ", language %s", SD_ID128_FORMAT_VAL(i->id), isempty(i->language) ? "C" : i->language);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering items[n++] = *i;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(n == hashmap_size(h));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering qsort(items, n, sizeof(CatalogItem), catalog_compare_func);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = mkdir_p(CATALOG_PATH, 0775);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Recursive mkdir %s: %s", CATALOG_PATH, strerror(-r));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto finish;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = fopen_temporary(CATALOG_DATABASE, &w, &p);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Failed to open database for writing: %s: %s",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering CATALOG_DATABASE, strerror(-r));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto finish;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering zero(header);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering memcpy(header.signature, CATALOG_SIGNATURE, sizeof(header.signature));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering header.header_size = htole64(ALIGN_TO(sizeof(CatalogHeader), 8));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering header.catalog_item_size = htole64(sizeof(CatalogItem));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering header.n_items = htole64(hashmap_size(h));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering k = fwrite(&header, 1, sizeof(header), w);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (k != sizeof(header)) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_error("%s: failed to write header.", p);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto finish;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering k = fwrite(items, 1, n * sizeof(CatalogItem), w);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (k != n * sizeof(CatalogItem)) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_error("%s: failed to write database.", p);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto finish;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering k = fwrite(sb->buf, 1, sb->len, w);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (k != sb->len) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("%s: failed to write strings.", p);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto finish;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fflush(w);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (ferror(w)) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("%s: failed to write database.", p);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto finish;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering fchmod(fileno(w), 0644);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (rename(p, CATALOG_DATABASE) < 0) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_error("rename (%s -> %s) failed: %m", p, CATALOG_DATABASE);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = -errno;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto finish;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_debug("%s: wrote %u items, with %zu bytes of strings, %ld total size.",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering CATALOG_DATABASE, n, sb->len, ftell(w));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering free(p);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering p = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringfinish:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering hashmap_free_free(h);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (sb)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering strbuf_cleanup(sb);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (p)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unlink(p);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int open_mmap(int *_fd, struct stat *_st, void **_p) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering const CatalogHeader *h;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int fd;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering void *p;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering struct stat st;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(_fd);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(_st);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(_p);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering fd = open(CATALOG_DATABASE, O_RDONLY|O_CLOEXEC);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (fd < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -errno;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (fstat(fd, &st) < 0) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering close_nointr_nofail(fd);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -errno;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (st.st_size < (off_t) sizeof(CatalogHeader)) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering close_nointr_nofail(fd);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering p = mmap(NULL, PAGE_ALIGN(st.st_size), PROT_READ, MAP_SHARED, fd, 0);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (p == MAP_FAILED) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering close_nointr_nofail(fd);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -errno;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering h = p;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (memcmp(h->signature, CATALOG_SIGNATURE, sizeof(h->signature)) != 0 ||
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering le64toh(h->header_size) < sizeof(CatalogHeader) ||
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering le64toh(h->catalog_item_size) < sizeof(CatalogItem) ||
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering h->incompatible_flags != 0 ||
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering le64toh(h->n_items) <= 0 ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering st.st_size < (off_t) (le64toh(h->header_size) + le64toh(h->catalog_item_size) * le64toh(h->n_items))) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering close_nointr_nofail(fd);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering munmap(p, st.st_size);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -EBADMSG;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *_fd = fd;
db2cb23b5b179707000d28a11efb3d888d06ee80Umut Tezduyar Lindskog *_st = st;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *_p = p;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
2ba5d84c491d6a593f2c077c63dffb6319b9590dColin Ian King
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic const char *find_id(void *p, sd_id128_t id) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering CatalogItem key, *f = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering const CatalogHeader *h = p;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering const char *loc;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering zero(key);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering key.id = id;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering loc = setlocale(LC_MESSAGES, NULL);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (loc && loc[0] && !streq(loc, "C") && !streq(loc, "POSIX")) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering strncpy(key.language, loc, sizeof(key.language));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering key.language[strcspn(key.language, ".@")] = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), catalog_compare_func);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!f) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering char *e;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering e = strchr(key.language, '_');
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (e) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *e = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), catalog_compare_func);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!f) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering zero(key.language);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), catalog_compare_func);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack }
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (!f)
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return NULL;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return (const char*) p +
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack le64toh(h->header_size) +
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack le64toh(h->n_items) * le64toh(h->catalog_item_size) +
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack le64toh(f->offset);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint catalog_get(sd_id128_t id, char **_text) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering _cleanup_close_ int fd = -1;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering void *p = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering struct stat st;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering char *text = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering const char *s;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(_text);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = open_mmap(&fd, &st, &p);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering s = find_id(p, id);
8d0e0ddda6501479eb69164687c83c1a7667b33aJan Engelhardt if (!s) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = -ENOENT;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto finish;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering text = strdup(s);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!text) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = -ENOMEM;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto finish;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *_text = text;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = 0;
8d0e0ddda6501479eb69164687c83c1a7667b33aJan Engelhardt
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringfinish:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (p)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering munmap(p, st.st_size);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic char *find_header(const char *s, const char *header) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering for (;;) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering const char *v, *e;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering v = startswith(s, header);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (v) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering v += strspn(v, WHITESPACE);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return strndup(v, strcspn(v, NEWLINE));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* End of text */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering e = strchr(s, '\n');
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!e)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* End of header */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (e == s)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return NULL;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack s = e + 1;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void dump_catalog_entry(FILE *f, sd_id128_t id, const char *s, bool oneline) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (oneline) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_free_ char *subject = NULL, *defined_by = NULL;
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering subject = find_header(s, "Subject:");
ff975efb2e88dcd5221a2f0d76c4c87e85b821a8Lennart Poettering defined_by = find_header(s, "Defined-By:");
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering fprintf(f, SD_ID128_FORMAT_STR " %s: %s\n",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SD_ID128_FORMAT_VAL(id),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering strna(defined_by), strna(subject));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "-- " SD_ID128_FORMAT_STR "\n%s\n",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SD_ID128_FORMAT_VAL(id), s);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint catalog_list(FILE *f, bool oneline) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_close_ int fd = -1;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering void *p = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct stat st;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering const CatalogHeader *h;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering const CatalogItem *items;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unsigned n;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_id128_t last_id;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bool last_id_set = false;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = open_mmap(&fd, &st, &p);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering h = p;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering items = (const CatalogItem*) ((const uint8_t*) p + le64toh(h->header_size));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering for (n = 0; n < le64toh(h->n_items); n++) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering const char *s;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (last_id_set && sd_id128_equal(last_id, items[n].id))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering continue;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert_se(s = find_id(p, items[n].id));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering dump_catalog_entry(f, items[n].id, s, oneline);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering last_id_set = true;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering last_id = items[n].id;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering munmap(p, st.st_size);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint catalog_list_items(FILE *f, bool oneline, char **items) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char **item;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering STRV_FOREACH(item, items) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_id128_t id;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int k;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char _cleanup_free_ *msg = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering k = sd_id128_from_string(*item, &id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (k < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_error("Failed to parse id128 '%s': %s",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *item, strerror(-r));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = k;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering continue;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering k = catalog_get(id, &msg);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (k < 0) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_full(k == -ENOENT ? LOG_NOTICE : LOG_ERR,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering "Failed to retrieve catalog entry for '%s': %s",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *item, strerror(-r));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = k;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering continue;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering dump_catalog_entry(f, id, msg, oneline);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering