Skip to content
Snippets Groups Projects
file.c 2.45 KiB
Newer Older
rtm's avatar
rtm committed
#include "types.h"
kaashoek's avatar
kaashoek committed
#include "stat.h"
rtm's avatar
rtm committed
#include "param.h"
#include "x86.h"
#include "mmu.h"
#include "proc.h"
#include "defs.h"
rsc's avatar
rsc committed
#include "file.h"
rtm's avatar
rtm committed
#include "spinlock.h"
kaashoek's avatar
kaashoek committed
#include "dev.h"
#include "fs.h"
#include "fsvar.h"
rtm's avatar
rtm committed

rsc's avatar
rsc committed
struct spinlock file_table_lock;
kaashoek's avatar
kaashoek committed
struct devsw devsw[NDEV];
rtm's avatar
rtm committed

rsc's avatar
rsc committed
struct file file[NFILE];
rtm's avatar
rtm committed

rsc's avatar
rsc committed
fileinit(void)
rsc's avatar
rsc committed
  initlock(&file_table_lock, "file_table");
rsc's avatar
rsc committed
// Allocate a file structure
rsc's avatar
rsc committed
struct file*
rsc's avatar
rsc committed
filealloc(void)
rtm's avatar
rtm committed
{
  int i;

rsc's avatar
rsc committed
  acquire(&file_table_lock);
rsc's avatar
rsc committed
  for(i = 0; i < NFILE; i++){
    if(file[i].type == FD_CLOSED){
      file[i].type = FD_NONE;
      file[i].ref = 1;
rsc's avatar
rsc committed
      release(&file_table_lock);
rsc's avatar
rsc committed
      return file + i;
rtm's avatar
rtm committed
    }
  }
rsc's avatar
rsc committed
  release(&file_table_lock);
rtm's avatar
rtm committed
  return 0;
}

rsc's avatar
rsc committed
// Write to file f.  Addr is kernel address.
rtm's avatar
rtm committed
int
rsc's avatar
rsc committed
filewrite(struct file *f, char *addr, int n)
rtm's avatar
rtm committed
{
rsc's avatar
rsc committed
  if(f->writable == 0)
rtm's avatar
rtm committed
    return -1;
rsc's avatar
rsc committed
  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);
rsc's avatar
rsc committed
    if(r > 0) {
rsc's avatar
rsc committed
      f->off += r;
kaashoek's avatar
kaashoek committed
    }
rsc's avatar
rsc committed
    iunlock(f->ip);
kaashoek's avatar
kaashoek committed
    return r;
rtm's avatar
rtm committed
  } else {
rsc's avatar
rsc committed
    panic("filewrite");
rtm's avatar
rtm committed
    return -1;
  }
}

rsc's avatar
rsc committed
// Read from file f.  Addr is kernel address.
rtm's avatar
rtm committed
int
rsc's avatar
rsc committed
fileread(struct file *f, char *addr, int n)
rtm's avatar
rtm committed
{
rsc's avatar
rsc committed
  if(f->readable == 0)
rtm's avatar
rtm committed
    return -1;
rsc's avatar
rsc committed
  if(f->type == FD_PIPE){
    return pipe_read(f->pipe, addr, n);
  } else if(f->type == FD_FILE){
    ilock(f->ip);
    int cc = readi(f->ip, addr, f->off, n);
    if(cc > 0)
rsc's avatar
rsc committed
      f->off += cc;
    iunlock(f->ip);
    return cc;
rtm's avatar
rtm committed
  } else {
rsc's avatar
rsc committed
    panic("fileread");
rtm's avatar
rtm committed
    return -1;
  }
}
rsc's avatar
rsc committed
// Close file f.  (Decrement ref count, close when reaches 0.)
rtm's avatar
rtm committed
void
rsc's avatar
rsc committed
fileclose(struct file *f)
rsc's avatar
rsc committed
  acquire(&file_table_lock);
rtm's avatar
rtm committed

rsc's avatar
rsc committed
  if(f->ref < 1 || f->type == FD_CLOSED)
rsc's avatar
rsc committed
    panic("fileclose");
rtm's avatar
rtm committed

rsc's avatar
rsc committed
  if(--f->ref == 0){
    struct file dummy = *f;
rsc's avatar
rsc committed
    f->ref = 0;
    f->type = FD_CLOSED;
    release(&file_table_lock);

    if(dummy.type == FD_PIPE){
rsc's avatar
rsc committed
      pipe_close(dummy.pipe, dummy.writable);
    } else if(dummy.type == FD_FILE){
      idecref(dummy.ip);
rtm's avatar
rtm committed
    } else {
rsc's avatar
rsc committed
      panic("fileclose");
rsc's avatar
rsc committed
    release(&file_table_lock);
rtm's avatar
rtm committed
}

rsc's avatar
rsc committed
// Get metadata about file f.
kaashoek's avatar
kaashoek committed
int
rsc's avatar
rsc committed
filestat(struct file *f, struct stat *st)
kaashoek's avatar
kaashoek committed
{
rsc's avatar
rsc committed
  if(f->type == FD_FILE){
    ilock(f->ip);
    stati(f->ip, st);
    iunlock(f->ip);
kaashoek's avatar
kaashoek committed
    return 0;
  } else
    return -1;
}

rsc's avatar
rsc committed
// Increment ref count for file f.
rtm's avatar
rtm committed
void
rsc's avatar
rsc committed
fileincref(struct file *f)
rtm's avatar
rtm committed
{
rsc's avatar
rsc committed
  acquire(&file_table_lock);
  if(f->ref < 1 || f->type == FD_CLOSED)
rsc's avatar
rsc committed
    panic("fileincref");
rsc's avatar
rsc committed
  f->ref++;
  release(&file_table_lock);