diff --git a/file.c b/file.c index cfbd7c9..47e4629 100644 --- a/file.c +++ b/file.c @@ -41,75 +41,55 @@ filealloc(void) return 0; } -// Write to file f. Addr is kernel address. -int -filewrite(struct file *f, char *addr, int n) +// Increment ref count for file f. +void +fileincref(struct file *f) { - if(f->writable == 0) - return -1; - if(f->type == FD_PIPE){ - return pipe_write(f->pipe, addr, n); - } else if(f->type == FD_FILE) { - ilock(f->ip); - int r = writei(f->ip, addr, f->off, n); - if(r > 0) { - f->off += r; - } - iunlock(f->ip); - return r; - } else { - panic("filewrite"); - return -1; - } + acquire(&file_table_lock); + if(f->ref < 1 || f->type == FD_CLOSED) + panic("fileincref"); + f->ref++; + release(&file_table_lock); } // Read from file f. Addr is kernel address. int fileread(struct file *f, char *addr, int n) { + int r; + if(f->readable == 0) return -1; - if(f->type == FD_PIPE){ + if(f->type == FD_PIPE) return pipe_read(f->pipe, addr, n); - } else if(f->type == FD_FILE){ + if(f->type == FD_FILE){ ilock(f->ip); - int cc = readi(f->ip, addr, f->off, n); - if(cc > 0) - f->off += cc; + if((r = readi(f->ip, addr, f->off, n)) > 0) + f->off += r; iunlock(f->ip); - return cc; - } else { - panic("fileread"); - return -1; + return r; } + panic("fileread"); } -// Close file f. (Decrement ref count, close when reaches 0.) -void -fileclose(struct file *f) +// Write to file f. Addr is kernel address. +int +filewrite(struct file *f, char *addr, int n) { - acquire(&file_table_lock); + int r; - if(f->ref < 1 || f->type == FD_CLOSED) - panic("fileclose"); - - if(--f->ref == 0){ - struct file dummy = *f; - - f->ref = 0; - f->type = FD_CLOSED; - release(&file_table_lock); - - if(dummy.type == FD_PIPE){ - pipe_close(dummy.pipe, dummy.writable); - } else if(dummy.type == FD_FILE){ - idecref(dummy.ip); - } else { - panic("fileclose"); - } - } else { - release(&file_table_lock); + if(f->writable == 0) + return -1; + if(f->type == FD_PIPE) + return pipe_write(f->pipe, addr, n); + if(f->type == FD_FILE){ + ilock(f->ip); + if((r = writei(f->ip, addr, f->off, n)) > 0) + f->off += r; + iunlock(f->ip); + return r; } + panic("filewrite"); } // Get metadata about file f. @@ -121,17 +101,35 @@ filestat(struct file *f, struct stat *st) stati(f->ip, st); iunlock(f->ip); return 0; - } else - return -1; + } + return -1; } -// Increment ref count for file f. +// Close file f. (Decrement ref count, close when reaches 0.) void -fileincref(struct file *f) +fileclose(struct file *f) { + struct file ff; acquire(&file_table_lock); + if(f->ref < 1 || f->type == FD_CLOSED) - panic("fileincref"); - f->ref++; + panic("fileclose"); + + if(--f->ref > 0){ + release(&file_table_lock); + return; + } + + ff = *f; + f->ref = 0; + f->type = FD_CLOSED; release(&file_table_lock); + + if(ff.type == FD_PIPE) + pipe_close(ff.pipe, ff.writable); + else if(ff.type == FD_FILE) + idecref(ff.ip); + else + panic("fileclose"); } +