int can_sleep_disk(char **types) { char **type; int r; _cleanup_free_ char *p = NULL; if (strv_isempty(types)) return true; /* If /sys is read-only we cannot sleep */ if (access("/sys/power/disk", W_OK) < 0) return false; r = read_one_line_file("/sys/power/disk", &p); if (r < 0) return false; STRV_FOREACH(type, types) { const char *word, *state; size_t l, k; k = strlen(*type); FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state) { if (l == k && memcmp(word, *type, l) == 0) return true; if (l == k + 2 && word[0] == '[' && memcmp(word + 1, *type, l - 2) == 0 && word[l-1] == ']') return true; } } return false; }
int safe_glob(const char *path, int flags, glob_t *pglob) { int k; /* We want to set GLOB_ALTDIRFUNC ourselves, don't allow it to be set. */ assert(!(flags & GLOB_ALTDIRFUNC)); if (!pglob->gl_closedir) pglob->gl_closedir = closedir_wrapper; if (!pglob->gl_readdir) pglob->gl_readdir = (struct dirent *(*)(void *)) readdir_no_dot; if (!pglob->gl_opendir) pglob->gl_opendir = (void *(*)(const char *)) opendir; if (!pglob->gl_lstat) pglob->gl_lstat = lstat; if (!pglob->gl_stat) pglob->gl_stat = stat; errno = 0; k = glob(path, flags | GLOB_ALTDIRFUNC, NULL, pglob); if (k == GLOB_NOMATCH) return -ENOENT; if (k == GLOB_NOSPACE) return -ENOMEM; if (k != 0) return errno > 0 ? -errno : -EIO; if (strv_isempty(pglob->gl_pathv)) return -ENOENT; return 0; }
static void print_status_info(StatusInfo *i) { assert(i); if (strv_isempty(i->locale)) puts(" System Locale: n/a\n"); else { char **j; printf(" System Locale: %s\n", i->locale[0]); STRV_FOREACH(j, i->locale + 1) printf(" %s\n", *j); } printf(" VC Keymap: %s\n", strna(i->vconsole_keymap)); if (!isempty(i->vconsole_keymap_toggle)) printf("VC Toggle Keymap: %s\n", i->vconsole_keymap_toggle); printf(" X11 Layout: %s\n", strna(i->x11_layout)); if (!isempty(i->x11_model)) printf(" X11 Model: %s\n", i->x11_model); if (!isempty(i->x11_variant)) printf(" X11 Variant: %s\n", i->x11_variant); if (!isempty(i->x11_options)) printf(" X11 Options: %s\n", i->x11_options); }
static int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) { _cleanup_strv_free_ char **l = NULL; const char *dir; keymaps = set_new(string_hash_func, string_compare_func); if (!keymaps) return log_oom(); NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) nftw(dir, nftw_cb, 20, FTW_MOUNT|FTW_PHYS); l = set_get_strv(keymaps); if (!l) { set_free_free(keymaps); return log_oom(); } set_free(keymaps); if (strv_isempty(l)) { log_error("Couldn't find any console keymaps."); return -ENOENT; } strv_sort(l); pager_open_if_enabled(); strv_print(l); return 0; }
int vconsole_write_data(Context *c) { _cleanup_strv_free_ char **l = NULL; struct stat st; int r; r = load_env_file(NULL, "/etc/vconsole.conf", NULL, &l); if (r < 0 && r != -ENOENT) return r; if (isempty(c->vc_keymap)) l = strv_env_unset(l, "KEYMAP"); else { _cleanup_free_ char *s = NULL; char **u; s = strappend("KEYMAP=", c->vc_keymap); if (!s) return -ENOMEM; u = strv_env_set(l, s); if (!u) return -ENOMEM; strv_free_and_replace(l, u); } if (isempty(c->vc_keymap_toggle)) l = strv_env_unset(l, "KEYMAP_TOGGLE"); else { _cleanup_free_ char *s = NULL; char **u; s = strappend("KEYMAP_TOGGLE=", c->vc_keymap_toggle); if (!s) return -ENOMEM; u = strv_env_set(l, s); if (!u) return -ENOMEM; strv_free_and_replace(l, u); } if (strv_isempty(l)) { if (unlink("/etc/vconsole.conf") < 0) return errno == ENOENT ? 0 : -errno; c->vc_mtime = USEC_INFINITY; return 0; } r = write_env_file_label("/etc/vconsole.conf", l); if (r < 0) return r; if (stat("/etc/vconsole.conf", &st) >= 0) c->vc_mtime = timespec_load(&st.st_mtim); return 0; }
static int list_vconsole_keymaps(DBusConnection *bus, char **args, unsigned n) { char _cleanup_strv_free_ **l = NULL; char **i; keymaps = set_new(string_hash_func, string_compare_func); if (!keymaps) return log_oom(); nftw("/usr/share/kbd/keymaps/", nftw_cb, 20, FTW_MOUNT|FTW_PHYS); nftw("/usr/lib/kbd/keymaps/", nftw_cb, 20, FTW_MOUNT|FTW_PHYS); nftw("/lib/kbd/keymaps/", nftw_cb, 20, FTW_MOUNT|FTW_PHYS); l = set_get_strv(keymaps); if (!l) { set_free_free(keymaps); return log_oom(); } set_free(keymaps); if (strv_isempty(l)) { log_error("Couldn't find any console keymaps."); return -ENOENT; } strv_sort(l); pager_open_if_enabled(); STRV_FOREACH(i, l) puts(*i); return 0; }
static int status_entries(const char *esp_path, sd_id128_t partition) { int r; _cleanup_(boot_config_free) BootConfig config = {}; printf("Default Boot Entry:\n"); r = boot_entries_load_config(esp_path, &config); if (r < 0) return log_error_errno(r, "Failed to load bootspec config from \"%s/loader\": %m", esp_path); if (config.default_entry < 0) printf("%zu entries, no entry suitable as default", config.n_entries); else { const BootEntry *e = &config.entries[config.default_entry]; printf(" title: %s\n", boot_entry_title(e)); if (e->version) printf(" version: %s\n", e->version); if (e->kernel) printf(" linux: %s\n", e->kernel); if (!strv_isempty(e->initrd)) { _cleanup_free_ char *t; t = strv_join(e->initrd, " "); if (!t) return log_oom(); printf(" initrd: %s\n", t); } if (!strv_isempty(e->options)) { _cleanup_free_ char *t; t = strv_join(e->options, " "); if (!t) return log_oom(); printf(" options: %s\n", t); } if (e->device_tree) printf(" devicetree: %s\n", e->device_tree); puts(""); } return 0; }
static const char *dkr_pull_current_layer(DkrPull *i) { assert(i); if (strv_isempty(i->ancestry)) return NULL; return i->ancestry[i->current_ancestry]; }
static int vconsole_write_data(Context *c) { int r; _cleanup_strv_free_ char **l = NULL; r = load_env_file("/etc/vconsole.conf", NULL, &l); if (r < 0 && r != -ENOENT) return r; if (isempty(c->vc_keymap)) l = strv_env_unset(l, "KEYMAP"); else { char *s, **u; s = strappend("KEYMAP=", c->vc_keymap); if (!s) return -ENOMEM; u = strv_env_set(l, s); free(s); strv_free(l); if (!u) return -ENOMEM; l = u; } if (isempty(c->vc_keymap_toggle)) l = strv_env_unset(l, "KEYMAP_TOGGLE"); else { char *s, **u; s = strappend("KEYMAP_TOGGLE=", c->vc_keymap_toggle); if (!s) return -ENOMEM; u = strv_env_set(l, s); free(s); strv_free(l); if (!u) return -ENOMEM; l = u; } if (strv_isempty(l)) { if (unlink("/etc/vconsole.conf") < 0) return errno == ENOENT ? 0 : -errno; return 0; } r = write_env_file_label("/etc/vconsole.conf", l); return r; }
static char *strdup_structured_data(struct structured_data *sd) { char *res, *tmp; if (strv_isempty(sd->params)) return NULL; xasprintf(&res, "[%s %s]", sd->id, (tmp = strv_join(sd->params, " "))); free(tmp); return res; }
static int determine_matches(const char *image, char **l, bool allow_any, char ***ret) { _cleanup_strv_free_ char **k = NULL; int r; /* Determine the matches to apply. If the list is empty we derive the match from the image name. If the list * contains exactly the "-" we return a wildcard list (which is the empty list), but only if this is expressly * permitted. */ if (strv_isempty(l)) { char *prefix; r = extract_prefix(image, &prefix); if (r < 0) return log_error_errno(r, "Failed to extract prefix of image name '%s': %m", image); if (!arg_quiet) log_info("(Matching unit files with prefix '%s'.)", prefix); r = strv_consume(&k, prefix); if (r < 0) return log_oom(); } else if (strv_equal(l, STRV_MAKE("-"))) { if (!allow_any) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Refusing all unit file match."); if (!arg_quiet) log_info("(Matching all unit files.)"); } else { k = strv_copy(l); if (!k) return log_oom(); if (!arg_quiet) { _cleanup_free_ char *joined = NULL; joined = strv_join(k, "', '"); if (!joined) return log_oom(); log_info("(Matching unit files with prefixes '%s'.)", joined); } } *ret = TAKE_PTR(k); return 0; }
static int context_write_data_machine_info(Context *c) { static const char * const name[_PROP_MAX] = { [PROP_PRETTY_HOSTNAME] = "PRETTY_HOSTNAME", [PROP_ICON_NAME] = "ICON_NAME", [PROP_CHASSIS] = "CHASSIS", [PROP_DEPLOYMENT] = "DEPLOYMENT", [PROP_LOCATION] = "LOCATION", }; _cleanup_strv_free_ char **l = NULL; int r, p; assert(c); r = load_env_file(NULL, "/etc/machine-info", NULL, &l); if (r < 0 && r != -ENOENT) return r; for (p = PROP_PRETTY_HOSTNAME; p <= PROP_LOCATION; p++) { _cleanup_free_ char *t = NULL; char **u; assert(name[p]); if (isempty(c->data[p])) { strv_env_unset(l, name[p]); continue; } t = strjoin(name[p], "=", c->data[p], NULL); if (!t) return -ENOMEM; u = strv_env_set(l, t); if (!u) return -ENOMEM; strv_free(l); l = u; } if (strv_isempty(l)) { if (unlink("/etc/machine-info") < 0) return errno == ENOENT ? 0 : -errno; return 0; } return write_env_file_label("/etc/machine-info", l); }
int locale_write_data(Context *c, char ***settings) { int r, p; _cleanup_strv_free_ char **l = NULL; /* Set values will be returned as strv in *settings on success. */ r = load_env_file(NULL, "/etc/locale.conf", NULL, &l); if (r < 0 && r != -ENOENT) return r; for (p = 0; p < _VARIABLE_LC_MAX; p++) { _cleanup_free_ char *t = NULL; char **u; const char *name; name = locale_variable_to_string(p); assert(name); if (isempty(c->locale[p])) { l = strv_env_unset(l, name); continue; } if (asprintf(&t, "%s=%s", name, c->locale[p]) < 0) return -ENOMEM; u = strv_env_set(l, t); if (!u) return -ENOMEM; strv_free(l); l = u; } if (strv_isempty(l)) { if (unlink("/etc/locale.conf") < 0) return errno == ENOENT ? 0 : -errno; return 0; } r = write_env_file_label("/etc/locale.conf", l); if (r < 0) return r; *settings = TAKE_PTR(l); return 0; }
int locale_write_data(Context *c, char ***settings) { _cleanup_strv_free_ char **l = NULL; struct stat st; int r, p; /* Set values will be returned as strv in *settings on success. */ for (p = 0; p < _VARIABLE_LC_MAX; p++) { _cleanup_free_ char *t = NULL; char **u; const char *name; name = locale_variable_to_string(p); assert(name); if (isempty(c->locale[p])) continue; if (asprintf(&t, "%s=%s", name, c->locale[p]) < 0) return -ENOMEM; u = strv_env_set(l, t); if (!u) return -ENOMEM; strv_free_and_replace(l, u); } if (strv_isempty(l)) { if (unlink("/etc/locale.conf") < 0) return errno == ENOENT ? 0 : -errno; c->locale_mtime = USEC_INFINITY; return 0; } r = write_env_file_label("/etc/locale.conf", l); if (r < 0) return r; *settings = TAKE_PTR(l); if (stat("/etc/locale.conf", &st) >= 0) c->locale_mtime = timespec_load(&st.st_mtim); return 0; }
static int locale_write_data(Context *c) { int r, p; char **l = NULL; r = load_env_file("/etc/locale.conf", NULL, &l); if (r < 0 && r != -ENOENT) return r; for (p = 0; p < _LOCALE_MAX; p++) { char *t, **u; assert(names[p]); if (isempty(c->locale[p])) { l = strv_env_unset(l, names[p]); continue; } if (asprintf(&t, "%s=%s", names[p], c->locale[p]) < 0) { strv_free(l); return -ENOMEM; } u = strv_env_set(l, t); free(t); strv_free(l); if (!u) return -ENOMEM; l = u; } if (strv_isempty(l)) { strv_free(l); if (unlink("/etc/locale.conf") < 0) return errno == ENOENT ? 0 : -errno; return 0; } r = write_env_file_label("/etc/locale.conf", l); strv_free(l); return r; }
static int generate_mask_symlinks(void) { char **u; int r = 0; if (strv_isempty(arg_mask)) return 0; STRV_FOREACH(u, arg_mask) { _cleanup_free_ char *p = NULL; p = strjoin(arg_dest, "/", *u, NULL); if (!p) return log_oom(); if (symlink("/dev/null", p) < 0) r = log_error_errno(errno, "Failed to create mask symlink %s: %m", p); }
static void test_config_parse_pass_environ(void) { /* int config_parse_pass_environ( const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) */ int r; _cleanup_strv_free_ char **passenv = NULL; r = config_parse_pass_environ(NULL, "fake", 1, "section", 1, "PassEnvironment", 0, "A B", &passenv, NULL); assert_se(r >= 0); assert_se(strv_length(passenv) == 2); assert_se(streq(passenv[0], "A")); assert_se(streq(passenv[1], "B")); r = config_parse_pass_environ(NULL, "fake", 1, "section", 1, "PassEnvironment", 0, "", &passenv, NULL); assert_se(r >= 0); assert_se(strv_isempty(passenv)); r = config_parse_pass_environ(NULL, "fake", 1, "section", 1, "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\", &passenv, NULL); assert_se(r >= 0); assert_se(strv_length(passenv) == 1); assert_se(streq(passenv[0], "normal_name")); }
int can_sleep_state(char **types) { char *w, *state, **type; int r; _cleanup_free_ char *p = NULL; if (strv_isempty(types)) return true; /* If /sys is read-only we cannot sleep */ if (access("/sys/power/state", W_OK) < 0) return false; r = read_one_line_file("/sys/power/state", &p); if (r < 0) return false; STRV_FOREACH(type, types) { size_t l, k; k = strlen(*type); FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) if (l == k && memcmp(w, *type, l) == 0) return true; }
static int transient_service_set_properties(sd_bus_message *m, char **argv, const char *pty_path) { int r; assert(m); r = transient_unit_set_properties(m, arg_property); if (r < 0) return r; r = transient_kill_set_properties(m); if (r < 0) return r; r = transient_cgroup_set_properties(m); if (r < 0) return r; if (arg_wait) { r = sd_bus_message_append(m, "(sv)", "AddRef", "b", 1); if (r < 0) return r; } if (arg_remain_after_exit) { r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit); if (r < 0) return r; } if (arg_service_type) { r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type); if (r < 0) return r; } if (arg_exec_user) { r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user); if (r < 0) return r; } if (arg_exec_group) { r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group); if (r < 0) return r; } if (arg_nice_set) { r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice); if (r < 0) return r; } if (pty_path) { const char *e; r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)", "StandardInput", "s", "tty", "StandardOutput", "s", "tty", "StandardError", "s", "tty", "TTYPath", "s", pty_path); if (r < 0) return r; e = getenv("TERM"); if (e) { char *n; n = strjoina("TERM=", e); r = sd_bus_message_append(m, "(sv)", "Environment", "as", 1, n); if (r < 0) return r; } } if (!strv_isempty(arg_environment)) { r = sd_bus_message_open_container(m, 'r', "sv"); if (r < 0) return r; r = sd_bus_message_append(m, "s", "Environment"); if (r < 0) return r; r = sd_bus_message_open_container(m, 'v', "as"); if (r < 0) return r; r = sd_bus_message_append_strv(m, arg_environment); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; } /* Exec container */ { r = sd_bus_message_open_container(m, 'r', "sv"); if (r < 0) return r; r = sd_bus_message_append(m, "s", "ExecStart"); if (r < 0) return r; r = sd_bus_message_open_container(m, 'v', "a(sasb)"); if (r < 0) return r; r = sd_bus_message_open_container(m, 'a', "(sasb)"); if (r < 0) return r; r = sd_bus_message_open_container(m, 'r', "sasb"); if (r < 0) return r; r = sd_bus_message_append(m, "s", argv[0]); if (r < 0) return r; r = sd_bus_message_append_strv(m, argv); if (r < 0) return r; r = sd_bus_message_append(m, "b", false); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; r = sd_bus_message_close_container(m); if (r < 0) return r; } return 0; }
int locale_setup(char ***environment) { char **add; char *variables[_VARIABLE_MAX] = {}; int r = 0, i; if (detect_container(NULL) <= 0) { r = parse_env_file("/proc/cmdline", WHITESPACE, "locale.LANG", &variables[VARIABLE_LANG], "locale.LANGUAGE", &variables[VARIABLE_LANGUAGE], "locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE], "locale.LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC], "locale.LC_TIME", &variables[VARIABLE_LC_TIME], "locale.LC_COLLATE", &variables[VARIABLE_LC_COLLATE], "locale.LC_MONETARY", &variables[VARIABLE_LC_MONETARY], "locale.LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES], "locale.LC_PAPER", &variables[VARIABLE_LC_PAPER], "locale.LC_NAME", &variables[VARIABLE_LC_NAME], "locale.LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS], "locale.LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE], "locale.LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT], "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION], NULL); if (r < 0 && r != -ENOENT) log_warning("Failed to read /proc/cmdline: %s", strerror(-r)); } /* Hmm, nothing set on the kernel cmd line? Then let's * try /etc/locale.conf */ if (r <= 0) { r = parse_env_file("/etc/locale.conf", NEWLINE, "LANG", &variables[VARIABLE_LANG], "LANGUAGE", &variables[VARIABLE_LANGUAGE], "LC_CTYPE", &variables[VARIABLE_LC_CTYPE], "LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC], "LC_TIME", &variables[VARIABLE_LC_TIME], "LC_COLLATE", &variables[VARIABLE_LC_COLLATE], "LC_MONETARY", &variables[VARIABLE_LC_MONETARY], "LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES], "LC_PAPER", &variables[VARIABLE_LC_PAPER], "LC_NAME", &variables[VARIABLE_LC_NAME], "LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS], "LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE], "LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT], "LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION], NULL); if (r < 0 && r != -ENOENT) log_warning("Failed to read /etc/locale.conf: %s", strerror(-r)); } if (r <= 0) { r = parse_env_file("/etc/default/locale", NEWLINE, "LANG", &variables[VARIABLE_LANG], "LANGUAGE", &variables[VARIABLE_LANGUAGE], "LC_CTYPE", &variables[VARIABLE_LC_CTYPE], "LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC], "LC_TIME", &variables[VARIABLE_LC_TIME], "LC_COLLATE", &variables[VARIABLE_LC_COLLATE], "LC_MONETARY", &variables[VARIABLE_LC_MONETARY], "LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES], "LC_PAPER", &variables[VARIABLE_LC_PAPER], "LC_NAME", &variables[VARIABLE_LC_NAME], "LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS], "LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE], "LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT], "LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION], NULL); if (r < 0 && r != -ENOENT) log_warning("Failed to read /etc/default/locale: %s", strerror(-r)); } add = NULL; for (i = 0; i < _VARIABLE_MAX; i++) { char *s; if (!variables[i]) continue; s = strjoin(variable_names[i], "=", variables[i], NULL); if (!s) { r = -ENOMEM; goto finish; } if (strv_consume(&add, s) < 0) { r = -ENOMEM; goto finish; } } if (!strv_isempty(add)) { char **e; e = strv_env_merge(2, *environment, add); if (!e) { r = -ENOMEM; goto finish; } strv_free(*environment); *environment = e; } r = 0; finish: strv_free(add); for (i = 0; i < _VARIABLE_MAX; i++) free(variables[i]); return r; }
static void test_strv_split_empty(void) { _cleanup_strv_free_ char **l = NULL; l = strv_split("", WHITESPACE); assert_se(l); assert_se(strv_isempty(l)); strv_free(l); l = strv_split("", NULL); assert_se(l); assert_se(strv_isempty(l)); strv_free(l); l = strv_split_full("", NULL, 0); assert_se(l); assert_se(strv_isempty(l)); strv_free(l); l = strv_split_full("", NULL, SPLIT_QUOTES); assert_se(l); assert_se(strv_isempty(l)); strv_free(l); l = strv_split_full("", WHITESPACE, SPLIT_QUOTES); assert_se(l); assert_se(strv_isempty(l)); strv_free(l); l = strv_split_full("", WHITESPACE, SPLIT_QUOTES | SPLIT_RELAX); assert_se(l); assert_se(strv_isempty(l)); strv_free(l); l = strv_split(" ", WHITESPACE); assert_se(l); assert_se(strv_isempty(l)); strv_free(l); l = strv_split(" ", NULL); assert_se(l); assert_se(strv_isempty(l)); strv_free(l); l = strv_split_full(" ", NULL, 0); assert_se(l); assert_se(strv_isempty(l)); strv_free(l); l = strv_split_full(" ", WHITESPACE, SPLIT_QUOTES); assert_se(l); assert_se(strv_isempty(l)); strv_free(l); l = strv_split_full(" ", NULL, SPLIT_QUOTES); assert_se(l); assert_se(strv_isempty(l)); strv_free(l); l = strv_split_full(" ", NULL, SPLIT_QUOTES | SPLIT_RELAX); assert_se(l); assert_se(strv_isempty(l)); }
int lookup_paths_init( LookupPaths *p, SystemdRunningAs running_as, bool personal, const char *generator, const char *generator_early, const char *generator_late) { const char *e; assert(p); /* First priority is whatever has been passed to us via env * vars */ e = getenv("SYSTEMD_UNIT_PATH"); if (e) { p->unit_path = path_split_and_make_absolute(e); if (!p->unit_path) return -ENOMEM; } else p->unit_path = NULL; if (strv_isempty(p->unit_path)) { /* Nothing is set, so let's figure something out. */ strv_free(p->unit_path); /* For the user units we include share/ in the search * path in order to comply with the XDG basedir * spec. For the system stuff we avoid such * nonsense. OTOH we include /lib in the search path * for the system stuff but avoid it for user * stuff. */ if (running_as == SYSTEMD_USER) { if (personal) p->unit_path = user_dirs(generator, generator_early, generator_late); else p->unit_path = strv_new( /* If you modify this you also want to modify * systemduserunitpath= in systemd.pc.in, and * the arrays in user_dirs() above! */ STRV_IFNOTNULL(generator_early), USER_CONFIG_UNIT_PATH, "/etc/systemd/user", "/run/systemd/user", STRV_IFNOTNULL(generator), "/usr/local/lib/systemd/user", "/usr/local/share/systemd/user", USER_DATA_UNIT_PATH, "/usr/lib/systemd/user", "/usr/share/systemd/user", STRV_IFNOTNULL(generator_late), NULL); if (!p->unit_path) return -ENOMEM; } else { p->unit_path = strv_new( /* If you modify this you also want to modify * systemdsystemunitpath= in systemd.pc.in! */ STRV_IFNOTNULL(generator_early), SYSTEM_CONFIG_UNIT_PATH, "/etc/systemd/system", "/run/systemd/system", STRV_IFNOTNULL(generator), "/usr/local/lib/systemd/system", SYSTEM_DATA_UNIT_PATH, "/usr/lib/systemd/system", #ifdef HAVE_SPLIT_USR "/lib/systemd/system", #endif STRV_IFNOTNULL(generator_late), NULL); if (!p->unit_path) return -ENOMEM; } } if (!path_strv_canonicalize(p->unit_path)) return -ENOMEM; strv_uniq(p->unit_path); if (!strv_isempty(p->unit_path)) { _cleanup_free_ char *t = strv_join(p->unit_path, "\n\t"); if (!t) return -ENOMEM; log_debug("Looking for unit files in (higher priority first):\n\t%s", t); } else { log_debug("Ignoring unit files."); strv_free(p->unit_path); p->unit_path = NULL; } if (running_as == SYSTEMD_SYSTEM) { #ifdef HAVE_SYSV_COMPAT /* /etc/init.d/ compatibility does not matter to users */ e = getenv("SYSTEMD_SYSVINIT_PATH"); if (e) { p->sysvinit_path = path_split_and_make_absolute(e); if (!p->sysvinit_path) return -ENOMEM; } else p->sysvinit_path = NULL; if (strv_isempty(p->sysvinit_path)) { strv_free(p->sysvinit_path); p->sysvinit_path = strv_new( SYSTEM_SYSVINIT_PATH, /* /etc/init.d/ */ NULL); if (!p->sysvinit_path) return -ENOMEM; } e = getenv("SYSTEMD_SYSVRCND_PATH"); if (e) { p->sysvrcnd_path = path_split_and_make_absolute(e); if (!p->sysvrcnd_path) return -ENOMEM; } else p->sysvrcnd_path = NULL; if (strv_isempty(p->sysvrcnd_path)) { strv_free(p->sysvrcnd_path); p->sysvrcnd_path = strv_new( SYSTEM_SYSVRCND_PATH, /* /etc/rcN.d/ */ NULL); if (!p->sysvrcnd_path) return -ENOMEM; } if (!path_strv_canonicalize(p->sysvinit_path)) return -ENOMEM; if (!path_strv_canonicalize(p->sysvrcnd_path)) return -ENOMEM; strv_uniq(p->sysvinit_path); strv_uniq(p->sysvrcnd_path); if (!strv_isempty(p->sysvinit_path)) { _cleanup_free_ char *t = strv_join(p->sysvinit_path, "\n\t"); if (!t) return -ENOMEM; log_debug("Looking for SysV init scripts in:\n\t%s", t); } else { log_debug("Ignoring SysV init scripts."); strv_free(p->sysvinit_path); p->sysvinit_path = NULL; } if (!strv_isempty(p->sysvrcnd_path)) { _cleanup_free_ char *t = strv_join(p->sysvrcnd_path, "\n\t"); if (!t) return -ENOMEM; log_debug("Looking for SysV rcN.d links in:\n\t%s", t); } else { log_debug("Ignoring SysV rcN.d links."); strv_free(p->sysvrcnd_path); p->sysvrcnd_path = NULL; } #else log_debug("SysV init scripts and rcN.d links support disabled"); #endif } return 0; }
int main(int argc, char *argv[]) { _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; _cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL; _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; int r; log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = loop_device_make_by_path(arg_image, (arg_flags & DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : O_RDWR, &d); if (r < 0) { log_error_errno(r, "Failed to set up loopback device: %m"); goto finish; } if (!arg_root_hash) { r = root_hash_load(arg_image, &arg_root_hash, &arg_root_hash_size); if (r < 0) { log_error_errno(r, "Failed to read root hash file for %s: %m", arg_image); goto finish; } } r = dissect_image(d->fd, arg_root_hash, arg_root_hash_size, arg_flags, &m); if (r == -ENOPKG) { log_error_errno(r, "Couldn't identify a suitable partition table or file system in %s.", arg_image); goto finish; } if (r == -EADDRNOTAVAIL) { log_error_errno(r, "No root partition for specified root hash found in %s.", arg_image); goto finish; } if (r == -ENOTUNIQ) { log_error_errno(r, "Multiple suitable root partitions found in image %s.", arg_image); goto finish; } if (r == -ENXIO) { log_error_errno(r, "No suitable root partition found in image %s.", arg_image); goto finish; } if (r == -EPROTONOSUPPORT) { log_error_errno(r, "Device %s is loopback block device with partition scanning turned off, please turn it on.", arg_image); goto finish; } if (r < 0) { log_error_errno(r, "Failed to dissect image: %m"); goto finish; } switch (arg_action) { case ACTION_DISSECT: { unsigned i; for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { DissectedPartition *p = m->partitions + i; int k; if (!p->found) continue; printf("Found %s '%s' partition", p->rw ? "writable" : "read-only", partition_designator_to_string(i)); if (!sd_id128_is_null(p->uuid)) printf(" (UUID " SD_ID128_FORMAT_STR ")", SD_ID128_FORMAT_VAL(p->uuid)); if (p->fstype) printf(" of type %s", p->fstype); if (p->architecture != _ARCHITECTURE_INVALID) printf(" for %s", architecture_to_string(p->architecture)); k = PARTITION_VERITY_OF(i); if (k >= 0) printf(" %s verity", m->partitions[k].found ? "with" : "without"); if (p->partno >= 0) printf(" on partition #%i", p->partno); if (p->node) printf(" (%s)", p->node); putchar('\n'); } r = dissected_image_acquire_metadata(m); if (r < 0) { log_error_errno(r, "Failed to acquire image metadata: %m"); goto finish; } if (m->hostname) printf(" Hostname: %s\n", m->hostname); if (!sd_id128_is_null(m->machine_id)) printf("Machine ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(m->machine_id)); if (!strv_isempty(m->machine_info)) { char **p, **q; STRV_FOREACH_PAIR(p, q, m->machine_info) printf("%s %s=%s\n", p == m->machine_info ? "Mach. Info:" : " ", *p, *q); } if (!strv_isempty(m->os_release)) { char **p, **q; STRV_FOREACH_PAIR(p, q, m->os_release) printf("%s %s=%s\n", p == m->os_release ? "OS Release:" : " ", *p, *q); } break; } case ACTION_MOUNT: r = dissected_image_decrypt_interactively(m, NULL, arg_root_hash, arg_root_hash_size, arg_flags, &di); if (r < 0) goto finish; r = dissected_image_mount(m, arg_path, UID_INVALID, arg_flags); if (r < 0) { log_error_errno(r, "Failed to mount image: %m"); goto finish; } if (di) { r = decrypted_image_relinquish(di); if (r < 0) { log_error_errno(r, "Failed to relinquish DM devices: %m"); goto finish; } } loop_device_relinquish(d); break; default: assert_not_reached("Unknown action."); } finish: free(arg_root_hash); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; }
static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) { _cleanup_fclose_ FILE *f = NULL; _cleanup_strv_free_ char **list = NULL; char line[LINE_MAX]; enum { NONE, MODELS, LAYOUTS, VARIANTS, OPTIONS } state = NONE, look_for; int r; if (n > 2) { log_error("Too many arguments."); return -EINVAL; } f = fopen("/usr/share/X11/xkb/rules/base.lst", "re"); if (!f) { log_error("Failed to open keyboard mapping list. %m"); return -errno; } if (streq(args[0], "list-x11-keymap-models")) look_for = MODELS; else if (streq(args[0], "list-x11-keymap-layouts")) look_for = LAYOUTS; else if (streq(args[0], "list-x11-keymap-variants")) look_for = VARIANTS; else if (streq(args[0], "list-x11-keymap-options")) look_for = OPTIONS; else assert_not_reached("Wrong parameter"); FOREACH_LINE(line, f, break) { char *l, *w; l = strstrip(line); if (isempty(l)) continue; if (l[0] == '!') { if (startswith(l, "! model")) state = MODELS; else if (startswith(l, "! layout")) state = LAYOUTS; else if (startswith(l, "! variant")) state = VARIANTS; else if (startswith(l, "! option")) state = OPTIONS; else state = NONE; continue; } if (state != look_for) continue; w = l + strcspn(l, WHITESPACE); if (n > 1) { char *e; if (*w == 0) continue; *w = 0; w++; w += strspn(w, WHITESPACE); e = strchr(w, ':'); if (!e) continue; *e = 0; if (!streq(w, args[1])) continue; } else *w = 0; r = strv_extend(&list, l); if (r < 0) return log_oom(); } if (strv_isempty(list)) { log_error("Couldn't find any entries."); return -ENOENT; } strv_sort(list); strv_uniq(list); pager_open_if_enabled(); strv_print(list); return 0; }
static int write_data_vconsole(void) { int r; char **l = NULL; r = load_env_file("/etc/vconsole.conf", &l); if (r < 0 && r != -ENOENT) return r; if (isempty(state.vc_keymap)) l = strv_env_unset(l, "KEYMAP"); else { char *s, **u; s = strappend("KEYMAP=", state.vc_keymap); if (!s) { strv_free(l); return -ENOMEM; } u = strv_env_set(l, s); free(s); strv_free(l); if (!u) return -ENOMEM; l = u; } if (isempty(state.vc_keymap_toggle)) l = strv_env_unset(l, "KEYMAP_TOGGLE"); else { char *s, **u; s = strappend("KEYMAP_TOGGLE=", state.vc_keymap_toggle); if (!s) { strv_free(l); return -ENOMEM; } u = strv_env_set(l, s); free(s); strv_free(l); if (!u) return -ENOMEM; l = u; } if (strv_isempty(l)) { strv_free(l); if (unlink("/etc/vconsole.conf") < 0) return errno == ENOENT ? 0 : -errno; return 0; } r = write_env_file("/etc/vconsole.conf", l); strv_free(l); return r; }
static int parse_ancestry(const void *payload, size_t size, char ***ret) { _cleanup_free_ char *buf = NULL; void *json_state = NULL; const char *p; enum { STATE_BEGIN, STATE_ITEM, STATE_COMMA, STATE_END, } state = STATE_BEGIN; _cleanup_strv_free_ char **l = NULL; size_t n = 0, allocated = 0; if (size <= 0) return -EBADMSG; if (memchr(payload, 0, size)) return -EBADMSG; buf = strndup(payload, size); if (!buf) return -ENOMEM; p = buf; for (;;) { _cleanup_free_ char *str; union json_value v = {}; int t; t = json_tokenize(&p, &str, &v, &json_state, NULL); if (t < 0) return t; switch (state) { case STATE_BEGIN: if (t == JSON_ARRAY_OPEN) state = STATE_ITEM; else return -EBADMSG; break; case STATE_ITEM: if (t == JSON_STRING) { if (!dkr_id_is_valid(str)) return -EBADMSG; if (n+1 > LAYERS_MAX) return -EFBIG; if (!GREEDY_REALLOC(l, allocated, n + 2)) return -ENOMEM; l[n++] = str; str = NULL; l[n] = NULL; state = STATE_COMMA; } else if (t == JSON_ARRAY_CLOSE) state = STATE_END; else return -EBADMSG; break; case STATE_COMMA: if (t == JSON_COMMA) state = STATE_ITEM; else if (t == JSON_ARRAY_CLOSE) state = STATE_END; else return -EBADMSG; break; case STATE_END: if (t == JSON_END) { if (strv_isempty(l)) return -EBADMSG; if (!strv_is_uniq(l)) return -EBADMSG; l = strv_reverse(l); *ret = l; l = NULL; return 0; } else return -EBADMSG; } } }
static int start_transient_timer( sd_bus *bus, char **argv) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; _cleanup_free_ char *timer = NULL, *service = NULL; const char *object = NULL; int r; assert(bus); assert(argv); r = bus_wait_for_jobs_new(bus, &w); if (r < 0) return log_oom(); if (arg_unit) { switch (unit_name_to_type(arg_unit)) { case UNIT_SERVICE: service = strdup(arg_unit); if (!service) return log_oom(); r = unit_name_change_suffix(service, ".timer", &timer); if (r < 0) return log_error_errno(r, "Failed to change unit suffix: %m"); break; case UNIT_TIMER: timer = strdup(arg_unit); if (!timer) return log_oom(); r = unit_name_change_suffix(timer, ".service", &service); if (r < 0) return log_error_errno(r, "Failed to change unit suffix: %m"); break; default: r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".service", &service); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".timer", &timer); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); break; } } else { r = make_unit_name(bus, UNIT_SERVICE, &service); if (r < 0) return r; r = unit_name_change_suffix(service, ".timer", &timer); if (r < 0) return log_error_errno(r, "Failed to change unit suffix: %m"); } r = sd_bus_message_new_method_call( bus, &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartTransientUnit"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); if (r < 0) return bus_log_create_error(r); /* Name and Mode */ r = sd_bus_message_append(m, "ss", timer, "fail"); if (r < 0) return bus_log_create_error(r); /* Properties */ r = sd_bus_message_open_container(m, 'a', "(sv)"); if (r < 0) return bus_log_create_error(r); r = transient_timer_set_properties(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'a', "(sa(sv))"); if (r < 0) return bus_log_create_error(r); if (!strv_isempty(argv)) { r = sd_bus_message_open_container(m, 'r', "sa(sv)"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append(m, "s", service); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_open_container(m, 'a', "(sv)"); if (r < 0) return bus_log_create_error(r); r = transient_service_set_properties(m, argv, NULL); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); } r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); polkit_agent_open_if_enabled(); r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) { log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r)); return r; } r = sd_bus_message_read(reply, "o", &object); if (r < 0) return bus_log_parse_error(r); r = bus_wait_for_jobs_one(w, object, arg_quiet); if (r < 0) return r; if (!arg_quiet) { log_info("Running timer as unit: %s", timer); if (argv[0]) log_info("Will run service as unit: %s", service); } return 0; }
int lookup_paths_init( LookupPaths *p, SystemdRunningAs running_as, bool personal, const char *root_dir, const char *generator, const char *generator_early, const char *generator_late) { const char *e; bool append = false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */ assert(p); /* First priority is whatever has been passed to us via env * vars */ e = getenv("SYSTEMD_UNIT_PATH"); if (e) { if (endswith(e, ":")) { e = strndupa(e, strlen(e) - 1); append = true; } /* FIXME: empty components in other places should be * rejected. */ p->unit_path = path_split_and_make_absolute(e); if (!p->unit_path) return -ENOMEM; } else p->unit_path = NULL; if (!p->unit_path || append) { /* Let's figure something out. */ _cleanup_strv_free_ char **unit_path; int r; /* For the user units we include share/ in the search * path in order to comply with the XDG basedir spec. * For the system stuff we avoid such nonsense. OTOH * we include /lib in the search path for the system * stuff but avoid it for user stuff. */ if (running_as == SYSTEMD_USER) { if (personal) unit_path = user_dirs(generator, generator_early, generator_late); else unit_path = strv_new( /* If you modify this you also want to modify * systemduserunitpath= in systemd.pc.in, and * the arrays in user_dirs() above! */ STRV_IFNOTNULL(generator_early), USER_CONFIG_UNIT_PATH, "/etc/systemd/user", "/run/systemd/user", STRV_IFNOTNULL(generator), "/usr/local/lib/systemd/user", "/usr/local/share/systemd/user", USER_DATA_UNIT_PATH, "/usr/lib/systemd/user", "/usr/share/systemd/user", STRV_IFNOTNULL(generator_late), NULL); } else unit_path = strv_new( /* If you modify this you also want to modify * systemdsystemunitpath= in systemd.pc.in! */ STRV_IFNOTNULL(generator_early), SYSTEM_CONFIG_UNIT_PATH, "/etc/systemd/system", "/run/systemd/system", STRV_IFNOTNULL(generator), "/usr/local/lib/systemd/system", SYSTEM_DATA_UNIT_PATH, "/usr/lib/systemd/system", #ifdef HAVE_SPLIT_USR "/lib/systemd/system", #endif STRV_IFNOTNULL(generator_late), NULL); if (!unit_path) return -ENOMEM; r = strv_extend_strv(&p->unit_path, unit_path); if (r < 0) return r; } if (!path_strv_resolve_uniq(p->unit_path, root_dir)) return -ENOMEM; if (!strv_isempty(p->unit_path)) { _cleanup_free_ char *t = strv_join(p->unit_path, "\n\t"); if (!t) return -ENOMEM; log_debug("Looking for unit files in (higher priority first):\n\t%s", t); } else { log_debug("Ignoring unit files."); strv_free(p->unit_path); p->unit_path = NULL; } if (running_as == SYSTEMD_SYSTEM) { #ifdef HAVE_SYSV_COMPAT /* /etc/init.d/ compatibility does not matter to users */ e = getenv("SYSTEMD_SYSVINIT_PATH"); if (e) { p->sysvinit_path = path_split_and_make_absolute(e); if (!p->sysvinit_path) return -ENOMEM; } else p->sysvinit_path = NULL; if (strv_isempty(p->sysvinit_path)) { strv_free(p->sysvinit_path); p->sysvinit_path = strv_new( SYSTEM_SYSVINIT_PATH, /* /etc/init.d/ */ NULL); if (!p->sysvinit_path) return -ENOMEM; } e = getenv("SYSTEMD_SYSVRCND_PATH"); if (e) { p->sysvrcnd_path = path_split_and_make_absolute(e); if (!p->sysvrcnd_path) return -ENOMEM; } else p->sysvrcnd_path = NULL; if (strv_isempty(p->sysvrcnd_path)) { strv_free(p->sysvrcnd_path); p->sysvrcnd_path = strv_new( SYSTEM_SYSVRCND_PATH, /* /etc/rcN.d/ */ NULL); if (!p->sysvrcnd_path) return -ENOMEM; } if (!path_strv_resolve_uniq(p->sysvinit_path, root_dir)) return -ENOMEM; if (!path_strv_resolve_uniq(p->sysvrcnd_path, root_dir)) return -ENOMEM; if (!strv_isempty(p->sysvinit_path)) { _cleanup_free_ char *t = strv_join(p->sysvinit_path, "\n\t"); if (!t) return -ENOMEM; log_debug("Looking for SysV init scripts in:\n\t%s", t); } else { log_debug("Ignoring SysV init scripts."); strv_free(p->sysvinit_path); p->sysvinit_path = NULL; } if (!strv_isempty(p->sysvrcnd_path)) { _cleanup_free_ char *t = strv_join(p->sysvrcnd_path, "\n\t"); if (!t) return -ENOMEM; log_debug("Looking for SysV rcN.d links in:\n\t%s", t); } else { log_debug("Ignoring SysV rcN.d links."); strv_free(p->sysvrcnd_path); p->sysvrcnd_path = NULL; } #else log_debug("SysV init scripts and rcN.d links support disabled"); #endif } return 0; }