summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/copy.c2
-rw-r--r--src/basic/dirent-util.c12
-rw-r--r--src/basic/dirent-util.h2
-rw-r--r--src/basic/fd-util.c12
-rw-r--r--src/basic/fd-util.h2
-rw-r--r--src/basic/fdset.c2
-rw-r--r--src/basic/fileio.c124
-rw-r--r--src/basic/fileio.h6
-rw-r--r--src/basic/fs-util.c15
-rw-r--r--src/basic/fs-util.h2
-rw-r--r--src/basic/missing.h8
-rw-r--r--src/basic/mount-util.c4
-rw-r--r--src/basic/parse-util.h2
-rw-r--r--src/basic/path-util.c49
-rw-r--r--src/basic/path-util.h3
-rw-r--r--src/basic/process-util.c12
-rw-r--r--src/basic/process-util.h2
-rw-r--r--src/basic/terminal-util.c19
-rw-r--r--src/basic/time-util.c37
-rw-r--r--src/basic/time-util.h1
-rw-r--r--src/basic/user-util.h5
-rw-r--r--src/basic/util.c2
22 files changed, 237 insertions, 86 deletions
diff --git a/src/basic/copy.c b/src/basic/copy.c
index e2db4be9ff..03487a6878 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -102,7 +102,7 @@ int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
if (try_cfr) {
n = try_copy_file_range(fdf, NULL, fdt, NULL, m, 0u);
if (n < 0) {
- if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV))
+ if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV, -EBADF))
return n;
try_cfr = false;
diff --git a/src/basic/dirent-util.c b/src/basic/dirent-util.c
index 5fb535cb13..59067121b7 100644
--- a/src/basic/dirent-util.c
+++ b/src/basic/dirent-util.c
@@ -52,12 +52,10 @@ int dirent_ensure_type(DIR *d, struct dirent *de) {
bool dirent_is_file(const struct dirent *de) {
assert(de);
- if (hidden_file(de->d_name))
+ if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN))
return false;
- if (de->d_type != DT_REG &&
- de->d_type != DT_LNK &&
- de->d_type != DT_UNKNOWN)
+ if (hidden_or_backup_file(de->d_name))
return false;
return true;
@@ -66,12 +64,10 @@ bool dirent_is_file(const struct dirent *de) {
bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
assert(de);
- if (de->d_type != DT_REG &&
- de->d_type != DT_LNK &&
- de->d_type != DT_UNKNOWN)
+ if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN))
return false;
- if (hidden_file_allow_backup(de->d_name))
+ if (de->d_name[0] == '.')
return false;
return endswith(de->d_name, suffix);
diff --git a/src/basic/dirent-util.h b/src/basic/dirent-util.h
index 6bf099b46c..b91d04908f 100644
--- a/src/basic/dirent-util.h
+++ b/src/basic/dirent-util.h
@@ -38,7 +38,7 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pu
on_error; \
} \
break; \
- } else if (hidden_file((de)->d_name)) \
+ } else if (hidden_or_backup_file((de)->d_name)) \
continue; \
else
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
index ec9560cd07..9130d023d7 100644
--- a/src/basic/fd-util.c
+++ b/src/basic/fd-util.c
@@ -25,11 +25,13 @@
#include <unistd.h>
#include "fd-util.h"
+#include "fs-util.h"
#include "macro.h"
#include "missing.h"
#include "parse-util.h"
#include "path-util.h"
#include "socket-util.h"
+#include "stdio-util.h"
#include "util.h"
int close_nointr(int fd) {
@@ -229,7 +231,7 @@ int close_all_fds(const int except[], unsigned n_except) {
while ((de = readdir(d))) {
int fd = -1;
- if (hidden_file(de->d_name))
+ if (hidden_or_backup_file(de->d_name))
continue;
if (safe_atoi(de->d_name, &fd) < 0)
@@ -356,3 +358,11 @@ bool fdname_is_valid(const char *s) {
return p - s < 256;
}
+
+int fd_get_path(int fd, char **ret) {
+ char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+
+ return readlink_malloc(procfs_path, ret);
+}
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
index 44528c6e35..b86e41698a 100644
--- a/src/basic/fd-util.h
+++ b/src/basic/fd-util.h
@@ -72,6 +72,8 @@ void cmsg_close_all(struct msghdr *mh);
bool fdname_is_valid(const char *s);
+int fd_get_path(int fd, char **ret);
+
/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
#define ERRNO_IS_DISCONNECT(r) \
IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)
diff --git a/src/basic/fdset.c b/src/basic/fdset.c
index 06f8ecbdbc..527f27bc67 100644
--- a/src/basic/fdset.c
+++ b/src/basic/fdset.c
@@ -151,7 +151,7 @@ int fdset_new_fill(FDSet **_s) {
while ((de = readdir(d))) {
int fd = -1;
- if (hidden_file(de->d_name))
+ if (hidden_or_backup_file(de->d_name))
continue;
r = safe_atoi(de->d_name, &fd);
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 69590941e5..2a9b6e46ad 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -1083,30 +1083,6 @@ int mkostemp_safe(char *pattern, int flags) {
return fd;
}
-int open_tmpfile(const char *path, int flags) {
- char *p;
- int fd;
-
- assert(path);
-
-#ifdef O_TMPFILE
- /* Try O_TMPFILE first, if it is supported */
- fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
- if (fd >= 0)
- return fd;
-#endif
-
- /* Fall back to unguessable name + unlinking */
- p = strjoina(path, "/systemd-tmp-XXXXXX");
-
- fd = mkostemp_safe(p, flags);
- if (fd < 0)
- return fd;
-
- unlink(p);
- return fd;
-}
-
int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
const char *fn;
char *t;
@@ -1278,3 +1254,103 @@ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space)
return fputs(s, f);
}
+
+int open_tmpfile_unlinkable(const char *directory, int flags) {
+ char *p;
+ int fd;
+
+ assert(directory);
+
+ /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
+
+#ifdef O_TMPFILE
+ /* Try O_TMPFILE first, if it is supported */
+ fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
+ if (fd >= 0)
+ return fd;
+#endif
+
+ /* Fall back to unguessable name + unlinking */
+ p = strjoina(directory, "/systemd-tmp-XXXXXX");
+
+ fd = mkostemp_safe(p, flags);
+ if (fd < 0)
+ return fd;
+
+ (void) unlink(p);
+
+ return fd;
+}
+
+int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
+ _cleanup_free_ char *tmp = NULL;
+ int r, fd;
+
+ assert(target);
+ assert(ret_path);
+
+ /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
+ assert((flags & O_EXCL) == 0);
+
+ /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
+ * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
+ * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
+
+#ifdef O_TMPFILE
+ {
+ _cleanup_free_ char *dn = NULL;
+
+ dn = dirname_malloc(target);
+ if (!dn)
+ return -ENOMEM;
+
+ fd = open(dn, O_TMPFILE|flags, 0640);
+ if (fd >= 0) {
+ *ret_path = NULL;
+ return fd;
+ }
+
+ log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn);
+ }
+#endif
+
+ r = tempfn_random(target, NULL, &tmp);
+ if (r < 0)
+ return r;
+
+ fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640);
+ if (fd < 0)
+ return -errno;
+
+ *ret_path = tmp;
+ tmp = NULL;
+
+ return fd;
+}
+
+int link_tmpfile(int fd, const char *path, const char *target) {
+
+ assert(fd >= 0);
+ assert(target);
+
+ /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
+ * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
+ * on the directory, and renameat2() is used instead.
+ *
+ * Note that in both cases we will not replace existing files. This is because linkat() dos not support this
+ * operation currently (renameat2() does), and there is no nice way to emulate this. */
+
+ if (path) {
+ if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0)
+ return -errno;
+ } else {
+ char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
+
+ xsprintf(proc_fd_path, "/proc/self/fd/%i", fd);
+
+ if (linkat(AT_FDCWD, proc_fd_path, AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0)
+ return -errno;
+ }
+
+ return 0;
+}
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index 8084895ff3..58dbc80c24 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -72,7 +72,6 @@ int fflush_and_check(FILE *f);
int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
int mkostemp_safe(char *pattern, int flags);
-int open_tmpfile(const char *path, int flags);
int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
int tempfn_random(const char *p, const char *extra, char **ret);
@@ -82,3 +81,8 @@ int write_timestamp_file_atomic(const char *fn, usec_t n);
int read_timestamp_file(const char *fn, usec_t *ret);
int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space);
+
+int open_tmpfile_unlinkable(const char *directory, int flags);
+int open_tmpfile_linkable(const char *target, int flags, char **ret_path);
+
+int link_tmpfile(int fd, const char *path, const char *target);
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index 51268828af..e24e7036f7 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -38,6 +38,7 @@
#include "mkdir.h"
#include "parse-util.h"
#include "path-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
@@ -493,3 +494,17 @@ int get_files_in_directory(const char *path, char ***list) {
return n;
}
+
+int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
+ char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
+ int r;
+
+ /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
+ xsprintf(path, "/proc/self/fd/%i", what);
+
+ r = inotify_add_watch(fd, path, mask);
+ if (r < 0)
+ return -errno;
+
+ return r;
+}
diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
index 0d23f8635f..517b599d6f 100644
--- a/src/basic/fs-util.h
+++ b/src/basic/fs-util.h
@@ -72,3 +72,5 @@ union inotify_event_buffer {
struct inotify_event ev;
uint8_t raw[INOTIFY_EVENT_MAX];
};
+
+int inotify_add_watch_fd(int fd, int what, uint32_t mask);
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 6a49ccd281..b389e94cf7 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -445,6 +445,10 @@ struct btrfs_ioctl_quota_ctl_args {
#define TMPFS_MAGIC 0x01021994
#endif
+#ifndef MQUEUE_MAGIC
+#define MQUEUE_MAGIC 0x19800202
+#endif
+
#ifndef MS_MOVE
#define MS_MOVE 8192
#endif
@@ -828,6 +832,10 @@ struct btrfs_ioctl_quota_ctl_args {
#define IPV6_UNICAST_IF 76
#endif
+#ifndef IPV6_MIN_MTU
+#define IPV6_MIN_MTU 1280
+#endif
+
#ifndef IFF_MULTI_QUEUE
#define IFF_MULTI_QUEUE 0x100
#endif
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index 5faa2eba05..ba698959b7 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -498,7 +498,9 @@ bool fstype_is_network(const char *fstype) {
"nfs4\0"
"gfs\0"
"gfs2\0"
- "glusterfs\0";
+ "glusterfs\0"
+ "pvfs2\0" /* OrangeFS */
+ ;
const char *x;
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
index c407263e16..7dc579a159 100644
--- a/src/basic/parse-util.h
+++ b/src/basic/parse-util.h
@@ -93,7 +93,7 @@ static inline int safe_atoli(const char *s, long int *ret_u) {
#if SIZE_MAX == UINT_MAX
static inline int safe_atozu(const char *s, size_t *ret_u) {
assert_cc(sizeof(size_t) == sizeof(unsigned));
- return safe_atou(s, ret_u);
+ return safe_atou(s, (unsigned *) ret_u);
}
#else
static inline int safe_atozu(const char *s, size_t *ret_u) {
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index 044a12889d..100e3f5af2 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -756,34 +756,37 @@ char *file_in_same_dir(const char *path, const char *filename) {
return ret;
}
-bool hidden_file_allow_backup(const char *filename) {
- assert(filename);
-
- return
- filename[0] == '.' ||
- streq(filename, "lost+found") ||
- streq(filename, "aquota.user") ||
- streq(filename, "aquota.group") ||
- endswith(filename, ".rpmnew") ||
- endswith(filename, ".rpmsave") ||
- endswith(filename, ".rpmorig") ||
- endswith(filename, ".dpkg-old") ||
- endswith(filename, ".dpkg-new") ||
- endswith(filename, ".dpkg-tmp") ||
- endswith(filename, ".dpkg-dist") ||
- endswith(filename, ".dpkg-bak") ||
- endswith(filename, ".dpkg-backup") ||
- endswith(filename, ".dpkg-remove") ||
- endswith(filename, ".swp");
-}
+bool hidden_or_backup_file(const char *filename) {
+ const char *p;
-bool hidden_file(const char *filename) {
assert(filename);
- if (endswith(filename, "~"))
+ if (filename[0] == '.' ||
+ streq(filename, "lost+found") ||
+ streq(filename, "aquota.user") ||
+ streq(filename, "aquota.group") ||
+ endswith(filename, "~"))
return true;
- return hidden_file_allow_backup(filename);
+ p = strrchr(filename, '.');
+ if (!p)
+ return false;
+
+ return STR_IN_SET(p + 1,
+ "rpmnew",
+ "rpmsave",
+ "rpmorig",
+ "dpkg-old",
+ "dpkg-new",
+ "dpkg-tmp",
+ "dpkg-dist",
+ "dpkg-bak",
+ "dpkg-backup",
+ "dpkg-remove",
+ "ucf-new",
+ "ucf-old",
+ "ucf-dist",
+ "swp");
}
bool is_device_path(const char *path) {
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
index 34d5cd1570..a27c13fcc3 100644
--- a/src/basic/path-util.h
+++ b/src/basic/path-util.h
@@ -122,7 +122,6 @@ bool path_is_safe(const char *p) _pure_;
char *file_in_same_dir(const char *path, const char *filename);
-bool hidden_file_allow_backup(const char *filename);
-bool hidden_file(const char *filename) _pure_;
+bool hidden_or_backup_file(const char *filename) _pure_;
bool is_device_path(const char *path);
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index ae3f6109ad..f2cea01979 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -731,6 +731,18 @@ void valgrind_summary_hack(void) {
#endif
}
+int pid_compare_func(const void *a, const void *b) {
+ const pid_t *p = a, *q = b;
+
+ /* Suitable for usage in qsort() */
+
+ if (*p < *q)
+ return -1;
+ if (*p > *q)
+ return 1;
+ return 0;
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index f5d193e762..ffd4bcb0ff 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -101,3 +101,5 @@ int sched_policy_from_string(const char *s);
#define PID_TO_PTR(p) ((void*) ((uintptr_t) p))
void valgrind_summary_hack(void);
+
+int pid_compare_func(const void *a, const void *b);
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index 0a9d2bbdef..9521b79daa 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -1135,14 +1135,19 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
}
bool colors_enabled(void) {
- const char *colors;
+ static int enabled = -1;
- colors = getenv("SYSTEMD_COLORS");
- if (!colors) {
- if (streq_ptr(getenv("TERM"), "dumb"))
- return false;
- return on_tty();
+ if (_unlikely_(enabled < 0)) {
+ const char *colors;
+
+ colors = getenv("SYSTEMD_COLORS");
+ if (colors)
+ enabled = parse_boolean(colors) != 0;
+ else if (streq_ptr(getenv("TERM"), "dumb"))
+ enabled = false;
+ else
+ enabled = on_tty();
}
- return parse_boolean(colors) != 0;
+ return enabled;
}
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index 7ca764abeb..edd9179cb8 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -1080,22 +1080,31 @@ bool timezone_is_valid(const char *name) {
return true;
}
-clockid_t clock_boottime_or_monotonic(void) {
- static clockid_t clock = -1;
- int fd;
-
- if (clock != -1)
- return clock;
-
- fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
- if (fd < 0)
- clock = CLOCK_MONOTONIC;
- else {
- safe_close(fd);
- clock = CLOCK_BOOTTIME;
+bool clock_boottime_supported(void) {
+ static int supported = -1;
+
+ /* Note that this checks whether CLOCK_BOOTTIME is available in general as well as available for timerfds()! */
+
+ if (supported < 0) {
+ int fd;
+
+ fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
+ if (fd < 0)
+ supported = false;
+ else {
+ safe_close(fd);
+ supported = true;
+ }
}
- return clock;
+ return supported;
+}
+
+clockid_t clock_boottime_or_monotonic(void) {
+ if (clock_boottime_supported())
+ return CLOCK_BOOTTIME;
+ else
+ return CLOCK_MONOTONIC;
}
int get_timezone(char **tz) {
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
index 77e3cd08d4..a5e3f567ec 100644
--- a/src/basic/time-util.h
+++ b/src/basic/time-util.h
@@ -112,6 +112,7 @@ bool ntp_synced(void);
int get_timezones(char ***l);
bool timezone_is_valid(const char *name);
+bool clock_boottime_supported(void);
clockid_t clock_boottime_or_monotonic(void);
#define xstrftime(buf, fmt, tm) \
diff --git a/src/basic/user-util.h b/src/basic/user-util.h
index c23f1d485d..8026eca3f4 100644
--- a/src/basic/user-util.h
+++ b/src/basic/user-util.h
@@ -21,6 +21,7 @@
#include <stdbool.h>
#include <sys/types.h>
+#include <unistd.h>
bool uid_is_valid(uid_t uid);
@@ -63,3 +64,7 @@ int take_etc_passwd_lock(const char *root);
#define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1))
#define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
+
+static inline bool userns_supported(void) {
+ return access("/proc/self/uid_map", F_OK) >= 0;
+}
diff --git a/src/basic/util.c b/src/basic/util.c
index b70c50047f..756c663be4 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -522,7 +522,7 @@ int on_ac_power(void) {
if (!de)
break;
- if (hidden_file(de->d_name))
+ if (hidden_or_backup_file(de->d_name))
continue;
device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);