file.c (2809B)
1 // 2 // File descriptors 3 // 4 5 #include "types.h" 6 #include "defs.h" 7 #include "param.h" 8 #include "fs.h" 9 #include "file.h" 10 #include "spinlock.h" 11 12 struct devsw devsw[NDEV]; 13 struct { 14 struct spinlock lock; 15 struct file file[NFILE]; 16 } ftable; 17 18 void 19 fileinit(void) 20 { 21 initlock(&ftable.lock, "ftable"); 22 } 23 24 // Allocate a file structure. 25 struct file* 26 filealloc(void) 27 { 28 struct file *f; 29 30 acquire(&ftable.lock); 31 for(f = ftable.file; f < ftable.file + NFILE; f++){ 32 if(f->ref == 0){ 33 f->ref = 1; 34 release(&ftable.lock); 35 return f; 36 } 37 } 38 release(&ftable.lock); 39 return 0; 40 } 41 42 // Increment ref count for file f. 43 struct file* 44 filedup(struct file *f) 45 { 46 acquire(&ftable.lock); 47 if(f->ref < 1) 48 panic("filedup"); 49 f->ref++; 50 release(&ftable.lock); 51 return f; 52 } 53 54 // Close file f. (Decrement ref count, close when reaches 0.) 55 void 56 fileclose(struct file *f) 57 { 58 struct file ff; 59 60 acquire(&ftable.lock); 61 if(f->ref < 1) 62 panic("fileclose"); 63 if(--f->ref > 0){ 64 release(&ftable.lock); 65 return; 66 } 67 ff = *f; 68 f->ref = 0; 69 f->type = FD_NONE; 70 release(&ftable.lock); 71 72 if(ff.type == FD_PIPE) 73 pipeclose(ff.pipe, ff.writable); 74 else if(ff.type == FD_INODE){ 75 begin_trans(); 76 iput(ff.ip); 77 commit_trans(); 78 } 79 } 80 81 // Get metadata about file f. 82 int 83 filestat(struct file *f, struct stat *st) 84 { 85 if(f->type == FD_INODE){ 86 ilock(f->ip); 87 stati(f->ip, st); 88 iunlock(f->ip); 89 return 0; 90 } 91 return -1; 92 } 93 94 // Read from file f. 95 int 96 fileread(struct file *f, char *addr, int n) 97 { 98 int r; 99 100 if(f->readable == 0) 101 return -1; 102 if(f->type == FD_PIPE) 103 return piperead(f->pipe, addr, n); 104 if(f->type == FD_INODE){ 105 ilock(f->ip); 106 if((r = readi(f->ip, addr, f->off, n)) > 0) 107 f->off += r; 108 iunlock(f->ip); 109 return r; 110 } 111 panic("fileread"); 112 } 113 114 //PAGEBREAK! 115 // Write to file f. 116 int 117 filewrite(struct file *f, char *addr, int n) 118 { 119 int r; 120 121 if(f->writable == 0) 122 return -1; 123 if(f->type == FD_PIPE) 124 return pipewrite(f->pipe, addr, n); 125 if(f->type == FD_INODE){ 126 // write a few blocks at a time to avoid exceeding 127 // the maximum log transaction size, including 128 // i-node, indirect block, allocation blocks, 129 // and 2 blocks of slop for non-aligned writes. 130 // this really belongs lower down, since writei() 131 // might be writing a device like the console. 132 int max = ((LOGSIZE-1-1-2) / 2) * 512; 133 int i = 0; 134 while(i < n){ 135 int n1 = n - i; 136 if(n1 > max) 137 n1 = max; 138 139 begin_trans(); 140 ilock(f->ip); 141 if ((r = writei(f->ip, addr + i, f->off, n1)) > 0) 142 f->off += r; 143 iunlock(f->ip); 144 commit_trans(); 145 146 if(r < 0) 147 break; 148 if(r != n1) 149 panic("short filewrite"); 150 i += r; 151 } 152 return i == n ? n : -1; 153 } 154 panic("filewrite"); 155 } 156