kernel+libc: Add unlink(), rmdir(), remove()
This commit is contained in:
parent
1b4f48b92c
commit
417e505750
@ -36,6 +36,7 @@ set(SOURCES
|
|||||||
src/sys/getdents.cpp
|
src/sys/getdents.cpp
|
||||||
src/sys/stat.cpp
|
src/sys/stat.cpp
|
||||||
src/sys/chdir.cpp
|
src/sys/chdir.cpp
|
||||||
|
src/sys/link.cpp
|
||||||
src/fs/VFS.cpp
|
src/fs/VFS.cpp
|
||||||
src/fs/tmpfs/FileSystem.cpp
|
src/fs/tmpfs/FileSystem.cpp
|
||||||
src/fs/devices/DeviceRegistry.cpp
|
src/fs/devices/DeviceRegistry.cpp
|
||||||
|
@ -43,6 +43,10 @@ namespace VFS
|
|||||||
|
|
||||||
virtual Result<void> add_entry(SharedPtr<Inode> inode, const char* name) = 0;
|
virtual Result<void> add_entry(SharedPtr<Inode> inode, const char* name) = 0;
|
||||||
|
|
||||||
|
virtual Result<void> remove_entry(const char* name) = 0;
|
||||||
|
|
||||||
|
virtual usize entries() const = 0;
|
||||||
|
|
||||||
// File-specific methods
|
// File-specific methods
|
||||||
virtual Result<usize> read(u8* buf, usize offset, usize length) const = 0;
|
virtual Result<usize> read(u8* buf, usize offset, usize length) const = 0;
|
||||||
|
|
||||||
@ -67,6 +71,9 @@ namespace VFS
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void did_link() = 0;
|
||||||
|
virtual void did_unlink() = 0;
|
||||||
|
|
||||||
// Metadata changers
|
// Metadata changers
|
||||||
virtual Result<void> chmod(mode_t mode) = 0;
|
virtual Result<void> chmod(mode_t mode) = 0;
|
||||||
|
|
||||||
@ -110,6 +117,16 @@ namespace VFS
|
|||||||
return err(ENOTDIR);
|
return err(ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<void> remove_entry(const char*) override
|
||||||
|
{
|
||||||
|
return err(ENOTDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
usize entries() const override
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool blocking() const override
|
bool blocking() const override
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -151,6 +168,16 @@ namespace VFS
|
|||||||
return err(ENOTDIR);
|
return err(ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<void> remove_entry(const char*) override
|
||||||
|
{
|
||||||
|
return err(ENOTDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
usize entries() const override
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
InodeType type() const override
|
InodeType type() const override
|
||||||
{
|
{
|
||||||
return InodeType::Device;
|
return InodeType::Device;
|
||||||
|
@ -79,6 +79,22 @@ namespace TmpFS
|
|||||||
|
|
||||||
TRY(m_entries.try_append(move(entry)));
|
TRY(m_entries.try_append(move(entry)));
|
||||||
|
|
||||||
|
inode->did_link();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> DirInode::remove_entry(const char* name)
|
||||||
|
{
|
||||||
|
SharedPtr<VFS::Inode> inode = TRY(find(name));
|
||||||
|
|
||||||
|
if (inode->type() == VFS::InodeType::Directory && inode->entries() != 2) return err(ENOTEMPTY);
|
||||||
|
|
||||||
|
m_entries.remove_first_matching(
|
||||||
|
[&](const VFS::DirectoryEntry& entry) { return !strcmp(entry.name.chars(), name); });
|
||||||
|
|
||||||
|
inode->did_unlink();
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +96,16 @@ namespace TmpFS
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void did_link() override
|
||||||
|
{
|
||||||
|
m_nlinks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void did_unlink() override
|
||||||
|
{
|
||||||
|
m_nlinks--;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~FileInode() = default;
|
virtual ~FileInode() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -105,6 +115,7 @@ namespace TmpFS
|
|||||||
mode_t m_mode;
|
mode_t m_mode;
|
||||||
u32 m_uid { 0 };
|
u32 m_uid { 0 };
|
||||||
u32 m_gid { 0 };
|
u32 m_gid { 0 };
|
||||||
|
u32 m_nlinks { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeviceInode : public VFS::DeviceInode
|
class DeviceInode : public VFS::DeviceInode
|
||||||
@ -196,6 +207,16 @@ namespace TmpFS
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void did_link() override
|
||||||
|
{
|
||||||
|
m_nlinks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void did_unlink() override
|
||||||
|
{
|
||||||
|
m_nlinks--;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~DeviceInode() = default;
|
virtual ~DeviceInode() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -205,6 +226,7 @@ namespace TmpFS
|
|||||||
mode_t m_mode;
|
mode_t m_mode;
|
||||||
u32 m_uid { 0 };
|
u32 m_uid { 0 };
|
||||||
u32 m_gid { 0 };
|
u32 m_gid { 0 };
|
||||||
|
u32 m_nlinks { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class DirInode : public VFS::Inode
|
class DirInode : public VFS::Inode
|
||||||
@ -298,6 +320,23 @@ namespace TmpFS
|
|||||||
return VFS::InodeType::Directory;
|
return VFS::InodeType::Directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void did_link() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void did_unlink() override
|
||||||
|
{
|
||||||
|
m_self = {};
|
||||||
|
m_entries.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
usize entries() const override
|
||||||
|
{
|
||||||
|
return m_entries.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> remove_entry(const char* name) override;
|
||||||
|
|
||||||
Result<SharedPtr<VFS::Inode>> create_file(const char* name) override;
|
Result<SharedPtr<VFS::Inode>> create_file(const char* name) override;
|
||||||
Result<SharedPtr<VFS::Inode>> create_subdirectory(const char* name) override;
|
Result<SharedPtr<VFS::Inode>> create_subdirectory(const char* name) override;
|
||||||
|
|
||||||
|
32
kernel/src/sys/link.cpp
Normal file
32
kernel/src/sys/link.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "memory/MemoryManager.h"
|
||||||
|
#include "sys/Syscall.h"
|
||||||
|
#include "thread/Scheduler.h"
|
||||||
|
#include <luna/PathParser.h>
|
||||||
|
|
||||||
|
Result<u64> sys_unlink(Registers*, SyscallArgs args)
|
||||||
|
{
|
||||||
|
auto path = TRY(MemoryManager::strdup_from_user(args[0]));
|
||||||
|
int flags = (int)args[1];
|
||||||
|
|
||||||
|
Thread* current = Scheduler::current();
|
||||||
|
|
||||||
|
PathParser parser = TRY(PathParser::create(path.chars()));
|
||||||
|
|
||||||
|
auto dirname = TRY(parser.dirname());
|
||||||
|
auto basename = TRY(parser.basename());
|
||||||
|
|
||||||
|
if (basename.view() == ".") return err(EINVAL);
|
||||||
|
|
||||||
|
auto inode = TRY(VFS::resolve_path(dirname.chars(), current->auth, current->current_directory));
|
||||||
|
if (!VFS::can_write(inode, current->auth)) return err(EACCES);
|
||||||
|
|
||||||
|
if (flags > 0)
|
||||||
|
{
|
||||||
|
auto child = TRY(inode->find(basename.chars()));
|
||||||
|
if (child->type() != VFS::InodeType::Directory) return err(ENOTDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
TRY(inode->remove_entry(basename.chars()));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -53,7 +53,7 @@ add_custom_target(libc
|
|||||||
COMMAND ${CMAKE_AR} -x $<TARGET_FILE:bare_libc>
|
COMMAND ${CMAKE_AR} -x $<TARGET_FILE:bare_libc>
|
||||||
COMMAND ${CMAKE_AR} -x $<TARGET_FILE:luna>
|
COMMAND ${CMAKE_AR} -x $<TARGET_FILE:luna>
|
||||||
COMMAND ${CMAKE_AR} -rcs ${CMAKE_CURRENT_BINARY_DIR}/libc.a *.o
|
COMMAND ${CMAKE_AR} -rcs ${CMAKE_CURRENT_BINARY_DIR}/libc.a *.o
|
||||||
COMMAND rm *.o
|
COMMAND /usr/bin/rm *.o
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
DEPENDS bare_libc luna crt0
|
DEPENDS bare_libc luna crt0
|
||||||
)
|
)
|
||||||
|
@ -128,6 +128,9 @@ extern "C"
|
|||||||
/* Write an error message to standard error. */
|
/* Write an error message to standard error. */
|
||||||
void perror(const char* s);
|
void perror(const char* s);
|
||||||
|
|
||||||
|
/* Remove a file from the filesystem. */
|
||||||
|
int remove(const char* path);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -103,6 +103,12 @@ extern "C"
|
|||||||
/* Retrieve the current working directory. */
|
/* Retrieve the current working directory. */
|
||||||
char* getcwd(char* buf, size_t size);
|
char* getcwd(char* buf, size_t size);
|
||||||
|
|
||||||
|
/* Remove a name from the filesystem. */
|
||||||
|
int unlink(const char* path);
|
||||||
|
|
||||||
|
/* Remove a directory from the filesystem. */
|
||||||
|
int rmdir(const char* path);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -336,6 +336,12 @@ extern "C"
|
|||||||
if (s && *s) fprintf(stderr, "%s: ", s);
|
if (s && *s) fprintf(stderr, "%s: ", s);
|
||||||
fprintf(stderr, "%s\n", strerror(err));
|
fprintf(stderr, "%s\n", strerror(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int remove(const char* path)
|
||||||
|
{
|
||||||
|
// On Luna, unlink() allows removal of directories.
|
||||||
|
return unlink(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void debug_log_impl(const char* format, va_list ap)
|
void debug_log_impl(const char* format, va_list ap)
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -300,4 +301,16 @@ extern "C"
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int unlink(const char* path)
|
||||||
|
{
|
||||||
|
long rc = syscall(SYS_unlink, path, 0);
|
||||||
|
__errno_return(rc, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rmdir(const char* path)
|
||||||
|
{
|
||||||
|
long rc = syscall(SYS_unlink, path, 1);
|
||||||
|
__errno_return(rc, int);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
_e(exit) _e(clock_gettime) _e(mmap) _e(munmap) _e(usleep) _e(open) _e(close) _e(read) _e(getpid) _e(write) \
|
_e(exit) _e(clock_gettime) _e(mmap) _e(munmap) _e(usleep) _e(open) _e(close) _e(read) _e(getpid) _e(write) \
|
||||||
_e(lseek) _e(mkdir) _e(execve) _e(mknod) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) _e(getuid) \
|
_e(lseek) _e(mkdir) _e(execve) _e(mknod) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) _e(getuid) \
|
||||||
_e(geteuid) _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(chmod) _e(chown) \
|
_e(geteuid) _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(chmod) _e(chown) \
|
||||||
_e(ioctl) _e(stat) _e(fstat) _e(chdir) _e(getcwd)
|
_e(ioctl) _e(stat) _e(fstat) _e(chdir) _e(getcwd) _e(unlink)
|
||||||
|
|
||||||
enum Syscalls
|
enum Syscalls
|
||||||
{
|
{
|
||||||
|
@ -111,13 +111,7 @@ template <typename T> class Vector
|
|||||||
{
|
{
|
||||||
if (m_size == 0) return {};
|
if (m_size == 0) return {};
|
||||||
|
|
||||||
T item = move(m_data[0]);
|
return remove_at(0);
|
||||||
|
|
||||||
m_size--;
|
|
||||||
|
|
||||||
memmove(m_data, m_data + 1, m_size * sizeof(T));
|
|
||||||
|
|
||||||
return move(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& operator[](usize index) const
|
const T& operator[](usize index) const
|
||||||
@ -177,8 +171,41 @@ template <typename T> class Vector
|
|||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T remove_at(usize index)
|
||||||
|
{
|
||||||
|
check(index < m_size);
|
||||||
|
|
||||||
|
T item = move(m_data[index]);
|
||||||
|
|
||||||
|
memmove(m_data + index, m_data + (index + 1), (m_size - (index + 1)) * sizeof(T));
|
||||||
|
|
||||||
|
m_size--;
|
||||||
|
|
||||||
|
return move(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Callback> Option<T> remove_first_matching(Callback callback)
|
||||||
|
{
|
||||||
|
Option<usize> index = {};
|
||||||
|
|
||||||
|
for (usize i = 0; i < m_size; i++)
|
||||||
|
{
|
||||||
|
if (callback(m_data[i]))
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!index.has_value()) return {};
|
||||||
|
|
||||||
|
return remove_at(index.value());
|
||||||
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
|
for (usize i = 0; i < m_size; i++) { m_data[i].~T(); }
|
||||||
|
|
||||||
m_size = m_capacity = 0;
|
m_size = m_capacity = 0;
|
||||||
free_impl(m_data);
|
free_impl(m_data);
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
|
Loading…
Reference in New Issue
Block a user