Explorar el Código

feat(pipe): send EOF on write end close

greatbridf hace 2 años
padre
commit
760c462f77

+ 1 - 0
include/kernel/errno.h

@@ -27,5 +27,6 @@ extern uint32_t* _get_errno(void);
 #define EPERM (1 << 9)
 #define ESRCH (1 << 10)
 #define EINTR (1 << 11)
+#define EPIPE (1 << 12)
 
 #endif

+ 20 - 2
include/kernel/process.hpp

@@ -165,7 +165,12 @@ public:
         {
             if (iter->ref == 1) {
                 if (iter->type == fs::file::types::pipe) {
-                    iter->ptr.pp->close_one();
+                    assert(iter->flags.read | iter->flags.write);
+                    if (iter->flags.read)
+                        iter->ptr.pp->close_read();
+                    else
+                        iter->ptr.pp->close_write();
+
                     if (iter->ptr.pp->is_free())
                         delete iter->ptr.pp;
                 }
@@ -245,6 +250,10 @@ public:
                 nullptr,
                 0,
                 1,
+                {
+                    .read = 1,
+                    .write = 0,
+                },
             });
             int fd = _next_fd();
             arr.insert(types::make_pair(fd, iter));
@@ -258,6 +267,10 @@ public:
                 nullptr,
                 0,
                 1,
+                {
+                    .read = 0,
+                    .write = 1,
+                },
             });
             fd = _next_fd();
             arr.insert(types::make_pair(fd, iter));
@@ -289,7 +302,12 @@ public:
                 { .ind = dentry->ind },
                 dentry->parent,
                 0,
-                1 });
+                1,
+                {
+                    .read = !!(flags & (O_RDONLY | O_RDWR)),
+                    .write = !!(flags & (O_WRONLY | O_RDWR)),
+                },
+            });
 
             int fd = _next_fd();
             arr.insert(types::make_pair(fd, iter));

+ 40 - 14
include/kernel/vfs.hpp

@@ -220,29 +220,35 @@ public:
 
     void close_read(void)
     {
-        // TODO: lock
-        flags &= (~READABLE);
+        {
+            types::lock_guard lck(m_cv.mtx());
+            flags &= (~READABLE);
+        }
+        m_cv.notify_all();
     }
 
     void close_write(void)
     {
-        // TODO: lock
-        flags &= (~WRITABLE);
+        {
+            types::lock_guard lck(m_cv.mtx());
+            flags &= (~WRITABLE);
+        }
+        m_cv.notify_all();
+    }
+
+    bool is_readable(void) const
+    {
+        return flags & READABLE;
     }
 
-    void close_one(void)
+    bool is_writeable(void) const
     {
-        // TODO: lock
-        if (flags & READABLE)
-            close_read();
-        else
-            close_write();
+        return flags & WRITABLE;
     }
 
     bool is_free(void) const
     {
-        // TODO: lock
-        return (flags & (READABLE | WRITABLE)) == 0;
+        return !(flags & (READABLE | WRITABLE));
     }
 
     int write(const char* buf, size_t n)
@@ -268,15 +274,31 @@ public:
     int read(char* buf, size_t n)
     {
         // TODO: check privilege
-        // TODO: check EPIPE
         {
             auto& mtx = m_cv.mtx();
             types::lock_guard lck(mtx);
 
-            while (this->buf.size() < n)
+            if (!is_writeable()) {
+                size_t orig_n = n;
+                while (!this->buf.empty() && n--)
+                    *(buf++) = this->buf.get();
+
+                return orig_n - n;
+            }
+
+            while (this->buf.size() < n) {
                 if (!m_cv.wait(mtx))
                     return -EINTR;
 
+                if (!is_writeable()) {
+                    size_t orig_n = n;
+                    while (!this->buf.empty() && n--)
+                        *(buf++) = this->buf.get();
+
+                    return orig_n - n;
+                }
+            }
+
             for (size_t i = 0; i < n; ++i)
                 *(buf++) = this->buf.get();
         }
@@ -299,6 +321,10 @@ struct file {
     vfs::dentry* parent;
     size_t cursor;
     size_t ref;
+    struct file_flags {
+        uint32_t read : 1;
+        uint32_t write : 1;
+    } flags;
 };
 
 inline fs::vfs::dentry* fs_root;

+ 3 - 1
src/kernel/process.cpp

@@ -344,7 +344,9 @@ void NORETURN init_scheduler(void)
 
     // init process has no parent
     auto* init = &procs->emplace(0)->value;
-    init->files.open("/dev/console", 0);
+    init->files.open("/dev/console", O_RDONLY);
+    init->files.open("/dev/console", O_WRONLY);
+    init->files.open("/dev/console", O_WRONLY);
 
     // we need interrupts enabled for cow mapping so now we disable it
     // in case timer interrupt mess things up

+ 2 - 2
src/kernel/syscall.cpp

@@ -71,7 +71,7 @@ int _syscall_write(interrupt_stack* data)
 
     auto* file = current_process->files[fd];
 
-    if (!file)
+    if (!file || !file->flags.write)
         return -EBADF;
 
     switch (file->type) {
@@ -103,7 +103,7 @@ int _syscall_read(interrupt_stack* data)
 
     auto* file = current_process->files[fd];
 
-    if (!file)
+    if (!file || !file->flags.read)
         return -EBADF;
 
     switch (file->type) {

+ 5 - 2
user-space-program/sh.c

@@ -35,9 +35,12 @@ char* strchr(const char* str, int c)
 char* gets(char* buf, int bufsize)
 {
     int n = read(STDIN_FILENO, buf, bufsize);
-    if (n > 0 && buf[n-1] == '\n') {
+    if (n > 0) {
+      if (buf[n-1] == '\n')
         buf[n-1] = 0;
-        return buf;
+      else
+        buf[n] = 0;
+      return buf;
     }
     return NULL;
 }