X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Futil.h;h=21a90a40e5b3e4391d9a9cd9212ebfc2701ee0e7;hp=891fcee239f0766ba5006f41f09a2bbc651e7bb6;hb=8507eb20b64010b26f23822cbf442bb0bf96511c;hpb=856a5a7d769826019d86bc52ae1bc2ed7b13ad44 diff --git a/src/shared/util.h b/src/shared/util.h index 891fcee23..21a90a40e 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -67,7 +67,24 @@ # error Unknown gid_t size #endif +#if SIZEOF_TIME_T == 8 +# define PRI_TIME PRIu64 +#elif SIZEOF_TIME_T == 4 +# define PRI_TIME PRIu32 +#else +# error Unknown time_t size +#endif + +#if SIZEOF_RLIM_T == 8 +# define RLIM_FMT "%" PRIu64 +#elif SIZEOF_RLIM_T == 4 +# define RLIM_FMT "%" PRIu32 +#else +# error Unknown rlim_t size +#endif + #include "macro.h" +#include "missing.h" #include "time-util.h" /* What is interpreted as whitespace? */ @@ -77,6 +94,12 @@ #define COMMENTS "#;" #define GLOB_CHARS "*?[" +/* What characters are special in the shell? */ +/* must be escaped outside and inside double-quotes */ +#define SHELL_NEED_ESCAPE "\"\\`$" +/* can be escaped or double-quoted */ +#define SHELL_NEED_QUOTES SHELL_NEED_ESCAPE GLOB_CHARS "'()<>|&;" + #define FORMAT_BYTES_MAX 8 #define ANSI_HIGHLIGHT_ON "\x1B[1;39m" @@ -105,6 +128,8 @@ bool streq_ptr(const char *a, const char *b) _pure_; #define newa(t, n) ((t*) alloca(sizeof(t)*(n))) +#define newa0(t, n) ((t*) alloca0(sizeof(t)*(n))) + #define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n))) #define malloc0(n) (calloc((n), 1)) @@ -133,21 +158,29 @@ static inline bool isempty(const char *p) { return !p || !p[0]; } -static inline const char *startswith(const char *s, const char *prefix) { - if (strncmp(s, prefix, strlen(prefix)) == 0) - return s + strlen(prefix); +static inline char *startswith(const char *s, const char *prefix) { + size_t l; + + l = strlen(prefix); + if (strncmp(s, prefix, l) == 0) + return (char*) s + l; + return NULL; } -static inline const char *startswith_no_case(const char *s, const char *prefix) { - if (strncasecmp(s, prefix, strlen(prefix)) == 0) - return s + strlen(prefix); +static inline char *startswith_no_case(const char *s, const char *prefix) { + size_t l; + + l = strlen(prefix); + if (strncasecmp(s, prefix, l) == 0) + return (char*) s + l; + return NULL; } char *endswith(const char *s, const char *postfix) _pure_; -bool first_word(const char *s, const char *word) _pure_; +char *first_word(const char *s, const char *word) _pure_; int close_nointr(int fd); int safe_close(int fd); @@ -170,7 +203,9 @@ int safe_atolli(const char *s, long long int *ret_i); int safe_atod(const char *s, double *ret_d); -#if __WORDSIZE == 32 +int safe_atou8(const char *s, uint8_t *ret); + +#if LONG_MAX == INT_MAX static inline int safe_atolu(const char *s, unsigned long *ret_u) { assert_cc(sizeof(unsigned long) == sizeof(unsigned)); return safe_atou(s, (unsigned*) ret_u); @@ -210,7 +245,7 @@ static inline int safe_atoi64(const char *s, int64_t *ret_i) { return safe_atolli(s, (long long int*) ret_i); } -char *split(const char *c, size_t *l, const char *separator, bool quoted, char **state); +const char* split(const char **state, size_t *l, const char *separator, bool quoted); #define FOREACH_WORD(word, length, s, state) \ _FOREACH_WORD(word, length, s, WHITESPACE, false, state) @@ -221,11 +256,8 @@ char *split(const char *c, size_t *l, const char *separator, bool quoted, char * #define FOREACH_WORD_QUOTED(word, length, s, state) \ _FOREACH_WORD(word, length, s, WHITESPACE, true, state) -#define FOREACH_WORD_SEPARATOR_QUOTED(word, length, s, separator, state) \ - _FOREACH_WORD(word, length, s, separator, true, state) - #define _FOREACH_WORD(word, length, s, separator, quoted, state) \ - for ((state) = NULL, (word) = split((s), &(length), (separator), (quoted), &(state)); (word); (word) = split((s), &(length), (separator), (quoted), &(state))) + for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted))) pid_t get_parent_of_pid(pid_t pid, pid_t *ppid); int get_starttime_of_pid(pid_t pid, unsigned long long *st); @@ -236,11 +268,13 @@ char *strnappend(const char *s, const char *suffix, size_t length); char *replace_env(const char *format, char **env); char **replace_env_argv(char **argv, char **env); +int readlinkat_malloc(int fd, const char *p, char **ret); int readlink_malloc(const char *p, char **r); int readlink_and_make_absolute(const char *p, char **r); int readlink_and_canonicalize(const char *p, char **r); int reset_all_signal_handlers(void); +int reset_signal_mask(void); char *strstrip(char *s); char *delete_chars(char *s, const char *bad); @@ -365,7 +399,8 @@ bool fstype_is_network(const char *fstype); int chvt(int vt); int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl); -int ask(char *ret, const char *replies, const char *text, ...) _printf_(3, 4); +int ask_char(char *ret, const char *replies, const char *text, ...) _printf_(3, 4); +int ask_string(char **ret, const char *text, ...) _printf_(2, 3); int reset_terminal_fd(int fd, bool switch_to_text); int reset_terminal(const char *name); @@ -397,6 +432,7 @@ int sigprocmask_many(int how, ...); bool hostname_is_set(void); +char* lookup_uid(uid_t uid); char* gethostname_malloc(void); char* getlogname_malloc(void); char* getusername_malloc(void); @@ -462,6 +498,7 @@ char *ellipsize(const char *s, size_t length, unsigned percent); /* bytes columns */ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent); +int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode); int touch(const char *path); char *unquote(const char *s, const char *quotes); @@ -474,6 +511,7 @@ noreturn void freeze(void); bool null_or_empty(struct stat *st) _pure_; int null_or_empty_path(const char *fn); +int null_or_empty_fd(int fd); DIR *xopendirat(int dirfd, const char *name, int flags); @@ -497,6 +535,8 @@ bool plymouth_running(void); bool hostname_is_valid(const char *s) _pure_; char* hostname_cleanup(char *s, bool lowercase); +bool machine_name_is_valid(const char *s) _pure_; + char* strshorten(char *s, size_t l); int terminal_vhangup_fd(int fd); @@ -504,9 +544,9 @@ int terminal_vhangup(const char *name); int vt_disallocate(const char *name); -int copy_file(const char *from, const char *to, int flags); - int symlink_atomic(const char *from, const char *to); +int mknod_atomic(const char *path, mode_t mode, dev_t dev); +int mkfifo_atomic(const char *path, mode_t mode); int fchmod_umask(int fd, mode_t mode); @@ -527,7 +567,6 @@ int glob_extend(char ***strv, const char *path); int dirent_ensure_type(DIR *d, struct dirent *de); -int in_search_path(const char *path, char **search); int get_files_in_directory(const char *path, char ***list); char *strjoin(const char *x, ...) _sentinel_; @@ -544,8 +583,6 @@ int block_get_whole_disk(dev_t d, dev_t *ret); int file_is_priv_sticky(const char *p); -int strdup_or_null(const char *a, char **b); - #define NULSTR_FOREACH(i, l) \ for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1) @@ -650,14 +687,21 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent); #define _cleanup_close_pair_ _cleanup_(close_pairp) _malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) { - if (_unlikely_(b == 0 || a > ((size_t) -1) / b)) + if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) return NULL; return malloc(a * b); } +_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) { + if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) + return NULL; + + return realloc(p, a * b); +} + _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) { - if (_unlikely_(b == 0 || a > ((size_t) -1) / b)) + if (_unlikely_(b != 0 && a > ((size_t) -1) / b)) return NULL; return memdup(p, a * b); @@ -666,7 +710,7 @@ _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_ bool filename_is_safe(const char *p) _pure_; bool path_is_safe(const char *p) _pure_; bool string_is_safe(const char *p) _pure_; -bool string_has_cc(const char *p) _pure_; +bool string_has_cc(const char *p, const char *ok) _pure_; /** * Check if a string contains any glob patterns. @@ -689,6 +733,7 @@ typedef enum DrawSpecialChar { DRAW_TRIANGULAR_BULLET, DRAW_BLACK_CIRCLE, DRAW_ARROW, + DRAW_DASH, _DRAW_SPECIAL_CHAR_MAX } DrawSpecialChar; @@ -807,29 +852,35 @@ int unlink_noerrno(const char *path); (void *) memset(_new_, 0, _len_); \ }) -#define strappenda(a, b) \ - ({ \ - const char *_a_ = (a), *_b_ = (b); \ - char *_c_; \ - size_t _x_, _y_; \ - _x_ = strlen(_a_); \ - _y_ = strlen(_b_); \ - _c_ = alloca(_x_ + _y_ + 1); \ - strcpy(stpcpy(_c_, _a_), _b_); \ - _c_; \ +#define alloca_align(size, align) \ + ({ \ + void *_ptr_; \ + size_t _mask_ = (align) - 1; \ + _ptr_ = alloca((size) + _mask_); \ + (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ }) -#define strappenda3(a, b, c) \ - ({ \ - const char *_a_ = (a), *_b_ = (b), *_c_ = (c); \ - char *_d_; \ - size_t _x_, _y_, _z_; \ - _x_ = strlen(_a_); \ - _y_ = strlen(_b_); \ - _z_ = strlen(_c_); \ - _d_ = alloca(_x_ + _y_ + _z_ + 1); \ - strcpy(stpcpy(stpcpy(_d_, _a_), _b_), _c_); \ - _d_; \ +#define alloca0_align(size, align) \ + ({ \ + void *_new_; \ + size_t _size_ = (size); \ + _new_ = alloca_align(_size_, (align)); \ + (void*)memset(_new_, 0, _size_); \ + }) + +#define strappenda(a, ...) \ + ({ \ + int _len = strlen(a); \ + unsigned _i; \ + char *_d_, *_p_; \ + const char *_appendees_[] = { __VA_ARGS__ }; \ + for (_i = 0; _i < ELEMENTSOF(_appendees_); _i++) \ + _len += strlen(_appendees_[_i]); \ + _d_ = alloca(_len + 1); \ + _p_ = stpcpy(_d_, a); \ + for (_i = 0; _i < ELEMENTSOF(_appendees_); _i++) \ + _p_ = stpcpy(_p_, _appendees_[_i]); \ + _d_; \ }) #define procfs_file_alloca(pid, field) \ @@ -894,8 +945,8 @@ int parse_proc_cmdline(int (*parse_word)(const char *key, const char *value)); int container_get_leader(const char *machine, pid_t *pid); -int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *root_fd); -int namespace_enter(int pidns_fd, int mntns_fd, int root_fd); +int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd); +int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd); bool pid_is_alive(pid_t pid); bool pid_is_unwaited(pid_t pid); @@ -925,3 +976,23 @@ union file_handle_union { }; int update_reboot_param_file(const char *param); + +int umount_recursive(const char *target, int flags); + +int bind_remount_recursive(const char *prefix, bool ro); + +int fflush_and_check(FILE *f); + +char *tempfn_xxxxxx(const char *p); +char *tempfn_random(const char *p); + +bool is_localhost(const char *hostname); + +int take_password_lock(const char *root); + +int is_symlink(const char *path); + +int unquote_first_word(const char **p, char **ret); +int unquote_many_words(const char **p, ...) _sentinel_; + +int free_and_strdup(char **p, const char *s);