diff --git a/include/sys/amd64/sys_file.h b/include/sys/amd64/sys_file.h index 0a0cecf..6e4cc32 100644 --- a/include/sys/amd64/sys_file.h +++ b/include/sys/amd64/sys_file.h @@ -22,3 +22,6 @@ int sys_access(const char *path, int mode); // TODO: const struct termios *termp, const struct winsize *winp int sys_openpty(int *master, int *slave); + +int sys_chmod(const char *path, mode_t mode); +int sys_chown(const char *path, uid_t uid, gid_t gid); diff --git a/include/sys/fs/node.h b/include/sys/fs/node.h index bc26e45..79ac4bd 100644 --- a/include/sys/fs/node.h +++ b/include/sys/fs/node.h @@ -45,6 +45,8 @@ struct vnode_operations { int (*stat) (struct vnode *at, struct stat *st); int (*access) (struct vnode *node, uid_t *uid, gid_t *gid, mode_t *mode); + int (*chmod) (struct vnode *node, mode_t mode); + int (*chown) (struct vnode *node, uid_t uid, gid_t gid); int (*readlink) (struct vnode *at, char *buf, size_t lim); diff --git a/include/sys/fs/vfs.h b/include/sys/fs/vfs.h index de95cdd..eb20f4a 100644 --- a/include/sys/fs/vfs.h +++ b/include/sys/fs/vfs.h @@ -39,6 +39,8 @@ int vfs_readdir(struct vfs_ioctx *ctx, struct ofile *fd, struct dirent *ent); int vfs_unlink(struct vfs_ioctx *ctx, const char *path); int vfs_rmdir(struct vfs_ioctx *ctx, const char *path); int vfs_mkdir(struct vfs_ioctx *ctx, const char *path, mode_t mode); +int vfs_chmod(struct vfs_ioctx *ctx, const char *path, mode_t mode); +int vfs_chown(struct vfs_ioctx *ctx, const char *path, uid_t uid, gid_t gid); int vfs_access(struct vfs_ioctx *ctx, const char *path, int accmode); int vfs_stat(struct vfs_ioctx *ctx, const char *path, struct stat *st); diff --git a/include/sys/syscall.h b/include/sys/syscall.h index 29ab6ac..b7d6308 100644 --- a/include/sys/syscall.h +++ b/include/sys/syscall.h @@ -13,6 +13,8 @@ #define SYSCALL_NR_CREAT 85 #define SYSCALL_NR_UNLINK 87 #define SYSCALL_NR_READDIR 89 +#define SYSCALL_NR_CHMOD 90 +#define SYSCALL_NR_CHOWN 92 #define SYSCALL_NR_BRK 12 #define SYSCALL_NR_NANOSLEEP 35 diff --git a/sys/amd64/sys_file.c b/sys/amd64/sys_file.c index da59517..07bc6f7 100644 --- a/sys/amd64/sys_file.c +++ b/sys/amd64/sys_file.c @@ -185,3 +185,18 @@ int sys_openpty(int *master, int *slave) { return -EINVAL; } +int sys_chmod(const char *path, mode_t mode) { + struct thread *thr = get_cpu()->thread; + _assert(thr); + _assert(path); + + return vfs_chmod(&thr->ioctx, path, mode); +} + +int sys_chown(const char *path, uid_t uid, gid_t gid) { + struct thread *thr = get_cpu()->thread; + _assert(thr); + _assert(path); + + return vfs_chown(&thr->ioctx, path, uid, gid); +} diff --git a/sys/amd64/syscall.c b/sys/amd64/syscall.c index dc4ccd0..6fb1113 100644 --- a/sys/amd64/syscall.c +++ b/sys/amd64/syscall.c @@ -26,6 +26,8 @@ const void *amd64_syscall_jmp_table[256] = { [SYSCALL_NR_MKDIR] = sys_mkdir, [SYSCALL_NR_CREAT] = sys_creat, [SYSCALL_NR_RMDIR] = sys_rmdir, + [SYSCALL_NR_CHMOD] = sys_chmod, + [SYSCALL_NR_CHOWN] = sys_chown, // Process [SYSCALL_NR_EXIT] = sys_exit, diff --git a/sys/tty.c b/sys/tty.c index aa8cb6e..69e22a5 100644 --- a/sys/tty.c +++ b/sys/tty.c @@ -74,6 +74,7 @@ static ssize_t tty_read(struct chrdev *tty, void *buf, size_t pos, size_t lim) { memcpy((char *) buf + p, ibuf, rd); rem -= rd; + p += rd; } return p; diff --git a/sys/vfs/ext2/ext2vnop.c b/sys/vfs/ext2/ext2vnop.c index 4e60ce1..93f7c76 100644 --- a/sys/vfs/ext2/ext2vnop.c +++ b/sys/vfs/ext2/ext2vnop.c @@ -30,8 +30,8 @@ static int ext2_vnode_truncate(struct vnode *vn, size_t length); static ssize_t ext2_vnode_readdir(struct ofile *fd, struct dirent *ent); //static void ext2_vnode_destroy(vnode_t *vn); static int ext2_vnode_stat(struct vnode *vn, struct stat *st); -//static int ext2_vnode_chmod(vnode_t *vn, mode_t mode); -//static int ext2_vnode_chown(vnode_t *vn, uid_t uid, gid_t gid); +static int ext2_vnode_chmod(struct vnode *vn, mode_t mode); +static int ext2_vnode_chown(struct vnode *vn, uid_t uid, gid_t gid); static int ext2_vnode_unlink(struct vnode *vn); //static int ext2_vnode_access(vnode_t *vn, uid_t *uid, gid_t *gid, mode_t *mode); static int ext2_vnode_readlink(struct vnode *vn, char *dst, size_t lim); @@ -48,8 +48,8 @@ struct vnode_operations ext2_vnode_ops = { .readlink = ext2_vnode_readlink, // .symlink = ext2_vnode_symlink, // -// .chmod = ext2_vnode_chmod, -// .chown = ext2_vnode_chown, + .chmod = ext2_vnode_chmod, + .chown = ext2_vnode_chown, .stat = ext2_vnode_stat, .unlink = ext2_vnode_unlink, // .access = ext2_vnode_access, @@ -427,7 +427,6 @@ static ssize_t ext2_vnode_write(struct ofile *fd, const void *buf, size_t count) } } - kinfo("Wrote %u bytes\n", written); return written; } @@ -585,28 +584,28 @@ static int ext2_vnode_stat(struct vnode *vn, struct stat *st) { return 0; } -//static int ext2_vnode_chmod(vnode_t *vn, mode_t mode) { -// _assert(vn && vn->fs && vn->fs_data); -// struct ext2_inode *inode = (struct ext2_inode *) vn->fs_data; -// -// // Update only access mode -// inode->type_perm &= ~0x1FF; -// inode->type_perm |= mode & 0x1FF; -// -// // Write the inode back -// return ext2_write_inode(vn->fs, inode, vn->fs_number); -//} -// -//static int ext2_vnode_chown(vnode_t *vn, uid_t uid, gid_t gid) { -// _assert(vn && vn->fs && vn->fs_data); -// struct ext2_inode *inode = (struct ext2_inode *) vn->fs_data; -// -// inode->gid = gid; -// inode->uid = uid; -// -// // Write the inode back -// return ext2_write_inode(vn->fs, inode, vn->fs_number); -//} +static int ext2_vnode_chmod(struct vnode *vn, mode_t mode) { + _assert(vn && vn->fs && vn->fs_data); + struct ext2_inode *inode = (struct ext2_inode *) vn->fs_data; + + // Update only access mode + inode->type_perm &= ~0x1FF; + inode->type_perm |= mode & 0x1FF; + + // Write the inode back + return ext2_write_inode(vn->fs, inode, vn->ino); +} + +static int ext2_vnode_chown(struct vnode *vn, uid_t uid, gid_t gid) { + _assert(vn && vn->fs && vn->fs_data); + struct ext2_inode *inode = (struct ext2_inode *) vn->fs_data; + + inode->gid = gid; + inode->uid = uid; + + // Write the inode back + return ext2_write_inode(vn->fs, inode, vn->ino); +} static int ext2_vnode_unlink(struct vnode *node) { _assert(node); diff --git a/sys/vfs/tar.c b/sys/vfs/tar.c index cf5b236..8c6d7f7 100644 --- a/sys/vfs/tar.c +++ b/sys/vfs/tar.c @@ -28,12 +28,17 @@ static int tarfs_vnode_open(struct ofile *of, int opt); static int tarfs_vnode_stat(struct vnode *node, struct stat *st); static ssize_t tarfs_vnode_read(struct ofile *fd, void *buf, size_t count); static off_t tarfs_vnode_lseek(struct ofile *fd, off_t off, int whence); +// Nodes can be chmod/chown'd +static int tarfs_vnode_chmod(struct vnode *node, mode_t mode); +static int tarfs_vnode_chown(struct vnode *node, uid_t uid, gid_t gid); static struct vnode_operations _tarfs_vnode_op = { .stat = tarfs_vnode_stat, .read = tarfs_vnode_read, .open = tarfs_vnode_open, .lseek = tarfs_vnode_lseek, + .chmod = tarfs_vnode_chmod, + .chown = tarfs_vnode_chown, }; static ssize_t tarfs_octal(const char *buf, size_t lim) { @@ -313,6 +318,14 @@ static off_t tarfs_vnode_lseek(struct ofile *fd, off_t offset, int whence) { return fd->pos; } +static int tarfs_vnode_chmod(struct vnode *node, mode_t mode) { + return 0; +} + +static int tarfs_vnode_chown(struct vnode *node, uid_t uid, gid_t gid) { + return 0; +} + // void tarfs_init(void) { diff --git a/sys/vfs/vfs_ops.c b/sys/vfs/vfs_ops.c index 20dfcf1..c1c491b 100644 --- a/sys/vfs/vfs_ops.c +++ b/sys/vfs/vfs_ops.c @@ -545,3 +545,60 @@ off_t vfs_lseek(struct vfs_ioctx *ctx, struct ofile *fd, off_t offset, int whenc return node->op->lseek(fd, offset, whence); } + +int vfs_chmod(struct vfs_ioctx *ctx, const char *path, mode_t mode) { + _assert(ctx); + _assert(path); + struct vnode *node; + int res; + + mode &= 0x1FF; + + if ((res = vfs_find(ctx, ctx->cwd_vnode, path, &node)) != 0) { + return res; + } + + // Only root or file owner can do that + if (ctx->uid != 0 && ctx->uid != node->uid) { + return -EACCES; + } + + if (!node->op || !node->op->chmod) { + return -EINVAL; + } + + if ((res = node->op->chmod(node, mode)) != 0) { + return res; + } + + node->mode = mode; + + return 0; +} + +int vfs_chown(struct vfs_ioctx *ctx, const char *path, uid_t uid, gid_t gid) { + struct vnode *node; + int res; + + if ((res = vfs_find(ctx, ctx->cwd_vnode, path, &node)) != 0) { + return res; + } + + // Only root can chown + if (ctx->uid != 0) { + return -EACCES; + } + + if (!node->op || !node->op->chown) { + return -EINVAL; + } + + if ((res = node->op->chown(node, uid, gid)) != 0) { + return res; + } + + node->uid = uid; + node->gid = gid; + + return 0; +}