1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 02:17:35 +00:00

Kernel: Make ProcessTracer inherit from File.

This commit is contained in:
Andreas Kling 2019-04-28 15:02:55 +02:00
parent 7ec1f6ab3c
commit e886337a67
12 changed files with 105 additions and 182 deletions

View file

@ -84,7 +84,7 @@ dword BXVGADevice::find_framebuffer_address()
return framebuffer_address; return framebuffer_address;
} }
Region* BXVGADevice::mmap(Process& process, LinearAddress preferred_laddr, size_t offset, size_t size) KResultOr<Region*> BXVGADevice::mmap(Process& process, LinearAddress preferred_laddr, size_t offset, size_t size)
{ {
ASSERT(offset == 0); ASSERT(offset == 0);
ASSERT(size == framebuffer_size_in_bytes()); ASSERT(size == framebuffer_size_in_bytes());

View file

@ -18,7 +18,7 @@ public:
void set_y_offset(int); void set_y_offset(int);
virtual int ioctl(Process&, unsigned request, unsigned arg) override; virtual int ioctl(Process&, unsigned request, unsigned arg) override;
virtual Region* mmap(Process&, LinearAddress preferred_laddr, size_t offset, size_t) override; virtual KResultOr<Region*> mmap(Process&, LinearAddress preferred_laddr, size_t offset, size_t) override;
size_t framebuffer_size_in_bytes() const { return m_framebuffer_size.area() * sizeof(dword) * 2; } size_t framebuffer_size_in_bytes() const { return m_framebuffer_size.area() * sizeof(dword) * 2; }
Size framebuffer_size() const { return m_framebuffer_size; } Size framebuffer_size() const { return m_framebuffer_size; }

View file

@ -7,7 +7,7 @@ class BlockDevice : public Device {
public: public:
virtual ~BlockDevice() override; virtual ~BlockDevice() override;
virtual Region* mmap(Process&, LinearAddress preferred_laddr, size_t offset, size_t size) = 0; virtual bool is_seekable() const override { return true; }
protected: protected:
BlockDevice(unsigned major, unsigned minor) : Device(major, minor) { } BlockDevice(unsigned major, unsigned minor) : Device(major, minor) { }

View file

@ -13,17 +13,7 @@ Device::~Device()
VFS::the().unregister_device(*this); VFS::the().unregister_device(*this);
} }
KResultOr<Retained<FileDescriptor>> Device::open(int options) String Device::absolute_path() const
{ {
UNUSED_PARAM(options); return String::format("device:%u,%u (%s)", m_major, m_minor, class_name());
return FileDescriptor::create(this);
}
void Device::close()
{
}
int Device::ioctl(Process&, unsigned, unsigned)
{
return -ENOTTY;
} }

View file

@ -33,42 +33,21 @@
// - Subclasses should take care to validate incoming addresses before dereferencing. // - Subclasses should take care to validate incoming addresses before dereferencing.
// //
#include <AK/Retainable.h> #include <Kernel/File.h>
#include <AK/Types.h>
#include <Kernel/FileSystem/FileDescriptor.h>
class Process; class Device : public File {
class Device : public Retainable<Device> {
public: public:
virtual ~Device(); virtual ~Device() override;
InodeMetadata metadata() const { return { }; }
virtual KResultOr<Retained<FileDescriptor>> open(int options);
virtual void close();
virtual bool can_read(Process&) const = 0;
virtual bool can_write(Process&) const = 0;
virtual ssize_t read(Process&, byte*, ssize_t) = 0;
virtual ssize_t write(Process&, const byte*, ssize_t) = 0;
unsigned major() const { return m_major; } unsigned major() const { return m_major; }
unsigned minor() const { return m_minor; } unsigned minor() const { return m_minor; }
virtual bool is_tty() const { return false; } virtual String absolute_path() const override;
virtual bool is_master_pty() const { return false; }
virtual int ioctl(Process&, unsigned request, unsigned arg);
virtual const char* class_name() const = 0;
uid_t uid() const { return m_uid; } uid_t uid() const { return m_uid; }
uid_t gid() const { return m_gid; } uid_t gid() const { return m_gid; }
virtual bool is_block_device() const { return false; } virtual bool is_device() const override { return true; }
virtual bool is_character_device() const { return false; }
protected: protected:
Device(unsigned major, unsigned minor); Device(unsigned major, unsigned minor);

View file

@ -1,3 +1,5 @@
#pragma once
#include <AK/Retainable.h> #include <AK/Retainable.h>
#include <AK/Types.h> #include <AK/Types.h>
#include <Kernel/FileSystem/FileDescriptor.h> #include <Kernel/FileSystem/FileDescriptor.h>

View file

@ -12,21 +12,15 @@
#include <Kernel/Devices/BlockDevice.h> #include <Kernel/Devices/BlockDevice.h>
#include <Kernel/VM/MemoryManager.h> #include <Kernel/VM/MemoryManager.h>
#include <Kernel/SharedMemory.h> #include <Kernel/SharedMemory.h>
#include <Kernel/ProcessTracer.h>
Retained<FileDescriptor> FileDescriptor::create(RetainPtr<Inode>&& inode) Retained<FileDescriptor> FileDescriptor::create(RetainPtr<Inode>&& inode)
{ {
return adopt(*new FileDescriptor(move(inode))); return adopt(*new FileDescriptor(move(inode)));
} }
Retained<FileDescriptor> FileDescriptor::create(RetainPtr<Device>&& device) Retained<FileDescriptor> FileDescriptor::create(RetainPtr<File>&& file)
{ {
return adopt(*new FileDescriptor(move(device))); return adopt(*new FileDescriptor(move(file)));
}
Retained<FileDescriptor> FileDescriptor::create(RetainPtr<ProcessTracer>&& tracer)
{
return adopt(*new FileDescriptor(move(tracer)));
} }
Retained<FileDescriptor> FileDescriptor::create(RetainPtr<SharedMemory>&& shared_memory) Retained<FileDescriptor> FileDescriptor::create(RetainPtr<SharedMemory>&& shared_memory)
@ -54,13 +48,8 @@ FileDescriptor::FileDescriptor(RetainPtr<Inode>&& inode)
{ {
} }
FileDescriptor::FileDescriptor(RetainPtr<Device>&& device) FileDescriptor::FileDescriptor(RetainPtr<File>&& file)
: m_device(move(device)) : m_file(move(file))
{
}
FileDescriptor::FileDescriptor(RetainPtr<ProcessTracer>&& tracer)
: m_tracer(move(tracer))
{ {
} }
@ -81,9 +70,9 @@ FileDescriptor::~FileDescriptor()
m_socket->detach_fd(m_socket_role); m_socket->detach_fd(m_socket_role);
m_socket = nullptr; m_socket = nullptr;
} }
if (m_device) { if (m_file) {
m_device->close(); m_file->close();
m_device = nullptr; m_file = nullptr;
} }
if (m_fifo) { if (m_fifo) {
m_fifo->close(fifo_direction()); m_fifo->close(fifo_direction());
@ -113,8 +102,8 @@ Retained<FileDescriptor> FileDescriptor::clone()
? FileDescriptor::create_pipe_reader(*m_fifo) ? FileDescriptor::create_pipe_reader(*m_fifo)
: FileDescriptor::create_pipe_writer(*m_fifo); : FileDescriptor::create_pipe_writer(*m_fifo);
} else { } else {
if (m_device) { if (m_file) {
descriptor = FileDescriptor::create(m_device.copy_ref()); descriptor = FileDescriptor::create(m_file.copy_ref());
descriptor->m_inode = m_inode.copy_ref(); descriptor->m_inode = m_inode.copy_ref();
} else if (m_socket) { } else if (m_socket) {
descriptor = FileDescriptor::create(m_socket.copy_ref(), m_socket_role); descriptor = FileDescriptor::create(m_socket.copy_ref(), m_socket_role);
@ -140,7 +129,7 @@ bool addition_would_overflow(off_t a, off_t b)
KResult FileDescriptor::fstat(stat& buffer) KResult FileDescriptor::fstat(stat& buffer)
{ {
ASSERT(!is_fifo()); ASSERT(!is_fifo());
if (!m_inode && !m_device) if (!m_inode && !m_file)
return KResult(-EBADF); return KResult(-EBADF);
auto metadata = this->metadata(); auto metadata = this->metadata();
@ -173,7 +162,7 @@ KResult FileDescriptor::fchmod(mode_t mode)
off_t FileDescriptor::seek(off_t offset, int whence) off_t FileDescriptor::seek(off_t offset, int whence)
{ {
ASSERT(!is_fifo()); ASSERT(!is_fifo());
if (!m_inode && !m_device) if (!m_inode && !m_file)
return -EBADF; return -EBADF;
// FIXME: The file type should be cached on the vnode. // FIXME: The file type should be cached on the vnode.
@ -210,15 +199,15 @@ off_t FileDescriptor::seek(off_t offset, int whence)
ssize_t FileDescriptor::read(Process& process, byte* buffer, ssize_t count) ssize_t FileDescriptor::read(Process& process, byte* buffer, ssize_t count)
{ {
if (m_tracer)
return m_tracer->read(buffer, count);
if (is_fifo()) { if (is_fifo()) {
ASSERT(fifo_direction() == FIFO::Reader); ASSERT(fifo_direction() == FIFO::Reader);
return m_fifo->read(buffer, count); return m_fifo->read(buffer, count);
} }
if (m_device) { if (m_file) {
// FIXME: What should happen to m_currentOffset? int nread = m_file->read(process, buffer, count);
return m_device->read(process, buffer, count); if (!m_file->is_seekable())
m_current_offset += nread;
return nread;
} }
if (m_socket) if (m_socket)
return m_socket->read(m_socket_role, buffer, count); return m_socket->read(m_socket_role, buffer, count);
@ -230,17 +219,15 @@ ssize_t FileDescriptor::read(Process& process, byte* buffer, ssize_t count)
ssize_t FileDescriptor::write(Process& process, const byte* data, ssize_t size) ssize_t FileDescriptor::write(Process& process, const byte* data, ssize_t size)
{ {
if (m_tracer) {
// FIXME: Figure out what the right error code would be.
return -EIO;
}
if (is_fifo()) { if (is_fifo()) {
ASSERT(fifo_direction() == FIFO::Writer); ASSERT(fifo_direction() == FIFO::Writer);
return m_fifo->write(data, size); return m_fifo->write(data, size);
} }
if (m_device) { if (m_file) {
// FIXME: What should happen to m_currentOffset? int nwritten = m_file->write(process, data, size);
return m_device->write(process, data, size); if (m_file->is_seekable())
m_current_offset += nwritten;
return nwritten;
} }
if (m_socket) if (m_socket)
return m_socket->write(m_socket_role, data, size); return m_socket->write(m_socket_role, data, size);
@ -252,14 +239,12 @@ ssize_t FileDescriptor::write(Process& process, const byte* data, ssize_t size)
bool FileDescriptor::can_write(Process& process) bool FileDescriptor::can_write(Process& process)
{ {
if (m_tracer)
return true;
if (is_fifo()) { if (is_fifo()) {
ASSERT(fifo_direction() == FIFO::Writer); ASSERT(fifo_direction() == FIFO::Writer);
return m_fifo->can_write(); return m_fifo->can_write();
} }
if (m_device) if (m_file)
return m_device->can_write(process); return m_file->can_write(process);
if (m_socket) if (m_socket)
return m_socket->can_write(m_socket_role); return m_socket->can_write(m_socket_role);
return true; return true;
@ -267,14 +252,12 @@ bool FileDescriptor::can_write(Process& process)
bool FileDescriptor::can_read(Process& process) bool FileDescriptor::can_read(Process& process)
{ {
if (m_tracer)
return m_tracer->can_read();
if (is_fifo()) { if (is_fifo()) {
ASSERT(fifo_direction() == FIFO::Reader); ASSERT(fifo_direction() == FIFO::Reader);
return m_fifo->can_read(); return m_fifo->can_read();
} }
if (m_device) if (m_file)
return m_device->can_read(process); return m_file->can_read(process);
if (m_socket) if (m_socket)
return m_socket->can_read(m_socket_role); return m_socket->can_read(m_socket_role);
return true; return true;
@ -282,11 +265,13 @@ bool FileDescriptor::can_read(Process& process)
ByteBuffer FileDescriptor::read_entire_file(Process& process) ByteBuffer FileDescriptor::read_entire_file(Process& process)
{ {
// HACK ALERT: (This entire function)
ASSERT(!is_fifo()); ASSERT(!is_fifo());
if (m_device) { if (m_file) {
auto buffer = ByteBuffer::create_uninitialized(1024); auto buffer = ByteBuffer::create_uninitialized(1024);
ssize_t nread = m_device->read(process, buffer.pointer(), buffer.size()); ssize_t nread = m_file->read(process, buffer.pointer(), buffer.size());
ASSERT(nread >= 0); ASSERT(nread >= 0);
buffer.trim(nread); buffer.trim(nread);
return buffer; return buffer;
@ -330,44 +315,47 @@ ssize_t FileDescriptor::get_dir_entries(byte* buffer, ssize_t size)
return stream.offset(); return stream.offset();
} }
bool FileDescriptor::is_device() const
{
return m_file && m_file->is_device();
}
bool FileDescriptor::is_tty() const bool FileDescriptor::is_tty() const
{ {
return m_device && m_device->is_tty(); return m_file && m_file->is_tty();
} }
const TTY* FileDescriptor::tty() const const TTY* FileDescriptor::tty() const
{ {
if (!is_tty()) if (!is_tty())
return nullptr; return nullptr;
return static_cast<const TTY*>(m_device.ptr()); return static_cast<const TTY*>(m_file.ptr());
} }
TTY* FileDescriptor::tty() TTY* FileDescriptor::tty()
{ {
if (!is_tty()) if (!is_tty())
return nullptr; return nullptr;
return static_cast<TTY*>(m_device.ptr()); return static_cast<TTY*>(m_file.ptr());
} }
bool FileDescriptor::is_master_pty() const bool FileDescriptor::is_master_pty() const
{ {
if (m_device) return m_file && m_file->is_master_pty();
return m_device->is_master_pty();
return false;
} }
const MasterPTY* FileDescriptor::master_pty() const const MasterPTY* FileDescriptor::master_pty() const
{ {
if (!is_master_pty()) if (!is_master_pty())
return nullptr; return nullptr;
return static_cast<const MasterPTY*>(m_device.ptr()); return static_cast<const MasterPTY*>(m_file.ptr());
} }
MasterPTY* FileDescriptor::master_pty() MasterPTY* FileDescriptor::master_pty()
{ {
if (!is_master_pty()) if (!is_master_pty())
return nullptr; return nullptr;
return static_cast<MasterPTY*>(m_device.ptr()); return static_cast<MasterPTY*>(m_file.ptr());
} }
int FileDescriptor::close() int FileDescriptor::close()
@ -389,22 +377,19 @@ const char* to_string(SocketRole role)
} }
} }
bool FileDescriptor::is_file() const bool FileDescriptor::is_fsfile() const
{ {
return !is_tty() && !is_fifo() && !is_device() && !is_socket() && !is_shared_memory(); return !is_tty() && !is_fifo() && !is_device() && !is_socket() && !is_shared_memory();
} }
KResultOr<String> FileDescriptor::absolute_path() KResultOr<String> FileDescriptor::absolute_path()
{ {
Stopwatch sw("absolute_path");
if (m_tracer)
return String::format("tracer:%d", m_tracer->pid());
if (is_tty()) if (is_tty())
return tty()->tty_name(); return tty()->tty_name();
if (is_fifo()) if (is_fifo())
return String::format("fifo:%u", m_fifo.ptr()); return String::format("fifo:%u", m_fifo.ptr());
if (is_device()) if (m_file)
return String::format("device:%u,%u (%s)", m_device->major(), m_device->minor(), m_device->class_name()); return m_file->absolute_path();
if (is_socket()) if (is_socket())
return String::format("socket:%x (role: %s)", m_socket.ptr(), to_string(m_socket_role)); return String::format("socket:%x (role: %s)", m_socket.ptr(), to_string(m_socket_role));
ASSERT(m_inode); ASSERT(m_inode);
@ -426,32 +411,20 @@ InodeMetadata FileDescriptor::metadata() const
return { }; return { };
} }
bool FileDescriptor::supports_mmap() const KResultOr<Region*> FileDescriptor::mmap(Process& process, LinearAddress laddr, size_t offset, size_t size, int prot)
{ {
if (m_tracer) if (m_file)
return false; return m_file->mmap(process, laddr, offset, size);
if (m_inode)
return true;
if (m_shared_memory)
return true;
if (m_device)
return m_device->is_block_device();
return false;
}
Region* FileDescriptor::mmap(Process& process, LinearAddress laddr, size_t offset, size_t size, int prot)
{
ASSERT(supports_mmap());
if (is_block_device())
return static_cast<BlockDevice&>(*m_device).mmap(process, laddr, offset, size);
if (is_shared_memory()) { if (is_shared_memory()) {
if (!shared_memory()->vmo()) if (!shared_memory()->vmo())
return nullptr; return KResult(-ENODEV);
return process.allocate_region_with_vmo(laddr, size, *shared_memory()->vmo(), offset, shared_memory()->name(), true, true); return process.allocate_region_with_vmo(laddr, size, *shared_memory()->vmo(), offset, shared_memory()->name(), true, true);
} }
if (!is_fsfile())
return KResult(-ENODEV);
ASSERT(m_inode); ASSERT(m_inode);
// FIXME: If PROT_EXEC, check that the underlying file system isn't mounted noexec. // FIXME: If PROT_EXEC, check that the underlying file system isn't mounted noexec.
String region_name; String region_name;
@ -469,26 +442,6 @@ Region* FileDescriptor::mmap(Process& process, LinearAddress laddr, size_t offse
return region; return region;
} }
bool FileDescriptor::is_block_device() const
{
return m_device && m_device->is_block_device();
}
bool FileDescriptor::is_character_device() const
{
return m_device && m_device->is_character_device();
}
CharacterDevice* FileDescriptor::character_device()
{
return is_character_device() ? static_cast<CharacterDevice*>(device()) : nullptr;
}
const CharacterDevice* FileDescriptor::character_device() const
{
return is_character_device() ? static_cast<const CharacterDevice*>(device()) : nullptr;
}
KResult FileDescriptor::truncate(off_t length) KResult FileDescriptor::truncate(off_t length)
{ {
if (is_file()) { if (is_file()) {

View file

@ -11,21 +11,19 @@
#include <Kernel/Net/Socket.h> #include <Kernel/Net/Socket.h>
#include <Kernel/SharedMemory.h> #include <Kernel/SharedMemory.h>
class File;
class TTY; class TTY;
class MasterPTY; class MasterPTY;
class Process; class Process;
class ProcessTracer;
class Region; class Region;
class CharacterDevice; class CharacterDevice;
class FileDescriptor : public Retainable<FileDescriptor> { class FileDescriptor : public Retainable<FileDescriptor> {
public: public:
static Retained<FileDescriptor> create(RetainPtr<Socket>&&, SocketRole = SocketRole::None); static Retained<FileDescriptor> create(RetainPtr<Socket>&&, SocketRole = SocketRole::None);
static Retained<FileDescriptor> create(RetainPtr<Inode>&&); static Retained<FileDescriptor> create(RetainPtr<Inode>&&);
static Retained<FileDescriptor> create(RetainPtr<Device>&&); static Retained<FileDescriptor> create(RetainPtr<File>&&);
static Retained<FileDescriptor> create(RetainPtr<SharedMemory>&&); static Retained<FileDescriptor> create(RetainPtr<SharedMemory>&&);
static Retained<FileDescriptor> create(RetainPtr<ProcessTracer>&&);
static Retained<FileDescriptor> create_pipe_writer(FIFO&); static Retained<FileDescriptor> create_pipe_writer(FIFO&);
static Retained<FileDescriptor> create_pipe_reader(FIFO&); static Retained<FileDescriptor> create_pipe_reader(FIFO&);
~FileDescriptor(); ~FileDescriptor();
@ -52,14 +50,12 @@ public:
bool is_directory() const; bool is_directory() const;
bool is_device() const { return m_device.ptr(); } // FIXME: These should go away once everything is a File.
Device* device() { return m_device.ptr(); } bool is_file() const { return m_file.ptr(); }
const Device* device() const { return m_device.ptr(); } File* file() { return m_file.ptr(); }
const File* file() const { return m_file.ptr(); }
bool is_block_device() const; bool is_device() const;
bool is_character_device() const;
CharacterDevice* character_device();
const CharacterDevice* character_device() const;
bool is_tty() const; bool is_tty() const;
const TTY* tty() const; const TTY* tty() const;
@ -73,8 +69,7 @@ public:
Inode* inode() { return m_inode.ptr(); } Inode* inode() { return m_inode.ptr(); }
const Inode* inode() const { return m_inode.ptr(); } const Inode* inode() const { return m_inode.ptr(); }
bool supports_mmap() const; KResultOr<Region*> mmap(Process&, LinearAddress, size_t offset, size_t, int prot);
Region* mmap(Process&, LinearAddress, size_t offset, size_t, int prot);
bool is_blocking() const { return m_is_blocking; } bool is_blocking() const { return m_is_blocking; }
void set_blocking(bool b) { m_is_blocking = b; } void set_blocking(bool b) { m_is_blocking = b; }
@ -89,7 +84,7 @@ public:
bool is_fifo() const { return m_fifo; } bool is_fifo() const { return m_fifo; }
FIFO::Direction fifo_direction() { return m_fifo_direction; } FIFO::Direction fifo_direction() { return m_fifo_direction; }
bool is_file() const; bool is_fsfile() const;
bool is_shared_memory() const { return m_shared_memory; } bool is_shared_memory() const { return m_shared_memory; }
SharedMemory* shared_memory() { return m_shared_memory.ptr(); } SharedMemory* shared_memory() { return m_shared_memory.ptr(); }
const SharedMemory* shared_memory() const { return m_shared_memory.ptr(); } const SharedMemory* shared_memory() const { return m_shared_memory.ptr(); }
@ -103,20 +98,16 @@ public:
KResult truncate(off_t); KResult truncate(off_t);
ProcessTracer* tracer() { return m_tracer.ptr(); }
const ProcessTracer* tracer() const { return m_tracer.ptr(); }
private: private:
friend class VFS; friend class VFS;
FileDescriptor(RetainPtr<Socket>&&, SocketRole); FileDescriptor(RetainPtr<Socket>&&, SocketRole);
explicit FileDescriptor(RetainPtr<Inode>&&); explicit FileDescriptor(RetainPtr<Inode>&&);
explicit FileDescriptor(RetainPtr<Device>&&); explicit FileDescriptor(RetainPtr<File>&&);
explicit FileDescriptor(RetainPtr<ProcessTracer>&&);
explicit FileDescriptor(RetainPtr<SharedMemory>&&); explicit FileDescriptor(RetainPtr<SharedMemory>&&);
FileDescriptor(FIFO&, FIFO::Direction); FileDescriptor(FIFO&, FIFO::Direction);
RetainPtr<Inode> m_inode; RetainPtr<Inode> m_inode;
RetainPtr<Device> m_device; RetainPtr<File> m_file;
off_t m_current_offset { 0 }; off_t m_current_offset { 0 };
@ -132,7 +123,6 @@ private:
FIFO::Direction m_fifo_direction { FIFO::Neither }; FIFO::Direction m_fifo_direction { FIFO::Neither };
RetainPtr<SharedMemory> m_shared_memory; RetainPtr<SharedMemory> m_shared_memory;
RetainPtr<ProcessTracer> m_tracer;
bool m_closed { false }; bool m_closed { false };
}; };

View file

@ -48,7 +48,8 @@ KERNEL_OBJS = \
Net/LoopbackAdapter.o \ Net/LoopbackAdapter.o \
Net/Routing.o \ Net/Routing.o \
Net/NetworkTask.o \ Net/NetworkTask.o \
ProcessTracer.o ProcessTracer.o \
File.o
VFS_OBJS = \ VFS_OBJS = \
FileSystem/ProcFS.o \ FileSystem/ProcFS.o \

View file

@ -175,11 +175,10 @@ void* Process::sys$mmap(const Syscall::SC_mmap_params* params)
auto* descriptor = file_descriptor(fd); auto* descriptor = file_descriptor(fd);
if (!descriptor) if (!descriptor)
return (void*)-EBADF; return (void*)-EBADF;
if (!descriptor->supports_mmap()) auto region_or_error = descriptor->mmap(*this, LinearAddress((dword)addr), offset, size, prot);
return (void*)-ENODEV; if (region_or_error.is_error())
auto* region = descriptor->mmap(*this, LinearAddress((dword)addr), offset, size, prot); return (void*)(int)region_or_error.error();
if (!region) auto region = region_or_error.value();
return (void*)-ENOMEM;
if (flags & MAP_SHARED) if (flags & MAP_SHARED)
region->set_shared(true); region->set_shared(true);
return region->laddr().as_ptr(); return region->laddr().as_ptr();
@ -1539,9 +1538,9 @@ int Process::sys$ioctl(int fd, unsigned request, unsigned arg)
auto* descriptor = file_descriptor(fd); auto* descriptor = file_descriptor(fd);
if (!descriptor) if (!descriptor)
return -EBADF; return -EBADF;
if (!descriptor->is_device()) if (!descriptor->is_file())
return -ENOTTY; return -ENOTTY;
return descriptor->device()->ioctl(*this, request, arg); return descriptor->file()->ioctl(*this, request, arg);
} }
int Process::sys$getdtablesize() int Process::sys$getdtablesize()

View file

@ -18,14 +18,18 @@ void ProcessTracer::did_syscall(dword function, dword arg1, dword arg2, dword ar
m_calls.enqueue(data); m_calls.enqueue(data);
} }
int ProcessTracer::read(byte* buffer, int buffer_size) int ProcessTracer::read(Process&, byte* buffer, int buffer_size)
{ {
if (!m_calls.is_empty()) { if (m_calls.is_empty())
auto data = m_calls.dequeue(); return 0;
// FIXME: This should not be an assertion. auto data = m_calls.dequeue();
ASSERT(buffer_size == sizeof(data)); // FIXME: This should not be an assertion.
memcpy(buffer, &data, sizeof(data)); ASSERT(buffer_size == sizeof(data));
return sizeof(data); memcpy(buffer, &data, sizeof(data));
} return sizeof(data);
return 0; }
String ProcessTracer::absolute_path() const
{
return String::format("tracer:%d", m_pid);
} }

View file

@ -1,25 +1,30 @@
#pragma once #pragma once
#include <AK/Retainable.h> #include <Kernel/File.h>
#include <AK/Retained.h>
#include <AK/CircularQueue.h> #include <AK/CircularQueue.h>
#include <Kernel/UnixTypes.h> #include <Kernel/UnixTypes.h>
class ProcessTracer : public Retainable<ProcessTracer> { class ProcessTracer : public File {
public: public:
static Retained<ProcessTracer> create(pid_t pid) { return adopt(*new ProcessTracer(pid)); } static Retained<ProcessTracer> create(pid_t pid) { return adopt(*new ProcessTracer(pid)); }
~ProcessTracer(); virtual ~ProcessTracer() override;
bool is_dead() const { return m_dead; } bool is_dead() const { return m_dead; }
void set_dead() { m_dead = true; } void set_dead() { m_dead = true; }
bool can_read() const { return !m_calls.is_empty() || m_dead; } virtual bool can_read(Process&) const override { return !m_calls.is_empty() || m_dead; }
int read(byte*, int); virtual int read(Process&, byte*, int) override;
virtual bool can_write(Process&) const override { return true; }
virtual int write(Process&, const byte*, int) override { return -EIO; }
virtual String absolute_path() const override;
void did_syscall(dword function, dword arg1, dword arg2, dword arg3, dword result); void did_syscall(dword function, dword arg1, dword arg2, dword arg3, dword result);
pid_t pid() const { return m_pid; } pid_t pid() const { return m_pid; }
private: private:
virtual const char* class_name() const override { return "ProcessTracer"; }
explicit ProcessTracer(pid_t); explicit ProcessTracer(pid_t);
struct CallData { struct CallData {