os_kernel_lab/code/lab8/kern/fs/vfs/vfspath.c

127 lines
2.6 KiB
C
Raw Normal View History

2012-08-22 12:32:13 +08:00
#include <defs.h>
#include <string.h>
#include <vfs.h>
#include <inode.h>
#include <iobuf.h>
#include <stat.h>
#include <proc.h>
#include <error.h>
#include <assert.h>
/*
* get_cwd_nolock - retrieve current process's working directory. without lock protect
*/
static struct inode *
get_cwd_nolock(void) {
return current->filesp->pwd;
}
/*
* set_cwd_nolock - set current working directory.
*/
static void
set_cwd_nolock(struct inode *pwd) {
current->filesp->pwd = pwd;
}
/*
* lock_cfs - lock the fs related process on current process
*/
static void
lock_cfs(void) {
lock_files(current->filesp);
}
/*
* unlock_cfs - unlock the fs related process on current process
*/
static void
unlock_cfs(void) {
unlock_files(current->filesp);
}
/*
* vfs_get_curdir - Get current directory as a inode.
*/
int
vfs_get_curdir(struct inode **dir_store) {
struct inode *node;
if ((node = get_cwd_nolock()) != NULL) {
vop_ref_inc(node);
*dir_store = node;
return 0;
}
return -E_NOENT;
}
/*
* vfs_set_curdir - Set current directory as a inode.
* The passed inode must in fact be a directory.
*/
int
vfs_set_curdir(struct inode *dir) {
int ret = 0;
lock_cfs();
struct inode *old_dir;
if ((old_dir = get_cwd_nolock()) != dir) {
if (dir != NULL) {
uint32_t type;
if ((ret = vop_gettype(dir, &type)) != 0) {
goto out;
}
if (!S_ISDIR(type)) {
ret = -E_NOTDIR;
goto out;
}
vop_ref_inc(dir);
}
set_cwd_nolock(dir);
if (old_dir != NULL) {
vop_ref_dec(old_dir);
}
}
out:
unlock_cfs();
return ret;
}
/*
* vfs_chdir - Set current directory, as a pathname. Use vfs_lookup to translate
* it to a inode.
*/
int
vfs_chdir(char *path) {
int ret;
struct inode *node;
if ((ret = vfs_lookup(path, &node)) == 0) {
ret = vfs_set_curdir(node);
vop_ref_dec(node);
}
return ret;
}
/*
* vfs_getcwd - retrieve current working directory(cwd).
*/
int
vfs_getcwd(struct iobuf *iob) {
int ret;
struct inode *node;
if ((ret = vfs_get_curdir(&node)) != 0) {
return ret;
}
assert(node->in_fs != NULL);
const char *devname = vfs_get_devname(node->in_fs);
if ((ret = iobuf_move(iob, (char *)devname, strlen(devname), 1, NULL)) != 0) {
goto out;
}
char colon = ':';
if ((ret = iobuf_move(iob, &colon, sizeof(colon), 1, NULL)) != 0) {
goto out;
}
ret = vop_namefile(node, iob);
out:
vop_ref_dec(node);
return ret;
}