From 19f6d710772305610b928bc2678b9d77fe11e770 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Sep 2013 10:03:46 -0500 Subject: specifier: rework specifier calls to return proper error message Previously the specifier calls could only indicate OOM by returning NULL. With this change they will return negative errno-style error codes like everything else. --- src/shared/install-printf.c | 54 ++++++++++++++++------- src/shared/install-printf.h | 2 +- src/shared/install.c | 25 ++++++----- src/shared/specifier.c | 105 +++++++++++++++++++++++++++----------------- src/shared/specifier.h | 14 +++--- 5 files changed, 123 insertions(+), 77 deletions(-) (limited to 'src/shared') diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c index 1157ea989b..1ee1243f4d 100644 --- a/src/shared/install-printf.c +++ b/src/shared/install-printf.c @@ -27,21 +27,35 @@ #include "util.h" #include "install-printf.h" -static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) { +static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) { InstallInfo *i = userdata; + char *n; + assert(i); - return unit_name_to_prefix_and_instance(i->name); + n = unit_name_to_prefix_and_instance(i->name); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; } -static char *specifier_prefix(char specifier, void *data, void *userdata) { +static int specifier_prefix(char specifier, void *data, void *userdata, char **ret) { InstallInfo *i = userdata; + char *n; + assert(i); - return unit_name_to_prefix(i->name); + n = unit_name_to_prefix(i->name); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; } -static char *specifier_instance(char specifier, void *data, void *userdata) { +static int specifier_instance(char specifier, void *data, void *userdata, char **ret) { InstallInfo *i = userdata; char *instance; int r; @@ -50,14 +64,19 @@ static char *specifier_instance(char specifier, void *data, void *userdata) { r = unit_name_to_instance(i->name, &instance); if (r < 0) - return NULL; - if (instance != NULL) - return instance; - else - return strdup(""); + return r; + + if (!instance) { + instance = strdup(""); + if (!instance) + return -ENOMEM; + } + + *ret = instance; + return 0; } -static char *specifier_user_name(char specifier, void *data, void *userdata) { +static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) { InstallInfo *i = userdata; const char *username; _cleanup_free_ char *tmp = NULL; @@ -82,18 +101,20 @@ static char *specifier_user_name(char specifier, void *data, void *userdata) { r = get_user_creds(&username, &uid, NULL, NULL, NULL); if (r < 0) - return NULL; + return r; if (asprintf(&printed, "%d", uid) < 0) - return NULL; + return -ENOMEM; break; }} - return printed; + + *ret = printed; + return 0; } -char *install_full_printf(InstallInfo *i, const char *format) { +int install_full_printf(InstallInfo *i, const char *format, char **ret) { /* This is similar to unit_full_printf() but does not support * anything path-related. @@ -129,6 +150,7 @@ char *install_full_printf(InstallInfo *i, const char *format) { assert(i); assert(format); + assert(ret); - return specifier_printf(format, table, i); + return specifier_printf(format, table, i, ret); } diff --git a/src/shared/install-printf.h b/src/shared/install-printf.h index 46f5294d21..6ffa488b1b 100644 --- a/src/shared/install-printf.h +++ b/src/shared/install-printf.h @@ -22,4 +22,4 @@ #pragma once #include "install.h" -char *install_full_printf(InstallInfo *i, const char *format); +int install_full_printf(InstallInfo *i, const char *format, char **ret); diff --git a/src/shared/install.c b/src/shared/install.c index 07e06c425f..9722ed4e1c 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -967,14 +967,15 @@ static int config_parse_user(const char *unit, InstallInfo *i = data; char* printed; + int r; assert(filename); assert(lvalue); assert(rvalue); - printed = install_full_printf(i, rvalue); - if (!printed) - return -ENOMEM; + r = install_full_printf(i, rvalue, &printed); + if (r < 0) + return r; free(i->user); i->user = printed; @@ -1200,9 +1201,9 @@ static int install_info_symlink_alias( STRV_FOREACH(s, i->aliases) { _cleanup_free_ char *alias_path = NULL, *dst = NULL; - dst = install_full_printf(i, *s); - if (!dst) - return -ENOMEM; + q = install_full_printf(i, *s, &dst); + if (q < 0) + return q; alias_path = path_make_absolute(dst, config_path); if (!alias_path) @@ -1232,9 +1233,9 @@ static int install_info_symlink_wants( STRV_FOREACH(s, i->wanted_by) { _cleanup_free_ char *path = NULL, *dst = NULL; - dst = install_full_printf(i, *s); - if (!dst) - return -ENOMEM; + q = install_full_printf(i, *s, &dst); + if (q < 0) + return q; if (!unit_name_is_valid(dst, true)) { r = -EINVAL; @@ -1269,9 +1270,9 @@ static int install_info_symlink_requires( STRV_FOREACH(s, i->required_by) { _cleanup_free_ char *path = NULL, *dst = NULL; - dst = install_full_printf(i, *s); - if (!dst) - return -ENOMEM; + q = install_full_printf(i, *s, &dst); + if (q < 0) + return q; if (!unit_name_is_valid(dst, true)) { r = -EINVAL; diff --git a/src/shared/specifier.c b/src/shared/specifier.c index bb8859fdfd..8fbf6db5df 100644 --- a/src/shared/specifier.c +++ b/src/shared/specifier.c @@ -32,21 +32,22 @@ * */ -char *specifier_printf(const char *text, const Specifier table[], void *userdata) { - char *r, *t; +int specifier_printf(const char *text, const Specifier table[], void *userdata, char **_ret) { + char *ret, *t; const char *f; bool percent = false; size_t l; + int r; assert(text); assert(table); l = strlen(text); - r = new(char, l+1); - if (!r) - return NULL; + ret = new(char, l+1); + if (!ret) + return -ENOMEM; - t = r; + t = ret; for (f = text; *f; f++, l--) { @@ -61,32 +62,31 @@ char *specifier_printf(const char *text, const Specifier table[], void *userdata break; if (i->lookup) { - char *n, *w; + _cleanup_free_ char *w = NULL; + char *n; size_t k, j; - w = i->lookup(i->specifier, i->data, userdata); - if (!w) { - free(r); - return NULL; + r = i->lookup(i->specifier, i->data, userdata, &w); + if (r < 0) { + free(ret); + return r; } - j = t - r; + j = t - ret; k = strlen(w); n = new(char, j + k + l + 1); if (!n) { - free(r); - free(w); - return NULL; + free(ret); + return -ENOMEM; } - memcpy(n, r, j); + memcpy(n, ret, j); memcpy(n + j, w, k); - free(r); - free(w); + free(ret); - r = n; + ret = n; t = n + j + k; } else { *(t++) = '%'; @@ -102,58 +102,81 @@ char *specifier_printf(const char *text, const Specifier table[], void *userdata } *t = 0; - return r; + *_ret = ret; + return 0; } /* Generic handler for simple string replacements */ -char* specifier_string(char specifier, void *data, void *userdata) { - return strdup(strempty(data)); +int specifier_string(char specifier, void *data, void *userdata, char **ret) { + char *n; + + n = strdup(strempty(data)); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; } -char *specifier_machine_id(char specifier, void *data, void *userdata) { +int specifier_machine_id(char specifier, void *data, void *userdata, char **ret) { sd_id128_t id; - char *buf; + char *n; int r; r = sd_id128_get_machine(&id); if (r < 0) - return NULL; + return r; - buf = new(char, 33); - if (!buf) - return NULL; + n = new(char, 33); + if (!n) + return -ENOMEM; - return sd_id128_to_string(id, buf); + *ret = sd_id128_to_string(id, n); + return 0; } -char *specifier_boot_id(char specifier, void *data, void *userdata) { +int specifier_boot_id(char specifier, void *data, void *userdata, char **ret) { sd_id128_t id; - char *buf; + char *n; int r; r = sd_id128_get_boot(&id); if (r < 0) - return NULL; + return r; - buf = new(char, 33); - if (!buf) - return NULL; + n = new(char, 33); + if (!n) + return -ENOMEM; - return sd_id128_to_string(id, buf); + *ret = sd_id128_to_string(id, n); + return 0; } -char *specifier_host_name(char specifier, void *data, void *userdata) { - return gethostname_malloc(); +int specifier_host_name(char specifier, void *data, void *userdata, char **ret) { + char *n; + + n = gethostname_malloc(); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; } -char *specifier_kernel_release(char specifier, void *data, void *userdata) { +int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret) { struct utsname uts; + char *n; int r; r = uname(&uts); if (r < 0) - return NULL; + return -errno; + + n = strdup(uts.release); + if (!n) + return -ENOMEM; - return strdup(uts.release); + *ret = n; + return 0; } diff --git a/src/shared/specifier.h b/src/shared/specifier.h index d13e6406b6..fca206f665 100644 --- a/src/shared/specifier.h +++ b/src/shared/specifier.h @@ -21,7 +21,7 @@ along with systemd; If not, see . ***/ -typedef char* (*SpecifierCallback)(char specifier, void *data, void *userdata); +typedef int (*SpecifierCallback)(char specifier, void *data, void *userdata, char **ret); typedef struct Specifier { const char specifier; @@ -29,11 +29,11 @@ typedef struct Specifier { void *data; } Specifier; -char *specifier_printf(const char *text, const Specifier table[], void *userdata); +int specifier_printf(const char *text, const Specifier table[], void *userdata, char **ret); -char *specifier_string(char specifier, void *data, void *userdata); +int specifier_string(char specifier, void *data, void *userdata, char **ret); -char *specifier_machine_id(char specifier, void *data, void *userdata); -char *specifier_boot_id(char specifier, void *data, void *userdata); -char *specifier_host_name(char specifier, void *data, void *userdata); -char *specifier_kernel_release(char specifier, void *data, void *userdata); +int specifier_machine_id(char specifier, void *data, void *userdata, char **ret); +int specifier_boot_id(char specifier, void *data, void *userdata, char **ret); +int specifier_host_name(char specifier, void *data, void *userdata, char **ret); +int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret); -- cgit v1.2.3-54-g00ecf