xref: /xv6-public/file.c (revision 0754d21c)
112abb1a5SRobert Morris //
212abb1a5SRobert Morris // File descriptors
312abb1a5SRobert Morris //
412abb1a5SRobert Morris 
59936bffaSrsc #include "types.h"
69936bffaSrsc #include "defs.h"
7558ab49fSrsc #include "param.h"
80aef8914SRuss Cox #include "fs.h"
91ddfbbb1SFrans Kaashoek #include "spinlock.h"
10dec637bcSFrans Kaashoek #include "sleeplock.h"
11dec637bcSFrans Kaashoek #include "file.h"
129936bffaSrsc 
139936bffaSrsc struct devsw devsw[NDEV];
147f399ccaSrsc struct {
157f399ccaSrsc   struct spinlock lock;
169936bffaSrsc   struct file file[NFILE];
177f399ccaSrsc } ftable;
189936bffaSrsc 
199936bffaSrsc void
fileinit(void)2050e514beSrsc fileinit(void)
219936bffaSrsc {
2234295f46Srsc   initlock(&ftable.lock, "ftable");
239936bffaSrsc }
249936bffaSrsc 
25eaea18cbSrsc // Allocate a file structure.
269936bffaSrsc struct file*
filealloc(void)2750e514beSrsc filealloc(void)
289936bffaSrsc {
297f399ccaSrsc   struct file *f;
309936bffaSrsc 
317f399ccaSrsc   acquire(&ftable.lock);
327f399ccaSrsc   for(f = ftable.file; f < ftable.file + NFILE; f++){
337f399ccaSrsc     if(f->ref == 0){
347f399ccaSrsc       f->ref = 1;
357f399ccaSrsc       release(&ftable.lock);
367f399ccaSrsc       return f;
379936bffaSrsc     }
389936bffaSrsc   }
397f399ccaSrsc   release(&ftable.lock);
409936bffaSrsc   return 0;
419936bffaSrsc }
429936bffaSrsc 
432186f88cSrsc // Increment ref count for file f.
441ccff18bSrsc struct file*
filedup(struct file * f)451ccff18bSrsc filedup(struct file *f)
469936bffaSrsc {
477f399ccaSrsc   acquire(&ftable.lock);
487f399ccaSrsc   if(f->ref < 1)
491ccff18bSrsc     panic("filedup");
502186f88cSrsc   f->ref++;
517f399ccaSrsc   release(&ftable.lock);
521ccff18bSrsc   return f;
539936bffaSrsc }
549936bffaSrsc 
5513491bf3Srsc // Close file f.  (Decrement ref count, close when reaches 0.)
5613491bf3Srsc void
fileclose(struct file * f)5713491bf3Srsc fileclose(struct file *f)
5813491bf3Srsc {
5913491bf3Srsc   struct file ff;
6013491bf3Srsc 
617f399ccaSrsc   acquire(&ftable.lock);
627f399ccaSrsc   if(f->ref < 1)
6313491bf3Srsc     panic("fileclose");
6413491bf3Srsc   if(--f->ref > 0){
657f399ccaSrsc     release(&ftable.lock);
6613491bf3Srsc     return;
6713491bf3Srsc   }
6813491bf3Srsc   ff = *f;
6913491bf3Srsc   f->ref = 0;
707f399ccaSrsc   f->type = FD_NONE;
717f399ccaSrsc   release(&ftable.lock);
7213491bf3Srsc 
7313491bf3Srsc   if(ff.type == FD_PIPE)
747834cca6Srsc     pipeclose(ff.pipe, ff.writable);
752e590463SRobert Morris   else if(ff.type == FD_INODE){
7671453f72SRobert Morris     begin_op();
7713491bf3Srsc     iput(ff.ip);
7871453f72SRobert Morris     end_op();
792e590463SRobert Morris   }
8013491bf3Srsc }
8113491bf3Srsc 
8213491bf3Srsc // Get metadata about file f.
8313491bf3Srsc int
filestat(struct file * f,struct stat * st)8413491bf3Srsc filestat(struct file *f, struct stat *st)
8513491bf3Srsc {
8613491bf3Srsc   if(f->type == FD_INODE){
8713491bf3Srsc     ilock(f->ip);
8813491bf3Srsc     stati(f->ip, st);
8913491bf3Srsc     iunlock(f->ip);
9013491bf3Srsc     return 0;
9113491bf3Srsc   }
9213491bf3Srsc   return -1;
9313491bf3Srsc }
9413491bf3Srsc 
9512abb1a5SRobert Morris // Read from file f.
969936bffaSrsc int
fileread(struct file * f,char * addr,int n)972cbb4b18Srsc fileread(struct file *f, char *addr, int n)
989936bffaSrsc {
992186f88cSrsc   int r;
1002186f88cSrsc 
1012cbb4b18Srsc   if(f->readable == 0)
1029936bffaSrsc     return -1;
1032186f88cSrsc   if(f->type == FD_PIPE)
1047834cca6Srsc     return piperead(f->pipe, addr, n);
105eaea18cbSrsc   if(f->type == FD_INODE){
10607090dd7Srsc     ilock(f->ip);
10707090dd7Srsc     if((r = readi(f->ip, addr, f->off, n)) > 0)
1082186f88cSrsc       f->off += r;
10907090dd7Srsc     iunlock(f->ip);
1102186f88cSrsc     return r;
1112186f88cSrsc   }
11250e514beSrsc   panic("fileread");
1139936bffaSrsc }
1149936bffaSrsc 
115e76dab4fSAustin Clements //PAGEBREAK!
11612abb1a5SRobert Morris // Write to file f.
1172186f88cSrsc int
filewrite(struct file * f,char * addr,int n)1182186f88cSrsc filewrite(struct file *f, char *addr, int n)
1199936bffaSrsc {
1202186f88cSrsc   int r;
1219936bffaSrsc 
1222186f88cSrsc   if(f->writable == 0)
1232186f88cSrsc     return -1;
1242186f88cSrsc   if(f->type == FD_PIPE)
1257834cca6Srsc     return pipewrite(f->pipe, addr, n);
126eaea18cbSrsc   if(f->type == FD_INODE){
1272e590463SRobert Morris     // write a few blocks at a time to avoid exceeding
1282e590463SRobert Morris     // the maximum log transaction size, including
1292e590463SRobert Morris     // i-node, indirect block, allocation blocks,
1302e590463SRobert Morris     // and 2 blocks of slop for non-aligned writes.
1312e590463SRobert Morris     // this really belongs lower down, since writei()
1322e590463SRobert Morris     // might be writing a device like the console.
133*0754d21cSRobert Morris     int max = ((MAXOPBLOCKS-1-1-2) / 2) * 512;
1342e590463SRobert Morris     int i = 0;
1352e590463SRobert Morris     while(i < n){
1362e590463SRobert Morris       int n1 = n - i;
1372e590463SRobert Morris       if(n1 > max)
1382e590463SRobert Morris         n1 = max;
1395053dd6aSRobert Morris 
14071453f72SRobert Morris       begin_op();
1415053dd6aSRobert Morris       ilock(f->ip);
1423a5fa7edSFrans Kaashoek       if ((r = writei(f->ip, addr + i, f->off, n1)) > 0)
1433a5fa7edSFrans Kaashoek         f->off += r;
1445053dd6aSRobert Morris       iunlock(f->ip);
14571453f72SRobert Morris       end_op();
1465053dd6aSRobert Morris 
1472e590463SRobert Morris       if(r < 0)
1482e590463SRobert Morris         break;
1492e590463SRobert Morris       if(r != n1)
1502e590463SRobert Morris         panic("short filewrite");
1512e590463SRobert Morris       i += r;
1522e590463SRobert Morris     }
1532e590463SRobert Morris     return i == n ? n : -1;
1549936bffaSrsc   }
1552186f88cSrsc   panic("filewrite");
1569936bffaSrsc }
1579936bffaSrsc 
158