summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorngie <ngie@FreeBSD.org>2015-01-11 19:15:28 +0000
committerngie <ngie@FreeBSD.org>2015-01-11 19:15:28 +0000
commit0a1f910d396bf47c3adf1608f16805eafce1c69c (patch)
treea6ea4260d0fa3a951d8063b29c894d9134fb675b
parentaddcd434f9cfc53268eb0ba8220e61e410a48727 (diff)
downloadFreeBSD-src-0a1f910d396bf47c3adf1608f16805eafce1c69c.zip
FreeBSD-src-0a1f910d396bf47c3adf1608f16805eafce1c69c.tar.gz
MFC discussed with: jilles, -developers
MFC r266971: - Return NULL and set errno to EINVAL if size is 0 (as required by POSIX). Update the manpage to reflect this change. - Always set the current position to the first null-byte when opening in append mode. This makes the implementation compatible with glibc's. Update the test suite. Reported by: pho Approved by: cognet
-rw-r--r--lib/libc/stdio/fmemopen.c17
-rw-r--r--lib/libc/stdio/fopen.39
-rw-r--r--tools/regression/lib/libc/stdio/test-fmemopen.c47
3 files changed, 65 insertions, 8 deletions
diff --git a/lib/libc/stdio/fmemopen.c b/lib/libc/stdio/fmemopen.c
index 581a91e..ebd3596 100644
--- a/lib/libc/stdio/fmemopen.c
+++ b/lib/libc/stdio/fmemopen.c
@@ -57,6 +57,14 @@ fmemopen(void * __restrict buf, size_t size, const char * __restrict mode)
int flags, rc;
/*
+ * POSIX says we shall return EINVAL if size is 0.
+ */
+ if (size == 0) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /*
* Retrieve the flags as used by open(2) from the mode argument, and
* validate them.
*/
@@ -119,14 +127,7 @@ fmemopen(void * __restrict buf, size_t size, const char * __restrict mode)
*/
switch (mode[0]) {
case 'a':
- if (ck->bin) {
- /*
- * This isn't useful, since the buffer isn't allowed
- * to grow.
- */
- ck->off = ck->len = size;
- } else
- ck->off = ck->len = strnlen(ck->buf, ck->size);
+ ck->off = ck->len = strnlen(ck->buf, ck->size);
break;
case 'r':
ck->len = size;
diff --git a/lib/libc/stdio/fopen.3 b/lib/libc/stdio/fopen.3
index f11f4e0..b39cb5a 100644
--- a/lib/libc/stdio/fopen.3
+++ b/lib/libc/stdio/fopen.3
@@ -302,6 +302,15 @@ for any of the errors specified for the routines
.Xr fclose 3
and
.Xr fflush 3 .
+.Pp
+The
+.Fn fmemopen
+function
+may also fail and set
+.Va errno
+if the
+.Fa size
+argument is 0.
.Sh SEE ALSO
.Xr open 2 ,
.Xr fclose 3 ,
diff --git a/tools/regression/lib/libc/stdio/test-fmemopen.c b/tools/regression/lib/libc/stdio/test-fmemopen.c
index 2788279..469cc1a 100644
--- a/tools/regression/lib/libc/stdio/test-fmemopen.c
+++ b/tools/regression/lib/libc/stdio/test-fmemopen.c
@@ -138,6 +138,13 @@ test_autoalloc()
/* Close the FILE *. */
rc = fclose(fp);
assert(rc == 0);
+
+ /* Open a FILE * using a wrong mode */
+ fp = fmemopen(NULL, 512, "r");
+ assert(fp == NULL);
+
+ fp = fmemopen(NULL, 512, "w");
+ assert(fp == NULL);
}
void
@@ -241,6 +248,44 @@ test_binary()
assert(rc == 0);
}
+void
+test_append_binary_pos()
+{
+ /*
+ * For compatibility with other implementations (glibc), we set the
+ * position to 0 when opening an automatically allocated binary stream
+ * for appending.
+ */
+
+ FILE *fp;
+
+ fp = fmemopen(NULL, 16, "ab+");
+ assert(ftell(fp) == 0L);
+ fclose(fp);
+
+ /*
+ * Make sure that a pre-allocated buffer behaves correctly.
+ */
+ char buf[] = "Hello";
+ fp = fmemopen(buf, sizeof(buf), "ab+");
+ assert(ftell(fp) == 5);
+ fclose(fp);
+}
+
+void
+test_size_0()
+{
+ /*
+ * POSIX mandates that we return EINVAL if size is 0
+ */
+
+ FILE *fp;
+
+ fp = fmemopen(NULL, 0, "r+");
+ assert(fp == NULL);
+ assert(errno == EINVAL);
+}
+
int
main(void)
{
@@ -248,5 +293,7 @@ main(void)
test_preexisting();
test_data_length();
test_binary();
+ test_append_binary_pos();
+ test_size_0();
return (0);
}
OpenPOWER on IntegriCloud