X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Fhwdb%2Fhwdb.c;h=4540260f9b869f4e195184810e0c50c75cb9e810;hb=53e1b683907c2f12330f00feb9630150196f064d;hp=6d4a03bedba7dbe172b03f3893f3435533d127fb;hpb=49141e0cd1a56e5f97e81e13a6d7be85138c134c;p=thirdparty%2Fsystemd.git diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c index 6d4a03bedba..4540260f9b8 100644 --- a/src/hwdb/hwdb.c +++ b/src/hwdb/hwdb.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -31,6 +32,7 @@ #include "hwdb-util.h" #include "label.h" #include "mkdir.h" +#include "path-util.h" #include "selinux-util.h" #include "strbuf.h" #include "string-util.h" @@ -390,7 +392,7 @@ static int trie_store(struct trie *trie, const char *filename) { int64_t size; struct trie_header_f h = { .signature = HWDB_SIG, - .tool_version = htole64(atoi(VERSION)), + .tool_version = htole64(atoi(PACKAGE_VERSION)), .header_size = htole64(sizeof(struct trie_header_f)), .node_size = htole64(sizeof(struct trie_node_f)), .child_entry_size = htole64(sizeof(struct trie_child_entry_f)), @@ -402,14 +404,14 @@ static int trie_store(struct trie *trie, const char *filename) { t.strings_off = sizeof(struct trie_header_f); trie_store_nodes_size(&t, trie->root); - r = fopen_temporary(filename , &t.f, &filename_tmp); + r = fopen_temporary(filename, &t.f, &filename_tmp); if (r < 0) return r; fchmod(fileno(t.f), 0444); /* write nodes */ if (fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET) < 0) - goto error; + goto error_fclose; root_off = trie_store_nodes(&t, trie->root); h.nodes_root_off = htole64(root_off); @@ -424,13 +426,20 @@ static int trie_store(struct trie *trie, const char *filename) { size = ftello(t.f); h.file_size = htole64(size); if (fseeko(t.f, 0, SEEK_SET) < 0) - goto error; - + goto error_fclose; fwrite(&h, sizeof(struct trie_header_f), 1, t.f); - if (fclose(t.f) < 0 || rename(filename_tmp, filename) < 0) { - unlink_noerrno(filename_tmp); - return -errno; - } + + if (ferror(t.f)) + goto error_fclose; + if (fflush(t.f) < 0) + goto error_fclose; + if (fsync(fileno(t.f)) < 0) + goto error_fclose; + if (rename(filename_tmp, filename) < 0) + goto error_fclose; + + /* write succeeded */ + fclose(t.f); log_debug("=== trie on-disk ==="); log_debug("size: %8"PRIi64" bytes", size); @@ -445,7 +454,7 @@ static int trie_store(struct trie *trie, const char *filename) { log_debug("strings start: %8"PRIu64, t.strings_off); return 0; - error: + error_fclose: r = -errno; fclose(t.f); unlink(filename_tmp); @@ -456,6 +465,8 @@ static int insert_data(struct trie *trie, char **match_list, char *line, const char *filename, uint16_t file_priority, uint32_t line_number) { char *value, **entry; + assert(line[0] == ' '); + value = strchr(line, '='); if (!value) return log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL, @@ -464,13 +475,15 @@ static int insert_data(struct trie *trie, char **match_list, char *line, value[0] = '\0'; value++; - /* libudev requires properties to start with a space */ + /* Replace multiple leading spaces by a single space */ while (isblank(line[0]) && isblank(line[1])) line++; - if (line[0] == '\0' || value[0] == '\0') + if (isempty(line + 1) || isempty(value)) return log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL, - "Empty %s in \"%s\", ignoring", line[0] == '\0' ? "key" : "value", line); + "Empty %s in \"%s=%s\", ignoring", + isempty(line + 1) ? "key" : "value", + line, value); STRV_FOREACH(entry, match_list) trie_insert(trie, trie->root, *entry, line, value, filename, file_priority, line_number); @@ -550,8 +563,8 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr break; } - /* another match */ if (line[0] != ' ') { + /* another match */ match = strdup(line); if (!match) return -ENOMEM; @@ -569,8 +582,8 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr break; case HW_DATA: - /* end of record */ if (len == 0) { + /* end of record */ state = HW_NONE; strv_clear(match_list); break; @@ -589,6 +602,10 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr }; } + if (state == HW_MATCH) + log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL, + "Property expected, ignoring record with no properties"); + return 0; } @@ -637,7 +654,7 @@ static int hwdb_update(int argc, char *argv[], void *userdata) { trie->nodes_count++; - r = conf_files_list_strv(&files, ".hwdb", arg_root, conf_file_dirs); + r = conf_files_list_strv(&files, ".hwdb", arg_root, 0, conf_file_dirs); if (r < 0) return log_error_errno(r, "Failed to enumerate hwdb files: %m"); @@ -662,7 +679,7 @@ static int hwdb_update(int argc, char *argv[], void *userdata) { log_debug("strings dedup'ed: %8zu bytes (%8zu)", trie->strings->dedup_len, trie->strings->dedup_count); - hwdb_bin = strjoin(arg_root, "/", arg_hwdb_bin_dir, "/hwdb.bin"); + hwdb_bin = path_join(arg_root, arg_hwdb_bin_dir, "hwdb.bin"); if (!hwdb_bin) return -ENOMEM;