- 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
This commit is contained in:
parent
b2fa7d8104
commit
4c524a4287
@ -56,6 +56,14 @@ fmemopen(void * __restrict buf, size_t size, const char * __restrict mode)
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
int flags, rc;
|
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
|
* Retrieve the flags as used by open(2) from the mode argument, and
|
||||||
* validate them.
|
* validate them.
|
||||||
@ -119,14 +127,7 @@ fmemopen(void * __restrict buf, size_t size, const char * __restrict mode)
|
|||||||
*/
|
*/
|
||||||
switch (mode[0]) {
|
switch (mode[0]) {
|
||||||
case 'a':
|
case 'a':
|
||||||
if (ck->bin) {
|
ck->off = ck->len = strnlen(ck->buf, ck->size);
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
ck->len = size;
|
ck->len = size;
|
||||||
|
@ -302,6 +302,15 @@ for any of the errors specified for the routines
|
|||||||
.Xr fclose 3
|
.Xr fclose 3
|
||||||
and
|
and
|
||||||
.Xr fflush 3 .
|
.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
|
.Sh SEE ALSO
|
||||||
.Xr open 2 ,
|
.Xr open 2 ,
|
||||||
.Xr fclose 3 ,
|
.Xr fclose 3 ,
|
||||||
|
@ -138,6 +138,13 @@ test_autoalloc()
|
|||||||
/* Close the FILE *. */
|
/* Close the FILE *. */
|
||||||
rc = fclose(fp);
|
rc = fclose(fp);
|
||||||
assert(rc == 0);
|
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
|
void
|
||||||
@ -241,6 +248,44 @@ test_binary()
|
|||||||
assert(rc == 0);
|
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
|
int
|
||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
@ -248,5 +293,7 @@ main(void)
|
|||||||
test_preexisting();
|
test_preexisting();
|
||||||
test_data_length();
|
test_data_length();
|
||||||
test_binary();
|
test_binary();
|
||||||
|
test_append_binary_pos();
|
||||||
|
test_size_0();
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user