瀏覽代碼

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().
Andreas Kling 6 年之前
父節點
當前提交
ec1d16b307

+ 8 - 2
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<String&>(other).m_impl.copyRef();
         return *this;
     }
 

+ 2 - 0
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);

+ 1 - 0
Kernel/Syscall.h

@@ -28,6 +28,7 @@ enum Function {
     PosixMunmap = 0x1996,
     GetDirEntries = 0x1997,
     PosixLstat = 0x1998,
+    PosixGetcwd = 0x1999,
 };
 
 void initialize();

+ 24 - 4
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");

+ 7 - 2
Kernel/Task.h

@@ -16,8 +16,8 @@ class Zone;
 class Task : public InlineLinkedListNode<Task> {
     friend class InlineLinkedListNode<Task>;
 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<Task*> 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<Zone>&&, 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();

二進制
Kernel/_fs_contents


+ 1 - 1
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();
 

+ 1 - 0
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

+ 8 - 0
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;
+}
+
 }
 

+ 1 - 3
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)
 
 }
-

+ 1 - 0
Userland/.gitignore

@@ -2,4 +2,5 @@ id
 sh
 ps
 ls
+pwd
 *.o

+ 7 - 2
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 $<
 

+ 15 - 0
Userland/pwd.cpp

@@ -0,0 +1,15 @@
+#include <LibC/unistd.h>
+#include <LibC/stdio.h>
+
+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;
+}
+

+ 3 - 0
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();
 }

+ 2 - 0
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; }

+ 5 - 0
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;
 

+ 1 - 0
VirtualFileSystem/VirtualFileSystem.h

@@ -78,6 +78,7 @@ private:
     friend class FileHandle;
 
     void enumerateDirectoryInode(InodeIdentifier, Function<bool(const FileSystem::DirectoryEntry&)>);
+    String absolutePath(InodeIdentifier);
     InodeIdentifier resolvePath(const String& path);
     InodeIdentifier resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode);