mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 00:32:45 +00:00 
			
		
		
		
	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().
This commit is contained in:
		
							parent
							
								
									eb4074bb9d
								
							
						
					
					
						commit
						ec1d16b307
					
				
					 17 changed files with 87 additions and 14 deletions
				
			
		
							
								
								
									
										10
									
								
								AK/String.h
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								AK/String.h
									
										
									
									
									
								
							|  | @ -76,9 +76,15 @@ public: | ||||||
| 
 | 
 | ||||||
|     String& operator=(String&& other) |     String& operator=(String&& other) | ||||||
|     { |     { | ||||||
|         if (this != &other) { |         if (this != &other) | ||||||
|             m_impl = move(other.m_impl); |             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; |         return *this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); |         return current->sys$get_dir_entries((int)arg1, (void*)arg2, (size_t)arg3); | ||||||
|     case Syscall::PosixLstat: |     case Syscall::PosixLstat: | ||||||
|         return current->sys$lstat((const char*)arg1, (void*)arg2); |         return current->sys$lstat((const char*)arg1, (void*)arg2); | ||||||
|  |     case Syscall::PosixGetcwd: | ||||||
|  |         return current->sys$getcwd((char*)arg1, (size_t)arg2); | ||||||
|     case Syscall::PosixOpen: |     case Syscall::PosixOpen: | ||||||
|         //kprintf("syscall: open('%s', %u)\n", arg1, arg2);
 |         //kprintf("syscall: open('%s', %u)\n", arg1, arg2);
 | ||||||
|         return current->sys$open((const char*)arg1, (size_t)arg2); |         return current->sys$open((const char*)arg1, (size_t)arg2); | ||||||
|  |  | ||||||
|  | @ -28,6 +28,7 @@ enum Function { | ||||||
|     PosixMunmap = 0x1996, |     PosixMunmap = 0x1996, | ||||||
|     GetDirEntries = 0x1997, |     GetDirEntries = 0x1997, | ||||||
|     PosixLstat = 0x1998, |     PosixLstat = 0x1998, | ||||||
|  |     PosixGetcwd = 0x1999, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void initialize(); | void initialize(); | ||||||
|  |  | ||||||
|  | @ -165,13 +165,13 @@ int Task::sys$munmap(void* addr, size_t size) | ||||||
| 
 | 
 | ||||||
| int Task::sys$spawn(const char* path) | 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) |     if (child) | ||||||
|         return child->pid(); |         return child->pid(); | ||||||
|     return -1; |     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('/'); |     auto parts = path.split('/'); | ||||||
|     if (parts.isEmpty()) |     if (parts.isEmpty()) | ||||||
|  | @ -186,7 +186,7 @@ Task* Task::create(const String& path, uid_t uid, gid_t gid) | ||||||
|         return nullptr; |         return nullptr; | ||||||
| 
 | 
 | ||||||
|     InterruptDisabler disabler; // FIXME: Get rid of this, jesus christ. This "critical" section is HUGE.
 |     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; |     ExecSpace space; | ||||||
|     space.hookableAlloc = [&] (const String& name, size_t size) { |     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; |     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_name(move(name)) | ||||||
|     , m_pid(next_pid++) |     , m_pid(next_pid++) | ||||||
|     , m_uid(uid) |     , m_uid(uid) | ||||||
|     , m_gid(gid) |     , m_gid(gid) | ||||||
|     , m_state(Runnable) |     , m_state(Runnable) | ||||||
|     , m_ring(Ring3) |     , m_ring(Ring3) | ||||||
|  |     , m_parentPID(parentPID) | ||||||
| { | { | ||||||
|     m_fileHandles.append(nullptr); |     m_fileHandles.append(nullptr); | ||||||
|     m_fileHandles.append(nullptr); |     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); |     m_nextRegion = LinearAddress(0x600000); | ||||||
| 
 | 
 | ||||||
|     memset(&m_tss, 0, sizeof(m_tss)); |     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_fileHandles.append(nullptr); |     m_fileHandles.append(nullptr); | ||||||
| 
 | 
 | ||||||
|  |     m_cwd = "/"; | ||||||
|  | 
 | ||||||
|     m_nextRegion = LinearAddress(0x600000); |     m_nextRegion = LinearAddress(0x600000); | ||||||
| 
 | 
 | ||||||
|     Region* codeRegion = nullptr; |     Region* codeRegion = nullptr; | ||||||
|  | @ -709,6 +718,17 @@ int Task::sys$lstat(const char* path, void* statbuf) | ||||||
|     return 0; |     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) | int Task::sys$open(const char* path, size_t pathLength) | ||||||
| { | { | ||||||
|     Task::checkSanity("sys$open"); |     Task::checkSanity("sys$open"); | ||||||
|  |  | ||||||
|  | @ -16,8 +16,8 @@ class Zone; | ||||||
| class Task : public InlineLinkedListNode<Task> { | class Task : public InlineLinkedListNode<Task> { | ||||||
|     friend class InlineLinkedListNode<Task>; |     friend class InlineLinkedListNode<Task>; | ||||||
| public: | public: | ||||||
|     static Task* create(const String& path, uid_t, gid_t); |     static Task* create(const String& path, uid_t, gid_t, pid_t parentPID); | ||||||
|     Task(String&& name, uid_t, gid_t); |     Task(String&& name, uid_t, gid_t, pid_t parentPID); | ||||||
| 
 | 
 | ||||||
|     static Vector<Task*> allTasks(); |     static Vector<Task*> allTasks(); | ||||||
| 
 | 
 | ||||||
|  | @ -103,6 +103,7 @@ public: | ||||||
|     void* sys$mmap(void*, size_t size); |     void* sys$mmap(void*, size_t size); | ||||||
|     int sys$munmap(void*, size_t size); |     int sys$munmap(void*, size_t size); | ||||||
|     int sys$get_dir_entries(int fd, void*, size_t); |     int sys$get_dir_entries(int fd, void*, size_t); | ||||||
|  |     int sys$getcwd(char*, size_t); | ||||||
| 
 | 
 | ||||||
|     struct |     struct | ||||||
|     { |     { | ||||||
|  | @ -157,6 +158,8 @@ private: | ||||||
|     dword m_timesScheduled { 0 }; |     dword m_timesScheduled { 0 }; | ||||||
|     pid_t m_waitee { -1 }; |     pid_t m_waitee { -1 }; | ||||||
| 
 | 
 | ||||||
|  |     String m_cwd; | ||||||
|  | 
 | ||||||
|     struct Region { |     struct Region { | ||||||
|         Region(LinearAddress, size_t, RetainPtr<Zone>&&, String&&); |         Region(LinearAddress, size_t, RetainPtr<Zone>&&, String&&); | ||||||
|         ~Region(); |         ~Region(); | ||||||
|  | @ -174,6 +177,8 @@ private: | ||||||
| 
 | 
 | ||||||
|     // FIXME: Implement some kind of ASLR?
 |     // FIXME: Implement some kind of ASLR?
 | ||||||
|     LinearAddress m_nextRegion; |     LinearAddress m_nextRegion; | ||||||
|  | 
 | ||||||
|  |     pid_t m_parentPID { 0 }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extern void task_init(); | extern void task_init(); | ||||||
|  |  | ||||||
										
											Binary file not shown.
										
									
								
							|  | @ -150,7 +150,7 @@ static void init_stage2() | ||||||
|     } |     } | ||||||
| #endif | #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(); |     banner(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,5 +4,6 @@ cp ../Userland/sh mnt/bin/sh | ||||||
| cp ../Userland/id mnt/bin/id | cp ../Userland/id mnt/bin/id | ||||||
| cp ../Userland/ps mnt/bin/ps | cp ../Userland/ps mnt/bin/ps | ||||||
| cp ../Userland/ls mnt/bin/ls | cp ../Userland/ls mnt/bin/ls | ||||||
|  | cp ../Userland/pwd mnt/bin/pwd | ||||||
| umount mnt | umount mnt | ||||||
| sync | sync | ||||||
|  |  | ||||||
|  | @ -45,5 +45,13 @@ int lstat(const char* path, stat* statbuf) | ||||||
|     return Syscall::invoke(Syscall::PosixLstat, (dword)path, (dword)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; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ int open(const char* path); | ||||||
| ssize_t read(int fd, void* buf, size_t count); | ssize_t read(int fd, void* buf, size_t count); | ||||||
| int close(int fd); | int close(int fd); | ||||||
| pid_t waitpid(pid_t); | pid_t waitpid(pid_t); | ||||||
| 
 | char* getcwd(char* buffer, size_t size); | ||||||
| int lstat(const char* path, stat* statbuf); | int lstat(const char* path, stat* statbuf); | ||||||
| 
 | 
 | ||||||
| #define	S_IFMT 0170000 | #define	S_IFMT 0170000 | ||||||
|  | @ -36,7 +36,6 @@ int lstat(const char* path, stat* statbuf); | ||||||
| #define S_IWOTH 0002 | #define S_IWOTH 0002 | ||||||
| #define S_IXOTH 0001 | #define S_IXOTH 0001 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) | ||||||
| #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) | #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) | ||||||
| #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) | #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) | #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 |  | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								Userland/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								Userland/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -2,4 +2,5 @@ id | ||||||
| sh | sh | ||||||
| ps | ps | ||||||
| ls | ls | ||||||
|  | pwd | ||||||
| *.o | *.o | ||||||
|  |  | ||||||
|  | @ -2,13 +2,15 @@ OBJS = \ | ||||||
|        id.o \
 |        id.o \
 | ||||||
|        sh.o \
 |        sh.o \
 | ||||||
|        ps.o \
 |        ps.o \
 | ||||||
|        ls.o |        ls.o \
 | ||||||
|  |        pwd.o | ||||||
| 
 | 
 | ||||||
| APPS = \
 | APPS = \
 | ||||||
|        id \
 |        id \
 | ||||||
|        sh \
 |        sh \
 | ||||||
|        ps \
 |        ps \
 | ||||||
|        ls |        ls \
 | ||||||
|  |        pwd | ||||||
| 
 | 
 | ||||||
| ARCH_FLAGS = | ARCH_FLAGS = | ||||||
| STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib | STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib | ||||||
|  | @ -40,6 +42,9 @@ ps: ps.o | ||||||
| ls: ls.o | ls: ls.o | ||||||
| 	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a | 	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a | ||||||
| 
 | 
 | ||||||
|  | pwd: pwd.o | ||||||
|  | 	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a | ||||||
|  | 
 | ||||||
| .cpp.o: | .cpp.o: | ||||||
| 	@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< | 	@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								Userland/pwd.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Userland/pwd.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @ -142,6 +142,9 @@ ssize_t FileHandle::get_dir_entries(byte* buffer, size_t size) | ||||||
|         return true; |         return true; | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     if (size < stream.offset()) | ||||||
|  |         return -1; | ||||||
|  | 
 | ||||||
|     memcpy(buffer, tempBuffer.pointer(), stream.offset()); |     memcpy(buffer, tempBuffer.pointer(), stream.offset()); | ||||||
|     return stream.offset(); |     return stream.offset(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -16,6 +16,8 @@ public: | ||||||
| 
 | 
 | ||||||
|     ByteBuffer readEntireFile(); |     ByteBuffer readEntireFile(); | ||||||
| 
 | 
 | ||||||
|  |     String absolutePath() const; | ||||||
|  | 
 | ||||||
| #ifdef SERENITY | #ifdef SERENITY | ||||||
|     int fd() const { return m_fd; } |     int fd() const { return m_fd; } | ||||||
|     void setFD(int fd) { m_fd = fd; } |     void setFD(int fd) { m_fd = fd; } | ||||||
|  |  | ||||||
|  | @ -28,6 +28,11 @@ public: | ||||||
|         return m_fileSystemID == other.m_fileSystemID && m_index == other.m_index; |         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; |     InodeMetadata metadata() const; | ||||||
|     bool isRootInode() const; |     bool isRootInode() const; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -78,6 +78,7 @@ private: | ||||||
|     friend class FileHandle; |     friend class FileHandle; | ||||||
| 
 | 
 | ||||||
|     void enumerateDirectoryInode(InodeIdentifier, Function<bool(const FileSystem::DirectoryEntry&)>); |     void enumerateDirectoryInode(InodeIdentifier, Function<bool(const FileSystem::DirectoryEntry&)>); | ||||||
|  |     String absolutePath(InodeIdentifier); | ||||||
|     InodeIdentifier resolvePath(const String& path); |     InodeIdentifier resolvePath(const String& path); | ||||||
|     InodeIdentifier resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode); |     InodeIdentifier resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling