16 #include <sys/types.h>
26 void Print(
const char* fmt, ...);
31 #define CHECK_ERR(err, msg) { \
33 fprintf(stderr, "%s error: %d\n", msg, err); \
58 int f = _open(datafile, _O_RDWR|_O_CREAT|_O_BINARY, _S_IREAD|_S_IWRITE);
75 _lseek(f, 0, SEEK_SET);
84 if (buf && directory && directory[index].size_comp) {
85 _lseek(f,
sizeof(
DataHeader) + directory[index].offset, SEEK_SET);
86 _write(f, buf, directory[index].size_comp);
101 return full_blocks + part_blocks;
107 if (result == 0) result = 1;
113 if (index >= 0 && index < (
int) header.
nfiles && directory)
114 return Blocks(directory[index].size_comp);
126 if (header.
nfiles == 0)
return;
130 DWORD max_usage = dir_usage;
132 for (i = 0; i < header.
nfiles; i++) {
134 if (last_block > max_usage)
135 max_usage = last_block;
139 block_map =
new(__FILE__,__LINE__) DWORD[nblocks];
146 ZeroMemory(block_map, nblocks*
sizeof(DWORD));
152 block_map[first_block+j] = 1;
154 for (i = 0; i < header.
nfiles; i++) {
159 block_map[first_block+j] = i+2;
168 if ((
int) (nblocks)-need > 0) {
172 for (start = 0; start < nblocks-need; start++) {
173 for (i = 0; block_map[start+i] == 0 && i < need; i++);
194 strncpy_s(datafile, name,
NAMELEN-1);
197 fopen_s(&f, datafile,
"rb");
202 Print(
"ERROR: datafile '%s' invalid version '%d'\n",
205 ZeroMemory(&header,
sizeof(header));
210 DWORD dirsize = header.
nfiles + 64;
212 dirbuf =
new(__FILE__,__LINE__) BYTE[len];
213 directory =
new(__FILE__,__LINE__)
DataEntry[dirsize];
215 if (!dirbuf || !directory) {
220 ZeroMemory(directory,
sizeof(
DataEntry) * dirsize);
225 int err = uncompress((BYTE*) directory, &len,
226 #pragma warning(suppress: 6029)
229 ZeroMemory(directory,
sizeof(
DataEntry) * dirsize);
238 Print(
"Creating Archive '%s'...\n", datafile);
259 if (req_name && *req_name && directory) {
261 int len = strlen(req_name);
263 ZeroMemory(path,
sizeof(path));
265 for (
int c = 0; c < len; c++) {
266 if (req_name[c] ==
'\\')
269 path[c] = req_name[c];
272 for (DWORD i = 0; i < header.
nfiles; i++) {
273 if (!_stricmp(directory[i].name, path))
285 if (directory && i >= 0 && i < (
int) header.
nfiles) {
286 char* name = directory[i].
name;
289 fopen_s(&f, name,
"rb");
292 fseek(f, 0, SEEK_END);
293 DWORD len = ftell(f);
294 fseek(f, 0, SEEK_SET);
296 BYTE* buf =
new(__FILE__,__LINE__) BYTE[len];
303 fread(buf, len, 1, f);
308 directory[i].
size_comp = (int) (len * 1.1);
309 BYTE* cbuf =
new(__FILE__,__LINE__) BYTE[directory[i].size_comp];
315 err = compress(cbuf, &directory[i].size_comp, buf, len);
334 if (directory && i >= 0 && i < (
int) header.
nfiles) {
336 fopen_s(&f, datafile,
"rb");
340 BYTE* cbuf =
new(__FILE__,__LINE__) BYTE[clen];
347 fseek(f,
sizeof(
DataHeader) + directory[i].offset, SEEK_SET);
348 fread(cbuf, clen, 1, f);
352 if (null_terminate) {
353 buf =
new(__FILE__,__LINE__) BYTE[len+1];
354 if (buf) buf[len] = 0;
358 buf =
new(__FILE__,__LINE__) BYTE[len];
366 err = uncompress(buf, &len, cbuf, clen);
388 DWORD len = strlen(name);
390 ZeroMemory(path,
sizeof(path));
392 for (DWORD c = 0; c < len; c++) {
399 int dirsize = header.
nfiles + 64;
401 if (directory && dirsize) {
402 for (
int i = 0; i < dirsize; i++) {
403 if (directory[i].size_orig == 0) {
404 ZeroMemory(directory[i].name,
NAMELEN);
405 strncpy_s(directory[i].name, path,
NAMELEN);
416 if (directory && dirsize) {
417 ZeroMemory(dir, (dirsize + 64) *
sizeof(
DataEntry));
418 CopyMemory(dir, directory, dirsize *
sizeof(
DataEntry));
423 header.
nfiles = dirsize + 64;
426 ZeroMemory(directory[dirsize].name,
NAMELEN);
427 strncpy_s(directory[dirsize].name, path,
NAMELEN);
441 if (directory && index >= 0 && index < (
int) header.
nfiles)
442 ZeroMemory(&directory[index],
sizeof(
DataEntry));
449 DWORD old_blocks = 0, old_offset = 0, new_blocks = 0;
450 DWORD old_dir_blocks = 0, old_dir_offset = 0, new_dir_blocks = 0;
461 if (index >= (
int) header.
nfiles) {
468 if (new_dir_blocks > old_dir_blocks) {
475 old_offset = directory[index].
offset;
488 Print(
"ERROR: Could not compress %d:%s\n", index, directory[index].name);
496 if (new_blocks > old_blocks) {
519 if (!directory || index < 0 || index >= (
int) header.
nfiles) {
520 Print(
"Could not extract '%s', not found\n", name);
528 fopen_s(&f, directory[index].name,
"wb");
530 fwrite(buf, directory[index].size_orig, 1, f);
534 Print(
"Could not extract '%s', could not open file for writing\n", name);
547 if (!directory || index < 0 || index >= (
int) header.
nfiles) {
548 Print(
"Could not remove '%s', not found\n", name);
565 printf(
"DATAFILE: %s\n", datafile);
566 printf(
"Files: %d\n", header.
nfiles);
569 if (directory && header.
nfiles) {
570 printf(
"Index Orig Size Comp Size Ratio Name\n");
571 printf(
"----- --------- --------- ----- ----------------\n");
573 for (DWORD i = 0; i < header.
nfiles; i++) {
583 int total_ratio = (int) (100.0 * (
double) total_comp / (double) total_orig);
585 printf(
"----- --------- --------- -----\n");
586 printf(
"TOTAL %9d %9d %2d%%\n\n", total_orig, total_comp, total_ratio);