Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/SoftEtherVPN/libhamcore.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavide Beatrici <git@davidebeatrici.dev>2021-03-10 00:06:53 +0300
committerDavide Beatrici <git@davidebeatrici.dev>2021-03-10 00:06:53 +0300
commitc798511e419ededd0cbe34a09f2aaca5111d9576 (patch)
tree040b3dde21f4e86509087330b8b40e7fe6d1ee82
parentafe882a6739dcb0efba5cc9fabd7647b98a9fbba (diff)
Introduce HamcoreBuild(), for building archives
-rwxr-xr-xFileSystem.c55
-rwxr-xr-xFileSystem.h8
-rw-r--r--Hamcore.c187
-rw-r--r--Hamcore.h2
-rw-r--r--Memory.c13
-rw-r--r--Memory.h2
6 files changed, 263 insertions, 4 deletions
diff --git a/FileSystem.c b/FileSystem.c
index b691746..cb64fe5 100755
--- a/FileSystem.c
+++ b/FileSystem.c
@@ -1,13 +1,17 @@
#include "FileSystem.h"
-FILE *FileOpen(const char *path)
+#include <string.h>
+
+#include <sys/stat.h>
+
+FILE *FileOpen(const char *path, const bool write)
{
if (!path)
{
return NULL;
}
- return fopen(path, "rb");
+ return fopen(path, write ? "wb" : "rb");
}
bool FileClose(FILE *file)
@@ -30,6 +34,16 @@ bool FileRead(FILE *file, void *dst, const size_t size)
return fread(dst, 1, size, file) == size;
}
+bool FileWrite(FILE *file, const void *src, const size_t size)
+{
+ if (!file || !src || size == 0)
+ {
+ return false;
+ }
+
+ return fwrite(src, 1, size, file) == size;
+}
+
bool FileSeek(FILE *file, const size_t offset)
{
if (!file)
@@ -39,3 +53,40 @@ bool FileSeek(FILE *file, const size_t offset)
return fseek(file, offset, SEEK_SET) == 0;
}
+
+size_t FileSize(const char *path)
+{
+ if (!path)
+ {
+ return 0;
+ }
+
+ struct stat st;
+ if (stat(path, &st) == -1)
+ {
+ return 0;
+ }
+
+ return st.st_size;
+}
+
+const char *PathRelativeToBase(const char *full, const char *base)
+{
+ if (!full || !base)
+ {
+ return NULL;
+ }
+
+ if (strstr(full, base) != &full[0])
+ {
+ return NULL;
+ }
+
+ full += strlen(base);
+ if (full[0] == '/')
+ {
+ ++full;
+ }
+
+ return full;
+}
diff --git a/FileSystem.h b/FileSystem.h
index 3d61408..b4092c7 100755
--- a/FileSystem.h
+++ b/FileSystem.h
@@ -4,10 +4,16 @@
#include <stdbool.h>
#include <stdio.h>
-FILE *FileOpen(const char *path);
+FILE *FileOpen(const char *path, const bool write);
bool FileClose(FILE *file);
bool FileRead(FILE *file, void *dst, const size_t size);
+bool FileWrite(FILE *file, const void *src, const size_t size);
+
bool FileSeek(FILE *file, const size_t offset);
+size_t FileSize(const char *path);
+
+const char *PathRelativeToBase(const char *full, const char *base);
+
#endif
diff --git a/Hamcore.c b/Hamcore.c
index 63eb9c3..229129e 100644
--- a/Hamcore.c
+++ b/Hamcore.c
@@ -8,6 +8,12 @@
#include <zlib.h>
+typedef struct COMPRESSED_FILE
+{
+ void *Data;
+ HAMCORE_FILE File;
+} COMPRESSED_FILE;
+
HAMCORE *HamcoreOpen(const char *path)
{
if (!path)
@@ -18,7 +24,7 @@ HAMCORE *HamcoreOpen(const char *path)
HAMCORE *hamcore = malloc(sizeof(HAMCORE));
memset(hamcore, 0, sizeof(HAMCORE));
- hamcore->File = FileOpen(path);
+ hamcore->File = FileOpen(path, false);
if (!hamcore->File)
{
free(hamcore);
@@ -190,3 +196,182 @@ FINAL:
free(buf);
return ok;
}
+
+bool HamcoreBuild(const char *dst_path, const char *base_path, const char **src_paths, const size_t num)
+{
+ if (!dst_path || !src_paths || num == 0)
+ {
+ return false;
+ }
+
+ COMPRESSED_FILE *compressed_files = calloc(num, sizeof(COMPRESSED_FILE));
+
+ void *buffer = NULL;
+ size_t buffer_size = 0;
+
+ for (size_t i = 0; i < num; ++i)
+ {
+ const char *path = src_paths[i];
+ if (!path)
+ {
+ continue;
+ }
+
+ FILE *handle = FileOpen(path, false);
+ if (!handle)
+ {
+ fprintf(stderr, "HamcoreBuild(): Failed to open \"%s\", skipping...\n", path);
+ continue;
+ }
+
+ COMPRESSED_FILE *compressed_file = &compressed_files[i];
+ HAMCORE_FILE *file = &compressed_file->File;
+
+ file->OriginalSize = FileSize(path);
+ void *content = malloc(file->OriginalSize);
+ int ret = FileRead(handle, content, file->OriginalSize);
+ FileClose(handle);
+
+ if (!ret)
+ {
+ fprintf(stderr, "HamcoreBuild(): Failed to read \"%s\", skipping...\n", path);
+ free(content);
+ continue;
+ }
+
+ const size_t wanted_size = CompressionBufferSize(file->OriginalSize);
+ if (buffer_size < wanted_size)
+ {
+ const size_t prev_size = buffer_size;
+ buffer_size = wanted_size;
+ buffer = realloc(buffer, buffer_size);
+ memset(buffer + prev_size, 0, buffer_size - prev_size);
+ }
+
+ file->Size = buffer_size;
+ ret = compress(buffer, (uLongf *)&file->Size, content, (uLong)file->OriginalSize);
+ free(content);
+
+ if (ret != Z_OK)
+ {
+ fprintf(stderr, "HamcoreBuild(): Failed to compress \"%s\" with error %d, skipping...\n", path, ret);
+ file->Size = 0;
+ continue;
+ }
+
+ const char *relative_path = base_path ? PathRelativeToBase(path, base_path) : path;
+ if (!relative_path)
+ {
+ fprintf(stderr, "HamcoreBuild(): Failed to get relative path for \"%s\", skipping...\n", path);
+ file->Size = 0;
+ continue;
+ }
+
+ const size_t path_size = strlen(relative_path) + 1;
+ file->Path = malloc(path_size);
+ memcpy(file->Path, relative_path, path_size);
+
+ compressed_file->Data = malloc(file->Size);
+ memcpy(compressed_file->Data, buffer, file->Size);
+ }
+
+ size_t offset = HAMCORE_HEADER_SIZE;
+ // Number of files
+ offset += sizeof(uint32_t);
+
+ // File table
+ for (size_t i = 0; i < num; ++i)
+ {
+ const HAMCORE_FILE *file = &compressed_files[i].File;
+ if (file->Size == 0)
+ {
+ continue;
+ }
+
+ // Path (length + string)
+ offset += sizeof(uint32_t) + strlen(file->Path);
+ // Original size
+ offset += sizeof(uint32_t);
+ // Size
+ offset += sizeof(uint32_t);
+ // Offset
+ offset += sizeof(uint32_t);
+ }
+
+ for (size_t i = 0; i < num; ++i)
+ {
+ HAMCORE_FILE *file = &compressed_files[i].File;
+ if (file->Size == 0)
+ {
+ continue;
+ }
+
+ file->Offset = offset;
+ offset += file->Size;
+ }
+
+ if (buffer_size < offset)
+ {
+ buffer_size = offset;
+ buffer = realloc(buffer, buffer_size);
+ }
+
+ void *ptr = buffer;
+ WriteAndSeek(&ptr, HAMCORE_HEADER_DATA, HAMCORE_HEADER_SIZE);
+ uint32_t tmp = BigEndian32((uint32_t)num);
+ WriteAndSeek(&ptr, &tmp, sizeof(tmp));
+
+ for (size_t i = 0; i < num; ++i)
+ {
+ const HAMCORE_FILE *file = &compressed_files[i].File;
+ if (file->Size == 0)
+ {
+ continue;
+ }
+
+ const size_t path_length = strlen(file->Path);
+ tmp = BigEndian32((uint32_t)path_length + 1);
+ WriteAndSeek(&ptr, &tmp, sizeof(tmp));
+ WriteAndSeek(&ptr, file->Path, path_length);
+ free(file->Path);
+
+ tmp = BigEndian32((uint32_t)file->OriginalSize);
+ WriteAndSeek(&ptr, &tmp, sizeof(tmp));
+
+ tmp = BigEndian32((uint32_t)file->Size);
+ WriteAndSeek(&ptr, &tmp, sizeof(tmp));
+
+ tmp = BigEndian32((uint32_t)file->Offset);
+ WriteAndSeek(&ptr, &tmp, sizeof(tmp));
+ }
+
+ for (size_t i = 0; i < num; ++i)
+ {
+ COMPRESSED_FILE *compressed_file = &compressed_files[i];
+ WriteAndSeek(&ptr, compressed_file->Data, compressed_file->File.Size);
+ free(compressed_file->Data);
+ }
+
+ free(compressed_files);
+
+ bool ok = false;
+
+ FILE *handle = FileOpen(dst_path, true);
+ if (!handle)
+ {
+ fprintf(stderr, "HamcoreBuild(): Failed to open \"%s\"!\n", dst_path);
+ goto FINAL;
+ }
+
+ if (!FileWrite(handle, buffer, buffer_size))
+ {
+ fprintf(stderr, "HamcoreBuild(): Failed to write \"%s\"!\n", dst_path);
+ goto FINAL;
+ }
+
+ ok = true;
+FINAL:
+ FileClose(handle);
+ free(buffer);
+ return ok;
+}
diff --git a/Hamcore.h b/Hamcore.h
index 8a2e248..7db79e9 100644
--- a/Hamcore.h
+++ b/Hamcore.h
@@ -34,4 +34,6 @@ void HamcoreClose(HAMCORE *hamcore);
const HAMCORE_FILE *HamcoreFind(const HAMCORE *hamcore, const char *path);
bool HamcoreRead(HAMCORE *hamcore, void *dst, const HAMCORE_FILE *file);
+bool HamcoreBuild(const char *dst_path, const char *base_path, const char **src_paths, const size_t num);
+
#endif
diff --git a/Memory.c b/Memory.c
index b7ef7fc..661d729 100644
--- a/Memory.c
+++ b/Memory.c
@@ -1,5 +1,7 @@
#include "Memory.h"
+#include <string.h>
+
size_t CompressionBufferSize(const size_t original_size) { return original_size * 2 + 256; }
uint32_t Swap32(const uint32_t value)
@@ -11,3 +13,14 @@ uint32_t Swap32(const uint32_t value)
((uint8_t *)&swapped)[3] = ((uint8_t *)&value)[0];
return swapped;
}
+
+void WriteAndSeek(void **dst, const void *src, const size_t size)
+{
+ if (!dst || !*dst)
+ {
+ return;
+ }
+
+ memcpy(*dst, src, size);
+ *dst += size;
+}
diff --git a/Memory.h b/Memory.h
index afb7655..f84e67c 100644
--- a/Memory.h
+++ b/Memory.h
@@ -14,4 +14,6 @@ size_t CompressionBufferSize(const size_t original_size);
uint32_t Swap32(const uint32_t value);
+void WriteAndSeek(void **dst, const void *src, const size_t size);
+
#endif