mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-07-10 23:09:18 +00:00
Update kernel
This commit is contained in:
37
storage/README.md
Normal file
37
storage/README.md
Normal file
@ -0,0 +1,37 @@
|
||||
# File System Implementation
|
||||
|
||||
---
|
||||
|
||||
## Nodes
|
||||
|
||||
### /storage
|
||||
|
||||
- `node.cpp`
|
||||
- **ref_node <=> device**
|
||||
- Handles open/close/read/write operations for the device
|
||||
|
||||
<br>
|
||||
|
||||
- `ref_node.cpp`
|
||||
- **kernel/user <=> node.cpp**
|
||||
- Maintains the count of references to a node and the seek position
|
||||
|
||||
<br>
|
||||
|
||||
- `file_descriptor.cpp`
|
||||
- **user <=> ref_node.cpp**
|
||||
- Manages the file descriptor table for user processes
|
||||
|
||||
<br>
|
||||
|
||||
- `kernel_io.cpp`
|
||||
- **kernel <=> file_descriptor.cpp**
|
||||
- Performs a similar role as `file_descriptor.cpp` but for kernel processes
|
||||
|
||||
### /storage/fs
|
||||
|
||||
This directory contains the implementations of various file systems, such as `fat32.cpp` and `ustar.cpp`.
|
||||
|
||||
### /storage/devices
|
||||
|
||||
This directory houses implementations of various devices, including /dev/null, /dev/zero, /dev/random, and more.
|
164
storage/devices/tty/kcon.cpp
Normal file
164
storage/devices/tty/kcon.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <filesystem/mounts.hpp>
|
||||
#include <filesystem/ioctl.hpp>
|
||||
#include <smp.hpp>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
size_t KConDevice::read(uint8_t *Buffer, size_t Size, off_t Offset)
|
||||
{
|
||||
return DriverManager->InputKeyboardDev->read(Buffer, Size, Offset);
|
||||
}
|
||||
|
||||
size_t KConDevice::write(uint8_t *Buffer, size_t Size, off_t Offset)
|
||||
{
|
||||
if (Offset != 0)
|
||||
fixme("Offset is %d", Offset);
|
||||
|
||||
for (size_t i = 0; i < Size; i++)
|
||||
putchar(((char *)Buffer)[i]);
|
||||
|
||||
if (!Config.Quiet)
|
||||
Display->SetBuffer(0);
|
||||
return Size;
|
||||
}
|
||||
|
||||
int KConDevice::ioctl(unsigned long Request, void *Argp)
|
||||
{
|
||||
static_assert(sizeof(struct termios) < PAGE_SIZE);
|
||||
|
||||
void *pArgp = thisProcess->PageTable->Get(Argp);
|
||||
switch (Request)
|
||||
{
|
||||
case TCGETS:
|
||||
{
|
||||
struct termios *t = (struct termios *)pArgp;
|
||||
memcpy(t, &this->term, sizeof(struct termios));
|
||||
break;
|
||||
}
|
||||
case TCSETS:
|
||||
{
|
||||
struct termios *t = (struct termios *)pArgp;
|
||||
memcpy(&this->term, t, sizeof(struct termios));
|
||||
break;
|
||||
}
|
||||
case TCSETSW:
|
||||
case TCSETSF:
|
||||
case TCGETA:
|
||||
case TCSETA:
|
||||
case TCSETAW:
|
||||
case TCSETAF:
|
||||
case TCSBRK:
|
||||
case TCXONC:
|
||||
case TCFLSH:
|
||||
case TIOCEXCL:
|
||||
case TIOCNXCL:
|
||||
case TIOCSCTTY:
|
||||
case TIOCGPGRP:
|
||||
case TIOCSPGRP:
|
||||
case TIOCOUTQ:
|
||||
case TIOCSTI:
|
||||
{
|
||||
fixme("ioctl %#lx not implemented", Request);
|
||||
return -ENOSYS;
|
||||
}
|
||||
case TIOCGWINSZ:
|
||||
{
|
||||
struct winsize *ws = (struct winsize *)pArgp;
|
||||
memcpy(ws, &this->termSize, sizeof(struct winsize));
|
||||
break;
|
||||
}
|
||||
case TIOCSWINSZ:
|
||||
{
|
||||
struct winsize *ws = (struct winsize *)pArgp;
|
||||
memcpy(&this->termSize, ws, sizeof(struct winsize));
|
||||
break;
|
||||
}
|
||||
case TIOCMGET:
|
||||
case TIOCMBIS:
|
||||
case TIOCMBIC:
|
||||
case TIOCMSET:
|
||||
{
|
||||
fixme("ioctl %#lx not implemented", Request);
|
||||
return -ENOSYS;
|
||||
}
|
||||
case TIOCGPTN:
|
||||
case 0xffffffff80045430: /* FIXME: ???? */
|
||||
{
|
||||
int *n = (int *)pArgp;
|
||||
*n = -1;
|
||||
break;
|
||||
}
|
||||
case TIOCSPTLCK:
|
||||
{
|
||||
int *n = (int *)pArgp;
|
||||
*n = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
debug("Unknown ioctl %#lx", Request);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
KConDevice::KConDevice() : Node(DevFS, "kcon", CHARDEVICE)
|
||||
{
|
||||
/*
|
||||
- ICRNL - Map Carriage Return to New Line
|
||||
- IXON - Enable XON/XOFF flow control
|
||||
|
||||
- OPOST - Enable output processing
|
||||
- ONLCR - Map New Line to Carriage Return - New Line
|
||||
|
||||
- CS8 - 8-bit characters
|
||||
- CREAD - Enable receiver
|
||||
- HUPCL - Hang up on last close
|
||||
|
||||
- ECHO - Echo input characters
|
||||
- ICANON - Enable canonical input (enable line editing)
|
||||
*/
|
||||
this->term.c_iflag = /*ICRNL |*/ IXON;
|
||||
this->term.c_oflag = OPOST | ONLCR;
|
||||
this->term.c_cflag = CS8 | CREAD | HUPCL;
|
||||
this->term.c_lflag = ECHO | ICANON;
|
||||
this->term.c_cc[VEOF] = 0x04; /* ^D */
|
||||
this->term.c_cc[VEOL] = 0x00; /* NUL */
|
||||
this->term.c_cc[VERASE] = 0x7f; /* DEL */
|
||||
this->term.c_cc[VINTR] = 0x03; /* ^C */
|
||||
this->term.c_cc[VKILL] = 0x15; /* ^U */
|
||||
this->term.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */
|
||||
this->term.c_cc[VQUIT] = 0x1c; /* ^\ */
|
||||
this->term.c_cc[VSTART] = 0x11; /* ^Q */
|
||||
this->term.c_cc[VSTOP] = 0x13; /* ^S */
|
||||
this->term.c_cc[VSUSP] = 0x1a; /* ^Z */
|
||||
this->term.c_cc[VTIME] = 0; /* Timeout for non-canonical read */
|
||||
this->term.c_cc[VWERASE] = 0x17; /* ^W */
|
||||
}
|
||||
|
||||
KConDevice::~KConDevice()
|
||||
{
|
||||
}
|
||||
}
|
92
storage/devices/tty/ptmx.cpp
Normal file
92
storage/devices/tty/ptmx.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <filesystem/mounts.hpp>
|
||||
#include <filesystem/ioctl.hpp>
|
||||
#include <smp.hpp>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
int PTMXDevice::open(int Flags, mode_t Mode)
|
||||
{
|
||||
SmartLock(PTMXLock);
|
||||
int id = -1;
|
||||
for (size_t i = 0; i < ptysId.Size; i++)
|
||||
{
|
||||
if (unlikely(ptysId.Buffer[i] == false))
|
||||
{
|
||||
id = int(i);
|
||||
ptysId.Buffer[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (id == -1)
|
||||
return -ENFILE;
|
||||
|
||||
PTYDevice *pty = new PTYDevice(pts, id);
|
||||
ptysList.push_back(pty);
|
||||
return pty->OpenMaster(Flags, Mode);
|
||||
}
|
||||
|
||||
void PTMXDevice::RemovePTY(int fd, Tasking::PCB *pcb)
|
||||
{
|
||||
SmartLock(PTMXLock);
|
||||
if (!pcb)
|
||||
pcb = thisProcess;
|
||||
assert(pcb != nullptr);
|
||||
|
||||
FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
RefNode *node = fdt->GetRefNode(fd);
|
||||
|
||||
assert(node->SpecialData != nullptr);
|
||||
PTYDevice *pty = (PTYDevice *)node->SpecialData;
|
||||
int id = pty->ptyId;
|
||||
|
||||
forItr(itr, ptysList)
|
||||
{
|
||||
if (*itr != pty)
|
||||
continue;
|
||||
|
||||
ptysList.erase(itr);
|
||||
delete *itr;
|
||||
break;
|
||||
}
|
||||
ptysId.Buffer[id] = false;
|
||||
}
|
||||
|
||||
PTMXDevice::PTMXDevice() : Node(DevFS, "ptmx", CHARDEVICE)
|
||||
{
|
||||
this->Mode = 0644;
|
||||
this->UserIdentifier = 0;
|
||||
this->GroupIdentifier = 0;
|
||||
pts = new Node(DevFS, "pts", DIRECTORY);
|
||||
|
||||
ptysId.Buffer = new uint8_t[0x1000];
|
||||
ptysId.Size = 0x1000;
|
||||
}
|
||||
|
||||
PTMXDevice::~PTMXDevice()
|
||||
{
|
||||
SmartLock(PTMXLock);
|
||||
delete pts;
|
||||
delete[] ptysId.Buffer;
|
||||
}
|
||||
}
|
213
storage/devices/tty/pty.cpp
Normal file
213
storage/devices/tty/pty.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <filesystem/mounts.hpp>
|
||||
#include <filesystem/ioctl.hpp>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
int PTYDevice::open(int Flags, mode_t Mode)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int PTYDevice::close()
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
size_t PTYDevice::read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
if (this->isMaster)
|
||||
{
|
||||
if (MasterDev != nullptr)
|
||||
return MasterDev->read(Buffer, Size, Offset);
|
||||
else
|
||||
fixme("MasterDev is nullptr");
|
||||
}
|
||||
|
||||
if (this->SlaveDev == nullptr)
|
||||
{
|
||||
fixme("SlaveDev is nullptr");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SlaveDev->read(Buffer, Size, Offset);
|
||||
}
|
||||
|
||||
size_t PTYDevice::write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
if (this->isMaster)
|
||||
{
|
||||
if (MasterDev != nullptr)
|
||||
return MasterDev->write(Buffer, Size, Offset);
|
||||
else
|
||||
fixme("MasterDev is nullptr");
|
||||
}
|
||||
|
||||
if (this->SlaveDev == nullptr)
|
||||
{
|
||||
fixme("SlaveDev is nullptr");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SlaveDev->write(Buffer, Size, Offset);
|
||||
}
|
||||
|
||||
int PTYDevice::ioctl(unsigned long Request,
|
||||
void *Argp)
|
||||
{
|
||||
static_assert(sizeof(struct termios) < PAGE_SIZE);
|
||||
void *pArgp = thisProcess->PageTable->Get(Argp);
|
||||
|
||||
switch (Request)
|
||||
{
|
||||
case TCGETS:
|
||||
{
|
||||
struct termios *t = (struct termios *)pArgp;
|
||||
memcpy(t, &this->term, sizeof(struct termios));
|
||||
break;
|
||||
}
|
||||
case TCSETS:
|
||||
{
|
||||
struct termios *t = (struct termios *)pArgp;
|
||||
memcpy(&this->term, t, sizeof(struct termios));
|
||||
break;
|
||||
}
|
||||
case TCSETSW:
|
||||
case TCSETSF:
|
||||
case TCGETA:
|
||||
case TCSETA:
|
||||
case TCSETAW:
|
||||
case TCSETAF:
|
||||
case TCSBRK:
|
||||
case TCXONC:
|
||||
case TCFLSH:
|
||||
case TIOCEXCL:
|
||||
case TIOCNXCL:
|
||||
case TIOCSCTTY:
|
||||
case TIOCGPGRP:
|
||||
case TIOCSPGRP:
|
||||
case TIOCOUTQ:
|
||||
case TIOCSTI:
|
||||
{
|
||||
fixme("ioctl %#lx not implemented", Request);
|
||||
return -ENOSYS;
|
||||
}
|
||||
case TIOCGWINSZ:
|
||||
{
|
||||
struct winsize *ws = (struct winsize *)pArgp;
|
||||
memcpy(ws, &this->termSize, sizeof(struct winsize));
|
||||
break;
|
||||
}
|
||||
case TIOCSWINSZ:
|
||||
{
|
||||
struct winsize *ws = (struct winsize *)pArgp;
|
||||
memcpy(&this->termSize, ws, sizeof(struct winsize));
|
||||
break;
|
||||
}
|
||||
case TIOCMGET:
|
||||
case TIOCMBIS:
|
||||
case TIOCMBIC:
|
||||
case TIOCMSET:
|
||||
{
|
||||
fixme("ioctl %#lx not implemented", Request);
|
||||
return -ENOSYS;
|
||||
}
|
||||
case TIOCGPTN:
|
||||
case 0xffffffff80045430: /* FIXME: ???? */
|
||||
{
|
||||
int *n = (int *)pArgp;
|
||||
*n = this->id;
|
||||
break;
|
||||
}
|
||||
case TIOCSPTLCK:
|
||||
{
|
||||
int *n = (int *)pArgp;
|
||||
*n = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
debug("Unknown ioctl %#lx", Request);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PTYDevice::OpenMaster(int Flags, mode_t Mode)
|
||||
{
|
||||
debug("Opening master PTY device %s", this->FullPath);
|
||||
FileDescriptorTable *fdt = thisProcess->FileDescriptors;
|
||||
int rfd = fdt->_open(this->FullPath, Flags, Mode);
|
||||
debug("Opened master PTY device %s with fd %d",
|
||||
this->FullPath, rfd);
|
||||
return rfd;
|
||||
}
|
||||
|
||||
PTYDevice::PTYDevice(Node *pts, int id) : Node(pts,
|
||||
std::to_string(id),
|
||||
CHARDEVICE)
|
||||
{
|
||||
/*
|
||||
- ICRNL - Map Carriage Return to New Line
|
||||
- IXON - Enable XON/XOFF flow control
|
||||
|
||||
- OPOST - Enable output processing
|
||||
- ONLCR - Map New Line to Carriage Return - New Line
|
||||
|
||||
- CS8 - 8-bit characters
|
||||
- CREAD - Enable receiver
|
||||
- HUPCL - Hang up on last close
|
||||
|
||||
- ECHO - Echo input characters
|
||||
- ICANON - Enable canonical input (enable line editing)
|
||||
*/
|
||||
this->term.c_iflag = /*ICRNL |*/ IXON;
|
||||
this->term.c_oflag = OPOST | ONLCR;
|
||||
this->term.c_cflag = CS8 | CREAD | HUPCL;
|
||||
this->term.c_lflag = ECHO | ICANON;
|
||||
this->term.c_cc[VEOF] = 0x04; /* ^D */
|
||||
this->term.c_cc[VEOL] = 0x00; /* NUL */
|
||||
this->term.c_cc[VERASE] = 0x7f; /* DEL */
|
||||
this->term.c_cc[VINTR] = 0x03; /* ^C */
|
||||
this->term.c_cc[VKILL] = 0x15; /* ^U */
|
||||
this->term.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */
|
||||
this->term.c_cc[VQUIT] = 0x1c; /* ^\ */
|
||||
this->term.c_cc[VSTART] = 0x11; /* ^Q */
|
||||
this->term.c_cc[VSTOP] = 0x13; /* ^S */
|
||||
this->term.c_cc[VSUSP] = 0x1a; /* ^Z */
|
||||
this->term.c_cc[VTIME] = 0; /* Timeout for non-canonical read */
|
||||
this->term.c_cc[VWERASE] = 0x17; /* ^W */
|
||||
|
||||
debug("Created PTY device %s", FullPath);
|
||||
}
|
||||
|
||||
PTYDevice::~PTYDevice() {}
|
||||
}
|
@ -17,33 +17,34 @@
|
||||
|
||||
#include <filesystem/mounts.hpp>
|
||||
#include <filesystem/ioctl.hpp>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../../kernel.h"
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
size_t PTMXDevice::read(uint8_t *Buffer, size_t Size, off_t Offset)
|
||||
size_t MasterPTY::read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
if (Size <= 0)
|
||||
return 0;
|
||||
|
||||
memset(Buffer, 0, Size);
|
||||
return Size;
|
||||
fixme("%.*s", Size, Buffer);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
size_t PTMXDevice::write(uint8_t *Buffer, size_t Size, off_t Offset)
|
||||
size_t MasterPTY::write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
return Size;
|
||||
fixme("%.*s", Size, Buffer);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
PTMXDevice::PTMXDevice() : Node(DevFS, "null", CHARDEVICE)
|
||||
MasterPTY::MasterPTY()
|
||||
{
|
||||
pts = new Node(DevFS, "pts", DIRECTORY);
|
||||
}
|
||||
|
||||
PTMXDevice::~PTMXDevice()
|
||||
MasterPTY::~MasterPTY()
|
||||
{
|
||||
delete pts;
|
||||
}
|
||||
}
|
50
storage/devices/tty/ptys.cpp
Normal file
50
storage/devices/tty/ptys.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <filesystem/mounts.hpp>
|
||||
#include <filesystem/ioctl.hpp>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
size_t SlavePTY::read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
fixme("%.*s", Size, Buffer);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
size_t SlavePTY::write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
fixme("%.*s", Size, Buffer);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
SlavePTY::SlavePTY()
|
||||
{
|
||||
}
|
||||
|
||||
SlavePTY::~SlavePTY()
|
||||
{
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
#include <filesystem/ioctl.hpp>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../../kernel.h"
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
@ -57,5 +57,6 @@ namespace vfs
|
||||
}
|
||||
|
||||
TTYDevice::TTYDevice() : Node(DevFS, "tty", CHARDEVICE) {}
|
||||
|
||||
TTYDevice::~TTYDevice() {}
|
||||
}
|
@ -68,10 +68,10 @@ namespace vfs
|
||||
// // .Write = fd_Write,
|
||||
// };
|
||||
|
||||
FileDescriptorTable::Fildes
|
||||
FileDescriptorTable::Fildes &
|
||||
FileDescriptorTable::GetFileDescriptor(int FileDescriptor)
|
||||
{
|
||||
foreach (auto fd in FileDescriptors)
|
||||
foreach (auto &fd in FileDescriptors)
|
||||
{
|
||||
if (fd.Descriptor == FileDescriptor)
|
||||
{
|
||||
@ -79,13 +79,13 @@ namespace vfs
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
return nullfd;
|
||||
}
|
||||
|
||||
FileDescriptorTable::DupFildes
|
||||
FileDescriptorTable::Fildes &
|
||||
FileDescriptorTable::GetDupFildes(int FileDescriptor)
|
||||
{
|
||||
foreach (auto fd in FildesDuplicates)
|
||||
foreach (auto &fd in FildesDuplicates)
|
||||
{
|
||||
if (fd.Descriptor == FileDescriptor)
|
||||
{
|
||||
@ -93,7 +93,48 @@ namespace vfs
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
return nullfd;
|
||||
}
|
||||
|
||||
FileDescriptorTable::Fildes &
|
||||
FileDescriptorTable::GetDescriptor(int FileDescriptor)
|
||||
{
|
||||
Fildes &fd = this->GetFileDescriptor(FileDescriptor);
|
||||
Fildes &dfd = this->GetDupFildes(FileDescriptor);
|
||||
|
||||
if (fd.Descriptor == -1 &&
|
||||
dfd.Descriptor == -1)
|
||||
return nullfd;
|
||||
|
||||
if (fd.Descriptor != -1)
|
||||
return fd;
|
||||
else
|
||||
return dfd;
|
||||
}
|
||||
|
||||
int FileDescriptorTable::GetFlags(int FileDescriptor)
|
||||
{
|
||||
Fildes &fd = this->GetDescriptor(FileDescriptor);
|
||||
if (fd == nullfd)
|
||||
{
|
||||
debug("invalid fd %d", FileDescriptor);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
return fd.Flags;
|
||||
}
|
||||
|
||||
int FileDescriptorTable::SetFlags(int FileDescriptor, int Flags)
|
||||
{
|
||||
Fildes &fd = this->GetDescriptor(FileDescriptor);
|
||||
if (fd == nullfd)
|
||||
{
|
||||
debug("invalid fd %d", FileDescriptor);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
fd.Flags = Flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileDescriptorTable::ProbeMode(mode_t Mode, int Flags)
|
||||
@ -143,12 +184,12 @@ namespace vfs
|
||||
if (Flags & O_CREAT)
|
||||
{
|
||||
int ret;
|
||||
Node *n = new Node(pcb->CurrentWorkingDirectory,
|
||||
AbsolutePath,
|
||||
NodeType::FILE,
|
||||
cwk_path_is_absolute(AbsolutePath),
|
||||
fs,
|
||||
&ret);
|
||||
new Node(pcb->CurrentWorkingDirectory,
|
||||
AbsolutePath,
|
||||
NodeType::FILE,
|
||||
cwk_path_is_absolute(AbsolutePath),
|
||||
fs,
|
||||
&ret);
|
||||
|
||||
if (ret == -EEXIST)
|
||||
{
|
||||
@ -159,7 +200,7 @@ namespace vfs
|
||||
{
|
||||
error("Failed to create file %s: %d",
|
||||
AbsolutePath, ret);
|
||||
assert(false);
|
||||
assert(ret < 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,6 +215,7 @@ namespace vfs
|
||||
AbsolutePath);
|
||||
return -EIO;
|
||||
}
|
||||
delete File;
|
||||
}
|
||||
|
||||
if (Flags & O_TRUNC)
|
||||
@ -213,15 +255,14 @@ namespace vfs
|
||||
FileDescriptors.push_back(fd);
|
||||
|
||||
char FileName[64];
|
||||
sprintf(FileName, "%d", fd.Descriptor);
|
||||
vfs::Node *n = fs->Create(FileName, vfs::NodeType::FILE, this->fdDir);
|
||||
if (n)
|
||||
{
|
||||
/* FIXME: Implement proper file descriptors */
|
||||
n->Size = File->FileSize;
|
||||
}
|
||||
itoa(fd.Descriptor, FileName, 10);
|
||||
assert(fs->CreateLink(FileName, AbsolutePath, this->fdDir) != nullptr);
|
||||
|
||||
return fd.Descriptor;
|
||||
int rfd = File->node->open(Flags, Mode);
|
||||
if (rfd <= 0)
|
||||
return fd.Descriptor;
|
||||
else
|
||||
return rfd;
|
||||
}
|
||||
|
||||
int FileDescriptorTable::RemoveFileDescriptor(int FileDescriptor)
|
||||
@ -233,7 +274,7 @@ namespace vfs
|
||||
FileDescriptors.erase(itr);
|
||||
|
||||
char FileName[64];
|
||||
sprintf(FileName, "%d", FileDescriptor);
|
||||
itoa(FileDescriptor, FileName, 10);
|
||||
fs->Delete(FileName, false, this->fdDir);
|
||||
return 0;
|
||||
}
|
||||
@ -246,7 +287,7 @@ namespace vfs
|
||||
FildesDuplicates.erase(itr);
|
||||
|
||||
char FileName[64];
|
||||
sprintf(FileName, "%d", FileDescriptor);
|
||||
itoa(FileDescriptor, FileName, 10);
|
||||
fs->Delete(FileName, false, this->fdDir);
|
||||
return 0;
|
||||
}
|
||||
@ -292,25 +333,58 @@ namespace vfs
|
||||
|
||||
const char *FileDescriptorTable::GetAbsolutePath(int FileDescriptor)
|
||||
{
|
||||
Fildes fd = this->GetFileDescriptor(FileDescriptor);
|
||||
DupFildes dfd = this->GetDupFildes(FileDescriptor);
|
||||
|
||||
if (fd.Descriptor == -1 &&
|
||||
dfd.Descriptor == -1)
|
||||
Fildes &fd = this->GetDescriptor(FileDescriptor);
|
||||
if (fd == nullfd)
|
||||
return "";
|
||||
|
||||
RefNode *hnd = nullptr;
|
||||
if (fd.Descriptor != -1)
|
||||
hnd = fd.Handle;
|
||||
else
|
||||
hnd = dfd.Handle;
|
||||
|
||||
Node *node = hnd->node;
|
||||
Node *node = fd.Handle->node;
|
||||
const char *path = new char[strlen(node->FullPath) + 1];
|
||||
strcpy((char *)path, node->FullPath);
|
||||
return path;
|
||||
}
|
||||
|
||||
RefNode *FileDescriptorTable::GetRefNode(int FileDescriptor)
|
||||
{
|
||||
Fildes &fd = this->GetDescriptor(FileDescriptor);
|
||||
if (fd == nullfd)
|
||||
return nullptr;
|
||||
|
||||
return fd.Handle;
|
||||
}
|
||||
|
||||
void FileDescriptorTable::Fork(FileDescriptorTable *Parent)
|
||||
{
|
||||
foreach (auto &fd in Parent->FileDescriptors)
|
||||
{
|
||||
debug("Forking fd: %d", fd.Descriptor);
|
||||
RefNode *node = fs->Open(fd.Handle->node->FullPath,
|
||||
thisProcess->CurrentWorkingDirectory);
|
||||
assert(node != nullptr);
|
||||
|
||||
Fildes new_fd;
|
||||
new_fd.Descriptor = fd.Descriptor;
|
||||
new_fd.Flags = fd.Flags;
|
||||
new_fd.Mode = fd.Mode;
|
||||
new_fd.Handle = node;
|
||||
this->FileDescriptors.push_back(new_fd);
|
||||
}
|
||||
|
||||
foreach (auto &fd in Parent->FildesDuplicates)
|
||||
{
|
||||
debug("Forking duplicated fd: %d", fd.Descriptor);
|
||||
RefNode *node = fs->Open(fd.Handle->node->FullPath,
|
||||
thisProcess->CurrentWorkingDirectory);
|
||||
assert(node != nullptr);
|
||||
|
||||
Fildes new_fd;
|
||||
new_fd.Descriptor = fd.Descriptor;
|
||||
new_fd.Flags = fd.Flags;
|
||||
new_fd.Mode = fd.Mode;
|
||||
new_fd.Handle = node;
|
||||
this->FildesDuplicates.push_back(new_fd);
|
||||
}
|
||||
}
|
||||
|
||||
int FileDescriptorTable::_open(const char *pathname, int flags,
|
||||
mode_t mode)
|
||||
{
|
||||
@ -325,84 +399,50 @@ namespace vfs
|
||||
return _open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);
|
||||
}
|
||||
|
||||
ssize_t FileDescriptorTable::_read(int fd, void *buf, size_t count)
|
||||
ssize_t FileDescriptorTable::_read(int _fd, void *buf, size_t count)
|
||||
{
|
||||
Fildes fdesc = this->GetFileDescriptor(fd);
|
||||
DupFildes dfdesc = this->GetDupFildes(fd);
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
Fildes &fd = this->GetDescriptor(_fd);
|
||||
if (fd == nullfd)
|
||||
{
|
||||
debug("invalid fd %d", _fd);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
RefNode *hnd = nullptr;
|
||||
if (fdesc.Descriptor != -1)
|
||||
hnd = fdesc.Handle;
|
||||
else
|
||||
hnd = dfdesc.Handle;
|
||||
|
||||
return hnd->read((uint8_t *)buf, count);
|
||||
return fd.Handle->read((uint8_t *)buf, count);
|
||||
}
|
||||
|
||||
ssize_t FileDescriptorTable::_write(int fd, const void *buf,
|
||||
ssize_t FileDescriptorTable::_write(int _fd, const void *buf,
|
||||
size_t count)
|
||||
{
|
||||
Fildes fdesc = this->GetFileDescriptor(fd);
|
||||
DupFildes dfdesc = this->GetDupFildes(fd);
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
Fildes &fd = this->GetDescriptor(_fd);
|
||||
if (fd == nullfd)
|
||||
{
|
||||
debug("invalid fd %d", _fd);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
RefNode *hnd = nullptr;
|
||||
if (fdesc.Descriptor != -1)
|
||||
hnd = fdesc.Handle;
|
||||
else
|
||||
hnd = dfdesc.Handle;
|
||||
|
||||
return hnd->write((uint8_t *)buf, count);
|
||||
return fd.Handle->write((uint8_t *)buf, count);
|
||||
}
|
||||
|
||||
int FileDescriptorTable::_close(int fd)
|
||||
int FileDescriptorTable::_close(int _fd)
|
||||
{
|
||||
Fildes fdesc = this->GetFileDescriptor(fd);
|
||||
DupFildes dfdesc = this->GetDupFildes(fd);
|
||||
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
Fildes &fd = this->GetDescriptor(_fd);
|
||||
if (fd == nullfd)
|
||||
{
|
||||
debug("invalid fd %d", _fd);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (RemoveFileDescriptor(fd) < 0)
|
||||
if (RemoveFileDescriptor(_fd) < 0)
|
||||
{
|
||||
debug("invalid fd %d", _fd);
|
||||
return -EBADF;
|
||||
|
||||
/* If the file descriptor is a duplicate,
|
||||
we don't need to close the handle,
|
||||
because it's a duplicate of another
|
||||
file descriptor. */
|
||||
}
|
||||
|
||||
bool Found = false;
|
||||
RefNode *hnd = nullptr;
|
||||
|
||||
if (fdesc.Descriptor != -1)
|
||||
hnd = fdesc.Handle;
|
||||
else
|
||||
hnd = dfdesc.Handle;
|
||||
|
||||
foreach (auto dfd in FileDescriptors)
|
||||
{
|
||||
if (dfd.Handle == hnd)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (auto dfd in FildesDuplicates)
|
||||
{
|
||||
if (dfd.Handle == hnd)
|
||||
if (dfd.Handle == fd.Handle)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
@ -410,28 +450,34 @@ namespace vfs
|
||||
}
|
||||
|
||||
if (!Found)
|
||||
delete hnd;
|
||||
foreach (auto dfd in FildesDuplicates)
|
||||
{
|
||||
if (dfd.Handle == fd.Handle)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the file descriptor is a duplicate,
|
||||
we don't need to close the handle,
|
||||
because it's a duplicate of another
|
||||
file descriptor. */
|
||||
if (!Found)
|
||||
delete fd.Handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
off_t FileDescriptorTable::_lseek(int fd, off_t offset, int whence)
|
||||
off_t FileDescriptorTable::_lseek(int _fd, off_t offset, int whence)
|
||||
{
|
||||
Fildes fdesc = this->GetFileDescriptor(fd);
|
||||
DupFildes dfdesc = this->GetDupFildes(fd);
|
||||
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
Fildes &fd = this->GetDescriptor(_fd);
|
||||
if (fd == nullfd)
|
||||
{
|
||||
debug("invalid fd %d", _fd);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
RefNode *hnd = nullptr;
|
||||
if (fdesc.Descriptor != -1)
|
||||
hnd = fdesc.Handle;
|
||||
else
|
||||
hnd = dfdesc.Handle;
|
||||
|
||||
return hnd->seek(offset, whence);
|
||||
return fd.Handle->seek(offset, whence);
|
||||
}
|
||||
|
||||
int FileDescriptorTable::_stat(const char *pathname,
|
||||
@ -465,24 +511,16 @@ namespace vfs
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FileDescriptorTable::_fstat(int fd, struct stat *statbuf)
|
||||
int FileDescriptorTable::_fstat(int _fd, struct stat *statbuf)
|
||||
{
|
||||
Fildes fdesc = this->GetFileDescriptor(fd);
|
||||
DupFildes dfdesc = this->GetDupFildes(fd);
|
||||
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
Fildes &fd = this->GetDescriptor(_fd);
|
||||
if (fd == nullfd)
|
||||
{
|
||||
debug("invalid fd %d", _fd);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
RefNode *hnd = nullptr;
|
||||
if (fdesc.Descriptor != -1)
|
||||
hnd = fdesc.Handle;
|
||||
else
|
||||
hnd = dfdesc.Handle;
|
||||
|
||||
Node *node = hnd->node;
|
||||
Node *node = fd.Handle->node;
|
||||
statbuf->st_dev = 0; /* FIXME: stub */
|
||||
statbuf->st_ino = node->IndexNode;
|
||||
statbuf->st_mode = node->Type | node->Mode;
|
||||
@ -530,12 +568,10 @@ namespace vfs
|
||||
|
||||
int FileDescriptorTable::_dup(int oldfd)
|
||||
{
|
||||
Fildes fdesc = this->GetFileDescriptor(oldfd);
|
||||
DupFildes dfdesc = this->GetDupFildes(oldfd);
|
||||
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
Fildes &fd = this->GetDescriptor(oldfd);
|
||||
if (fd == nullfd)
|
||||
{
|
||||
debug("invalid fd %d", oldfd);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
@ -543,17 +579,9 @@ namespace vfs
|
||||
if (newfd < 0)
|
||||
return -EMFILE;
|
||||
|
||||
DupFildes new_dfd{};
|
||||
if (fdesc.Descriptor != -1)
|
||||
{
|
||||
new_dfd.Handle = fdesc.Handle;
|
||||
new_dfd.Mode = fdesc.Mode;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_dfd.Handle = dfdesc.Handle;
|
||||
new_dfd.Mode = dfdesc.Mode;
|
||||
}
|
||||
Fildes new_dfd{};
|
||||
new_dfd.Handle = fd.Handle;
|
||||
new_dfd.Mode = fd.Mode;
|
||||
|
||||
new_dfd.Descriptor = newfd;
|
||||
this->FildesDuplicates.push_back(new_dfd);
|
||||
@ -564,17 +592,18 @@ namespace vfs
|
||||
|
||||
int FileDescriptorTable::_dup2(int oldfd, int newfd)
|
||||
{
|
||||
Fildes fdesc = this->GetFileDescriptor(oldfd);
|
||||
DupFildes dfdesc = this->GetDupFildes(oldfd);
|
||||
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
Fildes &fd = this->GetDescriptor(oldfd);
|
||||
if (fd == nullfd)
|
||||
{
|
||||
debug("invalid fd %d", oldfd);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (newfd < 0)
|
||||
{
|
||||
debug("invalid fd %d", newfd);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (newfd == oldfd)
|
||||
return newfd;
|
||||
@ -583,17 +612,9 @@ namespace vfs
|
||||
we ignore it. */
|
||||
this->_close(newfd);
|
||||
|
||||
DupFildes new_dfd{};
|
||||
if (fdesc.Descriptor != -1)
|
||||
{
|
||||
new_dfd.Handle = fdesc.Handle;
|
||||
new_dfd.Mode = fdesc.Mode;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_dfd.Handle = dfdesc.Handle;
|
||||
new_dfd.Mode = dfdesc.Mode;
|
||||
}
|
||||
Fildes new_dfd{};
|
||||
new_dfd.Handle = fd.Handle;
|
||||
new_dfd.Mode = fd.Mode;
|
||||
|
||||
new_dfd.Descriptor = newfd;
|
||||
this->FildesDuplicates.push_back(new_dfd);
|
||||
@ -602,39 +623,31 @@ namespace vfs
|
||||
return newfd;
|
||||
}
|
||||
|
||||
int FileDescriptorTable::_ioctl(int fd, unsigned long request, void *argp)
|
||||
int FileDescriptorTable::_ioctl(int _fd, unsigned long request, void *argp)
|
||||
{
|
||||
Fildes fdesc = this->GetFileDescriptor(fd);
|
||||
DupFildes dfdesc = this->GetDupFildes(fd);
|
||||
if (fdesc.Descriptor < 0 &&
|
||||
dfdesc.Descriptor < 0)
|
||||
Fildes &fd = this->GetDescriptor(_fd);
|
||||
if (fd == nullfd)
|
||||
{
|
||||
debug("invalid fd %d", _fd);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
RefNode *hnd = nullptr;
|
||||
if (fdesc.Descriptor != -1)
|
||||
hnd = fdesc.Handle;
|
||||
else
|
||||
hnd = dfdesc.Handle;
|
||||
|
||||
return hnd->ioctl(request, argp);
|
||||
return fd.Handle->ioctl(request, argp);
|
||||
}
|
||||
|
||||
FileDescriptorTable::FileDescriptorTable(void *Owner)
|
||||
{
|
||||
debug("+ %#lx", this);
|
||||
this->fdDir = fs->Create("fd", vfs::NodeType::DIRECTORY,
|
||||
((Tasking::PCB *)Owner)->ProcessDirectory);
|
||||
((Tasking::PCB *)Owner));
|
||||
}
|
||||
|
||||
FileDescriptorTable::~FileDescriptorTable()
|
||||
{
|
||||
debug("- %#lx", this);
|
||||
foreach (auto fd in FileDescriptors)
|
||||
foreach (auto &fd in FileDescriptors)
|
||||
{
|
||||
debug("Removing fd: %d(%#lx)",
|
||||
fd.Descriptor, fd);
|
||||
debug("Removing fd: %d", fd.Descriptor);
|
||||
this->RemoveFileDescriptor(fd.Descriptor);
|
||||
delete fd.Handle;
|
||||
}
|
||||
|
@ -282,24 +282,21 @@ namespace vfs
|
||||
}
|
||||
}
|
||||
|
||||
if (GetChild(SegmentName, CurrentParent) == nullptr)
|
||||
{
|
||||
Node *NewNode = new Node(CurrentParent,
|
||||
SegmentName,
|
||||
NodeType::DIRECTORY);
|
||||
|
||||
CurrentParent = NewNode;
|
||||
CurrentParent->Type = Type;
|
||||
CurrentParent->FullPath = CleanPath;
|
||||
}
|
||||
if (GetChild(SegmentName, CurrentParent) != nullptr)
|
||||
CurrentParent = GetChild(SegmentName, CurrentParent);
|
||||
else
|
||||
{
|
||||
CurrentParent = GetChild(SegmentName, CurrentParent);
|
||||
CurrentParent = new Node(CurrentParent,
|
||||
SegmentName,
|
||||
NodeType::DIRECTORY);
|
||||
}
|
||||
|
||||
delete[] SegmentName;
|
||||
} while (cwk_path_get_next_segment(&segment));
|
||||
|
||||
CurrentParent->Type = Type;
|
||||
// CurrentParent->FullPath = CleanPath;
|
||||
|
||||
vfsdbg("Virtual::Create()->\"%s\"", CurrentParent->Name);
|
||||
#ifdef DEBUG
|
||||
VirtualLock.Unlock();
|
||||
@ -315,6 +312,25 @@ namespace vfs
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Node *Virtual::CreateLink(const char *Path, const char *Target, Node *Parent)
|
||||
{
|
||||
Node *node = this->Create(Path, NodeType::SYMLINK, Parent);
|
||||
if (node)
|
||||
{
|
||||
node->Symlink = new char[strlen(Target) + 1];
|
||||
strncpy((char *)node->Symlink,
|
||||
Target,
|
||||
strlen(Target));
|
||||
|
||||
node->SymlinkTarget = node->vFS->GetNodeFromPath(node->Symlink);
|
||||
return node;
|
||||
}
|
||||
|
||||
error("Failed to create link \"%s\" -> \"%s\"",
|
||||
Path, Target);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Virtual::Delete(const char *Path, bool Recursive, Node *Parent)
|
||||
{
|
||||
vfsdbg("Virtual::Delete( Path: \"%s\" Parent: \"%s\" )",
|
||||
@ -337,8 +353,14 @@ namespace vfs
|
||||
}
|
||||
|
||||
Node *NodeToDelete = GetNodeFromPath(CleanPath, Parent);
|
||||
|
||||
if (!NodeToDelete->References.empty())
|
||||
fixme("Path \"%s\" is referenced by %d objects.",
|
||||
CleanPath, NodeToDelete->References.size());
|
||||
|
||||
delete[] CleanPath;
|
||||
return NodeToDelete->Delete(Recursive);
|
||||
delete NodeToDelete;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Virtual::Delete(Node *Path, bool Recursive, Node *Parent)
|
||||
@ -385,6 +407,14 @@ namespace vfs
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Node *Virtual::CreateIfNotExists(const char *Path, NodeType Type, Node *Parent)
|
||||
{
|
||||
Node *node = GetNodeFromPath(Path, Parent);
|
||||
if (node)
|
||||
return node;
|
||||
return Create(Path, Type, Parent);
|
||||
}
|
||||
|
||||
Virtual::Virtual()
|
||||
{
|
||||
SmartLock(VirtualLock);
|
||||
|
@ -59,8 +59,8 @@ ssize_t fread(int fd, void *buf, size_t count)
|
||||
|
||||
PCB *pcb = thisProcess;
|
||||
FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
ssize_t r = fdt->_read(fd, buf, count);
|
||||
return r;
|
||||
ssize_t ret = fdt->_read(fd, buf, count);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t fwrite(int fd, const void *buf, size_t count)
|
||||
@ -70,8 +70,8 @@ ssize_t fwrite(int fd, const void *buf, size_t count)
|
||||
|
||||
PCB *pcb = thisProcess;
|
||||
FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
ssize_t r = fdt->_write(fd, buf, count);
|
||||
return r;
|
||||
ssize_t ret = fdt->_write(fd, buf, count);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fclose(int fd)
|
||||
@ -81,8 +81,8 @@ int fclose(int fd)
|
||||
|
||||
PCB *pcb = thisProcess;
|
||||
FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
int r = fdt->_close(fd);
|
||||
return r;
|
||||
int ret = fdt->_close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
off_t lseek(int fd, off_t offset, int whence)
|
||||
@ -92,8 +92,8 @@ off_t lseek(int fd, off_t offset, int whence)
|
||||
|
||||
PCB *pcb = thisProcess;
|
||||
FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
off_t r = fdt->_lseek(fd, offset, whence);
|
||||
return r;
|
||||
off_t ret = fdt->_lseek(fd, offset, whence);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int stat(const char *pathname, struct stat *statbuf)
|
||||
@ -103,8 +103,8 @@ int stat(const char *pathname, struct stat *statbuf)
|
||||
|
||||
PCB *pcb = thisProcess;
|
||||
FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
int r = fdt->_stat(pathname, statbuf);
|
||||
return r;
|
||||
int ret = fdt->_stat(pathname, statbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fstat(int fd, struct stat *statbuf)
|
||||
@ -114,8 +114,8 @@ int fstat(int fd, struct stat *statbuf)
|
||||
|
||||
PCB *pcb = thisProcess;
|
||||
FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
int r = fdt->_fstat(fd, statbuf);
|
||||
return r;
|
||||
int ret = fdt->_fstat(fd, statbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lstat(const char *pathname, struct stat *statbuf)
|
||||
@ -125,6 +125,6 @@ int lstat(const char *pathname, struct stat *statbuf)
|
||||
|
||||
PCB *pcb = thisProcess;
|
||||
FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
int r = fdt->_lstat(pathname, statbuf);
|
||||
return r;
|
||||
int ret = fdt->_lstat(pathname, statbuf);
|
||||
return ret;
|
||||
}
|
||||
|
@ -22,31 +22,51 @@ namespace vfs
|
||||
{
|
||||
int Node::open(int Flags, mode_t Mode)
|
||||
{
|
||||
debug("Operation not handled");
|
||||
return -ENXIO;
|
||||
if (likely(open_ptr))
|
||||
return open_ptr(Flags, Mode);
|
||||
|
||||
debug("Operation not handled for %s(%#lx)",
|
||||
this->FullPath, this);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int Node::close()
|
||||
{
|
||||
debug("Operation not handled");
|
||||
return -ENXIO;
|
||||
if (likely(close_ptr))
|
||||
return close_ptr();
|
||||
|
||||
debug("Operation not handled for %s(%#lx)",
|
||||
this->FullPath, this);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
size_t Node::read(uint8_t *Buffer, size_t Size, off_t Offset)
|
||||
{
|
||||
debug("Operation not handled");
|
||||
return -ENXIO;
|
||||
if (likely(read_ptr))
|
||||
return read_ptr(Buffer, Size, Offset);
|
||||
|
||||
debug("Operation not handled for %s(%#lx)",
|
||||
this->FullPath, this);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
size_t Node::write(uint8_t *Buffer, size_t Size, off_t Offset)
|
||||
{
|
||||
debug("Operation not handled");
|
||||
return -ENXIO;
|
||||
if (likely(write_ptr))
|
||||
return write_ptr(Buffer, Size, Offset);
|
||||
|
||||
debug("Operation not handled for %s(%#lx)",
|
||||
this->FullPath, this);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int Node::ioctl(unsigned long Request, void *Argp)
|
||||
{
|
||||
debug("Operation not handled");
|
||||
if (likely(ioctl_ptr))
|
||||
return ioctl_ptr(Request, Argp);
|
||||
|
||||
debug("Operation not handled for %s(%#lx)",
|
||||
this->FullPath, this);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -55,7 +75,8 @@ namespace vfs
|
||||
SmartLock(NodeLock);
|
||||
RefNode *ref = new RefNode(this);
|
||||
References.push_back(ref);
|
||||
debug("Created reference %#lx for node %#lx", ref, this);
|
||||
debug("Created reference %#lx for node %#lx(%s)",
|
||||
ref, this, this->Name);
|
||||
return ref;
|
||||
}
|
||||
|
||||
@ -199,56 +220,24 @@ namespace vfs
|
||||
trace("Node %s(%#lx) has no parent",
|
||||
this->Name, this);
|
||||
}
|
||||
}
|
||||
|
||||
int Node::Delete(bool Recursive)
|
||||
{
|
||||
if (this->References.size() != 0)
|
||||
{
|
||||
debug("Node %s(%#lx) has %ld references",
|
||||
this->FullPath, this,
|
||||
this->References.size());
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (this->Type == MOUNTPOINT ||
|
||||
this->Type == DIRECTORY)
|
||||
{
|
||||
if (this->Children.size() != 0)
|
||||
{
|
||||
if (!Recursive)
|
||||
{
|
||||
debug("Node %s(%#lx) has %ld children",
|
||||
this->FullPath, this,
|
||||
this->Children.size());
|
||||
return -ENOTEMPTY;
|
||||
}
|
||||
|
||||
for (auto Child : this->Children)
|
||||
{
|
||||
int ret = Child->Delete(Recursive);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
debug("Failed to delete child %s(%#lx)",
|
||||
Child->FullPath, Child);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete this;
|
||||
return 0;
|
||||
debug("Created node %s(%#lx)", this->FullPath, this);
|
||||
}
|
||||
|
||||
Node::~Node()
|
||||
{
|
||||
debug("Destroyed node %#lx", this);
|
||||
assert(this->Children.size() == 0);
|
||||
debug("Destroyed node %s(%#lx)", this->FullPath, this);
|
||||
// assert(this->Children.size() == 0);
|
||||
|
||||
foreach (auto Child in this->Children)
|
||||
delete Child;
|
||||
|
||||
if (this->Parent)
|
||||
{
|
||||
debug("Removing node %s(%#lx) from parent %s(%#lx)",
|
||||
this->FullPath, this,
|
||||
this->Parent->FullPath, this->Parent);
|
||||
|
||||
this->Parent->Children.erase(std::find(this->Parent->Children.begin(),
|
||||
this->Parent->Children.end(),
|
||||
this));
|
||||
|
@ -150,6 +150,7 @@ namespace vfs
|
||||
{
|
||||
if (this->SymlinkTo)
|
||||
this->node->SymlinkTarget->RemoveReference(this);
|
||||
|
||||
this->node->RemoveReference(this);
|
||||
|
||||
debug("Destroyed reference node for %s [%#lx]",
|
||||
|
Reference in New Issue
Block a user