aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2017-08-02 15:00:38 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-08-02 15:00:38 +0000
commit316a44f33ceb9f81975568b67b8e8deb19cce156 (patch)
treef9b89366b2c846f75d867a76e34da5b04cc097dc
parent5ac5a7c0839a123c2982b37b383a7691fd216e7e (diff)
parent5ba2c21159f0bb4c0f7f1fbdbd4671f381b75816 (diff)
downloadbionic-316a44f33ceb9f81975568b67b8e8deb19cce156.tar.gz
Merge "Finish <stdio_ext.h>."
-rw-r--r--libc/include/stdio_ext.h2
-rw-r--r--libc/libc.arm.map2
-rw-r--r--libc/libc.arm64.map2
-rw-r--r--libc/libc.map.txt2
-rw-r--r--libc/libc.mips.map2
-rw-r--r--libc/libc.mips64.map2
-rw-r--r--libc/libc.x86.map2
-rw-r--r--libc/libc.x86_64.map2
-rw-r--r--libc/stdio/local.h9
-rw-r--r--libc/stdio/stdio_ext.cpp10
-rw-r--r--tests/stdio_ext_test.cpp64
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) {