Use O_APPEND for stdio append mode.
"Although not explicitly required by this volume of POSIX.1-2008, a good
implementation of append (a) mode would cause the O_APPEND flag to be set."
Yeah, about that...
Bug: N/A
Test: ran tests
Change-Id: I23c4bc5c1ebc92e0cb44025d2d313f321f9ffa68
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 1f27c83..dac7056 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -47,6 +47,24 @@
class stdio_DeathTest : public BionicDeathTest {};
class stdio_nofortify_DeathTest : public BionicDeathTest {};
+static void SetFileTo(const char* path, const char* content) {
+ FILE* fp;
+ ASSERT_NE(nullptr, fp = fopen(path, "w"));
+ ASSERT_NE(EOF, fputs(content, fp));
+ ASSERT_EQ(0, fclose(fp));
+}
+
+static void AssertFileIs(const char* path, const char* expected) {
+ FILE* fp;
+ ASSERT_NE(nullptr, fp = fopen(path, "r"));
+ char* line = nullptr;
+ size_t length;
+ ASSERT_NE(EOF, getline(&line, &length, fp));
+ ASSERT_EQ(0, fclose(fp));
+ ASSERT_STREQ(expected, line);
+ free(line);
+}
+
static void AssertFileIs(FILE* fp, const char* expected, bool is_fmemopen = false) {
rewind(fp);
@@ -1846,3 +1864,57 @@
sprintf(&buf[0], "hello");
ASSERT_EQ(buf, "hello");
}
+
+TEST(STDIO_TEST, fopen_append_mode_and_ftell) {
+ TemporaryFile tf;
+ SetFileTo(tf.filename, "0123456789");
+ FILE* fp = fopen(tf.filename, "a");
+ EXPECT_EQ(10, ftell(fp));
+ ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
+ EXPECT_EQ(2, ftell(fp));
+ ASSERT_NE(EOF, fputs("xxx", fp));
+ ASSERT_EQ(0, fflush(fp));
+ EXPECT_EQ(13, ftell(fp));
+ ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
+ EXPECT_EQ(13, ftell(fp));
+ ASSERT_EQ(0, fclose(fp));
+ AssertFileIs(tf.filename, "0123456789xxx");
+}
+
+TEST(STDIO_TEST, fdopen_append_mode_and_ftell) {
+ TemporaryFile tf;
+ SetFileTo(tf.filename, "0123456789");
+ int fd = open(tf.filename, O_RDWR);
+ ASSERT_NE(-1, fd);
+ // POSIX: "The file position indicator associated with the new stream is set to the position
+ // indicated by the file offset associated with the file descriptor."
+ ASSERT_EQ(4, lseek(fd, 4, SEEK_SET));
+ FILE* fp = fdopen(fd, "a");
+ EXPECT_EQ(4, ftell(fp));
+ ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
+ EXPECT_EQ(2, ftell(fp));
+ ASSERT_NE(EOF, fputs("xxx", fp));
+ ASSERT_EQ(0, fflush(fp));
+ EXPECT_EQ(13, ftell(fp));
+ ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
+ EXPECT_EQ(13, ftell(fp));
+ ASSERT_EQ(0, fclose(fp));
+ AssertFileIs(tf.filename, "0123456789xxx");
+}
+
+TEST(STDIO_TEST, freopen_append_mode_and_ftell) {
+ TemporaryFile tf;
+ SetFileTo(tf.filename, "0123456789");
+ FILE* other_fp = fopen("/proc/version", "r");
+ FILE* fp = freopen(tf.filename, "a", other_fp);
+ EXPECT_EQ(10, ftell(fp));
+ ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
+ EXPECT_EQ(2, ftell(fp));
+ ASSERT_NE(EOF, fputs("xxx", fp));
+ ASSERT_EQ(0, fflush(fp));
+ EXPECT_EQ(13, ftell(fp));
+ ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
+ EXPECT_EQ(13, ftell(fp));
+ ASSERT_EQ(0, fclose(fp));
+ AssertFileIs(tf.filename, "0123456789xxx");
+}