1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-30 14:38:12 +00:00

Fix up VFS::resolveSymbolicLink() to use a base inode instead of a base path.

Also more VFS error plumbing.
This commit is contained in:
Andreas Kling 2018-10-28 14:25:51 +01:00
parent 97726862dd
commit bea106fdb2
4 changed files with 24 additions and 25 deletions

View file

@ -234,11 +234,9 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
cwd = parentTask->m_cwd.copyRef(); cwd = parentTask->m_cwd.copyRef();
} }
auto handle = VirtualFileSystem::the().open(path, 0, cwd ? cwd->inode : InodeIdentifier()); auto handle = VirtualFileSystem::the().open(path, error, 0, cwd ? cwd->inode : InodeIdentifier());
if (!handle) { if (!handle)
error = -ENOENT; // FIXME: Get a more detailed error from VFS.
return nullptr; return nullptr;
}
if (!handle->metadata().mayExecute(uid, gid)) { if (!handle->metadata().mayExecute(uid, gid)) {
error = -EACCES; error = -EACCES;
@ -786,9 +784,10 @@ int Task::sys$close(int fd)
int Task::sys$lstat(const char* path, Unix::stat* statbuf) int Task::sys$lstat(const char* path, Unix::stat* statbuf)
{ {
VALIDATE_USER_BUFFER(statbuf, sizeof(Unix::stat)); VALIDATE_USER_BUFFER(statbuf, sizeof(Unix::stat));
auto handle = VirtualFileSystem::the().open(move(path), O_NOFOLLOW_NOERROR, cwdInode()); int error;
auto handle = VirtualFileSystem::the().open(move(path), error, O_NOFOLLOW_NOERROR, cwdInode());
if (!handle) if (!handle)
return -1; return error;
handle->stat(statbuf); handle->stat(statbuf);
return 0; return 0;
} }
@ -798,9 +797,10 @@ int Task::sys$readlink(const char* path, char* buffer, size_t size)
VALIDATE_USER_BUFFER(path, strlen(path)); VALIDATE_USER_BUFFER(path, strlen(path));
VALIDATE_USER_BUFFER(buffer, size); VALIDATE_USER_BUFFER(buffer, size);
auto handle = VirtualFileSystem::the().open(path, O_RDONLY | O_NOFOLLOW_NOERROR, cwdInode()); int error;
auto handle = VirtualFileSystem::the().open(path, error, O_RDONLY | O_NOFOLLOW_NOERROR, cwdInode());
if (!handle) if (!handle)
return -ENOENT; // FIXME: Get a more detailed error from VFS. return error;
if (!handle->metadata().isSymbolicLink()) if (!handle->metadata().isSymbolicLink())
return -EINVAL; return -EINVAL;
@ -818,9 +818,10 @@ int Task::sys$readlink(const char* path, char* buffer, size_t size)
int Task::sys$chdir(const char* path) int Task::sys$chdir(const char* path)
{ {
VALIDATE_USER_BUFFER(path, strlen(path)); VALIDATE_USER_BUFFER(path, strlen(path));
auto handle = VirtualFileSystem::the().open(path, 0, cwdInode()); int error;
auto handle = VirtualFileSystem::the().open(path, error, 0, cwdInode());
if (!handle) if (!handle)
return -ENOENT; // FIXME: More detailed error. return error;
if (!handle->isDirectory()) if (!handle->isDirectory())
return -ENOTDIR; return -ENOTDIR;
m_cwd = handle->vnode(); m_cwd = handle->vnode();
@ -842,9 +843,10 @@ int Task::sys$open(const char* path, int options)
VALIDATE_USER_BUFFER(path, strlen(path)); VALIDATE_USER_BUFFER(path, strlen(path));
if (m_fileHandles.size() >= m_maxFileHandles) if (m_fileHandles.size() >= m_maxFileHandles)
return -EMFILE; return -EMFILE;
auto handle = VirtualFileSystem::the().open(path, 0, cwdInode()); int error;
auto handle = VirtualFileSystem::the().open(path, error, 0, cwdInode());
if (!handle) if (!handle)
return -ENOENT; // FIXME: Detailed error. return error;
if (options & O_DIRECTORY && !handle->isDirectory()) if (options & O_DIRECTORY && !handle->isDirectory())
return -ENOTDIR; // FIXME: This should be handled by VFS::open. return -ENOTDIR; // FIXME: This should be handled by VFS::open.

View file

@ -131,7 +131,8 @@ static void init_stage2()
#ifdef KSYMS #ifdef KSYMS
{ {
auto handle = vfs->open("/kernel.map"); int error;
auto handle = vfs->open("/kernel.map", error);
if (!handle) { if (!handle) {
kprintf("Failed to open /kernel.map\n"); kprintf("Failed to open /kernel.map\n");
} else { } else {

View file

@ -363,11 +363,10 @@ bool VirtualFileSystem::touch(const String& path)
return inode.fileSystem()->setModificationTime(inode, ktime(nullptr)); return inode.fileSystem()->setModificationTime(inode, ktime(nullptr));
} }
OwnPtr<FileHandle> VirtualFileSystem::open(const String& path, int options, InodeIdentifier base) OwnPtr<FileHandle> VirtualFileSystem::open(const String& path, int& error, int options, InodeIdentifier base)
{ {
Locker locker(VirtualFileSystem::lock()); Locker locker(VirtualFileSystem::lock());
int error;
auto inode = resolvePath(path, error, base, options); auto inode = resolvePath(path, error, base, options);
if (!inode.isValid()) if (!inode.isValid())
return nullptr; return nullptr;
@ -397,15 +396,12 @@ OwnPtr<FileHandle> VirtualFileSystem::mkdir(const String& path, InodeIdentifier
return nullptr; return nullptr;
} }
InodeIdentifier VirtualFileSystem::resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode) InodeIdentifier VirtualFileSystem::resolveSymbolicLink(InodeIdentifier base, InodeIdentifier symlinkInode, int& error)
{ {
auto symlinkContents = symlinkInode.readEntireFile(); auto symlinkContents = symlinkInode.readEntireFile();
if (!symlinkContents) if (!symlinkContents)
return { }; return { };
char buf[4096]; return resolvePath((const char*)symlinkContents.pointer(), error, base);
ksprintf(buf, "/%s/%s", basePath.characters(), String((const char*)symlinkContents.pointer(), symlinkContents.size()).characters());
int error;
return resolvePath(buf, error);
} }
String VirtualFileSystem::absolutePath(InodeIdentifier inode) String VirtualFileSystem::absolutePath(InodeIdentifier inode)
@ -474,12 +470,13 @@ InodeIdentifier VirtualFileSystem::resolvePath(const String& path, int& error, I
error = -EIO; error = -EIO;
return { }; return { };
} }
auto parent = inode;
inode = inode.fileSystem()->childOfDirectoryInodeWithName(inode, part); inode = inode.fileSystem()->childOfDirectoryInodeWithName(inode, part);
if (!inode.isValid()) { if (!inode.isValid()) {
#ifdef VFS_DEBUG #ifdef VFS_DEBUG
kprintf("bad child\n"); kprintf("bad child\n");
#endif #endif
error = -EIO; error = -ENOENT;
return { }; return { };
} }
#ifdef VFS_DEBUG #ifdef VFS_DEBUG
@ -514,10 +511,9 @@ InodeIdentifier VirtualFileSystem::resolvePath(const String& path, int& error, I
for (unsigned j = 0; j < i; ++j) { for (unsigned j = 0; j < i; ++j) {
p += ksprintf(p, "/%s", parts[j].characters()); p += ksprintf(p, "/%s", parts[j].characters());
} }
inode = resolveSymbolicLink(buf, inode); inode = resolveSymbolicLink(parent, inode, error);
if (!inode.isValid()) { if (!inode.isValid()) {
kprintf("Symbolic link resolution failed :(\n"); kprintf("Symbolic link resolution failed :(\n");
error = -ENOENT;
return { }; return { };
} }
} }

View file

@ -86,7 +86,7 @@ public:
bool mountRoot(RetainPtr<FileSystem>&&); bool mountRoot(RetainPtr<FileSystem>&&);
bool mount(RetainPtr<FileSystem>&&, const String& path); bool mount(RetainPtr<FileSystem>&&, const String& path);
OwnPtr<FileHandle> open(const String& path, int options = 0, InodeIdentifier base = InodeIdentifier()); OwnPtr<FileHandle> open(const String& path, int& error, int options = 0, InodeIdentifier base = InodeIdentifier());
OwnPtr<FileHandle> create(const String& path, InodeIdentifier base = InodeIdentifier()); OwnPtr<FileHandle> create(const String& path, InodeIdentifier base = InodeIdentifier());
OwnPtr<FileHandle> mkdir(const String& path, InodeIdentifier base = InodeIdentifier()); OwnPtr<FileHandle> mkdir(const String& path, InodeIdentifier base = InodeIdentifier());
@ -106,7 +106,7 @@ private:
void enumerateDirectoryInode(InodeIdentifier, Function<bool(const FileSystem::DirectoryEntry&)>); void enumerateDirectoryInode(InodeIdentifier, Function<bool(const FileSystem::DirectoryEntry&)>);
InodeIdentifier resolvePath(const String& path, int& error, InodeIdentifier base = InodeIdentifier(), int options = 0); InodeIdentifier resolvePath(const String& path, int& error, InodeIdentifier base = InodeIdentifier(), int options = 0);
InodeIdentifier resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode); InodeIdentifier resolveSymbolicLink(InodeIdentifier base, InodeIdentifier symlinkInode, int& error);
RetainPtr<Node> allocateNode(); RetainPtr<Node> allocateNode();
void freeNode(Node*); void freeNode(Node*);