Beispiel #1
0
int FSEEK(register FILE *stream, OFFSET_TYPE offset, int whence)
{
#if defined(__UCLIBC_HAS_LFS__) && !defined(__DO_LARGEFILE)

	return fseeko64(stream, offset, whence);

#else

	__offmax_t pos = offset;
	int retval = -1;
	__STDIO_AUTO_THREADLOCK_VAR;

	if (((unsigned int) whence) > 2) {
		__set_errno(EINVAL);
	} else {
		__STDIO_AUTO_THREADLOCK(stream);

		__STDIO_STREAM_VALIDATE(stream);

		if ((!__STDIO_STREAM_IS_WRITING(stream)
			  || !__STDIO_COMMIT_WRITE_BUFFER(stream))
			&& ((whence != SEEK_CUR)
				 || (__stdio_adjust_position(stream, &pos) >= 0))
			&& (__SEEK(stream, &pos, whence) >= 0)
			) {

			/* Clear reading/writing modes, EOF, and ungots. */
			stream->__modeflags &=
				~(__MASK_READING|__FLAG_WRITING|__FLAG_EOF);

			/* Make sure all pointers are reset. */
			__STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
			__STDIO_STREAM_DISABLE_GETC(stream);
			__STDIO_STREAM_DISABLE_PUTC(stream);

			/* We reinitialize the mbstate object.  Doing so is
			 * implementation defined behavior. */
#ifdef __STDIO_MBSTATE
			__INIT_MBSTATE(&(stream->__state));
#endif
#ifdef __UCLIBC_HAS_WCHAR__
			stream->__ungot_width[0] = 0;
#endif

			retval = 0;
		}

		__STDIO_STREAM_VALIDATE(stream);

		__STDIO_AUTO_THREADUNLOCK(stream);
	}

	return retval;

#endif
}
Beispiel #2
0
 *      auto-transition via fseek() is a configurable option.
 *   Returns 0 on success and EOF otherwise.
 *
 * Notes:
 *   There are two function signatures, depending on wchar support,
 *   since with no wchar support the orientation is narrow by default.
 */

#ifdef __UCLIBC_HAS_WCHAR__
int __stdio_trans2w_o(FILE * __restrict stream, int oflag)
#else
int __stdio_trans2w(FILE * __restrict stream)
#endif
{
	__STDIO_STREAM_VALIDATE(stream);
	assert(!__STDIO_STREAM_IS_WRITING(stream));

#ifdef __UCLIBC_HAS_WCHAR__
	if (!(stream->__modeflags & oflag)) {
		if (stream->__modeflags & (__FLAG_NARROW|__FLAG_WIDE)) {
			__UNDEFINED_OR_NONPORTABLE;
			goto DO_EBADF;
		}
		stream->__modeflags |= oflag;
	}
#endif

	if (stream->__modeflags & __FLAG_READONLY) {
	DO_EBADF:
		__set_errno(EBADF);
	ERROR:
Beispiel #3
0
size_t attribute_hidden __stdio_WRITE(register FILE *stream,
                                      register const unsigned char *buf, size_t bufsize)
{
    size_t todo;
    ssize_t rv, stodo;

    __STDIO_STREAM_VALIDATE(stream);
    assert(stream->__filedes >= -1);
    assert(__STDIO_STREAM_IS_WRITING(stream));
    assert(!__STDIO_STREAM_BUFFER_WUSED(stream)); /* Buffer must be empty. */

    todo = bufsize;

    do {
        if (todo == 0) {		/* Done? */
            __STDIO_STREAM_VALIDATE(stream);
            return bufsize;
        }
        stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX;
        if ((rv = __WRITE(stream, (char *) buf, stodo)) >= 0) {
#ifdef __UCLIBC_MJN3_ONLY__
#warning TODO: Make custom stream write return check optional.
#endif
#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
            assert(rv <= stodo);
            if (rv > stodo) {	/* Wrote more than stodo! */
                /* 				abort(); */
            }
#endif
            todo -= rv;
            buf += rv;
        } else
#ifdef __UCLIBC_MJN3_ONLY__
#warning EINTR?
#endif
            /* 		if (errno != EINTR) */
        {
            __STDIO_STREAM_SET_ERROR(stream);

#ifdef __STDIO_BUFFERS
            if ((stodo = __STDIO_STREAM_BUFFER_SIZE(stream)) != 0) {
                unsigned char *s;

                if (stodo > todo) {
                    stodo = todo;
                }

                s  = stream->__bufstart;

                do {
                    if (((*s = *buf) == '\n')
                            && __STDIO_STREAM_IS_LBF(stream)
                       ) {
                        break;
                    }
                    ++s;
                    ++buf;
                } while (--stodo);

                stream->__bufpos = s;

                todo -= (s - stream->__bufstart);
            }
#endif /* __STDIO_BUFFERS */

            __STDIO_STREAM_VALIDATE(stream);
            return bufsize - todo;
        }
    } while (1);
}
int fflush_unlocked(register FILE *stream)
{
#ifdef __STDIO_BUFFERS

	int retval = 0;
#ifdef __UCLIBC_MJN3_ONLY__
#warning REMINDER: should probably define a modeflags type
#endif
	unsigned short bufmask = __FLAG_LBF;

#ifndef NDEBUG
	if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) {
		__STDIO_STREAM_VALIDATE(stream); /* debugging only */
	}
#endif

	if (stream == (FILE *) &_stdio_openlist) { /* Flush all lbf streams. */
		stream = NULL;
		bufmask = 0;
	}

	if (!stream) {				/* Flush all (lbf) writing streams. */

		__STDIO_OPENLIST_INC_USE;

		__STDIO_THREADLOCK_OPENLIST_ADD;
		stream = _stdio_openlist;
		__STDIO_THREADUNLOCK_OPENLIST_ADD;

		while(stream) {
			/* We only care about currently writing streams and do not want to
			 * block trying to obtain mutexes on non-writing streams. */
#warning fix for nonatomic
#warning unnecessary check if no threads
			if (__STDIO_STREAM_IS_WRITING(stream)) { /* ONLY IF ATOMIC!!! */
				__MY_STDIO_THREADLOCK(stream);
				/* Need to check again once we have the lock. */
				if (!(((stream->__modeflags | bufmask)
					   ^ (__FLAG_WRITING|__FLAG_LBF)
					   ) & (__FLAG_WRITING|__MASK_BUFMODE))
					) {
					if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
						__STDIO_STREAM_DISABLE_PUTC(stream);
						__STDIO_STREAM_CLEAR_WRITING(stream);
					} else {
						retval = EOF;
					}
				}
				__MY_STDIO_THREADUNLOCK(stream);
			}
			stream = stream->__nextopen;
		}

		__STDIO_OPENLIST_DEC_USE;

	} else if (__STDIO_STREAM_IS_WRITING(stream)) {
		if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) {
			__STDIO_STREAM_DISABLE_PUTC(stream);
			__STDIO_STREAM_CLEAR_WRITING(stream);
		} else {
			retval = EOF;
		}
	}
#if 0
	else if (stream->__modeflags & (__MASK_READING|__FLAG_READONLY)) {
		/* ANSI/ISO says behavior in this case is undefined but also says you
		 * shouldn't flush a stream you were reading from.  As usual, glibc
		 * caters to broken programs and simply ignores this. */
		__UNDEFINED_OR_NONPORTABLE;
		__STDIO_STREAM_SET_ERROR(stream);
		__set_errno(EBADF);
		retval = EOF;
	}
#endif

#ifndef NDEBUG
	if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) {
		__STDIO_STREAM_VALIDATE(stream); /* debugging only */
	}
#endif

	return retval;

#else  /* __STDIO_BUFFERS --------------------------------------- */

#ifndef NDEBUG
	if ((stream != NULL)
#ifdef __STDIO_HAS_OPENLIST
		&& (stream != (FILE *) &_stdio_openlist)
#endif
		) {
		__STDIO_STREAM_VALIDATE(stream); /* debugging only */
	}
#endif

#if 0
	if (stream && (stream->__modeflags & (__MASK_READING|__FLAG_READONLY))) {
		/* ANSI/ISO says behavior in this case is undefined but also says you
		 * shouldn't flush a stream you were reading from.  As usual, glibc
		 * caters to broken programs and simply ignores this. */
		__UNDEFINED_OR_NONPORTABLE;
		__STDIO_STREAM_SET_ERROR(stream);
		__set_errno(EBADF);
		return EOF;
	}
#endif

	return 0;
#endif /* __STDIO_BUFFERS */
}
Beispiel #5
0
void _stdio_validate_FILE(const FILE *stream)
{
#ifdef __UCLIBC_HAS_THREADS__
	assert(((unsigned int)(stream->__user_locking)) <= 2);
#endif

#warning Define a constant for minimum possible valid __filedes?
	assert(stream->__filedes >= -3);

	if (stream->__filedes < 0) {
/* 		assert((stream->__filedes != -1) */
/* #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
/* 			   || (stream->__cookie == &stream->__filedes) /\* custom *\/ */
/* #endif */
/* 			   ); */
/* 		assert((stream->__filedes == -1) || __STDIO_STREAM_IS_FBF(stream)); */

		assert(!__STDIO_STREAM_IS_FAKE_VSNPRINTF(stream)
			   || __STDIO_STREAM_IS_NARROW(stream));
		assert(!__STDIO_STREAM_IS_FAKE_VSSCANF(stream)
			   || __STDIO_STREAM_IS_NARROW(stream));
#ifdef __STDIO_STREAM_IS_FAKE_VSWPRINTF
		assert(!__STDIO_STREAM_IS_FAKE_VSWPRINTF(stream)
			   || __STDIO_STREAM_IS_WIDE(stream));
#endif
#ifdef __STDIO_STREAM_IS_FAKE_VSWSCANF
		assert(!__STDIO_STREAM_IS_FAKE_VSWSCANF(stream)
			   || __STDIO_STREAM_IS_WIDE(stream));
#endif
	}

#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
	if (stream->__cookie != &stream->__filedes) { /* custom */
		assert(stream->__filedes == -1);
	}
#endif

	/* Can not be both narrow and wide oriented at the same time. */
	assert(!(__STDIO_STREAM_IS_NARROW(stream)
			 && __STDIO_STREAM_IS_WIDE(stream)));


	/* The following impossible case is used to disable a stream. */
	if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY))
		== (__FLAG_READONLY|__FLAG_WRITEONLY)
		) {
		assert(stream->__modeflags == (__FLAG_READONLY|__FLAG_WRITEONLY));
		assert(stream->__filedes == -1);
#ifdef __STDIO_BUFFERS
		assert(stream->__bufpos == stream->__bufstart);
		assert(stream->__bufread == stream->__bufstart);
# ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__
		assert(stream->__bufputc_u == stream->__bufstart);
# endif
# ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__
		assert(stream->__bufgetc_u == stream->__bufstart);
# endif
#endif
	}

	if (__STDIO_STREAM_IS_READONLY(stream)) {
/* 		assert(!__STDIO_STREAM_IS_WRITEONLY(stream)); */
		assert(!__STDIO_STREAM_IS_WRITING(stream));
		if (stream->__modeflags & __FLAG_UNGOT) {
			assert(((unsigned)(stream->__ungot[1])) <= 1);
			assert(!__FEOF_UNLOCKED(stream));
		}
	}

	if (__STDIO_STREAM_IS_WRITEONLY(stream)) {
/* 		assert(!__STDIO_STREAM_IS_READONLY(stream)); */
		assert(!__STDIO_STREAM_IS_READING(stream));
		assert(!(stream->__modeflags & __FLAG_UNGOT));
	}

	if (__STDIO_STREAM_IS_NBF(stream)) {
		/* We require that all non buffered streams have no buffer. */
		assert(!__STDIO_STREAM_BUFFER_SIZE(stream));
	}

	assert((stream->__modeflags & __MASK_BUFMODE) <= __FLAG_NBF);

#ifdef __STDIO_BUFFERS
	/* Ensure __bufstart <= __bufpos <= __bufend. */
	assert(stream->__bufpos >= stream->__bufstart);
	assert(stream->__bufpos <= stream->__bufend);
	/* Ensure __bufstart <= __bufread <= __bufend. */
	assert(stream->__bufread >= stream->__bufstart);
	assert(stream->__bufread <= stream->__bufend);
#endif

	/* If EOF, then we must have no buffered readable or ungots. */
	if (__FEOF_UNLOCKED(stream)) {
#ifdef __STDIO_BUFFERS
		assert(stream->__bufpos == stream->__bufread);
#endif
		assert(!(stream->__modeflags & __FLAG_UNGOT));
	}


	if (!__STDIO_STREAM_IS_WRITING(stream)) {
#ifdef __STDIO_BUFFERS
		/* If not writing, then putc macro must be disabled. */
# ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__
		assert(stream->__bufputc_u == stream->__bufstart);
# endif
#endif
	}

	if (!__STDIO_STREAM_IS_READING(stream)) {
		/* If not reading, then can not have ungots. */
		assert(!(stream->__modeflags & __FLAG_UNGOT));
#ifdef __STDIO_BUFFERS
		/* Ensure __bufread == __bufstart. */
		assert(stream->__bufread == stream->__bufstart);
		/* If not reading, then getc macro must be disabled. */
# ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__
		assert(stream->__bufgetc_u == stream->__bufstart);
# endif
#endif
	}

	if (__STDIO_STREAM_IS_READING(stream)) {
		assert(!__STDIO_STREAM_IS_WRITING(stream));
#ifdef __STDIO_BUFFERS
		/* Ensure __bufpos <= __bufread. */
		assert(stream->__bufpos <= stream->__bufread);

		/* Ensure __bufgetc_u is valid. */
# ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__
		assert(stream->__bufgetc_u >= stream->__bufstart);
		assert(stream->__bufgetc_u <= stream->__bufread);
# endif

#endif
	}

	if (__STDIO_STREAM_IS_WRITING(stream)) {
		assert(!__STDIO_STREAM_IS_READING(stream));
#ifdef __STDIO_BUFFERS
# ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__
		assert(stream->__bufputc_u >= stream->__bufstart);
		assert(stream->__bufputc_u <= stream->__bufend);
# endif
#endif
	}

	/* If have an ungotten char, then getc (and putc) must be disabled. */
	/* Also, wide streams must have the getc/putc macros disabled. */
	if ((stream->__modeflags & __FLAG_UNGOT)
		|| __STDIO_STREAM_IS_WIDE(stream)
		) {
#ifdef __STDIO_BUFFERS
# ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__
		assert(stream->__bufputc_u == stream->__bufstart);
# endif
# ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__
		assert(stream->__bufgetc_u == stream->__bufstart);
# endif
#endif
	}

	/* TODO -- filepos?  ungot_width?  filedes?  nextopen? */
}
Beispiel #6
0
/* We assume here that we are the only remaining thread. */
void attribute_hidden _stdio_term(void)
{
#if defined(__STDIO_BUFFERS) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__)
	register FILE *ptr;

#ifdef __UCLIBC_HAS_THREADS__
	/* First, make sure the open file list is unlocked.  If it was
	 * locked, then I suppose there is a chance that a pointer in the
	 * chain might be corrupt due to a partial store.
	 */
	__stdio_init_mutex(&_stdio_openlist_add_lock);
#warning check
#ifdef __STDIO_BUFFERS
	__stdio_init_mutex(&_stdio_openlist_del_lock);
#endif

	/* Next we need to worry about the streams themselves.  If a stream
	 * is currently locked, then it may be in an invalid state.  So we
	 * 'disable' it in case a custom stream is stacked on top of it.
	 * Then we reinitialize the locks.
	 */
	for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) {
		if (__STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(ptr)) {
			/* The stream is already locked, so we don't want to touch it.
			 * However, if we have custom streams, we can't just close it
			 * or leave it locked since a custom stream may be stacked
			 * on top of it.  So we do unlock it, while also disabling it.
			 */
			ptr->__modeflags = (__FLAG_READONLY|__FLAG_WRITEONLY);
			__STDIO_STREAM_DISABLE_GETC(ptr);
			__STDIO_STREAM_DISABLE_PUTC(ptr);
			__STDIO_STREAM_INIT_BUFREAD_BUFPOS(ptr);
		}

		ptr->__user_locking = 1; /* Set locking mode to "by caller". */
		__stdio_init_mutex(&ptr->__lock); /* Shouldn't be necessary, but... */
	}
#endif

	/* Finally, flush all writing streams and shut down all custom streams.
	 * NOTE: We assume that any stacking by custom streams is done on top
	 *       of streams previously allocated, and hence further down the
	 *       list.  Otherwise we have no way of knowing the order in which
	 *       to shut them down.
	 *       Remember that freopen() counts as a new allocation here, even
	 *       though the stream is reused.  That's because it moves the
	 *       stream to the head of the list.
	 */
	for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) {
#ifdef __STDIO_BUFFERS
		/* Write any pending buffered chars. */
		if (__STDIO_STREAM_IS_WRITING(ptr)) {
			__STDIO_COMMIT_WRITE_BUFFER(ptr);
		}
#endif
#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
		/* Actually close all custom streams to perform any special cleanup. */
		if (ptr->__cookie != &ptr->__filedes) {
			__CLOSE(ptr);
		}
#endif
	}

#endif
}
Beispiel #7
0
int fclose(register FILE *stream)
{
    int rv = 0;
    __STDIO_AUTO_THREADLOCK_VAR;

#ifdef __STDIO_HAS_OPENLIST
#if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS)
    /* First, remove the file from the open file list. */
    {
        FILE *ptr;

        __STDIO_THREADLOCK_OPENLIST_DEL;
        __STDIO_THREADLOCK_OPENLIST_ADD;
        ptr = _stdio_openlist;
        if ((ptr = _stdio_openlist) == stream) {
            _stdio_openlist = stream->__nextopen;
        } else {
            while (ptr) {
                if (ptr->__nextopen == stream) {
                    ptr->__nextopen = stream->__nextopen;
                    break;
                }
                ptr = ptr->__nextopen;
            }
        }
        __STDIO_THREADUNLOCK_OPENLIST_ADD;
        __STDIO_THREADUNLOCK_OPENLIST_DEL;
    }
#endif
#endif

    __STDIO_AUTO_THREADLOCK(stream);

    __STDIO_STREAM_VALIDATE(stream);

#ifdef __STDIO_BUFFERS
    /* Write any pending buffered chars. */
    if (__STDIO_STREAM_IS_WRITING(stream)) {
        rv = fflush_unlocked(stream);
    }
#endif

    if (__CLOSE(stream) < 0) {	/* Must close even if fflush failed. */
        rv = EOF;
    }

    stream->__filedes = -1;

    /* We need a way for freopen to know that a file has been closed.
     * Since a file can't be both readonly and writeonly, that makes
     * an effective signal.  It also has the benefit of disabling
     * transitions to either reading or writing. */
#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
    /* Before we mark the file as closed, make sure we increment the openlist use count
     * so it isn't freed under us while still cleaning up. */
    __STDIO_OPENLIST_INC_USE;
#endif
    stream->__modeflags &= (__FLAG_FREEBUF|__FLAG_FREEFILE);
    stream->__modeflags |= (__FLAG_READONLY|__FLAG_WRITEONLY);

#ifndef NDEBUG
    __STDIO_STREAM_RESET_GCS(stream);

    /* Reinitialize everything (including putc since fflush could fail). */
    __STDIO_STREAM_DISABLE_GETC(stream);
    __STDIO_STREAM_DISABLE_PUTC(stream);
    __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);

# ifdef __UCLIBC_HAS_WCHAR__
    stream->__ungot_width[0] = 0;
# endif
# ifdef __STDIO_MBSTATE
    __INIT_MBSTATE(&(stream->__state));
# endif
#endif

    __STDIO_AUTO_THREADUNLOCK(stream);

    __STDIO_STREAM_FREE_BUFFER(stream);
#ifdef __UCLIBC_MJN3_ONLY__
#warning REMINDER: inefficient - locks and unlocks twice and walks whole list
#endif
#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS)
    /* inefficient - locks/unlocks twice and walks whole list */
    __STDIO_OPENLIST_INC_DEL_CNT;
    __STDIO_OPENLIST_DEC_USE;	/* This with free the file if necessary. */
#else
    __STDIO_STREAM_FREE_FILE(stream);
#endif

    return rv;
}