ext2 chmod() and chown()

This commit is contained in:
Mark
2020-01-27 12:11:55 +02:00
parent 2cc9c6ef07
commit c28da05558
3 changed files with 107 additions and 1 deletions
+3
View File
@@ -12,3 +12,6 @@ int ext2_read_block(struct fs *ext2, void *blk, uint32_t no);
int ext2_read_inode_block(struct fs *ext2, struct ext2_inode *inode, void *block, uint32_t index);
int ext2_read_inode(struct fs *ext2, struct ext2_inode *dst, uint32_t ino);
// NOTE: this function automatically updates access and modification time
// on the inode written
int ext2_write_inode(struct fs *ext2, struct ext2_inode *node, uint32_t ino);
+41
View File
@@ -30,6 +30,18 @@ int ext2_read_block(struct fs *fs, void *block, uint32_t no) {
return res;
}
int ext2_write_block(struct fs *fs, const void *block, uint32_t no) {
struct ext2_data *data = fs->fs_private;
_assert(data);
kdebug("Write block %u: %p\n", no, no * data->block_size);
int res = blk_write(fs->blk, block, no * data->block_size, data->block_size);
if (res == 1024) {
return 0;
}
kerror("Failed to write block %u: %s\n", no, kstrerror(res));
return res;
}
int ext2_read_inode(struct fs *fs, struct ext2_inode *inode, uint32_t ino) {
struct ext2_data *data = fs->fs_private;
_assert(data);
@@ -55,6 +67,35 @@ int ext2_read_inode(struct fs *fs, struct ext2_inode *inode, uint32_t ino) {
return 0;
}
int ext2_write_inode(struct fs *fs, struct ext2_inode *inode, uint32_t ino) {
// Automatically update inode times
inode->mtime = time();
inode->atime = inode->mtime;
struct ext2_data *data = fs->fs_private;
_assert(data);
char block[data->block_size];
if (ino < 1 || ino >= data->sb.inode_count) {
panic("Invalid inode number: %u\n", ino);
}
int res;
--ino;
uint32_t ino_group = ino / data->sb.block_group_inodes;
uint32_t ino_in_group = ino % data->sb.block_group_inodes;
uint32_t ino_block = data->bgdt[ino_group].inode_table_no + ino_in_group / data->inodes_per_block;
uint32_t offset_in_block = (ino_in_group % data->inodes_per_block) * data->inode_size;
_assert(offset_in_block < data->block_size);
if ((res = ext2_read_block(fs, block, ino_block)) != 0) {
return res;
}
memcpy(offset_in_block + block, inode, data->inode_size);
return ext2_write_block(fs, block, ino_block);
}
int ext2_read_inode_block(struct fs *fs, struct ext2_inode *inode, void *buf, uint32_t index) {
if (index < 12) {
return ext2_read_block(fs, buf, inode->direct_blocks[index]);
+63 -1
View File
@@ -5,6 +5,7 @@
#include "sys/fs/node.h"
#include "sys/string.h"
#include "sys/assert.h"
#include "sys/fcntl.h"
#include "sys/fs/fs.h"
#include "sys/panic.h"
#include "sys/debug.h"
@@ -13,7 +14,10 @@
static int ext2_vnode_find(struct vnode *at, const char *name, struct vnode **res);
static ssize_t ext2_vnode_read(struct ofile *fd, void *buf, size_t count);
static int ext2_vnode_open(struct ofile *fd, int opt);
static int ext2_vnode_opendir(struct ofile *fd);
static int ext2_vnode_chmod(struct vnode *vn, mode_t new_mode);
static int ext2_vnode_chown(struct vnode *node, uid_t new_uid, gid_t new_gid);
static ssize_t ext2_vnode_readdir(struct ofile *fd, struct dirent *ent);
static int ext2_vnode_stat(struct vnode *at, struct stat *st);
@@ -26,7 +30,10 @@ struct vnode_operations g_ext2_vnode_ops = {
.readdir = ext2_vnode_readdir,
.stat = ext2_vnode_stat,
.chmod = ext2_vnode_chmod,
.chown = ext2_vnode_chown,
.open = ext2_vnode_open,
.read = ext2_vnode_read,
};
@@ -88,6 +95,22 @@ static int ext2_vnode_find(struct vnode *at, const char *name, struct vnode **re
return -ENOENT;
}
static int ext2_vnode_open(struct ofile *fd, int opt) {
if ((opt & O_APPEND) && (opt & O_ACCMODE) == O_RDONLY) {
// Impossible, I guess
return -EINVAL;
}
if ((opt & O_ACCMODE) != O_RDONLY) {
// Not implemented
return -EROFS;
}
_assert(!(opt & O_DIRECTORY));
fd->pos = 0;
return 0;
}
static ssize_t ext2_vnode_read(struct ofile *fd, void *buf, size_t count) {
_assert(fd);
_assert(buf);
@@ -209,6 +232,45 @@ static ssize_t ext2_vnode_readdir(struct ofile *fd, struct dirent *ent) {
return ent->d_reclen;
}
static int ext2_vnode_chmod(struct vnode *node, mode_t new_mode) {
_assert(node);
struct ext2_inode *inode = node->fs_data;
_assert(inode);
struct fs *ext2 = node->fs;
_assert(ext2);
// Only rewrite inode if something really changed
if ((inode->mode & 0xFFF) != (new_mode & 0xFFF)) {
// chmod() only updates file mode, don't touch file type
inode->mode &= ~0xFFF;
inode->mode |= new_mode & 0xFFF;
node->mode = new_mode & 0xFFF;
return ext2_write_inode(ext2, inode, node->ino);
}
return 0;
}
static int ext2_vnode_chown(struct vnode *node, uid_t new_uid, gid_t new_gid) {
_assert(node);
struct ext2_inode *inode = node->fs_data;
_assert(inode);
struct fs *ext2 = node->fs;
_assert(ext2);
if (new_uid != inode->uid || new_gid != inode->gid) {
inode->uid = new_uid;
inode->gid = new_gid;
node->uid = new_uid;
node->gid = new_gid;
return ext2_write_inode(ext2, inode, node->ino);
}
return 0;
}
static int ext2_vnode_stat(struct vnode *node, struct stat *st) {
_assert(node && st);
struct ext2_inode *inode = node->fs_data;
@@ -262,7 +324,7 @@ void ext2_inode_to_vnode(struct vnode *vnode, struct ext2_inode *inode, uint32_t
vnode->type = VN_REG;
break;
default:
panic("Unsupported inode type: %04x\n", inode->mode);
panic("Unsupported inode type: %04x\n", inode->mode & 0xF000);
}
}