代码拉取完成,页面将自动刷新
同步操作将从 src-anolis-os/systemd 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From 054669a4cc4897792b6c209fd55ab1fc1d7b9bd5 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 17 Jul 2020 12:26:01 +0200
Subject: [PATCH] fileio: add support for read_full_file() on AF_UNIX stream
sockets
Optionally, teach read_full_file() the ability to connect to an AF_UNIX
socket if the specified path points to one.
(cherry picked from commit 412b888ec803cdf96fb1d005bb245d20abdb8f2e)
[Guorui Yu: Adds sockaddr_un_set_path function to socket-util.{c,h}]
Signed-off-by: Guorui Yu <GuoRui.Yu@linux.alibaba.com>
---
src/basic/fileio.c | 62 +++++++++++++++++++++++++++++++++++------
src/basic/fileio.h | 1 +
src/basic/socket-util.c | 42 ++++++++++++++++++++++++++++
src/basic/socket-util.h | 1 +
src/test/test-fileio.c | 50 +++++++++++++++++++++++++++++++++
5 files changed, 147 insertions(+), 9 deletions(-)
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index d7da834a74..9cb0a2bd28 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -27,6 +27,7 @@
#include "missing.h"
#include "parse-util.h"
#include "path-util.h"
+#include "socket-util.h"
#include "process-util.h"
#include "random-util.h"
#include "stdio-util.h"
@@ -450,21 +451,18 @@ int read_full_stream_full(
errno = 0;
k = fread(buf + l, 1, n - l, f);
- if (k > 0)
- l += k;
+
+ assert(k <= n - l);
+ l += k;
if (ferror(f)) {
r = errno > 0 ? -errno : -EIO;
goto finalize;
}
-
if (feof(f))
break;
- /* We aren't expecting fread() to return a short read outside
- * of (error && eof), assert buffer is full and enlarge buffer.
- */
- assert(l == n);
+ assert(k > 0); /* we can't have read zero bytes because that would have been EOF */
/* Safety check */
if (n >= READ_FULL_BYTES_MAX) {
@@ -584,8 +582,54 @@ int read_full_file_full(int dir_fd, const char *filename, ReadFullFileFlags flag
assert(contents);
r = xfopenat(dir_fd, filename, "re", 0, &f);
- if (r < 0)
- return r;
+ if (r < 0) {
+ _cleanup_close_ int dfd = -1, sk = -1;
+ union sockaddr_union sa;
+
+ /* ENXIO is what Linux returns if we open a node that is an AF_UNIX socket */
+ if (r != -ENXIO)
+ return r;
+
+ /* If this is enabled, let's try to connect to it */
+ if (!FLAGS_SET(flags, READ_FULL_FILE_CONNECT_SOCKET))
+ return -ENXIO;
+
+ if (dir_fd == AT_FDCWD)
+ r = sockaddr_un_set_path(&sa.un, filename);
+ else {
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+
+ /* If we shall operate relative to some directory, then let's use O_PATH first to
+ * open the socket inode, and then connect to it via /proc/self/fd/. We have to do
+ * this since there's not connectat() that takes a directory fd as first arg. */
+
+ dfd = openat(dir_fd, filename, O_PATH|O_CLOEXEC);
+ if (dfd < 0)
+ return -errno;
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", dfd);
+ r = sockaddr_un_set_path(&sa.un, procfs_path);
+ }
+ if (r < 0)
+ return r;
+
+ sk = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
+ if (sk < 0)
+ return -errno;
+
+ if (connect(sk, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
+ return errno == ENOTSOCK ? -ENXIO : -errno; /* propagate original error if this is
+ * not a socket after all */
+
+ if (shutdown(sk, SHUT_WR) < 0)
+ return -errno;
+
+ f = fdopen(sk, "r");
+ if (!f)
+ return -errno;
+
+ TAKE_FD(sk);
+ }
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index 916ddc5e47..1a16e0fd13 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -29,6 +29,7 @@ typedef enum {
typedef enum {
READ_FULL_FILE_SECURE = 1 << 0,
READ_FULL_FILE_WARN_WORLD_READABLE = 1 << 3,
+ READ_FULL_FILE_CONNECT_SOCKET = 1 << 4,
} ReadFullFileFlags;
int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts);
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 7f8066123b..427c8b89bb 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -1253,6 +1253,48 @@ int socket_ioctl_fd(void) {
return fd;
}
+int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) {
+ size_t l;
+
+ assert(ret);
+ assert(path);
+
+ /* Initialize ret->sun_path from the specified argument. This will interpret paths starting with '@' as
+ * abstract namespace sockets, and those starting with '/' as regular filesystem sockets. It won't accept
+ * anything else (i.e. no relative paths), to avoid ambiguities. Note that this function cannot be used to
+ * reference paths in the abstract namespace that include NUL bytes in the name. */
+
+ l = strlen(path);
+ if (l < 2)
+ return -EINVAL;
+ if (!IN_SET(path[0], '/', '@'))
+ return -EINVAL;
+
+ /* Don't allow paths larger than the space in sockaddr_un. Note that we are a tiny bit more restrictive than
+ * the kernel is: we insist on NUL termination (both for abstract namespace and regular file system socket
+ * addresses!), which the kernel doesn't. We do this to reduce chance of incompatibility with other apps that
+ * do not expect non-NUL terminated file system path*/
+ if (l+1 > sizeof(ret->sun_path))
+ return -EINVAL;
+
+ *ret = (struct sockaddr_un) {
+ .sun_family = AF_UNIX,
+ };
+
+ if (path[0] == '@') {
+ /* Abstract namespace socket */
+ memcpy(ret->sun_path + 1, path + 1, l); /* copy *with* trailing NUL byte */
+ return (int) (offsetof(struct sockaddr_un, sun_path) + l); /* 🔥 *don't* 🔥 include trailing NUL in size */
+
+ } else {
+ assert(path[0] == '/');
+
+ /* File system socket */
+ memcpy(ret->sun_path, path, l + 1); /* copy *with* trailing NUL byte */
+ return (int) (offsetof(struct sockaddr_un, sun_path) + l + 1); /* include trailing NUL in size */
+ }
+}
+
int socket_pass_pktinfo(int fd, bool b) {
int af;
socklen_t sl = sizeof(af);
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 30baba6c03..36edc58caf 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -186,6 +186,7 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
})
int socket_ioctl_fd(void);
+int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path);
static inline int setsockopt_int(int fd, int level, int optname, int value) {
if (setsockopt(fd, level, optname, &value, sizeof(value)) < 0)
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 14ba075144..82b7cb1242 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -14,6 +14,8 @@
#include "io-util.h"
#include "parse-util.h"
#include "process-util.h"
+#include "rm-rf.h"
+#include "socket-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
@@ -709,6 +711,53 @@ static void test_read_line3(void) {
assert_se(read_line(f, LINE_MAX, NULL) == 0);
}
+static void test_read_full_file_socket(void) {
+ _cleanup_(rm_rf_physical_and_freep) char *z = NULL;
+ _cleanup_close_ int listener = -1;
+ _cleanup_free_ char *data = NULL;
+ union sockaddr_union sa;
+ const char *j;
+ size_t size;
+ pid_t pid;
+ int r;
+
+ log_info("/* %s */", __func__);
+
+ listener = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
+ assert_se(listener >= 0);
+
+ assert_se(mkdtemp_malloc(NULL, &z) >= 0);
+ j = strjoina(z, "/socket");
+
+ assert_se(sockaddr_un_set_path(&sa.un, j) >= 0);
+
+ assert_se(bind(listener, &sa.sa, SOCKADDR_UN_LEN(sa.un)) >= 0);
+ assert_se(listen(listener, 1) >= 0);
+
+ r = safe_fork("(server)", FORK_DEATHSIG|FORK_LOG, &pid);
+ assert_se(r >= 0);
+ if (r == 0) {
+ _cleanup_close_ int rfd = -1;
+ /* child */
+
+ rfd = accept4(listener, NULL, 0, SOCK_CLOEXEC);
+ assert_se(rfd >= 0);
+
+#define TEST_STR "This is a test\nreally."
+
+ assert_se(write(rfd, TEST_STR, strlen(TEST_STR)) == strlen(TEST_STR));
+ _exit(EXIT_SUCCESS);
+ }
+
+ assert_se(read_full_file_full(AT_FDCWD, j, 0, &data, &size) == -ENXIO);
+ assert_se(read_full_file_full(AT_FDCWD, j, READ_FULL_FILE_CONNECT_SOCKET, &data, &size) >= 0);
+ assert_se(size == strlen(TEST_STR));
+ assert_se(streq(data, TEST_STR));
+
+ assert_se(wait_for_terminate_and_check("(server)", pid, WAIT_LOG) >= 0);
+#undef TEST_STR
+}
+
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
log_parse_environment();
@@ -733,6 +782,7 @@ int main(int argc, char *argv[]) {
test_read_line();
test_read_line2();
test_read_line3();
+ test_read_full_file_socket();
return 0;
}
--
2.39.1
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。