2#include "advisory-lock-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"
13#include "FileDescriptor.h"
14#include "PosixSubsystem.h"
15#include "advisory-lock-state.h"
16#include "modules/system/vfs/File.h"
19using namespace PosixAdvisory;
31static_assert(
sizeof(LinuxFlock) == 32,
"Linux amd64 flock size");
32static_assert(offsetof(LinuxFlock, type) == 0 && offsetof(LinuxFlock, whence) == 2 &&
33 offsetof(LinuxFlock, start) == 8 && offsetof(LinuxFlock, length) == 16 &&
34 offsetof(LinuxFlock, pid) == 24,
35 "Linux amd64 flock offsets");
37bool regularFile(
File* file) {
39 SYSCALL_ERROR(OperationNotSupported);
51bool admit(
void* context) {
52 const auto& admission = *
static_cast<Admission*
>(context);
53 return admission.subsystem.descriptorMatchesOpenDescription(admission.fd, admission.description);
57int posix_advisory_flock(
const DescriptorLease& descriptor,
int operation) {
59 const int lockType = operation & ~LOCK_NB;
60 if (lockType != LOCK_SH && lockType != LOCK_EX && lockType != LOCK_UN) {
61 SYSCALL_ERROR(InvalidArgument);
65 SYSCALL_ERROR(BadFileDescriptor);
69 File* file = description->getFile();
70 if (!regularFile(file))
73 SYSCALL_ERROR(BadFileDescriptor);
79 request.name = Namespace::Flock;
81 lockType == LOCK_UN ? Type::Unlock : (lockType == LOCK_SH ? Type::Read : Type::Write);
82 return posix_advisory_apply(description->advisoryOwner(), request, !(operation & LOCK_NB));
86 int command,
void* userLock) {
88 const bool ofd = command == F_OFD_GETLK || command == F_OFD_SETLK || command == F_OFD_SETLKW;
89 const bool query = command == F_GETLK || command == F_OFD_GETLK;
90 const bool wait = command == F_SETLKW || command == F_OFD_SETLKW;
91 if (!ofd && command != F_GETLK && command != F_SETLK && command != F_SETLKW) {
92 SYSCALL_ERROR(InvalidArgument);
96 SYSCALL_ERROR(BadFileDescriptor);
100 File* file = description->getFile();
101 if (!regularFile(file))
104 if (flags & O_PATH) {
105 SYSCALL_ERROR(BadFileDescriptor);
110 SYSCALL_ERROR(BadAddress);
113 if ((wire.type != F_RDLCK && wire.type != F_WRLCK && wire.type != F_UNLCK) ||
114 (command == F_GETLK && wire.type == F_UNLCK) || (ofd && wire.pid)) {
115 SYSCALL_ERROR(InvalidArgument);
121 wire.type == F_UNLCK ? Type::Unlock : (wire.type == F_RDLCK ? Type::Read : Type::Write);
122 request.pid =
static_cast<int32_t
>(
124 uint64_t position = 0, fileSize = 0;
125 if (wire.whence == 1) {
127 position = positionGuard.offset();
128 }
else if (wire.whence == 2) {
130 fileSize = file->getSize();
132 const RangeResult range =
133 normalise(wire.whence, wire.start, wire.length, position, fileSize, request.range);
134 if (range != RangeResult::Success) {
135 syscallError(range == RangeResult::Overflow ? Error::ValueTooLarge : Error::InvalidArgument);
138 AdvisoryOwner& owner = ofd ? description->advisoryOwner() : subsystem.advisoryOwner();
142 if (posix_advisory_query(owner, request, conflict, found) < 0)
146 wire.type = conflict.type == Type::Read ? F_RDLCK : F_WRLCK;
148 wire.start = conflict.range.first;
150 conflict.range.last == LastOffset ? 0 : conflict.range.last - conflict.range.first + 1;
151 wire.pid = conflict.pid;
154 SYSCALL_ERROR(BadAddress);
159 if ((request.type == Type::Read && (flags & O_ACCMODE) == O_WRONLY) ||
160 (request.type == Type::Write && (flags & O_ACCMODE) == O_RDONLY)) {
161 SYSCALL_ERROR(BadFileDescriptor);
164 Admission admission{subsystem,
static_cast<size_t>(fd), description};
165 return posix_advisory_apply(owner, request, wait,
166 !ofd && request.type != Type::Unlock ? admit : nullptr, &admission);
OpenFileDescriptionLease acquireOpenFileDescription() const
PositionGuard lockPosition() const
int getStatusFlags() const
Get current status flags.
bool supportsRegularFileOperations()
virtual uintptr_t futexIdentity()
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static bool copyToUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static ProcessorInformation & information()