#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
-#include "io-util.h"
+#include "iovec-util.h"
+#include "memfd-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
STRV_FOREACH(i, a)
log_info("Got: <%s>", *i);
- assert_se(streq_ptr(a[0], "one=BAR"));
- assert_se(streq_ptr(a[1], "two=bar"));
- assert_se(streq_ptr(a[2], "three=333\nxxxx"));
- assert_se(streq_ptr(a[3], "four=44\\\"44"));
- assert_se(streq_ptr(a[4], "five=55\"55FIVEcinco"));
- assert_se(streq_ptr(a[5], "six=seis sechs sis"));
- assert_se(streq_ptr(a[6], "seven=sevenval#nocomment"));
- assert_se(streq_ptr(a[7], "eight=eightval #nocomment"));
- assert_se(streq_ptr(a[8], "export nine=nineval"));
- assert_se(streq_ptr(a[9], "ten="));
- assert_se(streq_ptr(a[10], "eleven=value"));
- assert_se(streq_ptr(a[11], "twelve=\\value"));
- assert_se(streq_ptr(a[12], "thirteen=\\value"));
- assert_se(a[13] == NULL);
+ ASSERT_STREQ(a[0], "one=BAR");
+ ASSERT_STREQ(a[1], "two=bar");
+ ASSERT_STREQ(a[2], "three=333\nxxxx");
+ ASSERT_STREQ(a[3], "four=44\\\"44");
+ ASSERT_STREQ(a[4], "five=55\"55FIVEcinco");
+ ASSERT_STREQ(a[5], "six=seis sechs sis");
+ ASSERT_STREQ(a[6], "seven=sevenval#nocomment");
+ ASSERT_STREQ(a[7], "eight=eightval #nocomment");
+ ASSERT_STREQ(a[8], "export nine=nineval");
+ ASSERT_STREQ(a[9], "ten=");
+ ASSERT_STREQ(a[10], "eleven=value");
+ ASSERT_STREQ(a[11], "twelve=\\value");
+ ASSERT_STREQ(a[12], "thirteen=\\value");
+ ASSERT_NULL(a[13]);
strv_env_clean(a);
k = 0;
STRV_FOREACH(i, b) {
log_info("Got2: <%s>", *i);
- assert_se(streq(*i, a[k++]));
+ ASSERT_STREQ(*i, a[k++]);
}
r = parse_env_file(
log_info("twelve=[%s]", strna(twelve));
log_info("thirteen=[%s]", strna(thirteen));
- assert_se(streq(one, "BAR"));
- assert_se(streq(two, "bar"));
- assert_se(streq(three, "333\nxxxx"));
- assert_se(streq(four, "44\\\"44"));
- assert_se(streq(five, "55\"55FIVEcinco"));
- assert_se(streq(six, "seis sechs sis"));
- assert_se(streq(seven, "sevenval#nocomment"));
- assert_se(streq(eight, "eightval #nocomment"));
- assert_se(streq(nine, "nineval"));
- assert_se(ten == NULL);
- assert_se(streq(eleven, "value"));
- assert_se(streq(twelve, "\\value"));
- assert_se(streq(thirteen, "\\value"));
+ ASSERT_STREQ(one, "BAR");
+ ASSERT_STREQ(two, "bar");
+ ASSERT_STREQ(three, "333\nxxxx");
+ ASSERT_STREQ(four, "44\\\"44");
+ ASSERT_STREQ(five, "55\"55FIVEcinco");
+ ASSERT_STREQ(six, "seis sechs sis");
+ ASSERT_STREQ(seven, "sevenval#nocomment");
+ ASSERT_STREQ(eight, "eightval #nocomment");
+ ASSERT_STREQ(nine, "nineval");
+ ASSERT_NULL(ten);
+ ASSERT_STREQ(eleven, "value");
+ ASSERT_STREQ(twelve, "\\value");
+ ASSERT_STREQ(thirteen, "\\value");
{
/* prepare a temporary file to write the environment to */
assert_se(fd >= 0);
}
- r = write_env_file(p, a);
+ r = write_env_file(AT_FDCWD, p, NULL, a);
assert_se(r >= 0);
r = load_env_file(NULL, p, &b);
assert_se(f = popen(cmd, "re"));
assert_se(read_full_stream(f, &from_shell, &sz) >= 0);
assert_se(sz == strlen(value));
- assert_se(streq(from_shell, value));
+ ASSERT_STREQ(from_shell, value);
}
TEST(parse_multiline_env_file) {
STRV_FOREACH(i, a)
log_info("Got: <%s>", *i);
- assert_se(streq_ptr(a[0], "one=BAR VAR\tGAR"));
- assert_se(streq_ptr(a[1], "two=bar var\tgar"));
- assert_se(streq_ptr(a[2], "tri=bar var \tgar "));
- assert_se(a[3] == NULL);
+ ASSERT_STREQ(a[0], "one=BAR VAR\tGAR");
+ ASSERT_STREQ(a[1], "two=bar var\tgar");
+ ASSERT_STREQ(a[2], "tri=bar var \tgar ");
+ ASSERT_NULL(a[3]);
{
_cleanup_close_ int fd = mkostemp_safe(p);
assert_se(fd >= 0);
}
- r = write_env_file(p, a);
+ r = write_env_file(AT_FDCWD, p, NULL, a);
assert_se(r >= 0);
r = load_env_file(NULL, p, &b);
STRV_FOREACH(i, a)
log_info("Got: <%s>", *i);
- assert_se(streq(a[0], "one=2"));
- assert_se(streq(a[1], "twelve=12"));
- assert_se(streq(a[2], "twentyone=21"));
- assert_se(streq(a[3], "twentytwo=22"));
- assert_se(streq(a[4], "xxx=0x222"));
- assert_se(streq(a[5], "xxx_minus_three= - 3"));
- assert_se(streq(a[6], "yyy=2"));
- assert_se(streq(a[7], "zzz=replacement"));
- assert_se(streq(a[8], "zzzz="));
- assert_se(streq(a[9], "zzzzz="));
- assert_se(a[10] == NULL);
+ ASSERT_STREQ(a[0], "one=2");
+ ASSERT_STREQ(a[1], "twelve=12");
+ ASSERT_STREQ(a[2], "twentyone=21");
+ ASSERT_STREQ(a[3], "twentytwo=22");
+ ASSERT_STREQ(a[4], "xxx=0x222");
+ ASSERT_STREQ(a[5], "xxx_minus_three= - 3");
+ ASSERT_STREQ(a[6], "yyy=2");
+ ASSERT_STREQ(a[7], "zzz=replacement");
+ ASSERT_STREQ(a[8], "zzzz=");
+ ASSERT_STREQ(a[9], "zzzzz=");
+ ASSERT_NULL(a[10]);
r = merge_env_file(&a, NULL, t);
assert_se(r >= 0);
STRV_FOREACH(i, a)
log_info("Got2: <%s>", *i);
- assert_se(streq(a[0], "one=2"));
- assert_se(streq(a[1], "twelve=12"));
- assert_se(streq(a[2], "twentyone=21"));
- assert_se(streq(a[3], "twentytwo=22"));
- assert_se(streq(a[4], "xxx=0x222"));
- assert_se(streq(a[5], "xxx_minus_three=0x222 - 3"));
- assert_se(streq(a[6], "yyy=2"));
- assert_se(streq(a[7], "zzz=replacement"));
- assert_se(streq(a[8], "zzzz="));
- assert_se(streq(a[9], "zzzzz="));
- assert_se(a[10] == NULL);
+ ASSERT_STREQ(a[0], "one=2");
+ ASSERT_STREQ(a[1], "twelve=12");
+ ASSERT_STREQ(a[2], "twentyone=21");
+ ASSERT_STREQ(a[3], "twentytwo=22");
+ ASSERT_STREQ(a[4], "xxx=0x222");
+ ASSERT_STREQ(a[5], "xxx_minus_three=0x222 - 3");
+ ASSERT_STREQ(a[6], "yyy=2");
+ ASSERT_STREQ(a[7], "zzz=replacement");
+ ASSERT_STREQ(a[8], "zzzz=");
+ ASSERT_STREQ(a[9], "zzzzz=");
+ ASSERT_NULL(a[10]);
}
TEST(merge_env_file_invalid) {
r = executable_is_script(t, &command);
assert_se(r > 0);
- assert_se(streq(command, "/bin/script"));
+ ASSERT_STREQ(command, "/bin/script");
free(command);
r = executable_is_script("/bin/sh", &command);
assert_se(r == 0);
r = executable_is_script("/usr/bin/yum", &command);
- assert_se(r > 0 || r == -ENOENT);
if (r > 0) {
assert_se(startswith(command, "/"));
free(command);
}
TEST(status_field) {
- _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL;
+ _cleanup_free_ char *p = NULL, *s = NULL, *z = NULL;
unsigned long long total = 0, buffers = 0;
int r;
- assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0);
- puts(t);
- assert_se(streq(t, "1"));
-
r = get_proc_field("/proc/meminfo", "MemTotal", WHITESPACE, &p);
if (r != -ENOENT) {
assert_se(r == 0);
}
}
+TEST(read_one_line_file) {
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-fileio-1lf-XXXXXX";
+ int fd;
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *buf, *buf2, *buf3, *buf4, *buf5;
+
+ fd = mkostemp_safe(fn);
+ assert_se(fd >= 0);
+
+ f = fdopen(fd, "we");
+ assert_se(f);
+
+ assert_se(read_one_line_file(fn, &buf) == 0);
+ ASSERT_STREQ(buf, "");
+ assert_se(read_one_line_file(fn, &buf2) == 0);
+ ASSERT_STREQ(buf2, "");
+
+ assert_se(write_string_stream(f, "x", WRITE_STRING_FILE_AVOID_NEWLINE) >= 0);
+ fflush(f);
+
+ assert_se(read_one_line_file(fn, &buf3) == 1);
+ ASSERT_STREQ(buf3, "x");
+
+ assert_se(write_string_stream(f, "\n", WRITE_STRING_FILE_AVOID_NEWLINE) >= 0);
+ fflush(f);
+
+ assert_se(read_one_line_file(fn, &buf4) == 2);
+ ASSERT_STREQ(buf4, "x");
+
+ assert_se(write_string_stream(f, "\n", WRITE_STRING_FILE_AVOID_NEWLINE) >= 0);
+ fflush(f);
+
+ assert_se(read_one_line_file(fn, &buf5) == 2);
+ ASSERT_STREQ(buf5, "x");
+}
+
TEST(write_string_stream) {
_cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_stream-XXXXXX";
_cleanup_fclose_ FILE *f = NULL;
rewind(f);
assert_se(fgets(buf, sizeof(buf), f));
- assert_se(streq(buf, "boohoo\n"));
+ ASSERT_STREQ(buf, "boohoo\n");
f = safe_fclose(f);
f = fopen(fn, "w+");
assert_se(fgets(buf, sizeof(buf), f));
printf(">%s<", buf);
- assert_se(streq(buf, "boohoo"));
+ ASSERT_STREQ(buf, "boohoo");
}
TEST(write_string_file) {
_cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file-XXXXXX";
char buf[64] = {};
- _cleanup_close_ int fd;
+ _cleanup_close_ int fd = -EBADF;
fd = mkostemp_safe(fn);
assert_se(fd >= 0);
assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0);
assert_se(read(fd, buf, sizeof(buf)) == 7);
- assert_se(streq(buf, "boohoo\n"));
+ ASSERT_STREQ(buf, "boohoo\n");
}
TEST(write_string_file_no_create) {
_cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
- _cleanup_close_ int fd;
+ _cleanup_close_ int fd = -EBADF;
char buf[64] = {};
fd = mkostemp_safe(fn);
assert_se(write_string_file(fn, "boohoo", 0) == 0);
assert_se(read(fd, buf, sizeof buf) == (ssize_t) strlen("boohoo\n"));
- assert_se(streq(buf, "boohoo\n"));
+ ASSERT_STREQ(buf, "boohoo\n");
}
TEST(write_string_file_verify) {
int r;
r = read_one_line_file("/proc/version", &buf);
- if (ERRNO_IS_PRIVILEGE(r))
+ if (ERRNO_IS_NEG_PRIVILEGE(r))
return;
assert_se(r >= 0);
assert_se(buf2 = strjoin(buf, "\n"));
assert_se(write_string_file("/proc/version", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
}
+static void check_file_pairs_one(char **l) {
+ assert_se(l);
+ assert_se(strv_length(l) == 14);
+
+ STRV_FOREACH_PAIR(k, v, l) {
+ assert_se(STR_IN_SET(*k, "NAME", "ID", "PRETTY_NAME", "ANSI_COLOR", "HOME_URL", "SUPPORT_URL", "BUG_REPORT_URL"));
+ printf("%s=%s\n", *k, *v);
+ assert_se(!streq(*k, "NAME") || streq(*v, "Arch Linux"));
+ assert_se(!streq(*k, "ID") || streq(*v, "arch"));
+ assert_se(!streq(*k, "PRETTY_NAME") || streq(*v, "Arch Linux"));
+ assert_se(!streq(*k, "ANSI_COLOR") || streq(*v, "0;36"));
+ assert_se(!streq(*k, "HOME_URL") || streq(*v, "https://www.archlinux.org/"));
+ assert_se(!streq(*k, "SUPPORT_URL") || streq(*v, "https://bbs.archlinux.org/"));
+ assert_se(!streq(*k, "BUG_REPORT_URL") || streq(*v, "https://bugs.archlinux.org/"));
+ }
+}
+
TEST(load_env_file_pairs) {
_cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
int fd, r;
WRITE_STRING_FILE_CREATE);
assert_se(r == 0);
+ r = load_env_file_pairs_fd(fd, fn, &l);
+ assert_se(r >= 0);
+ check_file_pairs_one(l);
+ l = strv_free(l);
+
f = fdopen(fd, "r");
assert_se(f);
r = load_env_file_pairs(f, fn, &l);
assert_se(r >= 0);
-
- assert_se(strv_length(l) == 14);
- STRV_FOREACH_PAIR(k, v, l) {
- assert_se(STR_IN_SET(*k, "NAME", "ID", "PRETTY_NAME", "ANSI_COLOR", "HOME_URL", "SUPPORT_URL", "BUG_REPORT_URL"));
- printf("%s=%s\n", *k, *v);
- if (streq(*k, "NAME")) assert_se(streq(*v, "Arch Linux"));
- if (streq(*k, "ID")) assert_se(streq(*v, "arch"));
- if (streq(*k, "PRETTY_NAME")) assert_se(streq(*v, "Arch Linux"));
- if (streq(*k, "ANSI_COLOR")) assert_se(streq(*v, "0;36"));
- if (streq(*k, "HOME_URL")) assert_se(streq(*v, "https://www.archlinux.org/"));
- if (streq(*k, "SUPPORT_URL")) assert_se(streq(*v, "https://bbs.archlinux.org/"));
- if (streq(*k, "BUG_REPORT_URL")) assert_se(streq(*v, "https://bugs.archlinux.org/"));
- }
+ check_file_pairs_one(l);
}
TEST(search_and_fopen) {
char name[] = "/tmp/test-search_and_fopen.XXXXXX";
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
- _cleanup_close_ int fd = -1;
+ _cleanup_close_ int fd = -EBADF;
const char *e;
int r;
r = search_and_fopen(basename(name), "re", NULL, (const char**) dirs, &f, &p);
assert_se(r >= 0);
assert_se(e = path_startswith(p, "/tmp/"));
- assert_se(streq(basename(name), e));
+ ASSERT_STREQ(basename(name), e);
f = safe_fclose(f);
p = mfree(p);
+ r = search_and_fopen(basename(name), NULL, NULL, (const char**) dirs, NULL, &p);
+ assert_se(r >= 0);
+ assert_se(e = path_startswith(p, "/tmp/"));
+ ASSERT_STREQ(basename(name), e);
+ p = mfree(p);
+
r = search_and_fopen(name, "re", NULL, (const char**) dirs, &f, &p);
assert_se(r >= 0);
assert_se(path_equal(name, p));
f = safe_fclose(f);
p = mfree(p);
+ r = search_and_fopen(name, NULL, NULL, (const char**) dirs, NULL, &p);
+ assert_se(r >= 0);
+ assert_se(path_equal(name, p));
+ p = mfree(p);
+
r = search_and_fopen(basename(name), "re", "/", (const char**) dirs, &f, &p);
assert_se(r >= 0);
assert_se(e = path_startswith(p, "/tmp/"));
- assert_se(streq(basename(name), e));
+ ASSERT_STREQ(basename(name), e);
f = safe_fclose(f);
p = mfree(p);
+ r = search_and_fopen(basename(name), NULL, "/", (const char**) dirs, NULL, &p);
+ assert_se(r >= 0);
+ assert_se(e = path_startswith(p, "/tmp/"));
+ ASSERT_STREQ(basename(name), e);
+ p = mfree(p);
+
r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "re", NULL, (const char**) dirs, &f, &p);
assert_se(r == -ENOENT);
+ r = search_and_fopen("/a/file/which/does/not/exist/i/guess", NULL, NULL, (const char**) dirs, NULL, &p);
+ assert_se(r == -ENOENT);
r = search_and_fopen("afilewhichdoesnotexistiguess", "re", NULL, (const char**) dirs, &f, &p);
assert_se(r == -ENOENT);
+ r = search_and_fopen("afilewhichdoesnotexistiguess", NULL, NULL, (const char**) dirs, NULL, &p);
+ assert_se(r == -ENOENT);
r = unlink(name);
assert_se(r == 0);
r = search_and_fopen(basename(name), "re", NULL, (const char**) dirs, &f, &p);
assert_se(r == -ENOENT);
+ r = search_and_fopen(basename(name), NULL, NULL, (const char**) dirs, NULL, &p);
+ assert_se(r == -ENOENT);
}
TEST(search_and_fopen_nulstr) {
_cleanup_(unlink_tempfilep) char name[] = "/tmp/test-search_and_fopen.XXXXXX";
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
- _cleanup_close_ int fd = -1;
+ _cleanup_close_ int fd = -EBADF;
const char *e;
int r;
r = search_and_fopen_nulstr(basename(name), "re", NULL, dirs, &f, &p);
assert_se(r >= 0);
assert_se(e = path_startswith(p, "/tmp/"));
- assert_se(streq(basename(name), e));
+ ASSERT_STREQ(basename(name), e);
f = safe_fclose(f);
p = mfree(p);
_cleanup_(unlink_tempfilep) char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
_cleanup_free_ char *contents = NULL;
size_t size;
- _cleanup_close_ int fd = -1;
+ _cleanup_close_ int fd = -EBADF;
int r;
struct iovec iov[] = {
r = read_full_file(name, &contents, &size);
assert_se(r == 0);
printf("contents: %s", contents);
- assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
+ ASSERT_STREQ(contents, "abc\n" ALPHANUMERICAL "\n");
}
TEST(tempfn) {
char *ret = NULL, *p;
assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0);
- assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX"));
+ ASSERT_STREQ(ret, "/foo/bar/.#waldoXXXXXX");
free(ret);
assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0);
- assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX"));
+ ASSERT_STREQ(ret, "/foo/bar/.#[miau]waldoXXXXXX");
free(ret);
assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0);
r = read_line(f, SIZE_MAX, &s);
assert_se((size_t) r == eof_endings[i].length);
- assert_se(streq_ptr(s, "foo"));
+ ASSERT_STREQ(s, "foo");
assert_se(read_line(f, SIZE_MAX, NULL) == 0); /* Ensure we hit EOF */
}
TEST(read_full_file_socket) {
_cleanup_(rm_rf_physical_and_freep) char *z = NULL;
- _cleanup_close_ int listener = -1;
+ _cleanup_close_ int listener = -EBADF;
_cleanup_free_ char *data = NULL, *clientname = NULL;
union sockaddr_union sa;
const char *j, *jj;
/* Bind the *client* socket to some randomized name, to verify that this works correctly. */
assert_se(asprintf(&clientname, "@%" PRIx64 "/test-bindname", random_u64()) >= 0);
- r = safe_fork("(server)", FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork("(server)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &pid);
assert_se(r >= 0);
if (r == 0) {
union sockaddr_union peer = {};
socklen_t peerlen = sizeof(peer);
- _cleanup_close_ int rfd = -1;
+ _cleanup_close_ int rfd = -EBADF;
/* child */
rfd = accept4(listener, NULL, 0, SOCK_CLOEXEC);
assert_se(peer.un.sun_family == AF_UNIX);
assert_se(peerlen > offsetof(struct sockaddr_un, sun_path));
assert_se(peer.un.sun_path[0] == 0);
- assert_se(streq(peer.un.sun_path + 1, clientname + 1));
+ ASSERT_STREQ(peer.un.sun_path + 1, clientname + 1);
#define TEST_STR "This is a test\nreally."
assert_se(read_full_file_full(AT_FDCWD, jj, UINT64_MAX, SIZE_MAX, 0, NULL, &data, &size) == -ENXIO);
assert_se(read_full_file_full(AT_FDCWD, jj, 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));
+ ASSERT_STREQ(data, TEST_STR);
assert_se(wait_for_terminate_and_check("(server)", pid, WAIT_LOG) >= 0);
#undef TEST_STR
IN_SET(r,
-ENOENT, /* Some of the files might be absent */
-EINVAL, /* too small reads from /proc/self/pagemap trigger EINVAL */
- -EFBIG)); /* /proc/kcore and /proc/self/pagemap should be too large */
+ -EFBIG, /* /proc/kcore and /proc/self/pagemap should be too large */
+ -EBADF)); /* /proc/kcore is masked when we are running in docker. */
} else
log_info("read_virtual_file(\"%s\", %zu): %s (%zu bytes)", filename, max_size, r ? "non-truncated" : "truncated", size);
}
}
-TEST(test_read_virtual_file) {
+TEST(read_virtual_file) {
test_read_virtual_file_one(0);
test_read_virtual_file_one(1);
test_read_virtual_file_one(2);
test_read_virtual_file_one(SIZE_MAX);
}
+TEST(fdopen_independent) {
+#define TEST_TEXT "this is some random test text we are going to write to a memfd"
+ _cleanup_close_ int fd = -EBADF;
+ _cleanup_fclose_ FILE *f = NULL;
+ char buf[STRLEN(TEST_TEXT) + 1];
+
+ fd = memfd_new("fdopen_independent");
+ if (fd < 0) {
+ assert_se(ERRNO_IS_NOT_SUPPORTED(fd));
+ return;
+ }
+
+ assert_se(write(fd, TEST_TEXT, strlen(TEST_TEXT)) == strlen(TEST_TEXT));
+ /* we'll leave the read offset at the end of the memfd, the fdopen_independent() descriptors should
+ * start at the beginning anyway */
+
+ assert_se(fdopen_independent(fd, "re", &f) >= 0);
+ zero(buf);
+ assert_se(fread(buf, 1, sizeof(buf), f) == strlen(TEST_TEXT));
+ ASSERT_STREQ(buf, TEST_TEXT);
+ assert_se((fcntl(fileno(f), F_GETFL) & O_ACCMODE) == O_RDONLY);
+ assert_se(FLAGS_SET(fcntl(fileno(f), F_GETFD), FD_CLOEXEC));
+ f = safe_fclose(f);
+
+ assert_se(fdopen_independent(fd, "r", &f) >= 0);
+ zero(buf);
+ assert_se(fread(buf, 1, sizeof(buf), f) == strlen(TEST_TEXT));
+ ASSERT_STREQ(buf, TEST_TEXT);
+ assert_se((fcntl(fileno(f), F_GETFL) & O_ACCMODE) == O_RDONLY);
+ assert_se(!FLAGS_SET(fcntl(fileno(f), F_GETFD), FD_CLOEXEC));
+ f = safe_fclose(f);
+
+ assert_se(fdopen_independent(fd, "r+e", &f) >= 0);
+ zero(buf);
+ assert_se(fread(buf, 1, sizeof(buf), f) == strlen(TEST_TEXT));
+ ASSERT_STREQ(buf, TEST_TEXT);
+ assert_se((fcntl(fileno(f), F_GETFL) & O_ACCMODE) == O_RDWR);
+ assert_se(FLAGS_SET(fcntl(fileno(f), F_GETFD), FD_CLOEXEC));
+ f = safe_fclose(f);
+}
+
+
DEFINE_TEST_MAIN(LOG_DEBUG);