123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- //
- // 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)
- {
- memset(&ftable, 0, sizeof(ftable));
- 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);
- //cprintf("inside fileread\n");
- if((r = readi(f->ip, addr, f->off, n)) > 0)
- f->off += r;
- //cprintf("inside fileread: after readi rv=%x\n", r);
- iunlock(f->ip);
- return r;
- }
- panic("fileread");
- return -1;
- }
- //PAGEBREAK!
- // Write to file f.
- int
- filewrite(struct file *f, char *addr, int n)
- {
- int r;
- if(f->writable == 0)
- return -1;
- //cprintf("inside filewrite\n");
- 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.
- int max = ((LOGSIZE-1-1-2) / 2) * 512;
- int i = 0;
- while(i < n){
- int 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");
- return -1;
- }
|