From e0c82b6158021248d44c671ab51b38d0a325f43f Mon Sep 17 00:00:00 2001 From: Nat! Date: Mon, 25 Nov 2024 23:24:44 +0100 Subject: [PATCH] add some GLIBC compatibility, cant fix darwin though. it's too broken --- src/mulle-buffer-stdio.c | 272 +++++++++++++------- src/mulle-buffer-stdio.h | 4 + test/20_mimicry/broken-darwin.c | 18 ++ test/20_mimicry/broken-darwin.errors.darwin | 1 + test/20_mimicry/fget.c | 47 ++-- test/20_mimicry/fget.stdout | 2 +- test/20_mimicry/fget.stdout.darwin | 10 + test/20_mimicry/fput.c | 24 +- test/20_mimicry/fput.stdout | 2 +- test/20_mimicry/fput.stdout.darwin | 10 + test/20_mimicry/fread.c | 25 +- test/20_mimicry/fread.stdout | 2 +- test/20_mimicry/fread.stdout.darwin | 10 + test/20_mimicry/fseek.c | 25 +- test/20_mimicry/fseek.stdout | 24 +- test/20_mimicry/fseek.stdout.darwin | 15 ++ test/20_mimicry/fwrite.c | 43 ++-- test/20_mimicry/fwrite.stdout | 4 +- test/20_mimicry/fwrite.stdout.darwin | 10 + test/20_mimicry/memopen.c | 46 ++-- test/20_mimicry/memopen.errors.darwin | 1 + test/20_mimicry/modes-buffer.c | 66 +++++ test/20_mimicry/modes-buffer.stdout | 54 ++++ test/20_mimicry/modes-buffer.stdout.darwin | 54 ++++ test/20_mimicry/modes-fp.c | 65 +++++ test/20_mimicry/modes-fp.stdout | 54 ++++ test/20_mimicry/modes-fp.stdout.darwin | 54 ++++ 27 files changed, 756 insertions(+), 186 deletions(-) create mode 100644 test/20_mimicry/broken-darwin.c create mode 100644 test/20_mimicry/broken-darwin.errors.darwin create mode 100644 test/20_mimicry/fget.stdout.darwin create mode 100644 test/20_mimicry/fput.stdout.darwin create mode 100644 test/20_mimicry/fread.stdout.darwin create mode 100644 test/20_mimicry/fseek.stdout.darwin create mode 100644 test/20_mimicry/fwrite.stdout.darwin create mode 100644 test/20_mimicry/memopen.errors.darwin create mode 100644 test/20_mimicry/modes-buffer.c create mode 100644 test/20_mimicry/modes-buffer.stdout create mode 100644 test/20_mimicry/modes-buffer.stdout.darwin create mode 100644 test/20_mimicry/modes-fp.c create mode 100644 test/20_mimicry/modes-fp.stdout create mode 100644 test/20_mimicry/modes-fp.stdout.darwin diff --git a/src/mulle-buffer-stdio.c b/src/mulle-buffer-stdio.c index 9730610..91e5285 100644 --- a/src/mulle-buffer-stdio.c +++ b/src/mulle-buffer-stdio.c @@ -4,6 +4,135 @@ #include +// +// r : USEFUL: readonly. +// w : USEFUL: writeonly +// a : writeonly, seek to first null byte +// r+ : USEFUL: read and write +// w+ : read and write, The buffer contents are truncated (i.e., '\0' is placed in the first byte of the buffer). +// a+ : read and write, seek to first null byte +// + +// darwin: +// The fmemopen() function associates the buffer given by the buf and size +// arguments with a stream. The buf argument is either a null pointer or a +// pointer to a buffer that is at least size bytes long. If a null pointer +// is specified as the buf argument, fmemopen() allocates size bytes of +// memory, and this allocation is automatically freed when the stream is +// closed. If a non-null pointer is specified, the caller retains ownership +// of the buffer and is responsible for disposing of it after the stream has +// been closed. Buffers can be opened in text-mode (default) or binary-mode +// (if “b” is present in the second or third position of the mode argument). +// Buffers opened in text-mode make sure that writes are terminated with a +// NULL byte, if the last write hasn't filled up the whole buffer. Buffers +// opened in binary-mode never append a NULL byte. + +void *mulle_buffer_fmemopen( void *bytes, size_t length, const char *mode) +{ + struct mulle_buffer *buffer; + int append; + int truncate; + unsigned int bits; + + if( ! mode) + { + errno = EINVAL; + return( NULL); + } + +// darwin is just stupid broken, but it makes no sense to support it +// for test conformance, since its a bug +// #ifdef __APPLE__ +// if( ! bytes || ! length) +// { +// errno = EINVAL; +// return( NULL); +// } +// #endif + + bits = MULLE_BUFFER_IS_TEXT; + append = 0; + truncate = 0; + + switch( *mode++) + { + case 'r' : bits |= MULLE_BUFFER_IS_READONLY; + break; + case 'a' : append = 1; // fall thru + case 'w' : bits |= MULLE_BUFFER_IS_WRITEONLY; + break; + default : goto error_einval; + } + + for(;;) + { + switch( *mode++) + { + case 'b' : bits &= ~MULLE_BUFFER_IS_TEXT; + continue; + case '+' : bits &= ~MULLE_BUFFER_IS_READONLY|MULLE_BUFFER_IS_WRITEONLY; + truncate = 1; + continue; + case '\0' : goto done_parse; + default : goto error_einval; + } + } + +done_parse: + buffer = mulle_buffer_alloc( NULL); + + // The fmemopen() function associates the buffer given by the buf and size + // arguments with a stream. The buf argument is either a null pointer or a + // pointer to a buffer that is at least size bytes long. + // If a null pointer is specified as the buf argument, fmemopen() allocates + // size bytes of memory, and this allocation is automatically freed when + // the stream is closed. If a non-null pointer is specified, the caller + // retains ownership of the buffer and is responsible for disposing of it + // after the stream has been closed. + // + if( bytes) + mulle_buffer_init_with_static_bytes( buffer, + bytes, + length, + NULL); + else + mulle_buffer_init( buffer, length, NULL); + + buffer->_type |= bits; + buffer->_type |= MULLE_BUFFER_IS_INFLEXIBLE; + + // + // fmemopen has retarded semantics IMO + // + // In append mode, if no null byte is found within the buffer, then the + // initial position is length+1. (I don't think we can do this, we can just + // do length) + // + if( append) + { + while( buffer->_curr < buffer->_sentinel) + { + if( *buffer->_curr == '\0') + break; + ++buffer->_curr; + } + } + else + if( truncate && (bits != MULLE_BUFFER_IS_READONLY)) + { + if( ! mulle_buffer_is_full( buffer)) + *buffer->_curr = '\0'; + } + + return( buffer); + +error_einval: + errno = EINVAL; + return( NULL); +} + + + // // STDIO callback mimicry // @@ -66,6 +195,13 @@ int mulle_buffer_fseek( void *buffer, long seek, int mode) return( -1); } + // compatibility ... + if( mode == SEEK_END && (((struct mulle__buffer *) buffer)->_type & MULLE_BUFFER_IS_WRITEONLY)) + { + errno = ENOSPC; + return( -1); + } + rval = _mulle__buffer_set_seek( (struct mulle__buffer *) buffer, seek, mode); if( rval) errno = EINVAL; @@ -101,6 +237,7 @@ int mulle_buffer_fputc( int c, void *buffer) { if( ! buffer) return( EOF); + if( mulle_buffer_is_readonly( buffer)) { errno = EBADF; @@ -110,22 +247,42 @@ int mulle_buffer_fputc( int c, void *buffer) _mulle__buffer_add_byte( (struct mulle__buffer *) buffer, (unsigned char) c, ((struct mulle_buffer *) buffer)->_allocator); - return( (unsigned char) c); + +#ifdef __GLIBC__ + // stupid code for fmemopen compatibility (as observed on linux) + if( mulle_buffer_is_inflexible( buffer)) + return( (unsigned char) c); +#endif + + return( _mulle__buffer_has_overflown( buffer) ? EOF : (unsigned char) c); } int mulle_buffer_fputs( const char *s, void *buffer) { + size_t before; + if( ! buffer) return( 0); + if( mulle_buffer_is_readonly( buffer)) { errno = EBADF; return( EOF); } + before = mulle_buffer_get_length( buffer); mulle_buffer_add_c_string( buffer, (char *) s); - return( 0); + +#ifdef __GLIBC__ + // stupid code for fmemopen compatibility (as observed on linux) + if( mulle_buffer_is_inflexible( buffer)) + return( (int) (mulle_buffer_get_length( buffer) - before)); +#endif + + return( _mulle__buffer_has_overflown( buffer) + ? EOF + : (int) (mulle_buffer_get_length( buffer) - before)); } @@ -137,6 +294,14 @@ int mulle_buffer_fflush( void *buffer) return( EOF); } + // When a stream that has been opened for writing is flushed + // a null byte is written at the end of + // the buffer if there is space. The caller should ensure that an extra + // byte is available in the buffer (and that size counts that byte) to allow + // for this. + if( ((struct mulle__buffer *) buffer)->_type & MULLE_BUFFER_IS_TEXT) + _mulle__buffer_zero_last_byte_no_truncate( (struct mulle__buffer *) buffer); + if( _mulle__buffer_is_flushable( (struct mulle__buffer *) buffer)) _mulle__buffer_flush( (struct mulle__buffer *) buffer); return( 0); @@ -150,7 +315,7 @@ size_t mulle_buffer_fwrite( void *src, size_t size, size_t nmemb, void *buffe void *dst; if( ! buffer) - goto zero; + return( EOF); // seems the compatible way (no errno) dont ask if( mulle_buffer_is_readonly( buffer)) { @@ -164,9 +329,21 @@ size_t mulle_buffer_fwrite( void *src, size_t size, size_t nmemb, void *buffe bytes_to_write = size * nmemb; dst = mulle_buffer_advance( buffer, bytes_to_write); - // ain't doing partial writes + // ain't doing partial writes, except if inflexible, then it gets weird + // for compatibility + if( ! dst) { +#ifdef __GLIBC__ + if( mulle_buffer_is_inflexible( buffer)) + { + size_t remaining; + + remaining = mulle_buffer_remaining_length( buffer); + mulle_buffer_add_bytes( buffer, src, remaining); + return( nmemb); // (sic!) turbo retarded + } +#endif errno = ENOSPC; return( 0); } @@ -180,99 +357,16 @@ size_t mulle_buffer_fwrite( void *src, size_t size, size_t nmemb, void *buffe } -// -// r : USEFUL: readonly. -// w : USEFUL: writeonly -// a : writeonly, seek to first null byte -// r+ : USEFUL: read and write -// w+ : read and write, The buffer contents are truncated (i.e., '\0' is placed in the first byte of the buffer). -// a+ : read and write, seek to first null byte -// -void *mulle_buffer_fmemopen( void *bytes, size_t length, const char *mode) -{ - struct mulle_buffer *buffer; - int append; - int truncate; - unsigned int bits; - - if( ! mode) - { - errno = EINVAL; - return( NULL); - } - - bits = 0; - append = 0; - truncate = 0; - - switch( *mode++) - { - case 'r' : if( ! bytes) - goto error_einval; - bits = MULLE_BUFFER_IS_READONLY; - break; - case 'a' : append = 1; // fall thru - case 'w' : bits = MULLE_BUFFER_IS_WRITEONLY; - break; - default : goto error_einval; - } - - switch( *mode++) - { - case '+' : bits = 0; - truncate = 1; - case '\0' : break; - default : goto error_einval; - } - - buffer = mulle_buffer_create( NULL); - - if( bytes) - mulle_buffer_init_with_static_bytes( buffer, - bytes, - length, - NULL); - buffer->_type |= bits; - - // - // fmemopen has retarded semantics IMO - // - // In append mode, if no null byte is found within the buffer, then the - // initial position is length+1. (I don't think we can do this, we can just - // do length) - // - if( append) - { - while( buffer->_curr < buffer->_sentinel) - { - if( *buffer->_curr == '\0') - break; - ++buffer->_curr; - } - } - else - if( truncate && (bits != MULLE_BUFFER_IS_READONLY)) - { - if( ! mulle_buffer_is_full( buffer)) - *buffer->_curr = '\0'; - } - - return( buffer); - -error_einval: - errno = EINVAL; - return( NULL); -} - int mulle_buffer_fclose( void *buffer) { + mulle_buffer_fflush( buffer); mulle_buffer_destroy( buffer); return( 0); } -off_t mulle_buffer_lseek( void *buffer, off_t offset, int mode) +off_t mulle_buffer_lseek( void *buffer, off_t offset, int mode) { int rval; long seek; diff --git a/src/mulle-buffer-stdio.h b/src/mulle-buffer-stdio.h index 4a3e812..2007763 100644 --- a/src/mulle-buffer-stdio.h +++ b/src/mulle-buffer-stdio.h @@ -41,6 +41,10 @@ * r+ Open the stream for reading and writing. * w+ Open the stream for reading and writing. The buffer contents are truncated (i.e., '\0' is placed in the first byte of the buffer). * a+ Append; open the stream for reading and writing, with the initial buffer position set to the first null byte. + * + * Unfortunately in a cross-platform scenario (at least darwin and linux, + * the fmemopen interface is super flakey and unpredictable when it comes + * to seeking and writing in various modes). */ MULLE__FPRINTF_GLOBAL void *mulle_buffer_fmemopen( void *buf, size_t size, const char *mode); diff --git a/test/20_mimicry/broken-darwin.c b/test/20_mimicry/broken-darwin.c new file mode 100644 index 0000000..6a0313d --- /dev/null +++ b/test/20_mimicry/broken-darwin.c @@ -0,0 +1,18 @@ +#include + + +int main( void) +{ + FILE *fp; + + fp = fmemopen( NULL, 100, "w"); + if( ! fp) + { + perror( "fmemopen:"); + return( 1); + } + fclose( fp); + return( 0); +} + + diff --git a/test/20_mimicry/broken-darwin.errors.darwin b/test/20_mimicry/broken-darwin.errors.darwin new file mode 100644 index 0000000..a4b569c --- /dev/null +++ b/test/20_mimicry/broken-darwin.errors.darwin @@ -0,0 +1 @@ +fmemopen: diff --git a/test/20_mimicry/fget.c b/test/20_mimicry/fget.c index 5b29631..81122ea 100644 --- a/test/20_mimicry/fget.c +++ b/test/20_mimicry/fget.c @@ -41,19 +41,28 @@ static int safe_mulle_buffer_fgetc(void *buffer) return result; } -static void compare_fgetc(FILE *fp, void *buffer, const char *test_name) +static void compare_fgetc( FILE *fp, void *buffer, const char *test_name) { int c1, c2; int errno1, errno2; - signal(SIGSEGV, signal_handler); + if( fp && ! buffer || ! fp && buffer) + { + printf("Error in %s: FILE * %s; mulle_buffer: %s\n", + test_name, + fp ? "valid" : "NULL", + buffer ? "valid" : "NULL"); + return; + } + + signal( SIGSEGV, signal_handler); - errno = 0; - c1 = safe_fgetc(fp); + errno = 0; + c1 = safe_fgetc( fp); errno1 = errno; - errno = 0; - c2 = safe_mulle_buffer_fgetc(buffer); + errno = 0; + c2 = safe_mulle_buffer_fgetc( buffer); errno2 = errno; if (c1 == c2 && errno1 == errno2) @@ -69,11 +78,11 @@ static void compare_fgetc(FILE *fp, void *buffer, const char *test_name) } else { - printf("Error in %s: FILE*: char=%d, errno=%d; mulle_buffer: char=%d, errno=%d\n", + printf("Error in %s: FILE *: char=%d, errno=%d; mulle_buffer: char=%d, errno=%d\n", test_name, c1, errno1, c2, errno2); } - signal(SIGSEGV, SIG_DFL); // Reset signal handler + signal( SIGSEGV, SIG_DFL); // Reset signal handler } static void test_fgetc(void) @@ -82,17 +91,14 @@ static void test_fgetc(void) void *buffer; const char *test_string = "Hello"; - // Test case 1: NULL pointers - compare_fgetc(NULL, NULL, "NULL pointers"); - - // Test case 2: Zero-length memory - fp = fmemopen((void*)"", 0, "r"); - buffer = mulle_buffer_fmemopen((void*)"", 0, "r"); - compare_fgetc(fp, buffer, "Zero-length memory"); - fclose(fp); + // Test case 1: Zero-length memory + fp = fmemopen( (void *) "", 0, "r"); + buffer = mulle_buffer_fmemopen( (void *) "", 0, "r"); + compare_fgetc( fp, buffer, "Zero-length memory"); + fclose( fp); mulle_buffer_fclose(buffer); - // Test case 3: Normal case + // Test case 2: Normal case fp = fmemopen((void*)test_string, strlen(test_string), "r"); buffer = mulle_buffer_fmemopen((void*)test_string, strlen(test_string), "r"); @@ -108,12 +114,17 @@ static void test_fgetc(void) fclose(fp); mulle_buffer_fclose(buffer); - // Test case 4: Read-only empty file + // Test case 3: Read-only empty file fp = fmemopen(NULL, 0, "r"); buffer = mulle_buffer_fmemopen(NULL, 0, "r"); compare_fgetc(fp, buffer, "Read-only empty file"); fclose(fp); mulle_buffer_fclose(buffer); + + // Test case 4: NULL pointers + // MEMO: this will be different error code, as mulle_buffer_fgetc + // will refuse to crash + compare_fgetc( NULL, NULL, "NULL pointers"); } int main(int argc, const char * argv[]) diff --git a/test/20_mimicry/fget.stdout b/test/20_mimicry/fget.stdout index b21ffbb..a887294 100644 --- a/test/20_mimicry/fget.stdout +++ b/test/20_mimicry/fget.stdout @@ -1,4 +1,3 @@ -Error in NULL pointers: FILE*: char=-2, errno=0; mulle_buffer: char=-1, errno=0 Zero-length memory: Passed (char=-1, errno=0) Normal case: Passed (char=72, errno=0) Normal case: Passed (char=101, errno=0) @@ -8,3 +7,4 @@ Normal case: Passed (char=111, errno=0) Normal case: Passed (char=-1, errno=0) EOF case: Passed (char=-1, errno=0) Read-only empty file: Passed (char=-1, errno=0) +Error in NULL pointers: FILE *: char=-2, errno=0; mulle_buffer: char=-1, errno=0 diff --git a/test/20_mimicry/fget.stdout.darwin b/test/20_mimicry/fget.stdout.darwin new file mode 100644 index 0000000..f0b549c --- /dev/null +++ b/test/20_mimicry/fget.stdout.darwin @@ -0,0 +1,10 @@ +Error in Zero-length memory: FILE * NULL; mulle_buffer: valid +Normal case: Passed (char=72, errno=0) +Normal case: Passed (char=101, errno=0) +Normal case: Passed (char=108, errno=0) +Normal case: Passed (char=108, errno=0) +Normal case: Passed (char=111, errno=0) +Normal case: Passed (char=-1, errno=0) +EOF case: Passed (char=-1, errno=0) +Error in Read-only empty file: FILE * NULL; mulle_buffer: valid +Error in NULL pointers: FILE *: char=-2, errno=0; mulle_buffer: char=-1, errno=0 diff --git a/test/20_mimicry/fput.c b/test/20_mimicry/fput.c index 1eefb20..19c8f2d 100644 --- a/test/20_mimicry/fput.c +++ b/test/20_mimicry/fput.c @@ -46,6 +46,15 @@ static void compare_putc(int c, FILE *fp, void *buffer, const char *test_name) int r1, r2; int errno1, errno2; + if( fp && ! buffer || ! fp && buffer) + { + printf("Error in %s: FILE * %s; mulle_buffer: %s\n", + test_name, + fp ? "valid" : "NULL", + buffer ? "valid" : "NULL"); + return; + } + signal(SIGSEGV, signal_handler); errno = 0; @@ -82,17 +91,14 @@ static void test_putc(void) void *buffer; char test_char = 'A'; - // Test case 1: NULL pointers - compare_putc(test_char, NULL, NULL, "NULL pointers"); - - // Test case 2: Write to memory stream + // Test case 1: Write to memory stream fp = fmemopen(NULL, 100, "w"); buffer = mulle_buffer_fmemopen(NULL, 100, "w"); compare_putc(test_char, fp, buffer, "Write to memory stream"); fclose(fp); mulle_buffer_fclose(buffer); - // Test case 3: Write to full buffer + // Test case 2: Write to full buffer char small_buf[1] = {0}; fp = fmemopen(small_buf, 1, "w"); buffer = mulle_buffer_fmemopen(small_buf, 1, "w"); @@ -101,14 +107,14 @@ static void test_putc(void) fclose(fp); mulle_buffer_fclose(buffer); - // Test case 4: Write-only empty file + // Test case 3: Write-only empty file fp = fmemopen(NULL, 0, "w"); buffer = mulle_buffer_fmemopen(NULL, 0, "w"); compare_putc(test_char, fp, buffer, "Write-only empty file"); fclose(fp); mulle_buffer_fclose(buffer); - // Test case 5: Multiple writes + // Test case 4: Multiple writes fp = fmemopen(NULL, 100, "w"); buffer = mulle_buffer_fmemopen(NULL, 100, "w"); for (int i = 0; i < 5; i++) @@ -117,8 +123,12 @@ static void test_putc(void) } fclose(fp); mulle_buffer_fclose(buffer); + + // Test case 5: NULL pointers + compare_putc(test_char, NULL, NULL, "NULL pointers"); } + int main(int argc, const char * argv[]) { test_putc(); diff --git a/test/20_mimicry/fput.stdout b/test/20_mimicry/fput.stdout index ab2bd2f..473a7d5 100644 --- a/test/20_mimicry/fput.stdout +++ b/test/20_mimicry/fput.stdout @@ -1,4 +1,3 @@ -Error in NULL pointers: fputc: result=-2, errno=0; mulle_buffer_fputc: result=-1, errno=0 Write to memory stream: Passed (result=65, errno=0) Write to full buffer (first write): Passed (result=65, errno=0) Write to full buffer (second write): Passed (result=65, errno=0) @@ -8,3 +7,4 @@ Multiple writes: Passed (result=49, errno=0) Multiple writes: Passed (result=50, errno=0) Multiple writes: Passed (result=51, errno=0) Multiple writes: Passed (result=52, errno=0) +Error in NULL pointers: fputc: result=-2, errno=0; mulle_buffer_fputc: result=-1, errno=0 diff --git a/test/20_mimicry/fput.stdout.darwin b/test/20_mimicry/fput.stdout.darwin new file mode 100644 index 0000000..b02bc0b --- /dev/null +++ b/test/20_mimicry/fput.stdout.darwin @@ -0,0 +1,10 @@ +Error in Write to memory stream: FILE * NULL; mulle_buffer: valid +Write to full buffer (first write): Passed (result=65, errno=0) +Write to full buffer (second write): Passed (result=-1, errno=0) +Error in Write-only empty file: FILE * NULL; mulle_buffer: valid +Error in Multiple writes: FILE * NULL; mulle_buffer: valid +Error in Multiple writes: FILE * NULL; mulle_buffer: valid +Error in Multiple writes: FILE * NULL; mulle_buffer: valid +Error in Multiple writes: FILE * NULL; mulle_buffer: valid +Error in Multiple writes: FILE * NULL; mulle_buffer: valid +Error in NULL pointers: fputc: result=-2, errno=0; mulle_buffer_fputc: result=-1, errno=0 diff --git a/test/20_mimicry/fread.c b/test/20_mimicry/fread.c index 32752b6..053a43d 100644 --- a/test/20_mimicry/fread.c +++ b/test/20_mimicry/fread.c @@ -46,6 +46,15 @@ static void compare_read(void *ptr1, void *ptr2, size_t size, size_t nmemb, FILE size_t r1, r2; int errno1, errno2; + if( fp && ! buffer || ! fp && buffer) + { + printf("Error in %s: FILE * %s; mulle_buffer: %s\n", + test_name, + fp ? "valid" : "NULL", + buffer ? "valid" : "NULL"); + return; + } + signal(SIGSEGV, signal_handler); errno = 0; @@ -87,31 +96,28 @@ static void test_read(void) const char test_data[] = "Hello, World!"; char read_buf1[20], read_buf2[20]; - // Test case 1: NULL pointers - compare_read(read_buf1, read_buf2, 1, strlen(test_data), NULL, NULL, "NULL pointers"); - - // Test case 2: Read from memory stream + // Test case 1: Read from memory stream fp = fmemopen((void*)test_data, strlen(test_data), "r"); buffer = mulle_buffer_fmemopen((void*)test_data, strlen(test_data), "r"); compare_read(read_buf1, read_buf2, 1, strlen(test_data), fp, buffer, "Read from memory stream"); fclose(fp); mulle_buffer_fclose(buffer); - // Test case 3: Read more than available + // Test case 2: Read more than available fp = fmemopen((void*)test_data, strlen(test_data), "r"); buffer = mulle_buffer_fmemopen((void*)test_data, strlen(test_data), "r"); compare_read(read_buf1, read_buf2, 1, 20, fp, buffer, "Read more than available"); fclose(fp); mulle_buffer_fclose(buffer); - // Test case 4: Read-only empty file + // Test case 3: Read-only empty file fp = fmemopen("", 0, "r"); buffer = mulle_buffer_fmemopen("", 0, "r"); compare_read(read_buf1, read_buf2, 1, 10, fp, buffer, "Read-only empty file"); fclose(fp); mulle_buffer_fclose(buffer); - // Test case 5: Multiple reads + // Test case 4: Multiple reads fp = fmemopen((void*)test_data, strlen(test_data), "r"); buffer = mulle_buffer_fmemopen((void*)test_data, strlen(test_data), "r"); for (int i = 0; i < 5; i++) @@ -121,12 +127,15 @@ static void test_read(void) fclose(fp); mulle_buffer_fclose(buffer); - // Test case 6: Read with different size and nmemb + // Test case 5: Read with different size and nmemb fp = fmemopen((void*)test_data, strlen(test_data), "r"); buffer = mulle_buffer_fmemopen((void*)test_data, strlen(test_data), "r"); compare_read(read_buf1, read_buf2, 2, strlen(test_data) / 2, fp, buffer, "Read with size=2, nmemb=6"); fclose(fp); mulle_buffer_fclose(buffer); + + // Test case 6: NULL pointers + compare_read(read_buf1, read_buf2, 1, strlen(test_data), NULL, NULL, "NULL pointers"); } int main(int argc, const char * argv[]) diff --git a/test/20_mimicry/fread.stdout b/test/20_mimicry/fread.stdout index 244a8a3..807c987 100644 --- a/test/20_mimicry/fread.stdout +++ b/test/20_mimicry/fread.stdout @@ -1,4 +1,3 @@ -Error in NULL pointers: fread: result=18446744073709551615, errno=0; mulle_buffer_fread: result=0, errno=0 Read from memory stream: Passed (result=13, errno=0) Read more than available: Passed (result=13, errno=0) Read-only empty file: Passed (result=0, errno=0) @@ -8,3 +7,4 @@ Multiple reads: Passed (result=2, errno=0) Multiple reads: Passed (result=2, errno=0) Multiple reads: Passed (result=2, errno=0) Read with size=2, nmemb=6: Passed (result=6, errno=0) +Error in NULL pointers: fread: result=18446744073709551615, errno=0; mulle_buffer_fread: result=0, errno=0 diff --git a/test/20_mimicry/fread.stdout.darwin b/test/20_mimicry/fread.stdout.darwin new file mode 100644 index 0000000..fd1c975 --- /dev/null +++ b/test/20_mimicry/fread.stdout.darwin @@ -0,0 +1,10 @@ +Read from memory stream: Passed (result=13, errno=0) +Read more than available: Passed (result=13, errno=0) +Error in Read-only empty file: FILE * NULL; mulle_buffer: valid +Multiple reads: Passed (result=2, errno=0) +Multiple reads: Passed (result=2, errno=0) +Multiple reads: Passed (result=2, errno=0) +Multiple reads: Passed (result=2, errno=0) +Multiple reads: Passed (result=2, errno=0) +Read with size=2, nmemb=6: Passed (result=5, errno=0) +Error in NULL pointers: fread: result=18446744073709551615, errno=0; mulle_buffer_fread: result=0, errno=0 diff --git a/test/20_mimicry/fseek.c b/test/20_mimicry/fseek.c index e394a28..5b0597a 100644 --- a/test/20_mimicry/fseek.c +++ b/test/20_mimicry/fseek.c @@ -13,6 +13,15 @@ static void compare_seek_tell(FILE *fp, struct mulle_buffer *buffer, const char int errno1, errno2; int c1, c2; + if( fp && ! buffer || ! fp && buffer) + { + printf("Error in %s: FILE * %s; mulle_buffer: %s\n", + test_name, + fp ? "valid" : "NULL", + buffer ? "valid" : "NULL"); + return; + } + // Test initial position errno = 0; pos1 = ftell( fp); @@ -109,25 +118,25 @@ static void test_seek_tell(void) '1', '8', '4', '8' }; - // Test case 2: Normal case with read/write + // Test case 1: Normal case with read/write fp = fmemopen((void*)test_string, strlen(test_string), "a+"); buffer = mulle_buffer_fmemopen((void*)test_string, strlen(test_string), "a+"); compare_seek_tell(fp, buffer, "Normal case"); fclose(fp); mulle_buffer_fclose(buffer); - fp = fmemopen(NULL, 0, "w"); - buffer = mulle_buffer_fmemopen(NULL, 0, "w"); - compare_seek_tell(fp, buffer, "Empty file"); - fclose(fp); - mulle_buffer_fclose(buffer); - - // Test case 4: Read-only file, but mulle_buffer can't do read only + // Test case 2: Read-only file, but mulle_buffer can't do read only fp = fmemopen((void*)test_string, strlen(test_string), "r"); buffer = mulle_buffer_fmemopen((void*)test_string, strlen(test_string), "r"); compare_seek_tell(fp, buffer, "Read-only file"); fclose(fp); mulle_buffer_fclose(buffer); + + fp = fmemopen(NULL, 0, "w"); + buffer = mulle_buffer_fmemopen(NULL, 0, "w"); + compare_seek_tell(fp, buffer, "Empty file"); + fclose(fp); + mulle_buffer_fclose(buffer); } int main(int argc, const char * argv[]) diff --git a/test/20_mimicry/fseek.stdout b/test/20_mimicry/fseek.stdout index a6d7f94..c8333ce 100644 --- a/test/20_mimicry/fseek.stdout +++ b/test/20_mimicry/fseek.stdout @@ -1,21 +1,21 @@ Normal case - Initial position: FILE*=15 (errno=0), mulle_buffer=15 (errno=0) Normal case - Seek to 3: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) -Normal case - Read at 3: FILE*=' ' (32) (errno=0), mulle_buffer=' ' (32) (errno=0) +Normal case - Read at 3: FILE*=' ' (32) (errno=0), mulle_buffer='' (-1) (errno=9) Normal case - Seek -2 from current: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) Normal case - Write 'X': FILE*=88 (errno=0), mulle_buffer=88 (errno=0) -Normal case - Seek to end: FILE*=-1 (errno=0), mulle_buffer=0 (errno=0) -Normal case - Final position: FILE*=15 (errno=0), mulle_buffer=15 (errno=0) +Normal case - Seek to end: FILE*=-1 (errno=0), mulle_buffer=-1 (errno=28) +Normal case - Final position: FILE*=15 (errno=0), mulle_buffer=2 (errno=0) +Read-only file - Initial position: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) +Read-only file - Seek to 3: FILE*=-1 (errno=22), mulle_buffer=-1 (errno=22) +Read-only file - Read at 3: FILE*='' (-1) (errno=0), mulle_buffer='V' (86) (errno=0) +Read-only file - Seek -2 from current: FILE*=0 (errno=0), mulle_buffer=-1 (errno=22) +Read-only file - Write 'X': FILE*=-1 (errno=9), mulle_buffer=-1 (errno=9) +Read-only file - Seek to end: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) +Read-only file - Final position: FILE*=2 (errno=0), mulle_buffer=2 (errno=0) Empty file - Initial position: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) Empty file - Seek to 3: FILE*=-1 (errno=22), mulle_buffer=-1 (errno=22) Empty file - Read at 3: FILE*='' (-1) (errno=9), mulle_buffer='' (-1) (errno=9) Empty file - Seek -2 from current: FILE*=-1 (errno=22), mulle_buffer=-1 (errno=22) Empty file - Write 'X': FILE*=88 (errno=0), mulle_buffer=88 (errno=0) -Empty file - Seek to end: FILE*=-1 (errno=28), mulle_buffer=0 (errno=0) -Empty file - Final position: FILE*=0 (errno=0), mulle_buffer=48 (errno=0) -Read-only file - Initial position: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) -Read-only file - Seek to 3: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) -Read-only file - Read at 3: FILE*=' ' (32) (errno=0), mulle_buffer=' ' (32) (errno=0) -Read-only file - Seek -2 from current: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) -Read-only file - Write 'X': FILE*=-1 (errno=9), mulle_buffer=-1 (errno=9) -Read-only file - Seek to end: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) -Read-only file - Final position: FILE*=15 (errno=0), mulle_buffer=15 (errno=0) +Empty file - Seek to end: FILE*=-1 (errno=28), mulle_buffer=-1 (errno=28) +Empty file - Final position: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) diff --git a/test/20_mimicry/fseek.stdout.darwin b/test/20_mimicry/fseek.stdout.darwin new file mode 100644 index 0000000..607cfe2 --- /dev/null +++ b/test/20_mimicry/fseek.stdout.darwin @@ -0,0 +1,15 @@ +Normal case - Initial position: FILE*=16 (errno=0), mulle_buffer=16 (errno=0) +Normal case - Seek to 3: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) +Normal case - Read at 3: FILE*=' ' (32) (errno=0), mulle_buffer='' (-1) (errno=9) +Normal case - Seek -2 from current: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) +Normal case - Write 'X': FILE*=-1 (errno=0), mulle_buffer=88 (errno=0) +Normal case - Seek to end: FILE*=-1 (errno=0), mulle_buffer=-1 (errno=28) +Normal case - Final position: FILE*=17 (errno=0), mulle_buffer=2 (errno=0) +Read-only file - Initial position: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) +Read-only file - Seek to 3: FILE*=-1 (errno=22), mulle_buffer=-1 (errno=22) +Read-only file - Read at 3: FILE*='V' (86) (errno=0), mulle_buffer='V' (86) (errno=0) +Read-only file - Seek -2 from current: FILE*=-1 (errno=22), mulle_buffer=-1 (errno=22) +Read-only file - Write 'X': FILE*=88 (errno=0), mulle_buffer=-1 (errno=9) +Read-only file - Seek to end: FILE*=0 (errno=0), mulle_buffer=0 (errno=0) +Read-only file - Final position: FILE*=2 (errno=0), mulle_buffer=2 (errno=0) +Error in Empty file: FILE * NULL; mulle_buffer: valid diff --git a/test/20_mimicry/fwrite.c b/test/20_mimicry/fwrite.c index 7dffee8..a87525c 100644 --- a/test/20_mimicry/fwrite.c +++ b/test/20_mimicry/fwrite.c @@ -32,7 +32,7 @@ static size_t safe_mulle_buffer_fwrite(const void *ptr, size_t size, size_t nmem size_t result; if (setjmp(jump_buffer) == 0) { - result = mulle_buffer_fwrite(ptr, size, nmemb, buffer); + result = mulle_buffer_fwrite( (void *) ptr, size, nmemb, buffer); } else { @@ -41,19 +41,28 @@ static size_t safe_mulle_buffer_fwrite(const void *ptr, size_t size, size_t nmem return result; } -static void compare_write(const void *ptr, size_t size, size_t nmemb, FILE *fp, void *buffer, const char *test_name) +static void compare_write( const void *ptr, size_t size, size_t nmemb, FILE *fp, void *buffer, const char *test_name) { size_t r1, r2; int errno1, errno2; + if( fp && ! buffer || ! fp && buffer) + { + printf("Error in %s: FILE * %s; mulle_buffer: %s\n", + test_name, + fp ? "valid" : "NULL", + buffer ? "valid" : "NULL"); + return; + } + signal(SIGSEGV, signal_handler); - errno = 0; - r1 = safe_fwrite(ptr, size, nmemb, fp); + errno = 0; + r1 = safe_fwrite( ptr, size, nmemb, fp); errno1 = errno; - errno = 0; - r2 = safe_mulle_buffer_fwrite(ptr, size, nmemb, buffer); + errno = 0; + r2 = safe_mulle_buffer_fwrite( ptr, size, nmemb, buffer); errno2 = errno; if (r1 == r2 && errno1 == errno2) @@ -64,12 +73,12 @@ static void compare_write(const void *ptr, size_t size, size_t nmemb, FILE *fp, } else { - printf("%s: Passed (result=%zu, errno=%d)\n", test_name, r1, errno1); + printf("%s: Passed (result=%zd, errno=%d)\n", test_name, r1, errno1); } } else { - printf("Error in %s: fwrite: result=%zu, errno=%d; mulle_buffer_fwrite: result=%zu, errno=%d\n", + printf("Error in %s: fwrite: result=%zd, errno=%d; mulle_buffer_fwrite: result=%zu, errno=%d\n", test_name, r1, errno1, r2, errno2); } @@ -82,32 +91,29 @@ static void test_write(void) void *buffer; const char test_data[] = "Hello, World!"; - // Test case 1: NULL pointers - compare_write(test_data, 1, strlen(test_data), NULL, NULL, "NULL pointers"); - - // Test case 2: Write to memory stream + // Test case 1: Write to memory stream fp = fmemopen(NULL, 100, "w"); buffer = mulle_buffer_fmemopen(NULL, 100, "w"); compare_write(test_data, 1, strlen(test_data), fp, buffer, "Write to memory stream"); fclose(fp); mulle_buffer_fclose(buffer); - // Test case 3: Write to full buffer + // Test case 2: Write to buffer char small_buf[5] = {0}; fp = fmemopen(small_buf, 5, "w"); buffer = mulle_buffer_fmemopen(small_buf, 5, "w"); - compare_write(test_data, 1, strlen(test_data), fp, buffer, "Write to full buffer"); + compare_write(test_data, 1, strlen(test_data), fp, buffer, "Write to buffer"); fclose(fp); mulle_buffer_fclose(buffer); - // Test case 4: Write-only empty file + // Test case 3: Write-only empty file fp = fmemopen(NULL, 0, "w"); buffer = mulle_buffer_fmemopen(NULL, 0, "w"); compare_write(test_data, 1, strlen(test_data), fp, buffer, "Write-only empty file"); fclose(fp); mulle_buffer_fclose(buffer); - // Test case 5: Multiple writes + // Test case 4: Multiple writes fp = fmemopen(NULL, 100, "w"); buffer = mulle_buffer_fmemopen(NULL, 100, "w"); for (int i = 0; i < 5; i++) @@ -119,12 +125,15 @@ static void test_write(void) fclose(fp); mulle_buffer_fclose(buffer); - // Test case 6: Write with different size and nmemb + // Test case 5: Write with different size and nmemb fp = fmemopen(NULL, 100, "w"); buffer = mulle_buffer_fmemopen(NULL, 100, "w"); compare_write(test_data, 2, strlen(test_data) / 2, fp, buffer, "Write with size=2, nmemb=6"); fclose(fp); mulle_buffer_fclose(buffer); + + // Test case 7: NULL pointers + compare_write(test_data, 1, strlen(test_data), NULL, NULL, "NULL pointers"); } int main(int argc, const char * argv[]) diff --git a/test/20_mimicry/fwrite.stdout b/test/20_mimicry/fwrite.stdout index 70f1a25..7f06072 100644 --- a/test/20_mimicry/fwrite.stdout +++ b/test/20_mimicry/fwrite.stdout @@ -1,6 +1,5 @@ -Error in NULL pointers: fwrite: result=18446744073709551615, errno=0; mulle_buffer_fwrite: result=0, errno=0 Write to memory stream: Passed (result=13, errno=0) -Write to full buffer: Passed (result=13, errno=0) +Write to buffer: Passed (result=13, errno=0) Write-only empty file: Passed (result=13, errno=0) Multiple writes: Passed (result=1, errno=0) Multiple writes: Passed (result=1, errno=0) @@ -8,3 +7,4 @@ Multiple writes: Passed (result=1, errno=0) Multiple writes: Passed (result=1, errno=0) Multiple writes: Passed (result=1, errno=0) Write with size=2, nmemb=6: Passed (result=6, errno=0) +NULL pointers: Passed (both crashed as expected) diff --git a/test/20_mimicry/fwrite.stdout.darwin b/test/20_mimicry/fwrite.stdout.darwin new file mode 100644 index 0000000..8b96a97 --- /dev/null +++ b/test/20_mimicry/fwrite.stdout.darwin @@ -0,0 +1,10 @@ +Error in Write to memory stream: FILE * NULL; mulle_buffer: valid +Error in Write to buffer: fwrite: result=5, errno=0; mulle_buffer_fwrite: result=0, errno=28 +Error in Write-only empty file: FILE * NULL; mulle_buffer: valid +Error in Multiple writes: FILE * NULL; mulle_buffer: valid +Error in Multiple writes: FILE * NULL; mulle_buffer: valid +Error in Multiple writes: FILE * NULL; mulle_buffer: valid +Error in Multiple writes: FILE * NULL; mulle_buffer: valid +Error in Multiple writes: FILE * NULL; mulle_buffer: valid +Error in Write with size=2, nmemb=6: FILE * NULL; mulle_buffer: valid +NULL pointers: Passed (both crashed as expected) diff --git a/test/20_mimicry/memopen.c b/test/20_mimicry/memopen.c index 9c656f4..bad1597 100644 --- a/test/20_mimicry/memopen.c +++ b/test/20_mimicry/memopen.c @@ -13,71 +13,73 @@ int main(void) char buf[100]; FILE *fp; - // Test 1: Open with NULL buffer and "w" mode - buffer = mulle_buffer_fmemopen(NULL, 100, "w"); - if (!buffer) { - printf("Test 1 failed: Could not open NULL buffer in write mode\n"); - return 1; - } - mulle_buffer_fclose(buffer); - - // Test 2: Open with NULL buffer and "r" mode (should fail) + // Test 1: Open with NULL buffer and "r" mode + // doesn't fail anymore buffer = mulle_buffer_fmemopen(NULL, 100, "r"); - if (buffer) { - printf("Test 2 failed: Opened NULL buffer in read mode\n"); + if (! buffer) { + fprintf( stderr, "Test 1 failed: Opened NULL buffer in read mode\n"); mulle_buffer_fclose(buffer); return 1; } + mulle_buffer_fclose(buffer); - // Test 3: Open with existing buffer and "r" mode + // Test 2: Open with existing buffer and "r" mode strcpy(buf, "Hello, World!"); buffer = mulle_buffer_fmemopen(buf, strlen(buf), "r"); if (!buffer) { - printf("Test 3 failed: Could not open existing buffer in read mode\n"); + fprintf( stderr, "Test 2 failed: Could not open existing buffer in read mode\n"); return 1; } mulle_buffer_fclose(buffer); - // Test 4: Open with existing buffer and "wü" mode (should clear buffer[ 0]) + // Test 3: Open with existing buffer and "wü" mode (should clear buffer[ 0]) buffer = mulle_buffer_fmemopen(buf, sizeof(buf), "w+"); if (!buffer) { - printf("Test 4 failed: Could not open existing buffer in write mode\n"); + fprintf( stderr, "Test 3 failed: Could not open existing buffer in write mode\n"); return 1; } if (buf[0] != '\0') { - printf("Test 4 failed: Buffer not cleared in write mode\n"); + fprintf( stderr, "Test 3 failed: Buffer not cleared in write mode\n"); mulle_buffer_fclose(buffer); return 1; } mulle_buffer_fclose(buffer); - // Test 5: Open with existing buffer and "a" mode + // Test 4: Open with existing buffer and "a" mode strcpy(buf, "Hello"); buffer = mulle_buffer_fmemopen(buf, sizeof(buf), "a"); if (!buffer) { - printf("Test 5 failed: Could not open existing buffer in append mode\n"); + fprintf( stderr, "Test 4 failed: Could not open existing buffer in append mode\n"); return 1; } mulle_buffer_fclose(buffer); - // Test 6: Open with zero size + // Test 5: Open with zero size fp = fmemopen( NULL, 0, "w"); buffer = mulle_buffer_fmemopen(NULL, 0, "w"); if (buffer && ! fp) { - printf("Test 6 failed: Opened buffer with zero size\n"); + fprintf( stderr, "Test 5 failed: Opened buffer with zero size\n"); mulle_buffer_fclose(buffer); return 1; } mulle_buffer_fclose(buffer); fclose( fp); - // Test 7: Open with invalid mode + // Test 6: Open with invalid mode buffer = mulle_buffer_fmemopen(buf, sizeof(buf), "x"); if (buffer) { - printf("Test 7 failed: Opened buffer with invalid mode\n"); + fprintf( stderr, "Test 6 failed: Opened buffer with invalid mode\n"); mulle_buffer_fclose(buffer); return 1; } + // Test 7: Open with NULL buffer and "w" mode + buffer = mulle_buffer_fmemopen(NULL, 100, "w"); + if (!buffer) { + fprintf( stderr, "Test 7 failed: Could not open NULL buffer in write mode\n"); + return 1; + } + mulle_buffer_fclose(buffer); + return 0; } diff --git a/test/20_mimicry/memopen.errors.darwin b/test/20_mimicry/memopen.errors.darwin new file mode 100644 index 0000000..3e98dd7 --- /dev/null +++ b/test/20_mimicry/memopen.errors.darwin @@ -0,0 +1 @@ +buffer with zero size diff --git a/test/20_mimicry/modes-buffer.c b/test/20_mimicry/modes-buffer.c new file mode 100644 index 0000000..f013e8c --- /dev/null +++ b/test/20_mimicry/modes-buffer.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include + +static void test_buffer( struct mulle_buffer *fp) +{ + int res1; + long off; + + off = mulle_buffer_ftell( fp); + printf( "off %ld\n", off); + + errno = 0; + res1 = mulle_buffer_fseek( fp, -2, SEEK_CUR); + printf( "res1 %d: %s\n", res1, strerror( errno)); + + off = mulle_buffer_ftell( fp); + printf( "off %ld\n", off); + + errno = 0; + res1 = mulle_buffer_fputc( 'X', fp); + printf( "res1 %d: %s\n", res1, strerror( errno)); + + off = mulle_buffer_ftell( fp); + printf( "off %ld\n", off); + + errno = 0; + res1 = mulle_buffer_fseek( fp, 0, SEEK_END); + printf( "res1 %d: %s\n", res1, strerror( errno)); + + off = mulle_buffer_ftell( fp); + printf( "off %ld\n", off); +} + + +static void test( char *mode) +{ + struct mulle_buffer *fp; + char test_string[] = "VfL Bochum 1848"; + + printf( "---------------- %s ----------------\n", mode); + fp = mulle_buffer_fmemopen( (void *) test_string, strlen( test_string) - 4, mode); + if( ! fp) + abort(); + + test_buffer( fp); + + mulle_buffer_fclose( fp); + + printf( "s: \"%s\"\n", test_string); +} + + +int main( void) +{ + test( "w"); + test( "a"); + test( "r"); + test( "w+"); + test( "a+"); + test( "r+"); + + return( 0); +} diff --git a/test/20_mimicry/modes-buffer.stdout b/test/20_mimicry/modes-buffer.stdout new file mode 100644 index 0000000..247bc70 --- /dev/null +++ b/test/20_mimicry/modes-buffer.stdout @@ -0,0 +1,54 @@ +---------------- w ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Success +off 1 +res1 -1: No space left on device +off 1 +s: "X" +---------------- a ---------------- +off 11 +res1 0: Success +off 9 +res1 88: Success +off 10 +res1 -1: No space left on device +off 10 +s: "VfL BochuX" +---------------- r ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 -1: Bad file descriptor +off 0 +res1 0: Success +off 11 +s: "VfL Bochum 1848" +---------------- w+ ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Success +off 1 +res1 -1: No space left on device +off 1 +s: "X" +---------------- a+ ---------------- +off 11 +res1 0: Success +off 9 +res1 88: Success +off 10 +res1 -1: No space left on device +off 10 +s: "VfL BochuX" +---------------- r+ ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Success +off 1 +res1 0: Success +off 11 +s: "XfL Bochum 1848" diff --git a/test/20_mimicry/modes-buffer.stdout.darwin b/test/20_mimicry/modes-buffer.stdout.darwin new file mode 100644 index 0000000..9fa8b73 --- /dev/null +++ b/test/20_mimicry/modes-buffer.stdout.darwin @@ -0,0 +1,54 @@ +---------------- w ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Undefined error: 0 +off 1 +res1 -1: No space left on device +off 1 +s: "X" +---------------- a ---------------- +off 11 +res1 0: Undefined error: 0 +off 9 +res1 88: Undefined error: 0 +off 10 +res1 -1: No space left on device +off 10 +s: "VfL BochuX" +---------------- r ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 -1: Bad file descriptor +off 0 +res1 0: Undefined error: 0 +off 11 +s: "VfL Bochum 1848" +---------------- w+ ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Undefined error: 0 +off 1 +res1 -1: No space left on device +off 1 +s: "X" +---------------- a+ ---------------- +off 11 +res1 0: Undefined error: 0 +off 9 +res1 88: Undefined error: 0 +off 10 +res1 -1: No space left on device +off 10 +s: "VfL BochuX" +---------------- r+ ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Undefined error: 0 +off 1 +res1 0: Undefined error: 0 +off 11 +s: "XfL Bochum 1848" diff --git a/test/20_mimicry/modes-fp.c b/test/20_mimicry/modes-fp.c new file mode 100644 index 0000000..3923908 --- /dev/null +++ b/test/20_mimicry/modes-fp.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include + + +static void test_file( FILE *fp) +{ + int res1; + long off; + + off = ftell( fp); + printf( "off %ld\n", off); + + errno = 0; + res1 = fseek( fp, -2, SEEK_CUR); + printf( "res1 %d: %s\n", res1, strerror( errno)); + + off = ftell( fp); + printf( "off %ld\n", off); + + errno = 0; + res1 = fputc( 'X', fp); + printf( "res1 %d: %s\n", res1, strerror( errno)); + + off = ftell( fp); + printf( "off %ld\n", off); + + errno = 0; + res1 = fseek( fp, 0, SEEK_END); + printf( "res1 %d: %s\n", res1, strerror( errno)); + + off = ftell( fp); + printf( "off %ld\n", off); +} + + +static void test( char *mode) +{ + FILE *fp; + char test_string[] = "VfL Bochum 1848"; + + printf( "---------------- %s ----------------\n", mode); + fp = fmemopen( (void *) test_string, strlen( test_string) - 4, mode); + if( ! fp) + abort(); + + test_file( fp); + + printf( "s: \"%s\"\n", test_string); + fclose( fp); +} + + +int main( void) +{ + test( "r"); + test( "w"); + test( "a"); + test( "r+"); + test( "w+"); + test( "a+"); + + return( 0); +} diff --git a/test/20_mimicry/modes-fp.stdout b/test/20_mimicry/modes-fp.stdout new file mode 100644 index 0000000..47075b1 --- /dev/null +++ b/test/20_mimicry/modes-fp.stdout @@ -0,0 +1,54 @@ +---------------- r ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 -1: Bad file descriptor +off 0 +res1 0: Success +off 11 +s: "VfL Bochum 1848" +---------------- w ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Success +off 1 +res1 0: Success +off 1 +s: "X" +---------------- a ---------------- +off 11 +res1 0: Success +off 9 +res1 88: Success +off 12 +res1 -1: No space left on device +off 11 +s: "VfL Bochum 1848" +---------------- r+ ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Success +off 1 +res1 0: Success +off 11 +s: "XfL Bochum 1848" +---------------- w+ ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Success +off 1 +res1 0: Success +off 1 +s: "X" +---------------- a+ ---------------- +off 11 +res1 0: Success +off 9 +res1 88: Success +off 12 +res1 -1: No space left on device +off 11 +s: "VfL Bochum 1848" diff --git a/test/20_mimicry/modes-fp.stdout.darwin b/test/20_mimicry/modes-fp.stdout.darwin new file mode 100644 index 0000000..4a731d9 --- /dev/null +++ b/test/20_mimicry/modes-fp.stdout.darwin @@ -0,0 +1,54 @@ +---------------- r ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Undefined error: 0 +off 1 +res1 0: Undefined error: 0 +off 11 +s: "X" +---------------- w ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Undefined error: 0 +off 1 +res1 0: Undefined error: 0 +off 1 +s: "X" +---------------- a ---------------- +off 11 +res1 0: Undefined error: 0 +off 9 +res1 -1: Undefined error: 0 +off 12 +res1 -1: Undefined error: 0 +off 12 +s: "VfL Bochum 1848" +---------------- r+ ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Undefined error: 0 +off 1 +res1 0: Undefined error: 0 +off 11 +s: "X" +---------------- w+ ---------------- +off 0 +res1 -1: Invalid argument +off 0 +res1 88: Undefined error: 0 +off 1 +res1 0: Undefined error: 0 +off 1 +s: "X" +---------------- a+ ---------------- +off 11 +res1 0: Undefined error: 0 +off 9 +res1 -1: Undefined error: 0 +off 12 +res1 -1: Undefined error: 0 +off 12 +s: "VfL Bochum 1848"