2022-05-19 01:51:26 -07:00
|
|
|
// NOTE: For unknown reason functions in this module use __stdcall instead
|
|
|
|
// of regular __usercall.
|
|
|
|
|
|
|
|
#include "file_utils.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2022-06-18 00:58:15 -07:00
|
|
|
#include <string.h>
|
2022-05-19 01:51:26 -07:00
|
|
|
#include <zlib.h>
|
|
|
|
|
2022-07-25 08:37:22 -07:00
|
|
|
#include <vector>
|
2022-05-19 01:51:26 -07:00
|
|
|
|
2022-09-15 02:38:23 -07:00
|
|
|
#include "platform_compat.h"
|
|
|
|
|
2022-09-23 05:43:44 -07:00
|
|
|
namespace fallout {
|
|
|
|
|
2022-07-27 00:11:33 -07:00
|
|
|
static void fileCopy(const char* existingFilePath, const char* newFilePath);
|
|
|
|
|
2022-05-19 01:51:26 -07:00
|
|
|
// 0x452740
|
|
|
|
int fileCopyDecompressed(const char* existingFilePath, const char* newFilePath)
|
|
|
|
{
|
2022-06-18 00:58:15 -07:00
|
|
|
FILE* stream = compat_fopen(existingFilePath, "rb");
|
2022-05-19 01:51:26 -07:00
|
|
|
if (stream == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int magic[2];
|
|
|
|
magic[0] = fgetc(stream);
|
|
|
|
magic[1] = fgetc(stream);
|
|
|
|
fclose(stream);
|
|
|
|
|
|
|
|
if (magic[0] == 0x1F && magic[1] == 0x8B) {
|
2022-06-18 00:58:15 -07:00
|
|
|
gzFile inStream = compat_gzopen(existingFilePath, "rb");
|
|
|
|
FILE* outStream = compat_fopen(newFilePath, "wb");
|
2022-05-19 01:51:26 -07:00
|
|
|
|
|
|
|
if (inStream != NULL && outStream != NULL) {
|
|
|
|
for (;;) {
|
|
|
|
int ch = gzgetc(inStream);
|
|
|
|
if (ch == -1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
fputc(ch, outStream);
|
|
|
|
}
|
|
|
|
|
|
|
|
gzclose(inStream);
|
|
|
|
fclose(outStream);
|
|
|
|
} else {
|
|
|
|
if (inStream != NULL) {
|
|
|
|
gzclose(inStream);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (outStream != NULL) {
|
|
|
|
fclose(outStream);
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
2022-07-27 00:11:33 -07:00
|
|
|
fileCopy(existingFilePath, newFilePath);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0x452804
|
|
|
|
int fileCopyCompressed(const char* existingFilePath, const char* newFilePath)
|
|
|
|
{
|
2022-06-18 00:58:15 -07:00
|
|
|
FILE* inStream = compat_fopen(existingFilePath, "rb");
|
2022-05-19 01:51:26 -07:00
|
|
|
if (inStream == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int magic[2];
|
|
|
|
magic[0] = fgetc(inStream);
|
|
|
|
magic[1] = fgetc(inStream);
|
|
|
|
rewind(inStream);
|
|
|
|
|
|
|
|
if (magic[0] == 0x1F && magic[1] == 0x8B) {
|
|
|
|
// Source file is already gzipped, there is no need to do anything
|
|
|
|
// besides copying.
|
|
|
|
fclose(inStream);
|
2022-07-27 00:11:33 -07:00
|
|
|
fileCopy(existingFilePath, newFilePath);
|
2022-05-19 01:51:26 -07:00
|
|
|
} else {
|
2022-06-18 00:58:15 -07:00
|
|
|
gzFile outStream = compat_gzopen(newFilePath, "wb");
|
2022-05-19 01:51:26 -07:00
|
|
|
if (outStream == NULL) {
|
|
|
|
fclose(inStream);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy byte-by-byte.
|
|
|
|
for (;;) {
|
|
|
|
int ch = fgetc(inStream);
|
|
|
|
if (ch == -1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
gzputc(outStream, ch);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(inStream);
|
|
|
|
gzclose(outStream);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Check, implementation looks odd.
|
|
|
|
int _gzdecompress_file(const char* existingFilePath, const char* newFilePath)
|
|
|
|
{
|
2022-06-18 00:58:15 -07:00
|
|
|
FILE* stream = compat_fopen(existingFilePath, "rb");
|
2022-05-19 01:51:26 -07:00
|
|
|
if (stream == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int magic[2];
|
|
|
|
magic[0] = fgetc(stream);
|
|
|
|
magic[1] = fgetc(stream);
|
|
|
|
fclose(stream);
|
|
|
|
|
|
|
|
// TODO: Is it broken?
|
|
|
|
if (magic[0] != 0x1F || magic[1] != 0x8B) {
|
2022-06-18 00:58:15 -07:00
|
|
|
gzFile gzstream = compat_gzopen(existingFilePath, "rb");
|
2022-05-19 01:51:26 -07:00
|
|
|
if (gzstream == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-06-18 00:58:15 -07:00
|
|
|
stream = compat_fopen(newFilePath, "wb");
|
2022-05-19 01:51:26 -07:00
|
|
|
if (stream == NULL) {
|
|
|
|
gzclose(gzstream);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
int ch = gzgetc(gzstream);
|
|
|
|
if (ch == -1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
fputc(ch, stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
gzclose(gzstream);
|
|
|
|
fclose(stream);
|
|
|
|
} else {
|
2022-07-27 00:11:33 -07:00
|
|
|
fileCopy(existingFilePath, newFilePath);
|
2022-05-19 01:51:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2022-05-28 00:38:16 -07:00
|
|
|
|
2022-07-27 00:11:33 -07:00
|
|
|
static void fileCopy(const char* existingFilePath, const char* newFilePath)
|
2022-05-28 00:38:16 -07:00
|
|
|
{
|
2023-06-01 07:10:36 -07:00
|
|
|
FILE* in = compat_fopen(existingFilePath, "rb");
|
|
|
|
FILE* out = compat_fopen(newFilePath, "wb");
|
2022-07-25 08:37:22 -07:00
|
|
|
if (in != NULL && out != NULL) {
|
|
|
|
std::vector<unsigned char> buffer(0xFFFF);
|
|
|
|
|
|
|
|
size_t bytesRead;
|
|
|
|
while ((bytesRead = fread(buffer.data(), sizeof(*buffer.data()), buffer.size(), in)) > 0) {
|
|
|
|
size_t bytesWritten;
|
|
|
|
size_t offset = 0;
|
|
|
|
while ((bytesWritten = fwrite(buffer.data() + offset, sizeof(*buffer.data()), bytesRead, out)) > 0) {
|
|
|
|
bytesRead -= bytesWritten;
|
|
|
|
offset += bytesWritten;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bytesWritten < 0) {
|
|
|
|
bytesRead = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (in != NULL) {
|
|
|
|
fclose(in);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (out != NULL) {
|
|
|
|
fclose(out);
|
|
|
|
}
|
2022-05-28 00:38:16 -07:00
|
|
|
}
|
2022-09-23 05:43:44 -07:00
|
|
|
|
|
|
|
} // namespace fallout
|