libc: io: implement file io buffering and internal locking for concurrency

This commit is contained in:
2026-04-01 18:51:13 +01:00
parent f2e650d368
commit 548387c43a
23 changed files with 948 additions and 73 deletions
+6 -3
View File
@@ -15,10 +15,13 @@ int fclose(struct __opaque_file *stream)
close(stream->f_fd);
if (stream->f_buf) {
free(stream->f_buf);
if (stream->f_buf.buf_ptr) {
free(stream->f_buf.buf_ptr);
}
if (!(stream->f_flags & FILE_STATIC)) {
free(stream);
}
free(stream);
return SUCCESS;
}
@@ -1,6 +1,6 @@
#include "file.h"
int ferr(struct __opaque_file *stream)
int ferror(struct __opaque_file *stream)
{
return (stream->f_flags & FILE_ERR) != 0;
}
+12 -16
View File
@@ -3,29 +3,25 @@
#include <errno.h>
#include <stdio.h>
int fgetc(struct __opaque_file *stream)
int __fgetc(struct __opaque_file *stream)
{
if (stream->f_flags & (FILE_EOF | FILE_ERR)) {
return EOF;
}
size_t available = __libc_file_available(stream);
if (available == 0) {
int err = __libc_file_refill(stream);
if (err != SUCCESS) {
__set_errno(err);
stream->f_flags |= FILE_ERR;
return EOF;
}
available = __libc_file_available(stream);
}
if (available == 0) {
stream->f_flags |= FILE_EOF;
char c = 0;
int ret = __libc_file_read(stream, &c, 1);
if (ret < 1) {
return EOF;
}
char c = stream->f_buf[stream->f_buf_readptr++];
return c;
}
int fgetc(struct __opaque_file *stream)
{
__libc_file_lock(stream);
int ret = __fgetc(stream);
__libc_file_unlock(stream);
return ret;
}
+6 -1
View File
@@ -7,7 +7,9 @@ char *fgets(
int count,
struct __opaque_file *restrict stream)
{
__libc_file_lock(stream);
if (stream->f_flags & (FILE_EOF | FILE_ERR)) {
__libc_file_unlock(stream);
return NULL;
}
@@ -28,13 +30,16 @@ char *fgets(
}
}
if (ferr(stream)) {
if (ferror(stream)) {
__libc_file_unlock(stream);
return NULL;
}
if (feof(stream) && i == 0) {
__libc_file_unlock(stream);
return NULL;
}
__libc_file_unlock(stream);
return str;
}
+299 -46
View File
@@ -1,76 +1,329 @@
#include "file.h"
#include <errno.h>
#include <mango/futex.h>
#include <mango/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define DEFAULT_BUFFER_SIZE 4096
#define OP_READ 1
#define OP_WRITE 2
#define FILE_UNUSABLE(f) (((f)->f_flags & (FILE_EOF | FILE_ERR)) != 0)
#define FILE_UNUSABLE(f) (((f)->f_flags & (FILE_EOF | FILE_ERR)) != 0)
int __libc_file_refill(struct __opaque_file *f)
static long clear_buf(struct __opaque_file *f)
{
f->f_buf_datalen = 0;
f->f_buf_readptr = 0;
__libc_ringbuf_clear(&f->f_buf);
lseek(f->f_fd, f->f_seek, SEEK_SET);
return 0;
}
if (f->f_fd < 0) {
return EBADF;
static long refill_buf(struct __opaque_file *f)
{
kern_tracef("refill");
char *buf = NULL;
size_t available = 0;
long r = 0;
size_t nr_read = 0;
while (1) {
__libc_ringbuf_get_write_buffer(&f->f_buf, &buf, &available);
if (available == 0) {
__libc_ringbuf_put_write_buffer(
&f->f_buf,
&buf,
&available);
break;
}
kern_tracef("read(%d, %p, %zu)", f->f_fd, buf, available);
r = read(f->f_fd, buf, available);
if (r <= 0) {
break;
}
available = r;
nr_read += r;
__libc_ringbuf_put_write_buffer(&f->f_buf, &buf, &available);
}
if (f->f_flags & FILE_ERR) {
return EIO;
if (nr_read > 0) {
return nr_read;
}
if (f->f_flags & FILE_EOF) {
return SUCCESS;
if (r < 0) {
return -errno;
}
if (!f->f_buf) {
f->f_buf_max = DEFAULT_BUFFER_SIZE;
f->f_buf = malloc(f->f_buf_max);
if (!f->f_buf) {
f->f_buf_max = 0;
return ENOMEM;
return nr_read;
}
static long flush_buf(struct __opaque_file *f)
{
const char *buf = NULL;
size_t available = 0;
long r = 0;
size_t nr_written = 0;
while (1) {
__libc_ringbuf_get_read_buffer(&f->f_buf, &buf, &available);
if (available == 0) {
__libc_ringbuf_put_read_buffer(
&f->f_buf,
&buf,
&available);
break;
}
r = write(f->f_fd, buf, available);
kern_tracef(
"write(%d, %p, %zu) = %ld",
f->f_fd,
buf,
available,
r);
if (r < 0) {
break;
}
available = r;
nr_written += r;
__libc_ringbuf_put_read_buffer(&f->f_buf, &buf, &available);
}
if (nr_written > 0) {
return nr_written;
}
if (r < 0) {
return -errno;
}
return 0;
}
void __libc_file_lock(struct __opaque_file *f)
{
kern_futex_t expected = 0;
while (1) {
kern_tracef("lock=%u (%p)", f->f_lock, f);
expected = 0;
if (__atomic_compare_exchange_n(
&f->f_lock,
&expected,
1,
0,
__ATOMIC_ACQUIRE,
__ATOMIC_ACQUIRE)) {
kern_tracef("locked=%u (%p)", f->f_lock, f);
return;
}
kern_tracef("wait=%u (%p)", expected, f);
futex_wait(&f->f_lock, 1, FUTEX_PRIVATE);
}
}
void __libc_file_unlock(struct __opaque_file *f)
{
f->f_lock = 0;
futex_wake(&f->f_lock, 1, FUTEX_PRIVATE);
kern_tracef("unlocked=%u (%p)", f->f_lock, f);
}
static long read_buf(struct __opaque_file *f, void *out, size_t count)
{
kern_tracef("read_buf(%p, %zu)", out, count);
char *dest = out;
size_t nr_read = 0;
long r = 0;
while (nr_read < count) {
r = __libc_ringbuf_read(
&f->f_buf,
dest + nr_read,
count - nr_read);
if (r < 0) {
break;
}
nr_read += r;
if (r == 0) {
r = refill_buf(f);
if (r <= 0) {
break;
}
}
}
long r = read(f->f_fd, f->f_buf, f->f_buf_max);
if (r < 0) {
return -r;
return r;
}
f->f_buf_datalen = r;
return SUCCESS;
return nr_read;
}
int __libc_file_read(struct __opaque_file *f, void *out, size_t count)
static long read_nobuf(struct __opaque_file *f, void *out, size_t count)
{
if (f->f_fd < 0) {
return EBADF;
}
if (f->f_flags & FILE_ERR) {
return EIO;
}
if (f->f_flags & FILE_EOF) {
return SUCCESS;
}
size_t available = f->f_buf_datalen - f->f_buf_readptr;
if (count > available) {
count = available;
}
memcpy(out, f->f_buf + f->f_buf_readptr, count);
f->f_buf_readptr += count;
return count;
kern_tracef("read_nobuf");
return read(f->f_fd, out, count);
}
size_t __libc_file_available(struct __opaque_file *f)
long __libc_file_read(struct __opaque_file *f, void *out, size_t count)
{
return f->f_buf_datalen - f->f_buf_readptr;
long ret = 0;
if (f->f_prev != OP_READ) {
ret = flush_buf(f);
clear_buf(f);
}
if (ret != 0) {
return __set_errno(ret);
}
switch (f->f_buffer_mode) {
case _IOFBF:
case _IOLBF:
ret = read_buf(f, out, count);
break;
case _IONBF:
ret = read_nobuf(f, out, count);
break;
default:
ret = -EINVAL;
break;
}
f->f_prev = OP_READ;
if (ret < 0) {
f->f_flags |= FILE_ERR;
return __set_errno(-ret);
}
if (ret == 0) {
f->f_flags |= FILE_EOF;
}
f->f_seek += ret;
return ret;
}
static long write_fullbuf(struct __opaque_file *f, const void *p, size_t count)
{
const char *src = p;
size_t nr_written = 0;
long r = 0;
while (nr_written < count) {
r = __libc_ringbuf_write(
&f->f_buf,
src + nr_written,
count - nr_written);
if (r < 0) {
break;
}
nr_written += r;
if (r == 0) {
r = flush_buf(f);
if (r <= 0) {
break;
}
}
}
if (r < 0) {
return r;
}
return nr_written;
}
static long write_linebuf(
struct __opaque_file *f,
const void *out,
size_t count)
{
const char *s = out;
size_t nr_written = 0;
long r = 0;
while (nr_written < count) {
char c = s[nr_written];
r = __libc_ringbuf_write(&f->f_buf, &c, 1);
if (r < 0) {
break;
}
nr_written += r;
if (r == 0 || c == '\n') {
r = flush_buf(f);
if (r < 0) {
break;
}
}
}
if (r < 0) {
return r;
}
return nr_written;
}
static long write_nobuf(struct __opaque_file *f, const void *out, size_t count)
{
return write(f->f_fd, out, count);
}
long __libc_file_write(struct __opaque_file *f, const void *buf, size_t count)
{
if (f->f_lock != 1) {
kern_tracef("file is not locked!!!");
}
long ret = 0;
if (f->f_prev != OP_WRITE) {
ret = clear_buf(f);
}
if (ret != 0) {
return __set_errno(ret);
}
switch (f->f_buffer_mode) {
case _IOFBF:
ret = write_fullbuf(f, buf, count);
break;
case _IOLBF:
ret = write_linebuf(f, buf, count);
break;
case _IONBF:
ret = write_nobuf(f, buf, count);
break;
default:
ret = -EINVAL;
break;
}
f->f_prev = OP_WRITE;
if (ret < 0) {
f->f_flags |= FILE_ERR;
return __set_errno(-ret);
}
if (ret == 0) {
f->f_flags |= FILE_EOF;
}
f->f_seek += ret;
return ret;
}
+19 -6
View File
@@ -1,25 +1,38 @@
#ifndef _LIBC_IO_FILE_H_
#define _LIBC_IO_FILE_H_
#include "ringbuf.h"
#include <mango/types.h>
#include <stddef.h>
enum file_flags {
FILE_EOF = 0x01u,
FILE_ERR = 0x02u,
FILE_BIN = 0x04u,
FILE_STATIC = 0x08u,
};
struct __opaque_file {
enum file_flags f_flags;
kern_futex_t f_lock;
int f_prev;
int f_buffer_mode;
int f_fd;
char f_unget;
char *f_buf;
size_t f_buf_datalen, f_buf_max;
size_t f_buf_readptr;
/* the current seek position of the buffered data (i.e. the offset of
* the data that would be returned by reading f_buf). */
size_t f_seek;
struct ringbuf f_buf;
};
extern int __libc_file_refill(struct __opaque_file *f);
extern int __libc_file_read(struct __opaque_file *f, void *out, size_t count);
extern size_t __libc_file_available(struct __opaque_file *f);
extern void __libc_file_lock(struct __opaque_file *f);
extern void __libc_file_unlock(struct __opaque_file *f);
extern long __libc_file_read(struct __opaque_file *f, void *p, size_t count);
extern long __libc_file_write(
struct __opaque_file *f,
const void *p,
size_t count);
#endif
+6
View File
@@ -143,6 +143,12 @@ struct __opaque_file *fopen(const char *path, const char *mode)
return NULL;
}
if (fflags & FILE_BIN) {
out->f_buffer_mode = _IOFBF;
} else {
out->f_buffer_mode = _IOLBF;
}
out->f_fd = fd;
out->f_flags = fflags;
__set_errno(SUCCESS);
+6
View File
@@ -0,0 +1,6 @@
#include "file.h"
int fprintf(struct __opaque_file *stream, const char *format, ...)
{
return 0;
}
+27
View File
@@ -0,0 +1,27 @@
#include "file.h"
#include <errno.h>
#include <stdio.h>
int __fputc(int c, struct __opaque_file *stream)
{
if (stream->f_flags & (FILE_EOF | FILE_ERR)) {
return EOF;
}
char cv = c;
int ret = __libc_file_write(stream, &cv, 1);
if (ret < 1) {
return EOF;
}
return c;
}
int fputc(int c, struct __opaque_file *stream)
{
__libc_file_lock(stream);
int ret = __fputc(c, stream);
__libc_file_unlock(stream);
return ret;
}
+31
View File
@@ -0,0 +1,31 @@
#include "file.h"
#include <stdio.h>
extern int __fputc(int c, struct __opaque_file *stream);
int fputs(const char *restrict str, struct __opaque_file *restrict stream)
{
__libc_file_lock(stream);
if (stream->f_flags & (FILE_EOF | FILE_ERR)) {
__libc_file_unlock(stream);
return EOF;
}
size_t i = 0;
int err = 0;
for (i = 0; str[i]; i++) {
err = __fputc(str[i], stream);
if (err < 0) {
break;
}
}
__libc_file_unlock(stream);
if (i > 0) {
return i;
}
return err;
}
+26
View File
@@ -0,0 +1,26 @@
#include "file.h"
#include <unistd.h>
size_t fread(void *buf, size_t size, size_t count, struct __opaque_file *stream)
{
__libc_file_lock(stream);
size_t total = size * count;
if (total == 0) {
__libc_file_unlock(stream);
return 0;
}
long ret = __libc_file_read(stream, buf, total);
if (ret == 0) {
stream->f_flags |= FILE_EOF;
}
if (ret < 0) {
stream->f_flags |= FILE_ERR;
ret = 0;
}
__libc_file_unlock(stream);
return ret;
}
+8
View File
@@ -0,0 +1,8 @@
#include "file.h"
#include <unistd.h>
int fseek(struct __opaque_file *stream, long offset, int origin)
{
return lseek(stream->f_fd, offset, origin);
}
+8
View File
@@ -0,0 +1,8 @@
#include "file.h"
#include <unistd.h>
long ftell(struct __opaque_file *stream)
{
return lseek(stream->f_fd, 0, SEEK_CUR);
}
+29
View File
@@ -0,0 +1,29 @@
#include "file.h"
#include <unistd.h>
size_t fwrite(
const void *buf,
size_t size,
size_t count,
struct __opaque_file *stream)
{
__libc_file_lock(stream);
size_t total = size * count;
if (total == 0) {
return 0;
}
long ret = __libc_file_write(stream, buf, total);
if (ret == 0) {
stream->f_flags |= FILE_EOF;
}
if (ret < 0) {
stream->f_flags |= FILE_ERR;
ret = 0;
}
__libc_file_unlock(stream);
return ret;
}
+12
View File
@@ -0,0 +1,12 @@
#include <stddef.h>
#include <stdio.h>
int printf(const char *format, ...)
{
va_list arg;
va_start(arg, format);
int ret = vprintf(format, arg);
va_end(arg);
return ret;
}
+270
View File
@@ -0,0 +1,270 @@
#include "file.h"
#include <errno.h>
#include <mango/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define DEFAULT_BUFFER_SIZE 4096
static int ringbuf_init(struct ringbuf *buf)
{
if (buf->buf_ptr) {
return SUCCESS;
}
if (!buf->buf_max) {
buf->buf_max = DEFAULT_BUFFER_SIZE;
}
buf->buf_ptr = malloc(buf->buf_max);
if (!buf->buf_ptr) {
return ENOMEM;
}
return SUCCESS;
}
int __libc_ringbuf_get_read_buffer(
struct ringbuf *buf,
const char **out_bufp,
size_t *out_len)
{
int r = ringbuf_init(buf);
if (r != SUCCESS) {
return r;
}
size_t contiguous_capacity = 0;
if (buf->buf_readp > buf->buf_writep) {
contiguous_capacity = buf->buf_max - buf->buf_readp;
} else {
contiguous_capacity = buf->buf_writep - buf->buf_readp;
}
kern_tracef(
"OPEN READ: readp=%zu, writep=%zu, max=%zu -> %p cap=%zu",
buf->buf_readp,
buf->buf_writep,
buf->buf_max,
buf->buf_ptr + buf->buf_readp,
contiguous_capacity);
*out_len = contiguous_capacity;
if (contiguous_capacity == 0) {
*out_bufp = NULL;
} else {
*out_bufp = buf->buf_ptr + buf->buf_readp;
}
return SUCCESS;
}
void __libc_ringbuf_put_read_buffer(
struct ringbuf *buf,
const char **bufp,
size_t *len)
{
buf->buf_readp += *len;
if (buf->buf_readp == buf->buf_writep) {
buf->buf_readp = buf->buf_writep = 0;
}
kern_tracef("CLOSE READ: %p r=%zu", *bufp, *len);
*bufp = NULL;
*len = 0;
}
int __libc_ringbuf_get_write_buffer(
struct ringbuf *buf,
char **out_bufp,
size_t *out_len)
{
int r = ringbuf_init(buf);
if (r != SUCCESS) {
return r;
}
size_t contiguous_capacity = 0;
if (buf->buf_writep >= buf->buf_readp) {
contiguous_capacity = buf->buf_max - buf->buf_writep - 1;
if (buf->buf_readp > 0) {
contiguous_capacity++;
}
} else {
contiguous_capacity = buf->buf_readp - buf->buf_writep - 1;
}
kern_tracef(
"OPEN WRITE: readp=%zu, writep=%zu, max=%zu -> %p cap=%zu",
buf->buf_readp,
buf->buf_writep,
buf->buf_max,
buf->buf_ptr + buf->buf_readp,
contiguous_capacity);
*out_len = contiguous_capacity;
if (contiguous_capacity == 0) {
*out_bufp = NULL;
} else {
*out_bufp = buf->buf_ptr + buf->buf_writep;
}
return SUCCESS;
}
void __libc_ringbuf_put_write_buffer(
struct ringbuf *buf,
char **bufp,
size_t *len)
{
buf->buf_writep += *len;
if (buf->buf_readp == buf->buf_writep) {
buf->buf_readp = buf->buf_writep = 0;
}
kern_tracef(
"CLOSE WRITE: %p r=%zu (%c)",
*bufp,
*len,
*(char *)(*bufp));
*bufp = NULL;
*len = 0;
}
long __libc_ringbuf_read(struct ringbuf *buf, void *p, size_t count)
{
size_t nr_read = 0;
long r = 0;
while (nr_read < count) {
const char *src = NULL;
size_t available = 0;
r = __libc_ringbuf_get_read_buffer(buf, &src, &available);
if (r < 0) {
break;
}
char *dest = p + nr_read;
size_t to_copy = count - nr_read;
if (available == 0) {
__libc_ringbuf_put_read_buffer(buf, &src, &available);
break;
}
if (to_copy > available) {
to_copy = available;
}
memcpy(dest, src, to_copy);
nr_read += available;
__libc_ringbuf_put_read_buffer(buf, &src, &to_copy);
}
if (r < 0) {
return r;
}
return nr_read;
}
long __libc_ringbuf_write(struct ringbuf *buf, const void *p, size_t count)
{
size_t nr_written = 0;
long r = 0;
while (nr_written < count) {
char *dest = NULL;
size_t available = 0;
r = __libc_ringbuf_get_write_buffer(buf, &dest, &available);
if (r < 0) {
break;
}
const char *src = p + nr_written;
size_t to_copy = count - nr_written;
if (available == 0) {
__libc_ringbuf_put_write_buffer(buf, &dest, &available);
break;
}
if (to_copy > available) {
to_copy = available;
}
memcpy(dest, src, to_copy);
nr_written += available;
__libc_ringbuf_put_write_buffer(buf, &dest, &to_copy);
}
if (r < 0) {
return r;
}
return nr_written;
}
int __libc_ringbuf_clear(struct ringbuf *buf)
{
buf->buf_readp = buf->buf_writep = 0;
return 0;
}
int __libc_ringbuf_resize(struct ringbuf *buf, size_t max)
{
if (!(buf->buf_flags & RINGBUF_STATIC)) {
free(buf->buf_ptr);
buf->buf_ptr = NULL;
}
buf->buf_readp = buf->buf_writep = 0;
buf->buf_flags &= ~RINGBUF_STATIC;
buf->buf_max = max;
return 0;
}
int __libc_ringbuf_resize_static(struct ringbuf *buf, void *p, size_t max)
{
if (!(buf->buf_flags & RINGBUF_STATIC)) {
free(buf->buf_ptr);
buf->buf_ptr = NULL;
}
buf->buf_readp = buf->buf_writep = 0;
buf->buf_flags |= RINGBUF_STATIC;
buf->buf_ptr = p;
buf->buf_max = max;
return 0;
}
size_t __libc_ringbuf_available(const struct ringbuf *buf)
{
if (buf->buf_readp < buf->buf_writep) {
return buf->buf_writep - buf->buf_readp;
} else if (buf->buf_readp > buf->buf_writep) {
return buf->buf_max - buf->buf_readp + buf->buf_writep;
} else {
return 0;
}
}
size_t __libc_ringbuf_capacity(const struct ringbuf *buf)
{
if (buf->buf_readp > buf->buf_writep) {
return buf->buf_readp - buf->buf_writep - 1;
} else {
return buf->buf_max - buf->buf_writep + buf->buf_readp - 1;
}
}
+53
View File
@@ -0,0 +1,53 @@
#ifndef _LIBC_IO_RINGBUF_H_
#define _LIBC_IO_RINGBUF_H_
#include <stddef.h>
enum ringbuf_flags {
RINGBUF_NONE = 0,
RINGBUF_STATIC,
};
struct ringbuf {
enum ringbuf_flags buf_flags;
char *buf_ptr;
size_t buf_max;
size_t buf_readp, buf_writep;
};
extern int __libc_ringbuf_get_read_buffer(
struct ringbuf *buf,
const char **out_bufp,
size_t *out_len);
extern void __libc_ringbuf_put_read_buffer(
struct ringbuf *buf,
const char **bufp,
size_t *len);
extern int __libc_ringbuf_get_write_buffer(
struct ringbuf *buf,
char **out_bufp,
size_t *out_len);
extern void __libc_ringbuf_put_write_buffer(
struct ringbuf *buf,
char **bufp,
size_t *len);
extern long __libc_ringbuf_read(struct ringbuf *buf, void *p, size_t count);
extern long __libc_ringbuf_write(
struct ringbuf *buf,
const void *p,
size_t count);
extern int __libc_ringbuf_clear(struct ringbuf *buf);
extern int __libc_ringbuf_resize(struct ringbuf *buf, size_t max);
extern int __libc_ringbuf_resize_static(
struct ringbuf *buf,
void *p,
size_t max);
extern size_t __libc_ringbuf_available(const struct ringbuf *buf);
extern size_t __libc_ringbuf_capacity(const struct ringbuf *buf);
#endif
+39
View File
@@ -0,0 +1,39 @@
#include "file.h"
#include <errno.h>
#include <stdio.h>
extern int setvbuf(
struct __opaque_file *restrict stream,
char *restrict buf,
int mode,
size_t size)
{
switch (mode) {
case _IOFBF:
case _IOLBF:
case _IONBF:
break;
default:
return __set_errno(EINVAL);
}
if (stream->f_prev != 0) {
return __set_errno(EINVAL);
}
int err = SUCCESS;
if (buf) {
err = __libc_ringbuf_resize_static(&stream->f_buf, buf, size);
} else {
err = __libc_ringbuf_resize(&stream->f_buf, size);
}
if (err != SUCCESS) {
return __set_errno(err);
}
stream->f_buffer_mode = mode;
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
#include "file.h"
#include <stdio.h>
static struct __opaque_file __stderr = {
.f_fd = 2,
.f_flags = FILE_STATIC,
.f_buffer_mode = _IONBF,
};
extern struct __opaque_file *__libc_file_stderr(void)
{
return &__stderr;
}
+14
View File
@@ -0,0 +1,14 @@
#include "file.h"
#include <stdio.h>
static struct __opaque_file __stdin = {
.f_fd = 0,
.f_flags = FILE_STATIC,
.f_buffer_mode = _IOLBF,
};
extern struct __opaque_file *__libc_file_stdin(void)
{
return &__stdin;
}
+14
View File
@@ -0,0 +1,14 @@
#include "file.h"
#include <stdio.h>
static struct __opaque_file __stdout = {
.f_fd = 1,
.f_flags = FILE_STATIC,
.f_buffer_mode = _IOLBF,
};
extern struct __opaque_file *__libc_file_stdout(void)
{
return &__stdout;
}
+27
View File
@@ -0,0 +1,27 @@
#include "file.h"
#include <stddef.h>
#include <stdio.h>
extern int __libc_fctprintf(
void (*out)(char character, void *arg),
void *arg,
const char *format,
va_list va);
extern int __fputc(int c, struct __opaque_file *stream);
static inline void _out_file(char character, void *arg)
{
struct __opaque_file *fp = arg;
__fputc(character, fp);
}
int vprintf(const char *format, va_list arg)
{
__libc_file_lock(stdout);
int ret = __libc_fctprintf(_out_file, stdout, format, arg);
__libc_file_unlock(stdout);
return ret;
}
+21
View File
@@ -0,0 +1,21 @@
#include <errno.h>
#include <mango/handle.h>
#include <mango/msg.h>
#include <rosetta/fs.h>
#include <sys/remote.h>
int write(int fd, const void *buf, size_t count)
{
int err;
size_t nr_written;
kern_status_t status = fs_write(fd, buf, count, &err, &nr_written);
if (status != KERN_OK) {
return __set_errno(__errno_from_kern_status(status));
}
if (err != SUCCESS) {
return __set_errno(err);
}
return nr_written;
}