mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +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
Notes:
sideshowbarker
2024-07-19 18:39:22 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/ec1d16b307e
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -28,6 +28,7 @@ enum Function {
|
|||
PosixMunmap = 0x1996,
|
||||
GetDirEntries = 0x1997,
|
||||
PosixLstat = 0x1998,
|
||||
PosixGetcwd = 0x1999,
|
||||
};
|
||||
|
||||
void initialize();
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
|
Binary file not shown.
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
Userland/.gitignore
vendored
1
Userland/.gitignore
vendored
|
@ -2,4 +2,5 @@ id
|
|||
sh
|
||||
ps
|
||||
ls
|
||||
pwd
|
||||
*.o
|
||||
|
|
|
@ -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
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;
|
||||
});
|
||||
|
||||
if (size < stream.offset())
|
||||
return -1;
|
||||
|
||||
memcpy(buffer, tempBuffer.pointer(), stream.offset());
|
||||
return stream.offset();
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue