svn commit: r266971 - in head: lib/libc/stdio tools/regression/lib/libc/stdio

Pietro Cerutti gahr at FreeBSD.org
Mon Jun 2 13:48:58 UTC 2014


Author: gahr (ports committer)
Date: Mon Jun  2 13:48:57 2014
New Revision: 266971
URL: http://svnweb.freebsd.org/changeset/base/266971

Log:
  - 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

Modified:
  head/lib/libc/stdio/fmemopen.c
  head/lib/libc/stdio/fopen.3
  head/tools/regression/lib/libc/stdio/test-fmemopen.c

Modified: head/lib/libc/stdio/fmemopen.c
==============================================================================
--- head/lib/libc/stdio/fmemopen.c	Mon Jun  2 10:14:03 2014	(r266970)
+++ head/lib/libc/stdio/fmemopen.c	Mon Jun  2 13:48:57 2014	(r266971)
@@ -57,6 +57,14 @@ fmemopen(void * __restrict buf, size_t s
 	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 s
 	 */
 	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;

Modified: head/lib/libc/stdio/fopen.3
==============================================================================
--- head/lib/libc/stdio/fopen.3	Mon Jun  2 10:14:03 2014	(r266970)
+++ head/lib/libc/stdio/fopen.3	Mon Jun  2 13:48:57 2014	(r266971)
@@ -302,6 +302,15 @@ for any of the errors specified for the 
 .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 ,

Modified: head/tools/regression/lib/libc/stdio/test-fmemopen.c
==============================================================================
--- head/tools/regression/lib/libc/stdio/test-fmemopen.c	Mon Jun  2 10:14:03 2014	(r266970)
+++ head/tools/regression/lib/libc/stdio/test-fmemopen.c	Mon Jun  2 13:48:57 2014	(r266971)
@@ -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);
 }


More information about the svn-src-head mailing list