2#include "descriptor-path.h"
3#include "pedigree/kernel/process/Thread.h"
4#include "pedigree/kernel/processor/Processor.h"
5#include "pedigree/kernel/processor/ProcessorInformation.h"
6#include "pedigree/kernel/syscallError.h"
7#include "pedigree/kernel/utilities/StaticString.h"
8#include "pedigree/kernel/utilities/utility.h"
11#include "PosixSubsystem.h"
13#include "fanotify-syscalls.h"
14#include "modules/system/vfs/MountView.h"
15#include "modules/system/vfs/Symlink.h"
16#include "signalfd-syscalls.h"
17#include "timerfd-syscalls.h"
20constexpr uint32_t DirectoryPermissions = FILE_UR | FILE_UX | FILE_GR | FILE_GX | FILE_OR | FILE_OX;
21constexpr uint32_t LinkPermissions =
22 FILE_UR | FILE_UW | FILE_UX | FILE_GR | FILE_GW | FILE_GX | FILE_OR | FILE_OW | FILE_OX;
24class DescriptorOwner {
27 : m_Pid(pid), m_Identity(
identity) {}
31 auto* process = thread ? thread->
getParent() :
nullptr;
32 if (!process || process->getType() != Process::Posix) {
35 SYSCALL_ERROR(PermissionDenied);
38 auto* subsystem =
static_cast<PosixSubsystem*
>(process->getSubsystem());
39 if (!subsystem || subsystem->namespaceContext().get() != m_Identity.get()) {
40 SYSCALL_ERROR(DoesNotExist);
51bool descriptorNumber(
const StringView& name,
size_t& number) {
52 if (!name.length() || (name.length() > 1 && name[0] ==
'0'))
55 for (
size_t i = 0; i < name.length(); ++i) {
56 const char ch = name[i];
57 if (ch <
'0' || ch >
'9' || number > (~
size_t(0) - (ch -
'0')) / 10)
59 number = number * 10 + ch -
'0';
64class DescriptorLink final :
public Symlink {
66 DescriptorLink(
ProcFs& filesystem,
File* parent,
const String& name,
const DescriptorOwner& owner,
68 :
Symlink(name, 0, 0, 0, filesystem.getNextInode(), &filesystem, 0, parent),
71 setPermissions(LinkPermissions);
80 if (!acquire(descriptor))
82 auto path = descriptor->openingPath();
88 File* file = descriptor->getFile();
90 SYSCALL_ERROR(NoSuchDevice);
93 return view->anonymousPath(file, result);
98 SYSCALL_ERROR(OperationNotSupported);
102 int followLink(
char* buffer,
size_t length)
override {
104 if (!acquire(descriptor))
107 if (descriptor->getTimerFdImpl())
108 target.assign(
"anon_inode:[timerfd]");
109 else if (descriptor->getSignalFdImpl())
110 target.assign(
"anon_inode:[signalfd]");
111 else if (descriptor->getFanotifyImpl())
112 target.assign(
"anon_inode:[fanotify]");
113 else if (
File* file = descriptor->getFile()) {
114 auto path = descriptor->openingPath();
116 if (path && view && view->attachmentId(path)) {
120 if (!context || !context->snapshot(snapshot) || !view->formatPath(snapshot, path, target))
126 if (!file->getAttributes().links)
127 target +=
" (deleted)";
129 SYSCALL_ERROR(NoSuchDevice);
132 const size_t copied = length < target.length() ? length : target.length();
133 MemoryCopy(buffer, target.cstr(), copied);
134 return static_cast<int>(copied);
139 auto* subsystem = m_Owner.acquire();
142 if (!subsystem->acquireFileDescriptor(m_Fd, descriptor)) {
143 SYSCALL_ERROR(DoesNotExist);
148 DescriptorOwner m_Owner;
154 DescriptorDirectory(
ProcFs& filesystem,
File* parent,
size_t pid,
158 setPermissions(DirectoryPermissions);
169 if (!descriptorNumber(name, fd))
170 return LookupStatus::NotFound;
171 auto* subsystem = m_Owner.acquire();
173 return LookupStatus::NotFound;
175 if (!subsystem->acquireFileDescriptor(fd, descriptor))
176 return LookupStatus::NotFound;
178 new DescriptorLink(*
static_cast<ProcFs*
>(getFilesystem()),
this,
String(name), m_Owner, fd);
179 return child ? LookupStatus::Found : LookupStatus::IoError;
182 ReadStatus
readDirectory(uint64_t& cookie, DirectoryEntryEmitter emitter,
183 void* context)
override {
184 auto* subsystem = m_Owner.acquire();
186 return ReadStatus::IoError;
189 while (subsystem->acquireNextFileDescriptor(cookie, fd, descriptor)) {
192 DirectoryEntryView entry{
StringView(name, name.length()),
193 static_cast<ProcFs*
>(getFilesystem())->getNextInode(),
194 EntryType::Symlink, cookie, fd + 1};
195 if (!emitter(context, entry))
196 return ReadStatus::Stopped;
199 return ReadStatus::Complete;
203 DescriptorOwner m_Owner;
206class DevFdLink final :
public Symlink {
208 DevFdLink(
DevFs& filesystem,
File* parent)
209 :
Symlink(
String(
"fd"), 0, 0, 0, filesystem.getNextInode(), &filesystem, 12, parent) {
210 m_sTarget.assign(
"/proc/self/fd");
211 setPermissions(LinkPermissions);
216File* posix_make_descriptor_directory(
ProcFs& filesystem,
File* parent,
size_t pid,
218 return new DescriptorDirectory(filesystem, parent, pid,
identity);
221File* posix_make_dev_fd_link(
DevFs& filesystem,
File* parent) {
222 return new DevFdLink(filesystem, parent);
virtual bool cacheResolvedChildren() const
virtual ReadStatus readDirectory(uint64_t &cookie, DirectoryEntryEmitter emitter, void *context)
virtual LookupStatus resolveChild(const StringView &name, File *&child)
static ProcessorInformation & information()
virtual File * followLinkRetained(Directory::ChildLease &result)
virtual int followLink(char *pBuffer, size_t bufLen)
virtual bool isPathLink() const