123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- #include "_stdio.h"
- #if (O_ACCMODE != 3) || (O_RDONLY != 0) || (O_WRONLY != 1) || (O_RDWR != 2)
- #error Assumption violated - mode constants
- #endif
- #ifndef O_LARGEFILE
- #define O_LARGEFILE 0
- #endif
- FILE attribute_hidden *_stdio_fopen(intptr_t fname_or_mode,
- register const char * __restrict mode,
- register FILE * __restrict stream, int filedes)
- {
- __mode_t open_mode;
- int i;
-
- open_mode = O_RDONLY;
- if (*mode != 'r') {
- open_mode = (O_WRONLY | O_CREAT | O_TRUNC);
- if (*mode != 'w') {
- open_mode = (O_WRONLY | O_CREAT | O_APPEND);
- if (*mode != 'a') {
- DO_EINVAL:
- __set_errno(EINVAL);
- if (stream) {
- FREE_STREAM:
- assert(!(stream->__modeflags & __FLAG_FREEBUF));
- __STDIO_STREAM_FREE_FILE(stream);
- }
- return NULL;
- }
- }
- }
- if ((mode[1] == 'b')) {
- ++mode;
- }
- if (mode[1] == '+') {
- ++mode;
- open_mode |= (O_RDONLY | O_WRONLY);
- open_mode += (O_RDWR - (O_RDONLY | O_WRONLY));
- }
- #ifdef __UCLIBC_MJN3_ONLY__
- #warning CONSIDER: Implement glibc ccs option to bind a codeset?
- #warning CONSIDER: Implement glibc mmap option for readonly files?
- #warning CONSIDER: Implement a text mode using custom read/write funcs?
- #endif
- #if defined(__UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__) || defined(__UCLIBC_HAS_FOPEN_LARGEFILE_MODE__)
- while (*++mode) {
- # ifdef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__
- if (*mode == 'x') {
- open_mode |= O_EXCL;
- continue;
- }
- # endif
- # ifdef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__
- if (*mode == 'F') {
- open_mode |= O_LARGEFILE;
- continue;
- }
- # endif
- }
- #endif
- if (!stream) {
- if ((stream = malloc(sizeof(FILE))) == NULL) {
- return stream;
- }
- stream->__modeflags = __FLAG_FREEFILE;
- #ifdef __STDIO_BUFFERS
- stream->__bufstart = NULL;
- #endif
- #ifdef __UCLIBC_HAS_THREADS__
-
-
- __stdio_init_mutex(&stream->__lock);
- #endif
- }
- #ifdef __UCLIBC_MJN3_ONLY__
- #warning TODO: Verify fdopen append behavior of glibc.
- #endif
- if (filedes >= 0) {
- stream->__filedes = filedes;
-
- i = (open_mode & (O_ACCMODE|O_LARGEFILE)) + 1;
-
- if (((i & (((int) fname_or_mode) + 1)) != i)
- || (((open_mode & ~((__mode_t) fname_or_mode)) & O_APPEND)
- && fcntl(filedes, F_SETFL, O_APPEND))
- ) {
- goto DO_EINVAL;
- }
-
- __STDIO_WHEN_LFS( open_mode |= (((__mode_t) fname_or_mode)
- & O_LARGEFILE) );
- } else {
- __STDIO_WHEN_LFS( if (filedes < -1) open_mode |= O_LARGEFILE );
- if ((stream->__filedes = open(((const char *) fname_or_mode),
- open_mode, 0666)) < 0) {
- goto FREE_STREAM;
- }
- }
- stream->__modeflags &= __FLAG_FREEFILE;
- stream->__modeflags |=
- #if (O_APPEND != __FLAG_APPEND) || ((O_LARGEFILE != __FLAG_LARGEFILE) && (O_LARGEFILE != 0))
- # if (O_APPEND != __FLAG_APPEND)
- ((open_mode & O_APPEND) ? __FLAG_APPEND : 0) |
- # else
- (open_mode & O_APPEND) |
- # endif
- # if (O_LARGEFILE != __FLAG_LARGEFILE) && (O_LARGEFILE != 0)
- ((open_mode & O_LARGEFILE) ? __FLAG_LARGEFILE : 0) |
- # else
- (open_mode & O_LARGEFILE) |
- # endif
- #else
- (open_mode & (O_APPEND|O_LARGEFILE)) |
- #endif
- ((((open_mode & O_ACCMODE) + 1) ^ 0x03) * __FLAG_WRITEONLY);
- #ifdef __STDIO_BUFFERS
- i = errno;
- stream->__modeflags |= (isatty(stream->__filedes) * __FLAG_LBF);
- __set_errno(i);
- if (!stream->__bufstart) {
- if ((stream->__bufstart = malloc(BUFSIZ)) != NULL) {
- stream->__bufend = stream->__bufstart + BUFSIZ;
- stream->__modeflags |= __FLAG_FREEBUF;
- } else {
- # if __STDIO_BUILTIN_BUF_SIZE > 0
- stream->__bufstart = stream->__builtinbuf;
- stream->__bufend = stream->__builtinbuf + sizeof(stream->__builtinbuf);
- # else
- stream->__bufend = stream->__bufstart;
- # endif
- }
- }
- __STDIO_STREAM_DISABLE_GETC(stream);
- __STDIO_STREAM_DISABLE_PUTC(stream);
- __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
- #endif
- __STDIO_STREAM_RESET_GCS(stream);
- #ifdef __UCLIBC_HAS_WCHAR__
- stream->__ungot_width[0] = 0;
- #endif
- #ifdef __STDIO_MBSTATE
- __INIT_MBSTATE(&(stream->__state));
- #endif
- #ifdef __UCLIBC_HAS_THREADS__
-
- stream->__user_locking = _stdio_user_locking;
-
- #endif
- #ifdef __STDIO_HAS_OPENLIST
- #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
- if (!(stream->__modeflags & __FLAG_FREEFILE))
- {
-
- }
- else
- #endif
- {
-
- __STDIO_THREADLOCK_OPENLIST_DEL;
- __STDIO_THREADLOCK_OPENLIST_ADD;
- stream->__nextopen = _stdio_openlist;
- _stdio_openlist = stream;
- __STDIO_THREADUNLOCK_OPENLIST_ADD;
- __STDIO_THREADUNLOCK_OPENLIST_DEL;
- }
- #endif
- __STDIO_STREAM_VALIDATE(stream);
- return stream;
- }
|