2#include "filesystem-capability-syscalls.h"
3#include "pedigree/kernel/LockGuard.h"
4#include "pedigree/kernel/process/Process.h"
5#include "pedigree/kernel/process/TerminationDeferral.h"
6#include "pedigree/kernel/process/Thread.h"
7#include "pedigree/kernel/processor/Processor.h"
8#include "pedigree/kernel/processor/ProcessorInformation.h"
9#include "pedigree/kernel/syscallError.h"
14#include "FileDescriptor.h"
15#include "PosixSubsystem.h"
16#include "ResolvedPath.h"
17#include "UnixFilesystem.h"
18#include "file-syscalls.h"
19#include "modules/system/vfs/File.h"
20#include "modules/system/vfs/MountView.h"
21#include "modules/system/vfs/VFS.h"
24constexpr uint64_t MaximumPosition = 0x7fffffffffffffffULL;
25constexpr unsigned RenameNoReplace = 1, RenameExchange = 2, RenameWhiteout = 4;
27struct FilesystemResult {
28 FilesystemResult(
int result)
30 error(result < 0 ?
Processor::information().getCurrentThread()->getErrno() : 0) {}
37 String copied, normalised, basename;
40 bool copy(
const char* user) {
42 if (result != PosixSubsystem::UserStringSuccess) {
43 syscallError(result == PosixSubsystem::UserStringBadAddress ? Error::BadAddress
44 : Error::NameTooLong);
47 if (!copied.length()) {
48 SYSCALL_ERROR(DoesNotExist);
51 normalisePath(normalised, copied.cstr());
58 if (copied[0] !=
'/' && fd != AT_FDCWD) {
59 auto* subsystem =
static_cast<PosixSubsystem*
>(process->getSubsystem());
60 if (!subsystem || !subsystem->acquireFileDescriptor(fd, descriptor) ||
61 !descriptor->getFile()) {
62 SYSCALL_ERROR(BadFileDescriptor);
65 start = descriptor->openingPath();
66 if (!descriptor->getFile()->
isDirectory() || !start) {
67 SYSCALL_ERROR(NotADirectory);
72 if (!view.resolveParent(context, start, normalised, selected, basename))
74 parent.retain(selected);
78FilesystemResult allocate(
int fd,
int mode, off_t offset, off_t length) {
83 if (!subsystem || !subsystem->acquireFileDescriptor(fd, descriptor) ||
84 (descriptor->
getStatusFlags() & O_PATH) || !descriptor->getFile()) {
85 SYSCALL_ERROR(BadFileDescriptor);
88 if (offset < 0 || length <= 0) {
89 SYSCALL_ERROR(InvalidArgument);
92 constexpr unsigned KeepSize = 1;
93 if (
static_cast<unsigned>(mode) & ~KeepSize) {
94 SYSCALL_ERROR(OperationNotSupported);
98 if (access != O_WRONLY && access != O_RDWR) {
99 SYSCALL_ERROR(BadFileDescriptor);
103 if (descriptor->openingPath() && !mountWrite.acquire(descriptor->openingPath())) {
106 File* file = descriptor->getFile();
108 SYSCALL_ERROR(IllegalSeek);
112 SYSCALL_ERROR(IsADirectory);
116 SYSCALL_ERROR(DeviceDoesNotExist);
119 if (
static_cast<uint64_t
>(length) > MaximumPosition -
static_cast<uint64_t
>(offset)) {
120 SYSCALL_ERROR(FileTooLarge);
126 SYSCALL_ERROR(IoError);
133FilesystemResult renameWithFlags(
int oldDirFd,
const char* oldPath,
int newDirFd,
134 const char* newPath,
unsigned flags) {
135 if ((flags & ~(RenameNoReplace | RenameExchange | RenameWhiteout)) ||
136 ((flags & RenameExchange) && (flags & (RenameNoReplace | RenameWhiteout)))) {
137 SYSCALL_ERROR(InvalidArgument);
140 if (flags & (RenameExchange | RenameWhiteout)) {
141 SYSCALL_ERROR(OperationNotSupported);
145 return posix_renameat(oldDirFd, oldPath, newDirFd, newPath);
147 RenamePath source, destination;
148 if (!source.copy(oldPath) || !destination.copy(newPath))
151 auto context = process->acquireFilesystemContext();
153 if (!context || !view) {
154 SYSCALL_ERROR(DoesNotExist);
157 if (!source.resolve(oldDirFd, *view, context) || !destination.resolve(newDirFd, *view, context))
160 return view->rename(source.parent.path(), source.basename, destination.parent.path(),
161 destination.basename,
true,
162 source.copied.endswith(
'/') || destination.copied.endswith(
'/'))
169int posix_fallocate(
int fd,
int mode, off_t offset, off_t length) {
170 const FilesystemResult result = allocate(fd, mode, offset, length);
171 syscallError(result.error);
175int posix_renameat2(
int oldDirFd,
const char* oldPath,
int newDirFd,
const char* newPath,
177 const FilesystemResult result = renameWithFlags(oldDirFd, oldPath, newDirFd, newPath, flags);
178 syscallError(result.error);
int getStatusFlags() const
Get current status flags.
bool supportsRegularFileOperations()
bool allocateRange(size_t offset, size_t length, bool keepSize=false)
virtual bool isDirectory()
virtual bool isFifo() const
virtual bool isPipe() const
static UserStringResult copyUserString(const char *userString, String ©, size_t maxLength)
static ProcessorInformation & information()
void setErrno(size_t err)
Process * getParent() const