int write_env_file(const char *fname, char **l) { char **i; _cleanup_free_ char *p = NULL; _cleanup_fclose_ FILE *f = NULL; int r; r = fopen_temporary(fname, &f, &p); if (r < 0) return r; fchmod_umask(fileno(f), 0644); errno = 0; STRV_FOREACH(i, l) write_env_var(f, *i); fflush(f); if (ferror(f)) r = errno ? -errno : -EIO; else { if (rename(p, fname) < 0) r = -errno; else r = 0; } if (r < 0) unlink(p); return r; }
int write_env_file(const char *fname, char **l) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; char **i; int r; assert(fname); r = fopen_temporary(fname, &f, &p); if (r < 0) return r; fchmod_umask(fileno(f), 0644); STRV_FOREACH(i, l) write_env_var(f, *i); r = fflush_and_check(f); if (r >= 0) { if (rename(p, fname) >= 0) return 0; r = -errno; } unlink(p); return r; }
int write_string_file_atomic(const char *fn, const char *line) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; int r; assert(fn); assert(line); r = fopen_temporary(fn, &f, &p); if (r < 0) return r; fchmod_umask(fileno(f), 0644); errno = 0; fputs(line, f); if (!endswith(line, "\n")) fputc('\n', f); fflush(f); if (ferror(f)) r = errno ? -errno : -EIO; else { if (rename(p, fn) < 0) r = -errno; else r = 0; } if (r < 0) unlink(p); return r; }
static int write_string_file_atomic( const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; int r; assert(fn); assert(line); r = fopen_temporary(fn, &f, &p); if (r < 0) return r; (void) __fsetlocking(f, FSETLOCKING_BYCALLER); (void) fchmod_umask(fileno(f), 0644); r = write_string_stream_ts(f, line, flags, ts); if (r < 0) goto fail; if (rename(p, fn) < 0) { r = -errno; goto fail; } return 0; fail: (void) unlink(p); return r; }
static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; int r; assert(fn); assert(line); r = fopen_temporary(fn, &f, &p); if (r < 0) return r; (void) fchmod_umask(fileno(f), 0644); r = write_string_stream(f, line, enforce_newline); if (r >= 0) { if (rename(p, fn) < 0) r = -errno; } if (r < 0) (void) unlink(p); return r; }
static int write_data_x11(void) { FILE *f; char *temp_path; int r; if (isempty(state.x11_layout) && isempty(state.x11_model) && isempty(state.x11_variant) && isempty(state.x11_options)) { if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) return errno == ENOENT ? 0 : -errno; return 0; } mkdir_p_label("/etc/X11/xorg.conf.d", 0755); r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path); if (r < 0) return r; fchmod(fileno(f), 0644); fputs("# Read and parsed by systemd-localed. It's probably wise not to edit this file\n" "# manually too freely.\n" "Section \"InputClass\"\n" " Identifier \"system-keyboard\"\n" " MatchIsKeyboard \"on\"\n", f); if (!isempty(state.x11_layout)) fprintf(f, " Option \"XkbLayout\" \"%s\"\n", state.x11_layout); if (!isempty(state.x11_model)) fprintf(f, " Option \"XkbModel\" \"%s\"\n", state.x11_model); if (!isempty(state.x11_variant)) fprintf(f, " Option \"XkbVariant\" \"%s\"\n", state.x11_variant); if (!isempty(state.x11_options)) fprintf(f, " Option \"XkbOptions\" \"%s\"\n", state.x11_options); fputs("EndSection\n", f); fflush(f); if (ferror(f) || rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) { r = -errno; unlink("/etc/X11/xorg.conf.d/00-keyboard.conf"); unlink(temp_path); } else r = 0; fclose(f); free(temp_path); return r; }
int fopen_temporary_label(const char *target, const char *path, FILE **f, char **temp_path) { int r; r = mac_selinux_create_file_prepare(target, S_IFREG); if (r < 0) return r; r = fopen_temporary(path, f, temp_path); mac_selinux_create_file_clear(); return r; }
int write_env_file(const char *fname, char **l) { char **i, *p; FILE *f; int r; r = fopen_temporary(fname, &f, &p); if (r < 0) return r; fchmod_umask(fileno(f), 0644); errno = 0; STRV_FOREACH(i, l) { fputs(*i, f); fputc('\n', f); }
int write_env_file(const char *fname, char **l) { char **i; char _cleanup_free_ *p = NULL; FILE _cleanup_fclose_ *f = NULL; int r; r = fopen_temporary(fname, &f, &p); if (r < 0) return r; fchmod_umask(fileno(f), 0644); errno = 0; STRV_FOREACH(i, l) { fputs(*i, f); fputc('\n', f); }
static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node) { uint64_t i; struct trie_node_f n = { .prefix_off = htole64(trie->strings_off + node->prefix_off), .children_count = node->children_count, .values_count = htole64(node->values_count), }; struct trie_child_entry_f *children = NULL; int64_t node_off; if (node->children_count) { children = new0(struct trie_child_entry_f, node->children_count); if (!children) return -ENOMEM; } /* post-order recursion */ for (i = 0; i < node->children_count; i++) { int64_t child_off; child_off = trie_store_nodes(trie, node->children[i].child); if (child_off < 0) { free(children); return child_off; } children[i].c = node->children[i].c; children[i].child_off = htole64(child_off); } /* write node */ node_off = ftello(trie->f); if (fwrite(&n, sizeof(struct trie_node_f), 1, trie->f) != 1) log_error("Failed to write sizeof struct trie_node_f to n in %s\n", "[udevadm-hwdb.c:trie_store_nodes]"); trie->nodes_count++; /* append children array */ if (node->children_count) { if (fwrite(children, sizeof(struct trie_child_entry_f), node->children_count, trie->f) != node->children_count) log_error("Failed to write children_count in %s\n", "[udevadm-hwdb.c:trie_store_nodes]"); trie->children_count += node->children_count; free(children); } /* append values array */ for (i = 0; i < node->values_count; i++) { struct trie_value_entry_f v = { .key_off = htole64(trie->strings_off + node->values[i].key_off), .value_off = htole64(trie->strings_off + node->values[i].value_off), }; if (fwrite(&v, sizeof(struct trie_value_entry_f), 1, trie->f) != 1) log_error("Failed to write sizeof trie_value_entry_f to v in %s\n", "[udevadm-hwdb.c:trie_store_nodes]"); trie->values_count++; } return node_off; } static int trie_store(struct trie *trie, const char *filename) { struct trie_f t = { .trie = trie, }; char *filename_tmp; int64_t pos; int64_t root_off; int64_t size; struct trie_header_f h = { .signature = HWDB_SIG, .tool_version = htole64(atoi(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)), .value_entry_size = htole64(sizeof(struct trie_value_entry_f)), }; int err; /* calculate size of header, nodes, children entries, value entries */ t.strings_off = sizeof(struct trie_header_f); trie_store_nodes_size(&t, trie->root); err = fopen_temporary(filename , &t.f, &filename_tmp); if (err < 0) return err; fchmod(fileno(t.f), 0444); /* write nodes */ fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET); root_off = trie_store_nodes(&t, trie->root); h.nodes_root_off = htole64(root_off); pos = ftello(t.f); h.nodes_len = htole64(pos - sizeof(struct trie_header_f)); /* write string buffer */ if (fwrite(trie->strings->buf, trie->strings->len, 1, t.f) != 1) log_error("Failed to write into trie->strings->buf in %s\n", "[udevadm-hwdb.c:trie_store]"); h.strings_len = htole64(trie->strings->len); /* write header */ size = ftello(t.f); h.file_size = htole64(size); fseeko(t.f, 0, SEEK_SET); if (fwrite(&h, sizeof(struct trie_header_f), 1, t.f) != 1) log_error("Failed to write into h in %s\n", "[udevadm-hwdb.c:trie_store]"); err = ferror(t.f); if (err) err = -errno; fclose(t.f); if (err < 0 || rename(filename_tmp, filename) < 0) { unlink(filename_tmp); goto out; } log_debug("=== trie on-disk ===\n"); log_debug("size: %8llu bytes\n", (unsigned long long)size); log_debug("header: %8zu bytes\n", sizeof(struct trie_header_f)); log_debug("nodes: %8llu bytes (%8llu)\n", (unsigned long long)t.nodes_count * sizeof(struct trie_node_f), (unsigned long long)t.nodes_count); log_debug("child pointers: %8llu bytes (%8llu)\n", (unsigned long long)t.children_count * sizeof(struct trie_child_entry_f), (unsigned long long)t.children_count); log_debug("value pointers: %8llu bytes (%8llu)\n", (unsigned long long)t.values_count * sizeof(struct trie_value_entry_f), (unsigned long long)t.values_count); log_debug("string store: %8llu bytes\n", (unsigned long long)trie->strings->len); log_debug("strings start: %8llu\n", (unsigned long long) t.strings_off); out: free(filename_tmp); return err; } static int insert_data(struct trie *trie, struct udev_list *match_list, char *line, const char *filename) { char *value; struct udev_list_entry *entry; value = strchr(line, '='); if (!value) { log_error("Error, key/value pair expected but got '%s' in '%s':\n", line, filename); return -EINVAL; } value[0] = '\0'; value++; if (line[0] == '\0' || value[0] == '\0') { log_error("Error, empty key or value '%s' in '%s':\n", line, filename); return -EINVAL; } udev_list_entry_foreach(entry, udev_list_get_entry(match_list)) trie_insert(trie, trie->root, udev_list_entry_get_name(entry), line, value); return 0; } static int import_file(struct udev *udev, struct trie *trie, const char *filename) { enum { HW_MATCH, HW_DATA, HW_NONE, } state = HW_NONE; FILE *f; char line[LINE_MAX]; struct udev_list match_list; udev_list_init(udev, &match_list, false); f = fopen(filename, "re"); if (f == NULL) return -errno; while (fgets(line, sizeof(line), f)) { size_t len; char *pos; /* comment line */ if (line[0] == '#') continue; /* strip trailing comment */ pos = strchr(line, '#'); if (pos) pos[0] = '\0'; /* strip trailing whitespace */ len = strlen(line); while (len > 0 && isspace(line[len-1])) len--; line[len] = '\0'; switch (state) { case HW_NONE: if (len == 0) break; if (line[0] == ' ') { log_error("Error, MATCH expected but got '%s' in '%s':\n", line, filename); break; } /* start of record, first match */ state = HW_MATCH; udev_list_entry_add(&match_list, line, NULL); break; case HW_MATCH: if (len == 0) { log_error("Error, DATA expected but got empty line in '%s':\n", filename); state = HW_NONE; udev_list_cleanup(&match_list); break; } /* another match */ if (line[0] != ' ') { udev_list_entry_add(&match_list, line, NULL); break; } /* first data */ state = HW_DATA; insert_data(trie, &match_list, line, filename); break; case HW_DATA: /* end of record */ if (len == 0) { state = HW_NONE; udev_list_cleanup(&match_list); break; } if (line[0] != ' ') { log_error("Error, DATA expected but got '%s' in '%s':\n", line, filename); state = HW_NONE; udev_list_cleanup(&match_list); break; } insert_data(trie, &match_list, line, filename); break; }; } fclose(f); udev_list_cleanup(&match_list); return 0; } static void help(void) { printf("Usage: udevadm hwdb OPTIONS\n" " --update update the hardware database\n" " --test=<modalias> query database and print result\n" " --root=<path> alternative root path in the filesystem\n" " --help\n\n"); }
int x11_write_data(Context *c) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *temp_path = NULL; struct stat st; int r; if (isempty(c->x11_layout) && isempty(c->x11_model) && isempty(c->x11_variant) && isempty(c->x11_options)) { if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) return errno == ENOENT ? 0 : -errno; c->vc_mtime = USEC_INFINITY; return 0; } mkdir_p_label("/etc/X11/xorg.conf.d", 0755); r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path); if (r < 0) return r; (void) __fsetlocking(f, FSETLOCKING_BYCALLER); (void) fchmod(fileno(f), 0644); fputs("# Written by systemd-localed(8), read by systemd-localed and Xorg. It's\n" "# probably wise not to edit this file manually. Use localectl(1) to\n" "# instruct systemd-localed to update it.\n" "Section \"InputClass\"\n" " Identifier \"system-keyboard\"\n" " MatchIsKeyboard \"on\"\n", f); if (!isempty(c->x11_layout)) fprintf(f, " Option \"XkbLayout\" \"%s\"\n", c->x11_layout); if (!isempty(c->x11_model)) fprintf(f, " Option \"XkbModel\" \"%s\"\n", c->x11_model); if (!isempty(c->x11_variant)) fprintf(f, " Option \"XkbVariant\" \"%s\"\n", c->x11_variant); if (!isempty(c->x11_options)) fprintf(f, " Option \"XkbOptions\" \"%s\"\n", c->x11_options); fputs("EndSection\n", f); r = fflush_sync_and_check(f); if (r < 0) goto fail; if (rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) { r = -errno; goto fail; } if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) >= 0) c->x11_mtime = timespec_load(&st.st_mtim); return 0; fail: if (temp_path) (void) unlink(temp_path); return r; }
static int write_data_x11(void) { FILE *f; char *temp_path; int r; if (isempty(state.x11_layout) && isempty(state.x11_model) && isempty(state.x11_variant) && isempty(state.x11_options)) { #ifdef TARGET_FEDORA unlink("/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf"); /* Symlink this to /dev/null, so that s-s-k (if it is * still running) doesn't recreate this. */ symlink("/dev/null", "/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf"); #endif if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) return errno == ENOENT ? 0 : -errno; return 0; } mkdir_parents_label("/etc/X11/xorg.conf.d", 0755); r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path); if (r < 0) return r; fchmod(fileno(f), 0644); fputs("# Read and parsed by systemd-localed. It's probably wise not to edit this file\n" "# manually too freely.\n" "Section \"InputClass\"\n" " Identifier \"system-keyboard\"\n" " MatchIsKeyboard \"on\"\n", f); if (!isempty(state.x11_layout)) fprintf(f, " Option \"XkbLayout\" \"%s\"\n", state.x11_layout); if (!isempty(state.x11_model)) fprintf(f, " Option \"XkbModel\" \"%s\"\n", state.x11_model); if (!isempty(state.x11_variant)) fprintf(f, " Option \"XkbVariant\" \"%s\"\n", state.x11_variant); if (!isempty(state.x11_options)) fprintf(f, " Option \"XkbOptions\" \"%s\"\n", state.x11_options); fputs("EndSection\n", f); fflush(f); if (ferror(f) || rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) { r = -errno; unlink("/etc/X11/xorg.conf.d/00-keyboard.conf"); unlink(temp_path); } else { #ifdef TARGET_FEDORA unlink("/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf"); /* Symlink this to /dev/null, so that s-s-k (if it is * still running) doesn't recreate this. */ symlink("/dev/null", "/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf"); #endif r = 0; } fclose(f); free(temp_path); return r; }
static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node) { uint64_t i; struct trie_node_f n = { .prefix_off = htole64(trie->strings_off + node->prefix_off), .children_count = node->children_count, .values_count = htole64(node->values_count), }; struct trie_child_entry_f *children = NULL; int64_t node_off; if (node->children_count) { children = new0(struct trie_child_entry_f, node->children_count); if (!children) return -ENOMEM; } /* post-order recursion */ for (i = 0; i < node->children_count; i++) { int64_t child_off; child_off = trie_store_nodes(trie, node->children[i].child); if (child_off < 0) return child_off; children[i].c = node->children[i].c; children[i].child_off = htole64(child_off); } /* write node */ node_off = ftello(trie->f); fwrite(&n, sizeof(struct trie_node_f), 1, trie->f); trie->nodes_count++; /* append children array */ if (node->children_count) { fwrite(children, sizeof(struct trie_child_entry_f), node->children_count, trie->f); trie->children_count += node->children_count; free(children); } /* append values array */ for (i = 0; i < node->values_count; i++) { struct trie_value_entry_f v = { .key_off = htole64(trie->strings_off + node->values[i].key_off), .value_off = htole64(trie->strings_off + node->values[i].value_off), }; fwrite(&v, sizeof(struct trie_value_entry_f), 1, trie->f); trie->values_count++; } return node_off; } static int trie_store(struct trie *trie, const char *filename) { struct trie_f t = { .trie = trie, }; char *filename_tmp; int64_t pos; int64_t root_off; int64_t size; struct trie_header_f h = { .signature = HWDB_SIG, .tool_version = htole64(atoi(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)), .value_entry_size = htole64(sizeof(struct trie_value_entry_f)), }; int err; /* calculate size of header, nodes, children entries, value entries */ t.strings_off = sizeof(struct trie_header_f); trie_store_nodes_size(&t, trie->root); err = fopen_temporary(filename , &t.f, &filename_tmp); if (err < 0) return err; fchmod(fileno(t.f), 0444); /* write nodes */ fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET); root_off = trie_store_nodes(&t, trie->root); h.nodes_root_off = htole64(root_off); pos = ftello(t.f); h.nodes_len = htole64(pos - sizeof(struct trie_header_f)); /* write string buffer */ fwrite(trie->strings->buf, trie->strings->len, 1, t.f); h.strings_len = htole64(trie->strings->len); /* write header */ size = ftello(t.f); h.file_size = htole64(size); fseeko(t.f, 0, SEEK_SET); fwrite(&h, sizeof(struct trie_header_f), 1, t.f); err = ferror(t.f); if (err) err = -errno; fclose(t.f); if (err < 0 || rename(filename_tmp, filename) < 0) { unlink(filename_tmp); goto out; } log_debug("=== trie on-disk ===\n"); log_debug("size: %8llu bytes\n", (unsigned long long)size); log_debug("header: %8zu bytes\n", sizeof(struct trie_header_f)); log_debug("nodes: %8llu bytes (%8llu)\n", (unsigned long long)t.nodes_count * sizeof(struct trie_node_f), (unsigned long long)t.nodes_count); log_debug("child pointers: %8llu bytes (%8llu)\n", (unsigned long long)t.children_count * sizeof(struct trie_child_entry_f), (unsigned long long)t.children_count); log_debug("value pointers: %8llu bytes (%8llu)\n", (unsigned long long)t.values_count * sizeof(struct trie_value_entry_f), (unsigned long long)t.values_count); log_debug("string store: %8llu bytes\n", (unsigned long long)trie->strings->len); log_debug("strings start: %8llu\n", (unsigned long long) t.strings_off); out: free(filename_tmp); return err; } static int import_file(struct trie *trie, const char *filename) { FILE *f; char line[LINE_MAX]; char match[LINE_MAX]; char cond[LINE_MAX]; f = fopen(filename, "re"); if (f == NULL) return -errno; match[0] = '\0'; cond[0] = '\0'; while (fgets(line, sizeof(line), f)) { size_t len; if (line[0] == '#') continue; /* new line, new record */ if (line[0] == '\n') { match[0] = '\0'; cond[0] = '\0'; continue; } /* remove newline */ len = strlen(line); if (len < 2) continue; line[len-1] = '\0'; /* start of new record */ if (match[0] == '\0') { strcpy(match, line); cond[0] = '\0'; continue; } if (line[0] == '+') { strcpy(cond, line); continue; } /* TODO: support +; skip the entire record until we support it */ if (cond[0] != '\0') continue; /* value lines */ if (line[0] == ' ') { char *value; value = strchr(line, '='); if (!value) continue; value[0] = '\0'; value++; trie_insert(trie, trie->root, match, line, value); } } fclose(f); return 0; } static void help(void) { printf("Usage: udevadm hwdb OPTIONS\n" " --update update the hardware database\n" " --test=<modalias> query database and print result\n" " --root=<path> alternative root path in the filesystem\n" " --help\n\n"); }
static long write_catalog(const char *database, Hashmap *h, struct strbuf *sb, CatalogItem *items, size_t n) { CatalogHeader header; _cleanup_fclose_ FILE *w = NULL; int r; _cleanup_free_ char *d, *p = NULL; size_t k; d = dirname_malloc(database); if (!d) return log_oom(); r = mkdir_p(d, 0775); if (r < 0) { log_error("Recursive mkdir %s: %s", d, strerror(-r)); return r; } r = fopen_temporary(database, &w, &p); if (r < 0) { log_error("Failed to open database for writing: %s: %s", database, strerror(-r)); return r; } zero(header); memcpy(header.signature, CATALOG_SIGNATURE, sizeof(header.signature)); header.header_size = htole64(ALIGN_TO(sizeof(CatalogHeader), 8)); header.catalog_item_size = htole64(sizeof(CatalogItem)); header.n_items = htole64(hashmap_size(h)); r = -EIO; k = fwrite(&header, 1, sizeof(header), w); if (k != sizeof(header)) { log_error("%s: failed to write header.", p); goto error; } k = fwrite(items, 1, n * sizeof(CatalogItem), w); if (k != n * sizeof(CatalogItem)) { log_error("%s: failed to write database.", p); goto error; } k = fwrite(sb->buf, 1, sb->len, w); if (k != sb->len) { log_error("%s: failed to write strings.", p); goto error; } fflush(w); if (ferror(w)) { log_error("%s: failed to write database.", p); goto error; } fchmod(fileno(w), 0644); if (rename(p, database) < 0) { log_error("rename (%s -> %s) failed: %m", p, database); r = -errno; goto error; } return ftell(w); error: unlink(p); return r; }
static int x11_write_data(Context *c) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *temp_path = NULL; int r; if (isempty(c->x11_layout) && isempty(c->x11_model) && isempty(c->x11_variant) && isempty(c->x11_options)) { if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) return errno == ENOENT ? 0 : -errno; return 0; } mkdir_p_label("/etc/X11/xorg.conf.d", 0755); r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path); if (r < 0) return r; fchmod(fileno(f), 0644); fputs("# Read and parsed by systemd-localed. It's probably wise not to edit this file\n" "# manually too freely.\n" "Section \"InputClass\"\n" " Identifier \"system-keyboard\"\n" " MatchIsKeyboard \"on\"\n", f); if (!isempty(c->x11_layout)) fprintf(f, " Option \"XkbLayout\" \"%s\"\n", c->x11_layout); if (!isempty(c->x11_model)) fprintf(f, " Option \"XkbModel\" \"%s\"\n", c->x11_model); if (!isempty(c->x11_variant)) fprintf(f, " Option \"XkbVariant\" \"%s\"\n", c->x11_variant); if (!isempty(c->x11_options)) fprintf(f, " Option \"XkbOptions\" \"%s\"\n", c->x11_options); fputs("EndSection\n", f); r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) { r = -errno; goto fail; } return 0; fail: (void) unlink("/etc/X11/xorg.conf.d/00-keyboard.conf"); if (temp_path) (void) unlink(temp_path); return r; }
static int stdout_stream_save(StdoutStream *s) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(s); if (s->state != STDOUT_STREAM_RUNNING) return 0; if (!s->state_file) { struct stat st; r = fstat(s->fd, &st); if (r < 0) return log_warning_errno(errno, "Failed to stat connected stream: %m"); /* We use device and inode numbers as identifier for the stream */ if (asprintf(&s->state_file, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino) < 0) return log_oom(); } mkdir_p("/run/systemd/journal/streams", 0755); r = fopen_temporary(s->state_file, &f, &temp_path); if (r < 0) goto fail; fprintf(f, "# This is private data. Do not parse\n" "PRIORITY=%i\n" "LEVEL_PREFIX=%i\n" "FORWARD_TO_SYSLOG=%i\n" "FORWARD_TO_KMSG=%i\n" "FORWARD_TO_CONSOLE=%i\n" "STREAM_ID=%s\n", s->priority, s->level_prefix, s->forward_to_syslog, s->forward_to_kmsg, s->forward_to_console, s->id_field + strlen("_STREAM_ID=")); if (!isempty(s->identifier)) { _cleanup_free_ char *escaped; escaped = cescape(s->identifier); if (!escaped) { r = -ENOMEM; goto fail; } fprintf(f, "IDENTIFIER=%s\n", escaped); } if (!isempty(s->unit_id)) { _cleanup_free_ char *escaped; escaped = cescape(s->unit_id); if (!escaped) { r = -ENOMEM; goto fail; } fprintf(f, "UNIT=%s\n", escaped); } r = fflush_and_check(f); if (r < 0) goto fail; if (rename(temp_path, s->state_file) < 0) { r = -errno; goto fail; } if (!s->fdstore && !s->in_notify_queue) { LIST_PREPEND(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s); s->in_notify_queue = true; if (s->server->notify_event_source) { r = sd_event_source_set_enabled(s->server->notify_event_source, SD_EVENT_ON); if (r < 0) log_warning_errno(r, "Failed to enable notify event source: %m"); } } return 0; fail: (void) unlink(s->state_file); if (temp_path) (void) unlink(temp_path); return log_error_errno(r, "Failed to save stream data %s: %m", s->state_file); }