Browse Source

feat(truncate): add it to syscall, vfs and tmpfs

greatbridf 1 year ago
parent
commit
c29afbde1d
3 changed files with 44 additions and 0 deletions
  1. 3 0
      include/kernel/vfs.hpp
  2. 23 0
      src/kernel/syscall.cpp
  3. 18 0
      src/kernel/vfs.cpp

+ 3 - 0
include/kernel/vfs.hpp

@@ -215,6 +215,8 @@ public:
     virtual int inode_stat(dentry* dent, struct stat* stat);
     virtual dev_t inode_devid(inode* file);
 
+    virtual int truncate(inode* file, size_t size);
+
     // parameter 'length' in callback:
     // if 0, 'name' should be null terminated
     // else, 'name' size
@@ -330,6 +332,7 @@ int vfs_mknode(fs::vfs::dentry* dir, const char* filename, mode_t mode, dev_t sn
 int vfs_rmfile(fs::vfs::dentry* dir, const char* filename);
 int vfs_mkdir(fs::vfs::dentry* dir, const char* dirname, mode_t mode);
 int vfs_stat(fs::vfs::dentry* dent, statx* stat, unsigned int mask);
+int vfs_truncate(inode* file, size_t size);
 
 /**
  * @brief Opens a file or directory specified by the given path.

+ 23 - 0
src/kernel/syscall.cpp

@@ -926,6 +926,28 @@ int _syscall_mkdir(interrupt_stack* data)
     return 0;
 }
 
+int _syscall_truncate(interrupt_stack* data)
+{
+    SYSCALL_ARG1(const char* __user, pathname);
+    SYSCALL_ARG2(long, length);
+
+    auto path = types::make_path(pathname, current_process->pwd);
+
+    auto* dent = fs::vfs_open(*current_process->root, path);
+    if (!dent)
+        return -ENOENT;
+
+    if (S_ISDIR(dent->ind->mode))
+        return -EISDIR;
+
+    auto ret = fs::vfs_truncate(dent->ind, length);
+
+    if (ret != GB_OK)
+        return ret;
+
+    return 0;
+}
+
 extern "C" void syscall_entry(
     interrupt_stack* data,
     mmx_registers* mmxregs)
@@ -978,6 +1000,7 @@ void init_syscall(void)
     syscall_handlers[0x42] = _syscall_setsid;
     syscall_handlers[0x4e] = _syscall_gettimeofday;
     syscall_handlers[0x5b] = _syscall_munmap;
+    syscall_handlers[0x5c] = _syscall_truncate;
     syscall_handlers[0x72] = _syscall_wait4;
     syscall_handlers[0x7a] = _syscall_newuname;
     syscall_handlers[0x84] = _syscall_getpgid;

+ 18 - 0
src/kernel/vfs.cpp

@@ -194,6 +194,8 @@ int fs::vfs::inode_stat(dentry*, struct stat*)
 { return -EINVAL; }
 dev_t fs::vfs::inode_devid(fs::inode*)
 { return -EINVAL; }
+int fs::vfs::truncate(inode*, size_t)
+{ return -EINVAL; }
 
 class tmpfs : public virtual fs::vfs {
 private:
@@ -411,6 +413,17 @@ public:
     {
         return as_val(_getdata(file->ino));
     }
+
+    virtual int truncate(fs::inode* file, size_t size) override
+    {
+        if (!S_ISREG(file->mode))
+            return -EINVAL;
+
+        auto* data = as_fdata(_getdata(file->ino));
+        data->resize(size);
+        file->size = size;
+        return GB_OK;
+    }
 };
 
 fs::regular_file::regular_file(vfs::dentry* parent,
@@ -649,6 +662,11 @@ int fs::vfs_stat(fs::vfs::dentry* ent, statx* stat, unsigned int mask)
     return ent->ind->fs->inode_statx(ent, stat, mask);
 }
 
+int fs::vfs_truncate(inode *file, size_t size)
+{
+    return file->fs->truncate(file, size);
+}
+
 static std::list<fs::vfs*, types::memory::ident_allocator<fs::vfs*>> fs_es;
 
 int fs::register_block_device(dev_t node, fs::blkdev_ops ops)