Browse Source

feat(file): append to file

greatbridf 1 year ago
parent
commit
530db35b6a

+ 1 - 0
gblibc/include/errno.h

@@ -25,6 +25,7 @@ extern int* __errno_location(void);
 #define EISDIR 21
 #define EINVAL 22
 #define ENOTTY 25
+#define ESPIPE 29
 #define EPIPE 32
 
 #ifdef __cplusplus

+ 4 - 0
gblibc/include/fcntl.h

@@ -32,6 +32,10 @@
 #define AT_STATX_SYNC_FORCE   0x8000
 #define AT_STATX_DONT_SYNC    0x2000
 
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
 #ifdef __cplusplus
 extern "C" {
 #endif

+ 2 - 0
include/kernel/process.hpp

@@ -174,6 +174,7 @@ public:
                 new fs::fifo_file(nullptr, {
                     .read = 1,
                     .write = 0,
+                    .append = 0,
                 }, ppipe),
         } } );
         assert(inserted);
@@ -187,6 +188,7 @@ public:
                 new fs::fifo_file(nullptr, {
                     .read = 0,
                     .write = 1,
+                    .append = 0,
                 }, ppipe),
         } } );
         assert(inserted);

+ 22 - 4
include/kernel/vfs.hpp

@@ -5,9 +5,10 @@
 #include <vector>
 #include <functional>
 
+#include <errno.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <errno.h>
 #include <bits/alltypes.h>
 
 #include <assert.h>
@@ -270,6 +271,7 @@ struct file {
     struct file_flags {
         uint32_t read : 1;
         uint32_t write : 1;
+        uint32_t append : 1;
     } flags {};
 
     file(mode_t mode, vfs::dentry* parent, file_flags flags)
@@ -278,7 +280,22 @@ struct file {
     virtual ~file() = default;
 
     virtual ssize_t read(char* __user buf, size_t n) = 0;
-    virtual ssize_t write(const char* __user buf, size_t n) = 0;
+    virtual ssize_t do_write(const char* __user buf, size_t n) = 0;
+
+    virtual off_t seek(off_t n, int whence)
+    { return (void)n, (void)whence, -ESPIPE; }
+
+    ssize_t write(const char* __user buf, size_t n)
+    {
+        if (!flags.write)
+            return -EBADF;
+
+        if (flags.append) {
+            seek(0, SEEK_END);
+        }
+
+        return do_write(buf, n);
+    }
 
     // regular files should override this method
     virtual int getdents(char* __user buf, size_t cnt)
@@ -295,7 +312,8 @@ struct regular_file : public virtual file {
     regular_file(vfs::dentry* parent, file_flags flags, size_t cursor, inode* ind);
 
     virtual ssize_t read(char* __user buf, size_t n) override;
-    virtual ssize_t write(const char* __user buf, size_t n) override;
+    virtual ssize_t do_write(const char* __user buf, size_t n) override;
+    virtual off_t seek(off_t n, int whence) override;
     virtual int getdents(char* __user buf, size_t cnt) override;
     virtual int getdents64(char* __user buf, size_t cnt) override;
 };
@@ -307,7 +325,7 @@ struct fifo_file : public virtual file {
     fifo_file(vfs::dentry* parent, file_flags flags, std::shared_ptr<fs::pipe> ppipe);
 
     virtual ssize_t read(char* __user buf, size_t n) override;
-    virtual ssize_t write(const char* __user buf, size_t n) override;
+    virtual ssize_t do_write(const char* __user buf, size_t n) override;
 };
 
 inline fs::vfs::dentry* fs_root;

+ 1 - 0
src/kernel/process.cpp

@@ -198,6 +198,7 @@ int filearr::open(const process &current,
             new fs::regular_file(dentry->parent, {
                 .read = !(flags & O_WRONLY),
                 .write = !!(flags & (O_WRONLY | O_RDWR)),
+                .append = !!(S_ISREG(filemode) && flags & O_APPEND),
             }, 0, dentry->ind),
     } } );
     assert(inserted);

+ 29 - 9
src/kernel/vfs.cpp

@@ -446,12 +446,9 @@ ssize_t fs::regular_file::read(char* __user buf, size_t n)
     return n_wrote;
 }
 
-ssize_t fs::regular_file::write(const char* __user buf, size_t n)
+ssize_t fs::regular_file::do_write(const char* __user buf, size_t n)
 {
-    if (!flags.write)
-        return -EBADF;
-
-    if (S_ISDIR(ind->mode))
+    if (S_ISDIR(mode))
         return -EISDIR;
 
     // TODO: check privilege of user ptr
@@ -462,6 +459,32 @@ ssize_t fs::regular_file::write(const char* __user buf, size_t n)
     return n_wrote;
 }
 
+ssize_t fs::regular_file::seek(off_t n, int whence)
+{
+    if (!S_ISREG(mode))
+        return -ESPIPE;
+
+    size_t pos;
+    switch (whence) {
+    case SEEK_SET:
+        pos = n;
+        break;
+    case SEEK_CUR:
+        pos = cursor + n;
+        break;
+    case SEEK_END:
+        pos = ind->size + n;
+        break;
+    }
+
+    if (pos > ind->size)
+        return -EINVAL;
+
+    cursor = pos;
+
+    return cursor;
+}
+
 int fs::regular_file::getdents(char* __user buf, size_t cnt)
 {
     if (!S_ISDIR(ind->mode))
@@ -545,11 +568,8 @@ ssize_t fs::fifo_file::read(char* __user buf, size_t n)
     return ppipe->read(buf, n);
 }
 
-ssize_t fs::fifo_file::write(const char* __user buf, size_t n)
+ssize_t fs::fifo_file::do_write(const char* __user buf, size_t n)
 {
-    if (!flags.write)
-        return -EBADF;
-
     return ppipe->write(buf, n);
 }