xv6

port of xv6 to x86-64
git clone http://frotz.net/git/xv6.git
Log | Files | Refs | README | LICENSE

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