Skip to content

Instantly share code, notes, and snippets.

@BCDeshiG
Forked from mobius/libzip_simple.c
Last active November 5, 2021 16:11
Show Gist options
  • Save BCDeshiG/98b6be36bbef5632ef4a2f639b126716 to your computer and use it in GitHub Desktop.
Save BCDeshiG/98b6be36bbef5632ef4a2f639b126716 to your computer and use it in GitHub Desktop.
using libzip to extract files
/* Copyright (C) 2011 rocenting@gmail.com */
/* cc -o example.out libzip_simple.c -lzip */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <zip.h>
static void safe_create_dir(const char *dir)
{
if (mkdir(dir, 0755) < 0) {
if (errno != EEXIST) {
perror(dir);
exit(1);
}
}
}
int main(int argc, char *argv[])
{
const char *archive; // File path
struct zip *za; // Zip archive
struct zip_file *zf; // Stores file to be extracted
struct zip_stat sb; // Stores file info
char buf[100]; // Buffer to write stuff
int err; // Stores error code
int i, len;
FILE * fd; // Where file is extracted to
long long sum; // How much file has been copied so far
// Requires 1 argument (zip path)
if (argc != 2) {
fprintf(stderr, "Usage: %s archive.zip\n", argv[0]);
return 1;
}
// Open the zip file
archive = argv[1];
if ((za = zip_open(archive, 0, &err)) == NULL) {
zip_error_to_str(buf, sizeof(buf), err, errno);
fprintf(stderr, "Can't open zip archive '%s'\n", archive);
return 1;
}
// Unpack zip
for (i=0; i < zip_get_num_entries(za, 0); i++) { // Iterate through all files in zip
if (zip_stat_index(za, i, 0, &sb) == 0) { // Tries to grab file info
// Print file info
printf("==================\n");
printf("Name: [%s], ", sb.name);
printf("Size: [%llu], ", sb.size);
printf("mtime: [%u]\n", (unsigned int)sb.mtime);
len = strlen(sb.name);
if (sb.name[len - 1] == '/') { // Check if directory
safe_create_dir(sb.name); // Create directory
} else {
zf = zip_fopen_index(za, i, 0); // Open file within zip
if (!zf) {
fprintf(stderr, "Unable to open file within zip\n");
exit(100);
}
fd = fopen(sb.name, "wb"); // Create new file
if (fd == NULL) {
fprintf(stderr, "Unable to create destination file\n");
exit(101);
}
sum = 0;
while (sum != sb.size) { // Copy bytes to new file
len = zip_fread(zf, buf, 100);
if (len < 0) {
fprintf(stderr, "Unable to extract file contents\n");
exit(102);
}
fwrite(buf, 1, len, fd);
sum += len;
}
// Finished copying file
fclose(fd);
zip_fclose(zf);
}
} else {
printf("File[%s] Line[%d]\n", __FILE__, __LINE__);
}
}
if (zip_close(za) == -1) {
fprintf(stderr, "Can't close zip archive '%s'\n", archive);
return 1;
}
return 0;
}
@BCDeshiG
Copy link
Author

BCDeshiG commented Nov 5, 2021

Removed duplicated includes; fixed \n in outputs; altered to use fopen, fclose and fwrite instead of using unistd; added comments and more helpful error messages for my own learning purposes.

@BCDeshiG
Copy link
Author

BCDeshiG commented Nov 5, 2021

Why did the tab size change to 8?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment