diff --git a/libc/Makefile b/libc/Makefile index f118b39b..954163d4 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -66,56 +66,88 @@ signal/signotset.o \ signal/sigorset.o \ stdio/asprintf.o \ stdio/clearerr.o \ +stdio/clearerr_unlocked.o \ stdio/dprintf.o \ stdio/fbufsize.o \ +stdio/fbufsize_unlocked.o \ stdio/fclose.o \ stdio/fdeletefile.o \ stdio/feof.o \ +stdio/feof_unlocked.o \ stdio/ferror.o \ +stdio/ferror_unlocked.o \ stdio/fflush.o \ stdio/fflush_stop_reading.o \ +stdio/fflush_stop_reading_unlocked.o \ stdio/fflush_stop_writing.o \ +stdio/fflush_stop_writing_unlocked.o \ +stdio/fflush_unlocked.o \ stdio/fgetc.o \ +stdio/fgetc_unlocked.o \ stdio/fgets.o \ +stdio/fgets_unlocked.o \ +stdio/fileno_unlocked.o \ stdio/flbf.o \ +stdio/flbf_unlocked.o \ stdio/flockfile.o \ stdio/flushlbf.o \ stdio/fnewfile.o \ stdio/fpending.o \ +stdio/fpending_unlocked.o \ +stdio/fprintf_unlocked.o \ stdio/fpurge.o \ +stdio/fpurge_unlocked.o \ stdio/fputc.o \ +stdio/fputc_unlocked.o \ stdio/fputs.o \ +stdio/fputs_unlocked.o \ stdio/freadable.o \ +stdio/freadable_unlocked.o \ stdio/freading.o \ +stdio/freading_unlocked.o \ stdio/fread.o \ +stdio/fread_unlocked.o \ stdio/fregister.o \ stdio/fresetfile.o \ stdio/fscanf.o \ +stdio/fscanf_unlocked.o \ stdio/fseek.o \ stdio/fseeko.o \ +stdio/fseeko_unlocked.o \ stdio/fsetdefaultbuf.o \ +stdio/fsetdefaultbuf_unlocked.o \ stdio/fseterr.o \ +stdio/fseterr_unlocked.o \ stdio/fsetlocking.o \ +stdio/fsetlocking_unlocked.o \ stdio/fshutdown.o \ stdio/ftell.o \ stdio/ftello.o \ +stdio/ftello_unlocked.o \ stdio/ftrylockfile.o \ stdio/funlockfile.o \ stdio/fwritable.o \ +stdio/fwritable_unlocked.o \ stdio/fwrite.o \ +stdio/fwrite_unlocked.o \ stdio/fwriting.o \ +stdio/fwriting_unlocked.o \ stdio/getdelim.o \ stdio/getline.o \ stdio/rewind.o \ stdio/setbuf.o \ stdio/setvbuf.o \ +stdio/setvbuf_unlocked.o \ stdio/snprintf.o \ stdio/sprintf.o \ stdio/sscanf.o \ stdio/ungetc.o \ +stdio/ungetc_unlocked.o \ stdio/vasprintf.o \ stdio/vdprintf.o \ +stdio/vfprintf_unlocked.o \ stdio/vfscanf.o \ +stdio/vfscanf_unlocked.o \ stdio/vprintf_callback.o \ stdio/vscanf_callback.o \ stdio/vsnprintf.o \ @@ -359,10 +391,12 @@ stdio/fprintf.o \ stdio/freopen.o \ stdio/fsetpos.o \ stdio/getc.o \ +stdio/getc_unlocked.o \ stdio/perror.o \ stdio/popen.o \ stdio/printf.o \ stdio/putc.o \ +stdio/putc_unlocked.o \ stdio/removeat.o \ stdio/remove.o \ stdio/renameat.o \ diff --git a/libc/include/FILE.h b/libc/include/FILE.h index 8c516963..9399b700 100644 --- a/libc/include/FILE.h +++ b/libc/include/FILE.h @@ -29,6 +29,8 @@ #include +#include + __BEGIN_DECLS #ifndef __off_t_defined @@ -80,6 +82,7 @@ struct FILE int (*close_func)(void* user); void (*free_func)(void* free_user, struct FILE* fp); /* Application writers shouldn't use anything beyond this point. */ + pthread_mutex_t file_lock; struct FILE* prev; struct FILE* next; int flags; @@ -89,6 +92,12 @@ struct FILE size_t amount_output_buffered; }; +/* Internally used by standard library. */ +#if defined(__is_sortix_libc) +extern FILE* __first_file; +extern __pthread_mutex_t __first_file_lock; +#endif + __END_DECLS #endif diff --git a/libc/include/stdio.h b/libc/include/stdio.h index 35f077af..6be01c31 100644 --- a/libc/include/stdio.h +++ b/libc/include/stdio.h @@ -100,34 +100,51 @@ extern FILE* stderr; int asprintf(char** __restrict, const char* __restrict, ...); void clearerr(FILE* stream); +void clearerr_unlocked(FILE* stream); int dprintf(int fildes, const char* __restrict format, ...); int fclose(FILE* stream); FILE* fdopen(int fildes, const char* mode); int feof(FILE* stream); +int feof_unlocked(FILE* stream); int ferror(FILE* stream); +int ferror_unlocked(FILE* stream); int fflush(FILE* stream); +int fflush_unlocked(FILE* stream); int fileno(FILE* stream); +int fileno_unlocked(FILE* stream); int fgetc(FILE* stream); +int fgetc_unlocked(FILE* stream); int fgetpos(FILE* __restrict stream, fpos_t* __restrict pos); char* fgets(char* __restrict s, int n, FILE* __restrict stream); +char* fgets_unlocked(char* __restrict, int, FILE* __restrict); void flockfile(FILE* file); FILE* fopen(const char* __restrict filename, const char* __restrict mode); int fprintf(FILE* __restrict stream, const char* __restrict format, ...); +int fprintf_unlocked(FILE* __restrict stream, const char* __restrict format, ...); int fputc(int c, FILE* stream); -int fputs(const char* __restrict s, FILE* __restrict stream); +int fputc_unlocked(int c, FILE* stream); +int fputs(const char* __restrict, FILE* __restrict stream); +int fputs_unlocked(const char* __restrict, FILE* __restrict stream); size_t fread(void* __restrict ptr, size_t size, size_t nitems, FILE* __restrict stream); +size_t fread_unlocked(void* __restrict ptr, size_t size, size_t nitems, FILE* __restrict stream); FILE* freopen(const char* __restrict filename, const char *__restrict mode, FILE* __restrict stream); int fscanf(FILE* __restrict stream, const char* __restrict format, ... ); +int fscanf_unlocked(FILE* __restrict stream, const char* __restrict format, ... ); int fseek(FILE* stream, long offset, int whence); int fseeko(FILE* stream, off_t offset, int whence); +int fseeko_unlocked(FILE* stream, off_t offset, int whence); int fsetpos(FILE* stream, const fpos_t* pos); long ftell(FILE* stream); off_t ftello(FILE* stream); +off_t ftello_unlocked(FILE* stream); int ftrylockfile(FILE* file); void funlockfile(FILE* file); size_t fwrite(const void* __restrict ptr, size_t size, size_t nitems, FILE* __restrict stream); +size_t fwrite_unlocked(const void* __restrict ptr, size_t size, size_t nitems, FILE* __restrict stream); int getc(FILE* stream); +int getc_unlocked(FILE* stream); int getchar(void); +int getchar_unlocked(void); ssize_t getdelim(char** __restrict lineptr, size_t* __restrict n, int delimiter, FILE* __restrict stream); ssize_t getline(char** __restrict lineptr, size_t* __restrict n, FILE* __restrict stream); int pclose(FILE* steam); @@ -135,7 +152,9 @@ void perror(const char* s); FILE* popen(const char* command, const char* mode); int printf(const char* __restrict format, ...); int putc(int c, FILE* stream); +int putc_unlocked(int c, FILE* stream); int putchar(int c); +int putchar_unlocked(int c); int puts(const char* str); int removeat(int dirrfd, const char* path); int remove(const char* path); @@ -145,6 +164,7 @@ void rewind(FILE* stream); int snprintf(char* __restrict s, size_t n, const char* __restrict format, ...); void setbuf(FILE* __restrict stream, char* __restrict buf); int setvbuf(FILE* __restrict stream, char* __restrict buf, int type, size_t size); +int setvbuf_unlocked(FILE* __restrict stream, char* __restrict buf, int type, size_t size); char* sortix_gets(void); int sortix_puts(const char* str); int sprintf(char* __restrict s, const char* __restrict format, ...); @@ -153,10 +173,13 @@ int sscanf(const char* __restrict s, const char* __restrict format, ...); FILE* tmpfile(void); char* tmpnam(char* s); int ungetc(int c, FILE* stream); +int ungetc_unlocked(int c, FILE* stream); int vasprintf(char** __restrict, const char* __restrict, __gnuc_va_list); int vdprintf(int fildes, const char* __restrict format, __gnuc_va_list ap); int vfprintf(FILE* __restrict stream, const char* __restrict format, __gnuc_va_list ap); +int vfprintf_unlocked(FILE* __restrict stream, const char* __restrict format, __gnuc_va_list ap); int vfscanf(FILE* __restrict stream, const char* __restrict format, __gnuc_va_list arg); +int vfscanf_unlocked(FILE* __restrict stream, const char* __restrict format, __gnuc_va_list arg); int vprintf(const char* __restrict format, __gnuc_va_list ap); int vscanf(const char* __restrict format, __gnuc_va_list arg); int vsnprintf(char* __restrict, size_t, const char* __restrict, __gnuc_va_list); @@ -168,40 +191,45 @@ int vsscanf(const char* __restrict s, const char* __restrict format, __gnuc_va_l char* ctermid(char* s); FILE *fmemopen(void* __restrict buf, size_t size, const char* __restrict mode); FILE* open_memstream(char** bufp, size_t* sizep); -int getchar_unlocked(void); -int getc_unlocked(FILE* stream); -int putchar_unlocked(int c); -int putc_unlocked(int c, FILE* steam); #endif #if defined(_SORTIX_SOURCE) #include #define fbufsize __fbufsize +size_t fbufsize_unlocked(FILE* fp); #define freading __freading +int freading_unlocked(FILE* fp); #define fwriting __fwriting +int fwriting_unlocked(FILE* fp); #define freadable __freadable +int freadable_unlocked(FILE* fp); #define fwritable __fwritable +int fwritable_unlocked(FILE* fp); #define flbf __flbf +int flbf_unlocked(FILE* fp); #define fpurge __fpurge +void fpurge_unlocked(FILE* fp); #define fpending __fpending +size_t fpending_unlocked(FILE* fp); #define flushlbf _flushlbf #define fsetlocking __fsetlocking +int fsetlocking_unlocked(FILE* fp, int type); int fflush_stop_reading(FILE* fp); +int fflush_stop_reading_unlocked(FILE* fp); int fflush_stop_writing(FILE* fp); +int fflush_stop_writing_unlocked(FILE* fp); void fdeletefile(FILE* fp); void fseterr(FILE* fp); +void fseterr_unlocked(FILE* fp); void fregister(FILE* fp); void fresetfile(FILE* fp); void funregister(FILE* fp); FILE* fnewfile(void); int fsetdefaultbuf(FILE* fp); +int fsetdefaultbuf_unlocked(FILE* fp); int fcloseall(void); int fshutdown(FILE* fp); int fpipe(FILE* pipes[2]); -/* Internally used by standard library. */ -#if defined(__is_sortix_libc) -extern FILE* _firstfile; -#endif #endif #if defined(_SORTIX_SOURCE) || defined(_WANT_SORTIX_VPRINTF_CALLBACK) diff --git a/libc/include/wchar.h b/libc/include/wchar.h index e2914bfa..295c2941 100644 --- a/libc/include/wchar.h +++ b/libc/include/wchar.h @@ -27,6 +27,7 @@ #include +#include <__/pthread.h> #include #include <__/wchar.h> diff --git a/libc/stdio/clearerr.cpp b/libc/stdio/clearerr.cpp index 7065c2e7..e3e0aa32 100644 --- a/libc/stdio/clearerr.cpp +++ b/libc/stdio/clearerr.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,6 +26,7 @@ extern "C" void clearerr(FILE* fp) { - if ( fp->clearerr_func ) - fp->clearerr_func(fp->user); + flockfile(fp); + clearerr_unlocked(fp); + funlockfile(fp); } diff --git a/libc/stdio/clearerr_unlocked.cpp b/libc/stdio/clearerr_unlocked.cpp new file mode 100644 index 00000000..cf5137b9 --- /dev/null +++ b/libc/stdio/clearerr_unlocked.cpp @@ -0,0 +1,31 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/clearerr_unlocked.cpp + Clears the error condition on a FILE. + +*******************************************************************************/ + +#include + +extern "C" void clearerr_unlocked(FILE* fp) +{ + if ( fp->clearerr_func ) + fp->clearerr_func(fp->user); +} diff --git a/libc/stdio/fbufsize.cpp b/libc/stdio/fbufsize.cpp index 9c959094..616b23d1 100644 --- a/libc/stdio/fbufsize.cpp +++ b/libc/stdio/fbufsize.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,5 +26,8 @@ extern "C" size_t fbufsize(FILE* fp) { - return fp->buffersize; + flockfile(fp); + size_t result = fbufsize_unlocked(fp); + funlockfile(fp); + return result; } diff --git a/libc/stdio/fbufsize_unlocked.cpp b/libc/stdio/fbufsize_unlocked.cpp new file mode 100644 index 00000000..3c5ef430 --- /dev/null +++ b/libc/stdio/fbufsize_unlocked.cpp @@ -0,0 +1,30 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fbufsize_unlocked.cpp + Returns the size of the FILE's buffer. + +*******************************************************************************/ + +#include + +extern "C" size_t fbufsize_unlocked(FILE* fp) +{ + return fp->buffersize; +} diff --git a/libc/stdio/fcloseall.cpp b/libc/stdio/fcloseall.cpp index 3a17626a..8b987b42 100644 --- a/libc/stdio/fcloseall.cpp +++ b/libc/stdio/fcloseall.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -27,6 +27,9 @@ extern "C" int fcloseall(void) { int result = 0; - while ( _firstfile ) { result |= fclose(_firstfile); } - return (result) ? EOF : 0; + // We do not lock __first_file_lock here because this function is called on + // process termination and only one thread can call exit(3). + while ( __first_file ) + result |= fclose(__first_file); + return result ? EOF : 0; } diff --git a/libc/stdio/feof.cpp b/libc/stdio/feof.cpp index 2985fca7..e412a450 100644 --- a/libc/stdio/feof.cpp +++ b/libc/stdio/feof.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,10 +26,8 @@ extern "C" int feof(FILE* fp) { - size_t input_buffered = fp->amount_input_buffered - fp->offset_input_buffer; - if ( input_buffered ) - return 0; - if ( fp->eof_func ) - return fp->eof_func(fp->user); - return 0; + flockfile(fp); + int ret = feof_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/feof_unlocked.cpp b/libc/stdio/feof_unlocked.cpp new file mode 100644 index 00000000..14bd0402 --- /dev/null +++ b/libc/stdio/feof_unlocked.cpp @@ -0,0 +1,35 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/feof_unlocked.cpp + Returns whether the end of file condition is set on a FILE. + +*******************************************************************************/ + +#include + +extern "C" int feof_unlocked(FILE* fp) +{ + size_t input_buffered = fp->amount_input_buffered - fp->offset_input_buffer; + if ( input_buffered ) + return 0; + if ( fp->eof_func ) + return fp->eof_func(fp->user); + return 0; +} diff --git a/libc/stdio/ferror.cpp b/libc/stdio/ferror.cpp index 31c9ebdc..8f427fb3 100644 --- a/libc/stdio/ferror.cpp +++ b/libc/stdio/ferror.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,7 +26,8 @@ extern "C" int ferror(FILE* fp) { - if ( fp->error_func ) - return fp->error_func(fp->user); - return 0; + flockfile(fp); + int ret = ferror_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/ferror_unlocked.cpp b/libc/stdio/ferror_unlocked.cpp new file mode 100644 index 00000000..d8e913ff --- /dev/null +++ b/libc/stdio/ferror_unlocked.cpp @@ -0,0 +1,32 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/ferror_unlocked.cpp + Returns whether the error condition is set on a FILE. + +*******************************************************************************/ + +#include + +extern "C" int ferror_unlocked(FILE* fp) +{ + if ( fp->error_func ) + return fp->error_func(fp->user); + return 0; +} diff --git a/libc/stdio/fflush.cpp b/libc/stdio/fflush.cpp index 4d58bff8..fa4a9290 100644 --- a/libc/stdio/fflush.cpp +++ b/libc/stdio/fflush.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -22,23 +22,23 @@ *******************************************************************************/ +#include #include -#include extern "C" int fflush(FILE* fp) { if ( !fp ) { int result = 0; - for ( fp = _firstfile; fp; fp = fp->next ) { result |= fflush(fp); } + pthread_mutex_lock(&__first_file_lock); + for ( fp = __first_file; fp; fp = fp->next ) + result |= fflush(fp); + pthread_mutex_unlock(&__first_file_lock); return result; } - int mode = fp->flags & (_FILE_LAST_READ | _FILE_LAST_WRITE); - if ( (mode & _FILE_LAST_READ) && fflush_stop_reading(fp) == EOF ) - return EOF; - if ( (mode & _FILE_LAST_WRITE) && fflush_stop_writing(fp) == EOF ) - return EOF; - fp->flags |= mode; - return 0; + flockfile(fp); + int ret = fflush_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/fflush_stop_reading.cpp b/libc/stdio/fflush_stop_reading.cpp index 1c71dea9..203030c8 100644 --- a/libc/stdio/fflush_stop_reading.cpp +++ b/libc/stdio/fflush_stop_reading.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. This file is part of the Sortix C Library. @@ -22,37 +22,12 @@ *******************************************************************************/ -#include - -#include #include extern "C" int fflush_stop_reading(FILE* fp) { - if ( !(fp->flags & _FILE_LAST_READ) ) - return 0; - int ret = 0; - size_t bufferahead = fp->amount_input_buffered - fp->offset_input_buffer; - if ( (fp->flags & _FILE_STREAM) ) - { - if ( bufferahead ) - /* TODO: Data loss!*/{} - } - if ( !(fp->flags & _FILE_STREAM) ) - { - off_t rewind_amount = -((off_t) bufferahead); - off_t my_pos = fp->tell_func(fp->user); - off_t expected_pos = my_pos + rewind_amount; -#if 1 - if ( fp->seek_func && fp->seek_func(fp->user, expected_pos, SEEK_SET) != 0 ) -#else - if ( fp->seek_func && fp->seek_func(fp->user, rewind_amount, SEEK_CUR) != 0 ) -#endif - ret = EOF; - off_t newpos = fp->tell_func(fp->user); - assert(ret == EOF || expected_pos == newpos); - } - fp->amount_input_buffered = fp->offset_input_buffer = 0; - fp->flags &= ~_FILE_LAST_READ; + flockfile(fp); + int ret = fflush_stop_reading_unlocked(fp); + funlockfile(fp); return ret; } diff --git a/libc/stdio/fflush_stop_reading_unlocked.cpp b/libc/stdio/fflush_stop_reading_unlocked.cpp new file mode 100644 index 00000000..60828a5d --- /dev/null +++ b/libc/stdio/fflush_stop_reading_unlocked.cpp @@ -0,0 +1,58 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fflush_stop_reading_unlocked.cpp + Resets the FILE to a consistent state so it is ready for writing. + +*******************************************************************************/ + +#include + +#include +#include + +extern "C" int fflush_stop_reading_unlocked(FILE* fp) +{ + if ( !(fp->flags & _FILE_LAST_READ) ) + return 0; + int ret = 0; + size_t bufferahead = fp->amount_input_buffered - fp->offset_input_buffer; + if ( (fp->flags & _FILE_STREAM) ) + { + if ( bufferahead ) + /* TODO: Data loss!*/{} + } + if ( !(fp->flags & _FILE_STREAM) ) + { + off_t rewind_amount = -((off_t) bufferahead); + off_t my_pos = fp->tell_func(fp->user); + off_t expected_pos = my_pos + rewind_amount; +#if 1 + if ( fp->seek_func && fp->seek_func(fp->user, expected_pos, SEEK_SET) != 0 ) +#else + if ( fp->seek_func && fp->seek_func(fp->user, rewind_amount, SEEK_CUR) != 0 ) +#endif + ret = EOF; + off_t newpos = fp->tell_func(fp->user); + assert(ret == EOF || expected_pos == newpos); + } + fp->amount_input_buffered = fp->offset_input_buffer = 0; + fp->flags &= ~_FILE_LAST_READ; + return ret; +} diff --git a/libc/stdio/fflush_stop_writing.cpp b/libc/stdio/fflush_stop_writing.cpp index baf924da..23209fbb 100644 --- a/libc/stdio/fflush_stop_writing.cpp +++ b/libc/stdio/fflush_stop_writing.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. This file is part of the Sortix C Library. @@ -27,16 +27,8 @@ extern "C" int fflush_stop_writing(FILE* fp) { - if ( !(fp->flags & _FILE_LAST_WRITE) ) - return 0; - if ( !fp->write_func ) - return errno = EBADF, EOF; - size_t size = sizeof(unsigned char); - size_t count = fp->amount_output_buffered; - int ret = 0; - if ( fp->write_func(fp->buffer, size, count, fp->user) != count ) - ret = EOF; // TODO: Set errno! - fp->amount_output_buffered = 0; - fp->flags &= ~_FILE_LAST_WRITE; + flockfile(fp); + int ret = fflush_stop_writing_unlocked(fp); + funlockfile(fp); return ret; } diff --git a/libc/stdio/fflush_stop_writing_unlocked.cpp b/libc/stdio/fflush_stop_writing_unlocked.cpp new file mode 100644 index 00000000..ff3d3fa4 --- /dev/null +++ b/libc/stdio/fflush_stop_writing_unlocked.cpp @@ -0,0 +1,42 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fflush_stop_writing_unlocked.cpp + Resets the FILE to a consistent state so it is ready for reading. + +*******************************************************************************/ + +#include +#include + +extern "C" int fflush_stop_writing_unlocked(FILE* fp) +{ + if ( !(fp->flags & _FILE_LAST_WRITE) ) + return 0; + if ( !fp->write_func ) + return errno = EBADF, EOF; + size_t size = sizeof(unsigned char); + size_t count = fp->amount_output_buffered; + int ret = 0; + if ( fp->write_func(fp->buffer, size, count, fp->user) != count ) + ret = EOF; // TODO: Set errno! + fp->amount_output_buffered = 0; + fp->flags &= ~_FILE_LAST_WRITE; + return ret; +} diff --git a/libc/stdio/fflush_unlocked.cpp b/libc/stdio/fflush_unlocked.cpp new file mode 100644 index 00000000..c3dd144f --- /dev/null +++ b/libc/stdio/fflush_unlocked.cpp @@ -0,0 +1,36 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fflush_unlocked.cpp + Flushes a FILE. + +*******************************************************************************/ + +#include + +extern "C" int fflush_unlocked(FILE* fp) +{ + int mode = fp->flags & (_FILE_LAST_READ | _FILE_LAST_WRITE); + if ( (mode & _FILE_LAST_READ) && fflush_stop_reading_unlocked(fp) == EOF ) + return EOF; + if ( (mode & _FILE_LAST_WRITE) && fflush_stop_writing_unlocked(fp) == EOF ) + return EOF; + fp->flags |= mode; + return 0; +} diff --git a/libc/stdio/fgetc.cpp b/libc/stdio/fgetc.cpp index 8313a16d..014f1512 100644 --- a/libc/stdio/fgetc.cpp +++ b/libc/stdio/fgetc.cpp @@ -22,52 +22,12 @@ *******************************************************************************/ -#include #include -#include - -#include -#include -#include extern "C" int fgetc(FILE* fp) { - if ( !(fp->flags & _FILE_BUFFER_MODE_SET) ) - if ( fsetdefaultbuf(fp) != 0 ) - return EOF; // TODO: ferror doesn't report error! - - if ( fp->buffer_mode == _IONBF ) - { - unsigned char c; - if ( fread(&c, sizeof(c), 1, fp) != 1 ) - return EOF; - return c; - } - - if ( !fp->read_func ) - return EOF; // TODO: ferror doesn't report error! - - if ( fp->flags & _FILE_LAST_WRITE ) - fflush_stop_writing(fp); - fp->flags |= _FILE_LAST_READ; - - if ( fp->offset_input_buffer < fp->amount_input_buffered ) -retry: - return fp->buffer[fp->offset_input_buffer++]; - - assert(fp->buffer && fp->buffersize); - - size_t pushback = _FILE_MAX_PUSHBACK; - if ( fp->buffersize <= pushback ) - pushback = 0; - size_t count = fp->buffersize - pushback; - size_t size = sizeof(unsigned char); - size_t numread = fp->read_func(fp->buffer + pushback, size, count, fp->user); - if ( !numread ) - return EOF; - - fp->offset_input_buffer = pushback; - fp->amount_input_buffered = pushback + numread; - - goto retry; + flockfile(fp); + int ret = fgetc_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/fgetc_unlocked.cpp b/libc/stdio/fgetc_unlocked.cpp new file mode 100644 index 00000000..b683e257 --- /dev/null +++ b/libc/stdio/fgetc_unlocked.cpp @@ -0,0 +1,73 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fgetc_unlocked.cpp + Reads a single character from a FILE. + +*******************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +extern "C" int fgetc_unlocked(FILE* fp) +{ + if ( !(fp->flags & _FILE_BUFFER_MODE_SET) ) + if ( fsetdefaultbuf_unlocked(fp) != 0 ) + return EOF; // TODO: ferror doesn't report error! + + if ( fp->buffer_mode == _IONBF ) + { + unsigned char c; + if ( fread_unlocked(&c, sizeof(c), 1, fp) != 1 ) + return EOF; + return c; + } + + if ( !fp->read_func ) + return EOF; // TODO: ferror doesn't report error! + + if ( fp->flags & _FILE_LAST_WRITE ) + fflush_stop_writing_unlocked(fp); + fp->flags |= _FILE_LAST_READ; + + if ( fp->offset_input_buffer < fp->amount_input_buffered ) +retry: + return fp->buffer[fp->offset_input_buffer++]; + + assert(fp->buffer && fp->buffersize); + + size_t pushback = _FILE_MAX_PUSHBACK; + if ( fp->buffersize <= pushback ) + pushback = 0; + size_t count = fp->buffersize - pushback; + size_t size = sizeof(unsigned char); + size_t numread = fp->read_func(fp->buffer + pushback, size, count, fp->user); + if ( !numread ) + return EOF; + + fp->offset_input_buffer = pushback; + fp->amount_input_buffered = pushback + numread; + + goto retry; +} diff --git a/libc/stdio/fgets.cpp b/libc/stdio/fgets.cpp index 6005083c..8dabec75 100644 --- a/libc/stdio/fgets.cpp +++ b/libc/stdio/fgets.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014. This file is part of the Sortix C Library. @@ -23,25 +23,11 @@ *******************************************************************************/ #include -#include -extern "C" char* fgets(char* dest, int size, FILE* fp) +extern "C" char* fgets(char* restrict dest, int size, FILE* restrict fp) { - if ( size <= 0 ) - return errno = EINVAL, (char*) NULL; - int i; - for ( i = 0; i < size-1; i++ ) - { - int c = getc(fp); - if ( c == EOF ) - break; - dest[i] = c; - if ( c == '\n' ) { i++; break; } - } - if ( !i && (ferror(fp) || feof(fp)) ) - return NULL; - // TODO: The end-of-file state is lost here if feof(fp) and we are reading - // from a terminal that encountered a soft EOF. - dest[i] = '\0'; - return dest; + flockfile(fp); + char* result = fgets_unlocked(dest, size, fp); + funlockfile(fp); + return result; } diff --git a/libc/stdio/fgets_unlocked.cpp b/libc/stdio/fgets_unlocked.cpp new file mode 100644 index 00000000..82281a75 --- /dev/null +++ b/libc/stdio/fgets_unlocked.cpp @@ -0,0 +1,52 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fgets_unlocked.cpp + Reads a string from a FILE. + +*******************************************************************************/ + +#include +#include + +extern "C" +char* fgets_unlocked(char* restrict dest, int size, FILE* restrict fp) +{ + if ( size <= 0 ) + return errno = EINVAL, (char*) NULL; + int i; + for ( i = 0; i < size-1; i++ ) + { + int c = fgetc_unlocked(fp); + if ( c == EOF ) + break; + dest[i] = c; + if ( c == '\n' ) + { + i++; + break; + } + } + if ( !i && (ferror_unlocked(fp) || feof_unlocked(fp)) ) + return NULL; + // TODO: The end-of-file state is lost here if feof(fp) and we are reading + // from a terminal that encountered a soft EOF. + dest[i] = '\0'; + return dest; +} diff --git a/libc/stdio/fileno.cpp b/libc/stdio/fileno.cpp index 51ce3162..5d5d5b91 100644 --- a/libc/stdio/fileno.cpp +++ b/libc/stdio/fileno.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -27,7 +27,8 @@ extern "C" int fileno(FILE* fp) { - int result = fp->fileno_func ? fp->fileno_func(fp->user) : -1; - if ( result < 0 ) { errno = EBADF; } - return result; + flockfile(fp); + int ret = fileno_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/fileno_unlocked.cpp b/libc/stdio/fileno_unlocked.cpp new file mode 100644 index 00000000..04b9065b --- /dev/null +++ b/libc/stdio/fileno_unlocked.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fileno_unlocked.cpp + Returns the underlying file descriptor of a FILE if applicable. + +*******************************************************************************/ + +#include +#include + +extern "C" int fileno_unlocked(FILE* fp) +{ + int result = fp->fileno_func ? fp->fileno_func(fp->user) : -1; + if ( result < 0 ) + errno = EBADF; + return result; +} diff --git a/libc/stdio/flbf.cpp b/libc/stdio/flbf.cpp index 548fe27e..ca828278 100644 --- a/libc/stdio/flbf.cpp +++ b/libc/stdio/flbf.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,5 +26,8 @@ extern "C" int flbf(FILE* fp) { - return fp->buffer_mode == _IOLBF; + flockfile(fp); + int ret = flbf_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/flbf_unlocked.cpp b/libc/stdio/flbf_unlocked.cpp new file mode 100644 index 00000000..5f984a08 --- /dev/null +++ b/libc/stdio/flbf_unlocked.cpp @@ -0,0 +1,30 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/flbf_unlocked.cpp + Returns whether a FILE is line buffered. + +*******************************************************************************/ + +#include + +extern "C" int flbf_unlocked(FILE* fp) +{ + return fp->buffer_mode == _IOLBF; +} diff --git a/libc/stdio/flockfile.cpp b/libc/stdio/flockfile.cpp index 9d440791..7d2e1503 100644 --- a/libc/stdio/flockfile.cpp +++ b/libc/stdio/flockfile.cpp @@ -22,9 +22,10 @@ *******************************************************************************/ +#include #include -extern "C" void flockfile(FILE* /*fp*/) +extern "C" void flockfile(FILE* fp) { - // TODO: Thread safety. + pthread_mutex_lock(&fp->file_lock); } diff --git a/libc/stdio/flushlbf.cpp b/libc/stdio/flushlbf.cpp index 6e5b5d60..cbd81a9a 100644 --- a/libc/stdio/flushlbf.cpp +++ b/libc/stdio/flushlbf.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -22,10 +22,13 @@ *******************************************************************************/ +#include #include extern "C" void flushlbf(void) { - for ( FILE* fp = _firstfile; fp; fp = fp->next ) + pthread_mutex_lock(&__first_file_lock); + for ( FILE* fp = __first_file; fp; fp = fp->next ) fflush(fp); + pthread_mutex_unlock(&__first_file_lock); } diff --git a/libc/stdio/fnewfile.cpp b/libc/stdio/fnewfile.cpp index 6a09c971..61cc4532 100644 --- a/libc/stdio/fnewfile.cpp +++ b/libc/stdio/fnewfile.cpp @@ -22,6 +22,7 @@ *******************************************************************************/ +#include #include #include diff --git a/libc/stdio/fpending.cpp b/libc/stdio/fpending.cpp index c7ae251e..89a3e35c 100644 --- a/libc/stdio/fpending.cpp +++ b/libc/stdio/fpending.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,5 +26,8 @@ extern "C" size_t fpending(FILE* fp) { - return fp->amount_output_buffered; + flockfile(fp); + size_t ret = fpending_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/fpending_unlocked.cpp b/libc/stdio/fpending_unlocked.cpp new file mode 100644 index 00000000..16895c26 --- /dev/null +++ b/libc/stdio/fpending_unlocked.cpp @@ -0,0 +1,30 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fpending_unlocked.cpp + Returns the number of bytes pending in the output buffer. + +*******************************************************************************/ + +#include + +extern "C" size_t fpending_unlocked(FILE* fp) +{ + return fp->amount_output_buffered; +} diff --git a/libc/stdio/fprintf.cpp b/libc/stdio/fprintf.cpp index c56c1645..037030ee 100644 --- a/libc/stdio/fprintf.cpp +++ b/libc/stdio/fprintf.cpp @@ -29,7 +29,9 @@ extern "C" int fprintf(FILE* fp, const char* restrict format, ...) { va_list list; va_start(list, format); - int result = vfprintf(fp, format, list); + flockfile(fp); + int result = vfprintf_unlocked(fp, format, list); + funlockfile(fp); va_end(list); return result; } diff --git a/libc/stdio/fprintf_unlocked.cpp b/libc/stdio/fprintf_unlocked.cpp new file mode 100644 index 00000000..97fae0a7 --- /dev/null +++ b/libc/stdio/fprintf_unlocked.cpp @@ -0,0 +1,35 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fprintf_unlocked.cpp + Prints a string to a FILE. + +*******************************************************************************/ + +#include +#include + +extern "C" int fprintf_unlocked(FILE* fp, const char* restrict format, ...) +{ + va_list list; + va_start(list, format); + int result = vfprintf_unlocked(fp, format, list); + va_end(list); + return result; +} diff --git a/libc/stdio/fpurge.cpp b/libc/stdio/fpurge.cpp index 4b7a47df..10c67292 100644 --- a/libc/stdio/fpurge.cpp +++ b/libc/stdio/fpurge.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,7 +26,7 @@ extern "C" void fpurge(FILE* fp) { - fp->offset_input_buffer = 0; - fp->amount_input_buffered = 0; - fp->amount_output_buffered = 0; + flockfile(fp); + fpurge_unlocked(fp); + funlockfile(fp); } diff --git a/libc/stdio/fpurge_unlocked.cpp b/libc/stdio/fpurge_unlocked.cpp new file mode 100644 index 00000000..684cf06b --- /dev/null +++ b/libc/stdio/fpurge_unlocked.cpp @@ -0,0 +1,32 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fpurge_unlocked.cpp + Discards all contents in the FILE's buffer. + +*******************************************************************************/ + +#include + +extern "C" void fpurge_unlocked(FILE* fp) +{ + fp->offset_input_buffer = 0; + fp->amount_input_buffered = 0; + fp->amount_output_buffered = 0; +} diff --git a/libc/stdio/fputc.cpp b/libc/stdio/fputc.cpp index ab43d52e..f085f75e 100644 --- a/libc/stdio/fputc.cpp +++ b/libc/stdio/fputc.cpp @@ -26,31 +26,8 @@ extern "C" int fputc(int c, FILE* fp) { - if ( !(fp->flags & _FILE_BUFFER_MODE_SET) ) - if ( fsetdefaultbuf(fp) != 0 ) - return EOF; // TODO: ferror doesn't report error! - - if ( fp->buffer_mode == _IONBF ) - { - unsigned char c_char = c; - if ( fwrite(&c_char, sizeof(c_char), 1, fp) != 1 ) - return EOF; - return c; - } - - if ( !fp->write_func ) - return EOF; // TODO: ferror doesn't report error! - - if ( fp->flags & _FILE_LAST_READ ) - fflush_stop_reading(fp); - fp->flags |= _FILE_LAST_WRITE; - - if ( fp->amount_output_buffered == fp->buffersize && fflush(fp) != 0 ) - return EOF; - - fp->buffer[fp->amount_output_buffered++] = c; - if ( fp->buffer_mode == _IOLBF && c == '\n' && fflush(fp) != 0 ) - return EOF; - - return c; + flockfile(fp); + int ret = fputc_unlocked(c, fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/fputc_unlocked.cpp b/libc/stdio/fputc_unlocked.cpp new file mode 100644 index 00000000..9e7aee91 --- /dev/null +++ b/libc/stdio/fputc_unlocked.cpp @@ -0,0 +1,56 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fputc_unlocked.cpp + Writes a character to a FILE. + +*******************************************************************************/ + +#include + +extern "C" int fputc_unlocked(int c, FILE* fp) +{ + if ( !(fp->flags & _FILE_BUFFER_MODE_SET) ) + if ( fsetdefaultbuf_unlocked(fp) != 0 ) + return EOF; // TODO: ferror doesn't report error! + + if ( fp->buffer_mode == _IONBF ) + { + unsigned char c_char = c; + if ( fwrite_unlocked(&c_char, sizeof(c_char), 1, fp) != 1 ) + return EOF; + return c; + } + + if ( !fp->write_func ) + return EOF; // TODO: ferror doesn't report error! + + if ( fp->flags & _FILE_LAST_READ ) + fflush_stop_reading_unlocked(fp); + fp->flags |= _FILE_LAST_WRITE; + + if ( fp->amount_output_buffered == fp->buffersize && fflush_unlocked(fp) != 0 ) + return EOF; + + fp->buffer[fp->amount_output_buffered++] = c; + if ( fp->buffer_mode == _IOLBF && c == '\n' && fflush_unlocked(fp) != 0 ) + return EOF; + + return c; +} diff --git a/libc/stdio/fputs.cpp b/libc/stdio/fputs.cpp index c06f4d41..01000770 100644 --- a/libc/stdio/fputs.cpp +++ b/libc/stdio/fputs.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014. This file is part of the Sortix C Library. @@ -23,13 +23,11 @@ *******************************************************************************/ #include -#include extern "C" int fputs(const char* str, FILE* fp) { - size_t stringlen = strlen(str); - size_t result = fwrite(str, 1, stringlen, fp); - if ( result < stringlen ) - return EOF; + flockfile(fp); + int result = fputs_unlocked(str, fp); + funlockfile(fp); return result; } diff --git a/libc/stdio/fputs_unlocked.cpp b/libc/stdio/fputs_unlocked.cpp new file mode 100644 index 00000000..aad83945 --- /dev/null +++ b/libc/stdio/fputs_unlocked.cpp @@ -0,0 +1,35 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fputs_unlocked.cpp + Writes a string to a FILE. + +*******************************************************************************/ + +#include +#include + +extern "C" int fputs_unlocked(const char* str, FILE* fp) +{ + size_t stringlen = strlen(str); + size_t result = fwrite_unlocked(str, 1, stringlen, fp); + if ( result < stringlen ) + return EOF; + return result; +} diff --git a/libc/stdio/fread.cpp b/libc/stdio/fread.cpp index 6fd7c494..5bc291e3 100644 --- a/libc/stdio/fread.cpp +++ b/libc/stdio/fread.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,32 +26,8 @@ extern "C" size_t fread(void* ptr, size_t size, size_t nmemb, FILE* fp) { - if ( fp->buffer_mode == _IONBF ) - { - if ( !(fp->flags & _FILE_BUFFER_MODE_SET) ) - if ( fsetdefaultbuf(fp) != 0 ) - return EOF; // TODO: ferror doesn't report error! - if ( !fp->read_func ) - return 0; // TODO: ferror doesn't report error! - if ( fp->flags & _FILE_LAST_WRITE ) - fflush_stop_writing(fp); - fp->flags |= _FILE_LAST_READ; - return fp->read_func(ptr, size, nmemb, fp->user); - } - - unsigned char* buf = (unsigned char*) ptr; - for ( size_t n = 0; n < nmemb; n++ ) - { - size_t offset = n * size; - for ( size_t i = 0; i < size; i++ ) - { - int c = fgetc(fp); - if ( c == EOF ) - return n; - size_t index = i + offset; - buf[index] = c; - } - } - - return nmemb; + flockfile(fp); + size_t ret = fread_unlocked(ptr, size, nmemb, fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/fread_unlocked.cpp b/libc/stdio/fread_unlocked.cpp new file mode 100644 index 00000000..f06b82f0 --- /dev/null +++ b/libc/stdio/fread_unlocked.cpp @@ -0,0 +1,58 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fread_unlocked.cpp + Reads data from a FILE. + +*******************************************************************************/ + +#include + +extern "C" +size_t fread_unlocked(void* ptr, size_t size, size_t nmemb, FILE* fp) +{ + if ( fp->buffer_mode == _IONBF ) + { + if ( !(fp->flags & _FILE_BUFFER_MODE_SET) ) + if ( fsetdefaultbuf_unlocked(fp) != 0 ) + return EOF; // TODO: ferror doesn't report error! + if ( !fp->read_func ) + return 0; // TODO: ferror doesn't report error! + if ( fp->flags & _FILE_LAST_WRITE ) + fflush_stop_writing_unlocked(fp); + fp->flags |= _FILE_LAST_READ; + return fp->read_func(ptr, size, nmemb, fp->user); + } + + unsigned char* buf = (unsigned char*) ptr; + for ( size_t n = 0; n < nmemb; n++ ) + { + size_t offset = n * size; + for ( size_t i = 0; i < size; i++ ) + { + int c = fgetc_unlocked(fp); + if ( c == EOF ) + return n; + size_t index = i + offset; + buf[index] = c; + } + } + + return nmemb; +} diff --git a/libc/stdio/freadable.cpp b/libc/stdio/freadable.cpp index 52e72894..8fb76d8f 100644 --- a/libc/stdio/freadable.cpp +++ b/libc/stdio/freadable.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,5 +26,8 @@ extern "C" int freadable(FILE* fp) { - return fp->read_func != NULL; + flockfile(fp); + int ret = freadable_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/freadable_unlocked.cpp b/libc/stdio/freadable_unlocked.cpp new file mode 100644 index 00000000..17491e6f --- /dev/null +++ b/libc/stdio/freadable_unlocked.cpp @@ -0,0 +1,30 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/freadable_unlocked.cpp + Returns whether this FILE can be read from. + +*******************************************************************************/ + +#include + +extern "C" int freadable_unlocked(FILE* fp) +{ + return fp->read_func != NULL; +} diff --git a/libc/stdio/freading.cpp b/libc/stdio/freading.cpp index b09d7cec..736e8095 100644 --- a/libc/stdio/freading.cpp +++ b/libc/stdio/freading.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,7 +26,8 @@ extern "C" int freading(FILE* fp) { - if ( fp->read_func ) { return 1; } - if ( fp->flags & _FILE_LAST_READ ) { return 1; } - return 0; + flockfile(fp); + int ret = freading_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/freading_unlocked.cpp b/libc/stdio/freading_unlocked.cpp new file mode 100644 index 00000000..185a0192 --- /dev/null +++ b/libc/stdio/freading_unlocked.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/freading_unlocked.cpp + Returns whether the last operation was a read or FILE is read only. + +*******************************************************************************/ + +#include + +extern "C" int freading_unlocked(FILE* fp) +{ + if ( fp->read_func ) + return 1; + if ( fp->flags & _FILE_LAST_READ ) + return 1; + return 0; +} diff --git a/libc/stdio/fregister.cpp b/libc/stdio/fregister.cpp index e302acfe..aed41038 100644 --- a/libc/stdio/fregister.cpp +++ b/libc/stdio/fregister.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -23,24 +23,39 @@ *******************************************************************************/ +#include #include -extern "C" { FILE* _firstfile = NULL; } +extern "C" +{ + FILE* __first_file = NULL; + pthread_mutex_t __first_file_lock = PTHREAD_MUTEX_INITIALIZER; +} extern "C" void fregister(FILE* fp) { + pthread_mutex_lock(&__first_file_lock); fp->flags |= _FILE_REGISTERED; - if ( !_firstfile ) { _firstfile = fp; return; } - fp->next = _firstfile; - _firstfile->prev = fp; - _firstfile = fp; + if ( __first_file ) + { + fp->next = __first_file; + __first_file->prev = fp; + } + __first_file = fp; + pthread_mutex_unlock(&__first_file_lock); } extern "C" void funregister(FILE* fp) { - if ( !(fp->flags & _FILE_REGISTERED) ) { return; } - if ( !fp->prev ) { _firstfile = fp->next; } - if ( fp->prev ) { fp->prev->next = fp->next; } - if ( fp->next ) { fp->next->prev = fp->prev; } + if ( !(fp->flags & _FILE_REGISTERED) ) + return; + pthread_mutex_lock(&__first_file_lock); + if ( !fp->prev ) + __first_file = fp->next; + if ( fp->prev ) + fp->prev->next = fp->next; + if ( fp->next ) + fp->next->prev = fp->prev; fp->flags &= ~_FILE_REGISTERED; + pthread_mutex_unlock(&__first_file_lock); } diff --git a/libc/stdio/fresetfile.cpp b/libc/stdio/fresetfile.cpp index 50fe0925..4da2f918 100644 --- a/libc/stdio/fresetfile.cpp +++ b/libc/stdio/fresetfile.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014. This file is part of the Sortix C Library. @@ -37,6 +37,7 @@ extern "C" void fresetfile(FILE* fp) void (*free_func)(void*, FILE*) = fp->free_func; int kept_flags = fp->flags & (_FILE_REGISTERED | 0); memset(fp, 0, sizeof(*fp)); + fp->file_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; fp->flags = kept_flags | _FILE_AUTO_LOCK; fp->buffer_mode = -1; fp->free_user = free_user; diff --git a/libc/stdio/fscanf.cpp b/libc/stdio/fscanf.cpp index a3dc4215..532c2c01 100644 --- a/libc/stdio/fscanf.cpp +++ b/libc/stdio/fscanf.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. This file is part of the Sortix C Library. diff --git a/libc/stdio/fscanf_unlocked.cpp b/libc/stdio/fscanf_unlocked.cpp new file mode 100644 index 00000000..8efe54b9 --- /dev/null +++ b/libc/stdio/fscanf_unlocked.cpp @@ -0,0 +1,37 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fscanf_unlocked.cpp + Input format conversion. + +*******************************************************************************/ + +#include +#include + +extern "C" int fscanf_unlocked(FILE* fp, const char* format, ...) +{ + va_list ap; + va_start(ap, format); + flockfile(fp); + int ret = vfscanf_unlocked(fp, format, ap); + funlockfile(fp); + va_end(ap); + return ret; +} diff --git a/libc/stdio/fseeko.cpp b/libc/stdio/fseeko.cpp index 4655755e..d703686b 100644 --- a/libc/stdio/fseeko.cpp +++ b/libc/stdio/fseeko.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -22,15 +22,12 @@ *******************************************************************************/ -#include #include extern "C" int fseeko(FILE* fp, off_t offset, int whence) { - if ( fflush(fp) != 0 ) - return -1; - if ( !fp->seek_func ) - return errno = EBADF, -1; - int ret = fp->seek_func(fp->user, offset, whence); + flockfile(fp); + int ret = fseeko_unlocked(fp, offset, whence); + funlockfile(fp); return ret; } diff --git a/libc/stdio/fseeko_unlocked.cpp b/libc/stdio/fseeko_unlocked.cpp new file mode 100644 index 00000000..52e483e4 --- /dev/null +++ b/libc/stdio/fseeko_unlocked.cpp @@ -0,0 +1,36 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fseeko_unlocked.cpp + Changes the current offset in a FILE. + +*******************************************************************************/ + +#include +#include + +extern "C" int fseeko_unlocked(FILE* fp, off_t offset, int whence) +{ + if ( fflush_unlocked(fp) != 0 ) + return -1; + if ( !fp->seek_func ) + return errno = EBADF, -1; + int ret = fp->seek_func(fp->user, offset, whence); + return ret; +} diff --git a/libc/stdio/fsetdefaultbuf.cpp b/libc/stdio/fsetdefaultbuf.cpp index b257faac..c70a7943 100644 --- a/libc/stdio/fsetdefaultbuf.cpp +++ b/libc/stdio/fsetdefaultbuf.cpp @@ -23,44 +23,11 @@ *******************************************************************************/ #include -#include -#include extern "C" int fsetdefaultbuf(FILE* fp) { - char* buf = (char*) malloc(sizeof(char) * BUFSIZ); - if ( !buf ) - { - // TODO: Determine whether this is truly what we would want and whether - // a buffer should be pre-allocated when the FILE is created such that - // this situation _cannot_ occur. - - // Alright, we're in a bit of a situation here. Normally, we'd go - // buffered but we are out of memory. We could either fail, but that - // would mean subsequent calls such as fgetc and fputc would also fail - - // however that we are out of memory doesn't mean that IO would also - // fail. Therefore we'll revert to unbuffered semantics and hope that's - // good enough. - - return setvbuf(fp, NULL, _IONBF, 0); - } - - // Determine the buffering semantics depending on whether the destination is - // an interactive device or not. -#if defined(__is_sortix_kernel) - int mode = _IOLBF; // TODO: Detect this? -#else - int mode = fp->buffer_mode != -1 ? fp->buffer_mode - : isatty(fileno(fp)) ? _IOLBF : _IOFBF; -#endif - int ret = setvbuf(fp, buf, mode, BUFSIZ); - if ( ret ) - { - free(buf); - return -1; - } - - // The buffer now belongs to the FILE. - fp->flags |= _FILE_BUFFER_OWNED; + flockfile(fp); + int ret = fsetdefaultbuf_unlocked(fp); + funlockfile(fp); return ret; } diff --git a/libc/stdio/fsetdefaultbuf_unlocked.cpp b/libc/stdio/fsetdefaultbuf_unlocked.cpp new file mode 100644 index 00000000..b15909a7 --- /dev/null +++ b/libc/stdio/fsetdefaultbuf_unlocked.cpp @@ -0,0 +1,67 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fsetdefaultbuf_unlocked.cpp + Sets up default buffering semantics for a FILE. + +*******************************************************************************/ + +#include +#include +#include + +extern "C" int fsetdefaultbuf_unlocked(FILE* fp) +{ + char* buf = (char*) malloc(sizeof(char) * BUFSIZ); + if ( !buf ) + { + // TODO: Determine whether this is truly what we would want and whether + // a buffer should be pre-allocated when the FILE is created such that + // this situation _cannot_ occur. + + // Alright, we're in a bit of a situation here. Normally, we'd go + // buffered but we are out of memory. We could either fail, but that + // would mean subsequent calls such as fgetc and fputc would also fail - + // however that we are out of memory doesn't mean that IO would also + // fail. Therefore we'll revert to unbuffered semantics and hope that's + // good enough. + + return setvbuf_unlocked(fp, NULL, _IONBF, 0); + } + + // Determine the buffering semantics depending on whether the destination is + // an interactive device or not. +#if defined(__is_sortix_kernel) + int mode = _IOLBF; // TODO: Detect this? +#else + int mode = fp->buffer_mode != -1 ? fp->buffer_mode + : isatty(fileno_unlocked(fp)) ? _IOLBF + : _IOFBF; +#endif + int ret = setvbuf_unlocked(fp, buf, mode, BUFSIZ); + if ( ret ) + { + free(buf); + return -1; + } + + // The buffer now belongs to the FILE. + fp->flags |= _FILE_BUFFER_OWNED; + return ret; +} diff --git a/libc/stdio/fseterr.cpp b/libc/stdio/fseterr.cpp index af13ed68..1f38d87e 100644 --- a/libc/stdio/fseterr.cpp +++ b/libc/stdio/fseterr.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,6 +26,7 @@ extern "C" void fseterr(FILE* fp) { - if ( fp->seterr_func ) - fp->seterr_func(fp->user); + flockfile(fp); + fseterr_unlocked(fp); + funlockfile(fp); } diff --git a/libc/stdio/fseterr_unlocked.cpp b/libc/stdio/fseterr_unlocked.cpp new file mode 100644 index 00000000..dde3e6c8 --- /dev/null +++ b/libc/stdio/fseterr_unlocked.cpp @@ -0,0 +1,31 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fseterr_unlocked.cpp + Sets the error condition bit on a FILE. + +*******************************************************************************/ + +#include + +extern "C" void fseterr_unlocked(FILE* fp) +{ + if ( fp->seterr_func ) + fp->seterr_func(fp->user); +} diff --git a/libc/stdio/fsetlocking.cpp b/libc/stdio/fsetlocking.cpp index e0c97bb3..f29bea95 100644 --- a/libc/stdio/fsetlocking.cpp +++ b/libc/stdio/fsetlocking.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,11 +26,8 @@ extern "C" int fsetlocking(FILE* fp, int type) { - switch ( type ) - { - case FSETLOCKING_INTERNAL: fp->flags |= _FILE_AUTO_LOCK; - case FSETLOCKING_BYCALLER: fp->flags &= ~_FILE_AUTO_LOCK; - } - return (fp->flags & _FILE_AUTO_LOCK) ? FSETLOCKING_INTERNAL - : FSETLOCKING_BYCALLER; + flockfile(fp); + int ret = fsetlocking_unlocked(fp, type); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/fsetlocking_unlocked.cpp b/libc/stdio/fsetlocking_unlocked.cpp new file mode 100644 index 00000000..75e5074d --- /dev/null +++ b/libc/stdio/fsetlocking_unlocked.cpp @@ -0,0 +1,37 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fsetlocking_unlocked.cpp + Sets the desired locking semantics on a FILE. + +*******************************************************************************/ + +#include + +// TODO: What is this? This looks like something I ought to support! +extern "C" int fsetlocking_unlocked(FILE* fp, int type) +{ + switch ( type ) + { + case FSETLOCKING_INTERNAL: fp->flags |= _FILE_AUTO_LOCK; + case FSETLOCKING_BYCALLER: fp->flags &= ~_FILE_AUTO_LOCK; + } + return (fp->flags & _FILE_AUTO_LOCK) ? FSETLOCKING_INTERNAL + : FSETLOCKING_BYCALLER; +} diff --git a/libc/stdio/ftello.cpp b/libc/stdio/ftello.cpp index 688798c7..873a0a1d 100644 --- a/libc/stdio/ftello.cpp +++ b/libc/stdio/ftello.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -22,22 +22,12 @@ *******************************************************************************/ -#include - -#include #include extern "C" off_t ftello(FILE* fp) { - if ( !fp->tell_func ) - return errno = EBADF, -1; - off_t offset = fp->tell_func(fp->user); - if ( offset < 0 ) - return -1; - off_t readahead = fp->amount_input_buffered - fp->offset_input_buffer; - off_t writebehind = fp->amount_output_buffered; - off_t result = offset - readahead + writebehind; - if ( result < 0 ) // Too much ungetc'ing. - return 0; - return result; + flockfile(fp); + off_t ret = ftello_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/ftello_unlocked.cpp b/libc/stdio/ftello_unlocked.cpp new file mode 100644 index 00000000..867e2b1a --- /dev/null +++ b/libc/stdio/ftello_unlocked.cpp @@ -0,0 +1,43 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/ftello_unlocked.cpp + Returns the current offset of a FILE. + +*******************************************************************************/ + +#include + +#include +#include + +extern "C" off_t ftello_unlocked(FILE* fp) +{ + if ( !fp->tell_func ) + return errno = EBADF, -1; + off_t offset = fp->tell_func(fp->user); + if ( offset < 0 ) + return -1; + off_t readahead = fp->amount_input_buffered - fp->offset_input_buffer; + off_t writebehind = fp->amount_output_buffered; + off_t result = offset - readahead + writebehind; + if ( result < 0 ) // Too much ungetc'ing. + return 0; + return result; +} diff --git a/libc/stdio/ftrylockfile.cpp b/libc/stdio/ftrylockfile.cpp index 0f1627b9..33e149b1 100644 --- a/libc/stdio/ftrylockfile.cpp +++ b/libc/stdio/ftrylockfile.cpp @@ -22,10 +22,10 @@ *******************************************************************************/ +#include #include -extern "C" int ftrylockfile(FILE* /*fp*/) +extern "C" int ftrylockfile(FILE* fp) { - // TODO: Thread safety. - return 0; + return pthread_mutex_lock(&fp->file_lock) ? -1 : 0; } diff --git a/libc/stdio/funlockfile.cpp b/libc/stdio/funlockfile.cpp index d165a8f7..7d86e59a 100644 --- a/libc/stdio/funlockfile.cpp +++ b/libc/stdio/funlockfile.cpp @@ -22,9 +22,10 @@ *******************************************************************************/ +#include #include -extern "C" void funlockfile(FILE* /*fp*/) +extern "C" void funlockfile(FILE* fp) { - // TODO: Thread safety. + pthread_mutex_unlock(&fp->file_lock); } diff --git a/libc/stdio/fwritable.cpp b/libc/stdio/fwritable.cpp index 3b639ab6..35ebc656 100644 --- a/libc/stdio/fwritable.cpp +++ b/libc/stdio/fwritable.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,5 +26,8 @@ extern "C" int fwritable(FILE* fp) { - return fp->write_func != NULL; + flockfile(fp); + int ret = fwritable_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/fwritable_unlocked.cpp b/libc/stdio/fwritable_unlocked.cpp new file mode 100644 index 00000000..ade049c5 --- /dev/null +++ b/libc/stdio/fwritable_unlocked.cpp @@ -0,0 +1,30 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fwritable_unlocked.cpp + Returns whether this FILE can be written to. + +*******************************************************************************/ + +#include + +extern "C" int fwritable_unlocked(FILE* fp) +{ + return fp->write_func != NULL; +} diff --git a/libc/stdio/fwrite.cpp b/libc/stdio/fwrite.cpp index 4150f4a1..c8177b29 100644 --- a/libc/stdio/fwrite.cpp +++ b/libc/stdio/fwrite.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,31 +26,8 @@ extern "C" size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* fp) { - if ( fp->buffer_mode == _IONBF ) - { - if ( !(fp->flags & _FILE_BUFFER_MODE_SET) ) - if ( fsetdefaultbuf(fp) != 0 ) - return EOF; // TODO: ferror doesn't report error! - - if ( !fp->write_func ) - return 0; // TODO: ferror doesn't report error! - if ( fp->flags & _FILE_LAST_READ ) - fflush_stop_reading(fp); - fp->flags |= _FILE_LAST_WRITE; - return fp->write_func(ptr, size, nmemb, fp->user); - } - - const unsigned char* buf = (const unsigned char*) ptr; - for ( size_t n = 0; n < nmemb; n++ ) - { - size_t offset = n * size; - for ( size_t i = 0; i < size; i++ ) - { - size_t index = offset + i; - if ( fputc(buf[index], fp) == EOF ) - return n; - } - } - - return nmemb; + flockfile(fp); + size_t ret = fwrite_unlocked(ptr, size, nmemb, fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/fwrite_unlocked.cpp b/libc/stdio/fwrite_unlocked.cpp new file mode 100644 index 00000000..d6ccaf1b --- /dev/null +++ b/libc/stdio/fwrite_unlocked.cpp @@ -0,0 +1,57 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fwrite_unlocked.cpp + Writes data to a FILE. + +*******************************************************************************/ + +#include + +extern "C" +size_t fwrite_unlocked(const void* ptr, size_t size, size_t nmemb, FILE* fp) +{ + if ( fp->buffer_mode == _IONBF ) + { + if ( !(fp->flags & _FILE_BUFFER_MODE_SET) ) + if ( fsetdefaultbuf_unlocked(fp) != 0 ) + return EOF; // TODO: ferror doesn't report error! + + if ( !fp->write_func ) + return 0; // TODO: ferror doesn't report error! + if ( fp->flags & _FILE_LAST_READ ) + fflush_stop_reading_unlocked(fp); + fp->flags |= _FILE_LAST_WRITE; + return fp->write_func(ptr, size, nmemb, fp->user); + } + + const unsigned char* buf = (const unsigned char*) ptr; + for ( size_t n = 0; n < nmemb; n++ ) + { + size_t offset = n * size; + for ( size_t i = 0; i < size; i++ ) + { + size_t index = offset + i; + if ( fputc_unlocked(buf[index], fp) == EOF ) + return n; + } + } + + return nmemb; +} diff --git a/libc/stdio/fwriting.cpp b/libc/stdio/fwriting.cpp index af16d441..9d758d53 100644 --- a/libc/stdio/fwriting.cpp +++ b/libc/stdio/fwriting.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,7 +26,8 @@ extern "C" int fwriting(FILE* fp) { - if ( fp->write_func ) { return 1; } - if ( fp->flags & _FILE_LAST_WRITE ) { return 1; } - return 0; + flockfile(fp); + int ret = fwriting_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/fwriting_unlocked.cpp b/libc/stdio/fwriting_unlocked.cpp new file mode 100644 index 00000000..b8085eb1 --- /dev/null +++ b/libc/stdio/fwriting_unlocked.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/fwriting_unlocked.cpp + Returns whether the last operation was a write or FILE is write only. + +*******************************************************************************/ + +#include + +extern "C" int fwriting_unlocked(FILE* fp) +{ + if ( fp->write_func ) + return 1; + if ( fp->flags & _FILE_LAST_WRITE ) + return 1; + return 0; +} diff --git a/libc/stdio/getc.cpp b/libc/stdio/getc.cpp index 289ada86..7f6bff05 100644 --- a/libc/stdio/getc.cpp +++ b/libc/stdio/getc.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,5 +26,8 @@ extern "C" int getc(FILE* fp) { - return fgetc(fp); + flockfile(fp); + int ret = getc_unlocked(fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/getc_unlocked.cpp b/libc/stdio/getc_unlocked.cpp new file mode 100644 index 00000000..85c055ac --- /dev/null +++ b/libc/stdio/getc_unlocked.cpp @@ -0,0 +1,30 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/getc_unlocked.cpp + Reads a single character from a FILE. + +*******************************************************************************/ + +#include + +extern "C" int getc_unlocked(FILE* fp) +{ + return fgetc_unlocked(fp); +} diff --git a/libc/stdio/getdelim.cpp b/libc/stdio/getdelim.cpp index 37a934e4..baaffee8 100644 --- a/libc/stdio/getdelim.cpp +++ b/libc/stdio/getdelim.cpp @@ -37,9 +37,10 @@ extern "C" ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* fp) if ( n ) { *n = bufsize; } ssize_t written = 0; int c; + flockfile(fp); do { - if ( (c = getc(fp)) == EOF ) + if ( (c = getc_unlocked(fp)) == EOF ) { if ( written ) { break; } else { goto cleanup; } } @@ -54,10 +55,12 @@ extern "C" ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* fp) } (*lineptr)[written++] = c; } while ( c != delim ); + funlockfile(fp); (*lineptr)[written] = 0; return written; cleanup: + funlockfile(fp); free(malloced ? *lineptr : NULL); return -1; } diff --git a/libc/stdio/putc.cpp b/libc/stdio/putc.cpp index b0792e67..8a9f40d6 100644 --- a/libc/stdio/putc.cpp +++ b/libc/stdio/putc.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -26,5 +26,8 @@ extern "C" int putc(int c, FILE* fp) { - return fputc(c, fp); + flockfile(fp); + int ret = putc_unlocked(c, fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/putc_unlocked.cpp b/libc/stdio/putc_unlocked.cpp new file mode 100644 index 00000000..888e163e --- /dev/null +++ b/libc/stdio/putc_unlocked.cpp @@ -0,0 +1,30 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/putc_unlocked.cpp + Writes a character to a FILE. + +*******************************************************************************/ + +#include + +extern "C" int putc_unlocked(int c, FILE* fp) +{ + return fputc_unlocked(c, fp); +} diff --git a/libc/stdio/rewind.cpp b/libc/stdio/rewind.cpp index 8c8aa352..08c0e930 100644 --- a/libc/stdio/rewind.cpp +++ b/libc/stdio/rewind.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014. This file is part of the Sortix C Library. @@ -26,6 +26,8 @@ extern "C" void rewind(FILE* fp) { - fseek(fp, 0L, SEEK_SET); - clearerr(fp); + flockfile(fp); + fseeko_unlocked(fp, 0, SEEK_SET); + clearerr_unlocked(fp); + funlockfile(fp); } diff --git a/libc/stdio/setvbuf.cpp b/libc/stdio/setvbuf.cpp index b25896dd..9d5c71df 100644 --- a/libc/stdio/setvbuf.cpp +++ b/libc/stdio/setvbuf.cpp @@ -22,19 +22,12 @@ *******************************************************************************/ -#include #include extern "C" int setvbuf(FILE* fp, char* buf, int mode, size_t size) { - if ( fp->flags & _FILE_BUFFER_MODE_SET ) - return errno = EINVAL, -1; - fp->buffer_mode = mode; - if ( buf ) - { - fp->buffer = (unsigned char*) buf; - fp->buffersize = size; - fp->flags |= _FILE_BUFFER_MODE_SET; - } - return 0; + flockfile(fp); + int ret = setvbuf_unlocked(fp, buf, mode, size); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/setvbuf_unlocked.cpp b/libc/stdio/setvbuf_unlocked.cpp new file mode 100644 index 00000000..63832905 --- /dev/null +++ b/libc/stdio/setvbuf_unlocked.cpp @@ -0,0 +1,40 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/setvbuf_unlocked.cpp + Sets up buffering semantics for a FILE. + +*******************************************************************************/ + +#include +#include + +extern "C" int setvbuf_unlocked(FILE* fp, char* buf, int mode, size_t size) +{ + if ( fp->flags & _FILE_BUFFER_MODE_SET ) + return errno = EINVAL, -1; + fp->buffer_mode = mode; + if ( buf ) + { + fp->buffer = (unsigned char*) buf; + fp->buffersize = size; + fp->flags |= _FILE_BUFFER_MODE_SET; + } + return 0; +} diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp index d75e8926..61ca7853 100644 --- a/libc/stdio/stdio.cpp +++ b/libc/stdio/stdio.cpp @@ -47,14 +47,30 @@ extern "C" int init_stdio() return 0; } +extern "C" int getchar_unlocked(void) +{ + return fgetc_unlocked(stdin); +} + +extern "C" int putchar_unlocked(int c) +{ + return fputc_unlocked(c, stdout); +} + extern "C" int getchar(void) { - return fgetc(stdin); + flockfile(stdin); + int ret = getchar_unlocked(); + funlockfile(stdin); + return ret; } extern "C" int putchar(int c) { - return fputc(c, stdout); + flockfile(stdin); + int ret = putchar_unlocked(c); + funlockfile(stdin); + return ret; } extern "C" int puts(const char* str) diff --git a/libc/stdio/ungetc.cpp b/libc/stdio/ungetc.cpp index f58ab390..6f97c4e4 100644 --- a/libc/stdio/ungetc.cpp +++ b/libc/stdio/ungetc.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. This file is part of the Sortix C Library. @@ -24,33 +24,11 @@ *******************************************************************************/ #include -#include -#include extern "C" int ungetc(int c, FILE* fp) { - if ( !(fp->flags & _FILE_BUFFER_MODE_SET) ) - if ( fsetdefaultbuf(fp) != 0 ) - return EOF; // TODO: ferror doesn't report error! - - if ( !fp->read_func || fp->buffer_mode == _IONBF ) - return EOF; - - if ( fp->flags & _FILE_LAST_WRITE ) - fflush_stop_writing(fp); - fp->flags |= _FILE_LAST_READ; - - if ( fp->offset_input_buffer == 0 ) - { - size_t amount = fp->amount_input_buffered - fp->offset_input_buffer; - size_t offset = fp->buffersize - amount; - if ( !offset ) - return EOF; - memmove(fp->buffer + offset, fp->buffer, sizeof(fp->buffer[0]) * amount); - fp->offset_input_buffer = offset; - fp->amount_input_buffered = offset + amount; - } - - fp->buffer[--fp->offset_input_buffer] = c; - return c; + flockfile(fp); + int ret = ungetc_unlocked(c, fp); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/ungetc_unlocked.cpp b/libc/stdio/ungetc_unlocked.cpp new file mode 100644 index 00000000..3615d900 --- /dev/null +++ b/libc/stdio/ungetc_unlocked.cpp @@ -0,0 +1,56 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/ungetc_unlocked.cpp + Inserts data in front of the current read queue, allowing applications to + peek the incoming data and pretend they didn't. + +*******************************************************************************/ + +#include +#include +#include + +extern "C" int ungetc_unlocked(int c, FILE* fp) +{ + if ( !(fp->flags & _FILE_BUFFER_MODE_SET) ) + if ( fsetdefaultbuf_unlocked(fp) != 0 ) + return EOF; // TODO: ferror doesn't report error! + + if ( !fp->read_func || fp->buffer_mode == _IONBF ) + return EOF; + + if ( fp->flags & _FILE_LAST_WRITE ) + fflush_stop_writing_unlocked(fp); + fp->flags |= _FILE_LAST_READ; + + if ( fp->offset_input_buffer == 0 ) + { + size_t amount = fp->amount_input_buffered - fp->offset_input_buffer; + size_t offset = fp->buffersize - amount; + if ( !offset ) + return EOF; + memmove(fp->buffer + offset, fp->buffer, sizeof(fp->buffer[0]) * amount); + fp->offset_input_buffer = offset; + fp->amount_input_buffered = offset + amount; + } + + fp->buffer[--fp->offset_input_buffer] = c; + return c; +} diff --git a/libc/stdio/vfprintf.cpp b/libc/stdio/vfprintf.cpp index de293332..7f198117 100644 --- a/libc/stdio/vfprintf.cpp +++ b/libc/stdio/vfprintf.cpp @@ -26,15 +26,10 @@ #include #include -static size_t FileWriteCallback(void* user, const char* string, size_t stringlen) -{ - return fwrite(string, sizeof(char), stringlen, (FILE*) user); -} - extern "C" int vfprintf(FILE* fp, const char* restrict format, va_list list) { - size_t result = vprintf_callback(FileWriteCallback, fp, format, list); - if ( result == SIZE_MAX ) - return -1; - return (int) result; + flockfile(fp); + int ret = vfprintf_unlocked(fp, format, list); + funlockfile(fp); + return ret; } diff --git a/libc/stdio/vfprintf_unlocked.cpp b/libc/stdio/vfprintf_unlocked.cpp new file mode 100644 index 00000000..410c2b9b --- /dev/null +++ b/libc/stdio/vfprintf_unlocked.cpp @@ -0,0 +1,41 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/vfprintf_unlocked.cpp + Prints a string to a FILE. + +*******************************************************************************/ + +#include +#include +#include + +static size_t FileWriteCallback(void* user, const char* string, size_t stringlen) +{ + return fwrite_unlocked(string, sizeof(char), stringlen, (FILE*) user); +} + +extern "C" +int vfprintf_unlocked(FILE* fp, const char* restrict format, va_list list) +{ + size_t result = vprintf_callback(FileWriteCallback, fp, format, list); + if ( result == SIZE_MAX ) + return -1; + return (int) result; +} diff --git a/libc/stdio/vfscanf.cpp b/libc/stdio/vfscanf.cpp index 51898680..ca23c27b 100644 --- a/libc/stdio/vfscanf.cpp +++ b/libc/stdio/vfscanf.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2014. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014. This file is part of the Sortix C Library. @@ -24,17 +24,10 @@ #include -static int wrap_fgetc(void* fp) -{ - return fgetc((FILE*) fp); -} - -static int wrap_ungetc(int c, void* fp) -{ - return ungetc(c, (FILE*) fp); -} - extern "C" int vfscanf(FILE* fp, const char* format, va_list ap) { - return vscanf_callback(fp, wrap_fgetc, wrap_ungetc, format, ap); + flockfile(fp); + int result = vfscanf_unlocked(fp, format, ap); + funlockfile(fp); + return result; } diff --git a/libc/stdio/vfscanf_unlocked.cpp b/libc/stdio/vfscanf_unlocked.cpp new file mode 100644 index 00000000..bd238553 --- /dev/null +++ b/libc/stdio/vfscanf_unlocked.cpp @@ -0,0 +1,40 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + stdio/vfscanf_unlocked.cpp + Input format conversion. + +*******************************************************************************/ + +#include + +static int wrap_fgetc(void* fp) +{ + return fgetc_unlocked((FILE*) fp); +} + +static int wrap_ungetc(int c, void* fp) +{ + return ungetc_unlocked(c, (FILE*) fp); +} + +extern "C" int vfscanf_unlocked(FILE* fp, const char* format, va_list ap) +{ + return vscanf_callback(fp, wrap_fgetc, wrap_ungetc, format, ap); +}