Skip to content

Commit

Permalink
finished zip, need more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
g2px1 committed May 11, 2023
1 parent cb92961 commit a2a99cf
Show file tree
Hide file tree
Showing 7 changed files with 378 additions and 84 deletions.
13 changes: 12 additions & 1 deletion theia_zip/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,15 @@ project(theia_zip)

set(CMAKE_CXX_STANDARD 20)

add_executable(theia_zip main.cpp zip.cpp zip.h)
find_package(zstd CONFIG REQUIRED)

add_executable(theia_zip
main.cpp
zip.h
ZIPArchive.h
ZIPArchive.cpp
crc32.h)

target_link_libraries(${PROJECT_NAME}
zstd::libzstd_static
)
113 changes: 113 additions & 0 deletions theia_zip/ZIPArchive.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//
// Created by Kirill Zhukov on 11.05.2023.
//

#include "ZIPArchive.h"


void ZIPArchive::lookup_directory() {
std::vector<std::string> directories = {this->path};

while (!directories.empty()) {
std::string dir_path = directories.back();
directories.pop_back();

DIR* dir = opendir(dir_path.c_str());
if (dir == nullptr) {
std::cerr << "Error opening directory " << dir_path << std::endl;
continue;
}

dirent* entry;
while ((entry = readdir(dir)) != nullptr) {
if (entry->d_type == DT_DIR) {
if (std::string(entry->d_name) == "." || std::string(entry->d_name) == "..") {
continue; // Skip current and parent directories
}
std::string subdir_path = dir_path + "/" + entry->d_name;
directories.push_back(subdir_path);
} else {
size_t pos = dir_path.find(this->path);
if (pos == std::string::npos) {
std::cerr << "Error: root path not found in directory path " << dir_path << std::endl;
continue;
}
std::string parent_path = dir_path.substr(pos + this->path.length());
if (parent_path.front() == '/') {
parent_path = parent_path.substr(1);
}

if (parent_path.empty()) {
this->files.emplace_back(entry->d_name);
} else {
this->files.push_back(std::string(parent_path).append("/").append(entry->d_name));
}
}
}
closedir(dir);
}
}

const std::string &ZIPArchive::getPath() const {
return path;
}

void ZIPArchive::setPath(const std::string &path) {
ZIPArchive::path = path;
}

const std::string &ZIPArchive::getArchivePath() const {
return archive_path;
}

void ZIPArchive::setArchivePath(const std::string &archivePath) {
archive_path = archivePath;
}

void ZIPArchive::archive() {
if (this->files.empty()) {
this->lookup_directory();
}
FILE *zip = fopen(this->archive_path.c_str(), "wb");

time_t mod_time = time(NULL);
tm_t *mod_tm = localtime(&mod_time);
uint16_t dos_mod_time = zip_time(mod_tm);
uint16_t dos_mod_date = zip_date(mod_tm);
std::vector<Compressed_file> compressed_files;

for (auto &it : this->files) {
std::string filepath = this->path + "/" + it;
if (isDirectory(filepath.c_str())) {
FILE *fp = fopen(filepath.c_str(), "r");
size_t uncompressed_filesize = getFileSize(fp);
char data[uncompressed_filesize];
fread(data, sizeof(data), 1, fp);
uint32_t crc32 = th_crc32((uint8_t *) data, uncompressed_filesize);
Compressed_file cf = compress_file(data);
cf.crc32 = crc32;
cf.lfh_offset = ftell(zip);
cf.uncompressed_size = uncompressed_filesize;
compressed_files.push_back(cf);
write_local_file_header(zip, it.c_str(), crc32, cf.compressed_size, uncompressed_filesize, dos_mod_time,
dos_mod_date);
fwrite(cf.compressed_data.c_str(), cf.compressed_size, 1, fp);
fclose(fp);
continue;
}
Compressed_file cf{};
cf.crc32 = 0;
cf.lfh_offset = ftell(zip);
cf.compressed_size = 0;
cf.uncompressed_size = 0;
compressed_files.push_back(cf);
write_local_file_header(zip, it.c_str(), 0, cf.compressed_size, 0, dos_mod_time, dos_mod_date);
}
ulong_t cd_offset = ftell(zip);
for (long_t i = 0; i < this->files.size(); i++) {
Compressed_file cf = compressed_files.at(i);
write_central_directory_file_header(zip, this->files.at(i).c_str(), cf.crc32, cf.compressed_size, cf.uncompressed_size, cf.lfh_offset, dos_mod_time, dos_mod_date);
}
ulong_t cd_sz = cd_offset - ftell(zip);
write_end_of_central_directory_record(zip, this->files.size(), cd_sz, cd_offset);
}
33 changes: 33 additions & 0 deletions theia_zip/ZIPArchive.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// Created by Kirill Zhukov on 11.05.2023.
//

#ifndef THEIA_ZIP_ZIPARCHIVE_H
#define THEIA_ZIP_ZIPARCHIVE_H
#include "iostream"
#include "vector"
#include "dirent.h"
#include "zip.h"
#include "crc32.h"

class ZIPArchive {
public:
ZIPArchive(char *path, char *archive_path) : path(path), archive_path(archive_path) {
generate_crc32_table();
}
public:
std::vector<std::string> files;
public:
void archive();
const std::string &getPath() const;
void setPath(const std::string &path);
const std::string &getArchivePath() const;
void setArchivePath(const std::string &archivePath);
private:
void lookup_directory();
private:
std::string path;
std::string archive_path;
};

#endif //THEIA_ZIP_ZIPARCHIVE_H
69 changes: 69 additions & 0 deletions theia_zip/crc32.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// Created by Kirill Zhukov on 11.05.2023.
//

#ifndef THEIA_ZIP_CRC32_H
#define THEIA_ZIP_CRC32_H

#include <cstdint>
#include "unistd.h"

static uint32_t crc_table[256];
static inline void generate_crc32_table() {
uint32_t c;
int i, j;

for (i = 0; i < 256; i++) {
c = i;
for (j = 0; j < 8; j++) {
if (c & 1) {
c = 0xEDB88320 ^ (c >> 1);
} else {
c = c >> 1;
}
}
crc_table[i] = c;
}
}

static inline uint32_t th_crc32(uint8_t *data, size_t length) {
uint32_t c = 0 ^ ~0U;
while (length--) {
c = crc_table[(c ^ *data++) & 0xFF] ^ (c >> 8);
}
return c ^ ~0U;
}

#if 0

#define POLYNOMIAL 0xEDB88320
uint32_t crc32(uint8_t *data, size_t len) {
uint32_t crc = ~0;
uint32_t i, j;
uint32_t byte;

static uint32_t table[0x100];

// Generate lookup table
if (table[1] == 0) {
for (i = 0; i < 0x100; ++i) {
uint32_t crc = i;
for (j = 0; j < 8; ++j) {
crc = (crc >> 1) ^ (- (int32_t)(crc & 1) & POLYNOMIAL);
}
table[i] = crc;
}
}

// Calculate CRC
for (i = 0; i < len; ++i) {
byte = data[i];
crc = (crc >> 8) ^ table[(crc ^ byte) & 0xFF];
}

return ~crc;
}

#endif

#endif //THEIA_ZIP_CRC32_H
65 changes: 3 additions & 62 deletions theia_zip/main.cpp
Original file line number Diff line number Diff line change
@@ -1,67 +1,8 @@
#include <cstdio>
#include <cstdlib>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstring>
#include <string>
#include <iostream>
#include "vector"
#include "stack"
#include <filesystem>

class DirectoryScanner {
public:
std::vector<std::string> files;
void print_directory_contents(const std::string& root_path) {
std::vector<std::string> directories = {root_path};

while (!directories.empty()) {
std::string dir_path = directories.back();
directories.pop_back();

DIR* dir = opendir(dir_path.c_str());
if (dir == nullptr) {
std::cerr << "Error opening directory " << dir_path << std::endl;
continue;
}

dirent* entry;
while ((entry = readdir(dir)) != nullptr) {
if (entry->d_type == DT_DIR) {
if (std::string(entry->d_name) == "." || std::string(entry->d_name) == "..") {
continue; // Skip current and parent directories
}
std::string subdir_path = dir_path + "/" + entry->d_name;
directories.push_back(subdir_path);
} else {
size_t pos = dir_path.find(root_path);
if (pos == std::string::npos) {
std::cerr << "Error: root path not found in directory path " << dir_path << std::endl;
continue;
}
std::string parent_path = dir_path.substr(pos + root_path.length());
if (parent_path.front() == '/') {
parent_path = parent_path.substr(1);
}
// std::cout << parent_path << "/" << entry->d_name << std::endl;
this->files.push_back(std::string(parent_path).append(entry->d_name));
}
}

closedir(dir);
}
}
};
#include "ZIPArchive.h"

int main(int argc, char *argv[]) {
DirectoryScanner directoryScanner;
directoryScanner.print_directory_contents("/Users/kirillzhukov/Desktop/test");
// print_directory_contents("/Users/kirillzhukov/Desktop/test", "");
for(auto it : directoryScanner.files) {
printf("dir: %s\n", it.c_str());
}
ZIPArchive archiver("/Users/kirillzhukov/Desktop/mvfst", "/Users/kirillzhukov/Desktop/ar/mvfst.zip");
archiver.archive();
return 0;
}

17 changes: 0 additions & 17 deletions theia_zip/zip.cpp

This file was deleted.

Loading

0 comments on commit a2a99cf

Please sign in to comment.