X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=bootcensus;a=blobdiff_plain;f=src%2Flibc%2Ffile.c;fp=src%2Flibc%2Ffile.c;h=cc73f71e375a415cc61e45c4b5b68c04c8e41c37;hp=0000000000000000000000000000000000000000;hb=78e3e75fc7b5838d0261c876d00e1b8c3e0bcfe0;hpb=7b6f6de2124e28ae7da5599a7cdaf2c171c4f15e diff --git a/src/libc/file.c b/src/libc/file.c new file mode 100644 index 0000000..cc73f71 --- /dev/null +++ b/src/libc/file.c @@ -0,0 +1,216 @@ +#ifndef FILE_H_ +#define FILE_H_ + +#include +#include +#include "fs.h" +#include "panic.h" + +enum { + MODE_READ = 1, + MODE_WRITE = 2, + MODE_APPEND = 4, + MODE_CREATE = 8, + MODE_TRUNCATE = 16 +}; + +enum { + STATUS_EOF = 1, + STATUS_ERR = 2 +}; + +struct FILE { + unsigned int mode; + unsigned int status; + struct fs_node *fsn; +}; + +FILE *fopen(const char *path, const char *mode) +{ + FILE *fp; + struct fs_node *node; + unsigned int mflags = 0; + + while(*mode) { + int c = *mode++; + switch(c) { + case 'r': + mflags |= MODE_READ; + if(*mode == '+') { + mflags |= MODE_WRITE; + mode++; + } + break; + case 'w': + mflags |= MODE_WRITE | MODE_TRUNCATE; + if(*mode == '+') { + mflags |= MODE_READ | MODE_CREATE; + mode++; + } + break; + case 'a': + mflags |= MODE_WRITE | MODE_APPEND; + if(*mode == '+') { + mflags |= MODE_READ | MODE_CREATE; + mode++; + } + break; + case 'b': + break; + default: + errno = EINVAL; + return 0; + } + } + + if(!(node = fs_open(path, 0))) { + /* TODO: create */ + errno = ENOENT; /* TODO */ + return 0; + } + if(node->type != FSNODE_FILE) { + errno = EISDIR; + return 0; + } + + if(!(fp = malloc(sizeof *fp))) { + errno = ENOMEM; + return 0; + } + fp->fsn = node; + fp->mode = mflags; + fp->status = 0; + + return fp; +} + +int fclose(FILE *fp) +{ + if(!fp) { + errno = EINVAL; + return -1; + } + + fs_close(fp->fsn); + free(fp); + return 0; +} + +long filesize(FILE *fp) +{ + return fs_filesize(fp->fsn); +} + +int fseek(FILE *fp, long offset, int from) +{ + if(!fp) { + errno = EINVAL; + return -1; + } + if(from < 0 || from > 2) { + errno = EINVAL; + return -1; + } + + fs_seek(fp->fsn, offset, from); + fp->status &= ~STATUS_EOF; + return 0; +} + +void rewind(FILE *fp) +{ + fseek(fp, 0, SEEK_SET); +} + +long ftell(FILE *fp) +{ + if(!fp) { + errno = EINVAL; + return -1; + } + return fs_tell(fp->fsn); +} + +size_t fread(void *buf, size_t size, size_t count, FILE *fp) +{ + int res; + if(!fp) return 0; + if((res = fs_read(fp->fsn, buf, size * count)) == -1) { + fp->status |= STATUS_EOF; + return 0; + } + return res / size; +} + +size_t fwrite(const void *buf, size_t size, size_t count, FILE *fp) +{ + int res; + if(!fp) return 0; + if(!(fp->mode & MODE_WRITE)) { + fp->status |= STATUS_ERR; + return 0; + } + if((res = fs_write(fp->fsn, (void*)buf, size * count)) == -1) { + return 0; + } + return res / size; +} + +int fgetc(FILE *fp) +{ + unsigned char c; + if(fread(&c, 1, 1, fp) < 1) { + return -1; + } + return c; +} + +char *fgets(char *buf, int size, FILE *fp) +{ + int c; + char *s = buf; + + while(--size > 0 && (c = fgetc(fp)) >= 0) { + *s++ = c; + if(c == '\n') break; + } + *s = 0; + return s > buf ? buf : 0; +} + +int fputc(int c, FILE *fp) +{ + if(fp == stdout || fp == stderr) { + return putchar(c); + } + + panic("fputc on anything other than stdout/stderr not implemented yet\n"); + return -1; +} + +int fflush(FILE *fp) +{ + if(fp == stdout || fp == stderr) { + return 0; /* do nothing */ + } + + panic("fflush on anything other than stdout/stderr not implemented yet\n"); + return -1; +} + +int feof(FILE *fp) +{ + return (fp->status & STATUS_EOF) != 0; +} + +int ferror(FILE *fp) +{ + return (fp->status & STATUS_ERR) != 0; +} + +void clearerr(FILE *fp) +{ + fp->status = 0; +} + +#endif /* FILE_H_ */