mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-22 09:29:52 +03:00
Merge pull request #1277 from davidebeatrici/hamcorebuilder-revamp
New hamcorebuilder implementation, independent from Cedar and Mayaqua
This commit is contained in:
commit
25e2854725
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
|||||||
[submodule "src/Mayaqua/3rdparty/cpu_features"]
|
[submodule "src/Mayaqua/3rdparty/cpu_features"]
|
||||||
path = src/Mayaqua/3rdparty/cpu_features
|
path = src/Mayaqua/3rdparty/cpu_features
|
||||||
url = https://github.com/google/cpu_features.git
|
url = https://github.com/google/cpu_features.git
|
||||||
|
[submodule "3rdparty/tinydir"]
|
||||||
|
path = 3rdparty/tinydir
|
||||||
|
url = https://github.com/cxong/tinydir.git
|
||||||
|
1
3rdparty/tinydir
vendored
Submodule
1
3rdparty/tinydir
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit ec6bff2043eaac3ad25423705e63a781762a0dfd
|
@ -144,7 +144,7 @@ add_subdirectory(vpntest)
|
|||||||
# hamcore.se2 archive file
|
# hamcore.se2 archive file
|
||||||
add_custom_target(hamcore-archive-build
|
add_custom_target(hamcore-archive-build
|
||||||
ALL
|
ALL
|
||||||
COMMAND hamcorebuilder "${TOP_DIRECTORY}/src/bin/hamcore/" "${BUILD_DIRECTORY}/hamcore.se2"
|
COMMAND hamcorebuilder "${BUILD_DIRECTORY}/hamcore.se2" "${TOP_DIRECTORY}/src/bin/hamcore"
|
||||||
DEPENDS hamcorebuilder
|
DEPENDS hamcorebuilder
|
||||||
COMMENT "Building hamcore.se2 archive file..."
|
COMMENT "Building hamcore.se2 archive file..."
|
||||||
VERBATIM
|
VERBATIM
|
||||||
|
@ -64,7 +64,9 @@
|
|||||||
|
|
||||||
#define GC_UI_APPID_CM L"SoftEther.SoftEther VPN Client Developer Edition"
|
#define GC_UI_APPID_CM L"SoftEther.SoftEther VPN Client Developer Edition"
|
||||||
|
|
||||||
|
//// Hamcore
|
||||||
|
|
||||||
|
#define HAMCORE_HEADER_DATA "HamCore"
|
||||||
|
#define HAMCORE_HEADER_SIZE 7
|
||||||
|
|
||||||
#endif // GLOBAL_CONST_H
|
#endif // GLOBAL_CONST_H
|
||||||
|
|
||||||
|
@ -610,110 +610,6 @@ bool GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enumeration of direction with all sub directories
|
|
||||||
TOKEN_LIST *EnumDirWithSubDirs(char *dirname)
|
|
||||||
{
|
|
||||||
TOKEN_LIST *ret;
|
|
||||||
UNI_TOKEN_LIST *ret2;
|
|
||||||
wchar_t tmp[MAX_SIZE];
|
|
||||||
// Validate arguments
|
|
||||||
if (dirname == NULL)
|
|
||||||
{
|
|
||||||
dirname = "./";
|
|
||||||
}
|
|
||||||
|
|
||||||
StrToUni(tmp, sizeof(tmp), dirname);
|
|
||||||
|
|
||||||
ret2 = EnumDirWithSubDirsW(tmp);
|
|
||||||
|
|
||||||
ret = UniTokenListToTokenList(ret2);
|
|
||||||
|
|
||||||
UniFreeToken(ret2);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
UNI_TOKEN_LIST *EnumDirWithSubDirsW(wchar_t *dirname)
|
|
||||||
{
|
|
||||||
ENUM_DIR_WITH_SUB_DATA d;
|
|
||||||
UNI_TOKEN_LIST *ret;
|
|
||||||
UINT i;
|
|
||||||
// Validate arguments
|
|
||||||
if (dirname == NULL)
|
|
||||||
{
|
|
||||||
dirname = L"./";
|
|
||||||
}
|
|
||||||
|
|
||||||
Zero(&d, sizeof(d));
|
|
||||||
|
|
||||||
d.FileList = NewListFast(NULL);
|
|
||||||
|
|
||||||
EnumDirWithSubDirsMain(&d, dirname);
|
|
||||||
|
|
||||||
ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
|
|
||||||
|
|
||||||
ret->NumTokens = LIST_NUM(d.FileList);
|
|
||||||
ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);
|
|
||||||
|
|
||||||
for (i = 0;i < ret->NumTokens;i++)
|
|
||||||
{
|
|
||||||
wchar_t *s = LIST_DATA(d.FileList, i);
|
|
||||||
|
|
||||||
ret->Token[i] = UniCopyStr(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeStrList(d.FileList);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
void EnumDirWithSubDirsMain(ENUM_DIR_WITH_SUB_DATA *d, wchar_t *dirname)
|
|
||||||
{
|
|
||||||
DIRLIST *dir;
|
|
||||||
UINT i;
|
|
||||||
// Validate arguments
|
|
||||||
if (d == NULL || dirname == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dir = EnumDirExW(dirname, NULL);
|
|
||||||
if (dir == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Files
|
|
||||||
for (i = 0;i < dir->NumFiles;i++)
|
|
||||||
{
|
|
||||||
DIRENT *e = dir->File[i];
|
|
||||||
|
|
||||||
if (e->Folder == false)
|
|
||||||
{
|
|
||||||
wchar_t tmp[MAX_SIZE];
|
|
||||||
|
|
||||||
ConbinePathW(tmp, sizeof(tmp), dirname, e->FileNameW);
|
|
||||||
|
|
||||||
Add(d->FileList, CopyUniStr(tmp));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sub directories
|
|
||||||
for (i = 0;i < dir->NumFiles;i++)
|
|
||||||
{
|
|
||||||
DIRENT *e = dir->File[i];
|
|
||||||
|
|
||||||
if (e->Folder)
|
|
||||||
{
|
|
||||||
wchar_t tmp[MAX_SIZE];
|
|
||||||
|
|
||||||
ConbinePathW(tmp, sizeof(tmp), dirname, e->FileNameW);
|
|
||||||
|
|
||||||
EnumDirWithSubDirsMain(d, tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeDir(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enumeration of directory
|
// Enumeration of directory
|
||||||
DIRLIST *EnumDirEx(char *dirname, COMPARE *compare)
|
DIRLIST *EnumDirEx(char *dirname, COMPARE *compare)
|
||||||
{
|
{
|
||||||
@ -1079,161 +975,6 @@ void FreeHamcore()
|
|||||||
hamcore = NULL;
|
hamcore = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a Hamcore file
|
|
||||||
void BuildHamcore(char *dst_filename, char *src_dir, bool unix_only)
|
|
||||||
{
|
|
||||||
char exe_dir[MAX_SIZE];
|
|
||||||
bool ok = true;
|
|
||||||
LIST *o;
|
|
||||||
UINT i;
|
|
||||||
TOKEN_LIST *src_file_list;
|
|
||||||
|
|
||||||
GetExeDir(exe_dir, sizeof(exe_dir));
|
|
||||||
|
|
||||||
src_file_list = EnumDirWithSubDirs(src_dir);
|
|
||||||
|
|
||||||
o = NewListFast(CompareHamcore);
|
|
||||||
|
|
||||||
for (i = 0;i < src_file_list->NumTokens;i++)
|
|
||||||
{
|
|
||||||
char rpath[MAX_SIZE];
|
|
||||||
BUF *b;
|
|
||||||
char s[MAX_SIZE];
|
|
||||||
|
|
||||||
StrCpy(s, sizeof(s), src_file_list->Token[i]);
|
|
||||||
Trim(s);
|
|
||||||
|
|
||||||
if (GetRelativePath(rpath, sizeof(rpath), s, src_dir) == false)
|
|
||||||
{
|
|
||||||
// Unknown error !
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
ReplaceStr(rpath, sizeof(rpath), rpath, "/", "\\");
|
|
||||||
|
|
||||||
if (unix_only)
|
|
||||||
{
|
|
||||||
// Exclude non-UNIX files
|
|
||||||
if (EndWith(s, ".exe") ||
|
|
||||||
EndWith(s, ".dll") ||
|
|
||||||
EndWith(s, ".sys") ||
|
|
||||||
EndWith(s, ".inf") ||
|
|
||||||
EndWith(s, ".cat") ||
|
|
||||||
EndWith(s, ".wav"))
|
|
||||||
{
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (InStr(rpath, "\\node_modules\\"))
|
|
||||||
{
|
|
||||||
// Exclude node_modules in the hamcore\webroot
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ok)
|
|
||||||
{
|
|
||||||
b = ReadDump(s);
|
|
||||||
if (b == NULL)
|
|
||||||
{
|
|
||||||
Print("Failed to open '%s'.\n", s);
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HC *c = ZeroMalloc(sizeof(HC));
|
|
||||||
UINT tmp_size;
|
|
||||||
void *tmp;
|
|
||||||
c->FileName = CopyStr(rpath);
|
|
||||||
c->Size = b->Size;
|
|
||||||
tmp_size = CalcCompress(c->Size);
|
|
||||||
tmp = Malloc(tmp_size);
|
|
||||||
c->SizeCompressed = Compress(tmp, tmp_size, b->Buf, b->Size);
|
|
||||||
c->Buffer = tmp;
|
|
||||||
Insert(o, c);
|
|
||||||
Print("%s: %u -> %u\n", s, c->Size, c->SizeCompressed);
|
|
||||||
FreeBuf(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ok)
|
|
||||||
{
|
|
||||||
// Calculate the offset of the buffer for each file
|
|
||||||
UINT i, z;
|
|
||||||
char tmp[MAX_SIZE];
|
|
||||||
BUF *b;
|
|
||||||
z = 0;
|
|
||||||
z += HAMCORE_HEADER_SIZE;
|
|
||||||
// The number of files
|
|
||||||
z += sizeof(UINT);
|
|
||||||
// For file table first
|
|
||||||
for (i = 0;i < LIST_NUM(o);i++)
|
|
||||||
{
|
|
||||||
HC *c = LIST_DATA(o, i);
|
|
||||||
// File name
|
|
||||||
z += StrLen(c->FileName) + sizeof(UINT);
|
|
||||||
// File size
|
|
||||||
z += sizeof(UINT);
|
|
||||||
z += sizeof(UINT);
|
|
||||||
// Offset data
|
|
||||||
z += sizeof(UINT);
|
|
||||||
}
|
|
||||||
// File body
|
|
||||||
for (i = 0;i < LIST_NUM(o);i++)
|
|
||||||
{
|
|
||||||
HC *c = LIST_DATA(o, i);
|
|
||||||
// Buffer body
|
|
||||||
c->Offset = z;
|
|
||||||
printf("%s: offset: %u\n", c->FileName, c->Offset);
|
|
||||||
z += c->SizeCompressed;
|
|
||||||
}
|
|
||||||
// Writing
|
|
||||||
b = NewBuf();
|
|
||||||
// Header
|
|
||||||
WriteBuf(b, HAMCORE_HEADER_DATA, HAMCORE_HEADER_SIZE);
|
|
||||||
WriteBufInt(b, LIST_NUM(o));
|
|
||||||
for (i = 0;i < LIST_NUM(o);i++)
|
|
||||||
{
|
|
||||||
HC *c = LIST_DATA(o, i);
|
|
||||||
// File name
|
|
||||||
WriteBufStr(b, c->FileName);
|
|
||||||
// File size
|
|
||||||
WriteBufInt(b, c->Size);
|
|
||||||
WriteBufInt(b, c->SizeCompressed);
|
|
||||||
// Offset
|
|
||||||
WriteBufInt(b, c->Offset);
|
|
||||||
}
|
|
||||||
// Body
|
|
||||||
for (i = 0;i < LIST_NUM(o);i++)
|
|
||||||
{
|
|
||||||
HC *c = LIST_DATA(o, i);
|
|
||||||
WriteBuf(b, c->Buffer, c->SizeCompressed);
|
|
||||||
}
|
|
||||||
// Writing
|
|
||||||
StrCpy(tmp, sizeof(tmp), dst_filename);
|
|
||||||
Print("Writing %s...\n", tmp);
|
|
||||||
FileDelete(tmp);
|
|
||||||
DumpBuf(b, tmp);
|
|
||||||
FreeBuf(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0;i < LIST_NUM(o);i++)
|
|
||||||
{
|
|
||||||
HC *c = LIST_DATA(o, i);
|
|
||||||
Free(c->Buffer);
|
|
||||||
Free(c->FileName);
|
|
||||||
Free(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReleaseList(o);
|
|
||||||
|
|
||||||
FreeToken(src_file_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comparison of the HCs
|
// Comparison of the HCs
|
||||||
int CompareHamcore(void *p1, void *p2)
|
int CompareHamcore(void *p1, void *p2)
|
||||||
{
|
{
|
||||||
@ -1798,67 +1539,6 @@ UNI_TOKEN_LIST *ParseSplitedPathW(wchar_t *path)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the relative path
|
|
||||||
bool GetRelativePathW(wchar_t *dst, UINT size, wchar_t *fullpath, wchar_t *basepath)
|
|
||||||
{
|
|
||||||
wchar_t fullpath2[MAX_SIZE];
|
|
||||||
wchar_t basepath2[MAX_SIZE];
|
|
||||||
// Validate arguments
|
|
||||||
if (dst == NULL || fullpath == NULL || basepath == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ClearUniStr(dst, size);
|
|
||||||
|
|
||||||
NormalizePathW(fullpath2, sizeof(fullpath2), fullpath);
|
|
||||||
NormalizePathW(basepath2, sizeof(basepath2), basepath);
|
|
||||||
|
|
||||||
#ifdef OS_WIN32
|
|
||||||
UniStrCat(basepath2, sizeof(basepath2), L"\\");
|
|
||||||
#else // OS_WIN32
|
|
||||||
UniStrCat(basepath2, sizeof(basepath2), L"/");
|
|
||||||
#endif // OS_WIN32
|
|
||||||
|
|
||||||
if (UniStrLen(fullpath2) <= UniStrLen(basepath2))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UniStartWith(fullpath2, basepath2) == false)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UniStrCpy(dst, size, fullpath2 + UniStrLen(basepath2));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool GetRelativePath(char *dst, UINT size, char *fullpath, char *basepath)
|
|
||||||
{
|
|
||||||
wchar_t dst_w[MAX_SIZE];
|
|
||||||
wchar_t fullpath_w[MAX_SIZE];
|
|
||||||
wchar_t basepath_w[MAX_SIZE];
|
|
||||||
bool ret;
|
|
||||||
// Validate arguments
|
|
||||||
if (dst == NULL || fullpath == NULL || basepath == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
StrToUni(fullpath_w, sizeof(fullpath_w), fullpath);
|
|
||||||
StrToUni(basepath_w, sizeof(basepath_w), basepath);
|
|
||||||
|
|
||||||
ret = GetRelativePathW(dst_w, sizeof(dst_w), fullpath_w, basepath_w);
|
|
||||||
if (ret == false)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UniToStr(dst, size, dst_w);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalize the file path
|
// Normalize the file path
|
||||||
void NormalizePathW(wchar_t *dst, UINT size, wchar_t *src)
|
void NormalizePathW(wchar_t *dst, UINT size, wchar_t *src)
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
#define HAMCORE_FILE_NAME "hamcore.se2"
|
#define HAMCORE_FILE_NAME "hamcore.se2"
|
||||||
#define HAMCORE_FILE_NAME_2 "_hamcore.se2"
|
#define HAMCORE_FILE_NAME_2 "_hamcore.se2"
|
||||||
#define HAMCORE_TEXT_NAME "hamcore.txt"
|
#define HAMCORE_TEXT_NAME "hamcore.txt"
|
||||||
#define HAMCORE_HEADER_DATA "HamCore"
|
|
||||||
#define HAMCORE_HEADER_SIZE 7
|
|
||||||
#define HAMCORE_CACHE_EXPIRES (5 * 60 * 1000)
|
#define HAMCORE_CACHE_EXPIRES (5 * 60 * 1000)
|
||||||
|
|
||||||
// IO structure
|
// IO structure
|
||||||
@ -148,11 +146,6 @@ struct ZIP_PACKER
|
|||||||
ZIP_FILE *CurrentFile;
|
ZIP_FILE *CurrentFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ENUM_DIR_WITH_SUB_DATA
|
|
||||||
{
|
|
||||||
LIST *FileList;
|
|
||||||
};
|
|
||||||
|
|
||||||
void InitCrc32();
|
void InitCrc32();
|
||||||
UINT Crc32(void *buf, UINT pos, UINT len);
|
UINT Crc32(void *buf, UINT pos, UINT len);
|
||||||
UINT Crc32First(void *buf, UINT pos, UINT len);
|
UINT Crc32First(void *buf, UINT pos, UINT len);
|
||||||
@ -204,8 +197,6 @@ bool FileRenameInnerW(wchar_t *old_name, wchar_t *new_name);
|
|||||||
bool FileRenameW(wchar_t *old_name, wchar_t *new_name);
|
bool FileRenameW(wchar_t *old_name, wchar_t *new_name);
|
||||||
void NormalizePath(char *dst, UINT size, char *src);
|
void NormalizePath(char *dst, UINT size, char *src);
|
||||||
void NormalizePathW(wchar_t *dst, UINT size, wchar_t *src);
|
void NormalizePathW(wchar_t *dst, UINT size, wchar_t *src);
|
||||||
bool GetRelativePathW(wchar_t *dst, UINT size, wchar_t *fullpath, wchar_t *basepath);
|
|
||||||
bool GetRelativePath(char *dst, UINT size, char *fullpath, char *basepath);
|
|
||||||
UNI_TOKEN_LIST *ParseSplitedPathW(wchar_t *path);
|
UNI_TOKEN_LIST *ParseSplitedPathW(wchar_t *path);
|
||||||
char *GetCurrentPathEnvStr();
|
char *GetCurrentPathEnvStr();
|
||||||
bool IsFileExistsInnerW(wchar_t *name);
|
bool IsFileExistsInnerW(wchar_t *name);
|
||||||
@ -234,7 +225,6 @@ void GetDbDir(char *name, UINT size);
|
|||||||
void GetDbDirW(wchar_t *name, UINT size);
|
void GetDbDirW(wchar_t *name, UINT size);
|
||||||
void GetPidDir(char *name, UINT size);
|
void GetPidDir(char *name, UINT size);
|
||||||
void GetPidDirW(wchar_t *name, UINT size);
|
void GetPidDirW(wchar_t *name, UINT size);
|
||||||
void BuildHamcore(char *dst_filename, char *src_dir, bool unix_only);
|
|
||||||
int CompareHamcore(void *p1, void *p2);
|
int CompareHamcore(void *p1, void *p2);
|
||||||
void InitHamcore();
|
void InitHamcore();
|
||||||
void FreeHamcore();
|
void FreeHamcore();
|
||||||
@ -246,9 +236,6 @@ DIRLIST *EnumDir(char *dirname);
|
|||||||
DIRLIST *EnumDirW(wchar_t *dirname);
|
DIRLIST *EnumDirW(wchar_t *dirname);
|
||||||
DIRLIST *EnumDirEx(char *dirname, COMPARE *compare);
|
DIRLIST *EnumDirEx(char *dirname, COMPARE *compare);
|
||||||
DIRLIST *EnumDirExW(wchar_t *dirname, COMPARE *compare);
|
DIRLIST *EnumDirExW(wchar_t *dirname, COMPARE *compare);
|
||||||
UNI_TOKEN_LIST *EnumDirWithSubDirsW(wchar_t *dirname);
|
|
||||||
TOKEN_LIST *EnumDirWithSubDirs(char *dirname);
|
|
||||||
void EnumDirWithSubDirsMain(ENUM_DIR_WITH_SUB_DATA *d, wchar_t *dirname);
|
|
||||||
void FreeDir(DIRLIST *d);
|
void FreeDir(DIRLIST *d);
|
||||||
int CompareDirListByName(void *p1, void *p2);
|
int CompareDirListByName(void *p1, void *p2);
|
||||||
bool GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
|
bool GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size);
|
||||||
@ -263,6 +250,3 @@ bool IsInLines(BUF *buf, char *str, bool instr);
|
|||||||
bool IsInLinesFile(wchar_t *filename, char *str, bool instr);
|
bool IsInLinesFile(wchar_t *filename, char *str, bool instr);
|
||||||
|
|
||||||
#endif // FILEIO_H
|
#endif // FILEIO_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,12 +22,6 @@ static LOCK *iconv_lock = NULL;
|
|||||||
void *iconv_cache_wide_to_str = 0;
|
void *iconv_cache_wide_to_str = 0;
|
||||||
void *iconv_cache_str_to_wide = 0;
|
void *iconv_cache_str_to_wide = 0;
|
||||||
|
|
||||||
// Initialize the string
|
|
||||||
void ClearUniStr(wchar_t *str, UINT str_size)
|
|
||||||
{
|
|
||||||
UniStrCpy(str, str_size, L"");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Examine whether the string contains the specified character
|
// Examine whether the string contains the specified character
|
||||||
bool UniInChar(wchar_t *string, wchar_t c)
|
bool UniInChar(wchar_t *string, wchar_t c)
|
||||||
{
|
{
|
||||||
|
@ -98,7 +98,6 @@ bool UniIsSafeChar(wchar_t c);
|
|||||||
BUF *UniStrToBin(wchar_t *str);
|
BUF *UniStrToBin(wchar_t *str);
|
||||||
bool UniInStr(wchar_t *str, wchar_t *keyword);
|
bool UniInStr(wchar_t *str, wchar_t *keyword);
|
||||||
bool UniInStrEx(wchar_t *str, wchar_t *keyword, bool case_sensitive);
|
bool UniInStrEx(wchar_t *str, wchar_t *keyword, bool case_sensitive);
|
||||||
void ClearUniStr(wchar_t *str, UINT str_size);
|
|
||||||
bool UniInChar(wchar_t *string, wchar_t c);
|
bool UniInChar(wchar_t *string, wchar_t c);
|
||||||
UNI_TOKEN_LIST *UniGetLines(wchar_t *str);
|
UNI_TOKEN_LIST *UniGetLines(wchar_t *str);
|
||||||
wchar_t *UniDefaultTokenSplitChars();
|
wchar_t *UniDefaultTokenSplitChars();
|
||||||
|
@ -444,7 +444,6 @@ typedef struct ZIP_DIR_HEADER ZIP_DIR_HEADER;
|
|||||||
typedef struct ZIP_END_HEADER ZIP_END_HEADER;
|
typedef struct ZIP_END_HEADER ZIP_END_HEADER;
|
||||||
typedef struct ZIP_FILE ZIP_FILE;
|
typedef struct ZIP_FILE ZIP_FILE;
|
||||||
typedef struct ZIP_PACKER ZIP_PACKER;
|
typedef struct ZIP_PACKER ZIP_PACKER;
|
||||||
typedef struct ENUM_DIR_WITH_SUB_DATA ENUM_DIR_WITH_SUB_DATA;
|
|
||||||
|
|
||||||
// TcpIp.h
|
// TcpIp.h
|
||||||
typedef struct MAC_HEADER MAC_HEADER;
|
typedef struct MAC_HEADER MAC_HEADER;
|
||||||
|
22
src/hamcorebuilder/CMakeLists.txt
Normal file → Executable file
22
src/hamcorebuilder/CMakeLists.txt
Normal file → Executable file
@ -1,3 +1,21 @@
|
|||||||
add_executable(hamcorebuilder hamcorebuilder.c)
|
include(TestBigEndian)
|
||||||
|
|
||||||
target_link_libraries(hamcorebuilder cedar mayaqua)
|
add_executable(hamcorebuilder
|
||||||
|
main.c
|
||||||
|
FileSystem.c
|
||||||
|
FileSystem.h
|
||||||
|
)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
target_compile_definitions(hamcorebuilder PRIVATE "OS_WINDOWS")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
test_big_endian(BIG_ENDIAN)
|
||||||
|
if(BIG_ENDIAN)
|
||||||
|
target_compile_definitions(hamcorebuilder PRIVATE "BYTE_ORDER_BIG_ENDIAN")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(hamcorebuilder PRIVATE "${TOP_DIRECTORY}/3rdparty/tinydir")
|
||||||
|
|
||||||
|
find_package(ZLIB REQUIRED)
|
||||||
|
target_link_libraries(hamcorebuilder PRIVATE ZLIB::ZLIB)
|
||||||
|
220
src/hamcorebuilder/FileSystem.c
Executable file
220
src/hamcorebuilder/FileSystem.c
Executable file
@ -0,0 +1,220 @@
|
|||||||
|
#include "FileSystem.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
ENTRIES *EnumEntries(const char *path)
|
||||||
|
{
|
||||||
|
if (!path)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinydir_dir dir;
|
||||||
|
if (tinydir_open_sorted(&dir, path) == -1)
|
||||||
|
{
|
||||||
|
printf("tinydir_open_sorted() failed!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENTRIES *entries = calloc(1, sizeof(ENTRIES));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < dir.n_files; ++i)
|
||||||
|
{
|
||||||
|
tinydir_file file;
|
||||||
|
if (tinydir_readfile_n(&dir, &file, i) == -1)
|
||||||
|
{
|
||||||
|
printf("tinydir_readfile_n() failed at index %zu!\n", i);
|
||||||
|
FreeEntries(entries);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.is_dir)
|
||||||
|
{
|
||||||
|
if (strcmp(file.name, ".") == 0 || strcmp(file.name, "..") == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef OS_WINDOWS
|
||||||
|
if (IsWindowsExtension(file.extension))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
++entries->Num;
|
||||||
|
entries->List = realloc(entries->List, sizeof(ENTRY) * entries->Num);
|
||||||
|
|
||||||
|
ENTRY *entry = &entries->List[entries->Num - 1];
|
||||||
|
entry->IsDir = file.is_dir;
|
||||||
|
strcpy(entry->Path, file.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
tinydir_close(&dir);
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENTRIES *EnumEntriesRecursively(const char *path, const bool files_only)
|
||||||
|
{
|
||||||
|
if (!path)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENTRIES *tmp = EnumEntries(path);
|
||||||
|
if (!tmp)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENTRIES *entries = calloc(1, sizeof(ENTRIES));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < tmp->Num; ++i)
|
||||||
|
{
|
||||||
|
ENTRY *entry = &tmp->List[i];
|
||||||
|
if (!files_only || !entry->IsDir)
|
||||||
|
{
|
||||||
|
++entries->Num;
|
||||||
|
entries->List = realloc(entries->List, sizeof(ENTRY) * entries->Num);
|
||||||
|
memcpy(&entries->List[entries->Num - 1], entry, sizeof(ENTRY));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!entry->IsDir)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ENTRIES *tmp_2 = EnumEntries(entry->Path);
|
||||||
|
if (!tmp_2)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t offset = tmp->Num;
|
||||||
|
|
||||||
|
tmp->Num += tmp_2->Num;
|
||||||
|
tmp->List = realloc(tmp->List, sizeof(ENTRY) * tmp->Num);
|
||||||
|
|
||||||
|
memcpy(&tmp->List[offset], tmp_2->List, sizeof(ENTRY) * tmp_2->Num);
|
||||||
|
|
||||||
|
FreeEntries(tmp_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeEntries(tmp);
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeEntries(ENTRIES *entries)
|
||||||
|
{
|
||||||
|
if (!entries)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries->List)
|
||||||
|
{
|
||||||
|
free(entries->List);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *FileOpen(const char *path, const bool write)
|
||||||
|
{
|
||||||
|
if (!path)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fopen(path, write ? "wb" : "rb");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileClose(FILE *file)
|
||||||
|
{
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fclose(file) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileRead(FILE *file, void *dst, const size_t size)
|
||||||
|
{
|
||||||
|
if (!file || !dst || size == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FileSize(const char *path)
|
||||||
|
{
|
||||||
|
if (!path)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if (stat(path, &st) == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return st.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *PathRelativeToBase(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef OS_WINDOWS
|
||||||
|
bool IsWindowsExtension(const char *extension)
|
||||||
|
{
|
||||||
|
if (!extension)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(extension, "cat") == 0 ||
|
||||||
|
strcmp(extension, "dll") == 0 ||
|
||||||
|
strcmp(extension, "exe") == 0 ||
|
||||||
|
strcmp(extension, "inf") == 0 ||
|
||||||
|
strcmp(extension, "sys") == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
39
src/hamcorebuilder/FileSystem.h
Executable file
39
src/hamcorebuilder/FileSystem.h
Executable file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef FILESYSTEM_H
|
||||||
|
#define FILESYSTEM_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <tinydir.h>
|
||||||
|
|
||||||
|
#define MAX_PATH_LENGTH _TINYDIR_PATH_MAX
|
||||||
|
|
||||||
|
typedef struct ENTRY
|
||||||
|
{
|
||||||
|
bool IsDir;
|
||||||
|
char Path[MAX_PATH_LENGTH];
|
||||||
|
} ENTRY;
|
||||||
|
|
||||||
|
typedef struct ENTRIES
|
||||||
|
{
|
||||||
|
size_t Num;
|
||||||
|
ENTRY *List;
|
||||||
|
} ENTRIES;
|
||||||
|
|
||||||
|
ENTRIES *EnumEntries(const char *path);
|
||||||
|
ENTRIES *EnumEntriesRecursively(const char *path, const bool files_only);
|
||||||
|
void FreeEntries(ENTRIES *entries);
|
||||||
|
|
||||||
|
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);
|
||||||
|
size_t FileSize(const char *path);
|
||||||
|
|
||||||
|
char *PathRelativeToBase(char *full, const char *base);
|
||||||
|
|
||||||
|
#ifndef OS_WINDOWS
|
||||||
|
bool IsWindowsExtension(const char *extension);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -1,75 +0,0 @@
|
|||||||
// SoftEther VPN Source Code - Developer Edition Master Branch
|
|
||||||
// Cedar Communication Module
|
|
||||||
|
|
||||||
|
|
||||||
// hamcorebuilder.c
|
|
||||||
// hamcore.se2 Build Utility
|
|
||||||
|
|
||||||
#include <GlobalConst.h>
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <winsock2.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <wincrypt.h>
|
|
||||||
#include <wininet.h>
|
|
||||||
#include <shlobj.h>
|
|
||||||
#include <commctrl.h>
|
|
||||||
#include <Dbghelp.h>
|
|
||||||
#endif // WIN32
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <wchar.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <Mayaqua/Mayaqua.h>
|
|
||||||
#include <Cedar/Cedar.h>
|
|
||||||
|
|
||||||
|
|
||||||
// main function
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
MayaquaMinimalMode();
|
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUG) // In VC++ compilers, the macro is "_DEBUG", not "DEBUG".
|
|
||||||
// If set memcheck = true, the program will be vitally slow since it will log all malloc() / realloc() / free() calls to find the cause of memory leak.
|
|
||||||
// For normal debug we set memcheck = false.
|
|
||||||
// Please set memcheck = true if you want to test the cause of memory leaks.
|
|
||||||
InitMayaqua(false, true, argc, argv);
|
|
||||||
#else
|
|
||||||
InitMayaqua(false, false, argc, argv);
|
|
||||||
#endif
|
|
||||||
InitCedar();
|
|
||||||
|
|
||||||
Print("hamcore.se2 Build Utility\n");
|
|
||||||
Print("Copyright (c) SoftEther VPN Project. All Rights Reserved.\n\n");
|
|
||||||
|
|
||||||
if (argc < 3)
|
|
||||||
{
|
|
||||||
Print("Usage: hamcorebuilder <src_dir> <dest_hamcore_filename>\n\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *src_dir = argv[1];
|
|
||||||
char *dst_filename = argv[2];
|
|
||||||
|
|
||||||
Print("Src Dir: '%s'\n", src_dir);
|
|
||||||
Print("Dest Filename: '%s'\n", dst_filename);
|
|
||||||
|
|
||||||
Print("\nProcessing...\n");
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
BuildHamcore(dst_filename, src_dir, false);
|
|
||||||
#else
|
|
||||||
BuildHamcore(dst_filename, src_dir, true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Print("\nDone.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeCedar();
|
|
||||||
FreeMayaqua();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
258
src/hamcorebuilder/main.c
Executable file
258
src/hamcorebuilder/main.c
Executable file
@ -0,0 +1,258 @@
|
|||||||
|
#include "GlobalConst.h"
|
||||||
|
|
||||||
|
#include "FileSystem.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#ifdef BYTE_ORDER_BIG_ENDIAN
|
||||||
|
# define BigEndian32
|
||||||
|
#else
|
||||||
|
# define BigEndian32 Swap32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct CompressedFile
|
||||||
|
{
|
||||||
|
char *Path;
|
||||||
|
uint8_t *Data;
|
||||||
|
size_t Size;
|
||||||
|
size_t OriginalSize;
|
||||||
|
size_t Offset;
|
||||||
|
} CompressedFile;
|
||||||
|
|
||||||
|
size_t CompressionBufferSize(const size_t original_size)
|
||||||
|
{
|
||||||
|
return original_size * 2 + 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Swap32(const uint32_t value)
|
||||||
|
{
|
||||||
|
uint32_t swapped;
|
||||||
|
((uint8_t *)&swapped)[0] = ((uint8_t *)&value)[3];
|
||||||
|
((uint8_t *)&swapped)[1] = ((uint8_t *)&value)[2];
|
||||||
|
((uint8_t *)&swapped)[2] = ((uint8_t *)&value)[1];
|
||||||
|
((uint8_t *)&swapped)[3] = ((uint8_t *)&value)[0];
|
||||||
|
return swapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteAndSeek(uint8_t **dst, const void *src, const size_t size)
|
||||||
|
{
|
||||||
|
if (!dst || !*dst)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(*dst, src, size);
|
||||||
|
*dst += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuildHamcore(const char *dst, const char *src)
|
||||||
|
{
|
||||||
|
ENTRIES *entries = EnumEntriesRecursively(src, true);
|
||||||
|
if (!entries)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *buffer = NULL;
|
||||||
|
size_t buffer_size = 0;
|
||||||
|
const size_t num = entries->Num;
|
||||||
|
CompressedFile *files = calloc(num, sizeof(CompressedFile));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num; ++i)
|
||||||
|
{
|
||||||
|
CompressedFile *file = &files[i];
|
||||||
|
char *path = entries->List[i].Path;
|
||||||
|
|
||||||
|
file->OriginalSize = FileSize(path);
|
||||||
|
if (file->OriginalSize == 0)
|
||||||
|
{
|
||||||
|
printf("Skipping \"%s\" because empty...\n", path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *handle = FileOpen(path, false);
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
printf("Failed to open \"%s\", skipping...\n", path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *content = malloc(file->OriginalSize);
|
||||||
|
if (!FileRead(handle, content, file->OriginalSize))
|
||||||
|
{
|
||||||
|
printf("FileRead() failed for \"%s\", skipping...\n", path);
|
||||||
|
free(content);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileClose(handle);
|
||||||
|
|
||||||
|
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;
|
||||||
|
const int ret = compress(buffer, (uLongf *)&file->Size, content, (uLong)file->OriginalSize);
|
||||||
|
free(content);
|
||||||
|
|
||||||
|
if (ret != Z_OK)
|
||||||
|
{
|
||||||
|
printf("Failed to compress \"%s\" with error %d, skipping...\n", path, ret);
|
||||||
|
file->Size = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *relative_path = PathRelativeToBase(path, src);
|
||||||
|
if (!relative_path)
|
||||||
|
{
|
||||||
|
printf("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);
|
||||||
|
|
||||||
|
file->Data = malloc(file->Size);
|
||||||
|
memcpy(file->Data, buffer, file->Size);
|
||||||
|
|
||||||
|
printf("\"%s\": %zu bytes -> %zu bytes\n", file->Path, file->OriginalSize, file->Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeEntries(entries);
|
||||||
|
|
||||||
|
size_t offset = HAMCORE_HEADER_SIZE;
|
||||||
|
// Number of files
|
||||||
|
offset += sizeof(uint32_t);
|
||||||
|
// File table
|
||||||
|
for (size_t i = 0; i < num; ++i)
|
||||||
|
{
|
||||||
|
CompressedFile *file = &files[i];
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
CompressedFile *file = &files[i];
|
||||||
|
if (file->Size == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
file->Offset = offset;
|
||||||
|
printf("Offset for \"%s\": %zu\n", file->Path, file->Offset);
|
||||||
|
offset += file->Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer_size < offset)
|
||||||
|
{
|
||||||
|
buffer_size = offset;
|
||||||
|
buffer = realloc(buffer, buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *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)
|
||||||
|
{
|
||||||
|
CompressedFile *file = &files[i];
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
CompressedFile *file = &files[i];
|
||||||
|
WriteAndSeek(&ptr, file->Data, file->Size);
|
||||||
|
free(file->Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(files);
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
FILE *handle = FileOpen(dst, true);
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
printf("FileOpen() failed!\n");
|
||||||
|
goto FINAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nWriting to \"%s\"...\n", dst);
|
||||||
|
|
||||||
|
if (!FileWrite(handle, buffer, buffer_size))
|
||||||
|
{
|
||||||
|
printf("FileWrite() failed!\n");
|
||||||
|
goto FINAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = true;
|
||||||
|
FINAL:
|
||||||
|
FileClose(handle);
|
||||||
|
free(buffer);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(const int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
printf("hamcore.se2 builder\n\n");
|
||||||
|
|
||||||
|
if (argc < 3)
|
||||||
|
{
|
||||||
|
printf("Usage: hamcorebuilder <dest_file> <src_dir>\n\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *dst = argv[1];
|
||||||
|
const char *src = argv[2];
|
||||||
|
|
||||||
|
printf("Destination: \"%s\"\n", dst);
|
||||||
|
printf("Source: \"%s\"\n\n", src);
|
||||||
|
|
||||||
|
if (!BuildHamcore(dst, src))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nDone!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user