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 7aacb359bb..fbf9da7dbd 100644 Binary files a/Kernel/_fs_contents and b/Kernel/_fs_contents differ diff --git a/Kernel/init.cpp b/Kernel/init.cpp index e67e92329a..99bca8f15b 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -150,7 +150,7 @@ static void init_stage2() } #endif - auto* shTask = Task::create("/bin/sh", (uid_t)100, (gid_t)100); + auto* shTask = Task::create("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0); banner(); diff --git a/Kernel/sync-sh b/Kernel/sync-sh index a0f071bd68..e2d1e6cd2a 100755 --- a/Kernel/sync-sh +++ b/Kernel/sync-sh @@ -4,5 +4,6 @@ cp ../Userland/sh mnt/bin/sh cp ../Userland/id mnt/bin/id cp ../Userland/ps mnt/bin/ps cp ../Userland/ls mnt/bin/ls +cp ../Userland/pwd mnt/bin/pwd umount mnt sync diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index 42e3f49c32..f0c5831940 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -45,5 +45,13 @@ int lstat(const char* path, stat* statbuf) return Syscall::invoke(Syscall::PosixLstat, (dword)path, (dword)statbuf); } +char* getcwd(char* buffer, size_t size) +{ + int rc = Syscall::invoke(Syscall::PosixGetcwd, (dword)buffer, (dword)size); + if (rc != 0) + return nullptr; + return buffer; +} + } diff --git a/LibC/unistd.h b/LibC/unistd.h index 7dcbe0b51f..96603a6795 100644 --- a/LibC/unistd.h +++ b/LibC/unistd.h @@ -11,7 +11,7 @@ int open(const char* path); ssize_t read(int fd, void* buf, size_t count); int close(int fd); pid_t waitpid(pid_t); - +char* getcwd(char* buffer, size_t size); int lstat(const char* path, stat* statbuf); #define S_IFMT 0170000 @@ -36,7 +36,6 @@ int lstat(const char* path, stat* statbuf); #define S_IWOTH 0002 #define S_IXOTH 0001 - #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) @@ -45,4 +44,3 @@ int lstat(const char* path, stat* statbuf); #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) } - diff --git a/Userland/.gitignore b/Userland/.gitignore index 5f641bf9a1..ed1a6797f5 100644 --- a/Userland/.gitignore +++ b/Userland/.gitignore @@ -2,4 +2,5 @@ id sh ps ls +pwd *.o diff --git a/Userland/Makefile b/Userland/Makefile index c1cd22033c..e47a8578b6 100644 --- a/Userland/Makefile +++ b/Userland/Makefile @@ -2,13 +2,15 @@ OBJS = \ id.o \ sh.o \ ps.o \ - ls.o + ls.o \ + pwd.o APPS = \ id \ sh \ ps \ - ls + ls \ + pwd ARCH_FLAGS = STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib @@ -40,6 +42,9 @@ ps: ps.o ls: ls.o $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a +pwd: pwd.o + $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a + .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/Userland/pwd.cpp b/Userland/pwd.cpp new file mode 100644 index 0000000000..ebb7d5b6d3 --- /dev/null +++ b/Userland/pwd.cpp @@ -0,0 +1,15 @@ +#include +#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);