123 lines
3.0 KiB
C
123 lines
3.0 KiB
C
#include "inc.h"
|
|
|
|
static int search_dir(
|
|
struct inode *ldir_ptr, /* dir record parent */
|
|
char string[NAME_MAX], /* component to search for */
|
|
ino_t *numb /* pointer to new dir record */
|
|
) {
|
|
/* The search_dir function performs the operation of searching for the
|
|
* component ``string" in ldir_ptr. It returns the response and the
|
|
* number of the inode in numb.
|
|
*/
|
|
struct inode *dir_tmp;
|
|
size_t pos = 0;
|
|
int r;
|
|
|
|
/*
|
|
* This function search a particular element (in string) in a inode and
|
|
* return its number.
|
|
*/
|
|
|
|
if ((ldir_ptr->i_stat.st_mode & S_IFMT) != S_IFDIR)
|
|
return ENOTDIR;
|
|
|
|
if (strcmp(string, ".") == 0) {
|
|
*numb = ldir_ptr->i_stat.st_ino;
|
|
return OK;
|
|
}
|
|
|
|
/*
|
|
* Parent directories need special attention to make sure directory
|
|
* inodes stay consistent.
|
|
*/
|
|
if (strcmp(string, "..") == 0) {
|
|
if (ldir_ptr->i_stat.st_ino ==
|
|
v_pri.inode_root->i_stat.st_ino) {
|
|
*numb = v_pri.inode_root->i_stat.st_ino;
|
|
return OK;
|
|
}
|
|
else {
|
|
dir_tmp = alloc_inode();
|
|
r = read_inode(dir_tmp, ldir_ptr->extent, pos, &pos);
|
|
if ((r != OK) || (pos >= ldir_ptr->i_stat.st_size)) {
|
|
put_inode(dir_tmp);
|
|
return ENOENT;
|
|
}
|
|
/* Temporary fix for extent spilling */
|
|
put_inode(dir_tmp);
|
|
dir_tmp = alloc_inode();
|
|
/* End of fix */
|
|
r = read_inode(dir_tmp, ldir_ptr->extent, pos, &pos);
|
|
if ((r != OK) || (pos >= ldir_ptr->i_stat.st_size)) {
|
|
put_inode(dir_tmp);
|
|
return ENOENT;
|
|
}
|
|
*numb = dir_tmp->i_stat.st_ino;
|
|
put_inode(dir_tmp);
|
|
return OK;
|
|
}
|
|
}
|
|
|
|
/* Read the dir's content */
|
|
while (TRUE) {
|
|
dir_tmp = alloc_inode();
|
|
r = read_inode(dir_tmp, ldir_ptr->extent, pos, &pos);
|
|
if ((r != OK) || (pos >= ldir_ptr->i_stat.st_size)) {
|
|
put_inode(dir_tmp);
|
|
return ENOENT;
|
|
}
|
|
|
|
if ((strcmp(dir_tmp->i_name, string) == 0) ||
|
|
(strcmp(dir_tmp->i_name, "..") &&
|
|
strcmp(string, "..") == 0)) {
|
|
if (dir_tmp->i_stat.st_ino ==
|
|
v_pri.inode_root->i_stat.st_ino) {
|
|
*numb = v_pri.inode_root->i_stat.st_ino;
|
|
put_inode(dir_tmp);
|
|
return OK;
|
|
}
|
|
|
|
*numb = dir_tmp->i_stat.st_ino;
|
|
put_inode(dir_tmp);
|
|
return OK;
|
|
}
|
|
|
|
put_inode(dir_tmp);
|
|
}
|
|
}
|
|
|
|
int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
|
|
int *is_mountpt)
|
|
{
|
|
/* Given a directory and a component of a path, look up the component
|
|
* in the directory, find the inode, open it, and return its details.
|
|
*/
|
|
struct inode *dirp, *rip;
|
|
ino_t ino_nr;
|
|
int r;
|
|
|
|
/* Find the starting inode. */
|
|
if ((dirp = find_inode(dir_nr)) == NULL)
|
|
return EINVAL;
|
|
|
|
/* Look up the directory entry. */
|
|
if ((r = search_dir(dirp, name, &ino_nr)) != OK)
|
|
return r;
|
|
|
|
/* The component has been found in the directory. Get the inode. */
|
|
if ((rip = get_inode(ino_nr)) == NULL)
|
|
return EIO; /* FIXME: this could have multiple causes */
|
|
|
|
/* Return its details to the caller. */
|
|
node->fn_ino_nr = rip->i_stat.st_ino;
|
|
node->fn_mode = rip->i_stat.st_mode;
|
|
node->fn_size = rip->i_stat.st_size;
|
|
node->fn_uid = rip->i_stat.st_uid;
|
|
node->fn_gid = rip->i_stat.st_gid;
|
|
node->fn_dev = rip->i_stat.st_rdev;
|
|
|
|
*is_mountpt = rip->i_mountpoint;
|
|
|
|
return OK;
|
|
}
|