diff options
author | Michal Schmidt <mschmidt@redhat.com> | 2012-10-30 14:29:38 +0100 |
---|---|---|
committer | Michal Schmidt <mschmidt@redhat.com> | 2012-10-30 15:41:15 +0100 |
commit | f8b69d1dfc307562a353f6aa923b7c2b915aaddb (patch) | |
tree | 79a9776e85e7f9ad9ca944665cc428be480789f3 /src/shared/util.h | |
parent | 26acfdae44e3605788420432d28a7264214d1213 (diff) |
shared, core: do not always accept numbers in string lookups
The behaviour of the common name##_from_string conversion is surprising.
It accepts not only the strings from name##_table but also any number
that falls within the range of the table. The order of items in most of
our tables is an internal affair. It should not be visible to the user.
I know of a case where the surprising numeric conversion leads to a crash.
We will allow the direct numeric conversion only for the tables where the
mapping of strings to numeric values has an external meaning. This holds
for the following lookup tables:
- netlink_family, ioprio_class, ip_tos, sched_policy - their numeric
values are stable as they are defined by the Linux kernel interface.
- log_level, log_facility_unshifted - the well-known syslog interface.
We allow the user to use numeric values whose string names systemd does
not know. For instance, the user may want to test a new kernel featuring
a scheduling policy that did not exist when his systemd version was
released. A slightly unpleasant effect of this is that the
name##_to_string conversion cannot return pointers to constant strings
anymore. The strings have to be allocated on demand and freed by the
caller.
Diffstat (limited to 'src/shared/util.h')
-rw-r--r-- | src/shared/util.h | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/src/shared/util.h b/src/shared/util.h index f726263dd3..ca80bfe2e8 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -291,6 +291,7 @@ int make_console_stdio(void); unsigned long long random_ull(void); +/* For basic lookup tables with strictly enumerated entries */ #define __DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ scope const char *name##_to_string(type i) { \ if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \ @@ -299,15 +300,11 @@ unsigned long long random_ull(void); } \ scope type name##_from_string(const char *s) { \ type i; \ - unsigned u = 0; \ assert(s); \ for (i = 0; i < (type)ELEMENTSOF(name##_table); i++) \ if (name##_table[i] && \ streq(name##_table[i], s)) \ return i; \ - if (safe_atou(s, &u) >= 0 && \ - u < ELEMENTSOF(name##_table)) \ - return (type) u; \ return (type) -1; \ } \ struct __useless_struct_to_allow_trailing_semicolon__ @@ -315,6 +312,39 @@ unsigned long long random_ull(void); #define DEFINE_STRING_TABLE_LOOKUP(name,type) __DEFINE_STRING_TABLE_LOOKUP(name,type,) #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) __DEFINE_STRING_TABLE_LOOKUP(name,type,static) +/* For string conversions where numbers are also acceptable */ +#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \ + int name##_to_string_alloc(type i, char **str) { \ + char *s; \ + int r; \ + if (i < 0 || i > max) \ + return -ERANGE; \ + if (i < (type) ELEMENTSOF(name##_table)) { \ + s = strdup(name##_table[i]); \ + if (!s) \ + return log_oom(); \ + } else { \ + r = asprintf(&s, "%u", i); \ + if (r < 0) \ + return log_oom(); \ + } \ + *str = s; \ + return 0; \ + } \ + type name##_from_string(const char *s) { \ + type i; \ + unsigned u = 0; \ + assert(s); \ + for (i = 0; i < (type)ELEMENTSOF(name##_table); i++) \ + if (name##_table[i] && \ + streq(name##_table[i], s)) \ + return i; \ + if (safe_atou(s, &u) >= 0 && u < max) \ + return (type) u; \ + return (type) -1; \ + } \ + struct __useless_struct_to_allow_trailing_semicolon__ + int fd_nonblock(int fd, bool nonblock); int fd_cloexec(int fd, bool cloexec); @@ -478,25 +508,25 @@ int strdup_or_null(const char *a, char **b); #define NULSTR_FOREACH_PAIR(i, j, l) \ for ((i) = (l), (j) = strchr((i), 0)+1; (i) && *(i); (i) = strchr((j), 0)+1, (j) = *(i) ? strchr((i), 0)+1 : (i)) -const char *ioprio_class_to_string(int i); +int ioprio_class_to_string_alloc(int i, char **s); int ioprio_class_from_string(const char *s); const char *sigchld_code_to_string(int i); int sigchld_code_from_string(const char *s); -const char *log_facility_unshifted_to_string(int i); +int log_facility_unshifted_to_string_alloc(int i, char **s); int log_facility_unshifted_from_string(const char *s); -const char *log_level_to_string(int i); +int log_level_to_string_alloc(int i, char **s); int log_level_from_string(const char *s); -const char *sched_policy_to_string(int i); +int sched_policy_to_string_alloc(int i, char **s); int sched_policy_from_string(const char *s); const char *rlimit_to_string(int i); int rlimit_from_string(const char *s); -const char *ip_tos_to_string(int i); +int ip_tos_to_string_alloc(int i, char **s); int ip_tos_from_string(const char *s); const char *signal_to_string(int i); |