Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4540 → Rev 4541

/trunk/uspace/lib/libc/generic/io/io.c
35,6 → 35,7
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <bool.h>
44,12 → 45,18
#include <ipc/devmap.h>
#include <adt/list.h>
 
static void _fflushbuf(FILE *stream);
 
static FILE stdin_null = {
.fd = -1,
.error = true,
.eof = true,
.klog = false,
.phone = -1
.phone = -1,
.btype = _IONBF,
.buf = NULL,
.buf_size = 0,
.buf_head = NULL
};
 
static FILE stdout_klog = {
57,7 → 64,11
.error = false,
.eof = false,
.klog = true,
.phone = -1
.phone = -1,
.btype = _IOLBF,
.buf = NULL,
.buf_size = BUFSIZ,
.buf_head = NULL
};
 
static FILE stderr_klog = {
65,7 → 76,11
.error = false,
.eof = false,
.klog = true,
.phone = -1
.phone = -1,
.btype = _IONBF,
.buf = NULL,
.buf_size = 0,
.buf_head = NULL
};
 
FILE *stdin = NULL;
156,6 → 171,30
return true;
}
 
/** Set stream buffer. */
void setvbuf(FILE *stream, void *buf, int mode, size_t size)
{
stream->btype = mode;
stream->buf = buf;
stream->buf_size = size;
stream->buf_head = stream->buf;
}
 
/** Allocate stream buffer. */
static int _fallocbuf(FILE *stream)
{
assert(stream->buf == NULL);
 
stream->buf = malloc(stream->buf_size);
if (stream->buf == NULL) {
errno = ENOMEM;
return -1;
}
 
stream->buf_head = stream->buf;
return 0;
}
 
/** Open a stream.
*
* @param path Path of the file to open.
186,6 → 225,9
stream->eof = false;
stream->klog = false;
stream->phone = -1;
 
/* FIXME: Should select buffering type based on what was opened. */
setvbuf(stream, NULL, _IOFBF, BUFSIZ);
list_append(&stream->link, &files);
206,6 → 248,9
stream->eof = false;
stream->klog = false;
stream->phone = -1;
 
/* FIXME: Should select buffering type based on what was opened. */
setvbuf(stream, NULL, _IOLBF, BUFSIZ);
list_append(&stream->link, &files);
236,6 → 281,9
stream->eof = false;
stream->klog = false;
stream->phone = -1;
 
/* FIXME: Should select buffering type based on what was opened. */
setvbuf(stream, NULL, _IOLBF, BUFSIZ);
list_append(&stream->link, &files);
283,7 → 331,10
{
size_t left = size * nmemb;
size_t done = 0;
 
/* Make sure no data is pending write. */
_fflushbuf(stream);
 
while ((left > 0) && (!stream->error) && (!stream->eof)) {
ssize_t rd = read(stream->fd, buf + done, left);
300,15 → 351,7
return (done / size);
}
 
/** Write to a stream.
*
* @param buf Source buffer.
* @param size Size of each record.
* @param nmemb Number of records to write.
* @param stream Pointer to the stream.
*
*/
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
{
size_t left = size * nmemb;
size_t done = 0;
332,6 → 375,91
return (done / size);
}
 
/** Drain stream buffer, do not sync stream. */
static void _fflushbuf(FILE *stream)
{
size_t bytes_used;
 
if (!stream->buf || stream->btype == _IONBF || stream->error)
return;
 
bytes_used = stream->buf_head - stream->buf;
if (bytes_used == 0)
return;
 
(void) _fwrite(stream->buf, 1, bytes_used, stream);
stream->buf_head = stream->buf;
}
 
/** Write to a stream.
*
* @param buf Source buffer.
* @param size Size of each record.
* @param nmemb Number of records to write.
* @param stream Pointer to the stream.
*
*/
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
{
uint8_t *data;
size_t bytes_left;
size_t now;
size_t buf_free;
size_t total_written;
size_t i;
uint8_t b;
bool need_flush;
 
/* If not buffered stream, write out directly. */
if (stream->btype == _IONBF)
return _fwrite(buf, size, nmemb, stream);
 
/* Perform lazy allocation of stream buffer. */
if (stream->buf == NULL) {
if (_fallocbuf(stream) != 0)
return 0; /* Errno set by _fallocbuf(). */
}
 
data = (uint8_t *) buf;
bytes_left = size * nmemb;
total_written = 0;
need_flush = false;
 
while (!stream->error && bytes_left > 0) {
 
buf_free = stream->buf_size - (stream->buf_head - stream->buf);
if (bytes_left > buf_free)
now = buf_free;
else
now = bytes_left;
 
for (i = 0; i < now; i++) {
b = data[i];
stream->buf_head[i] = b;
 
if (b == '\n' && stream->btype == _IOLBF)
need_flush = true;
}
 
buf += now;
stream->buf_head += now;
buf_free -= now;
bytes_left -= now;
total_written += now;
 
if (buf_free == 0) {
/* Only need to drain buffer. */
_fflushbuf(stream);
need_flush = false;
}
}
 
if (need_flush)
fflush(stream);
 
return (total_written / size);
}
 
int fputc(wchar_t c, FILE *stream)
{
char buf[STR_BOUNDS(1)];
405,6 → 533,8
 
int fflush(FILE *stream)
{
_fflushbuf(stream);
 
if (stream->klog) {
klog_update();
return EOK;