《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

126 lines
2.6 KiB

#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;
}