X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=4cf928f83a3049a443e1cb5bf9404914ed7e2a06;hp=9a45e6058e200813fed1bae7ff9d27f0ebb164a5;hb=943aad8ca57a6b5c49c4ea60f9e8c13bf9b20e6c;hpb=49371bb50e0fe6e9e90309a20006bcfd9e2fa8f4 diff --git a/src/shared/util.c b/src/shared/util.c index 9a45e6058..4cf928f83 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -57,6 +57,8 @@ #include #include #include +#include +#include #include "macro.h" #include "util.h" @@ -75,6 +77,10 @@ char **saved_argv = NULL; static volatile unsigned cached_columns = 0; static volatile unsigned cached_lines = 0; +bool is_efiboot(void) { + return access("/sys/firmware/efi", F_OK) >= 0; +} + size_t page_size(void) { static __thread size_t pgsz = 0; long r; @@ -148,8 +154,7 @@ usec_t timespec_load(const struct timespec *ts) { ts->tv_nsec == (long) -1) return (usec_t) -1; - if (ts->tv_sec > 0 && - USEC_PER_SEC > ((UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / (usec_t) ts->tv_sec)) + if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC) return (usec_t) -1; return @@ -179,7 +184,7 @@ usec_t timeval_load(const struct timeval *tv) { tv->tv_usec == (suseconds_t) -1) return (usec_t) -1; - if (USEC_PER_SEC > (UINT64_MAX - tv->tv_usec) / (usec_t) tv->tv_sec) + if ((usec_t) tv->tv_sec > (UINT64_MAX - tv->tv_usec) / USEC_PER_SEC) return (usec_t) -1; return @@ -378,7 +383,7 @@ int safe_atou(const char *s, unsigned *ret_u) { errno = 0; l = strtoul(s, &x, 0); - if (!x || *x || errno) + if (!x || x == s || *x || errno) return errno ? -errno : -EINVAL; if ((unsigned long) (unsigned) l != l) @@ -398,7 +403,7 @@ int safe_atoi(const char *s, int *ret_i) { errno = 0; l = strtol(s, &x, 0); - if (!x || *x || errno) + if (!x || x == s || *x || errno) return errno ? -errno : -EINVAL; if ((long) (int) l != l) @@ -418,7 +423,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) { errno = 0; l = strtoull(s, &x, 0); - if (!x || *x || errno) + if (!x || x == s || *x || errno) return errno ? -errno : -EINVAL; *ret_llu = l; @@ -435,7 +440,7 @@ int safe_atolli(const char *s, long long int *ret_lli) { errno = 0; l = strtoll(s, &x, 0); - if (!x || *x || errno) + if (!x || x == s || *x || errno) return errno ? -errno : -EINVAL; *ret_lli = l; @@ -3395,6 +3400,12 @@ int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct return ret; } +static int is_temporary_fs(struct statfs *s) { + assert(s); + return s->f_type == TMPFS_MAGIC || + (long)s->f_type == (long)RAMFS_MAGIC; +} + int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) { struct statfs s; @@ -3408,9 +3419,7 @@ int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root /* We refuse to clean disk file systems with this call. This * is extra paranoia just to be sure we never ever remove * non-state data */ - - if (s.f_type != TMPFS_MAGIC && - s.f_type != RAMFS_MAGIC) { + if (!is_temporary_fs(&s)) { log_error("Attempted to remove disk file system, and we can't allow that."); close_nointr_nofail(fd); return -EPERM; @@ -3443,8 +3452,7 @@ static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bo if (statfs(path, &s) < 0) return -errno; - if (s.f_type != TMPFS_MAGIC && - s.f_type != RAMFS_MAGIC) { + if (!is_temporary_fs(&s)) { log_error("Attempted to remove disk file system, and we can't allow that."); return -EPERM; } @@ -3463,8 +3471,7 @@ static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bo return -errno; } - if (s.f_type != TMPFS_MAGIC && - s.f_type != RAMFS_MAGIC) { + if (!is_temporary_fs(&s)) { log_error("Attempted to remove disk file system, and we can't allow that."); close_nointr_nofail(fd); return -EPERM; @@ -5208,7 +5215,7 @@ static const char *const ioprio_class_table[] = { [IOPRIO_CLASS_IDLE] = "idle" }; -DEFINE_STRING_TABLE_LOOKUP(ioprio_class, int); +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX); static const char *const sigchld_code_table[] = { [CLD_EXITED] = "exited", @@ -5244,7 +5251,7 @@ static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = { [LOG_FAC(LOG_LOCAL7)] = "local7" }; -DEFINE_STRING_TABLE_LOOKUP(log_facility_unshifted, int); +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0)); static const char *const log_level_table[] = { [LOG_EMERG] = "emerg", @@ -5257,7 +5264,7 @@ static const char *const log_level_table[] = { [LOG_DEBUG] = "debug" }; -DEFINE_STRING_TABLE_LOOKUP(log_level, int); +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG); static const char* const sched_policy_table[] = { [SCHED_OTHER] = "other", @@ -5267,7 +5274,7 @@ static const char* const sched_policy_table[] = { [SCHED_RR] = "rr" }; -DEFINE_STRING_TABLE_LOOKUP(sched_policy, int); +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX); static const char* const rlimit_table[] = { [RLIMIT_CPU] = "LimitCPU", @@ -5297,7 +5304,7 @@ static const char* const ip_tos_table[] = { [IPTOS_LOWCOST] = "low-cost", }; -DEFINE_STRING_TABLE_LOOKUP(ip_tos, int); +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff); static const char *const __signal_table[] = { [SIGHUP] = "HUP", @@ -5762,7 +5769,7 @@ bool in_initrd(void) { saved = access("/etc/initrd-release", F_OK) >= 0 && statfs("/", &s) >= 0 && - (s.f_type == TMPFS_MAGIC || s.f_type == RAMFS_MAGIC); + is_temporary_fs(&s); return saved; } @@ -6116,3 +6123,95 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, } return NULL; } + +bool is_locale_utf8(void) { + const char *set; + static int cached_answer = -1; + + if (cached_answer >= 0) + goto out; + + if (!setlocale(LC_ALL, "")) { + cached_answer = true; + goto out; + } + + set = nl_langinfo(CODESET); + if (!set) { + cached_answer = true; + goto out; + } + + cached_answer = streq(set, "UTF-8"); +out: + return (bool)cached_answer; +} + +const char *draw_special_char(DrawSpecialChar ch) { + static const char *draw_table[2][_DRAW_SPECIAL_CHAR_MAX] = { + /* UTF-8 */ { + [DRAW_TREE_VERT] = "\342\224\202 ", /* │ */ + [DRAW_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */ + [DRAW_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */ + [DRAW_TRIANGULAR_BULLET] = "\342\200\243 ", /* ‣ */ + }, + /* ASCII fallback */ { + [DRAW_TREE_VERT] = "| ", + [DRAW_TREE_BRANCH] = "|-", + [DRAW_TREE_RIGHT] = "`-", + [DRAW_TRIANGULAR_BULLET] = "> ", + } + }; + + 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; +}