Skip to content

Instantly share code, notes, and snippets.

@GameKyuubi
Forked from clalancette/ziptest.cc
Last active May 14, 2023 03:49
Show Gist options
  • Save GameKyuubi/590fe295493b88f444c1ed2b8f06084b to your computer and use it in GitHub Desktop.
Save GameKyuubi/590fe295493b88f444c1ed2b8f06084b to your computer and use it in GitHub Desktop.
packager for SRB2Kart mods
//
// Compile with
// g++ -o srb2kz -lzip srb2kz.cc
//
#include <iostream>
#include <string>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <zip.h>
#include <vector>
#include <algorithm>
static bool is_dir(const std::string& dir)
{
struct stat st;
::stat(dir.c_str(), &st);
return S_ISDIR(st.st_mode);
}
static void walk_directory(const std::string& startdir, const std::string& inputdir, zip_t *zipper)
{
printf("WalkDirectory(Startdir: %s, Inputdir: %s) \n", startdir.c_str(), inputdir.c_str());
DIR *dp = ::opendir(inputdir.c_str());
if (dp == nullptr) {
throw std::runtime_error("Failed to open input directory: " + std::string(::strerror(errno)));
}
// Read all directory entries into a vector.
std::vector<std::string> entries;
struct dirent *dirp;
while ((dirp = readdir(dp)) != NULL) {
if (dirp->d_name[0] != '.' && dirp->d_name != std::string("..")) {
entries.push_back(dirp->d_name);
}
}
::closedir(dp);
// Sort the entries.
std::sort(entries.begin(), entries.end());
// Now walk through the sorted entries.
for (const auto& entry : entries) {
std::string fullname = inputdir + "/" + entry;
if (is_dir(fullname)) {
if (zip_dir_add(zipper, fullname.substr(startdir.length() + 1).c_str(), ZIP_FL_ENC_UTF_8) < 0) {
throw std::runtime_error("Failed to add directory to zip: " + std::string(zip_strerror(zipper)));
}
walk_directory(startdir, fullname, zipper);
} else {
zip_source_t *source = zip_source_file(zipper, fullname.c_str(), 0, 0);
if (source == nullptr) {
throw std::runtime_error("Failed to add file to zip: " + std::string(zip_strerror(zipper)));
}
if (zip_file_add(zipper, fullname.substr(startdir.length() + 1).c_str(), source, ZIP_FL_ENC_UTF_8) < 0) {
zip_source_free(source);
throw std::runtime_error("Failed to add file to zip: " + std::string(zip_strerror(zipper)));
}
}
}
}
static void zip_directory(const std::string& inputdir, const std::string& output_filename)
{
int errorp;
zip_t *zipper = zip_open(output_filename.c_str(), ZIP_CREATE | ZIP_EXCL, &errorp);
if (zipper == nullptr) {
zip_error_t ziperror;
zip_error_init_with_code(&ziperror, errorp);
throw std::runtime_error("Failed to open output file " + output_filename + ": " + zip_error_strerror(&ziperror));
}
try {
walk_directory(inputdir, inputdir, zipper);
} catch(...) {
zip_close(zipper);
throw;
}
zip_close(zipper);
}
int main(int argc, char *argv[])
{
if (argc != 3) {
fprintf(stderr, "Usage: %s <input_dir> <output_file>\n", argv[0]);
return 1;
}
zip_directory(argv[1], argv[2]);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment