MCPcopy Create free account
hub / github.com/OpenTTD/OpenTTD / ExtractTar

Function ExtractTar

src/fileio.cpp:590–654  ·  view source on GitHub ↗

* Extract the tar with the given filename in the directory * where the tar resides. * @param tar_filename the name of the tar to extract. * @param subdir The sub directory the tar is in. * @return false on failure. */

Source from the content-addressed store, hash-verified

588 * @return false on failure.
589 */
590bool ExtractTar(const std::string &tar_filename, Subdirectory subdir)
591{
592 TarList::iterator it = _tar_list[subdir].find(tar_filename);
593 /* We don't know the file. */
594 if (it == _tar_list[subdir].end()) return false;
595
596 const auto &dirname = it->second;
597
598 /* The file doesn't have a sub directory! */
599 if (dirname.empty()) {
600 Debug(misc, 3, "Extracting {} failed; archive rejected, the contents must be in a sub directory", tar_filename);
601 return false;
602 }
603
604 std::string filename = tar_filename;
605 auto p = filename.find_last_of(PATHSEPCHAR);
606 /* The file's path does not have a separator? */
607 if (p == std::string::npos) return false;
608
609 filename.replace(p + 1, std::string::npos, dirname);
610 Debug(misc, 8, "Extracting {} to directory {}", tar_filename, filename);
611 FioCreateDirectory(filename);
612
613 for (auto &it2 : _tar_filelist[subdir]) {
614 if (tar_filename != it2.second.tar_filename) continue;
615
616 /* it2.first is tarball + PATHSEPCHAR + name. */
617 std::string_view name = it2.first;
618 name.remove_prefix(name.find_first_of(PATHSEPCHAR) + 1);
619 filename.replace(p + 1, std::string::npos, name);
620
621 Debug(misc, 9, " extracting {}", filename);
622
623 /* First open the file in the .tar. */
624 size_t to_copy = 0;
625 auto in = FioFOpenFileTar(it2.second, &to_copy);
626 if (!in.has_value()) {
627 Debug(misc, 6, "Extracting {} failed; could not open {}", filename, tar_filename);
628 return false;
629 }
630
631 /* Now open the 'output' file. */
632 auto out = FileHandle::Open(filename, "wb");
633 if (!out.has_value()) {
634 Debug(misc, 6, "Extracting {} failed; could not open {}", filename, filename);
635 return false;
636 }
637
638 /* Now read from the tar and write it into the file. */
639 char buffer[4096];
640 size_t read;
641 for (; to_copy != 0; to_copy -= read) {
642 read = fread(buffer, 1, std::min(to_copy, lengthof(buffer)), *in);
643 if (read <= 0 || fwrite(buffer, 1, read, *out) != read) break;
644 }
645
646 if (to_copy != 0) {
647 Debug(misc, 6, "Extracting {} failed; still {} bytes to copy", filename, to_copy);

Callers 1

AfterDownloadMethod · 0.85

Calls 5

FioCreateDirectoryFunction · 0.85
FioFOpenFileTarFunction · 0.85
findMethod · 0.45
endMethod · 0.45
emptyMethod · 0.45

Tested by

no test coverage detected