mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 18:37:34 +00:00
Add basic symlink support.
- sys$readlink + readlink() - Add a /proc/PID/exe symlink to the process's executable. - Print symlink contents in ls output. - Some work on plumbing options into VFS::open().
This commit is contained in:
parent
1d4af51250
commit
97726862dd
20 changed files with 140 additions and 46 deletions
|
@ -96,6 +96,16 @@ ByteBuffer procfs$pid_stack(Task& task)
|
|||
return buffer;
|
||||
}
|
||||
|
||||
ByteBuffer procfs$pid_exe(Task& task)
|
||||
{
|
||||
InodeIdentifier inode;
|
||||
{
|
||||
InterruptDisabler disabler;
|
||||
inode = task.executableInode();
|
||||
}
|
||||
return VirtualFileSystem::the().absolutePath(inode).toByteBuffer();
|
||||
}
|
||||
|
||||
void ProcFileSystem::addProcess(Task& task)
|
||||
{
|
||||
ASSERT_INTERRUPTS_DISABLED();
|
||||
|
@ -105,6 +115,8 @@ void ProcFileSystem::addProcess(Task& task)
|
|||
m_pid2inode.set(task.pid(), dir.index());
|
||||
addFile(createGeneratedFile("vm", [&task] { return procfs$pid_vm(task); }), dir.index());
|
||||
addFile(createGeneratedFile("stack", [&task] { return procfs$pid_stack(task); }), dir.index());
|
||||
if (task.executableInode().isValid())
|
||||
addFile(createGeneratedFile("exe", [&task] { return procfs$pid_exe(task); }, 00120777), dir.index());
|
||||
}
|
||||
|
||||
void ProcFileSystem::removeProcess(Task& task)
|
||||
|
|
|
@ -116,6 +116,8 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3)
|
|||
return current->sys$uname((utsname*)arg1);
|
||||
case Syscall::SetMmapName:
|
||||
return current->sys$set_mmap_name((void*)arg1, (size_t)arg2, (const char*)arg3);
|
||||
case Syscall::PosixReadlink:
|
||||
return current->sys$readlink((const char*)arg1, (char*)arg2, (size_t)arg3);
|
||||
default:
|
||||
kprintf("int0x80: Unknown function %x requested {%x, %x, %x}\n", function, arg1, arg2, arg3);
|
||||
break;
|
||||
|
|
|
@ -35,6 +35,7 @@ enum Function {
|
|||
PosixChdir = 0x2003,
|
||||
PosixUname = 0x2004,
|
||||
SetMmapName = 0x2005,
|
||||
PosixReadlink = 0x2006,
|
||||
};
|
||||
|
||||
void initialize();
|
||||
|
|
|
@ -234,7 +234,7 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
|
|||
cwd = parentTask->m_cwd.copyRef();
|
||||
}
|
||||
|
||||
auto handle = VirtualFileSystem::the().open(path, cwd ? cwd->inode : InodeIdentifier());
|
||||
auto handle = VirtualFileSystem::the().open(path, 0, cwd ? cwd->inode : InodeIdentifier());
|
||||
if (!handle) {
|
||||
error = -ENOENT; // FIXME: Get a more detailed error from VFS.
|
||||
return nullptr;
|
||||
|
@ -261,7 +261,7 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
|
|||
}
|
||||
|
||||
InterruptDisabler disabler; // FIXME: Get rid of this, jesus christ. This "critical" section is HUGE.
|
||||
Task* t = new Task(parts.takeLast(), uid, gid, parentPID, Ring3);
|
||||
Task* t = new Task(parts.takeLast(), uid, gid, parentPID, Ring3, handle->vnode());
|
||||
|
||||
t->m_arguments = move(taskArguments);
|
||||
|
||||
|
@ -362,13 +362,14 @@ Task* Task::createKernelTask(void (*e)(), String&& name)
|
|||
return task;
|
||||
}
|
||||
|
||||
Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring)
|
||||
Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring, RetainPtr<VirtualFileSystem::Node>&& executable)
|
||||
: m_name(move(name))
|
||||
, m_pid(next_pid++)
|
||||
, m_uid(uid)
|
||||
, m_gid(gid)
|
||||
, m_state(Runnable)
|
||||
, m_ring(ring)
|
||||
, m_executable(move(executable))
|
||||
, m_parentPID(parentPID)
|
||||
{
|
||||
m_fileHandles.append(nullptr); // stdin
|
||||
|
@ -785,17 +786,39 @@ int Task::sys$close(int fd)
|
|||
int Task::sys$lstat(const char* path, Unix::stat* statbuf)
|
||||
{
|
||||
VALIDATE_USER_BUFFER(statbuf, sizeof(Unix::stat));
|
||||
auto handle = VirtualFileSystem::the().open(move(path), cwdInode());
|
||||
auto handle = VirtualFileSystem::the().open(move(path), O_NOFOLLOW_NOERROR, cwdInode());
|
||||
if (!handle)
|
||||
return -1;
|
||||
handle->stat(statbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Task::sys$readlink(const char* path, char* buffer, size_t size)
|
||||
{
|
||||
VALIDATE_USER_BUFFER(path, strlen(path));
|
||||
VALIDATE_USER_BUFFER(buffer, size);
|
||||
|
||||
auto handle = VirtualFileSystem::the().open(path, O_RDONLY | O_NOFOLLOW_NOERROR, cwdInode());
|
||||
if (!handle)
|
||||
return -ENOENT; // FIXME: Get a more detailed error from VFS.
|
||||
|
||||
if (!handle->metadata().isSymbolicLink())
|
||||
return -EINVAL;
|
||||
|
||||
auto contents = handle->readEntireFile();
|
||||
if (!contents)
|
||||
return -EIO; // FIXME: Get a more detailed error from VFS.
|
||||
|
||||
memcpy(buffer, contents.pointer(), min(size, contents.size()));
|
||||
if (contents.size() + 1 < size)
|
||||
buffer[contents.size()] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Task::sys$chdir(const char* path)
|
||||
{
|
||||
VALIDATE_USER_BUFFER(path, strlen(path));
|
||||
auto handle = VirtualFileSystem::the().open(path, cwdInode());
|
||||
auto handle = VirtualFileSystem::the().open(path, 0, cwdInode());
|
||||
if (!handle)
|
||||
return -ENOENT; // FIXME: More detailed error.
|
||||
if (!handle->isDirectory())
|
||||
|
@ -811,17 +834,20 @@ int Task::sys$getcwd(char* buffer, size_t size)
|
|||
return -ENOTIMPL;
|
||||
}
|
||||
|
||||
int Task::sys$open(const char* path, size_t pathLength)
|
||||
int Task::sys$open(const char* path, int options)
|
||||
{
|
||||
#ifdef DEBUG_IO
|
||||
kprintf("Task::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength);
|
||||
#endif
|
||||
VALIDATE_USER_BUFFER(path, pathLength);
|
||||
VALIDATE_USER_BUFFER(path, strlen(path));
|
||||
if (m_fileHandles.size() >= m_maxFileHandles)
|
||||
return -EMFILE;
|
||||
auto handle = VirtualFileSystem::the().open(String(path, pathLength), cwdInode());
|
||||
auto handle = VirtualFileSystem::the().open(path, 0, cwdInode());
|
||||
if (!handle)
|
||||
return -ENOENT; // FIXME: Detailed error.
|
||||
if (options & O_DIRECTORY && !handle->isDirectory())
|
||||
return -ENOTDIR; // FIXME: This should be handled by VFS::open.
|
||||
|
||||
int fd = m_fileHandles.size();
|
||||
handle->setFD(fd);
|
||||
m_fileHandles.append(move(handle));
|
||||
|
|
|
@ -87,7 +87,7 @@ public:
|
|||
uid_t sys$getuid();
|
||||
gid_t sys$getgid();
|
||||
pid_t sys$getpid();
|
||||
int sys$open(const char* path, size_t pathLength);
|
||||
int sys$open(const char* path, int options);
|
||||
int sys$close(int fd);
|
||||
int sys$read(int fd, void* outbuf, size_t nread);
|
||||
int sys$lstat(const char*, Unix::stat*);
|
||||
|
@ -108,6 +108,7 @@ public:
|
|||
int sys$gethostname(char* name, size_t length);
|
||||
int sys$get_arguments(int* argc, char*** argv);
|
||||
int sys$uname(utsname*);
|
||||
int sys$readlink(const char*, char*, size_t);
|
||||
|
||||
static void initialize();
|
||||
|
||||
|
@ -134,12 +135,13 @@ public:
|
|||
bool isValidAddressForUser(LinearAddress) const;
|
||||
|
||||
InodeIdentifier cwdInode() const { return m_cwd ? m_cwd->inode : InodeIdentifier(); }
|
||||
InodeIdentifier executableInode() const { return m_executable ? m_executable->inode : InodeIdentifier(); }
|
||||
|
||||
private:
|
||||
friend class MemoryManager;
|
||||
friend bool scheduleNewTask();
|
||||
|
||||
Task(String&& name, uid_t, gid_t, pid_t parentPID, RingLevel);
|
||||
Task(String&& name, uid_t, gid_t, pid_t parentPID, RingLevel, RetainPtr<VirtualFileSystem::Node>&& = nullptr);
|
||||
|
||||
void allocateLDT();
|
||||
|
||||
|
@ -171,6 +173,7 @@ private:
|
|||
size_t m_maxFileHandles { 16 };
|
||||
|
||||
RetainPtr<VirtualFileSystem::Node> m_cwd;
|
||||
RetainPtr<VirtualFileSystem::Node> m_executable;
|
||||
|
||||
struct Region : public Retainable<Region> {
|
||||
Region(LinearAddress, size_t, RetainPtr<Zone>&&, String&&);
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#define EDOM 33 // Math argument out of domain of func
|
||||
#define ERANGE 34 // Math result not representable
|
||||
#define ENAMETOOLONG 36 // Name too long
|
||||
|
||||
#define ELOOP 40 // Too many symbolic links
|
||||
#define EOVERFLOW 75 // Value too large for defined data type
|
||||
|
||||
#define ENOTIMPL 999 // Not implemented
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue