0,0 → 1,120 |
/* This file contains the procedures for opening, closing, and seeking on files. */ |
|
/* Methods: |
* do_open: perform the OPEN system call |
* do_close: perform the CLOSE system call |
* do_lseek: perform the SEEK system call |
*/ |
|
|
#include "fs.h" |
#include "block.h" |
#include "file.h" |
#include "fproc.h" |
#include "inode.h" |
#include "param.h" |
|
|
int do_open() |
{ |
|
/* Perform the open(file_name) system call */ |
|
int r; |
register inode_t *rip; |
filp_t *fil_ptr; |
|
|
r = fetch_name(file_name, strlen(file_name)+1); |
if (r != OK) |
return err_code; /* name was bad */ |
|
/* See if file descriptor and filp slots are available. */ |
if ( (r = get_fd(0, &fd, &fil_ptr)) != OK) |
return r; |
|
/* Scan path name. */ |
if ( (rip = eat_path(user_path)) == NIL_INODE) |
return err_code; |
|
/* Claim the file descriptor and filp slot and fill them in. */ |
fp->fp_filp[fd] = fil_ptr; |
fil_ptr->filp_count = 1; |
fil_ptr->filp_ino = rip; |
fil_ptr->filp_flags = R_BIT; |
|
return fd; |
} |
|
int do_close() |
{ |
|
/* Perform the close(fd) system call. */ |
|
register filp_t *rfilp; |
register inode_t *rip; |
|
|
/* First locate the inode that belongs to the file descriptor */ |
if ( (rfilp = get_filp(fd)) == NIL_FILP) |
return err_code; |
|
rip = rfilp->filp_ino; /* 'rip' points to the inode */ |
|
if (--rfilp->filp_count == 0) { |
put_inode(rip); |
} |
|
fp->fp_filp[fd] = NIL_FILP; |
|
return OK; |
} |
|
int do_lseek() |
{ |
|
/* Perform the seek(ls_fd, offset, whence) system call. */ |
|
register filp_t *rfilp; |
register offset_t pos, new_pos; |
|
|
/* Check to see if the file descriptor is valid. */ |
if ( (rfilp = get_filp(fd)) == NIL_FILP) |
return err_code; |
|
|
/* The value of 'whence' determines the start position to use. */ |
switch(whence) { |
case 0: pos = 0; |
break; |
case 1: pos = rfilp->filp_pos; |
break; |
case 2: pos = rfilp->filp_ino->i_size; |
break; |
default: return FS_EINVAL; |
} |
|
/* Check for overflow. */ |
if (((long)offset > 0) && ((long)(pos + offset) < (long)pos)) |
return FS_EINVAL; |
if (((long)offset < 0) && ((long)(pos + offset) > (long)pos)) |
return FS_EINVAL; |
|
new_pos = pos + offset; |
|
/* Check for setting behind the end. */ |
if ((new_pos) > rfilp->filp_ino->i_size) { |
pos = rfilp->filp_ino->i_size; |
} |
else if (new_pos < 0) { |
pos = 0; |
} |
else { |
pos = new_pos; |
} |
rfilp->filp_pos = pos; |
|
return pos; |
} |
|