2#include "pedigree/kernel/process/FilesystemCredentials.h"
3#include "pedigree/kernel/process/TerminationDeferral.h"
4#include "pedigree/kernel/process/Thread.h"
5#include "pedigree/kernel/processor/Processor.h"
6#include "pedigree/kernel/processor/ProcessorInformation.h"
7#include "pedigree/kernel/syscallError.h"
12#include "FileDescriptor.h"
13#include "PosixProcess.h"
14#include "PosixSubsystem.h"
15#include "file-syscalls.h"
17#include "metadata-syscalls.h"
18#include "modules/system/vfs/MountView.h"
19#include "modules/system/vfs/Pipe.h"
20#include "modules/system/vfs/VFS.h"
25 MknodResult(
int result)
27 error(result < 0 ?
Processor::information().getCurrentThread()->getErrno() : 0) {}
31MknodResult createNode(
int dirfd,
const char* userPath, mode_t suppliedMode) {
33 const mode_t mode =
static_cast<uint16_t
>(suppliedMode);
34 const mode_t type = mode & S_IFMT;
35 if (type != 0 && type != S_IFREG && type != S_IFIFO) {
36 syscallError(type == S_IFBLK || type == S_IFCHR || type == S_IFSOCK
37 ? Error::OperationNotSupported
38 : type == S_IFDIR ? Error::NotEnoughPermissions
39 : Error::InvalidArgument);
42 if (mode & (S_ISUID | S_ISGID)) {
43 SYSCALL_ERROR(OperationNotSupported);
48 if (copiedStatus != PosixSubsystem::UserStringSuccess) {
49 syscallError(copiedStatus == PosixSubsystem::UserStringBadAddress ? Error::BadAddress
50 : Error::NameTooLong);
53 if (!copied.length()) {
54 SYSCALL_ERROR(DoesNotExist);
58 auto* subsystem =
static_cast<PosixSubsystem*
>(process->getSubsystem());
60 auto context = process->acquireFilesystemContext();
61 if (!subsystem || !view || !context) {
62 SYSCALL_ERROR(DoesNotExist);
67 if (copied[0] !=
'/' && dirfd != AT_FDCWD) {
68 if (!subsystem->acquireFileDescriptor(dirfd, descriptor) || !descriptor->getFile()) {
69 SYSCALL_ERROR(BadFileDescriptor);
72 start = descriptor->openingPath();
73 if (!descriptor->getFile()->
isDirectory() || !start) {
74 SYSCALL_ERROR(NotADirectory);
79 normalisePath(path, copied.cstr());
80 if (!view->resolveParent(context, start, path, parent, basename))
82 if (!basename.length() || basename ==
"." || basename ==
"..") {
83 SYSCALL_ERROR(FileExists);
86 if (basename.length() > NAME_MAX) {
87 SYSCALL_ERROR(NameTooLong);
90 if (copied[copied.length() - 1] ==
'/') {
94 syscallError(status == Directory::LookupStatus::Found ? Error::FileExists
95 : status ==
Directory::LookupStatus::NotFound ? Error::DoesNotExist
96 : status ==
Directory::LookupStatus::Retry ? Error::NoMoreProcesses
100 mode_t permissions = mode & 01777;
101 if (process->getType() == Process::Posix)
102 permissions &= ~static_cast<PosixProcess*>(process)->getMask();
104 return view->createFile(parent, basename, permissions) ? 0 : -1;
108 if (!parent || parent->provider() != view || !parent->node()->
isDirectory()) {
109 SYSCALL_ERROR(NotADirectory);
113 if (directory->getFilesystem()->
isReadOnly()) {
114 SYSCALL_ERROR(ReadOnlyFilesystem);
120 if (!Process::currentFilesystemCredentials(credentials)) {
121 SYSCALL_ERROR(PermissionDenied);
124 Pipe* pipe =
new Pipe(basename, 0, 0, 0, 0, directory->getFilesystem(), 0, directory);
126 SYSCALL_ERROR(OutOfMemory);
130 const uint32_t vfsPermissions =
131 ((permissions & 0400) ? FILE_UR : 0) | ((permissions & 0200) ? FILE_UW : 0) |
132 ((permissions & 0100) ? FILE_UX : 0) | ((permissions & 0040) ? FILE_GR : 0) |
133 ((permissions & 0020) ? FILE_GW : 0) | ((permissions & 0010) ? FILE_GX : 0) |
134 ((permissions & 0004) ? FILE_OR : 0) | ((permissions & 0002) ? FILE_OW : 0) |
135 ((permissions & 0001) ? FILE_OX : 0) | ((permissions & S_ISVTX) ? FILE_STICKY : 0);
136 pipe->setPermissions(vfsPermissions);
137 pipe->setUid(credentials.uid);
138 pipe->setGid(credentials.gid);
140 const Directory::AddStatus added = view->createEphemeral(parent, pipe, LandlockAccess::MakeFifo);
141 if (added != Directory::AddStatus::Added) {
147 syscallError(added == Directory::AddStatus::IoError ? Error::IoError
148 : added ==
Directory::AddStatus::Detached ? Error::DoesNotExist
149 : Error::FileExists);
157int posix_mknodat(
int dirfd,
const char* path, mode_t mode, dev_t device) {
160 const MknodResult result = createNode(dirfd, path, mode);
161 syscallError(result.error);
static Directory * fromFile(File *pF)
MUST_USE_RESULT LookupStatus lookupChild(const HashedStringView &s, ChildLease &child) const
virtual bool isDirectory()
static UserStringResult copyUserString(const char *userString, String ©, size_t maxLength)
static ProcessorInformation & information()
static bool checkAccess(File *pFile, bool bRead, bool bWrite, bool bExecute)