/* This file is part of Fennix Kernel. Fennix Kernel is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fennix Kernel is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Fennix Kernel. If not, see . */ #include #include #include #include "../../kernel.h" namespace vfs { size_t USTARNode::read(uint8_t *Buffer, size_t Size, off_t Offset) { if (Size <= 0) Size = this->Size; if (Offset > this->Size) return 0; if ((this->Size - Offset) == 0) return 0; /* EOF */ if (Offset + (off_t)Size > this->Size) Size = this->Size; memcpy(Buffer, (uint8_t *)(this->Address + Offset), Size); return Size; } USTARNode::USTARNode(uintptr_t Address, const char *Name, NodeType Type, Virtual *vfs_ctx) : Node(nullptr, Name, Type, true, vfs_ctx, nullptr), Address(Address) { } USTARNode::~USTARNode() {} bool USTAR::TestArchive(uintptr_t Address) { if (!Memory::Virtual().Check((void *)Address)) { error("Address %#lx is not mapped!", Address); return false; } FileHeader *header = (FileHeader *)Address; if (memcmp(header->signature, "ustar", 5) != 0) { error("ustar signature invalid!"); return false; } return true; } void USTAR::ReadArchive(uintptr_t Address, Virtual *vfs_ctx) { trace("Initializing USTAR with address %#lx", Address); if (!this->TestArchive(Address)) return; /* Check whether the archive is deflated */ FileHeader *header = (FileHeader *)Address; debug("USTAR signature valid! Name:%s Signature:%s Mode:%d Size:%lu", header->name, header->signature, string2int(header->mode), header->size); for (size_t i = 0;; i++) { if (memcmp(header->signature, "ustar", 5) != 0) break; memmove(header->name, header->name + 1, strlen(header->name)); if (header->name[strlen(header->name) - 1] == '/') { debug("Removing trailing slash from %s", header->name); header->name[strlen(header->name) - 1] = 0; } // if (!isempty((char *)header->name)) // KPrint("Adding file \e88AACC%s\eCCCCCC (\e88AACC%lu \eCCCCCCbytes)", header->name, size); // else // goto NextFileAddress; size_t size = getsize(header->size); Node *node; NodeType type = NODE_TYPE_NONE; if (isempty((char *)header->name)) goto NextFileAddress; switch (header->typeflag[0]) { case REGULAR_FILE: type = NodeType::FILE; break; case SYMLINK: type = NodeType::SYMLINK; break; case DIRECTORY: type = NodeType::DIRECTORY; break; case CHARDEV: type = NodeType::CHARDEVICE; break; case BLOCKDEV: type = NodeType::BLOCKDEVICE; break; default: warn("Unknown type: %d", header->typeflag[0]); break; } node = new USTARNode((Address + 512), header->name, type, vfs_ctx); // debug("%s %d KiB, Type:%c", header->name, // TO_KiB(size), header->typeflag[0]); node->Mode = string2int(header->mode); node->Size = size; node->GroupIdentifier = getsize(header->gid); node->UserIdentifier = getsize(header->uid); node->DeviceMajor = getsize(header->dev_maj); node->DeviceMinor = getsize(header->dev_min); node->AccessTime = getsize(header->mtime); node->ModifyTime = getsize(header->mtime); node->ChangeTime = getsize(header->mtime); node->IndexNode = i; if (type == NodeType::SYMLINK) { node->Symlink = new char[strlen(header->link) + 1]; strncpy((char *)node->Symlink, header->link, strlen(header->link)); } NextFileAddress: Address += ((size / 512) + 1) * 512; if (size % 512) Address += 512; header = (FileHeader *)Address; } } USTAR::USTAR() {} USTAR::~USTAR() {} }