Skip to content

Commit

Permalink
archive library rewrite with C
Browse files Browse the repository at this point in the history
  • Loading branch information
sulincix committed May 26, 2024
1 parent b7cdaf6 commit fdaf76b
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 267 deletions.
13 changes: 7 additions & 6 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,16 @@ deps += [dependency('gio-2.0', static: get_option('static'), required:true)]
pkgconfig_dep += ['gio-2.0']


#libarchive
#libarchive (no vapi)
if get_option('libarchive')
libarchive = dependency('libarchive', static:get_option('static'),required:false)
libarchive = dependency('libarchive', static:get_option('static'), required:false)
if not libarchive.found()
conf += ['no_libarchive']
endif
deps += [libarchive]
else
conf += ['libarchive']
pkgconfig_dep += ['libarchive']
endif
else
conf += ['no_libarchive']
error('libarchive not found')
endif

#libreadline
Expand Down
227 changes: 227 additions & 0 deletions src/ccode/archive-extract.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <archive.h>
#include <archive_entry.h>

extern void set_archive_type(char* type, char* algorthm);
extern void write_archive(char* path, char** add_list);

extern void error_add(char* message);

extern char* build_string(char* format, ...);

#if DEBUG
extern void debug(char* message);
#define fdebug(A, ...) \
do { \
char* message = build_string(A, ##__VA_ARGS__); \
debug(message); \
free(message); \
} while (0)
#else
#define debug(A)
#define fdebug(A,...)
#endif

extern void info(char* message);
#define finfo(A, ...) \
do { \
char* message = build_string(A, ##__VA_ARGS__); \
info(message); \
free(message); \
} while (0)

#include <archive_extract.h>

archive* archive_new(){
fdebug("new archive");
archive *data = calloc(1, sizeof(archive));
data->add_list_size = 0;
data->a = array_new();
return data;
}

void archive_unref(archive *data){
free(data);
}

void archive_load(archive *data, char* path) {
fdebug("archive load: %s", path);
data->archive_path = strdup(path);
set_archive_type("zip", "none");
}

void archive_load_archive(archive *data) {
data->archive = archive_read_new();
archive_read_support_filter_all(data->archive);
archive_read_support_format_all(data->archive);
if (archive_read_open_filename(data->archive, data->archive_path, 10240) != ARCHIVE_OK) {
char* error_msg = build_string("Failed to open archive: %s", archive_error_string(data->archive));
error_add(error_msg);
}
}

void archive_set_target(archive *data, char* target){
fdebug("archive set target: %s", target);
data->target_path = strdup(target);
}

int archive_is_archive(archive *data, char *path) {
fdebug("is archive: %s", path);
data->archive = archive_read_new();
archive_read_support_filter_all(data->archive);
archive_read_support_format_all(data->archive);
int result = archive_read_open_filename(data->archive, path, 10240);
return result == ARCHIVE_OK;
}

char** archive_list_files(archive *data, int* len) {
fdebug("archive list files: %s", data->archive_path);
archive_load_archive(data);
struct archive_entry *entry;
char **ret = NULL;
size_t ret_size = 0;
while (archive_read_next_header(data->archive, &entry) == ARCHIVE_OK) {
array_add(data->a,archive_entry_pathname(entry));
archive_read_data_skip(data->archive);
}
return array_get(data->a, len);
}

void archive_add(archive *data, char *path) {
fdebug("archive add: %s", path);
array_add(data->a, path);
}

void archive_create(archive *data){
fdebug("archive create: %s", data->archive_path);
int *len;
write_archive(data->archive_path, array_get(data->a, &len));
}

void archive_extract(archive *data, char *path) {
fdebug("archive extract: %s => %s", data->archive_path, path);
archive_load_archive(data);
struct archive_entry *entry;
while (archive_read_next_header(data->archive, &entry) == ARCHIVE_OK) {
char *entry_path = archive_entry_pathname(entry);
char *target_file = NULL;
if(strlen(entry_path) == 0){
continue;
} else if (strcmp(entry_path, path) != 0) {
continue;
}
finfo("Extract: %s", entry_path);
if (data->target_path != NULL) {
size_t target_file_len = strlen(data->target_path) + strlen(entry_path) + 2;
target_file = malloc(target_file_len);
snprintf((char *)target_file, target_file_len, "%s/%s", data->target_path, entry_path);
} else {
target_file = entry_path;
}
/* Check if entry is a directory */
mode_t mode = archive_entry_filetype(entry);
if (S_ISDIR(mode)) {
/* Create the directory if it doesn't exist */
if (access(target_file, F_OK) != -1) {
continue;
}
if (mkdir(target_file, 0755) != 0) {
char* error_msg = build_string("Failed to create directory: %s", target_file);
error_add(error_msg);
}
continue;
}
FILE *file = fopen(target_file, "wb");
if (file == NULL) {
char* error_msg = build_string("Failed to open file for writing: %s", target_file);
error_add(error_msg);
}
char buffer[4096];
ssize_t size;
while ((size = archive_read_data(data->archive, buffer, sizeof(buffer))) > 0) {
fwrite(buffer, 1, size, file);
}
fclose(file);
chmod(target_file, 0755);
}
}


char* archive_readfile(archive *data, char *file_path) {
archive_load_archive(data);
struct archive_entry *entry;
char *ret = NULL;
while (archive_read_next_header(data->archive, &entry) == ARCHIVE_OK) {
char *entry_path = archive_entry_pathname(entry);
if (strcmp(entry_path, file_path) != 0)
continue;
size_t size = archive_entry_size(entry);
ret = (char *)malloc(size + 1);
if (ret == NULL) {
char* error_msg = build_string("Memory allocation failed");
error_add(error_msg);
}
ssize_t bytes_read = archive_read_data(data->archive, ret, size);
if (bytes_read < 0) {
char* error_msg = build_string("Failed to read file: %s", archive_error_string(data->archive));
free(ret);
error_add(error_msg);
}
ret[bytes_read] = '\0';
break;
}
archive_read_close(data->archive);
return ret;
}

#include <sys/stat.h>

void archive_extract_all(archive *data) {
archive_load_archive(data);
struct archive_entry *entry;
while (archive_read_next_header(data->archive, &entry) == ARCHIVE_OK) {
char *entry_path = archive_entry_pathname(entry);
char *target_file = NULL;
if(strlen(entry_path) == 0){
continue;
}
finfo("Extract: %s", entry_path);
if (data->target_path != NULL) {
size_t target_file_len = strlen(data->target_path) + strlen(entry_path) + 2;
target_file = malloc(target_file_len);
snprintf((char *)target_file, target_file_len, "%s/%s", data->target_path, entry_path);
} else {
target_file = entry_path;
}
/* Check if entry is a directory */
mode_t mode = archive_entry_filetype(entry);
if (S_ISDIR(mode)) {
/* Create the directory if it doesn't exist */
if (access(target_file, F_OK) != -1) {
continue;
}
if (mkdir(target_file, 0755) != 0) {
char* error_msg = build_string("Failed to create directory: %s", target_file);
error_add(error_msg);
}
continue;
}
FILE *file = fopen(target_file, "wb");
if (file == NULL) {
char* error_msg = build_string("Failed to open file for writing: %s", target_file);
error_add(error_msg);
}
char buffer[4096];
ssize_t size;
while ((size = archive_read_data(data->archive, buffer, sizeof(buffer))) > 0){
fwrite(buffer, 1, size, file);
}
fclose(file);
chmod(target_file, 0755);
}
}


28 changes: 28 additions & 0 deletions src/include/archive_extract.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef ARCHIVE_CREATE_H
#define ARCHIVE_CREATE_H

#include <array.h>

typedef struct archive {
struct archive *archive;
char *archive_path;
char *target_path;
int add_list_size;
array *a;
} archive;

archive* archive_new();
void archive_create();
void archive_unref(archive* arch);
void archive_load(archive* arch, char* path);
void archive_set_target(archive* arch, char* path);
void archive_extract_all(archive* arch);
void archive_extract(archive* arch, char* path);
void archive_create_archive(archive* arch);
void archive_add(archive* arch, char* path);
char* archive_readfile(archive* arch, char* path);
char** archive_list_files(archive* arch, int* len);
int archive_is_archive(archive* arch, char* path);

#endif /* ARCHIVE_CREATE_H */

Loading

0 comments on commit fdaf76b

Please sign in to comment.