1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 18:37:34 +00:00

Add basic symlink support.

- sys$readlink + readlink()
- Add a /proc/PID/exe symlink to the process's executable.
- Print symlink contents in ls output.
- Some work on plumbing options into VFS::open().
This commit is contained in:
Andreas Kling 2018-10-28 14:11:51 +01:00
parent 1d4af51250
commit 97726862dd
20 changed files with 140 additions and 46 deletions

View file

@ -96,6 +96,16 @@ ByteBuffer procfs$pid_stack(Task& task)
return buffer;
}
ByteBuffer procfs$pid_exe(Task& task)
{
InodeIdentifier inode;
{
InterruptDisabler disabler;
inode = task.executableInode();
}
return VirtualFileSystem::the().absolutePath(inode).toByteBuffer();
}
void ProcFileSystem::addProcess(Task& task)
{
ASSERT_INTERRUPTS_DISABLED();
@ -105,6 +115,8 @@ void ProcFileSystem::addProcess(Task& task)
m_pid2inode.set(task.pid(), dir.index());
addFile(createGeneratedFile("vm", [&task] { return procfs$pid_vm(task); }), dir.index());
addFile(createGeneratedFile("stack", [&task] { return procfs$pid_stack(task); }), dir.index());
if (task.executableInode().isValid())
addFile(createGeneratedFile("exe", [&task] { return procfs$pid_exe(task); }, 00120777), dir.index());
}
void ProcFileSystem::removeProcess(Task& task)

View file

@ -116,6 +116,8 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3)
return current->sys$uname((utsname*)arg1);
case Syscall::SetMmapName:
return current->sys$set_mmap_name((void*)arg1, (size_t)arg2, (const char*)arg3);
case Syscall::PosixReadlink:
return current->sys$readlink((const char*)arg1, (char*)arg2, (size_t)arg3);
default:
kprintf("int0x80: Unknown function %x requested {%x, %x, %x}\n", function, arg1, arg2, arg3);
break;

View file

@ -35,6 +35,7 @@ enum Function {
PosixChdir = 0x2003,
PosixUname = 0x2004,
SetMmapName = 0x2005,
PosixReadlink = 0x2006,
};
void initialize();

View file

@ -234,7 +234,7 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
cwd = parentTask->m_cwd.copyRef();
}
auto handle = VirtualFileSystem::the().open(path, cwd ? cwd->inode : InodeIdentifier());
auto handle = VirtualFileSystem::the().open(path, 0, cwd ? cwd->inode : InodeIdentifier());
if (!handle) {
error = -ENOENT; // FIXME: Get a more detailed error from VFS.
return nullptr;
@ -261,7 +261,7 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
}
InterruptDisabler disabler; // FIXME: Get rid of this, jesus christ. This "critical" section is HUGE.
Task* t = new Task(parts.takeLast(), uid, gid, parentPID, Ring3);
Task* t = new Task(parts.takeLast(), uid, gid, parentPID, Ring3, handle->vnode());
t->m_arguments = move(taskArguments);
@ -362,13 +362,14 @@ Task* Task::createKernelTask(void (*e)(), String&& name)
return task;
}
Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring)
Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring, RetainPtr<VirtualFileSystem::Node>&& executable)
: m_name(move(name))
, m_pid(next_pid++)
, m_uid(uid)
, m_gid(gid)
, m_state(Runnable)
, m_ring(ring)
, m_executable(move(executable))
, m_parentPID(parentPID)
{
m_fileHandles.append(nullptr); // stdin
@ -785,17 +786,39 @@ int Task::sys$close(int fd)
int Task::sys$lstat(const char* path, Unix::stat* statbuf)
{
VALIDATE_USER_BUFFER(statbuf, sizeof(Unix::stat));
auto handle = VirtualFileSystem::the().open(move(path), cwdInode());
auto handle = VirtualFileSystem::the().open(move(path), O_NOFOLLOW_NOERROR, cwdInode());
if (!handle)
return -1;
handle->stat(statbuf);
return 0;
}
int Task::sys$readlink(const char* path, char* buffer, size_t size)
{
VALIDATE_USER_BUFFER(path, strlen(path));
VALIDATE_USER_BUFFER(buffer, size);
auto handle = VirtualFileSystem::the().open(path, O_RDONLY | O_NOFOLLOW_NOERROR, cwdInode());
if (!handle)
return -ENOENT; // FIXME: Get a more detailed error from VFS.
if (!handle->metadata().isSymbolicLink())
return -EINVAL;
auto contents = handle->readEntireFile();
if (!contents)
return -EIO; // FIXME: Get a more detailed error from VFS.
memcpy(buffer, contents.pointer(), min(size, contents.size()));
if (contents.size() + 1 < size)
buffer[contents.size()] = '\0';
return 0;
}
int Task::sys$chdir(const char* path)
{
VALIDATE_USER_BUFFER(path, strlen(path));
auto handle = VirtualFileSystem::the().open(path, cwdInode());
auto handle = VirtualFileSystem::the().open(path, 0, cwdInode());
if (!handle)
return -ENOENT; // FIXME: More detailed error.
if (!handle->isDirectory())
@ -811,17 +834,20 @@ int Task::sys$getcwd(char* buffer, size_t size)
return -ENOTIMPL;
}
int Task::sys$open(const char* path, size_t pathLength)
int Task::sys$open(const char* path, int options)
{
#ifdef DEBUG_IO
kprintf("Task::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength);
#endif
VALIDATE_USER_BUFFER(path, pathLength);
VALIDATE_USER_BUFFER(path, strlen(path));
if (m_fileHandles.size() >= m_maxFileHandles)
return -EMFILE;
auto handle = VirtualFileSystem::the().open(String(path, pathLength), cwdInode());
auto handle = VirtualFileSystem::the().open(path, 0, cwdInode());
if (!handle)
return -ENOENT; // FIXME: Detailed error.
if (options & O_DIRECTORY && !handle->isDirectory())
return -ENOTDIR; // FIXME: This should be handled by VFS::open.
int fd = m_fileHandles.size();
handle->setFD(fd);
m_fileHandles.append(move(handle));

View file

@ -87,7 +87,7 @@ public:
uid_t sys$getuid();
gid_t sys$getgid();
pid_t sys$getpid();
int sys$open(const char* path, size_t pathLength);
int sys$open(const char* path, int options);
int sys$close(int fd);
int sys$read(int fd, void* outbuf, size_t nread);
int sys$lstat(const char*, Unix::stat*);
@ -108,6 +108,7 @@ public:
int sys$gethostname(char* name, size_t length);
int sys$get_arguments(int* argc, char*** argv);
int sys$uname(utsname*);
int sys$readlink(const char*, char*, size_t);
static void initialize();
@ -134,12 +135,13 @@ public:
bool isValidAddressForUser(LinearAddress) const;
InodeIdentifier cwdInode() const { return m_cwd ? m_cwd->inode : InodeIdentifier(); }
InodeIdentifier executableInode() const { return m_executable ? m_executable->inode : InodeIdentifier(); }
private:
friend class MemoryManager;
friend bool scheduleNewTask();
Task(String&& name, uid_t, gid_t, pid_t parentPID, RingLevel);
Task(String&& name, uid_t, gid_t, pid_t parentPID, RingLevel, RetainPtr<VirtualFileSystem::Node>&& = nullptr);
void allocateLDT();
@ -171,6 +173,7 @@ private:
size_t m_maxFileHandles { 16 };
RetainPtr<VirtualFileSystem::Node> m_cwd;
RetainPtr<VirtualFileSystem::Node> m_executable;
struct Region : public Retainable<Region> {
Region(LinearAddress, size_t, RetainPtr<Zone>&&, String&&);

View file

@ -35,7 +35,6 @@
#define EDOM 33 // Math argument out of domain of func
#define ERANGE 34 // Math result not representable
#define ENAMETOOLONG 36 // Name too long
#define ELOOP 40 // Too many symbolic links
#define EOVERFLOW 75 // Value too large for defined data type
#define ENOTIMPL 999 // Not implemented