int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_(image_hashmap_freep) Hashmap *images = NULL; _cleanup_strv_free_ char **l = NULL; Image *image; Iterator i; int r; assert(bus); assert(path); assert(nodes); images = hashmap_new(&string_hash_ops); if (!images) return -ENOMEM; r = image_discover(images); if (r < 0) return r; HASHMAP_FOREACH(image, images, i) { char *p; p = image_bus_path(image->name); if (!p) return -ENOMEM; r = strv_consume(&l, p); if (r < 0) return r; }
static int write_requires_after(FILE *f, const char *opts) { _cleanup_strv_free_ char **names = NULL, **units = NULL; _cleanup_free_ char *res = NULL; char **s; int r; assert(f); assert(opts); r = fstab_extract_values(opts, "x-systemd.requires", &names); if (r < 0) return log_warning_errno(r, "Failed to parse options: %m"); if (r == 0) return 0; STRV_FOREACH(s, names) { char *x; r = unit_name_mangle_with_suffix(*s, UNIT_NAME_NOGLOB, ".mount", &x); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); r = strv_consume(&units, x); if (r < 0) return log_oom(); }
static int load_env_file_push( const char *filename, unsigned line, const char *key, char *value, void *userdata) { char ***m = userdata; char *p; int r; if (!utf8_is_valid(key)) { _cleanup_free_ char *t = utf8_escape_invalid(key); log_error("%s:%u: invalid UTF-8 for key '%s', ignoring.", strna(filename), line, t); return -EINVAL; } if (value && !utf8_is_valid(value)) { _cleanup_free_ char *t = utf8_escape_invalid(value); log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, t); return -EINVAL; } p = strjoin(key, "=", strempty(value), NULL); if (!p) return -ENOMEM; r = strv_consume(m, p); if (r < 0) return r; free(value); return 0; }
int search_acl_groups(char*** dst, const char* path, bool* belong) { acl_t acl; assert(path); assert(belong); acl = acl_get_file(path, ACL_TYPE_DEFAULT); if (acl) { acl_entry_t entry; int r; r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); while (r > 0) { acl_tag_t tag; gid_t *gid; char *name; r = acl_get_tag_type(entry, &tag); if (r < 0) break; if (tag != ACL_GROUP) goto next; gid = acl_get_qualifier(entry); if (!gid) break; if (in_gid(*gid) > 0) { *belong = true; break; } name = gid_to_name(*gid); if (!name) { acl_free(acl); return log_oom(); } r = strv_consume(dst, name); if (r < 0) { acl_free(acl); return log_oom(); } next: r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); } acl_free(acl); } return 0; }
int config_parse_strv(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) { char ***sv = data; const char *word, *state; size_t l; int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); if (isempty(rvalue)) { char **empty; /* Empty assignment resets the list. As a special rule * we actually fill in a real empty array here rather * than NULL, since some code wants to know if * something was set at all... */ empty = strv_new(NULL, NULL); if (!empty) return log_oom(); strv_free(*sv); *sv = empty; return 0; } FOREACH_WORD_QUOTED(word, l, rvalue, state) { char *n; n = strndup(word, l); if (!n) return log_oom(); if (!utf8_is_valid(n)) { log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue); continue; } r = strv_consume(sv, n); if (r < 0) return log_oom(); }
int strv_extend(char ***l, const char *value) { char *v; if (!value) return 0; v = strdup(value); if (!v) return -ENOMEM; return strv_consume(l, v); }
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 generate_path(char **var, char **filenames) { char **filename; _cleanup_strv_free_ char **ans = NULL; int r; STRV_FOREACH(filename, filenames) { char *t; t = dirname_malloc(*filename); if (!t) return -ENOMEM; r = strv_consume(&ans, t); if (r < 0) return r; }
static int driver_list_queued_owners(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { struct kdbus_cmd_name_list cmd = {}; struct kdbus_name_list *name_list; struct kdbus_cmd_name *name; _cleanup_strv_free_ char **owners = NULL; char *arg0; int r; r = sd_bus_message_read(m, "s", &arg0); if (r < 0) return r; assert_return(service_name_is_valid(arg0), -EINVAL); cmd.flags = KDBUS_NAME_LIST_QUEUED; r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd); if (r < 0) return -errno; name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset); KDBUS_ITEM_FOREACH(name, name_list, names) { char *n; if (name->size <= sizeof(*name)) continue; if (!streq(name->name, arg0)) continue; if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) return -ENOMEM; r = strv_consume(&owners, n); if (r < 0) return r; }
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; }
int pull_find_old_etags( const char *url, const char *image_root, int dt, const char *prefix, const char *suffix, char ***etags) { _cleanup_free_ char *escaped_url = NULL; _cleanup_closedir_ DIR *d = NULL; _cleanup_strv_free_ char **l = NULL; struct dirent *de; int r; assert(url); assert(etags); if (!image_root) image_root = "/var/lib/machines"; escaped_url = xescape(url, FILENAME_ESCAPE); if (!escaped_url) return -ENOMEM; d = opendir(image_root); if (!d) { if (errno == ENOENT) { *etags = NULL; return 0; } return -errno; } FOREACH_DIRENT_ALL(de, d, return -errno) { const char *a, *b; char *u; if (de->d_type != DT_UNKNOWN && de->d_type != dt) continue; if (prefix) { a = startswith(de->d_name, prefix); if (!a) continue; } else a = de->d_name; a = startswith(a, escaped_url); if (!a) continue; a = startswith(a, "."); if (!a) continue; if (suffix) { b = endswith(de->d_name, suffix); if (!b) continue; } else b = strchr(de->d_name, 0); if (a >= b) continue; r = cunescape_length(a, b - a, 0, &u); if (r < 0) return r; if (!http_etag_is_valid(u)) { free(u); continue; } r = strv_consume(&l, u); if (r < 0) return r; } *etags = l; l = NULL; return 0; }
static int parse_proc_cmdline_item(const char *key, const char *value) { int r; assert(key); if (streq(key, "systemd.mask")) { if (!value) log_error("Missing argument for systemd.mask= kernel command line parameter."); else { char *n; r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n); if (r < 0) return log_error_errno(r, "Failed to glob unit name: %m"); r = strv_consume(&arg_mask, n); if (r < 0) return log_oom(); } } else if (streq(key, "systemd.wants")) { if (!value) log_error("Missing argument for systemd.want= kernel command line parameter."); else { char *n; r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n); if (r < 0) return log_error_errno(r, "Failed to glob unit name: %m"); r = strv_consume(&arg_wants, n); if (r < 0) return log_oom(); } } else if (streq(key, "systemd.debug-shell")) { if (value) { r = parse_boolean(value); if (r < 0) log_error("Failed to parse systemd.debug-shell= argument '%s', ignoring.", value); else arg_debug_shell = r; } else arg_debug_shell = true; } else if (streq(key, "systemd.unit")) { if (!value) log_error("Missing argument for systemd.unit= kernel command line parameter."); else { r = free_and_strdup(&arg_default_unit, value); if (r < 0) return log_error_errno(r, "Failed to set default unit %s: %m", value); } } else if (!value) { const char *target; target = runlevel_to_target(key); if (target) { r = free_and_strdup(&arg_default_unit, target); if (r < 0) return log_error_errno(r, "Failed to set default unit %s: %m", target); } } return 0; }
int acl_search_groups(const char *path, char ***ret_groups) { _cleanup_strv_free_ char **g = NULL; _cleanup_(acl_freep) acl_t acl = NULL; bool ret = false; acl_entry_t entry; int r; assert(path); acl = acl_get_file(path, ACL_TYPE_DEFAULT); if (!acl) return -errno; r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); for (;;) { _cleanup_(acl_free_gid_tpp) gid_t *gid = NULL; acl_tag_t tag; if (r < 0) return -errno; if (r == 0) break; if (acl_get_tag_type(entry, &tag) < 0) return -errno; if (tag != ACL_GROUP) goto next; gid = acl_get_qualifier(entry); if (!gid) return -errno; if (in_gid(*gid) > 0) { if (!ret_groups) return true; ret = true; } if (ret_groups) { char *name; name = gid_to_name(*gid); if (!name) return -ENOMEM; r = strv_consume(&g, name); if (r < 0) return r; } next: r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); } if (ret_groups) *ret_groups = TAKE_PTR(g); return ret; }