2#include "fanotify-syscalls.h"
3#include "pedigree/kernel/process/Process.h"
4#include "pedigree/kernel/process/TerminationDeferral.h"
5#include "pedigree/kernel/process/Thread.h"
6#include "pedigree/kernel/processor/Processor.h"
7#include "pedigree/kernel/processor/ProcessorInformation.h"
8#include "pedigree/kernel/syscallError.h"
12#include "FileDescriptor.h"
13#include "PosixSubsystem.h"
14#include "file-handle-syscalls.h"
15#include "modules/system/vfs/File.h"
16#include "modules/system/vfs/Filesystem.h"
21 int finish(
int result) {
34int posix_fanotify_init(
unsigned flags,
unsigned eventFlags) {
35 FanotifyResult completion;
36 constexpr unsigned CloseOnExec = 1, NonBlock = 2, Classes = 0x0c, ReportFid = 0x200;
37 constexpr unsigned KnownFlags =
38 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x100 | 0x200 | 0x400 | 0x800;
39 constexpr unsigned EventFlags =
40 3 | O_APPEND | O_NONBLOCK | O_SYNC | O_DSYNC | O_CLOEXEC | O_LARGEFILE | O_NOATIME;
41 if ((flags & ~KnownFlags) || (flags & Classes) == Classes || (eventFlags & ~EventFlags) ||
42 (eventFlags & 3) == 3) {
43 SYSCALL_ERROR(InvalidArgument);
44 return completion.finish(-1);
46 if (!posix_effective_root()) {
47 SYSCALL_ERROR(NotEnoughPermissions);
48 return completion.finish(-1);
50 if (!(flags & ReportFid) || (flags & ~(CloseOnExec | NonBlock | ReportFid))) {
51 SYSCALL_ERROR(OperationNotSupported);
52 return completion.finish(-1);
56 auto* subsystem =
static_cast<PosixSubsystem*
>(thread->getParent()->getSubsystem());
58 SYSCALL_ERROR(InvalidArgument);
59 return completion.finish(-1);
61 auto instance = FanotifyInstance::create();
63 return completion.finish(-1);
65 new FileDescriptor(
nullptr, 0, 0xFFFFFFFF, flags & CloseOnExec ? FD_CLOEXEC : 0,
66 O_RDWR | (flags & NonBlock ? O_NONBLOCK : 0));
67 if (!descriptor || !descriptor->acquireOpenFileDescription()) {
69 SYSCALL_ERROR(OutOfMemory);
70 return completion.finish(-1);
72 descriptor->setFanotifyImpl(instance);
74 const size_t fd = subsystem->installFileDescriptor(descriptor, published);
76 return completion.finish(
static_cast<int>(fd));
79int posix_fanotify_mark(
int fd,
unsigned flags, uint64_t mask,
int dirfd,
const char* path) {
80 FanotifyResult completion;
81 constexpr unsigned Add = 1, Remove = 2, DontFollow = 4, OnlyDirectory = 8, Flush = 0x80;
82 constexpr unsigned KnownFlags = 0x1ff;
83 const unsigned operation = flags & (Add | Remove | Flush);
84 if ((flags & ~KnownFlags) || (operation != Add && operation != Remove && operation != Flush) ||
85 (flags & 0x110) == 0x110) {
86 SYSCALL_ERROR(InvalidArgument);
87 return completion.finish(-1);
89 if (operation == Flush && flags != Flush) {
90 SYSCALL_ERROR(InvalidArgument);
91 return completion.finish(-1);
95 auto* subsystem =
static_cast<PosixSubsystem*
>(thread->getParent()->getSubsystem());
97 if (!subsystem || !subsystem->acquireFileDescriptor(fd, descriptor)) {
98 SYSCALL_ERROR(BadFileDescriptor);
99 return completion.finish(-1);
101 auto instance = descriptor->getFanotifyImpl();
103 SYSCALL_ERROR(InvalidArgument);
104 return completion.finish(-1);
106 if (flags & ~(Add | Remove | DontFollow | OnlyDirectory | Flush)) {
107 SYSCALL_ERROR(OperationNotSupported);
108 return completion.finish(-1);
110 if (operation == Flush) {
111 const int result = instance->flushMarks();
114 return completion.finish(result);
116 constexpr uint64_t KnownMask = 0x00001fff | 0x00004000 | 0x000f0000 | 0x08000000 | 0x40000000;
117 if (!mask || (mask & ~KnownMask) || (mask & (0x00070000 | 0x00004000))) {
118 SYSCALL_ERROR(InvalidArgument);
119 return completion.finish(-1);
121 constexpr uint64_t SupportedMask = 0x02 | 0x04 | 0x08 | 0x10 | 0x20;
122 if (mask & ~SupportedMask) {
123 SYSCALL_ERROR(OperationNotSupported);
124 return completion.finish(-1);
127 if (!path && dirfd == AT_FDCWD) {
128 SYSCALL_ERROR(BadFileDescriptor);
129 return completion.finish(-1);
131 if (!target.resolve(dirfd, path, !(flags & DontFollow),
false,
true))
132 return completion.finish(-1);
133 if ((flags & OnlyDirectory) && !target.file->
isDirectory()) {
134 SYSCALL_ERROR(NotADirectory);
135 return completion.finish(-1);
138 return completion.finish(-1);
141 auto status = target.mount.filesystem()->
encodeFileHandle(*target.file, handle);
142 if (status != FileHandleStatus::Success)
143 return completion.finish(posix_handle_error(status));
144 status = target.mount.filesystem()->fileHandleFsid(fsid);
145 if (status != FileHandleStatus::Success)
146 return completion.finish(posix_handle_error(status));
148 instance->changeMark(*target.file, target.mount, handle, fsid, mask, operation == Remove);
151 return completion.finish(result);
virtual bool isDirectory()
virtual FileHandleStatus encodeFileHandle(File &file, FileHandle &handle)
static ProcessorInformation & information()
static bool checkAccess(File *pFile, bool bRead, bool bWrite, bool bExecute)