#include #include #include #include #include #include #include #include #include /* * 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; }