From ec1d16b307e1467391d5d314bf700cb151ca96f4 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 24 Oct 2018 14:28:22 +0200 Subject: [PATCH] Add a "pwd" utility to userland. It's implemented as a separate process. How cute is that. Tasks now have a current working directory. Spawned tasks inherit their parent task's working directory. Currently everyone just uses "/" as there's no way to chdir(). --- AK/String.h | 10 +++++++-- Kernel/Syscall.cpp | 2 ++ Kernel/Syscall.h | 1 + Kernel/Task.cpp | 28 ++++++++++++++++++++++---- Kernel/Task.h | 9 +++++++-- Kernel/_fs_contents | Bin 1024000 -> 1024000 bytes Kernel/init.cpp | 2 +- Kernel/sync-sh | 1 + LibC/unistd.cpp | 8 ++++++++ LibC/unistd.h | 4 +--- Userland/.gitignore | 1 + Userland/Makefile | 9 +++++++-- Userland/pwd.cpp | 15 ++++++++++++++ VirtualFileSystem/FileHandle.cpp | 3 +++ VirtualFileSystem/FileHandle.h | 2 ++ VirtualFileSystem/InodeIdentifier.h | 5 +++++ VirtualFileSystem/VirtualFileSystem.h | 1 + 17 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 Userland/pwd.cpp diff --git a/AK/String.h b/AK/String.h index 4def06f2e6..96a193a331 100644 --- a/AK/String.h +++ b/AK/String.h @@ -76,9 +76,15 @@ public: String& operator=(String&& other) { - if (this != &other) { + if (this != &other) m_impl = move(other.m_impl); - } + return *this; + } + + String& operator=(const String& other) + { + if (this != &other) + m_impl = const_cast(other).m_impl.copyRef(); return *this; } diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 846c1b99ea..538b635d15 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -70,6 +70,8 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3) return current->sys$get_dir_entries((int)arg1, (void*)arg2, (size_t)arg3); case Syscall::PosixLstat: return current->sys$lstat((const char*)arg1, (void*)arg2); + case Syscall::PosixGetcwd: + return current->sys$getcwd((char*)arg1, (size_t)arg2); case Syscall::PosixOpen: //kprintf("syscall: open('%s', %u)\n", arg1, arg2); return current->sys$open((const char*)arg1, (size_t)arg2); diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index ff0b8af69e..bef6d5ff36 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -28,6 +28,7 @@ enum Function { PosixMunmap = 0x1996, GetDirEntries = 0x1997, PosixLstat = 0x1998, + PosixGetcwd = 0x1999, }; void initialize(); diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 7005394ee5..50bc885708 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -165,13 +165,13 @@ int Task::sys$munmap(void* addr, size_t size) int Task::sys$spawn(const char* path) { - auto* child = Task::create(path, m_uid, m_gid); + auto* child = Task::create(path, m_uid, m_gid, m_pid); if (child) return child->pid(); return -1; } -Task* Task::create(const String& path, uid_t uid, gid_t gid) +Task* Task::create(const String& path, uid_t uid, gid_t gid, pid_t parentPID) { auto parts = path.split('/'); if (parts.isEmpty()) @@ -186,7 +186,7 @@ Task* Task::create(const String& path, uid_t uid, gid_t gid) return nullptr; InterruptDisabler disabler; // FIXME: Get rid of this, jesus christ. This "critical" section is HUGE. - Task* t = new Task(parts.takeLast(), uid, gid); + Task* t = new Task(parts.takeLast(), uid, gid, parentPID); ExecSpace space; space.hookableAlloc = [&] (const String& name, size_t size) { @@ -222,18 +222,25 @@ Task* Task::create(const String& path, uid_t uid, gid_t gid) return t; } -Task::Task(String&& name, uid_t uid, gid_t gid) +Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID) : m_name(move(name)) , m_pid(next_pid++) , m_uid(uid) , m_gid(gid) , m_state(Runnable) , m_ring(Ring3) + , m_parentPID(parentPID) { m_fileHandles.append(nullptr); m_fileHandles.append(nullptr); m_fileHandles.append(nullptr); + auto* parentTask = Task::fromPID(parentPID); + if (parentTask) + m_cwd = parentTask->m_cwd; + else + m_cwd = "/"; + m_nextRegion = LinearAddress(0x600000); memset(&m_tss, 0, sizeof(m_tss)); @@ -288,6 +295,8 @@ Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring) m_fileHandles.append(nullptr); m_fileHandles.append(nullptr); + m_cwd = "/"; + m_nextRegion = LinearAddress(0x600000); Region* codeRegion = nullptr; @@ -709,6 +718,17 @@ int Task::sys$lstat(const char* path, void* statbuf) return 0; } +int Task::sys$getcwd(char* buffer, size_t size) +{ + if (size < m_cwd.length() + 1) { + // FIXME: return -ERANGE; + return -1; + } + memcpy(buffer, m_cwd.characters(), m_cwd.length()); + buffer[m_cwd.length()] = '\0'; + return 0; +} + int Task::sys$open(const char* path, size_t pathLength) { Task::checkSanity("sys$open"); diff --git a/Kernel/Task.h b/Kernel/Task.h index c7ca13eeb4..9dc8de9c1b 100644 --- a/Kernel/Task.h +++ b/Kernel/Task.h @@ -16,8 +16,8 @@ class Zone; class Task : public InlineLinkedListNode { friend class InlineLinkedListNode; public: - static Task* create(const String& path, uid_t, gid_t); - Task(String&& name, uid_t, gid_t); + static Task* create(const String& path, uid_t, gid_t, pid_t parentPID); + Task(String&& name, uid_t, gid_t, pid_t parentPID); static Vector allTasks(); @@ -103,6 +103,7 @@ public: void* sys$mmap(void*, size_t size); int sys$munmap(void*, size_t size); int sys$get_dir_entries(int fd, void*, size_t); + int sys$getcwd(char*, size_t); struct { @@ -157,6 +158,8 @@ private: dword m_timesScheduled { 0 }; pid_t m_waitee { -1 }; + String m_cwd; + struct Region { Region(LinearAddress, size_t, RetainPtr&&, String&&); ~Region(); @@ -174,6 +177,8 @@ private: // FIXME: Implement some kind of ASLR? LinearAddress m_nextRegion; + + pid_t m_parentPID { 0 }; }; extern void task_init(); diff --git a/Kernel/_fs_contents b/Kernel/_fs_contents index 7aacb359bb12fc7d45c55342defaaa38d7d02b0e..fbf9da7dbd5ef29a9cb06874f60a9272d501ee38 100644 GIT binary patch delta 5470 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 +#include + +int main(int c, char** v) +{ + char buffer[1024]; + char* ptr = getcwd(buffer, sizeof(buffer)); + if (!ptr) { + printf("getcwd() failed\n"); + return 1; + } + printf("%s\n", ptr); + return 0; +} + diff --git a/VirtualFileSystem/FileHandle.cpp b/VirtualFileSystem/FileHandle.cpp index 90c0beade2..172fe74cf5 100644 --- a/VirtualFileSystem/FileHandle.cpp +++ b/VirtualFileSystem/FileHandle.cpp @@ -142,6 +142,9 @@ ssize_t FileHandle::get_dir_entries(byte* buffer, size_t size) return true; }); + if (size < stream.offset()) + return -1; + memcpy(buffer, tempBuffer.pointer(), stream.offset()); return stream.offset(); } diff --git a/VirtualFileSystem/FileHandle.h b/VirtualFileSystem/FileHandle.h index f75d88895c..0aa23b93dd 100644 --- a/VirtualFileSystem/FileHandle.h +++ b/VirtualFileSystem/FileHandle.h @@ -16,6 +16,8 @@ public: ByteBuffer readEntireFile(); + String absolutePath() const; + #ifdef SERENITY int fd() const { return m_fd; } void setFD(int fd) { m_fd = fd; } diff --git a/VirtualFileSystem/InodeIdentifier.h b/VirtualFileSystem/InodeIdentifier.h index 865b07f838..d985266ec6 100644 --- a/VirtualFileSystem/InodeIdentifier.h +++ b/VirtualFileSystem/InodeIdentifier.h @@ -28,6 +28,11 @@ public: return m_fileSystemID == other.m_fileSystemID && m_index == other.m_index; } + bool operator!=(const InodeIdentifier& other) const + { + return m_fileSystemID != other.m_fileSystemID || m_index != other.m_index; + } + InodeMetadata metadata() const; bool isRootInode() const; diff --git a/VirtualFileSystem/VirtualFileSystem.h b/VirtualFileSystem/VirtualFileSystem.h index bafb791d9f..53e8fcb4a1 100644 --- a/VirtualFileSystem/VirtualFileSystem.h +++ b/VirtualFileSystem/VirtualFileSystem.h @@ -78,6 +78,7 @@ private: friend class FileHandle; void enumerateDirectoryInode(InodeIdentifier, Function); + String absolutePath(InodeIdentifier); InodeIdentifier resolvePath(const String& path); InodeIdentifier resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode);