// 创建一个根dnode。
vfs_sysroot = vfs_d_alloc(NULL, &vfs_empty);
+ vfs_sysroot->parent = vfs_sysroot;
atomic_fetch_add(&vfs_sysroot->ref_count, 1);
}
return parent;
if (HSTR_EQ(str, &vfs_ddot)) {
- return parent->parent ? parent->parent : parent;
+ return parent->parent;
}
uint32_t hash = str->hash;
{
int errno;
+ if ((errno = vfs_check_writable(to_link))) {
+ return errno;
+ }
+
lock_inode(to_link->inode);
if (to_link->super_block->root != name->super_block->root) {
errno = EXDEV;
int
vfs_fsync(struct v_file* file)
{
+ int errno;
+ if ((errno = vfs_check_writable(file->dnode))) {
+ return errno;
+ }
+
lock_inode(file->inode);
- int errno = ENOTSUP;
pcache_commit_all(file->inode);
+ errno = ENOTSUP;
if (file->ops->sync) {
errno = file->ops->sync(file);
}
char name_str[VFS_NAME_MAXLEN];
struct hstr name = HSTR(name_str, 0);
int errno;
- if ((errno =
- vfs_walk(__current->cwd, path, fdir, &name, VFS_WALK_PARENT))) {
+ if ((errno = vfs_walk_proc(path, fdir, &name, VFS_WALK_PARENT))) {
return errno;
}
}
struct v_file* file = fd_s->file;
+
+ if ((errno = vfs_check_writable(file->dnode))) {
+ goto done;
+ }
+
if ((file->inode->itype & VFS_IFDIR)) {
errno = EISDIR;
goto done;
struct v_file* file = fd_s->file;
+ if (!file->ops->seek) {
+ errno = ENOTSUP;
+ goto done;
+ }
+
lock_inode(file->inode);
- size_t fpos = file->f_pos;
+ int overflow = 0;
+ int fpos = file->f_pos;
switch (options) {
case FSEEK_CUR:
- fpos = (size_t)((int)file->f_pos + offset);
+ overflow = __builtin_sadd_overflow((int)file->f_pos, offset, &fpos);
break;
case FSEEK_END:
- fpos = (size_t)((int)file->inode->fsize + offset);
+ overflow =
+ __builtin_sadd_overflow((int)file->inode->fsize, offset, &fpos);
break;
case FSEEK_SET:
fpos = offset;
break;
}
- if (!(errno = file->ops->seek(file->inode, fpos))) {
+ if (overflow) {
+ errno = EOVERFLOW;
+ } else if (!(errno = file->ops->seek(file->inode, fpos))) {
file->f_pos = fpos;
}
int
vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth)
{
- if (!dnode) {
+ if (!dnode || dnode->parent == dnode) {
return 0;
}
if (depth > 64) {
- return ELOOP;
+ return ENAMETOOLONG;
}
size_t len = vfs_get_path(dnode->parent, buf, size, depth + 1);
return len;
}
+ buf[len++] = VFS_PATH_DELIM;
+
size_t cpy_size = MIN(dnode->name.len, size - len);
strncpy(buf + len, dnode->name.value, cpy_size);
len += cpy_size;
- if (len < size) {
- buf[len++] = VFS_PATH_DELIM;
- }
-
return len;
}
{
int errno;
struct v_dnode* dnode;
- if (!(errno =
- vfs_walk(__current->cwd, path, &dnode, NULL, VFS_WALK_NOFOLLOW))) {
+ if (!(errno = vfs_walk_proc(path, &dnode, NULL, VFS_WALK_NOFOLLOW))) {
errno = vfs_readlink(dnode, buf, size);
}
{
int errno;
struct v_dnode* dnode;
- if ((errno = vfs_walk(__current->cwd, pathname, &dnode, NULL, 0))) {
+ if ((errno = vfs_walk_proc(pathname, &dnode, NULL, 0))) {
return DO_STATUS(errno);
}
lock_dnode(dnode);
+ if ((errno = vfs_check_writable(dnode))) {
+ goto done;
+ }
+
if ((dnode->super_block->fs->types & FSTYPE_ROFS)) {
errno = EROFS;
goto done;
char name_value[VFS_NAME_MAXLEN];
struct hstr name = HHSTR(name_value, 0, 0);
- if (!dir) {
- errno = ENOMEM;
+ if ((errno = vfs_walk_proc(path, &parent, &name, VFS_WALK_PARENT))) {
goto done;
}
- if ((errno =
- vfs_walk(__current->cwd, path, &parent, &name, VFS_WALK_PARENT))) {
+ if ((errno = vfs_check_writable(parent))) {
goto done;
}
- dir = vfs_d_alloc(parent, &name);
+ if (!(dir = vfs_d_alloc(parent, &name))) {
+ errno = ENOMEM;
+ goto done;
+ }
lock_dnode(parent);
lock_inode(parent->inode);
int
__vfs_do_unlink(struct v_dnode* dnode)
{
+ int errno;
struct v_inode* inode = dnode->inode;
if (dnode->ref_count > 1) {
return EBUSY;
}
+ if ((errno = vfs_check_writable(dnode))) {
+ return errno;
+ }
+
lock_inode(inode);
- int errno;
if (inode->open_count) {
errno = EBUSY;
} else if (!(inode->itype & VFS_IFDIR)) {
{
int errno;
struct v_dnode* dnode;
- if ((errno = vfs_walk(__current->cwd, pathname, &dnode, NULL, 0))) {
- goto done;
- }
- if ((dnode->super_block->fs->types & FSTYPE_ROFS)) {
- errno = EROFS;
+ if ((errno = vfs_walk_proc(pathname, &dnode, NULL, 0))) {
goto done;
}
{
int errno;
struct v_fd* fd_s;
+
if (!(errno = vfs_getfd(fildes, &fd_s))) {
errno = vfs_fsync(fd_s->file);
}
{
int errno;
struct v_dnode* dnode;
- if ((errno = vfs_walk(__current->cwd, pathname, &dnode, NULL, 0))) {
+ if ((errno = vfs_walk_proc(pathname, &dnode, NULL, 0))) {
goto done;
}
- if ((dnode->super_block->fs->types & FSTYPE_ROFS)) {
- errno = EROFS;
+
+ if (errno = vfs_check_writable(dnode)) {
goto done;
}
+
if (!dnode->inode->ops->set_symlink) {
errno = ENOTSUP;
goto done;
struct v_dnode* dnode;
int errno = 0;
- if ((errno = vfs_walk(__current->cwd, path, &dnode, NULL, 0))) {
+ if ((errno = vfs_walk_proc(path, &dnode, NULL, 0))) {
goto done;
}
int
vfs_do_rename(struct v_dnode* current, struct v_dnode* target)
{
+ int errno = 0;
if (current->inode->id == target->inode->id) {
// hard link
return 0;
}
+ if (errno = vfs_check_writable(current)) {
+ return errno;
+ }
+
if (current->ref_count > 1 || target->ref_count > 1) {
return EBUSY;
}
return EXDEV;
}
- int errno = 0;
-
struct v_dnode* oldparent = current->parent;
struct v_dnode* newparent = target->parent;
struct hstr name = HSTR(valloc(VFS_NAME_MAXLEN), 0);
int errno = 0;
- if ((errno = vfs_walk(__current->cwd, oldpath, &cur, NULL, 0))) {
+ if ((errno = vfs_walk_proc(oldpath, &cur, NULL, 0))) {
goto done;
}