Mercurial > hg > CbC > CbC_xv6
diff src/file.c @ 0:83c23a36980d
Init
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 26 May 2017 23:11:05 +0900 |
parents | |
children | 36bd61f5c847 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/file.c Fri May 26 23:11:05 2017 +0900 @@ -0,0 +1,189 @@ +// +// File descriptors +// + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "fs.h" +#include "file.h" +#include "spinlock.h" + +struct devsw devsw[NDEV]; +struct { + struct spinlock lock; + struct file file[NFILE]; +} ftable; + +void fileinit (void) +{ + initlock(&ftable.lock, "ftable"); +} + +// Allocate a file structure. +struct file* filealloc (void) +{ + struct file *f; + + acquire(&ftable.lock); + + for (f = ftable.file; f < ftable.file + NFILE; f++) { + if (f->ref == 0) { + f->ref = 1; + release(&ftable.lock); + return f; + } + } + + release(&ftable.lock); + return 0; +} + +// Increment ref count for file f. +struct file* filedup (struct file *f) +{ + acquire(&ftable.lock); + + if (f->ref < 1) { + panic("filedup"); + } + + f->ref++; + release(&ftable.lock); + return f; +} + +// Close file f. (Decrement ref count, close when reaches 0.) +void fileclose (struct file *f) +{ + struct file ff; + + acquire(&ftable.lock); + + if (f->ref < 1) { + panic("fileclose"); + } + + if (--f->ref > 0) { + release(&ftable.lock); + return; + } + + ff = *f; + f->ref = 0; + f->type = FD_NONE; + release(&ftable.lock); + + if (ff.type == FD_PIPE) { + pipeclose(ff.pipe, ff.writable); + + } else if (ff.type == FD_INODE) { + begin_trans(); + iput(ff.ip); + commit_trans(); + } +} + +// Get metadata about file f. +int filestat (struct file *f, struct stat *st) +{ + if (f->type == FD_INODE) { + ilock(f->ip); + stati(f->ip, st); + iunlock(f->ip); + + return 0; + } + + return -1; +} + +// Read from file f. +int fileread (struct file *f, char *addr, int n) +{ + int r; + + if (f->readable == 0) { + return -1; + } + + if (f->type == FD_PIPE) { + return piperead(f->pipe, addr, n); + } + + if (f->type == FD_INODE) { + ilock(f->ip); + + if ((r = readi(f->ip, addr, f->off, n)) > 0) { + f->off += r; + } + + iunlock(f->ip); + + return r; + } + + panic("fileread"); +} + +//PAGEBREAK! +// Write to file f. +int filewrite (struct file *f, char *addr, int n) +{ + int r; + int i; + int max; + int n1; + + if (f->writable == 0) { + return -1; + } + + if (f->type == FD_PIPE) { + return pipewrite(f->pipe, addr, n); + } + + if (f->type == FD_INODE) { + // write a few blocks at a time to avoid exceeding + // the maximum log transaction size, including + // i-node, indirect block, allocation blocks, + // and 2 blocks of slop for non-aligned writes. + // this really belongs lower down, since writei() + // might be writing a device like the console. + max = ((LOGSIZE - 1 - 1 - 2) / 2) * 512; + i = 0; + + while (i < n) { + n1 = n - i; + + if (n1 > max) { + n1 = max; + } + + begin_trans(); + ilock(f->ip); + + if ((r = writei(f->ip, addr + i, f->off, n1)) > 0) { + f->off += r; + } + + iunlock(f->ip); + commit_trans(); + + if (r < 0) { + break; + } + + if (r != n1) { + panic("short filewrite"); + } + + i += r; + } + + return i == n ? n : -1; + } + + panic("filewrite"); +} +