int fputc(int c, FAR FILE *stream) { unsigned char buf = (unsigned char)c; int ret; ret = lib_fwrite(&buf, 1, stream); if (ret > 0) { /* Flush the buffer if a newline is output */ #ifdef CONFIG_STDIO_LINEBUFFER if (c == '\n') { ret = lib_fflush(stream, true); if (ret < 0) { return EOF; } } #endif return c; } else { return EOF; } }
int fflush(FAR FILE *stream) { int ret; /* Is the stream argument NULL? */ if (!stream) { /* Yes... then this is a request to flush all streams */ ret = lib_flushall(sched_getstreams()); } else { ret = lib_fflush(stream, true); } /* Check the return value */ if (ret < 0) { /* An error occurred during the flush AND/OR we were unable to flush * all of the buffered write data. Set the errno value. */ set_errno(-ret); /* And return EOF on failure. */ return EOF; } return OK; }
int lib_flushall(FAR struct streamlist *list) { int lasterrno = OK; int ret = OK; /* Make sure that there are streams associated with this thread */ if (list) { int i; /* Process each stream in the thread's stream list */ stream_semtake(list); for (i = 0; i < CONFIG_NFILE_STREAMS; i++) { FILE *stream = &list->sl_streams[i]; /* If the stream is open (i.e., assigned a non-negative file * descriptor) and opened for writing, then flush all of the pending * write data in the stream. */ if (stream->fs_filedes >= 0 && (stream->fs_oflags & O_WROK) != 0) { /* Flush the writable FILE */ if (lib_fflush(stream, true) != 0) { /* An error occurred during the flush AND/OR we were unable * to flush all of the buffered write data. Return EOF on failure. */ lasterrno = get_errno(); ret = ERROR; } } } stream_semgive(list); } /* If any flush failed, return that last failed flush */ if (ret != OK) { set_errno(lasterrno); } return ret; }
int lib_wrflush(FAR FILE *stream) { #if CONFIG_STDIO_BUFFER_SIZE > 0 /* Verify that we were passed a valid (i.e., non-NULL) stream */ #ifdef CONFIG_DEBUG if (!stream) { return -EINVAL; } #endif /* Verify that the stream is opened for writing... lib_fflush will * return an error if it is called for a stream that is not opened for * writing. Check that first so that this function will not fail in * that case. */ if ((stream->fs_oflags & O_WROK) == 0) { /* Report that the success was successful if we attempt to flush a * read-only stream. */ return OK; } /* Flush the stream. Return success if there is no buffered write data * -- i.e., that the stream is opened for writing and that all of the * buffered write data was successfully flushed by lib_fflush(). */ return lib_fflush(stream, true); #else /* Verify that we were passed a valid (i.e., non-NULL) stream */ #ifdef CONFIG_DEBUG if (!stream) { return -EINVAL; } #endif return OK; #endif }
int fputs(FAR const char *s, FAR FILE *stream) { int nput; int ret; char ch; /* Make sure that a string was provided. */ #ifdef CONFIG_DEBUG /* Most parameter checking is disabled if DEBUG is off */ if (!s) { set_errno(EINVAL); return EOF; } #endif /* Write the string. Loop until the null terminator is encountered */ for (nput = 0, ch = up_romgetc(s); ch; nput++, s++, ch = up_romgetc(s)) { /* Write the next character to the stream buffer */ ret = lib_fwrite(&ch, 1, stream); if (ret <= 0) { return EOF; } /* Flush the buffer if a newline was written to the buffer */ #ifdef CONFIG_STDIO_LINEBUFFER if (ch == '\n') { ret = lib_fflush(stream, true); if (ret < 0) { return EOF; } } #endif } return nput; }
int puts(FAR const char *s) { FILE *stream = stdout; int nwritten; int nput = EOF; int ret; /* Write the string (the next two steps must be atomic) */ lib_take_semaphore(stream); /* Write the string without its trailing '\0' */ nwritten = fputs(s, stream); if (nwritten > 0) { /* Followed by a newline */ char newline = '\n'; ret = lib_fwrite(&newline, 1, stream); if (ret > 0) { nput = nwritten + 1; /* Flush the buffer after the newline is output if line buffering * is enabled. */ if ((stream->fs_flags & __FS_FLAG_LBF) != 0) { ret = lib_fflush(stream, true); if (ret < 0) { nput = EOF; } } } } lib_give_semaphore(stdout); return nput; }
int fflush(FAR FILE *stream) { /* Is the stream argument NULL? */ if (!stream) { /* Yes... then this is a request to flush all streams */ return lib_flushall(sched_getstreams()); } else if (lib_fflush(stream, true) != 0) { /* An error occurred during the flush AND/OR we were unable to flush all * of the buffered write data. Return EOF on failure. */ return EOF; } return OK; }
int puts(FAR const char *s) { FILE *stream = stdout; int nwritten; int nput = EOF; int ret; /* Write the string (the next two steps must be atomic) */ lib_take_semaphore(stream); /* Write the string without its trailing '\0' */ nwritten = fputs(s, stream); if (nwritten > 0) { /* Followed by a newline */ char newline = '\n'; ret = lib_fwrite(&newline, 1, stream); if (ret > 0) { nput = nwritten + 1; /* Flush the buffer after the newline is output. */ #ifdef CONFIG_STDIO_LINEBUFFER ret = lib_fflush(stream, true); if (ret < 0) { nput = EOF; } #endif } } lib_give_semaphore(stdout); return nput; }
ssize_t lib_fwrite(FAR const void *ptr, size_t count, FAR FILE *stream) #if CONFIG_STDIO_BUFFER_SIZE > 0 { FAR const unsigned char *start = ptr; FAR const unsigned char *src = ptr; ssize_t ret = ERROR; unsigned char *dest; /* Make sure that writing to this stream is allowed */ if (stream == NULL) { set_errno(EBADF); return ret; } if ((stream->fs_oflags & O_WROK) == 0) { set_errno(EBADF); goto errout; } /* Get exclusive access to the stream */ lib_take_semaphore(stream); /* If the buffer is currently being used for read access, then * discard all of the read-ahead data. We do not support concurrent * buffered read/write access. */ if (lib_rdflush(stream) < 0) { goto errout_with_semaphore; } /* Loop until all of the bytes have been buffered */ while (count > 0) { /* Determine the number of bytes left in the buffer */ size_t gulp_size = stream->fs_bufend - stream->fs_bufpos; /* Will the user data fit into the amount of buffer space * that we have left? */ if (gulp_size > count) { /* Yes, clip the gulp to the size of the user data */ gulp_size = count; } /* Adjust the number of bytes remaining to be transferred * on the next pass through the loop (might be zero). */ count -= gulp_size; /* Transfer the data into the buffer */ for (dest = stream->fs_bufpos; gulp_size > 0; gulp_size--) { *dest++ = *src++; } stream->fs_bufpos = dest; /* Is the buffer full? */ if (dest >= stream->fs_bufend) { /* Flush the buffered data to the IO stream */ int bytes_buffered = lib_fflush(stream, false); if (bytes_buffered < 0) { goto errout_with_semaphore; } } } /* Return the number of bytes written */ ret = src - start; errout_with_semaphore: lib_give_semaphore(stream); errout: if (ret < 0) { stream->fs_flags |= __FS_FLAG_ERROR; } return ret; }
int fclose(FAR FILE *stream) { int err = EINVAL; int ret = ERROR; /* Verify that a stream was provided. */ if (stream) { /* Flush the stream */ ret = lib_fflush(stream, true); err = errno; /* Close the underlying file descriptor */ if (stream->fs_filedes > 0) { /* Close the file and save the return status */ int status = close(stream->fs_filedes); /* If close() returns an error but flush() did not then make * sure that we return the close() error condition. */ if (ret == 0) { ret = status; err = errno; } } #if CONFIG_STDIO_BUFFER_SIZE > 0 /* Destroy the semaphore */ sem_destroy(&stream->fs_sem); /* Release the buffer */ if (stream->fs_bufstart) { lib_free(stream->fs_bufstart); } /* Clear the whole structure */ memset(stream, 0, sizeof(FILE)); #else #if CONFIG_NUNGET_CHARS > 0 /* Reset the number of ungetc characters */ stream->fs_nungotten = 0; #endif /* Reset the flags */ stream->fs_oflags = 0; #endif /* Setting the fs_filedescriptor to -1 makes the stream available for reuse */ stream->fs_filedes = -1; } /* On an error, reset the errno to the first error encountered and return * EOF. */ if (ret != OK) { set_errno(err); return EOF; } /* Return success */ return OK; }