diff options
Diffstat (limited to 'libc/bios/fileops.c')
-rw-r--r-- | libc/bios/fileops.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/libc/bios/fileops.c b/libc/bios/fileops.c new file mode 100644 index 0000000..5c71a37 --- /dev/null +++ b/libc/bios/fileops.c @@ -0,0 +1,168 @@ + +#include <bios.h> +#include <fcntl.h> +#include <errno.h> + +#include "io.h" +#include "rawio.h" + +static int op_open(); +static int op_close(); +static int op_read(); +static int op_write(); +static long op_lseek(); + +int +__fileops(cmd, fd, buf, len) +int cmd, fd, len; +char * buf; +{ + switch(cmd) + { + case CMD_OPEN: return op_open(buf, fd, len); + case CMD_READ: return op_read(fd, buf, len); +/* + case CMD_WRITE: return op_write(fd, buf, len); + case CMD_LSEEK: rv = op_lseek(fd, *(long*)buf, len); + (*(long*)buf) = rv; + if( rv == -1 ) return -1; + else return 0; + */ + case CMD_CLOSE: return op_close(fd); + } + + errno=EINVAL; + return -1; +} + +#define MAX_OPEN_FILES 5 +ioblock _iob[MAX_OPEN_FILES]; + +static int +op_read(fd,buf,len) +int fd,len; +char * buf; +{ + ioblock* cur = &_iob[fd]; + int amount_read = 0; + int amount_left_in_buffer; + int amount_to_copy; + + if (fd >= MAX_OPEN_FILES || _iob[fd].block_read == 0) + { + errno = EBADF; + return -1; + } + + while (len > 0) + { + /* pull in next block as required */ + if (cur->amount_left <= 0) + { + int read_len = cur->block_read(cur, + cur->buffer, + (long) cur->offset / sizeof(cur->buffer) + ); +#ifdef DEBUG + fprintf(stderr, "br: returned %d\n", read_len); +#endif + if (read_len <= 0) + break; + cur->amount_left = read_len; + } + if (cur->amount_left > len) + amount_to_copy = len; + else + amount_to_copy = cur->amount_left; + +#ifdef DEBUG + fprintf(stderr, "r: len=%d, amount_left=%ld, offset=%ld, buf=%x\n", + len, cur->amount_left, cur->offset, + (int) cur->buffer[cur->offset % sizeof(cur->buffer)]); +#endif + memcpy(buf, + &cur->buffer[cur->offset % sizeof(cur->buffer)], + amount_to_copy); + amount_read += amount_to_copy; + len -= amount_to_copy; + cur->offset += amount_to_copy; + buf += amount_to_copy; + cur->amount_left -= amount_to_copy; + } + return amount_read; +} + +/****************************************************************************/ + +static int +op_open(name, flags, mode) +char * name; +int flags, mode; +{ + int fd; + ioblock* cur; + + /* + * discover whether the iob has been initialised or not + */ + if (_iob[0].flags == 0) + { + _iob[0].flags = O_RDONLY; + _iob[1].flags = O_WRONLY; + _iob[2].flags = O_WRONLY; + } + /* + * discover next free iob + */ + for (fd = 3; fd < MAX_OPEN_FILES; ++fd) + { + if (_iob[fd].block_read == NULL && _iob[fd].block_write == NULL) + break; + } + if (fd >= MAX_OPEN_FILES) + { + errno = EMFILE; /* too many open files */ + return -1; + } + + /* + * try and find the file + */ + cur = &_iob[fd]; + if (fsdos_open_file(cur, name, flags, mode) >= 0) + { + cur->amount_left = 0; + cur->offset = 0; + return fd; + } + cur->block_read = NULL; /* ensure that the file is closed */ + cur->block_write = NULL; + errno = ENOENT; + return -1; +} + +/****************************************************************************/ + +static int +op_close(fd) +int fd; +{ + if (fd >= MAX_OPEN_FILES || _iob[0].flags == 0) + { + errno = EBADF; + return -1; + } + else + { + ioblock* cur = &_iob[fd]; + cur->close(cur); + cur->block_read = NULL; + cur->block_write = NULL; + cur->close = NULL; + cur->flags = 0; + return 0; + } +} + +/****************************************************************************/ + |