1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-30 21:58:10 +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:
Andreas Kling 2018-10-24 14:28:22 +02:00
parent eb4074bb9d
commit ec1d16b307
17 changed files with 87 additions and 14 deletions

View file

@ -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;
} }

View file

@ -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);

View file

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

View file

@ -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");

View file

@ -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.

View file

@ -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();

View file

@ -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

View file

@ -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;
}
} }

View file

@ -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
View file

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

View file

@ -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
View 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;
}

View file

@ -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();
} }

View file

@ -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; }

View file

@ -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;

View file

@ -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);