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