1 Star 0 Fork 49

李双全/systemd

forked from src-anolis-os/systemd 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
10024-fileio-teach-read_full_file_full-to-read-from-offse.patch 10.52 KB
一键复制 编辑 原始数据 按行查看 历史
From 5be0e8a2c3e683c195fd872979d6e5741c80d13f Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 4 Nov 2020 20:25:06 +0100
Subject: [PATCH] fileio: teach read_full_file_full() to read from offset/with
maximum size
(cherry picked from commit 7399b3f8083b65db4cb9acb17e4b5c897ba7946d)
Signed-off-by: Guorui Yu <GuoRui.Yu@linux.alibaba.com>
---
src/basic/fileio.c | 60 ++++++++++++++++++++++++++++++------------
src/basic/fileio.h | 12 ++++-----
src/test/test-fileio.c | 49 ++++++++++++++++++++++++++++++++--
3 files changed, 96 insertions(+), 25 deletions(-)
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 35eaa3c1c7..c14f9797bd 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -388,44 +388,58 @@ int read_full_virtual_file(const char *filename, char **ret_contents, size_t *re
int read_full_stream_full(
FILE *f,
const char *filename,
+ uint64_t offset,
+ size_t size,
ReadFullFileFlags flags,
char **ret_contents,
size_t *ret_size) {
_cleanup_free_ char *buf = NULL;
- struct stat st;
size_t n, n_next, l;
int fd, r;
assert(f);
assert(ret_contents);
- n_next = LINE_MAX; /* Start size */
+ if (offset != UINT64_MAX && offset > LONG_MAX)
+ return -ERANGE;
+
+ n_next = size != SIZE_MAX ? size : LINE_MAX; /* Start size */
fd = fileno(f);
- if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see fmemopen(), let's
- * optimize our buffering) */
+ if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see
+ * fmemopen()), let's optimize our buffering */
+ struct stat st;
if (fstat(fd, &st) < 0)
return -errno;
if (S_ISREG(st.st_mode)) {
-
- /* Safety check */
- if (st.st_size > READ_FULL_BYTES_MAX)
- return -E2BIG;
-
- /* Start with the right file size. Note that we increase the size
- * to read here by one, so that the first read attempt already
- * makes us notice the EOF. */
- if (st.st_size > 0)
- n_next = st.st_size + 1;
+ if (size == SIZE_MAX) {
+ uint64_t rsize =
+ LESS_BY((uint64_t) st.st_size, offset == UINT64_MAX ? 0 : offset);
+
+ /* Safety check */
+ if (rsize > READ_FULL_BYTES_MAX)
+ return -E2BIG;
+
+ /* Start with the right file size. Note that we increase the size to read
+ * here by one, so that the first read attempt already makes us notice the
+ * EOF. If the reported size of the file is zero, we avoid this logic
+ * however, since quite likely it might be a virtual file in procfs that all
+ * report a zero file size. */
+ if (st.st_size > 0)
+ n_next = rsize + 1;
+ }
if (flags & READ_FULL_FILE_WARN_WORLD_READABLE)
(void) warn_file_is_world_accessible(filename, &st, NULL, 0);
}
}
+ if (offset != UINT64_MAX && fseek(f, offset, SEEK_SET) < 0)
+ return -errno;
+
n = l = 0;
for (;;) {
char *t;
@@ -462,6 +476,11 @@ int read_full_stream_full(
if (feof(f))
break;
+ if (size != SIZE_MAX) { /* If we got asked to read some specific size, we already sized the buffer right, hence leave */
+ assert(l == size);
+ break;
+ }
+
assert(k > 0); /* we can't have read zero bytes because that would have been EOF */
/* Safety check */
@@ -577,15 +596,18 @@ static int xfopenat(int dir_fd, const char *path, const char *mode, int flags, F
int read_full_file_full(
int dir_fd,
const char *filename,
+ uint64_t offset,
+ size_t size,
ReadFullFileFlags flags,
const char *bind_name,
- char **contents, size_t *size) {
+ char **ret_contents,
+ size_t *ret_size) {
_cleanup_fclose_ FILE *f = NULL;
int r;
assert(filename);
- assert(contents);
+ assert(ret_contents);
r = xfopenat(dir_fd, filename, "re", 0, &f);
if (r < 0) {
@@ -600,6 +622,10 @@ int read_full_file_full(
if (!FLAGS_SET(flags, READ_FULL_FILE_CONNECT_SOCKET))
return -ENXIO;
+ /* Seeking is not supported on AF_UNIX sockets */
+ if (offset != UINT64_MAX)
+ return -ESPIPE;
+
if (dir_fd == AT_FDCWD)
r = sockaddr_un_set_path(&sa.un, filename);
else {
@@ -653,7 +679,7 @@ int read_full_file_full(
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
- return read_full_stream_full(f, filename, flags, contents, size);
+ return read_full_stream_full(f, filename, offset, size, flags, ret_contents, ret_size);
}
static int parse_env_file_internal(
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index 82897e209c..03150ce776 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -44,13 +44,13 @@ static inline int write_string_file(const char *fn, const char *line, WriteStrin
int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4);
int read_one_line_file(const char *filename, char **line);
-int read_full_file_full(int dir_fd, const char *filename, ReadFullFileFlags flags, const char *bind_name, char **contents, size_t *size);
-static inline int read_full_file(const char *filename, char **contents, size_t *size) {
- return read_full_file_full(AT_FDCWD, filename, 0, NULL, contents, size);
+int read_full_file_full(int dir_fd, const char *filename, uint64_t offset, size_t size, ReadFullFileFlags flags, const char *bind_name, char **ret_contents, size_t *ret_size);
+static inline int read_full_file(const char *filename, char **ret_contents, size_t *ret_size) {
+ return read_full_file_full(AT_FDCWD, filename, UINT64_MAX, SIZE_MAX, 0, NULL, ret_contents, ret_size);
}
-int read_full_stream_full(FILE *f, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size);
-static inline int read_full_stream(FILE *f, char **contents, size_t *size) {
- return read_full_stream_full(f, NULL, 0, contents, size);
+int read_full_stream_full(FILE *f, const char *filename, uint64_t offset, size_t size, ReadFullFileFlags flags, char **ret_contents, size_t *ret_size);
+static inline int read_full_stream(FILE *f, char **ret_contents, size_t *ret_size) {
+ return read_full_stream_full(f, NULL, UINT64_MAX, SIZE_MAX, 0, ret_contents, ret_size);
}
int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size);
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index 5ec70eec14..5d0006149b 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -762,8 +762,8 @@ static void test_read_full_file_socket(void) {
_exit(EXIT_SUCCESS);
}
- assert_se(read_full_file_full(AT_FDCWD, j, 0, NULL, &data, &size) == -ENXIO);
- assert_se(read_full_file_full(AT_FDCWD, j, READ_FULL_FILE_CONNECT_SOCKET, clientname, &data, &size) >= 0);
+ assert_se(read_full_file_full(AT_FDCWD, j, UINT64_MAX, SIZE_MAX, 0, NULL, &data, &size) == -ENXIO);
+ assert_se(read_full_file_full(AT_FDCWD, j, UINT64_MAX, SIZE_MAX, READ_FULL_FILE_CONNECT_SOCKET, clientname, &data, &size) >= 0);
assert_se(size == strlen(TEST_STR));
assert_se(streq(data, TEST_STR));
@@ -771,6 +771,50 @@ static void test_read_full_file_socket(void) {
#undef TEST_STR
}
+static void test_read_full_file_offset_size(void) {
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_(unlink_and_freep) char *fn = NULL;
+ _cleanup_free_ char *rbuf = NULL;
+ size_t rbuf_size;
+ uint8_t buf[4711];
+
+ random_bytes(buf, sizeof(buf));
+
+ assert_se(tempfn_random_child(NULL, NULL, &fn) >= 0);
+ assert_se(f = fopen(fn, "we"));
+ assert_se(fwrite(buf, 1, sizeof(buf), f) == sizeof(buf));
+ assert_se(fflush_and_check(f) >= 0);
+
+ assert_se(read_full_file_full(AT_FDCWD, fn, UINT64_MAX, SIZE_MAX, 0, NULL, &rbuf, &rbuf_size) >= 0);
+ assert_se(rbuf_size == sizeof(buf));
+ assert_se(memcmp(buf, rbuf, rbuf_size) == 0);
+ rbuf = mfree(rbuf);
+
+ assert_se(read_full_file_full(AT_FDCWD, fn, UINT64_MAX, 128, 0, NULL, &rbuf, &rbuf_size) >= 0);
+ assert_se(rbuf_size == 128);
+ assert_se(memcmp(buf, rbuf, rbuf_size) == 0);
+ rbuf = mfree(rbuf);
+
+ assert_se(read_full_file_full(AT_FDCWD, fn, 1234, SIZE_MAX, 0, NULL, &rbuf, &rbuf_size) >= 0);
+ assert_se(rbuf_size == sizeof(buf) - 1234);
+ assert_se(memcmp(buf + 1234, rbuf, rbuf_size) == 0);
+ rbuf = mfree(rbuf);
+
+ assert_se(read_full_file_full(AT_FDCWD, fn, 2345, 777, 0, NULL, &rbuf, &rbuf_size) >= 0);
+ assert_se(rbuf_size == 777);
+ assert_se(memcmp(buf + 2345, rbuf, rbuf_size) == 0);
+ rbuf = mfree(rbuf);
+
+ assert_se(read_full_file_full(AT_FDCWD, fn, 4700, 20, 0, NULL, &rbuf, &rbuf_size) >= 0);
+ assert_se(rbuf_size == 11);
+ assert_se(memcmp(buf + 4700, rbuf, rbuf_size) == 0);
+ rbuf = mfree(rbuf);
+
+ assert_se(read_full_file_full(AT_FDCWD, fn, 10000, 99, 0, NULL, &rbuf, &rbuf_size) >= 0);
+ assert_se(rbuf_size == 0);
+ rbuf = mfree(rbuf);
+}
+
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
log_parse_environment();
@@ -796,6 +840,7 @@ int main(int argc, char *argv[]) {
test_read_line2();
test_read_line3();
test_read_full_file_socket();
+ test_read_full_file_offset_size();
return 0;
}
--
2.39.1
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/shqli/systemd.git
git@gitee.com:shqli/systemd.git
shqli
systemd
systemd
a8

搜索帮助

0d507c66 1850385 C8b1a773 1850385