kernel: Add initial support for symbolic links :D
This commit is contained in:
parent
b75bd4cd14
commit
67a9d130e2
@ -15,28 +15,60 @@ namespace VFS
|
|||||||
return *root_fs->root_inode();
|
return *root_fs->root_inode();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<SharedPtr<Inode>> resolve_path(const char* path, Credentials auth, SharedPtr<Inode> working_directory)
|
static constexpr int MAX_SYMLINKS = 8;
|
||||||
|
|
||||||
|
Result<SharedPtr<Inode>> resolve_path_impl(const char* path, Credentials auth, SharedPtr<Inode> current_inode,
|
||||||
|
bool follow_last_symlink, int& symlinks_followed)
|
||||||
{
|
{
|
||||||
|
if (symlinks_followed >= MAX_SYMLINKS) return err(ELOOP);
|
||||||
|
|
||||||
if (*path == '\0') return err(ENOENT);
|
if (*path == '\0') return err(ENOENT);
|
||||||
|
|
||||||
auto parser = TRY(PathParser::create(path));
|
auto parser = TRY(PathParser::create(path));
|
||||||
|
|
||||||
SharedPtr<Inode> current_inode;
|
SharedPtr<Inode> parent_inode = current_inode;
|
||||||
|
|
||||||
if (parser.is_absolute() || !working_directory) current_inode = root_fs->root_inode();
|
|
||||||
else
|
|
||||||
current_inode = working_directory;
|
|
||||||
|
|
||||||
const char* section;
|
const char* section;
|
||||||
while (parser.next().try_set_value(section))
|
while (parser.next().try_set_value(section))
|
||||||
{
|
{
|
||||||
if (!can_execute(current_inode, auth)) return err(EACCES);
|
if (!can_execute(current_inode, auth)) return err(EACCES);
|
||||||
current_inode = TRY(current_inode->find(section));
|
current_inode = TRY(current_inode->find(section));
|
||||||
|
|
||||||
|
if (current_inode->type() == VFS::InodeType::Symlink && (follow_last_symlink || parser.has_next()))
|
||||||
|
{
|
||||||
|
auto link = TRY(current_inode->readlink());
|
||||||
|
|
||||||
|
SharedPtr<VFS::Inode> symlink_root;
|
||||||
|
|
||||||
|
if (PathParser::is_absolute(link.chars())) symlink_root = root_fs->root_inode();
|
||||||
|
else
|
||||||
|
symlink_root = parent_inode;
|
||||||
|
|
||||||
|
symlinks_followed++;
|
||||||
|
current_inode = TRY(resolve_path_impl(link.chars(), auth, symlink_root, true, symlinks_followed));
|
||||||
|
symlinks_followed--;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_inode = current_inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return current_inode;
|
return current_inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<SharedPtr<Inode>> resolve_path(const char* path, Credentials auth, SharedPtr<VFS::Inode> working_directory,
|
||||||
|
bool follow_last_symlink)
|
||||||
|
{
|
||||||
|
SharedPtr<Inode> current_inode;
|
||||||
|
|
||||||
|
if (PathParser::is_absolute(path) || !working_directory) current_inode = root_fs->root_inode();
|
||||||
|
else
|
||||||
|
current_inode = working_directory;
|
||||||
|
|
||||||
|
int symlinks_followed = 0;
|
||||||
|
|
||||||
|
return resolve_path_impl(path, auth, current_inode, follow_last_symlink, symlinks_followed);
|
||||||
|
}
|
||||||
|
|
||||||
Result<SharedPtr<Inode>> create_directory(const char* path, Credentials auth, SharedPtr<Inode> working_directory)
|
Result<SharedPtr<Inode>> create_directory(const char* path, Credentials auth, SharedPtr<Inode> working_directory)
|
||||||
{
|
{
|
||||||
auto parser = TRY(PathParser::create(path));
|
auto parser = TRY(PathParser::create(path));
|
||||||
|
@ -12,7 +12,8 @@ namespace VFS
|
|||||||
{
|
{
|
||||||
RegularFile,
|
RegularFile,
|
||||||
Directory,
|
Directory,
|
||||||
Device
|
Device,
|
||||||
|
Symlink
|
||||||
};
|
};
|
||||||
|
|
||||||
class Inode;
|
class Inode;
|
||||||
@ -28,6 +29,8 @@ namespace VFS
|
|||||||
|
|
||||||
virtual Result<SharedPtr<Inode>> create_device_inode(u32 major, u32 minor) = 0;
|
virtual Result<SharedPtr<Inode>> create_device_inode(u32 major, u32 minor) = 0;
|
||||||
|
|
||||||
|
virtual Result<SharedPtr<Inode>> create_symlink_inode(StringView link) = 0;
|
||||||
|
|
||||||
virtual Result<void> set_mount_dir(SharedPtr<Inode> parent) = 0;
|
virtual Result<void> set_mount_dir(SharedPtr<Inode> parent) = 0;
|
||||||
|
|
||||||
virtual u64 handles() const
|
virtual u64 handles() const
|
||||||
@ -92,6 +95,12 @@ namespace VFS
|
|||||||
|
|
||||||
virtual bool blocking() const = 0;
|
virtual bool blocking() const = 0;
|
||||||
|
|
||||||
|
// Symlink-specific methods
|
||||||
|
virtual Result<StringView> readlink()
|
||||||
|
{
|
||||||
|
return StringView {};
|
||||||
|
}
|
||||||
|
|
||||||
// Metadata accessors
|
// Metadata accessors
|
||||||
virtual usize size() const = 0;
|
virtual usize size() const = 0;
|
||||||
|
|
||||||
@ -250,7 +259,8 @@ namespace VFS
|
|||||||
};
|
};
|
||||||
|
|
||||||
Result<SharedPtr<Inode>> resolve_path(const char* path, Credentials auth,
|
Result<SharedPtr<Inode>> resolve_path(const char* path, Credentials auth,
|
||||||
SharedPtr<VFS::Inode> working_directory = {});
|
SharedPtr<VFS::Inode> working_directory = {},
|
||||||
|
bool follow_last_symlink = true);
|
||||||
|
|
||||||
Result<SharedPtr<Inode>> create_directory(const char* path, Credentials auth,
|
Result<SharedPtr<Inode>> create_directory(const char* path, Credentials auth,
|
||||||
SharedPtr<VFS::Inode> working_directory = {});
|
SharedPtr<VFS::Inode> working_directory = {});
|
||||||
|
@ -24,6 +24,15 @@ namespace TmpFS
|
|||||||
return (SharedPtr<VFS::Inode>)inode;
|
return (SharedPtr<VFS::Inode>)inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<SharedPtr<VFS::Inode>> FileSystem::create_symlink_inode(StringView link)
|
||||||
|
{
|
||||||
|
SharedPtr<SymlinkInode> inode = TRY(make_shared<SymlinkInode>());
|
||||||
|
inode->set_fs(*this, {});
|
||||||
|
TRY(inode->set_link(link, {}));
|
||||||
|
inode->set_inode_number(m_next_inode_number++, {});
|
||||||
|
return (SharedPtr<VFS::Inode>)inode;
|
||||||
|
}
|
||||||
|
|
||||||
Result<SharedPtr<VFS::Inode>> FileSystem::create_dir_inode(SharedPtr<VFS::Inode> parent)
|
Result<SharedPtr<VFS::Inode>> FileSystem::create_dir_inode(SharedPtr<VFS::Inode> parent)
|
||||||
{
|
{
|
||||||
SharedPtr<DirInode> inode = TRY(make_shared<DirInode>());
|
SharedPtr<DirInode> inode = TRY(make_shared<DirInode>());
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <luna/Badge.h>
|
#include <luna/Badge.h>
|
||||||
#include <luna/Buffer.h>
|
#include <luna/Buffer.h>
|
||||||
#include <luna/StaticString.h>
|
#include <luna/StaticString.h>
|
||||||
|
#include <luna/String.h>
|
||||||
#include <luna/Vector.h>
|
#include <luna/Vector.h>
|
||||||
|
|
||||||
namespace TmpFS
|
namespace TmpFS
|
||||||
@ -20,6 +21,7 @@ namespace TmpFS
|
|||||||
Result<SharedPtr<VFS::Inode>> create_file_inode() override;
|
Result<SharedPtr<VFS::Inode>> create_file_inode() override;
|
||||||
Result<SharedPtr<VFS::Inode>> create_dir_inode(SharedPtr<VFS::Inode> parent) override;
|
Result<SharedPtr<VFS::Inode>> create_dir_inode(SharedPtr<VFS::Inode> parent) override;
|
||||||
Result<SharedPtr<VFS::Inode>> create_device_inode(u32 major, u32 minor) override;
|
Result<SharedPtr<VFS::Inode>> create_device_inode(u32 major, u32 minor) override;
|
||||||
|
Result<SharedPtr<VFS::Inode>> create_symlink_inode(StringView link) override;
|
||||||
|
|
||||||
Result<void> set_mount_dir(SharedPtr<VFS::Inode> parent) override;
|
Result<void> set_mount_dir(SharedPtr<VFS::Inode> parent) override;
|
||||||
|
|
||||||
@ -120,6 +122,115 @@ namespace TmpFS
|
|||||||
u32 m_nlinks { 0 };
|
u32 m_nlinks { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SymlinkInode : public VFS::FileInode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SymlinkInode() = default;
|
||||||
|
|
||||||
|
VFS::InodeType type() const override
|
||||||
|
{
|
||||||
|
return VFS::InodeType::Symlink;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_fs(FileSystem& fs, Badge<FileSystem>)
|
||||||
|
{
|
||||||
|
m_fs = &fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_inode_number(usize inum, Badge<FileSystem>)
|
||||||
|
{
|
||||||
|
m_inode_number = inum;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> set_link(StringView link, Badge<FileSystem>)
|
||||||
|
{
|
||||||
|
m_link = TRY(String::from_string_view(link));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
VFS::FileSystem* fs() const override
|
||||||
|
{
|
||||||
|
return m_fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize inode_number() const override
|
||||||
|
{
|
||||||
|
return m_inode_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<usize> read(u8*, usize, usize) const override
|
||||||
|
{
|
||||||
|
return err(ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<usize> write(const u8*, usize, usize) override
|
||||||
|
{
|
||||||
|
return err(ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> truncate(usize) override
|
||||||
|
{
|
||||||
|
return err(ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
usize size() const override
|
||||||
|
{
|
||||||
|
return m_link.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
mode_t mode() const override
|
||||||
|
{
|
||||||
|
return 0777;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 uid() const override
|
||||||
|
{
|
||||||
|
return m_uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 gid() const override
|
||||||
|
{
|
||||||
|
return m_gid;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> chmod(mode_t) override
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> chown(u32 uid, u32 gid) override
|
||||||
|
{
|
||||||
|
m_uid = uid;
|
||||||
|
m_gid = gid;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void did_link() override
|
||||||
|
{
|
||||||
|
m_nlinks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void did_unlink() override
|
||||||
|
{
|
||||||
|
m_nlinks--;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<StringView> readlink() override
|
||||||
|
{
|
||||||
|
return m_link.view();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~SymlinkInode() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VFS::FileSystem* m_fs;
|
||||||
|
String m_link;
|
||||||
|
usize m_inode_number;
|
||||||
|
u32 m_uid { 0 };
|
||||||
|
u32 m_gid { 0 };
|
||||||
|
u32 m_nlinks { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
class DeviceInode : public VFS::DeviceInode
|
class DeviceInode : public VFS::DeviceInode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -104,7 +104,7 @@ Result<u64> sys_fchmodat(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
|
||||||
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH));
|
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
|
||||||
|
|
||||||
if (current->auth.euid != 0 && current->auth.euid != inode->uid()) return err(EPERM);
|
if (current->auth.euid != 0 && current->auth.euid != inode->uid()) return err(EPERM);
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ Result<u64> sys_fchownat(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
auto* current = Scheduler::current();
|
auto* current = Scheduler::current();
|
||||||
|
|
||||||
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH));
|
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
|
||||||
|
|
||||||
if (current->auth.euid != 0) return err(EPERM);
|
if (current->auth.euid != 0) return err(EPERM);
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ Result<u64> sys_unlinkat(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
kinfoln("unlinkat: remove %s from directory %s, dirfd is %d", basename.chars(), dirname.chars(), dirfd);
|
kinfoln("unlinkat: remove %s from directory %s, dirfd is %d", basename.chars(), dirname.chars(), dirfd);
|
||||||
|
|
||||||
auto inode = TRY(current->resolve_atfile(dirfd, dirname, false));
|
auto inode = TRY(current->resolve_atfile(dirfd, dirname, false, false));
|
||||||
if (!VFS::can_write(inode, current->auth)) return err(EACCES);
|
if (!VFS::can_write(inode, current->auth)) return err(EACCES);
|
||||||
|
|
||||||
if (flags > 0)
|
if (flags > 0)
|
||||||
@ -34,3 +34,31 @@ Result<u64> sys_unlinkat(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<u64> sys_symlinkat(Registers*, SyscallArgs args)
|
||||||
|
{
|
||||||
|
auto target = TRY(MemoryManager::strdup_from_user(args[0]));
|
||||||
|
int dirfd = (int)args[1];
|
||||||
|
auto linkpath = TRY(MemoryManager::strdup_from_user(args[2]));
|
||||||
|
|
||||||
|
if (target.is_empty()) return err(ENOENT);
|
||||||
|
|
||||||
|
auto* current = Scheduler::current();
|
||||||
|
|
||||||
|
auto parser = TRY(PathParser::create(linkpath.chars()));
|
||||||
|
auto parent = TRY(parser.dirname());
|
||||||
|
|
||||||
|
auto parent_inode = TRY(current->resolve_atfile(dirfd, parent, false, true));
|
||||||
|
|
||||||
|
if (!VFS::can_write(parent_inode, current->auth)) return err(EACCES);
|
||||||
|
|
||||||
|
auto child_name = TRY(parser.basename());
|
||||||
|
|
||||||
|
TRY(VFS::validate_filename(child_name.view()));
|
||||||
|
|
||||||
|
auto inode = TRY(parent_inode->fs()->create_symlink_inode(target.view()));
|
||||||
|
TRY(inode->chown(current->auth.euid, current->auth.egid));
|
||||||
|
TRY(parent_inode->add_entry(inode, child_name.chars()));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -31,7 +31,8 @@ Result<u64> sys_openat(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
int error;
|
int error;
|
||||||
SharedPtr<VFS::Inode> parent_inode;
|
SharedPtr<VFS::Inode> parent_inode;
|
||||||
bool ok = current->resolve_atfile(dirfd, path, false, &parent_inode).try_set_value_or_error(inode, error);
|
bool ok = current->resolve_atfile(dirfd, path, false, !(flags & O_NOFOLLOW), &parent_inode)
|
||||||
|
.try_set_value_or_error(inode, error);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
if (error == ENOENT && (flags & O_CREAT) && !path.is_empty())
|
if (error == ENOENT && (flags & O_CREAT) && !path.is_empty())
|
||||||
@ -51,6 +52,9 @@ Result<u64> sys_openat(Registers*, SyscallArgs args)
|
|||||||
if ((flags & O_WRONLY) && !VFS::can_write(inode, current->auth)) return err(EACCES);
|
if ((flags & O_WRONLY) && !VFS::can_write(inode, current->auth)) return err(EACCES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This should only be possible if O_NOFOLLOW was in flags.
|
||||||
|
if (inode->type() == VFS::InodeType::Symlink) return err(ELOOP);
|
||||||
|
|
||||||
if (flags & O_TMPFILE)
|
if (flags & O_TMPFILE)
|
||||||
{
|
{
|
||||||
if (inode->type() != VFS::InodeType::Directory) return err(EINVAL);
|
if (inode->type() != VFS::InodeType::Directory) return err(EINVAL);
|
||||||
|
@ -14,6 +14,7 @@ static mode_t make_mode(mode_t mode, VFS::InodeType type)
|
|||||||
case VFS::InodeType::RegularFile: result |= S_IFREG; break;
|
case VFS::InodeType::RegularFile: result |= S_IFREG; break;
|
||||||
case VFS::InodeType::Directory: result |= S_IFDIR; break;
|
case VFS::InodeType::Directory: result |= S_IFDIR; break;
|
||||||
case VFS::InodeType::Device: result |= S_IFCHR; break;
|
case VFS::InodeType::Device: result |= S_IFCHR; break;
|
||||||
|
case VFS::InodeType::Symlink: result |= S_IFLNK; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +30,7 @@ Result<u64> sys_fstatat(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
Thread* current = Scheduler::current();
|
Thread* current = Scheduler::current();
|
||||||
|
|
||||||
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH));
|
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
|
||||||
|
|
||||||
stat kstat;
|
stat kstat;
|
||||||
|
|
||||||
|
@ -49,13 +49,15 @@ Result<FileDescriptor*> Thread::resolve_fd(int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result<SharedPtr<VFS::Inode>> Thread::resolve_atfile(int dirfd, const String& path, bool allow_empty_path,
|
Result<SharedPtr<VFS::Inode>> Thread::resolve_atfile(int dirfd, const String& path, bool allow_empty_path,
|
||||||
SharedPtr<VFS::Inode>* parent_inode)
|
bool follow_last_symlink, SharedPtr<VFS::Inode>* parent_inode)
|
||||||
{
|
{
|
||||||
if (parent_inode) *parent_inode = this->current_directory;
|
if (parent_inode) *parent_inode = this->current_directory;
|
||||||
|
|
||||||
if (PathParser::is_absolute(path.view())) return VFS::resolve_path(path.chars(), this->auth);
|
if (PathParser::is_absolute(path.view()))
|
||||||
|
return VFS::resolve_path(path.chars(), this->auth, {}, follow_last_symlink);
|
||||||
|
|
||||||
if (dirfd == AT_FDCWD) return VFS::resolve_path(path.chars(), this->auth, this->current_directory);
|
if (dirfd == AT_FDCWD)
|
||||||
|
return VFS::resolve_path(path.chars(), this->auth, this->current_directory, follow_last_symlink);
|
||||||
|
|
||||||
auto descriptor = TRY(resolve_fd(dirfd));
|
auto descriptor = TRY(resolve_fd(dirfd));
|
||||||
|
|
||||||
@ -63,7 +65,7 @@ Result<SharedPtr<VFS::Inode>> Thread::resolve_atfile(int dirfd, const String& pa
|
|||||||
|
|
||||||
if (path.is_empty() && allow_empty_path) return descriptor->inode;
|
if (path.is_empty() && allow_empty_path) return descriptor->inode;
|
||||||
|
|
||||||
return VFS::resolve_path(path.chars(), this->auth, descriptor->inode);
|
return VFS::resolve_path(path.chars(), this->auth, descriptor->inode, follow_last_symlink);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileDescriptor::should_append()
|
bool FileDescriptor::should_append()
|
||||||
|
@ -76,6 +76,7 @@ struct Thread : public LinkedListNode<Thread>
|
|||||||
Result<int> allocate_fd(int min);
|
Result<int> allocate_fd(int min);
|
||||||
Result<FileDescriptor*> resolve_fd(int fd);
|
Result<FileDescriptor*> resolve_fd(int fd);
|
||||||
Result<SharedPtr<VFS::Inode>> resolve_atfile(int dirfd, const String& path, bool allow_empty_path,
|
Result<SharedPtr<VFS::Inode>> resolve_atfile(int dirfd, const String& path, bool allow_empty_path,
|
||||||
|
bool follow_last_symlink,
|
||||||
SharedPtr<VFS::Inode>* parent_inode = nullptr);
|
SharedPtr<VFS::Inode>* parent_inode = nullptr);
|
||||||
|
|
||||||
FPData fp_data;
|
FPData fp_data;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#define AT_FDCWD -100
|
#define AT_FDCWD -100
|
||||||
|
|
||||||
#define AT_EMPTY_PATH 1
|
#define AT_EMPTY_PATH 1
|
||||||
|
#define AT_SYMLINK_NOFOLLOW 2
|
||||||
|
|
||||||
#define AT_REMOVEDIR 1
|
#define AT_REMOVEDIR 1
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#define S_IFMT 070000
|
#define S_IFMT 070000
|
||||||
#define S_IFREG 000000
|
#define S_IFREG 000000
|
||||||
|
#define S_IFLNK 010000
|
||||||
#define S_IFDIR 040000
|
#define S_IFDIR 040000
|
||||||
#define S_IFCHR 050000
|
#define S_IFCHR 050000
|
||||||
|
|
||||||
@ -13,6 +14,7 @@
|
|||||||
#define S_ISREG(mode) __CHECK_TYPE(mode, S_IFREG)
|
#define S_ISREG(mode) __CHECK_TYPE(mode, S_IFREG)
|
||||||
#define S_ISDIR(mode) __CHECK_TYPE(mode, S_IFDIR)
|
#define S_ISDIR(mode) __CHECK_TYPE(mode, S_IFDIR)
|
||||||
#define S_ISCHR(mode) __CHECK_TYPE(mode, S_IFCHR)
|
#define S_ISCHR(mode) __CHECK_TYPE(mode, S_IFCHR)
|
||||||
|
#define S_ISLNK(mode) __CHECK_TYPE(mode, S_IFLNK)
|
||||||
|
|
||||||
#define S_IRWXU 0700
|
#define S_IRWXU 0700
|
||||||
#define S_IRUSR 0400
|
#define S_IRUSR 0400
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#define O_CLOEXEC 128
|
#define O_CLOEXEC 128
|
||||||
#define O_DIRECTORY 256
|
#define O_DIRECTORY 256
|
||||||
#define O_TMPFILE 512
|
#define O_TMPFILE 512
|
||||||
|
#define O_NOFOLLOW 1024
|
||||||
|
|
||||||
#define O_ACCMODE O_RDWR
|
#define O_ACCMODE O_RDWR
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
_e(lseek) _e(mkdir) _e(execve) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) _e(getuid) _e(geteuid) \
|
_e(lseek) _e(mkdir) _e(execve) _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(fchmodat) _e(fchownat) _e(ioctl) \
|
_e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \
|
||||||
_e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \
|
_e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \
|
||||||
_e(umount) _e(pstat) _e(getrusage)
|
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat)
|
||||||
|
|
||||||
enum Syscalls
|
enum Syscalls
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user