mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 10:37:45 +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
|
@ -74,7 +74,8 @@ ByteBuffer FileSystem::readEntireInode(InodeIdentifier inode, FileHandle* handle
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
auto contents = ByteBuffer::createUninitialized(metadata.size);
|
||||
size_t initialSize = metadata.size ? metadata.size : 4096;
|
||||
auto contents = ByteBuffer::createUninitialized(initialSize);
|
||||
|
||||
Unix::ssize_t nread;
|
||||
byte buffer[512];
|
||||
|
@ -87,6 +88,7 @@ ByteBuffer FileSystem::readEntireInode(InodeIdentifier inode, FileHandle* handle
|
|||
memcpy(out, buffer, nread);
|
||||
out += nread;
|
||||
offset += nread;
|
||||
ASSERT(offset <= initialSize); // FIXME: Support dynamically growing the buffer.
|
||||
}
|
||||
if (nread < 0) {
|
||||
kprintf("[fs] readInode: ERROR: %d\n", nread);
|
||||
|
|
|
@ -60,12 +60,12 @@ auto SyntheticFileSystem::createTextFile(String&& name, String&& text) -> OwnPtr
|
|||
file->metadata.size = file->data.size();
|
||||
file->metadata.uid = 100;
|
||||
file->metadata.gid = 200;
|
||||
file->metadata.mode = 04;
|
||||
file->metadata.mode = 0040644;
|
||||
file->metadata.mtime = mepoch;
|
||||
return file;
|
||||
}
|
||||
|
||||
auto SyntheticFileSystem::createGeneratedFile(String&& name, Function<ByteBuffer()>&& generator) -> OwnPtr<File>
|
||||
auto SyntheticFileSystem::createGeneratedFile(String&& name, Function<ByteBuffer()>&& generator, Unix::mode_t mode) -> OwnPtr<File>
|
||||
{
|
||||
auto file = make<File>();
|
||||
file->generator = move(generator);
|
||||
|
@ -73,7 +73,7 @@ auto SyntheticFileSystem::createGeneratedFile(String&& name, Function<ByteBuffer
|
|||
file->metadata.size = 0;
|
||||
file->metadata.uid = 0;
|
||||
file->metadata.gid = 0;
|
||||
file->metadata.mode = 0100644;
|
||||
file->metadata.mode = mode;
|
||||
file->metadata.mtime = mepoch;
|
||||
return file;
|
||||
}
|
||||
|
@ -146,9 +146,8 @@ bool SyntheticFileSystem::enumerateDirectoryInode(InodeIdentifier inode, Functio
|
|||
callback({ ".", synInode.metadata.inode });
|
||||
callback({ "..", synInode.parent });
|
||||
|
||||
for (auto& child : synInode.children) {
|
||||
for (auto& child : synInode.children)
|
||||
callback({ child->name, child->metadata.inode });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -214,8 +213,8 @@ Unix::ssize_t SyntheticFileSystem::readInodeBytes(InodeIdentifier inode, Unix::o
|
|||
generatedData = handle->generatorCache();
|
||||
}
|
||||
}
|
||||
auto* data = generatedData ? &generatedData : &file.data;
|
||||
|
||||
auto* data = generatedData ? &generatedData : &file.data;
|
||||
Unix::ssize_t nread = min(static_cast<Unix::off_t>(data->size() - offset), static_cast<Unix::off_t>(count));
|
||||
memcpy(buffer, data->pointer() + offset, nread);
|
||||
if (nread == 0 && handle && handle->generatorCache())
|
||||
|
|
|
@ -40,7 +40,7 @@ protected:
|
|||
|
||||
OwnPtr<File> createDirectory(String&& name);
|
||||
OwnPtr<File> createTextFile(String&& name, String&& text);
|
||||
OwnPtr<File> createGeneratedFile(String&& name, Function<ByteBuffer()>&&);
|
||||
OwnPtr<File> createGeneratedFile(String&& name, Function<ByteBuffer()>&&, Unix::mode_t = 0100644);
|
||||
|
||||
InodeIdentifier addFile(OwnPtr<File>&&, InodeIndex parent = RootInodeIndex);
|
||||
bool removeFile(InodeIndex);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <AK/kmalloc.h>
|
||||
#include <AK/kstdio.h>
|
||||
#include <AK/ktime.h>
|
||||
#include "sys-errno.h"
|
||||
|
||||
//#define VFS_DEBUG
|
||||
|
||||
|
@ -104,7 +105,8 @@ bool VirtualFileSystem::mount(RetainPtr<FileSystem>&& fileSystem, const String&
|
|||
{
|
||||
ASSERT(fileSystem);
|
||||
|
||||
auto inode = resolvePath(path);
|
||||
int error;
|
||||
auto inode = resolvePath(path, error);
|
||||
if (!inode.isValid()) {
|
||||
kprintf("[VFS] mount can't resolve mount point '%s'\n", path.characters());
|
||||
return false;
|
||||
|
@ -172,7 +174,8 @@ void VirtualFileSystem::freeNode(Node* node)
|
|||
|
||||
bool VirtualFileSystem::isDirectory(const String& path, InodeIdentifier base)
|
||||
{
|
||||
auto inode = resolvePath(path, base);
|
||||
int error;
|
||||
auto inode = resolvePath(path, error, base);
|
||||
if (!inode.isValid())
|
||||
return false;
|
||||
|
||||
|
@ -226,7 +229,8 @@ void VirtualFileSystem::enumerateDirectoryInode(InodeIdentifier directoryInode,
|
|||
|
||||
void VirtualFileSystem::listDirectory(const String& path)
|
||||
{
|
||||
auto directoryInode = resolvePath(path);
|
||||
int error;
|
||||
auto directoryInode = resolvePath(path, error);
|
||||
if (!directoryInode.isValid())
|
||||
return;
|
||||
|
||||
|
@ -326,7 +330,8 @@ void VirtualFileSystem::listDirectory(const String& path)
|
|||
|
||||
void VirtualFileSystem::listDirectoryRecursively(const String& path)
|
||||
{
|
||||
auto directory = resolvePath(path);
|
||||
int error;
|
||||
auto directory = resolvePath(path, error);
|
||||
if (!directory.isValid())
|
||||
return;
|
||||
|
||||
|
@ -351,17 +356,19 @@ bool VirtualFileSystem::touch(const String& path)
|
|||
{
|
||||
Locker locker(VirtualFileSystem::lock());
|
||||
|
||||
auto inode = resolvePath(path);
|
||||
int error;
|
||||
auto inode = resolvePath(path, error);
|
||||
if (!inode.isValid())
|
||||
return false;
|
||||
return inode.fileSystem()->setModificationTime(inode, ktime(nullptr));
|
||||
}
|
||||
|
||||
OwnPtr<FileHandle> VirtualFileSystem::open(const String& path, InodeIdentifier base)
|
||||
OwnPtr<FileHandle> VirtualFileSystem::open(const String& path, int options, InodeIdentifier base)
|
||||
{
|
||||
Locker locker(VirtualFileSystem::lock());
|
||||
|
||||
auto inode = resolvePath(path, base);
|
||||
int error;
|
||||
auto inode = resolvePath(path, error, base, options);
|
||||
if (!inode.isValid())
|
||||
return nullptr;
|
||||
auto vnode = getOrCreateNode(inode);
|
||||
|
@ -397,7 +404,8 @@ InodeIdentifier VirtualFileSystem::resolveSymbolicLink(const String& basePath, I
|
|||
return { };
|
||||
char buf[4096];
|
||||
ksprintf(buf, "/%s/%s", basePath.characters(), String((const char*)symlinkContents.pointer(), symlinkContents.size()).characters());
|
||||
return resolvePath(buf);
|
||||
int error;
|
||||
return resolvePath(buf, error);
|
||||
}
|
||||
|
||||
String VirtualFileSystem::absolutePath(InodeIdentifier inode)
|
||||
|
@ -407,6 +415,7 @@ String VirtualFileSystem::absolutePath(InodeIdentifier inode)
|
|||
if (!inode.isValid())
|
||||
return String();
|
||||
|
||||
int error;
|
||||
Vector<InodeIdentifier> lineage;
|
||||
while (inode != m_rootNode->inode) {
|
||||
if (auto* mount = findMountForGuest(inode))
|
||||
|
@ -414,7 +423,7 @@ String VirtualFileSystem::absolutePath(InodeIdentifier inode)
|
|||
else
|
||||
lineage.append(inode);
|
||||
if (inode.metadata().isDirectory()) {
|
||||
inode = resolvePath("..", inode);
|
||||
inode = resolvePath("..", error, inode);
|
||||
} else
|
||||
inode = inode.fileSystem()->findParentOfInode(inode);
|
||||
ASSERT(inode.isValid());
|
||||
|
@ -434,7 +443,7 @@ String VirtualFileSystem::absolutePath(InodeIdentifier inode)
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
InodeIdentifier VirtualFileSystem::resolvePath(const String& path, InodeIdentifier base)
|
||||
InodeIdentifier VirtualFileSystem::resolvePath(const String& path, int& error, InodeIdentifier base, int options)
|
||||
{
|
||||
if (path.isEmpty())
|
||||
return { };
|
||||
|
@ -455,12 +464,14 @@ InodeIdentifier VirtualFileSystem::resolvePath(const String& path, InodeIdentifi
|
|||
#ifdef VFS_DEBUG
|
||||
kprintf("invalid metadata\n");
|
||||
#endif
|
||||
error = -EIO;
|
||||
return { };
|
||||
}
|
||||
if (!metadata.isDirectory()) {
|
||||
#ifdef VFS_DEBUG
|
||||
kprintf("not directory\n");
|
||||
#endif
|
||||
error = -EIO;
|
||||
return { };
|
||||
}
|
||||
inode = inode.fileSystem()->childOfDirectoryInodeWithName(inode, part);
|
||||
|
@ -468,6 +479,7 @@ InodeIdentifier VirtualFileSystem::resolvePath(const String& path, InodeIdentifi
|
|||
#ifdef VFS_DEBUG
|
||||
kprintf("bad child\n");
|
||||
#endif
|
||||
error = -EIO;
|
||||
return { };
|
||||
}
|
||||
#ifdef VFS_DEBUG
|
||||
|
@ -489,6 +501,14 @@ InodeIdentifier VirtualFileSystem::resolvePath(const String& path, InodeIdentifi
|
|||
}
|
||||
metadata = inode.metadata();
|
||||
if (metadata.isSymbolicLink()) {
|
||||
if (i == parts.size() - 1) {
|
||||
if (options & O_NOFOLLOW) {
|
||||
error = -ELOOP;
|
||||
return { };
|
||||
}
|
||||
if (options & O_NOFOLLOW_NOERROR)
|
||||
return inode;
|
||||
}
|
||||
char buf[4096] = "";
|
||||
char* p = buf;
|
||||
for (unsigned j = 0; j < i; ++j) {
|
||||
|
@ -497,6 +517,7 @@ InodeIdentifier VirtualFileSystem::resolvePath(const String& path, InodeIdentifi
|
|||
inode = resolveSymbolicLink(buf, inode);
|
||||
if (!inode.isValid()) {
|
||||
kprintf("Symbolic link resolution failed :(\n");
|
||||
error = -ENOENT;
|
||||
return { };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,13 @@
|
|||
#include "Limits.h"
|
||||
#include "FileSystem.h"
|
||||
|
||||
#define O_RDONLY 0
|
||||
#define O_WRONLY 1
|
||||
#define O_RDWR 2
|
||||
#define O_DIRECTORY 00200000
|
||||
#define O_NOFOLLOW 00400000
|
||||
#define O_NOFOLLOW_NOERROR 0x4000000
|
||||
|
||||
class CharacterDevice;
|
||||
class FileHandle;
|
||||
|
||||
|
@ -79,7 +86,7 @@ public:
|
|||
bool mountRoot(RetainPtr<FileSystem>&&);
|
||||
bool mount(RetainPtr<FileSystem>&&, const String& path);
|
||||
|
||||
OwnPtr<FileHandle> open(const String& path, InodeIdentifier base = InodeIdentifier());
|
||||
OwnPtr<FileHandle> open(const String& path, int options = 0, InodeIdentifier base = InodeIdentifier());
|
||||
OwnPtr<FileHandle> create(const String& path, InodeIdentifier base = InodeIdentifier());
|
||||
OwnPtr<FileHandle> mkdir(const String& path, InodeIdentifier base = InodeIdentifier());
|
||||
|
||||
|
@ -98,7 +105,7 @@ private:
|
|||
friend class FileHandle;
|
||||
|
||||
void enumerateDirectoryInode(InodeIdentifier, Function<bool(const FileSystem::DirectoryEntry&)>);
|
||||
InodeIdentifier resolvePath(const String& path, InodeIdentifier base = InodeIdentifier());
|
||||
InodeIdentifier resolvePath(const String& path, int& error, InodeIdentifier base = InodeIdentifier(), int options = 0);
|
||||
InodeIdentifier resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode);
|
||||
|
||||
RetainPtr<Node> allocateNode();
|
||||
|
|
|
@ -34,5 +34,5 @@
|
|||
#define EPIPE 32 // Broken pipe
|
||||
#define EDOM 33 // Math argument out of domain of func
|
||||
#define ERANGE 34 // Math result not representable
|
||||
|
||||
#define ELOOP 40 // Too many symbolic links
|
||||
#define EOVERFLOW 75 // Value too large for defined data type
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue