33 #include <archive_entry.h>
37 bool isSupportedArchiveType(
const std::string& extension)
41 const std::set<std::string> extensions{
"zip",
"gz",
"tgz",
"bz2",
"rar"};
42 return extensions.find(extension) != extensions.end();
45 archive* _openArchive(
const std::string& filename)
47 auto archive = archive_read_new();
48 archive_read_support_format_all(archive);
49 archive_read_support_filter_all(archive);
53 if (!extension.empty())
55 if (isSupportedArchiveType(extension))
56 archive_read_support_format_raw(archive);
58 if (archive_read_open_filename(archive, filename.c_str(), 10240) == ARCHIVE_OK)
62 archive_read_free(archive);
68 auto archive = archive_read_new();
69 archive_read_support_format_all(archive);
70 archive_read_support_filter_all(archive);
74 if (!extension.empty())
76 if (isSupportedArchiveType(extension))
77 archive_read_support_format_raw(archive);
79 if (archive_read_open_memory(archive, (
void*)blob.
data.data(), blob.
data.size()) == ARCHIVE_OK)
83 archive_read_free(archive);
87 int copy_data(
struct archive* ar,
struct archive* aw)
95 auto r = archive_read_data_block(ar, &buff, &size, &offset);
100 r = archive_write_data_block(aw, buff, size, offset);
103 std::cerr << archive_error_string(aw) << std::endl;
109 void _extractArchive(archive* archive,
const std::string& filename,
const std::string& destination)
111 auto writer = archive_write_disk_new();
112 archive_write_disk_set_options(writer, 0);
113 archive_write_disk_set_standard_lookup(writer);
117 archive_entry* entry;
118 auto r = archive_read_next_header(archive, &entry);
119 if (r == ARCHIVE_EOF)
122 std::cerr << archive_error_string(archive) << std::endl;
123 if (r < ARCHIVE_WARN)
125 throw std::runtime_error(std::string(
"Error reading file from archive: ") + archive_error_string(archive));
127 const char* currentFile = archive_entry_pathname(entry);
130 if (std::string(currentFile) ==
"data")
131 currentFile = filename.c_str();
132 const std::string fullOutputPath = destination +
"/" + currentFile;
133 archive_entry_set_pathname(entry, fullOutputPath.c_str());
134 r = archive_write_header(writer, entry);
136 std::cerr << archive_error_string(writer) << std::endl;
137 else if (archive_entry_size(entry) > 0)
139 r = copy_data(archive, writer);
141 std::cerr << archive_error_string(writer) << std::endl;
142 if (r < ARCHIVE_WARN)
143 throw std::runtime_error(std::string(
"Error writing file from archive to disk: ") +
144 archive_error_string(archive));
146 r = archive_write_finish_entry(writer);
148 std::cerr << archive_error_string(writer) << std::endl;
149 if (r < ARCHIVE_WARN)
150 throw std::runtime_error(std::string(
"Error finishing current file: ") + archive_error_string(archive));
152 archive_read_free(archive);
153 archive_write_close(writer);
154 archive_write_free(writer);
157 void extractFile(
const std::string& filename,
const std::string& destination)
159 auto archive = _openArchive(filename);
161 throw std::runtime_error(filename +
" is not a supported archive type");
162 _extractArchive(archive, fs::path(filename).stem().
string(), destination);
165 void extractBlob(
core::Blob&& blob,
const std::string& destination)
167 auto archive = _openArchive(blob);
169 throw std::runtime_error(
"Blob is not a supported archive type");
170 _extractArchive(archive, fs::path(blob.
name).stem().string(), destination);
179 if (!mkdtemp((
char*)path.data()))
180 throw std::runtime_error(
"Could not create temporary directory");
182 ~TmpFolder() { fs::remove_all(path); }
183 std::string path{
"/tmp/brayns_extracted_XXXXXX"};
191 , _registry(registry)
197 return isSupportedArchiveType(extension);
203 const auto loaderName = properties.
getProperty<std::string>(
"loaderName",
"");
206 for (
const auto& i : fs::directory_iterator(path))
208 const std::string currPath = i.path().string();
211 if (loader && loader->isSupported(currPath, extension))
213 return loader->importFromFile(currPath, callback, properties);
218 return loaderMatch.importFromFile(currPath, callback, properties);
221 throw std::runtime_error(
"No loader found for archive.");
228 extractBlob(std::move(blob), tmpFolder.path);
229 return loadExtracted(tmpFolder.path, callback, properties);
236 extractFile(filename, tmpFolder.path);
237 return loadExtracted(tmpFolder.path, callback, properties);
247 return {
"zip",
"gz",
"tgz",
"bz2",
"rar"};
ModelDescriptorPtr importFromStorage(const std::string &storage, const LoaderProgress &callback, const PropertyMap &properties) const final
ArchiveLoader(Scene &scene, LoaderRegistry ®istry)
ModelDescriptorPtr importFromBlob(Blob &&blob, const LoaderProgress &callback, const PropertyMap &properties) const final
bool isSupported(const std::string &storage, const std::string &extension) const final
std::string getName() const final
std::vector< std::string > getSupportedStorage() const final
bool isSupportedFile(const std::string &filename) const
const Loader & getSuitableLoader(const std::string &filename, const std::string &filetype, const std::string &loaderName) const
T getProperty(const std::string &name, T valIfNotFound) const
Scene object This object contains collections of geometries, materials and light sources that are use...
const std::string LOADER_NAME
std::shared_ptr< ModelDescriptor > ModelDescriptorPtr
std::string extractExtension(const std::string &filename)