diff --git a/Kernel/exec/binary_parse.cpp b/Kernel/exec/binary_parse.cpp index 4b063aa0..e91fd71a 100644 --- a/Kernel/exec/binary_parse.cpp +++ b/Kernel/exec/binary_parse.cpp @@ -100,6 +100,12 @@ namespace Execute BinaryType GetBinaryType(std::string Path) { FileNode *node = fs->GetByPath(Path.c_str(), nullptr); + if (node->IsSymbolicLink()) + { + char buffer[512]; + node->ReadLink(buffer, sizeof(buffer)); + node = fs->GetByPath(buffer, node->Parent); + } debug("Checking binary type of %s (returning %p)", Path.c_str(), node); assert(node != nullptr); return GetBinaryType(node); diff --git a/Kernel/exec/elf/elf_loader.cpp b/Kernel/exec/elf/elf_loader.cpp index a6ba646f..5d734fd7 100644 --- a/Kernel/exec/elf/elf_loader.cpp +++ b/Kernel/exec/elf/elf_loader.cpp @@ -335,6 +335,13 @@ namespace Execute } else { + if (ifd->IsSymbolicLink()) + { + char buffer[512]; + ifd->ReadLink(buffer, sizeof(buffer)); + ifd = fs->GetByPath(buffer, ifd->Parent); + } + debug("ifd: %p, interpreter: %s", ifd, interpreterPath.c_str()); if (GetBinaryType(interpreterPath) != BinTypeELF) { @@ -798,6 +805,14 @@ namespace Execute error("Failed to open %s, errno: %d", AbsolutePath.c_str(), fd); return; } + + if (fd->IsSymbolicLink()) + { + char buffer[512]; + fd->ReadLink(buffer, sizeof(buffer)); + fd = fs->GetByPath(buffer, fd->Parent); + } + debug("Opened %s", AbsolutePath.c_str()); int argc = 0; diff --git a/Kernel/exec/spawn.cpp b/Kernel/exec/spawn.cpp index e068b3f8..8c826763 100644 --- a/Kernel/exec/spawn.cpp +++ b/Kernel/exec/spawn.cpp @@ -40,9 +40,20 @@ namespace Execute return -ENOENT; if (!fd->IsRegularFile()) - return -ENOEXEC; + { + if (fd->IsSymbolicLink()) + { + char buffer[512]; + fd->ReadLink(buffer, sizeof(buffer)); + fd = fs->GetByPath(buffer, fd->Parent); + if (fd == nullptr) + return -ENOENT; + } + else + return -ENOEXEC; + } - switch (GetBinaryType(Path)) + switch (GetBinaryType(fd)) { case BinaryType::BinTypeELF: { diff --git a/Kernel/storage/filesystem.cpp b/Kernel/storage/filesystem.cpp index 5fd5f9e0..2ca81220 100644 --- a/Kernel/storage/filesystem.cpp +++ b/Kernel/storage/filesystem.cpp @@ -161,6 +161,7 @@ namespace vfs } Inode *Node = NULL; + bool readSymlinks = true; /* FIXME: implement */ do { auto it = DeviceMap.find(__Parent->Node->Device); @@ -170,6 +171,22 @@ namespace vfs if (it->second.fsi->Ops.Lookup == NULL) ReturnLogError(nullptr, "Lookup not supported for %d", it->first); + if (readSymlinks && __Parent->IsSymbolicLink()) + { + if (it->second.fsi->Ops.ReadLink == NULL) + ReturnLogError(nullptr, "Readlink not supported for %d", it->first); + + char buffer[256]; + int ret = it->second.fsi->Ops.ReadLink(__Parent->Node, buffer, sizeof(buffer)); + if (ret < 0) + ReturnLogError(nullptr, "Readlink for \"%s\"(%d) failed with %d", __Parent->Path.c_str(), it->first, ret); + + FileNode *target = this->GetByPath(buffer, __Parent->Parent ? __Parent->Parent : __Parent); + if (target == nullptr) + ReturnLogError(nullptr, "Failed to find target for \"%s\"", __Parent->Path.c_str()); + __Parent = target; + } + std::string segmentName(segment.begin, segment.size); int ret = it->second.fsi->Ops.Lookup(__Parent->Node, segmentName.c_str(), &Node); if (ret < 0) diff --git a/Kernel/storage/fs/ustar.cpp b/Kernel/storage/fs/ustar.cpp index e8b84d93..890c3231 100644 --- a/Kernel/storage/fs/ustar.cpp +++ b/Kernel/storage/fs/ustar.cpp @@ -389,7 +389,7 @@ namespace vfs Size = strlen(node->Header->link); strncpy(Buffer, node->Header->link, Size); - debug("Read %d bytes from %d", Size, Node->Index); + debug("Read %d bytes from %d: \"%s\"", Size, Node->Index, Buffer); return Size; } diff --git a/Kernel/tasking/process.cpp b/Kernel/tasking/process.cpp index f23735ce..f4f7117b 100644 --- a/Kernel/tasking/process.cpp +++ b/Kernel/tasking/process.cpp @@ -113,6 +113,12 @@ namespace Tasking trace("Setting exe %s to %s", this->Name, path); Executable = fs->GetByPath(path, ProcDirectory); + if (Executable->IsSymbolicLink()) + { + char buffer[512]; + Executable->ReadLink(buffer, sizeof(buffer)); + Executable = fs->GetByPath(buffer, Executable->Parent); + } FileNode *exe = fs->GetByPath("exe", ProcDirectory); if (exe) fs->Remove(exe);