Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2373 → Rev 2374

/branches/fs/uspace/fs/open.c
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;
}