#include "virt.h"
static int parse_chid_type(const char *s, size_t *ret) {
- char *e;
+ const char *e;
unsigned u;
int r;
}
static char *mangle_word(const char *word, ProcCmdlineFlags flags) {
- char *c;
-
- c = startswith(word, "rd.");
+ char *c = (char*) startswith(word, "rd.");
if (c) {
/* Filter out arguments that are intended only for the initrd */
return (char*) word;
}
+#define mangle_word(word, flags) const_generic(word, mangle_word(word, flags))
+
static int proc_cmdline_parse_strv(char **args, proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags) {
int r;
int socket_address_parse_vsock(SocketAddress *ret_address, const char *s) {
/* AF_VSOCK socket in vsock:cid:port notation */
_cleanup_free_ char *n = NULL;
- char *e, *cid_start;
+ const char *e, *cid_start;
unsigned port, cid;
int type, r;
return NULL;
}
-void* bsearch_safe(const void *key, const void *base, size_t nmemb, size_t size, comparison_fn_t compar) {
+void* bsearch_safe_internal(const void *key, const void *base, size_t nmemb, size_t size, comparison_fn_t compar) {
/**
* Normal bsearch requires base to be nonnull. Here were require
* that only if nmemb > 0.
return NULL;
assert(base);
- return bsearch(key, base, nmemb, size, compar);
+ return (void*) bsearch(key, base, nmemb, size, compar);
}
void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) {
(typeof((b)[0])*) xbsearch_r((const void*) _k, (b), (n), sizeof((b)[0]), (comparison_userdata_fn_t) _func_, userdata); \
})
-void* bsearch_safe(const void *key, const void *base, size_t nmemb, size_t size, comparison_fn_t compar);
+void* bsearch_safe_internal(const void *key, const void *base, size_t nmemb, size_t size, comparison_fn_t compar);
+#define bsearch_safe(key, base, nmemb, size, compar) \
+ const_generic((base), bsearch_safe_internal(key, base, nmemb, size, compar))
#define typesafe_bsearch(k, b, n, func) \
({ \
return strndup(a, strcspn(a, reject));
}
-char* find_line_startswith(const char *haystack, const char *needle) {
- char *p;
-
+char* find_line_startswith_internal(const char *haystack, const char *needle) {
assert(haystack);
assert(needle);
/* Finds the first line in 'haystack' that starts with the specified string. Returns a pointer to the
* first character after it */
- p = strstr(haystack, needle);
+ char *p = (char*) strstr(haystack, needle);
if (!p)
return NULL;
return p + strlen(needle);
}
-char* find_line(const char *haystack, const char *needle) {
- char *p;
-
+char* find_line_internal(const char *haystack, const char *needle) {
assert(haystack);
assert(needle);
/* Finds the first line in 'haystack' that match the specified string. Returns a pointer to the
* beginning of the line */
- p = find_line_startswith(haystack, needle);
+ char *p = (char*) find_line_startswith(haystack, needle);
if (!p)
return NULL;
return NULL;
}
-char* find_line_after(const char *haystack, const char *needle) {
- char *p;
-
+char* find_line_after_internal(const char *haystack, const char *needle) {
assert(haystack);
assert(needle);
/* Finds the first line in 'haystack' that match the specified string. Returns a pointer to the
* next line after it */
- p = find_line_startswith(haystack, needle);
+ char *p = (char*) find_line_startswith(haystack, needle);
if (!p)
return NULL;
return t1[yl];
}
-char* strrstr(const char *haystack, const char *needle) {
+char* strrstr_internal(const char *haystack, const char *needle) {
/* Like strstr() but returns the last rather than the first occurrence of "needle" in "haystack". */
if (!haystack || !needle)
/* Special case: for the empty string we return the very last possible occurrence, i.e. *after* the
* last char, not before. */
if (*needle == 0)
- return strchr(haystack, 0);
+ return (char*) strchr(haystack, 0);
for (const char *p = strstr(haystack, needle), *q; p; p = q) {
q = strstr(p + 1, needle);
#include "basic-forward.h"
#include "string-util-fundamental.h" /* IWYU pragma: export */
-static inline char* strstr_ptr(const char *haystack, const char *needle) {
+static inline char* strstr_ptr_internal(const char *haystack, const char *needle) {
if (!haystack || !needle)
return NULL;
- return strstr(haystack, needle);
+ return (char*) strstr(haystack, needle);
}
-static inline char* strstrafter(const char *haystack, const char *needle) {
- char *p;
+#define strstr_ptr(haystack, needle) \
+ const_generic(haystack, strstr_ptr_internal(haystack, needle))
+static inline char* strstrafter_internal(const char *haystack, const char *needle) {
/* Returns NULL if not found, or pointer to first character after needle if found */
- p = strstr_ptr(haystack, needle);
+ char *p = (char*) strstr_ptr(haystack, needle);
if (!p)
return NULL;
return p + strlen(needle);
}
+#define strstrafter(haystack, needle) \
+ const_generic(haystack, strstrafter_internal(haystack, needle))
+
static inline const char* strnull(const char *s) {
return s ?: "(null)";
}
(char*) memdupa_suffix0(_t, strnlen(_t, n)); \
})
-char* find_line_startswith(const char *haystack, const char *needle);
-char* find_line(const char *haystack, const char *needle);
-char* find_line_after(const char *haystack, const char *needle);
+char* find_line_startswith_internal(const char *haystack, const char *needle);
+#define find_line_startswith(haystack, needle) \
+ const_generic(haystack, find_line_startswith_internal(haystack, needle))
+
+char* find_line_internal(const char *haystack, const char *needle);
+#define find_line(haystack, needle) \
+ const_generic(haystack, find_line_internal(haystack, needle))
+
+char* find_line_after_internal(const char *haystack, const char *needle);
+#define find_line_after(haystack, needle) \
+ const_generic(haystack, find_line_after_internal(haystack, needle))
bool version_is_valid(const char *s) _pure_;
bool version_is_valid_versionspec(const char *s) _pure_;
ssize_t strlevenshtein(const char *x, const char *y);
-char* strrstr(const char *haystack, const char *needle) _pure_;
+char* strrstr_internal(const char *haystack, const char *needle) _pure_;
+#define strrstr(haystack, needle) \
+ const_generic(haystack, strrstr_internal(haystack, needle))
size_t str_common_prefix(const char *a, const char *b) _pure_;
return strv_consume_with_size(l, n, x);
}
-char* startswith_strv(const char *s, char * const *l) {
+char* startswith_strv_internal(const char *s, char * const *l) {
STRV_FOREACH(i, l) {
- char *found = startswith(s, *i);
+ char *found = (char*) startswith(s, *i);
if (found)
return found;
}
return NULL;
}
-char* endswith_strv(const char *s, char * const *l) {
+char* endswith_strv_internal(const char *s, char * const *l) {
STRV_FOREACH(i, l) {
- char *found = endswith(s, *i);
+ char *found = (char*) endswith(s, *i);
if (found)
return found;
}
strv_print_full(l, NULL);
}
-char* startswith_strv(const char *s, char * const *l);
+char* startswith_strv_internal(const char *s, char * const *l);
+#define startswith_strv(s, l) const_generic(s, startswith_strv_internal(s, l))
#define STARTSWITH_SET(p, ...) \
startswith_strv(p, STRV_MAKE(__VA_ARGS__))
-char* endswith_strv(const char *s, char * const *l);
+char* endswith_strv_internal(const char *s, char * const *l);
+#define endswith_strv(s, l) const_generic(s, endswith_strv_internal(s, l))
#define ENDSWITH_SET(p, ...) \
endswith_strv(p, STRV_MAKE(__VA_ARGS__))
assert(ret);
FOREACH_ELEMENT(i, table) {
- char *e;
-
- e = startswith(p, i->suffix);
+ const char *e = startswith(p, i->suffix);
if (e) {
*ret = i->usec;
return e;
assert(ret);
FOREACH_ELEMENT(i, table) {
- char *e;
-
- e = startswith(p, i->suffix);
+ const char *e = startswith(p, i->suffix);
if (e) {
*ret = i->nsec;
return e;
int unit_name_change_suffix(const char *n, const char *suffix, char **ret) {
_cleanup_free_ char *s = NULL;
size_t a, b;
- char *e;
+ const char *e;
assert(n);
assert(suffix);
}
bool unit_name_is_hashed(const char *name) {
- char *s;
+ const char *s;
if (!unit_name_is_valid(name, UNIT_NAME_PLAIN))
return false;
int unit_name_hash_long(const char *name, char **ret) {
_cleanup_free_ char *n = NULL, *hash = NULL;
- char *suffix;
+ const char *suffix;
le64_t h;
size_t len;
if (streq(slice, SPECIAL_ROOT_SLICE))
subslice = strjoin(name, ".slice");
else {
- char *e;
+ const char *e;
assert_se(e = endswith(slice, ".slice"));
static int add_crypttab_device(const char *name, const char *device, const char *keyspec, const char *options) {
_cleanup_free_ char *keyfile = NULL, *keydev = NULL, *headerdev = NULL, *filtered_header = NULL;
crypto_device *d = NULL;
- char *uuid;
int r;
- uuid = startswith(device, "UUID=");
+ const char *uuid = startswith(device, "UUID=");
if (!uuid)
uuid = path_startswith(device, "/dev/disk/by-uuid/");
if (!uuid)
#else
# define ENUM_TYPE_S64(id) id
#endif
+
+/* This macro is used to have a const-returning and non-const returning version of a function based on
+ * whether its first argument is const or not (e.g. strstr()). */
+#define const_generic(ptr, call) \
+ _Generic(0 ? (ptr) : (void*) 1, \
+ const void*: (const typeof(*call)*) (call), \
+ void*: (call))
#include "macro-fundamental.h"
#include "string-util-fundamental.h"
-sd_char *startswith(const sd_char *s, const sd_char *prefix) {
+sd_char *startswith_internal(const sd_char *s, const sd_char *prefix) {
size_t l;
assert(s);
return (sd_char*) s + l;
}
-sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) {
+sd_char *startswith_no_case_internal(const sd_char *s, const sd_char *prefix) {
size_t l;
assert(s);
return (sd_char*) s + l;
}
-sd_char* endswith(const sd_char *s, const sd_char *suffix) {
+sd_char* endswith_internal(const sd_char *s, const sd_char *suffix) {
size_t sl, pl;
assert(s);
return (sd_char*) s + sl - pl;
}
-sd_char* endswith_no_case(const sd_char *s, const sd_char *suffix) {
+sd_char* endswith_no_case_internal(const sd_char *s, const sd_char *suffix) {
size_t sl, pl;
assert(s);
return strlen(s);
}
-sd_char *startswith(const sd_char *s, const sd_char *prefix) _pure_;
-sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) _pure_;
-sd_char *endswith(const sd_char *s, const sd_char *suffix) _pure_;
-sd_char *endswith_no_case(const sd_char *s, const sd_char *suffix) _pure_;
+sd_char *startswith_internal(const sd_char *s, const sd_char *prefix) _pure_;
+#define startswith(s, prefix) const_generic(s, startswith_internal(s, prefix))
+
+sd_char *startswith_no_case_internal(const sd_char *s, const sd_char *prefix) _pure_;
+#define startswith_no_case(s, prefix) const_generic(s, startswith_no_case_internal(s, prefix))
+
+sd_char *endswith_internal(const sd_char *s, const sd_char *suffix) _pure_;
+#define endswith(s, suffix) const_generic(s, endswith_internal(s, suffix))
+
+sd_char *endswith_no_case_internal(const sd_char *s, const sd_char *suffix) _pure_;
+#define endswith_no_case(s, suffix) const_generic(s, endswith_no_case_internal(s, suffix))
static inline bool isempty(const sd_char *a) {
return !a || a[0] == '\0';
const char *dir_path,
const char *dentry_name) {
- char *luks_suffix, *directory_suffix;
+ const char *luks_suffix, *directory_suffix;
_cleanup_free_ char *path = NULL;
struct stat st;
int r;
SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
_cleanup_free_ char *u = NULL;
- char *eq;
- eq = memchr(data, '=', size);
+ const char *eq = memchr(data, '=', size);
if (eq) {
size -= eq - (char*) data + 1;
data = ++eq;
int bus_set_address_system_remote(sd_bus *b, const char *host) {
_cleanup_free_ char *e = NULL;
- char *m = NULL, *c = NULL, *a, *rbracket = NULL, *p = NULL;
+ const char *m = NULL, *c = NULL, *a, *rbracket = NULL, *p = NULL;
assert(b);
assert(host);
/* Let's see if a port was given */
m = strchr(rbracket ? rbracket + 1 : host, ':');
if (m) {
- char *t;
+ const char *t;
bool got_forward_slash = false;
p = m + 1;
if (!ssh_escaped)
return -ENOMEM;
- a = strjoin("unixexec:path=", ssh_escaped, ",argv1=-xT",
- p ? ",argv2=-p,argv3=" : "", strempty(p),
- ",argv", p ? "4" : "2", "=--,argv", p ? "5" : "3", "=", e,
- ",argv", p ? "6" : "4", "=systemd-stdio-bridge", c);
- if (!a)
+ char *address = strjoin(
+ "unixexec:path=", ssh_escaped, ",argv1=-xT",
+ p ? ",argv2=-p,argv3=" : "", strempty(p),
+ ",argv", p ? "4" : "2", "=--,argv", p ? "5" : "3", "=", e,
+ ",argv", p ? "6" : "4", "=systemd-stdio-bridge", c);
+ if (!address)
return -ENOMEM;
- return free_and_replace(b->address, a);
+ return free_and_replace(b->address, address);
}
_public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) {
}
static const struct trie_node_f *node_lookup_f(sd_hwdb *hwdb, const struct trie_node_f *node, uint8_t c) {
- struct trie_child_entry_f *child;
+ const struct trie_child_entry_f *child;
struct trie_child_entry_f search;
search.c = c;
}
int catalog_file_lang(const char *filename, char **ret) {
- char *beg, *end, *lang;
-
assert(filename);
assert(ret);
- end = endswith(filename, ".catalog");
+ const char *end = endswith(filename, ".catalog");
if (!end)
return 0;
- beg = end - 1;
+ const char *beg = end - 1;
while (beg > filename && !IN_SET(*beg, '.', '/') && end - beg < 32)
beg--;
if (*beg != '.' || end <= beg + 1)
return 0;
- lang = strndup(beg + 1, end - beg - 1);
+ char *lang = strndup(beg + 1, end - beg - 1);
if (!lang)
return -ENOMEM;
}
static const char* find_id(const void *p, sd_id128_t id) {
- CatalogItem *f = NULL, key = { .id = id };
+ CatalogItem key = { .id = id };
+ const CatalogItem *f = NULL;
const CatalogHeader *h = ASSERT_PTR(p);
const char *loc;
void *userdata) {
char **suboption_value = data;
- char* p;
assert(filename);
assert(lvalue);
return 0;
}
- p = startswith(rvalue, "string:");
+ const char *p = startswith(rvalue, "string:");
if (!p) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Failed to parse %s=%s'. Invalid format, ignoring.", lvalue, rvalue);
}
static int bus_append_root_hash_signature(sd_bus_message *m, const char *field, const char *eq) {
- char *value;
_cleanup_free_ void *roothash_sig_decoded = NULL;
size_t roothash_sig_decoded_size = 0;
int r;
if (path_is_absolute(eq))
return bus_append_string(m, "RootHashSignaturePath", eq);
- if (!(value = startswith(eq, "base64:")))
+ const char *value = startswith(eq, "base64:");
+ if (!value)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Failed to decode %s value '%s': neither a path nor starts with 'base64:'.",
field, eq);
int show_man_page(const char *desc, bool null_stdio) {
const char *args[4] = { "man", NULL, NULL, NULL };
- char *e = NULL;
+ const char *e = NULL;
pid_t pid;
size_t k;
int r;
int parse_syscall_and_errno(const char *in, char **name, int *error) {
_cleanup_free_ char *n = NULL;
- char *p;
+ const char *p;
int e = -1;
assert(in);
unsigned found_tries_done = UINT_MAX, found_tries_left = UINT_MAX;
_cleanup_free_ char *dname = NULL;
size_t found_architecture_index = SIZE_MAX;
- const char *e;
+ char *e;
dname = strdup((*entry)->d_name);
if (!dname)
}
static int get_usb_specifier(sd_device *dev, char **ret) {
- char *ports, *config, *interf, *s, *buf;
+ char *ports, *config, *interf, *buf;
const char *sysname;
int r;
return log_device_debug_errno(dev, r, "Failed to get sysname: %m");
/* get USB port number chain, configuration, interface */
- s = strchr(sysname, '-');
+ const char *s = strchr(sysname, '-');
if (!s)
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"sysname \"%s\" does not have '-' in the expected place.", sysname);
ports = strdupa_safe(s + 1);
- s = strchr(ports, ':');
+ char *t = strchr(ports, ':');
if (!s)
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"sysname \"%s\" does not have ':' in the expected place.", sysname);
- *s = '\0';
- config = s + 1;
+ *t = '\0';
+ config = t + 1;
s = strchr(config, '.');
if (!s)
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"sysname \"%s\" does not have '.' in the expected place.", sysname);
- *s = '\0';
- interf = s + 1;
+ *t = '\0';
+ interf = t + 1;
/* prefix every port number in the chain with "u" */
string_replace_char(ports, '.', 'u');