along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <alloca.h>
#include <inttypes.h>
#include <time.h>
#include <sys/time.h>
#include <dirent.h>
#include <sys/resource.h>
#include <stddef.h>
+#include <unistd.h>
#include "macro.h"
-
-typedef uint64_t usec_t;
-typedef uint64_t nsec_t;
-
-typedef struct dual_timestamp {
- usec_t realtime;
- usec_t monotonic;
-} dual_timestamp;
+#include "time-util.h"
union dirent_storage {
struct dirent de;
((NAME_MAX + 1 + sizeof(long)) & ~(sizeof(long) - 1))];
};
-#define MSEC_PER_SEC 1000ULL
-#define USEC_PER_SEC 1000000ULL
-#define USEC_PER_MSEC 1000ULL
-#define NSEC_PER_SEC 1000000000ULL
-#define NSEC_PER_MSEC 1000000ULL
-#define NSEC_PER_USEC 1000ULL
-
-#define USEC_PER_MINUTE (60ULL*USEC_PER_SEC)
-#define NSEC_PER_MINUTE (60ULL*NSEC_PER_SEC)
-#define USEC_PER_HOUR (60ULL*USEC_PER_MINUTE)
-#define NSEC_PER_HOUR (60ULL*NSEC_PER_MINUTE)
-#define USEC_PER_DAY (24ULL*USEC_PER_HOUR)
-#define NSEC_PER_DAY (24ULL*NSEC_PER_HOUR)
-#define USEC_PER_WEEK (7ULL*USEC_PER_DAY)
-#define NSEC_PER_WEEK (7ULL*NSEC_PER_DAY)
-#define USEC_PER_MONTH (2629800ULL*USEC_PER_SEC)
-#define NSEC_PER_MONTH (2629800ULL*NSEC_PER_SEC)
-#define USEC_PER_YEAR (31557600ULL*USEC_PER_SEC)
-#define NSEC_PER_YEAR (31557600ULL*NSEC_PER_SEC)
-
/* What is interpreted as whitespace? */
#define WHITESPACE " \t\n\r"
#define NEWLINE "\n\r"
#define QUOTES "\"\'"
-#define COMMENTS "#;\n"
+#define COMMENTS "#;"
-#define FORMAT_TIMESTAMP_MAX (5+11+9+4+1)
-#define FORMAT_TIMESTAMP_PRETTY_MAX 256
-#define FORMAT_TIMESPAN_MAX 64
#define FORMAT_BYTES_MAX 8
#define ANSI_HIGHLIGHT_ON "\x1B[1;39m"
+#define ANSI_RED_ON "\x1B[31m"
#define ANSI_HIGHLIGHT_RED_ON "\x1B[1;31m"
+#define ANSI_GREEN_ON "\x1B[32m"
#define ANSI_HIGHLIGHT_GREEN_ON "\x1B[1;32m"
#define ANSI_HIGHLIGHT_YELLOW_ON "\x1B[1;33m"
#define ANSI_HIGHLIGHT_OFF "\x1B[0m"
-
-bool is_efiboot(void);
-
-usec_t now(clockid_t clock);
-
-dual_timestamp* dual_timestamp_get(dual_timestamp *ts);
-dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u);
-
-#define dual_timestamp_is_set(ts) ((ts)->realtime > 0)
-
-usec_t timespec_load(const struct timespec *ts);
-struct timespec *timespec_store(struct timespec *ts, usec_t u);
-
-usec_t timeval_load(const struct timeval *tv);
-struct timeval *timeval_store(struct timeval *tv, usec_t u);
+#define ANSI_ERASE_TO_END_OF_LINE "\x1B[K"
size_t page_size(void);
#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
#define streq(a,b) (strcmp((a),(b)) == 0)
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
+#define strcaseeq(a,b) (strcasecmp((a),(b)) == 0)
+#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
bool streq_ptr(const char *a, const char *b);
void close_many(const int fds[], unsigned n_fd);
int parse_boolean(const char *v);
-int parse_usec(const char *t, usec_t *usec);
-int parse_nsec(const char *t, nsec_t *nsec);
int parse_bytes(const char *t, off_t *bytes);
int parse_pid(const char *s, pid_t* ret_pid);
int parse_uid(const char *s, uid_t* ret_uid);
int safe_atollu(const char *s, unsigned long long *ret_u);
int safe_atolli(const char *s, long long int *ret_i);
+int safe_atod(const char *s, double *ret_d);
+
#if __WORDSIZE == 32
static inline int safe_atolu(const char *s, unsigned long *ret_u) {
assert_cc(sizeof(unsigned long) == sizeof(unsigned));
pid_t get_parent_of_pid(pid_t pid, pid_t *ppid);
int get_starttime_of_pid(pid_t pid, unsigned long long *st);
-int write_one_line_file(const char *fn, const char *line);
-int write_one_line_file_atomic(const char *fn, const char *line);
-int read_one_line_file(const char *fn, char **line);
-int read_full_file(const char *fn, char **contents, size_t *size);
-
-int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
-int load_env_file(const char *fname, char ***l);
-int write_env_file(const char *fname, char **l);
-
char *strappend(const char *s, const char *suffix);
char *strnappend(const char *s, const char *suffix, size_t length);
bool chars_intersect(const char *a, const char *b);
-char *format_timestamp(char *buf, size_t l, usec_t t);
-char *format_timestamp_pretty(char *buf, size_t l, usec_t t);
-char *format_timespan(char *buf, size_t l, usec_t t);
-
int make_stdio(int fd);
int make_null_stdio(void);
int make_console_stdio(void);
bool is_device_path(const char *path);
int dir_is_empty(const char *path);
+char* dirname_malloc(const char *path);
void rename_process(const char name[8]);
cpu_set_t* cpu_set_malloc(unsigned *ncpus);
-int status_vprintf(const char *status, bool ellipse, const char *format, va_list ap);
-int status_printf(const char *status, bool ellipse, const char *format, ...);
+int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap);
+int status_printf(const char *status, bool ellipse, bool ephemeral, const char *format, ...);
int status_welcome(void);
int fd_columns(int fd);
DIR *xopendirat(int dirfd, const char *name, int flags);
-void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t);
-void dual_timestamp_deserialize(const char *value, dual_timestamp *t);
-
char *fstab_node_to_udev_node(const char *p);
+char *resolve_dev_console(char **active);
bool tty_is_vc(const char *tty);
bool tty_is_vc_resolve(const char *tty);
bool tty_is_console(const char *tty);
int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell);
int get_group_creds(const char **groupname, gid_t *gid);
+int in_gid(gid_t gid);
int in_group(const char *name);
+char* uid_to_name(uid_t uid);
+char* gid_to_name(gid_t gid);
+
int glob_exists(const char *path);
int dirent_ensure_type(DIR *d, struct dirent *de);
void warn_melody(void);
-int get_shell(char **ret);
int get_home_dir(char **ret);
-void freep(void *p);
-void fclosep(FILE **f);
-void closep(int *fd);
-void closedirp(DIR **d);
-void umaskp(mode_t *u);
+static inline void freep(void *p) {
+ free(*(void**) p);
+}
+
+static inline void fclosep(FILE **f) {
+ if (*f)
+ fclose(*f);
+}
+
+static inline void pclosep(FILE **f) {
+ if (*f)
+ pclose(*f);
+}
+
+static inline void closep(int *fd) {
+ if (*fd >= 0)
+ close_nointr_nofail(*fd);
+}
+
+static inline void closedirp(DIR **d) {
+ if (*d)
+ closedir(*d);
+}
+
+static inline void umaskp(mode_t *u) {
+ umask(*u);
+}
+
+#define _cleanup_free_ _cleanup_(freep)
+#define _cleanup_fclose_ _cleanup_(fclosep)
+#define _cleanup_pclose_ _cleanup_(pclosep)
+#define _cleanup_close_ _cleanup_(closep)
+#define _cleanup_closedir_ _cleanup_(closedirp)
+#define _cleanup_umask_ _cleanup_(umaskp)
+#define _cleanup_globfree_ _cleanup_(globfree)
_malloc_ static inline void *malloc_multiply(size_t a, size_t b) {
if (_unlikely_(b == 0 || a > ((size_t) -1) / b))
}
bool filename_is_safe(const char *p);
+bool path_is_safe(const char *p);
bool string_is_safe(const char *p);
-
-int parse_timestamp(const char *t, usec_t *usec);
+bool string_has_cc(const char *p);
void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
int (*compar) (const void *, const void *, void *),
DRAW_TREE_VERT,
DRAW_TREE_BRANCH,
DRAW_TREE_RIGHT,
+ DRAW_TREE_SPACE,
DRAW_TRIANGULAR_BULLET,
_DRAW_SPECIAL_CHAR_MAX
} DrawSpecialChar;
const char *draw_special_char(DrawSpecialChar ch);
+
+char *strreplace(const char *text, const char *old_string, const char *new_string);
+
+char *strip_tab_ansi(char **p, size_t *l);
+
+int on_ac_power(void);
+
+int search_and_fopen(const char *path, const char *mode, const char **search, FILE **_f);
+int search_and_fopen_nulstr(const char *path, const char *mode, const char *search, FILE **_f);
+int create_tmp_dir(char template[], char** dir_name);
+
+#define FOREACH_LINE(line, f, on_error) \
+ for (;;) \
+ if (!fgets(line, sizeof(line), f)) { \
+ if (ferror(f)) { \
+ on_error; \
+ } \
+ break; \
+ } else
+
+#define FOREACH_DIRENT(de, d, on_error) \
+ for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \
+ if (!de) { \
+ if (errno > 0) { \
+ on_error; \
+ } \
+ break; \
+ } else if (ignore_file((de)->d_name)) \
+ continue; \
+ else
+
+static inline void *mempset(void *s, int c, size_t n) {
+ memset(s, c, n);
+ return (uint8_t*)s + n;
+}
+
+char *hexmem(const void *p, size_t l);
+void *unhexmem(const char *p, size_t l);
+
+char *strextend(char **x, ...);
+char *strrep(const char *s, unsigned n);
+
+void* greedy_realloc(void **p, size_t *allocated, size_t need);
+#define GREEDY_REALLOC(array, allocated, need) \
+ greedy_realloc((void**) &(array), &(allocated), sizeof((array)[0]) * (need))
+
+static inline void _reset_errno_(int *saved_errno) {
+ errno = *saved_errno;
+}
+
+#define PROTECT_ERRNO __attribute__((cleanup(_reset_errno_))) int _saved_errno_ = errno
+
+struct umask_struct {
+ mode_t mask;
+ bool quit;
+};
+
+static inline void _reset_umask_(struct umask_struct *s) {
+ umask(s->mask);
+};
+
+#define RUN_WITH_UMASK(mask) \
+ for (__attribute__((cleanup(_reset_umask_))) struct umask_struct _saved_umask_ = { umask(mask), false }; \
+ !_saved_umask_.quit ; \
+ _saved_umask_.quit = true)
+
+static inline unsigned u64log2(uint64_t n) {
+ return (n > 1) ? __builtin_clzll(n) ^ 63U : 0;
+}
+
+static inline bool logind_running(void) {
+ return access("/run/systemd/seats/", F_OK) >= 0;
+}
+
+#define DECIMAL_STR_WIDTH(x) \
+ ({ \
+ typeof(x) _x_ = (x); \
+ unsigned ans = 1; \
+ while (_x_ /= 10) \
+ ans++; \
+ ans; \
+ })
+
+int unlink_noerrno(const char *path);
+
+#define alloca0(n) \
+ ({ \
+ char *_new_; \
+ size_t _len_ = n; \
+ _new_ = alloca(_len_); \
+ (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 procfs_file_alloca(pid, field) \
+ ({ \
+ pid_t _pid_ = (pid); \
+ char *_r_; \
+ _r_ = alloca(sizeof("/proc/") -1 + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
+ sprintf(_r_, "/proc/%lu/" field, (unsigned long) _pid_); \
+ _r_; \
+ })