summaryrefslogtreecommitdiff
path: root/src/fs/file.cc
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-01-04 14:12:24 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-01-04 14:12:24 +0800
commita64d25c07b31d57f8706073e11cd774d0880d6dd (patch)
treea4bbae6cff94fa69eea30db865267b211eb4c86b /src/fs/file.cc
parent210025560c80b48af4875af199f183ad709e3bf0 (diff)
parentd3cf3f08d1343d6b265516d5a79ce2d197b59d26 (diff)
downloadlume-a64d25c07b31d57f8706073e11cd774d0880d6dd.tar.gz
lume-a64d25c07b31d57f8706073e11cd774d0880d6dd.tar.xz
Merge pull request #5 from Richard-Qin-001/dev/file-system
feat(file-system): implement read and write FAT32 File System and basic shell
Diffstat (limited to 'src/fs/file.cc')
-rw-r--r--src/fs/file.cc137
1 files changed, 135 insertions, 2 deletions
diff --git a/src/fs/file.cc b/src/fs/file.cc
index 99bb65d..623b535 100644
--- a/src/fs/file.cc
+++ b/src/fs/file.cc
@@ -3,12 +3,135 @@
#include "kernel/mm.h"
#include "drivers/uart.h"
#include "kernel/proc.h"
+#include "kernel/slab.h"
#define NFILE 100
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
+extern void *operator new(unsigned long, void *p);
+
+int Pipe::create_pair(file** f0, file** f1)
+{
+ void *mem = Slab::kmalloc(sizeof(Pipe));
+ if (!mem)
+ return -1;
+ Pipe *pi = new (mem) Pipe();
+
+ *f0 = FileTable::alloc();
+ *f1 = FileTable::alloc();
+
+ if (*f0 == nullptr || *f1 == nullptr)
+ {
+ if (*f0)
+ FileTable::close(*f0);
+ if (*f1)
+ FileTable::close(*f1);
+ pi->~Pipe();
+ Slab::kfree(pi);
+ return -1;
+ }
+
+ (*f0)->type = FD_PIPE;
+ (*f0)->readable = 1;
+ (*f0)->writable = 0;
+ (*f0)->pipe = pi;
+
+ (*f1)->type = FD_PIPE;
+ (*f1)->readable = 0;
+ (*f1)->writable = 1;
+ (*f1)->pipe = pi;
+
+ return 0;
+}
+
+void Pipe::close(bool is_writer)
+{
+ lock.acquire();
+ if (is_writer)
+ {
+ write_open = false;
+ ProcManager::wakeup(&nread); // Wake up the process that is currently reading
+ }
+ else
+ {
+ read_open = false;
+ ProcManager::wakeup(&nwrite); // Wake up the process that is writing
+ }
+
+ bool empty = !read_open && !write_open;
+ lock.release();
+
+ if (empty)
+ {
+ this->~Pipe();
+ Slab::kfree(this);
+ }
+}
+
+int Pipe::write(uint64_t addr, int n)
+{
+ int i = 0;
+ struct Proc *p = myproc();
+
+ lock.acquire();
+ while (i < n)
+ {
+ if (!read_open || p->xstate) // The read end is closed or the process is abnormal
+ {
+ lock.release();
+ return -1;
+ }
+
+ if (nwrite == nread + SIZE) // buffer is full
+ {
+ ProcManager::wakeup(&nread);
+ ProcManager::sleep(&nwrite, &lock);
+ }
+ else
+ {
+ char ch;
+ if (VM::copyin(p->pagetable, &ch, addr + i, 1) < 0)
+ break;
+ data[nwrite++ % SIZE] = ch;
+ i++;
+ }
+ }
+ ProcManager::wakeup(&nread);
+ lock.release();
+ return i;
+}
+
+int Pipe::read(uint64_t addr, int n)
+{
+ int i = 0;
+ struct Proc *p = myproc();
+
+ lock.acquire();
+ while (nread == nwrite && write_open) // The buffer is empty and the write end is not closed
+ {
+ if (p->xstate)
+ {
+ lock.release();
+ return -1;
+ }
+ ProcManager::sleep(&nread, &lock);
+ }
+
+ for (i = 0; i < n; ++i)
+ {
+ if (nread == nwrite)
+ break;
+ char ch = data[nread++ % SIZE];
+ if (VM::copyout(p->pagetable, addr + i, &ch, 1) < 0)
+ break;
+ }
+ ProcManager::wakeup(&nwrite);
+ lock.release();
+ return i;
+}
+
namespace FileTable
{
struct
@@ -82,7 +205,8 @@ namespace FileTable
}
else if (ff.type == FD_PIPE)
{
- // pipeclose(ff.pipe, ff.writable);
+ if (ff.pipe)
+ ff.pipe->close(ff.writable);
}
}
@@ -101,6 +225,11 @@ namespace FileTable
VFS::iunlock(f->ip);
return r;
}
+ else if (f->type == FD_PIPE)
+ {
+ if (f->pipe)
+ return f->pipe->read(addr, n);
+ }
return -1;
}
@@ -119,7 +248,11 @@ namespace FileTable
VFS::iunlock(f->ip);
return r;
}
- // else if (f->type == FD_PIPE) ...
+ else if (f->type == FD_PIPE)
+ {
+ if (f->pipe)
+ return f->pipe->write(addr, n);
+ }
return -1;
}