0,0 → 1,140 |
/* This file contains the code for performing four system calls relating to |
* status and directories. |
*/ |
|
/* Methods: |
* do_chdir: perform the CHDIR system call |
* do_stat: perform the STAT system call |
* do_fstat: perform the FSTAT system call |
*/ |
|
|
#include "fs.h" |
#include "stat.h" |
#include "file.h" |
#include "fproc.h" |
#include "inode.h" |
#include "param.h" |
|
|
static int change(inode_t **iip, char *name_ptr, int len); |
static int stat_inode(inode_t *rip, filp_t *fil_ptr, char *user_addr); |
|
int do_chdir() |
{ |
|
/* Perform the chdir(file_name) system call */ |
int r; |
|
r = change(&fp->fp_workdir, file_name, strlen(file_name)+1); |
|
return r; |
} |
|
int change(inode_t **iip, char *name_ptr, int len) |
{ |
|
/* |
* iip: pointer to the inode pointer for the dir |
* name_ptr: pointer to the directory name to change to |
* len: length of the directory name string |
*/ |
|
/* Do the actual work for chdir() and chroot(). */ |
|
inode_t *rip; |
register int r; |
|
r = OK; |
|
/* Try to open the new directory. */ |
if (fetch_name(name_ptr, len) != OK) |
return err_code; |
|
if ((rip = eat_path(user_path)) == NIL_INODE) |
return err_code; |
|
/* It must be a directory and also be searchable. */ |
if ((rip->i_mode & I_TYPE) != I_DIRECTORY) |
r = FS_ENOTDIR; |
|
/* If error, return inode. */ |
if (r != OK) { |
put_inode(rip); |
return r; |
} |
|
/* Everything is OK. Make the change. */ |
put_inode(*iip); /* release the old directory */ |
*iip = rip; /* acquire the new one */ |
|
return OK; |
} |
|
int do_stat() |
{ |
|
/* Perform the stat(name, buf) system call. */ |
|
register inode_t *rip; |
register int r; |
|
/* Both stat() and fstat() use the same routine to do the real work. That |
* routine expects an inode, so acquire it temporarily. |
*/ |
|
if (fetch_name(file_name, strlen(file_name)+1) != OK) |
return err_code; |
|
if ((rip = eat_path(user_path)) == NIL_INODE) |
return err_code; |
|
r = stat_inode(rip, NIL_FILP, fp->buffer); /* actually do the work.*/ |
put_inode(rip); /* release the inode */ |
|
return r; |
} |
|
int do_fstat() |
{ |
|
/* Perform the fstat(fd, buf) system call. */ |
|
register filp_t *rfilp; |
|
|
/* Is the file descriptor valid? */ |
if ((rfilp = get_filp(fd)) == NIL_FILP) |
return err_code; |
|
if (rfilp->filp_ino == NIL_INODE) |
return FS_ENOENT; |
|
return(stat_inode(rfilp->filp_ino, NIL_FILP, fp->buffer)); |
} |
|
int stat_inode(register inode_t *rip, filp_t *fil_ptr, char *user_addr) |
{ |
|
/* |
* rip: pointer to inode to stat |
* fil_ptr: filp pointer, supplied by 'fstat' |
* user_addr: user space address where stat buf goes |
*/ |
|
/* Common code for stat and fstat system calls. */ |
|
stat_t statbuf; |
|
/* Fill in the statbuf struct. */ |
statbuf.st_ino = rip->i_num; |
statbuf.st_mode = rip->i_mode; |
statbuf.st_nlink = rip->i_nlinks & BYTE; |
statbuf.st_size = rip->i_size; |
|
/* Copy infomations to userspace. */ |
memcpy(user_addr, &statbuf, sizeof(statbuf)); |
|
return OK; |
} |
|