From 9fcf1b27fc705cc131b258478d95ce9de65aabc0 Mon Sep 17 00:00:00 2001 From: Owen Shepherd Date: Thu, 27 Dec 2012 00:46:40 +0000 Subject: [PATCH] Add an up to date POSIX port (works on Mac OS X). This is fully functional except for strerror. Warning cleanup is to come. --- platform/posix/Config.jam | 8 +- platform/posix/Jamfile | 2 + .../posix/functions/_PDCLIB/_PDCLIB_Exit.c | 4 +- .../functions/_PDCLIB/_PDCLIB_allocpages.c | 40 +++++ .../functions/_PDCLIB/_PDCLIB_freepages.c | 32 ++++ .../_PDCLIB/{rename.c => _PDCLIB_rename.c} | 51 +----- platform/posix/functions/_PDCLIB/allocpages.c | 83 --------- platform/posix/functions/_PDCLIB/close.c | 36 ---- platform/posix/functions/_PDCLIB/fillbuffer.c | 79 --------- .../posix/functions/_PDCLIB/flushbuffer.c | 111 ------------ platform/posix/functions/_PDCLIB/open.c | 166 ------------------ platform/posix/functions/_PDCLIB/seek.c | 73 -------- platform/posix/functions/_PDCLIB/stdinit.c | 7 +- platform/posix/functions/signal/signal.c | 7 +- .../posix/functions/stdio/_PDCLIB_fileops.c | 75 ++++++++ platform/posix/functions/stdio/_PDCLIB_open.c | 62 +++++++ platform/posix/functions/stdio/remove.c | 31 +--- platform/posix/functions/stdio/tmpfile.c | 65 +++---- platform/posix/includes/errno.h | 4 + platform/posix/internals/_PDCLIB_config.h | 126 +------------ 20 files changed, 265 insertions(+), 797 deletions(-) create mode 100644 platform/posix/Jamfile create mode 100644 platform/posix/functions/_PDCLIB/_PDCLIB_allocpages.c create mode 100644 platform/posix/functions/_PDCLIB/_PDCLIB_freepages.c rename platform/posix/functions/_PDCLIB/{rename.c => _PDCLIB_rename.c} (62%) delete mode 100644 platform/posix/functions/_PDCLIB/allocpages.c delete mode 100644 platform/posix/functions/_PDCLIB/close.c delete mode 100644 platform/posix/functions/_PDCLIB/fillbuffer.c delete mode 100644 platform/posix/functions/_PDCLIB/flushbuffer.c delete mode 100644 platform/posix/functions/_PDCLIB/open.c delete mode 100644 platform/posix/functions/_PDCLIB/seek.c create mode 100644 platform/posix/functions/stdio/_PDCLIB_fileops.c create mode 100644 platform/posix/functions/stdio/_PDCLIB_open.c create mode 100644 platform/posix/includes/errno.h diff --git a/platform/posix/Config.jam b/platform/posix/Config.jam index 92728f9..f068ce6 100644 --- a/platform/posix/Config.jam +++ b/platform/posix/Config.jam @@ -4,7 +4,11 @@ rule PDCLibTargetHeaders { SubDirHdrs $(PDCLIB_TOP) platform posix internals ; } -PDCLIB_TEST_LINKFLAGS += -nostdlib ; -PDCLIB_TEST_LINKLIBS += -lgcc ; +if $(OS) = "MACOSX" { + # Need to link libSystem +} else { + PDCLIB_TEST_LINKFLAGS += -nostdlib ; + PDCLIB_TEST_LINKLIBS += -lgcc ; +} PDCLIB_OPTIONS = nothread notime dlmalloc ; \ No newline at end of file diff --git a/platform/posix/Jamfile b/platform/posix/Jamfile new file mode 100644 index 0000000..88c948a --- /dev/null +++ b/platform/posix/Jamfile @@ -0,0 +1,2 @@ +SubDir PDCLIB_TOP platform posix ; +PDCLibConfig ; \ No newline at end of file diff --git a/platform/posix/functions/_PDCLIB/_PDCLIB_Exit.c b/platform/posix/functions/_PDCLIB/_PDCLIB_Exit.c index 5c95fca..6efed71 100644 --- a/platform/posix/functions/_PDCLIB/_PDCLIB_Exit.c +++ b/platform/posix/functions/_PDCLIB/_PDCLIB_Exit.c @@ -15,7 +15,7 @@ #ifndef REGTEST #include <_PDCLIB_glue.h> -extern void _exit( int status ) _PDCLIB_NORETURN; +extern void _exit( int status ) _PDCLIB_noreturn; void _PDCLIB_Exit( int status ) { @@ -29,9 +29,11 @@ void _PDCLIB_Exit( int status ) int main( void ) { +#ifndef REGTEST int UNEXPECTED_RETURN = 0; _PDCLIB_Exit( 0 ); TESTCASE( UNEXPECTED_RETURN ); +#endif return TEST_RESULTS; } diff --git a/platform/posix/functions/_PDCLIB/_PDCLIB_allocpages.c b/platform/posix/functions/_PDCLIB/_PDCLIB_allocpages.c new file mode 100644 index 0000000..c63e780 --- /dev/null +++ b/platform/posix/functions/_PDCLIB/_PDCLIB_allocpages.c @@ -0,0 +1,40 @@ +/* _PDCLIB_allocpages( int const ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +/* This is an example implementation of _PDCLIB_allocpages() (declared in + _PDCLIB_config.h), fit for use with POSIX kernels. +*/ + +#ifndef REGTEST +#include +#include +#include +#include <_PDCLIB_glue.h> + +void * _PDCLIB_allocpages( size_t n ) +{ + void *addr = mmap( + NULL, n * _PDCLIB_MALLOC_PAGESIZE, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + + if(addr != MAP_FAILED) { + return addr; + } else { + return NULL; + } +} + +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + return TEST_RESULTS; +} + +#endif diff --git a/platform/posix/functions/_PDCLIB/_PDCLIB_freepages.c b/platform/posix/functions/_PDCLIB/_PDCLIB_freepages.c new file mode 100644 index 0000000..ed4ea0c --- /dev/null +++ b/platform/posix/functions/_PDCLIB/_PDCLIB_freepages.c @@ -0,0 +1,32 @@ +/* _PDCLIB_freepages( void *, size_t ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +/* This is an example implementation of _PDCLIB_allocpages() (declared in + _PDCLIB_config.h), fit for use with POSIX kernels. +*/ + +#ifndef REGTEST +#include +#include +#include +#include <_PDCLIB_glue.h> + +void _PDCLIB_freepages( void * p, size_t n ) +{ + munmap( p, n * _PDCLIB_MALLOC_PAGESIZE ); +} + +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + return TEST_RESULTS; +} + +#endif \ No newline at end of file diff --git a/platform/posix/functions/_PDCLIB/rename.c b/platform/posix/functions/_PDCLIB/_PDCLIB_rename.c similarity index 62% rename from platform/posix/functions/_PDCLIB/rename.c rename to platform/posix/functions/_PDCLIB/_PDCLIB_rename.c index a37eeb3..cc5a173 100644 --- a/platform/posix/functions/_PDCLIB/rename.c +++ b/platform/posix/functions/_PDCLIB/_PDCLIB_rename.c @@ -27,29 +27,6 @@ int _PDCLIB_rename( const char * old, const char * new ) { if ( unlink( old ) == EOF ) { - switch ( errno ) - { - /* See the comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - case EACCES: - case EFAULT: - case EIO: - case EISDIR: - case ELOOP: - case ENAMETOOLONG: - case ENOENT: - case ENOMEM: - case ENOTDIR: - case EPERM: - case EROFS: - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } return -1; } else @@ -59,32 +36,6 @@ int _PDCLIB_rename( const char * old, const char * new ) } else { - switch ( errno ) - { - /* See the comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - case EACCES: - case EEXIST: - case EFAULT: - case EIO: - case ELOOP: - case EMLINK: - case ENAMETOOLONG: - case ENOENT: - case ENOMEM: - case ENOSPC: - case ENOTDIR: - case EPERM: - case EROFS: - case EXDEV: - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } return EOF; } } @@ -98,6 +49,7 @@ int _PDCLIB_rename( const char * old, const char * new ) int main( void ) { +#ifndef REGTEST FILE * file; remove( testfile1 ); remove( testfile2 ); @@ -133,6 +85,7 @@ int main( void ) /* remove both files */ remove( testfile1 ); remove( testfile2 ); +#endif return TEST_RESULTS; } diff --git a/platform/posix/functions/_PDCLIB/allocpages.c b/platform/posix/functions/_PDCLIB/allocpages.c deleted file mode 100644 index 435e8c6..0000000 --- a/platform/posix/functions/_PDCLIB/allocpages.c +++ /dev/null @@ -1,83 +0,0 @@ -/* $Id$ */ - -/* _PDCLIB_allocpages( int const ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_allocpages() (declared in - _PDCLIB_config.h), fit for use with POSIX kernels. -*/ - -#include -#include - -int brk( void * ); -void * sbrk( intptr_t ); - -#ifndef _PDCLIB_GLUE_H -#define _PDCLIB_GLUE_H _PDCLIB_GLUE_H -#include <_PDCLIB_glue.h> -#endif - -static void * membreak = NULL; - -void * _PDCLIB_allocpages( int const n ) -{ - if ( membreak == NULL ) - { - /* first call, make sure end-of-heap is page-aligned */ - intptr_t unaligned = 0; - membreak = sbrk( 0 ); - unaligned = _PDCLIB_PAGESIZE - (intptr_t)membreak % _PDCLIB_PAGESIZE; - if ( unaligned < _PDCLIB_PAGESIZE ) - { - /* end-of-heap not page-aligned - adjust */ - if ( sbrk( unaligned ) != membreak ) - { - /* error */ - return NULL; - } - membreak = (char *)membreak + unaligned; - } - } - /* increasing or decreasing heap - standard operation */ - void * oldbreak = membreak; - membreak = (void *)( (char *)membreak + ( n * _PDCLIB_PAGESIZE ) ); - if ( brk( membreak ) == 0 ) - { - /* successful */ - return oldbreak; - } - else - { - /* out of memory */ - membreak = oldbreak; - return NULL; - } -} - -#ifdef TEST -#include <_PDCLIB_test.h> - -int main( void ) -{ -#ifndef REGTEST - { - char * startbreak = sbrk( 0 ); - TESTCASE( _PDCLIB_allocpages( 0 ) ); - TESTCASE( ( (char *)sbrk( 0 ) - startbreak ) <= _PDCLIB_PAGESIZE ); - startbreak = sbrk( 0 ); - TESTCASE( _PDCLIB_allocpages( 1 ) ); - TESTCASE( sbrk( 0 ) == startbreak + ( 1 * _PDCLIB_PAGESIZE ) ); - TESTCASE( _PDCLIB_allocpages( 5 ) ); - TESTCASE( sbrk( 0 ) == startbreak + ( 6 * _PDCLIB_PAGESIZE ) ); - TESTCASE( _PDCLIB_allocpages( -3 ) ); - TESTCASE( sbrk( 0 ) == startbreak + ( 3 * _PDCLIB_PAGESIZE ) ); - } -#endif - return TEST_RESULTS; -} - -#endif diff --git a/platform/posix/functions/_PDCLIB/close.c b/platform/posix/functions/_PDCLIB/close.c deleted file mode 100644 index c4b6173..0000000 --- a/platform/posix/functions/_PDCLIB/close.c +++ /dev/null @@ -1,36 +0,0 @@ -/* $Id$ */ - -/* _PDCLIB_close( _PDCLIB_fd_t fd ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_close() fit for use with POSIX - kernels. -*/ - -#include - -#ifndef REGTEST -#include <_PDCLIB_glue.h> - -extern int close( int fd ); - -int _PDCLIB_close( int fd ) -{ - return close( fd ); -} - -#endif - -#ifdef TEST -#include <_PDCLIB_test.h> - -int main( void ) -{ - /* No testdriver; tested in driver for _PDCLIB_open(). */ - return TEST_RESULTS; -} - -#endif diff --git a/platform/posix/functions/_PDCLIB/fillbuffer.c b/platform/posix/functions/_PDCLIB/fillbuffer.c deleted file mode 100644 index 1d45025..0000000 --- a/platform/posix/functions/_PDCLIB/fillbuffer.c +++ /dev/null @@ -1,79 +0,0 @@ -/* $Id$ */ - -/* _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_fillbuffer() fit for - use with POSIX kernels. -*/ - -#include - -#ifndef REGTEST -#include <_PDCLIB_glue.h> - -#include - -typedef long ssize_t; -extern ssize_t read( int fd, void * buf, size_t count ); - -int _PDCLIB_fillbuffer( struct _PDCLIB_file_t * stream ) -{ - /* No need to handle buffers > INT_MAX, as PDCLib doesn't allow them */ - ssize_t rc = read( stream->handle, stream->buffer, stream->bufsize ); - if ( rc > 0 ) - { - /* Reading successful. */ - if ( ! ( stream->status & _PDCLIB_FBIN ) ) - { - /* TODO: Text stream conversion here */ - } - stream->pos.offset += rc; - stream->bufend = rc; - stream->bufidx = 0; - return 0; - } - if ( rc < 0 ) - { - /* Reading error */ - switch ( errno ) - { - /* See comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - case EBADF: - case EFAULT: - case EINTR: - case EINVAL: - case EIO: - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } - stream->status |= _PDCLIB_ERRORFLAG; - return EOF; - } - /* End-of-File */ - stream->status |= _PDCLIB_EOFFLAG; - return EOF; -} - -#endif - -#ifdef TEST -#include <_PDCLIB_test.h> - -int main( void ) -{ - /* Testing covered by ftell.c */ - return TEST_RESULTS; -} - -#endif - diff --git a/platform/posix/functions/_PDCLIB/flushbuffer.c b/platform/posix/functions/_PDCLIB/flushbuffer.c deleted file mode 100644 index e68c6c4..0000000 --- a/platform/posix/functions/_PDCLIB/flushbuffer.c +++ /dev/null @@ -1,111 +0,0 @@ -/* $Id$ */ - -/* _PDCLIB_flushbuffer( struct _PDCLIB_file_t * ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_flushbuffer() fit for - use with POSIX kernels. -*/ - -#include -#include - -#ifndef REGTEST -#include <_PDCLIB_glue.h> - -#include - -typedef long ssize_t; -extern ssize_t write( int fd, const void * buf, size_t count ); - -/* The number of attempts to complete an output buffer flushing before giving - * up. - * */ -#define _PDCLIB_IO_RETRIES 1 - -/* What the system should do after an I/O operation did not succeed, before */ -/* trying again. (Empty by default.) */ -#define _PDCLIB_IO_RETRY_OP( stream ) - -int _PDCLIB_flushbuffer( struct _PDCLIB_file_t * stream ) -{ - if ( ! ( stream->status & _PDCLIB_FBIN ) ) - { - /* TODO: Text stream conversion here */ - } - /* No need to handle buffers > INT_MAX, as PDCLib doesn't allow them */ - _PDCLIB_size_t written = 0; - int rc; - /* Keep trying to write data until everything is written, an error - occurs, or the configured number of retries is exceeded. - */ - for ( unsigned int retries = _PDCLIB_IO_RETRIES; retries > 0; --retries ) - { - rc = (int)write( stream->handle, stream->buffer + written, stream->bufidx - written ); - if ( rc < 0 ) - { - /* Write error */ - switch ( errno ) - { - /* See <_PDCLIB_config.h>. There should be differenciated errno - handling here, possibly even a 1:1 mapping; but that is up - to the individual platform. - */ - case EBADF: - case EFAULT: - case EFBIG: - case EINTR: - case EINVAL: - case EIO: - case ENOSPC: - case EPIPE: - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } - stream->status |= _PDCLIB_ERRORFLAG; - /* Move unwritten remains to begin of buffer. */ - stream->bufidx -= written; - memmove( stream->buffer, stream->buffer + written, stream->bufidx ); - return EOF; - } - written += (_PDCLIB_size_t)rc; - stream->pos.offset += rc; - if ( written == stream->bufidx ) - { - /* Buffer written completely. */ - stream->bufidx = 0; - return 0; - } - } - /* Number of retries exceeded. You probably want a different errno value - here. - */ - _PDCLIB_errno = _PDCLIB_ERROR; - stream->status |= _PDCLIB_ERRORFLAG; - /* Move unwritten remains to begin of buffer. */ - stream->bufidx -= written; - memmove( stream->buffer, stream->buffer + written, stream->bufidx ); - return EOF; -} - -#endif - - -#ifdef TEST -#include <_PDCLIB_test.h> - -int main( void ) -{ - /* Testing covered by ftell.c */ - return TEST_RESULTS; -} - -#endif - diff --git a/platform/posix/functions/_PDCLIB/open.c b/platform/posix/functions/_PDCLIB/open.c deleted file mode 100644 index 2098dd3..0000000 --- a/platform/posix/functions/_PDCLIB/open.c +++ /dev/null @@ -1,166 +0,0 @@ -/* $Id$ */ - -/* _PDCLIB_open( char const * const, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -/* This is an example implementation of _PDCLIB_open() fit for use with POSIX - kernels. -*/ - -#include - -#ifndef REGTEST -#include <_PDCLIB_glue.h> - -#include -#include -#include -#include - -#include "/usr/include/errno.h" - -int _PDCLIB_open( char const * const filename, unsigned int mode ) -{ - /* This is an example implementation of _PDCLIB_open() fit for use with - POSIX kernels. - */ - int osmode; - switch ( mode & ( _PDCLIB_FREAD | _PDCLIB_FWRITE | _PDCLIB_FAPPEND | _PDCLIB_FRW ) ) - { - case _PDCLIB_FREAD: /* "r" */ - osmode = O_RDONLY; - break; - case _PDCLIB_FWRITE: /* "w" */ - osmode = O_WRONLY | O_CREAT | O_TRUNC; - break; - case _PDCLIB_FAPPEND: /* "a" */ - osmode = O_WRONLY | O_APPEND | O_CREAT; - break; - case _PDCLIB_FREAD | _PDCLIB_FRW: /* "r+" */ - osmode = O_RDWR; - break; - case _PDCLIB_FWRITE | _PDCLIB_FRW: /* "w+" */ - osmode = O_RDWR | O_CREAT | O_TRUNC; - break; - case _PDCLIB_FAPPEND | _PDCLIB_FRW: /* "a+" */ - osmode = O_RDWR | O_APPEND | O_CREAT; - break; - default: /* Invalid mode */ - return -1; - } - int rc; - if ( osmode & O_CREAT ) - { - rc = open( filename, osmode, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ); - } - else - { - rc = open( filename, osmode ); - } - if ( rc == -1 ) - { - switch ( errno ) - { - /* See the comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - case EACCES: - case EFAULT: - case EINTR: - case EISDIR: - case ELOOP: - case EMFILE: - case ENAMETOOLONG: - case ENFILE: - case ENODEV: - case ENOENT: - case ENOMEM: - case ENOSPC: - case ENOTDIR: - case EOVERFLOW: - case EROFS: - case ETXTBSY: - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } - } - return rc; -} - -#endif - -#ifdef TEST -#include <_PDCLIB_test.h> - -#include -#include - -int main( void ) -{ - /* This testdriver assumes POSIX, i.e. _PDCLIB_fd_t being int and being - incremented by one on each successful open. - */ - int fh; - char buffer[ 10 ]; - remove( testfile ); - /* Trying to read non-existent file. */ - TESTCASE( _PDCLIB_open( testfile, _PDCLIB_FREAD ) == _PDCLIB_NOHANDLE ); - /* Writing to file, trying to read from it. */ - TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FWRITE ) ) != _PDCLIB_NOHANDLE ); - TESTCASE( write( fh, "test", 4 ) == 4 ); - TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 ); - TESTCASE( read( fh, buffer, 4 ) == -1 ); - TESTCASE( _PDCLIB_close( fh ) == 0 ); - /* Reading from file, trying to write to it. */ - TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FREAD ) ) != _PDCLIB_NOHANDLE ); - TESTCASE( write( fh, "test", 4 ) == -1 ); - TESTCASE( _PDCLIB_close( fh ) == 0 ); - /* Appending to file, trying to read from it. */ - TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FAPPEND ) ) != _PDCLIB_NOHANDLE ); - TESTCASE( write( fh, "app", 3 ) == 3 ); - TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 ); - TESTCASE( read( fh, buffer, 10 ) == -1 ); - TESTCASE( write( fh, "end", 3 ) == 3 ); - TESTCASE( _PDCLIB_close( fh ) == 0 ); - /* Reading and writing from file ("r+"). */ - TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FREAD | _PDCLIB_FRW ) ) != _PDCLIB_NOHANDLE ); - TESTCASE( read( fh, buffer, 10 ) == 10 ); - TESTCASE( memcmp( buffer, "testappend", 10 ) == 0 ); - TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 ); - TESTCASE( write( fh, "wedo", 4 ) == 4 ); - TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 ); - TESTCASE( read( fh, buffer, 10 ) == 10 ); - TESTCASE( memcmp( buffer, "wedoappend", 10 ) == 0 ); - TESTCASE( _PDCLIB_close( fh ) == 0 ); - /* Writing and reading from file ("w+"). */ - TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FWRITE | _PDCLIB_FRW ) ) != _PDCLIB_NOHANDLE ); - TESTCASE( write( fh, "test", 4 ) == 4 ); - TESTCASE( lseek( fh, 1, SEEK_SET ) == 1 ); - TESTCASE( read( fh, buffer, 2 ) == 2 ); - TESTCASE( memcmp( buffer, "es", 2 ) == 0 ); - TESTCASE( write( fh, "sie", 3 ) == 3 ); - TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 ); - TESTCASE( read( fh, buffer, 6 ) == 6 ); - TESTCASE( memcmp( buffer, "tessie", 6 ) == 0 ); - TESTCASE( _PDCLIB_close( fh ) == 0 ); - /* Appending and reading from file ("a+"). */ - TESTCASE( ( fh = _PDCLIB_open( testfile, _PDCLIB_FAPPEND | _PDCLIB_FRW ) ) != _PDCLIB_NOHANDLE ); - TESTCASE( write( fh, "baby", 4 ) == 4 ); - TESTCASE( lseek( fh, 0, SEEK_SET ) == 0 ); - TESTCASE( read( fh, buffer, 10 ) == 10 ); - TESTCASE( memcmp( buffer, "tessiebaby", 10 ) == 0 ); - TESTCASE( _PDCLIB_close( fh ) == 0 ); - /* Cleaning up. */ - TESTCASE( remove( testfile ) == 0 ); - return TEST_RESULTS; -} - -#endif - diff --git a/platform/posix/functions/_PDCLIB/seek.c b/platform/posix/functions/_PDCLIB/seek.c deleted file mode 100644 index 755abe2..0000000 --- a/platform/posix/functions/_PDCLIB/seek.c +++ /dev/null @@ -1,73 +0,0 @@ -/* $Id$ */ - -/* int64_t _PDCLIB_seek( FILE *, int64_t, int ) - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#include - -#ifndef _PDCLIB_GLUE_H -#define _PDCLIB_GLUE_H -#include <_PDCLIB_glue.h> -#endif - -#include "/usr/include/errno.h" - -extern _PDCLIB_int64_t lseek64( int fd, _PDCLIB_int64_t offset, int whence ); - -_PDCLIB_int64_t _PDCLIB_seek( struct _PDCLIB_file_t * stream, _PDCLIB_int64_t offset, int whence ) -{ - switch ( whence ) - { - case SEEK_SET: - case SEEK_CUR: - case SEEK_END: - /* EMPTY - OK */ - break; - default: - /* See comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - _PDCLIB_errno = _PDCLIB_ERROR; - return EOF; - break; - } - _PDCLIB_int64_t rc = lseek64( stream->handle, offset, whence ); - if ( rc != EOF ) - { - stream->ungetidx = 0; - stream->bufidx = 0; - stream->bufend = 0; - stream->pos.offset = rc; - return rc; - } - switch ( errno ) - { - case EBADF: - case EFAULT: - /* See comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } - return EOF; -} - -#ifdef TEST -#include <_PDCLIB_test.h> - -int main( void ) -{ - /* Testing covered by ftell.c */ - return TEST_RESULTS; -} - -#endif - diff --git a/platform/posix/functions/_PDCLIB/stdinit.c b/platform/posix/functions/_PDCLIB/stdinit.c index 2554e9f..8400ce3 100644 --- a/platform/posix/functions/_PDCLIB/stdinit.c +++ b/platform/posix/functions/_PDCLIB/stdinit.c @@ -29,9 +29,10 @@ static unsigned char _PDCLIB_sin_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; static unsigned char _PDCLIB_sout_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; static unsigned char _PDCLIB_serr_ungetbuf[_PDCLIB_UNGETCBUFSIZE]; -static struct _PDCLIB_file_t _PDCLIB_serr = { 2, _PDCLIB_serr_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_serr_ungetbuf, _IONBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, NULL }; -static struct _PDCLIB_file_t _PDCLIB_sout = { 1, _PDCLIB_sout_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sout_ungetbuf, _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, &_PDCLIB_serr }; -static struct _PDCLIB_file_t _PDCLIB_sin = { 0, _PDCLIB_sin_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sin_ungetbuf, _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC, NULL, &_PDCLIB_sout }; +extern _PDCLIB_fileops_t _PDCLIB_fileops; +static struct _PDCLIB_file_t _PDCLIB_serr = { &_PDCLIB_fileops, { .sval = 2 }, 0, _PDCLIB_serr_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_serr_ungetbuf, _IONBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, NULL }; +static struct _PDCLIB_file_t _PDCLIB_sout = { &_PDCLIB_fileops, { .sval = 1 }, 0, _PDCLIB_sout_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sout_ungetbuf, _IOLBF | _PDCLIB_FWRITE | _PDCLIB_STATIC, NULL, &_PDCLIB_serr }; +static struct _PDCLIB_file_t _PDCLIB_sin = { &_PDCLIB_fileops, { .sval = 0 }, 0, _PDCLIB_sin_buffer, BUFSIZ, 0, 0, { 0, 0 }, 0, _PDCLIB_sin_ungetbuf, _IOLBF | _PDCLIB_FREAD | _PDCLIB_STATIC, NULL, &_PDCLIB_sout }; struct _PDCLIB_file_t * stdin = &_PDCLIB_sin; struct _PDCLIB_file_t * stdout = &_PDCLIB_sout; diff --git a/platform/posix/functions/signal/signal.c b/platform/posix/functions/signal/signal.c index e07877d..d666b24 100644 --- a/platform/posix/functions/signal/signal.c +++ b/platform/posix/functions/signal/signal.c @@ -9,8 +9,8 @@ #include #ifndef REGTEST - #include +#include void (*_PDCLIB_sigabrt)( int ) = SIG_DFL; void (*_PDCLIB_sigfpe)( int ) = SIG_DFL; @@ -53,10 +53,7 @@ void (*signal( int sig, void (*func)( int ) ) )( int ) _PDCLIB_sigterm = func; break; default: - /* The standard calls for an unspecified "positive value". You - will probably want to define a specific value for this. - */ - _PDCLIB_errno = 1; + errno = EINVAL; return SIG_ERR; } return oldhandler; diff --git a/platform/posix/functions/stdio/_PDCLIB_fileops.c b/platform/posix/functions/stdio/_PDCLIB_fileops.c new file mode 100644 index 0000000..20138b7 --- /dev/null +++ b/platform/posix/functions/stdio/_PDCLIB_fileops.c @@ -0,0 +1,75 @@ +/* _PDCLIB_fileops + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef REGTEST +#include +#include +#include <_PDCLIB_glue.h> +#include +#include + +static bool readf( _PDCLIB_fd_t fd, void * buf, size_t length, + size_t * numBytesRead ) +{ + ssize_t res = read(fd.sval, buf, length); + if(res == -1) { + return false; + } else { + *numBytesRead = res; + return true; + } +} + +static bool writef( _PDCLIB_fd_t fd, const void * buf, size_t length, + size_t * numBytesWritten ) +{ + ssize_t res = write(fd.sval, buf, length); + if(res == -1) { + return false; + } else { + *numBytesWritten = res; + return true; + } +} + +/* Note: Assumes being compiled with an OFF64 programming model */ + +static bool seekf( _PDCLIB_fd_t fd, int_fast64_t offset, int whence, + int_fast64_t* newPos ) +{ + off_t npos = lseek( fd.sval, offset, whence ); + if( npos == -1 ) { + return false; + } else { + *newPos = npos; + return true; + } +} + +static void closef( _PDCLIB_fd_t self ) +{ + close( self.sval ); +} + +const _PDCLIB_fileops_t _PDCLIB_fileops = { + .read = readf, + .write = writef, + .seek = seekf, + .close = closef, +}; + +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + // Tested by stdio test cases + return TEST_RESULTS; +} + +#endif diff --git a/platform/posix/functions/stdio/_PDCLIB_open.c b/platform/posix/functions/stdio/_PDCLIB_open.c new file mode 100644 index 0000000..9f3cdec --- /dev/null +++ b/platform/posix/functions/stdio/_PDCLIB_open.c @@ -0,0 +1,62 @@ +/* _PDCLIB_open(_PDCLIB_fd_t*, const _PDCLIB_fileops_t**, + char const*, unsigned int) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ +#ifndef REGTEST +#include <_PDCLIB_glue.h> +#include <_PDCLIB_io.h> +#include + +extern const _PDCLIB_fileops_t _PDCLIB_fileops; + +bool _PDCLIB_open( + _PDCLIB_fd_t* fd, const _PDCLIB_fileops_t** ops, + char const * filename, unsigned int mode ) +{ + int osmode; + switch ( mode & ( _PDCLIB_FREAD | _PDCLIB_FWRITE | _PDCLIB_FAPPEND | _PDCLIB_FRW ) ) + { + case _PDCLIB_FREAD: /* "r" */ + osmode = O_RDONLY; + break; + case _PDCLIB_FWRITE: /* "w" */ + osmode = O_WRONLY | O_CREAT | O_TRUNC; + break; + case _PDCLIB_FAPPEND: /* "a" */ + osmode = O_WRONLY | O_APPEND | O_CREAT; + break; + case _PDCLIB_FREAD | _PDCLIB_FRW: /* "r+" */ + osmode = O_RDWR; + break; + case _PDCLIB_FWRITE | _PDCLIB_FRW: /* "w+" */ + osmode = O_RDWR | O_CREAT | O_TRUNC; + break; + case _PDCLIB_FAPPEND | _PDCLIB_FRW: /* "a+" */ + osmode = O_RDWR | O_APPEND | O_CREAT; + break; + default: /* Invalid mode */ + return -1; + } + + fd->sval = open(filename, osmode, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + if(fd->sval == -1) { + return false; + } + + *ops = &_PDCLIB_fileops; + return true; +} +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + return TEST_RESULTS; +} + +#endif \ No newline at end of file diff --git a/platform/posix/functions/stdio/remove.c b/platform/posix/functions/stdio/remove.c index 389df30..f4f63fe 100644 --- a/platform/posix/functions/stdio/remove.c +++ b/platform/posix/functions/stdio/remove.c @@ -15,15 +15,12 @@ #include -#include "/usr/include/errno.h" - extern struct _PDCLIB_file_t * _PDCLIB_filelist; extern int unlink( const char * pathname ); int remove( const char * pathname ) { - int rc; struct _PDCLIB_file_t * current = _PDCLIB_filelist; while ( current != NULL ) { @@ -33,33 +30,7 @@ int remove( const char * pathname ) } current = current->next; } - if ( ( rc = unlink( pathname ) ) == -1 ) - { - switch ( errno ) - { - /* See the comments on implementation-defined errno values in - <_PDCLIB_config.h>. - */ - case EACCES: - case EFAULT: - case EIO: - case EISDIR: - case ELOOP: - case ENAMETOOLONG: - case ENOENT: - case ENOMEM: - case ENOTDIR: - case EPERM: - case EROFS: - _PDCLIB_errno = _PDCLIB_ERROR; - break; - default: - /* This should be something like EUNKNOWN. */ - _PDCLIB_errno = _PDCLIB_ERROR; - break; - } - } - return rc; + return unlink( pathname ); } #endif diff --git a/platform/posix/functions/stdio/tmpfile.c b/platform/posix/functions/stdio/tmpfile.c index 29750d4..deb992c 100644 --- a/platform/posix/functions/stdio/tmpfile.c +++ b/platform/posix/functions/stdio/tmpfile.c @@ -21,36 +21,32 @@ #include #include -extern struct _PDCLIB_file_t * _PDCLIB_filelist; +extern const _PDCLIB_fileops_t _PDCLIB_fileops; -/* This is an example implementation of tmpfile() fit for use with POSIX - kernels. -*/ -struct _PDCLIB_file_t * tmpfile( void ) +FILE* _PDCLIB_nothrow tmpfile( void ) { - FILE * rc; - /* This is the chosen way to get high-quality randomness. Replace as - appropriate. - */ - FILE * randomsource = fopen( "/proc/sys/kernel/random/uuid", "rb" ); - char filename[ L_tmpnam ]; - _PDCLIB_fd_t fd; - if ( randomsource == NULL ) + + /* Good quality random source */ + int urandom = open( "/dev/urandom", O_RDONLY | O_CLOEXEC ); + if(urandom == -1) { + // TODO: errno! return NULL; } + + int fd; + char filename[ L_tmpnam ]; for ( ;; ) { - /* Get a filename candidate. What constitutes a valid filename and - where temporary files are usually located is platform-dependent, - which is one reason why this function is located in the platform - overlay. The other reason is that a *good* implementation should - use high-quality randomness instead of a pseudo-random sequence to - generate the filename candidate, which is *also* platform-dependent. - */ - unsigned int random; - fscanf( randomsource, "%u", &random ); - sprintf( filename, "/tmp/%u.tmp", random ); + long long randnum; + if( read(urandom, &randnum, sizeof randnum ) != sizeof randnum ) + { + // TODO: errno! + close( urandom ); + return NULL; + } + + sprintf( filename, "/tmp/%llx.tmp", randnum ); /* Check if file of this name exists. Note that fopen() is a very weak check, which does not take e.g. access permissions into account (file might exist but not readable). Replace with something more @@ -61,27 +57,18 @@ struct _PDCLIB_file_t * tmpfile( void ) { break; } - close( fd ); } - fclose( randomsource ); - /* See fopen(). */ - if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) + _PDCLIB_UNGETCBUFSIZE + L_tmpnam + BUFSIZ ) ) == NULL ) + close( urandom ); + + FILE* rc = _PDCLIB_fvopen(((_PDCLIB_fd_t){ .sval = fd}), &_PDCLIB_fileops, + _PDCLIB_FWRITE | _PDCLIB_FRW | + _PDCLIB_DELONCLOSE, filename); + if( rc == NULL ) { - /* No memory to set up FILE structure */ close( fd ); return NULL; } - rc->status = _PDCLIB_filemode( "wb+" ) | _IOLBF | _PDCLIB_DELONCLOSE; - rc->handle = fd; - rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t ); - rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE; - rc->buffer = rc->filename + L_tmpnam; - strcpy( rc->filename, filename ); - rc->bufsize = BUFSIZ; - rc->bufidx = 0; - rc->ungetidx = 0; - rc->next = _PDCLIB_filelist; - _PDCLIB_filelist = rc; + return rc; } diff --git a/platform/posix/includes/errno.h b/platform/posix/includes/errno.h new file mode 100644 index 0000000..5e6f8a0 --- /dev/null +++ b/platform/posix/includes/errno.h @@ -0,0 +1,4 @@ +#ifndef _PDCLIB_ERRNO_H +#define _PDCLIB_ERRNO_H +#include +#endif diff --git a/platform/posix/internals/_PDCLIB_config.h b/platform/posix/internals/_PDCLIB_config.h index 314eed5..5cee1ef 100644 --- a/platform/posix/internals/_PDCLIB_config.h +++ b/platform/posix/internals/_PDCLIB_config.h @@ -62,6 +62,9 @@ #endif #define _PDCLIB_LLONG_BYTES 8 +// Match Darwin headers +#define _PDCLIB_INT64_IS_LLONG + /* defines the div() function family that allows taking quotient */ /* and remainder of an integer division in one operation. Many platforms */ /* support this in hardware / opcode, and the standard permits ordering of */ @@ -147,9 +150,9 @@ struct _PDCLIB_lldiv_t /* Large enough an integer to hold all character codes of the largest supported locale. */ -#define _PDCLIB_wint signed int -#define _PDCLIB_wchar unsigned int -#define _PDCLIB_WCHAR UINT +#define _PDCLIB_wint int +#define _PDCLIB_wchar int +#define _PDCLIB_WCHAR INT #define _PDCLIB_intptr long #define _PDCLIB_INTPTR LONG @@ -354,121 +357,4 @@ struct _PDCLIB_imaxdiv_t */ #define _PDCLIB_UNGETCBUFSIZE 1 -/* errno -------------------------------------------------------------------- */ - -/* These are the values that _PDCLIB_errno can be set to by the library. - - By keeping PDCLib's errno in the _PDCLIB_* namespace, the library is capable - to "translate" between errno values used by the hosting operating system and - those used and passed out by the library. - - Example: In the example platform, the remove() function uses the unlink() - system call as backend. Linux sets its errno to EISDIR if you try to unlink() - a directory, but POSIX demands EPERM. Within the remove() function, you can - catch the 'errno == EISDIR', and set '_PDCLIB_errno = _PDCLIB_EPERM'. Anyone - using PDCLib's will "see" EPERM instead of EISDIR (the _PDCLIB_* - prefix removed by mechanics). - - If you do not want that kind of translation, you might want to "match" the - values used by PDCLib with those used by the host OS, as to avoid confusion. - - The C standard only defines three distinct errno values: ERANGE, EDOM, and - EILSEQ. The standard leaves it up to "the implementation" whether there are - any more beyond those three. There is some controversy as to whether errno is - such a good idea at all, so you might want to come up with a different error - reporting facility for your platform. - - Things used to say "Since errno values beyond the three defined by the - standard are not portable anyway (unless you look at POSIX), having your own - error reporting facility would not hurt anybody either." at this point. - However, then somebody birthed C++11 into the world, which copied POSIX's - errno values into C++. Yes, even EINTR. Therefore, this library defines - them. That said, thats nothing stopping you from using your own error - reporting facility for things outside the C library. - - Sometimes the standard says to set errno to indicate an error, but does not - prescribe a value. We will use a value from the following list. If POSIX - defines a value, we use that; otherwise, we use as seems suitable. - - If porting to a system which uses an errno-like reporting system (e.g. a - UNIX), you'll probably want to define them to match what the OS uses -*/ -/* C errno values */ -#define _PDCLIB_ERANGE 1 -#define _PDCLIB_EDOM 2 -#define _PDCLIB_EILSEQ 3 - -/* C++11/POSIX errno values */ -#define _PDCLIB_E2BIG 4 -#define _PDCLIB_ECONNRESET 5 -#define _PDCLIB_EISCONN 6 -#define _PDCLIB_ENOENT 7 -#define _PDCLIB_ENOTRECOVERABLE 8 -#define _PDCLIB_EROFS 9 -#define _PDCLIB_EACCES 10 -#define _PDCLIB_EDEADLK 11 -#define _PDCLIB_EISDIR 12 -#define _PDCLIB_ENOEXEC 13 -#define _PDCLIB_ENOTSOCK 14 -#define _PDCLIB_ESPIPE 15 -#define _PDCLIB_EADDRINUSE 16 -#define _PDCLIB_EDESTADDRREQ 17 -#define _PDCLIB_ELOOP 18 -#define _PDCLIB_ENOLCK 19 -#define _PDCLIB_ENOTSUPP 20 -#define _PDCLIB_ESRCH 21 -#define _PDCLIB_EADDRNOTAVAIL 22 -#define _PDCLIB_EMFILE 23 -#define _PDCLIB_ENOLINK 24 -#define _PDCLIB_ENOTTY 25 -#define _PDCLIB_ETIME 26 -#define _PDCLIB_EAFNOSUPPORT 27 -#define _PDCLIB_EEXIST 28 -#define _PDCLIB_EMLINK 29 -#define _PDCLIB_ENOMEM 30 -#define _PDCLIB_ENXIO 31 -#define _PDCLIB_ETIMEDOUT 32 -#define _PDCLIB_EAGAIN 33 -#define _PDCLIB_EFAULT 34 -#define _PDCLIB_EMSGSIZE 35 -#define _PDCLIB_ENOMSG 36 -#define _PDCLIB_EOPNOTSUPP 37 -#define _PDCLIB_ETXTBSY 38 -#define _PDCLIB_EALREADY 39 -#define _PDCLIB_EFBIG 40 -#define _PDCLIB_ENAMETOOLONG 41 -#define _PDCLIB_ENOPROTOOPT 42 -#define _PDCLIB_EOVERFLOW 43 -#define _PDCLIB_EWOULDBLOCK _PDCLIB_EAGAIN -#define _PDCLIB_EBADF 44 -#define _PDCLIB_EHOSTUNREACH 45 -#define _PDCLIB_ENETDOWN 46 -#define _PDCLIB_ENOSPC 47 -#define _PDCLIB_EOWNERDEAD 48 -#define _PDCLIB_EXDEV 49 -#define _PDCLIB_EBADMSG 50 -#define _PDCLIB_EIDRM 51 -#define _PDCLIB_ENETRESET 52 -#define _PDCLIB_ENOSR 53 -#define _PDCLIB_EPERM 54 -#define _PDCLIB_EBUSY 55 -#define _PDCLIB_ENETUNREACH 56 -#define _PDCLIB_ENOSTR 57 -#define _PDCLIB_EPIPE 58 -#define _PDCLIB_ECANCELED 59 -#define _PDCLIB_EINPROGRESS 60 -#define _PDCLIB_ENFILE 61 -#define _PDCLIB_ENOSYS 62 -#define _PDCLIB_EPROTO 63 -#define _PDCLIB_ECHILD 64 -#define _PDCLIB_EINTR 65 -#define _PDCLIB_ENOBUFS 66 -#define _PDCLIB_ENOTCONN 67 -#define _PDCLIB_EPROTONOSUPPORT 68 -#define _PDCLIB_ECONNABORTED 69 -#define _PDCLIB_EINVAL 70 -#define _PDCLIB_ENODATA 71 -#define _PDCLIB_ENOTDIR 72 -#define _PDCLIB_EPROTOTYPE 73 - #endif -- 2.40.0