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 zcmbVQ4RBP|6~1S)3GYEjb~hm#2(X)Mel{wQg@`N=Ni>x}K@&i6N-9M82^#qk5n3W4 zf?Giy-Mp3y4r8H1o!AzXMon6Ohyzw?m691|WGo$$sRCNTFhfVCqUm?uyKh-G0i9kr zoIU5BbMJlke)pVn+0=RKrp{YmO?4(ml7y%++|C?*+rncDn9AC2cHT~ovg894akOZu zNs*+Qwsh_5bVuKyC`~fTvz>#45WRhU)1nk=Ys}u7G^7a%)!N)6ze;NB^F8YxZjWg7 zID|u)XtHZIWkg*!8J~vyWtrJRY@2e_oSQu?BNA!Kn!s-cO$6Nnngj}iCWEFJ72^+u z=Vc1<=zAaa8zB`I+<1gCOnxh98mJsp0lLiyl@zrtp5S+cyD`LVr~5A=eu&%QQVIGI z=nl|yP!$hhe0uZliiVLwe3EBvVf<&f%q3Whm;sNOpdW)~fo6m51lx+V`KpXm;h=^!LX5*o zI+BuT)w;z8XkSvxaeqd>$68&f$%3L#6tqn^o~vce-Fj$iSI5rbLTvryqfJkCKI#bl zW9x~wIVX=er{VK$=j8@U&(Ez4Co)>9|0kp02(`Hfjh9<0p`U*Oi=nsEMvmkm}50}GRMSKJm4@P zlJT3oLX;>zU-5dy-%z}U?X!f)W;p~0#uPg~ruY`c|DrhGS4W8u8uKyoJ3qbI_S3H= z$+1f*HQC%unLe9_85N(s({g%|es-u3e%J<#<)^3X8qQ+3DgEj6O1%{lhC*NH%yj)k zOlm%JP}kC}IReIvvxg{K9!R4M!~eO98jL-cy>7mU_$yLC+y4jqA<^D9v^85mN zo-xlFwMS7i)-sDJcN~CwtOTC&C5rCXBw^GY%zx`hNAmtjjzJ16-@;T(jQRI>< zW@{hFs?ijrM!9-4l~Jbr`(sorx7<%Ib*DYC`)=LoL1MF7Kd^#3ogua<*}BuI;yL;D z{j@p$QsdI#?gOj=ArM!E!*3msBTtAMA(Ptzp(9tORBOxh8x*#S+BdGJDu;sf`JuE= zb}ywx`mP~D1mWkC&0#Gd85{V;S4WS@L@8BNzO#zc2L9i)6&cehp~FV)jtSy@1t z?tk*MARD{|lJ3#G?(+%i39_evyx}jPj)(6}h}?X_9E%VkVkr9tzj;&}xi!-LAbH&x z>fmkYHpmN@tT-L&_)$wSDr1*N#r2PkS}0%NNJZhi1oJQB%n{jR<`WZU%a_sl__Ru; z2GGn_Dszj-D;K>&&Y|&WRr-@fn#PM$wyTS%XlN!~M>cl?($^z`lNq3E^%ig?V?vL%$65W5W88c2=WQk1LH#`?+d=(9CEG#0OUZ-5JtAFvtYrQG zj~F3eS*f+hg?xXLdBG6H%nOEse*z4-sF?)rK!ATh$@NOUfx&|Qap2rPQ^|KJxlYMT zm29SD*soXeUe*7yB{zvzmEv_}aESRhA$pYl9Lu)|@n7Z$*r|XiFTf4X3mBthep;}e z3v%Ym6@OguZHoU^@hbkXY}Aov{fFw+tpC8x`VZW!|G>@q54?sQfP1t4gKU<6;AZ&; zZkB)GX88whmVemBWZtQm-pg(y(mlv5FA_^dd#Y3wmkyT)U#4C& zQk~QC^ajGtE272X*|E)p714A+iKZn?^qK5}JLhRlx2u)^n7U!}mFal6b4x}HTPo}3P=;rv z>H;Xu)-c43y^|kGSj8f&q5~GZ!?_@P6;CAiAF=$)HYWIIXvwHG|uId+1||mD`V$Fk0;9 z6c_riRI@S832zq8fOg}4K`KJUnT3}J|$auBU3Cdh8aTvSCG&mZR#K*Ue<>5;gEk`uJ>$^SDj2IgG5G3>ckt5h=Y!}mWS z5bBrGoVs>)yqhHD%);fVZOUvPpUX!7E zxV$Cz*-czn;ntP3cNV_y-%hLT<6U&>%6iruujHRIf&a-tdi02eeaWH$R)$ffYI-b(rDIt;lx_6 z5+n0{@ApPg*VK+TCoK2GH_PQX_v@8VwxuhJ^@DzOg~QzNxQBeiKS)uvbe4}-{Dwg3PC delta 966 zcmaKqT}TvB6vxkNp0G;nr5!L>iU(~LxqUB^$;x9nm+hoB$%{8;O64= zA)>a$_#n0QVDwVE4KW}+>_g#GqV%Ls3z;NH4ZRqpPUr59Ap{Nl_}}xt=bSlr<_2Od zfmln#Bp4=n08c1OC`ennxa9qXG|4XEG~u!hQ6h2=sfnNDJ+hf@nTdItxI?YEf}m;| zu50Amx%YYFDfs)yS%u$uSvx$DmA6{7O} za$mKLa}Q(#w5|VtfJ!WJB2`E=QiHe>1FX5i&D#Y4?4WG?{YS{$H$W{`)FJhV8)-lq zktXa?99pX_lmm5vl4(oejjweutD7^tp#R$OXxGmD*FhxZTwywXD*Tk#<}+gAZUhBe-em zufn2@x`b!j^J z@9$(=^H}SQO(yrWF7Sy8nsAE`T^wC%_Ng-(oS=Tk%V>e(d@(W&fRNr>?!a4kk4f#uE!= bagH1k?)tmakaWa|n2-!4Q}K73@3s8_?0gC! 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);