aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/include/stdio.h3
-rw-r--r--src/lib/libc/stdio.c106
2 files changed, 84 insertions, 25 deletions
diff --git a/src/lib/include/stdio.h b/src/lib/include/stdio.h
index 9048ecb..1555296 100644
--- a/src/lib/include/stdio.h
+++ b/src/lib/include/stdio.h
@@ -12,6 +12,8 @@ void setup_libc_stdio();
#define BUFSIZ 256
+#define STDIO_FL_EOF 1
+#define STDIO_FL_ERR 2
struct file_t {
fd_t fd;
@@ -19,6 +21,7 @@ struct file_t {
int file_mode;
size_t pos;
+ int flags;
int buf_mode;
char *out_buf;
diff --git a/src/lib/libc/stdio.c b/src/lib/libc/stdio.c
index 2872f62..fe3bd2c 100644
--- a/src/lib/libc/stdio.c
+++ b/src/lib/libc/stdio.c
@@ -15,13 +15,13 @@ FILE libc_tty_stdio, libc_stdin, libc_stdout, libc_stderr;
void initialize_out_buffer(FILE* f, int buf_mode) {
f->buf_mode = 0;
- f->out_buf = 0;
+ f->out_buf = NULL;
f->out_buf_size = f->out_buf_used = 0;
f->out_buf_owned = false;
if (buf_mode != 0) {
f->out_buf = malloc(BUFSIZ);
- if (f->out_buf == 0) {
+ if (f->out_buf == NULL) {
f->file_mode &= ~FM_WRITE;
return;
}
@@ -33,13 +33,13 @@ void initialize_out_buffer(FILE* f, int buf_mode) {
}
void initialize_in_buffer(FILE* f) {
- f->in_buf = 0;
+ f->in_buf = NULL;
f->in_buf_size = 0;
f->in_buf_begin = f->in_buf_end = 0;
if (f->file_mode & FM_READ) {
f->in_buf = malloc(BUFSIZ);
- if (f->in_buf == 0) {
+ if (f->in_buf == NULL) {
f->file_mode &= ~FM_READ;
return;
}
@@ -52,6 +52,7 @@ void setup_libc_stdio() {
libc_tty_stdio.fd = STD_FD_TTY_STDIO;
libc_tty_stdio.file_mode = (libc_tty_stdio.st.access & (FM_READ | FM_WRITE));
libc_tty_stdio.pos = 0;
+ libc_tty_stdio.flags = 0;
initialize_out_buffer(&libc_tty_stdio, _IOLBF);
initialize_in_buffer(&libc_tty_stdio);
@@ -69,6 +70,7 @@ void setup_libc_stdio() {
ASSERT(libc_stdin.st.access & FM_READ);
libc_stdin.file_mode = FM_READ;
libc_stdin.pos = 0;
+ libc_stdin.flags = 0;
initialize_out_buffer(&libc_stdin, 0);
initialize_in_buffer(&libc_stdin);
@@ -83,6 +85,7 @@ void setup_libc_stdio() {
ASSERT(libc_stdout.st.access & FM_WRITE);
libc_stdout.file_mode = FM_WRITE;
libc_stdout.pos = 0;
+ libc_stdout.flags = 0;
initialize_out_buffer(&libc_stdout, _IOLBF);
initialize_in_buffer(&libc_stdout);
@@ -94,6 +97,7 @@ void setup_libc_stdio() {
ASSERT(libc_stderr.st.access & FM_WRITE);
libc_stderr.file_mode = FM_WRITE;
libc_stderr.pos = 0;
+ libc_stderr.flags = 0;
initialize_out_buffer(&libc_stderr, _IONBF);
initialize_in_buffer(&libc_stderr);
@@ -131,12 +135,49 @@ int printf(const char* fmt, ...) {
FILE *fopen(const char *path, const char *mode) {
- // TODO
- return 0;
+ if (path == NULL) return NULL;
+ if (mode == NULL || strlen(mode) == 0) {
+ mode = "r";
+ }
+
+ int flags = 0;
+ if (mode[0] == 'r') flags |= FM_READ;
+ if (mode[0] == 'w') flags |= FM_WRITE | FM_CREATE | FM_TRUNC;
+ if (mode[0] == 'a') flags |= FM_WRITE | FM_CREATE | FM_APPEND;
+ if (mode[1] == '+' || (mode[1] == 'b' && mode[2] == '+'))
+ flags |= FM_READ | FM_WRITE;
+
+ FILE* f = (FILE*)malloc(sizeof(FILE));
+ if (f == NULL) return NULL;
+
+ f->fd = sc_open(path, flags);
+ dbg_printf("FOPEN %s %s: fd=%d\n", path, mode, f->fd);
+ if (f->fd == 0) goto error;
+
+ if (!sc_stat_open(f->fd, &f->st)) goto error;
+ dbg_printf("FOPEN %s %s: stat ok\n");
+ f->file_mode = flags;
+
+ f->flags = 0;
+ if ((flags & FM_APPEND) && f->st.type == FT_REGULAR) {
+ f->pos = f->st.size;
+ } else {
+ f->pos = 0;
+ }
+
+ initialize_out_buffer(f, (flags & FM_WRITE ? _IOLBF : 0));
+ initialize_in_buffer(f);
+
+ return f;
+
+error:
+ if (f->fd != 0) sc_close(f->fd);
+ free(f);
+ return NULL;
}
FILE *freopen(const char *path, const char *mode, FILE *stream) {
// TODO
- return 0;
+ return NULL;
}
int fclose(FILE* f) {
if (fflush(f) != 0) return EOF;
@@ -159,6 +200,8 @@ int fclose(FILE* f) {
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
ASSERT(size == 1); //TODO all cases
+ if (fflush(stream) == EOF) return 0;
+
if (stream == NULL || stream->fd == 0) return 0;
// TODO buffering
@@ -203,8 +246,7 @@ char *fgets(char *s, int size, FILE *stream) {
return s;
}
int getc(FILE *stream) {
- // TODO
- return 0;
+ return fgetc(stream);
}
int ungetc(int c, FILE *stream) {
// TODO
@@ -362,20 +404,18 @@ int vfprintf(FILE *stream, const char *format, va_list ap) {
}
-// ---------------------
-// COMPLICATED FUNCTIONS
-// ---------------------
+// ----------------------
+// FLAG-RELATED FUNCTIONS
+// ----------------------
void clearerr(FILE *stream) {
- // TODO
+ stream->flags = 0;
}
int feof(FILE *stream) {
- // TODO
- return 0;
+ return (stream->flags & STDIO_FL_EOF);
}
int ferror(FILE *stream) {
- // TODO
- return 0;
+ return (stream->flags & STDIO_FL_ERR);
}
int fileno(FILE *stream) {
return stream->fd;
@@ -388,23 +428,39 @@ int fileno(FILE *stream) {
int fseek(FILE *stream, long offset, int whence) {
- // TODO
- return 0;
+ fpos_t pos;
+ if (whence == SEEK_SET) {
+ pos = offset;
+ } else if (whence == SEEK_CUR) {
+ pos = stream->pos + offset;
+ } else if (whence == SEEK_END) {
+ pos = stream->st.size + offset;
+ } else {
+ stream->flags |= STDIO_FL_ERR;
+ return -1;
+ }
+ return fsetpos(stream, &pos);
}
long ftell(FILE *stream) {
- // TODO
- return 0;
+ return stream->pos;
}
void rewind(FILE *stream) {
- // TODO
+ fflush(stream);
+ stream->pos = 0;
}
int fgetpos(FILE *stream, fpos_t *pos) {
- // TODO
+ *pos = ftell(stream);
return 0;
}
int fsetpos(FILE *stream, const fpos_t *pos) {
- // TODO
- return 0;
+ fflush(stream);
+ if (*pos <= stream->st.size) {
+ stream->pos = *pos;
+ return 0;
+ } else {
+ stream->flags |= STDIO_FL_EOF;
+ return -1;
+ }
}
// ---------------------