Browse Source

feat(syscall): add sendfile64

greatbridf 1 year ago
parent
commit
8efa4a211a
5 changed files with 43 additions and 33 deletions
  1. 3 0
      gblibc/include/sys/types.h
  2. 1 2
      include/kernel/vfs.hpp
  3. 1 1
      src/fs/fat.cpp
  4. 29 21
      src/kernel/syscall.cpp
  5. 9 9
      src/kernel/vfs.cpp

+ 3 - 0
gblibc/include/sys/types.h

@@ -11,6 +11,9 @@ typedef int pid_t;
 typedef uint32_t ino_t;
 typedef int32_t off_t;
 
+typedef uint64_t ino64_t;
+typedef int64_t off64_t;
+
 #ifdef __cplusplus
 }
 #endif

+ 1 - 2
include/kernel/vfs.hpp

@@ -6,6 +6,7 @@
 #include <functional>
 
 #include <sys/stat.h>
+#include <sys/types.h>
 #include <kernel/errno.h>
 #include <bits/alltypes.h>
 
@@ -39,8 +40,6 @@
 #define DT_MAX (S_DT_MASK + 1) /* 16 */
 
 namespace fs {
-using ino_t = size_t;
-using ino64_t = uint64_t;
 using blksize_t = size_t;
 using blkcnt_t = size_t;
 

+ 1 - 1
src/fs/fat.cpp

@@ -83,7 +83,7 @@ int fat32::inode_readdir(fs::inode* dir, size_t offset, const fs::vfs::filldir_f
                 continue;
             }
 
-            fs::ino_t ino = _rearrange(d);
+            ino_t ino = _rearrange(d);
             auto* ind = get_inode(ino);
             if (!ind) {
                 mode_t mode = 0777;

+ 29 - 21
src/kernel/syscall.cpp

@@ -560,34 +560,42 @@ int _syscall_munmap(interrupt_stack* data)
     kill_current(-1);
 }
 
-int _syscall_sendfile64(interrupt_stack*)
+int _syscall_sendfile64(interrupt_stack* data)
 {
-    not_implemented();
+    SYSCALL_ARG1(int, out_fd);
+    SYSCALL_ARG2(int, in_fd);
+    SYSCALL_ARG3(off64_t*, offset);
+    SYSCALL_ARG4(size_t, count);
 
-    // SYSCALL_ARG1(int, out_fd);
-    // SYSCALL_ARG2(int, in_fd);
-    // SYSCALL_ARG3(off_t*, offset);
-    // SYSCALL_ARG4(size_t, count);
+    auto* out_file = current_process->files[out_fd];
+    auto* in_file = current_process->files[in_fd];
 
-    // auto* out_file = current_process->files[out_fd];
-    // auto* in_file = current_process->files[in_fd];
-
-    // if (!out_file || !in_file)
-    //     return -EBADF;
+    if (!out_file || !in_file)
+        return -EBADF;
 
-    // if (out_file->type != fs::file::types::ind
-    //     || in_file->type != fs::file::types::ind)
-    //     return -EINVAL;
+    // TODO: check whether in_fd supports mmapping (for example,
+    //       whether it is a char device) if not, return -EINVAL
 
-    // if (!out_file->flags.write || !in_file->flags.read)
-    //     return -EBADF;
+    if (offset)
+        not_implemented();
 
-    // if (out_file->ptr.ind->flags.in.directory
-    //     || in_file->ptr.ind->flags.in.directory)
-    //     return -EBADF;
+    constexpr size_t bufsize = 512;
+    std::vector<char> buf(bufsize);
+    size_t totn = 0;
+    while (totn < count) {
+        size_t n = std::min(count - totn, bufsize);
+        ssize_t ret = in_file->read(buf.data(), n);
+        if (ret < 0)
+            return ret;
+        if (ret == 0)
+            break;
+        ret = out_file->write(buf.data(), ret);
+        if (ret < 0)
+            return ret;
+        totn += ret;
+    }
 
-    // if (offset)
-    //     return -EINVAL;
+    return totn;
 }
 
 int _syscall_statx(interrupt_stack* data)

+ 9 - 9
src/kernel/vfs.cpp

@@ -203,11 +203,11 @@ private:
     using fdata_t = std::vector<char>;
 
 private:
-    std::map<fs::ino_t, void*> inode_data;
-    fs::ino_t _next_ino;
+    std::map<ino_t, void*> inode_data;
+    ino_t _next_ino;
 
 private:
-    fs::ino_t _assign_ino(void)
+    ino_t _assign_ino(void)
     {
         return _next_ino++;
     }
@@ -224,17 +224,17 @@ private:
     {
         return std::bit_cast<ptr_t>(data);
     }
-    inline void* _getdata(fs::ino_t ino) const
+    inline void* _getdata(ino_t ino) const
     {
         return inode_data.find(ino)->second;
     }
-    inline fs::ino_t _savedata(void* data)
+    inline ino_t _savedata(void* data)
     {
-        fs::ino_t ino = _assign_ino();
+        ino_t ino = _assign_ino();
         inode_data.insert(std::make_pair(ino, data));
         return ino;
     }
-    inline fs::ino_t _savedata(ptr_t data)
+    inline ino_t _savedata(ptr_t data)
     {
         return _savedata((void*)data);
     }
@@ -463,7 +463,7 @@ int fs::regular_file::getdents(char* __user buf, size_t cnt)
 
     size_t orig_cnt = cnt;
     int nread = ind->fs->inode_readdir(ind, cursor,
-        [&buf, &cnt](const char* fn, size_t len, fs::ino_t ino, uint8_t type) {
+        [&buf, &cnt](const char* fn, size_t len, ino_t ino, uint8_t type) {
             if (!len)
                 len = strlen(fn);
 
@@ -499,7 +499,7 @@ int fs::regular_file::getdents64(char* __user buf, size_t cnt)
 
     size_t orig_cnt = cnt;
     int nread = ind->fs->inode_readdir(ind, cursor,
-        [&buf, &cnt](const char* fn, size_t len, fs::ino_t ino, uint8_t type) {
+        [&buf, &cnt](const char* fn, size_t len, ino_t ino, uint8_t type) {
             if (!len)
                 len = strlen(fn);