diff options
author | Elliott Hughes <enh@google.com> | 2017-08-02 15:00:38 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-08-02 15:00:38 +0000 |
commit | 316a44f33ceb9f81975568b67b8e8deb19cce156 (patch) | |
tree | f9b89366b2c846f75d867a76e34da5b04cc097dc | |
parent | 5ac5a7c0839a123c2982b37b383a7691fd216e7e (diff) | |
parent | 5ba2c21159f0bb4c0f7f1fbdbd4671f381b75816 (diff) | |
download | bionic-316a44f33ceb9f81975568b67b8e8deb19cce156.tar.gz |
Merge "Finish <stdio_ext.h>."
-rw-r--r-- | libc/include/stdio_ext.h | 2 | ||||
-rw-r--r-- | libc/libc.arm.map | 2 | ||||
-rw-r--r-- | libc/libc.arm64.map | 2 | ||||
-rw-r--r-- | libc/libc.map.txt | 2 | ||||
-rw-r--r-- | libc/libc.mips.map | 2 | ||||
-rw-r--r-- | libc/libc.mips64.map | 2 | ||||
-rw-r--r-- | libc/libc.x86.map | 2 | ||||
-rw-r--r-- | libc/libc.x86_64.map | 2 | ||||
-rw-r--r-- | libc/stdio/local.h | 9 | ||||
-rw-r--r-- | libc/stdio/stdio_ext.cpp | 10 | ||||
-rw-r--r-- | tests/stdio_ext_test.cpp | 64 |
11 files changed, 85 insertions, 14 deletions
diff --git a/libc/include/stdio_ext.h b/libc/include/stdio_ext.h index fdf677293..3c5abc322 100644 --- a/libc/include/stdio_ext.h +++ b/libc/include/stdio_ext.h @@ -40,7 +40,9 @@ __BEGIN_DECLS size_t __fbufsize(FILE*) __INTRODUCED_IN(23); int __freadable(FILE*) __INTRODUCED_IN(23); +int __freading(FILE*) __INTRODUCED_IN_FUTURE; int __fwritable(FILE*) __INTRODUCED_IN(23); +int __fwriting(FILE*) __INTRODUCED_IN_FUTURE; int __flbf(FILE*) __INTRODUCED_IN(23); void __fpurge(FILE*) __INTRODUCED_IN(23); size_t __fpending(FILE*) __INTRODUCED_IN(23); diff --git a/libc/libc.arm.map b/libc/libc.arm.map index d79e36b7d..06856c8ba 100644 --- a/libc/libc.arm.map +++ b/libc/libc.arm.map @@ -1320,6 +1320,8 @@ LIBC_O { LIBC_P { global: + __freading; # future + __fwriting; # future getlogin_r; # future } LIBC_O; diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map index ed1e82cca..50e4390b1 100644 --- a/libc/libc.arm64.map +++ b/libc/libc.arm64.map @@ -1240,6 +1240,8 @@ LIBC_O { LIBC_P { global: + __freading; # future + __fwriting; # future getlogin_r; # future } LIBC_O; diff --git a/libc/libc.map.txt b/libc/libc.map.txt index af8e5502a..3e4d36eca 100644 --- a/libc/libc.map.txt +++ b/libc/libc.map.txt @@ -1345,6 +1345,8 @@ LIBC_O { LIBC_P { global: + __freading; # future + __fwriting; # future getlogin_r; # future } LIBC_O; diff --git a/libc/libc.mips.map b/libc/libc.mips.map index 90a65e0c3..3fa7c9dea 100644 --- a/libc/libc.mips.map +++ b/libc/libc.mips.map @@ -1304,6 +1304,8 @@ LIBC_O { LIBC_P { global: + __freading; # future + __fwriting; # future getlogin_r; # future } LIBC_O; diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map index ed1e82cca..50e4390b1 100644 --- a/libc/libc.mips64.map +++ b/libc/libc.mips64.map @@ -1240,6 +1240,8 @@ LIBC_O { LIBC_P { global: + __freading; # future + __fwriting; # future getlogin_r; # future } LIBC_O; diff --git a/libc/libc.x86.map b/libc/libc.x86.map index 821756227..bd74fbe46 100644 --- a/libc/libc.x86.map +++ b/libc/libc.x86.map @@ -1302,6 +1302,8 @@ LIBC_O { LIBC_P { global: + __freading; # future + __fwriting; # future getlogin_r; # future } LIBC_O; diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map index ed1e82cca..50e4390b1 100644 --- a/libc/libc.x86_64.map +++ b/libc/libc.x86_64.map @@ -1240,6 +1240,8 @@ LIBC_O { LIBC_P { global: + __freading; # future + __fwriting; # future getlogin_r; # future } LIBC_O; diff --git a/libc/stdio/local.h b/libc/stdio/local.h index 6fb2c0d1a..bf6a8f867 100644 --- a/libc/stdio/local.h +++ b/libc/stdio/local.h @@ -127,10 +127,11 @@ struct __sfileext { // Values for `__sFILE::_flags`. #define __SLBF 0x0001 // Line buffered. #define __SNBF 0x0002 // Unbuffered. -// RD and WR are never simultaneously asserted: use _SRW instead. -#define __SRD 0x0004 // OK to read. -#define __SWR 0x0008 // OK to write. -#define __SRW 0x0010 // Open for reading & writing. +// __SRD and __SWR are mutually exclusive because they indicate what we did last. +// If you want to know whether we were opened read-write, check __SRW instead. +#define __SRD 0x0004 // Last operation was read. +#define __SWR 0x0008 // Last operation was write. +#define __SRW 0x0010 // Was opened for reading & writing. #define __SEOF 0x0020 // Found EOF. #define __SERR 0x0040 // Found error. #define __SMBF 0x0080 // `_buf` is from malloc. diff --git a/libc/stdio/stdio_ext.cpp b/libc/stdio/stdio_ext.cpp index ebc705c87..8cf4f4b3d 100644 --- a/libc/stdio/stdio_ext.cpp +++ b/libc/stdio/stdio_ext.cpp @@ -39,17 +39,13 @@ size_t __fbufsize(FILE* fp) { return fp->_bf._size; } -/* For a _SRW stream, we don't know whether we last read or wrote. int __freading(FILE* fp) { - return (fp->_flags & _SRD) != 0 || ...; + return (fp->_flags & __SRD) != 0; } -*/ -/* For a _SRW stream, we don't know whether we last read or wrote. -int __fwriting(FILE*) { - return (fp->_flags & _SWR) != 0 || ...; +int __fwriting(FILE* fp) { + return (fp->_flags & __SWR) != 0; } -*/ int __freadable(FILE* fp) { return (fp->_flags & (__SRD|__SRW)) != 0; diff --git a/tests/stdio_ext_test.cpp b/tests/stdio_ext_test.cpp index 78725675d..128e25558 100644 --- a/tests/stdio_ext_test.cpp +++ b/tests/stdio_ext_test.cpp @@ -116,20 +116,78 @@ TEST(stdio_ext, _flushlbf) { } TEST(stdio_ext, __freadable__fwritable) { - FILE* fp = fopen("/dev/null", "r"); + FILE* fp; + + // Read-only. + fp = fopen("/dev/null", "r"); ASSERT_TRUE(__freadable(fp)); ASSERT_FALSE(__fwritable(fp)); fclose(fp); + // Write-only. fp = fopen("/dev/null", "w"); ASSERT_FALSE(__freadable(fp)); ASSERT_TRUE(__fwritable(fp)); fclose(fp); - fp = fopen("/dev/null", "w+"); - ASSERT_TRUE(__freadable(fp)); + // Append (aka write-only). + fp = fopen("/dev/null", "a"); + ASSERT_FALSE(__freadable(fp)); ASSERT_TRUE(__fwritable(fp)); fclose(fp); + + // The three read-write modes. + for (auto read_write_mode : {"r+", "w+", "a+"}) { + fp = fopen("/dev/null", read_write_mode); + ASSERT_TRUE(__freadable(fp)); + ASSERT_TRUE(__fwritable(fp)); + fclose(fp); + } +} + +TEST(stdio_ext, __freading__fwriting) { + FILE* fp; + + // Append (aka write-only). Never reading. Always writing. + fp = fopen("/dev/zero", "a"); + ASSERT_FALSE(__freading(fp)); // Not reading initially. + ASSERT_TRUE(__fwriting(fp)); // Writing initially. + ASSERT_TRUE(fputc('x', fp) != EOF); + ASSERT_FALSE(__freading(fp)); // Not reading after write. + ASSERT_TRUE(__fwriting(fp)); // Still writing after write. + fclose(fp); + + // Write-only. Never reading. Always writing. + fp = fopen("/dev/zero", "w"); + ASSERT_FALSE(__freading(fp)); // Not reading initially. + ASSERT_TRUE(__fwriting(fp)); // Writing initially. + ASSERT_TRUE(fputc('x', fp) != EOF); + ASSERT_FALSE(__freading(fp)); // Not reading after write. + ASSERT_TRUE(__fwriting(fp)); // Still writing after write. + fclose(fp); + + // Read-only. Always reading. Never writing. + fp = fopen("/dev/zero", "r"); + ASSERT_TRUE(__freading(fp)); // Reading initially. + ASSERT_FALSE(__fwriting(fp)); // Not writing initially. + ASSERT_TRUE(fgetc(fp) == 0); + ASSERT_TRUE(__freading(fp)); // Still reading after read. + ASSERT_FALSE(__fwriting(fp)); // Still not writing after read. + fclose(fp); + + // The three read-write modes. + for (auto read_write_mode : {"r+", "w+", "a+"}) { + fp = fopen("/dev/zero", read_write_mode); + ASSERT_FALSE(__freading(fp)); // Not reading initially. + ASSERT_FALSE(__fwriting(fp)); // Not writing initially. + ASSERT_TRUE(fgetc(fp) == 0); + ASSERT_TRUE(__freading(fp)); // Reading after read. + ASSERT_FALSE(__fwriting(fp)); // Not writing after read. + ASSERT_TRUE(fputc('x', fp) != EOF); + ASSERT_FALSE(__freading(fp)); // Not reading after write. + ASSERT_TRUE(__fwriting(fp)); // Writing after write. + fclose(fp); + } } TEST(stdio_ext, __fsetlocking) { |