| 181 | } |
| 182 | |
| 183 | std::shared_ptr<IBlob> TarFile::readFile(const std::filesystem::path& name) |
| 184 | { |
| 185 | std::string normalizedName = name.lexically_normal().relative_path().generic_string(); |
| 186 | |
| 187 | if (normalizedName.empty()) |
| 188 | return nullptr; |
| 189 | |
| 190 | auto entry = m_Files.find(normalizedName); |
| 191 | |
| 192 | if (entry == m_Files.end()) |
| 193 | return nullptr; |
| 194 | |
| 195 | // prevent concurrent file operations from multiple threads from this point on |
| 196 | std::lock_guard<std::mutex> lockGuard(m_Mutex); |
| 197 | |
| 198 | if (fseeko(m_ArchiveFile, entry->second.offset, SEEK_SET) != 0) |
| 199 | { |
| 200 | log::warning("Error seeking to offset %ull for file '%s' in tar archive '%s'", |
| 201 | entry->second.offset, normalizedName.c_str(), m_ArchivePath.c_str()); |
| 202 | return nullptr; |
| 203 | } |
| 204 | |
| 205 | void* data = malloc(entry->second.size); |
| 206 | |
| 207 | if (!data) |
| 208 | return nullptr; |
| 209 | |
| 210 | size_t sizeRead = fread(data, 1, entry->second.size, m_ArchiveFile); |
| 211 | |
| 212 | if (sizeRead != entry->second.size) |
| 213 | { |
| 214 | log::warning("Error reading file '%s' (%ull bytes) from tar archive '%s'", |
| 215 | entry->second.size, normalizedName.c_str(), m_ArchivePath.c_str()); |
| 216 | free(data); |
| 217 | return nullptr; |
| 218 | } |
| 219 | |
| 220 | std::shared_ptr<Blob> blob = std::make_shared<Blob>(data, entry->second.size); |
| 221 | |
| 222 | return std::static_pointer_cast<IBlob>(blob); |
| 223 | } |
| 224 | |
| 225 | bool TarFile::writeFile(const std::filesystem::path&, const void*, size_t) |
| 226 | { |