From 07630cea1f3a845c09309f197ac7c4f11edd3b62 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 24 Oct 2015 22:58:24 +0200 Subject: util-lib: split our string related calls from util.[ch] into its own file string-util.[ch] There are more than enough calls doing string manipulations to deserve its own files, hence do something about it. This patch also sorts the #include blocks of all files that needed to be updated, according to the sorting suggestions from CODING_STYLE. Since pretty much every file needs our string manipulation functions this effectively means that most files have sorted #include blocks now. Also touches a few unrelated include files. --- src/basic/util.c | 744 +------------------------------------------------------ 1 file changed, 1 insertion(+), 743 deletions(-) (limited to 'src/basic/util.c') diff --git a/src/basic/util.c b/src/basic/util.c index d6488f8fd6..233a6c2e35 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -94,6 +94,7 @@ #include "random-util.h" #include "signal-util.h" #include "sparse-endian.h" +#include "string-util.h" #include "strv.h" #include "terminal-util.h" #include "utf8.h" @@ -120,101 +121,6 @@ size_t page_size(void) { return pgsz; } -int strcmp_ptr(const char *a, const char *b) { - - /* Like strcmp(), but tries to make sense of NULL pointers */ - if (a && b) - return strcmp(a, b); - - if (!a && b) - return -1; - - if (a && !b) - return 1; - - return 0; -} - -bool streq_ptr(const char *a, const char *b) { - return strcmp_ptr(a, b) == 0; -} - -char* endswith(const char *s, const char *postfix) { - size_t sl, pl; - - assert(s); - assert(postfix); - - sl = strlen(s); - pl = strlen(postfix); - - if (pl == 0) - return (char*) s + sl; - - if (sl < pl) - return NULL; - - if (memcmp(s + sl - pl, postfix, pl) != 0) - return NULL; - - return (char*) s + sl - pl; -} - -char* endswith_no_case(const char *s, const char *postfix) { - size_t sl, pl; - - assert(s); - assert(postfix); - - sl = strlen(s); - pl = strlen(postfix); - - if (pl == 0) - return (char*) s + sl; - - if (sl < pl) - return NULL; - - if (strcasecmp(s + sl - pl, postfix) != 0) - return NULL; - - return (char*) s + sl - pl; -} - -char* first_word(const char *s, const char *word) { - size_t sl, wl; - const char *p; - - assert(s); - assert(word); - - /* Checks if the string starts with the specified word, either - * followed by NUL or by whitespace. Returns a pointer to the - * NUL or the first character after the whitespace. */ - - sl = strlen(s); - wl = strlen(word); - - if (sl < wl) - return NULL; - - if (wl == 0) - return (char*) s; - - if (memcmp(s, word, wl) != 0) - return NULL; - - p = s + wl; - if (*p == 0) - return (char*) p; - - if (!strchr(WHITESPACE, *p)) - return NULL; - - p += strspn(p, WHITESPACE); - return (char*) p; -} - int close_nointr(int fd) { assert(fd >= 0); @@ -553,66 +459,6 @@ int safe_atod(const char *s, double *ret_d) { return 0; } -static size_t strcspn_escaped(const char *s, const char *reject) { - bool escaped = false; - int n; - - for (n=0; s[n]; n++) { - if (escaped) - escaped = false; - else if (s[n] == '\\') - escaped = true; - else if (strchr(reject, s[n])) - break; - } - - /* if s ends in \, return index of previous char */ - return n - escaped; -} - -/* Split a string into words. */ -const char* split(const char **state, size_t *l, const char *separator, bool quoted) { - const char *current; - - current = *state; - - if (!*current) { - assert(**state == '\0'); - return NULL; - } - - current += strspn(current, separator); - if (!*current) { - *state = current; - return NULL; - } - - if (quoted && strchr("\'\"", *current)) { - char quotechars[2] = {*current, '\0'}; - - *l = strcspn_escaped(current + 1, quotechars); - if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] || - (current[*l + 2] && !strchr(separator, current[*l + 2]))) { - /* right quote missing or garbage at the end */ - *state = current; - return NULL; - } - *state = current++ + *l + 2; - } else if (quoted) { - *l = strcspn_escaped(current, separator); - if (current[*l] && !strchr(separator, current[*l])) { - /* unfinished escape */ - *state = current; - return NULL; - } - *state = current + *l; - } else { - *l = strcspn(current, separator); - *state = current + *l; - } - - return current; -} int fchmod_umask(int fd, mode_t m) { mode_t u; @@ -625,48 +471,6 @@ int fchmod_umask(int fd, mode_t m) { return r; } -char *truncate_nl(char *s) { - assert(s); - - s[strcspn(s, NEWLINE)] = 0; - return s; -} - -char *strnappend(const char *s, const char *suffix, size_t b) { - size_t a; - char *r; - - if (!s && !suffix) - return strdup(""); - - if (!s) - return strndup(suffix, b); - - if (!suffix) - return strdup(s); - - assert(s); - assert(suffix); - - a = strlen(s); - if (b > ((size_t) -1) - a) - return NULL; - - r = new(char, a+b+1); - if (!r) - return NULL; - - memcpy(r, s, a); - memcpy(r+a, suffix, b); - r[a+b] = 0; - - return r; -} - -char *strappend(const char *s, const char *suffix) { - return strnappend(s, suffix, suffix ? strlen(suffix) : 0); -} - int readlinkat_malloc(int fd, const char *p, char **ret) { size_t l = 100; int r; @@ -769,40 +573,6 @@ int readlink_and_canonicalize(const char *p, char **r) { return 0; } -char *strstrip(char *s) { - char *e; - - /* Drops trailing whitespace. Modifies the string in - * place. Returns pointer to first non-space character */ - - s += strspn(s, WHITESPACE); - - for (e = strchr(s, 0); e > s; e --) - if (!strchr(WHITESPACE, e[-1])) - break; - - *e = 0; - - return s; -} - -char *delete_chars(char *s, const char *bad) { - char *f, *t; - - /* Drops all whitespace, regardless where in the string */ - - for (f = s, t = s; *f; f++) { - if (strchr(bad, *f)) - continue; - - *(t++) = *f; - } - - *t = 0; - - return s; -} - char *file_in_same_dir(const char *path, const char *filename) { char *e, *ret; size_t k; @@ -1504,18 +1274,6 @@ int undecchar(char c) { return -EINVAL; } -char *ascii_strlower(char *t) { - char *p; - - assert(t); - - for (p = t; *p; p++) - if (*p >= 'A' && *p <= 'Z') - *p = *p - 'A' + 'a'; - - return t; -} - _pure_ static bool hidden_file_allow_backup(const char *filename) { assert(filename); @@ -1663,17 +1421,6 @@ int close_all_fds(const int except[], unsigned n_except) { return r; } -bool chars_intersect(const char *a, const char *b) { - const char *p; - - /* Returns true if any of the chars in a are in b. */ - for (p = a; *p; p++) - if (strchr(b, *p)) - return true; - - return false; -} - bool fstype_is_network(const char *fstype) { static const char table[] = "afs\0" @@ -2196,115 +1943,6 @@ int running_in_chroot(void) { return ret == 0; } -static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) { - size_t x; - char *r; - - assert(s); - assert(percent <= 100); - assert(new_length >= 3); - - if (old_length <= 3 || old_length <= new_length) - return strndup(s, old_length); - - r = new0(char, new_length+1); - if (!r) - return NULL; - - x = (new_length * percent) / 100; - - if (x > new_length - 3) - x = new_length - 3; - - memcpy(r, s, x); - r[x] = '.'; - r[x+1] = '.'; - r[x+2] = '.'; - memcpy(r + x + 3, - s + old_length - (new_length - x - 3), - new_length - x - 3); - - return r; -} - -char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) { - size_t x; - char *e; - const char *i, *j; - unsigned k, len, len2; - - assert(s); - assert(percent <= 100); - assert(new_length >= 3); - - /* if no multibyte characters use ascii_ellipsize_mem for speed */ - if (ascii_is_valid(s)) - return ascii_ellipsize_mem(s, old_length, new_length, percent); - - if (old_length <= 3 || old_length <= new_length) - return strndup(s, old_length); - - x = (new_length * percent) / 100; - - if (x > new_length - 3) - x = new_length - 3; - - k = 0; - for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) { - int c; - - c = utf8_encoded_to_unichar(i); - if (c < 0) - return NULL; - k += unichar_iswide(c) ? 2 : 1; - } - - if (k > x) /* last character was wide and went over quota */ - x ++; - - for (j = s + old_length; k < new_length && j > i; ) { - int c; - - j = utf8_prev_char(j); - c = utf8_encoded_to_unichar(j); - if (c < 0) - return NULL; - k += unichar_iswide(c) ? 2 : 1; - } - assert(i <= j); - - /* we don't actually need to ellipsize */ - if (i == j) - return memdup(s, old_length + 1); - - /* make space for ellipsis */ - j = utf8_next_char(j); - - len = i - s; - len2 = s + old_length - j; - e = new(char, len + 3 + len2 + 1); - if (!e) - return NULL; - - /* - printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n", - old_length, new_length, x, len, len2, k); - */ - - memcpy(e, s, len); - e[len] = 0xe2; /* tri-dot ellipsis: … */ - e[len + 1] = 0x80; - e[len + 2] = 0xa6; - - memcpy(e + len + 3, j, len2 + 1); - - return e; -} - -char *ellipsize(const char *s, size_t length, unsigned percent) { - return ellipsize_mem(s, strlen(s), length, percent); -} - int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) { _cleanup_close_ int fd; int r; @@ -2637,32 +2275,10 @@ void execute_directories(const char* const* directories, usec_t timeout, char *a wait_for_terminate_and_warn(name, executor_pid, true); } -bool nulstr_contains(const char*nulstr, const char *needle) { - const char *i; - - if (!nulstr) - return false; - - NULSTR_FOREACH(i, nulstr) - if (streq(i, needle)) - return true; - - return false; -} - bool plymouth_running(void) { return access("/run/plymouth/pid", F_OK) >= 0; } -char* strshorten(char *s, size_t l) { - assert(s); - - if (l < strlen(s)) - s[l] = 0; - - return s; -} - int pipe_eof(int fd) { struct pollfd pollfd = { .fd = fd, @@ -3150,63 +2766,6 @@ int get_files_in_directory(const char *path, char ***list) { return n; } -char *strjoin(const char *x, ...) { - va_list ap; - size_t l; - char *r, *p; - - va_start(ap, x); - - if (x) { - l = strlen(x); - - for (;;) { - const char *t; - size_t n; - - t = va_arg(ap, const char *); - if (!t) - break; - - n = strlen(t); - if (n > ((size_t) -1) - l) { - va_end(ap); - return NULL; - } - - l += n; - } - } else - l = 0; - - va_end(ap); - - r = new(char, l+1); - if (!r) - return NULL; - - if (x) { - p = stpcpy(r, x); - - va_start(ap, x); - - for (;;) { - const char *t; - - t = va_arg(ap, const char *); - if (!t) - break; - - p = stpcpy(p, t); - } - - va_end(ap); - } else - r[0] = 0; - - return r; -} - bool is_main_thread(void) { static thread_local int cached = 0; @@ -3832,29 +3391,6 @@ bool string_is_safe(const char *p) { return true; } -/** - * Check if a string contains control characters. If 'ok' is non-NULL - * it may be a string containing additional CCs to be considered OK. - */ -bool string_has_cc(const char *p, const char *ok) { - const char *t; - - assert(p); - - for (t = p; *t; t++) { - if (ok && strchr(ok, *t)) - continue; - - if (*t > 0 && *t < ' ') - return true; - - if (*t == 127) - return true; - } - - return false; -} - bool path_is_safe(const char *p) { if (isempty(p)) @@ -3976,139 +3512,6 @@ const char *draw_special_char(DrawSpecialChar ch) { return draw_table[!is_locale_utf8()][ch]; } -char *strreplace(const char *text, const char *old_string, const char *new_string) { - const char *f; - char *t, *r; - size_t l, old_len, new_len; - - assert(text); - assert(old_string); - assert(new_string); - - old_len = strlen(old_string); - new_len = strlen(new_string); - - l = strlen(text); - r = new(char, l+1); - if (!r) - return NULL; - - f = text; - t = r; - while (*f) { - char *a; - size_t d, nl; - - if (!startswith(f, old_string)) { - *(t++) = *(f++); - continue; - } - - d = t - r; - nl = l - old_len + new_len; - a = realloc(r, nl + 1); - if (!a) - goto oom; - - l = nl; - r = a; - t = r + d; - - t = stpcpy(t, new_string); - f += old_len; - } - - *t = 0; - return r; - -oom: - free(r); - return NULL; -} - -char *strip_tab_ansi(char **ibuf, size_t *_isz) { - const char *i, *begin = NULL; - enum { - STATE_OTHER, - STATE_ESCAPE, - STATE_BRACKET - } state = STATE_OTHER; - char *obuf = NULL; - size_t osz = 0, isz; - FILE *f; - - assert(ibuf); - assert(*ibuf); - - /* Strips ANSI color and replaces TABs by 8 spaces */ - - isz = _isz ? *_isz : strlen(*ibuf); - - f = open_memstream(&obuf, &osz); - if (!f) - return NULL; - - for (i = *ibuf; i < *ibuf + isz + 1; i++) { - - switch (state) { - - case STATE_OTHER: - if (i >= *ibuf + isz) /* EOT */ - break; - else if (*i == '\x1B') - state = STATE_ESCAPE; - else if (*i == '\t') - fputs(" ", f); - else - fputc(*i, f); - break; - - case STATE_ESCAPE: - if (i >= *ibuf + isz) { /* EOT */ - fputc('\x1B', f); - break; - } else if (*i == '[') { - state = STATE_BRACKET; - begin = i + 1; - } else { - fputc('\x1B', f); - fputc(*i, f); - state = STATE_OTHER; - } - - break; - - case STATE_BRACKET: - - if (i >= *ibuf + isz || /* EOT */ - (!(*i >= '0' && *i <= '9') && *i != ';' && *i != 'm')) { - fputc('\x1B', f); - fputc('[', f); - state = STATE_OTHER; - i = begin-1; - } else if (*i == 'm') - state = STATE_OTHER; - break; - } - } - - if (ferror(f)) { - fclose(f); - free(obuf); - return NULL; - } - - fclose(f); - - free(*ibuf); - *ibuf = obuf; - - if (_isz) - *_isz = osz; - - return obuf; -} - int on_ac_power(void) { bool found_offline = false, found_online = false; _cleanup_closedir_ DIR *d = NULL; @@ -4267,77 +3670,6 @@ int search_and_fopen_nulstr(const char *path, const char *mode, const char *root return search_and_fopen_internal(path, mode, root, s, _f); } -char *strextend(char **x, ...) { - va_list ap; - size_t f, l; - char *r, *p; - - assert(x); - - l = f = *x ? strlen(*x) : 0; - - va_start(ap, x); - for (;;) { - const char *t; - size_t n; - - t = va_arg(ap, const char *); - if (!t) - break; - - n = strlen(t); - if (n > ((size_t) -1) - l) { - va_end(ap); - return NULL; - } - - l += n; - } - va_end(ap); - - r = realloc(*x, l+1); - if (!r) - return NULL; - - p = r + f; - - va_start(ap, x); - for (;;) { - const char *t; - - t = va_arg(ap, const char *); - if (!t) - break; - - p = stpcpy(p, t); - } - va_end(ap); - - *p = 0; - *x = r; - - return r + l; -} - -char *strrep(const char *s, unsigned n) { - size_t l; - char *r, *p; - unsigned i; - - assert(s); - - l = strlen(s); - p = r = malloc(l * n + 1); - if (!r) - return NULL; - - for (i = 0; i < n; i++) - p = stpcpy(p, s); - - *p = 0; - return r; -} - void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) { size_t a, newalloc; void *q; @@ -4424,37 +3756,6 @@ bool id128_is_valid(const char *s) { return true; } -int split_pair(const char *s, const char *sep, char **l, char **r) { - char *x, *a, *b; - - assert(s); - assert(sep); - assert(l); - assert(r); - - if (isempty(sep)) - return -EINVAL; - - x = strstr(s, sep); - if (!x) - return -EINVAL; - - a = strndup(s, x - s); - if (!a) - return -ENOMEM; - - b = strdup(x + strlen(sep)); - if (!b) { - free(a); - return -ENOMEM; - } - - *l = a; - *r = b; - - return 0; -} - int shall_restore_state(void) { _cleanup_free_ char *value = NULL; int r; @@ -5407,30 +4708,6 @@ int is_device_node(const char *path) { return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode)); } -int free_and_strdup(char **p, const char *s) { - char *t; - - assert(p); - - /* Replaces a string pointer with an strdup()ed new string, - * possibly freeing the old one. */ - - if (streq_ptr(*p, s)) - return 0; - - if (s) { - t = strdup(s); - if (!t) - return -ENOMEM; - } else - t = NULL; - - free(*p); - *p = t; - - return 1; -} - ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) { char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; _cleanup_close_ int fd = -1; @@ -6080,22 +5357,3 @@ bool fdname_is_valid(const char *s) { bool oom_score_adjust_is_valid(int oa) { return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX; } - -void string_erase(char *x) { - - if (!x) - return; - - /* A delicious drop of snake-oil! To be called on memory where - * we stored passphrases or so, after we used them. */ - - memory_erase(x, strlen(x)); -} - -char *string_free_erase(char *s) { - if (!s) - return NULL; - - string_erase(s); - return mfree(s); -} -- cgit v1.2.3-54-g00ecf