/* PowerComPress v0.9 Copyright (C) 2005 Jonas Gehring PowerComPress is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. PowerComPress is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with PowerComPress; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // C Source File // Created 26.09.2005; 18:34:41 #include #include #include #include "pcpress.h" #include "brieflz.h" #include "boolsoft.h" #include "advdialogs.h" // Header for a compressed file in a GroupFile typedef struct { unsigned long hcode; char varname[18]; char type[6]; size_t varsize; } GROUPHEADER; size_t groupcount_uncompressed; size_t groupcount_compressed; size_t filecount; size_t groupsize; size_t splitcount; char groupname[18]; char ogroupname[18]; unsigned char splitnum = 0; /* Only for testing!!! void ShowHeader(GROUPHEADER *header) { char msg[40]; // Initialize dialog AdvDlgInit(100, 58, "PowerComPress", B_ESC, B_OK, TRUE, save_int_1); // Add dialog elements sprintf(msg, "%lX", header->hcode); AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_CENTERED); sprintf(msg, "%s", header->varname); AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_CENTERED); sprintf(msg, "%ld", header->varsize); AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_CENTERED); sprintf(msg, "%s", header->type); AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_CENTERED); AdvDlgDo(); } */ // Store a 32-bit unsigned value in network order. static void put_uint32(byte *p, unsigned long val) { p[0] = octet(val >> 24); p[1] = octet(val >> 16); p[2] = octet(val >> 8); p[3] = octet(val ); } // Read a 32-bit unsigned value in network order. static unsigned long get_uint32(const byte *p) { return ((unsigned long) octet(p[0]) << 24) | ((unsigned long) octet(p[1]) << 16) | ((unsigned long) octet(p[2]) << 8) | ((unsigned long) octet(p[3]) ); } // Generate name of a splitted file and store it in 'groupfile' void GetSplitName(char *buffer, short splitnum) { //char table[10] = {'0','1','2','3','4','5' if (splitnum < 10) { if (strlen(ogroupname)-strcspn(ogroupname, append) > 6) { memset(buffer, 0, strlen(buffer)); strncpy(buffer, ogroupname, strlen(ogroupname)-1); sprintf(groupname, "%s%d", buffer, splitnum); //AdvDlgMessage("SPLIT", groupname, B_NONE); } else { sprintf(groupname, "%s%d", ogroupname, splitnum); } } } // Generates a name less than 12 chars for a GroupFile entry void GetGroupEntryName(char *buffer) { short appendpos = strcspn(buffer, append); short charcut = strlen(buffer)-12; char name[9], tbuffer[20]; if (charcut <= 0) { return; } memset(tbuffer, 0, sizeof(char)*20); memset(name, 0, sizeof(char)*9); strcpy(name, &buffer[appendpos]); strncpy(tbuffer, buffer, (appendpos-(charcut+1))); tbuffer[(appendpos-charcut)] = 160; strcat(tbuffer, name); while (strlen(buffer) > 12) { buffer[appendpos-1] = 160; strcpy(buffer + appendpos, name); buffer[strlen(buffer) - appendpos + strlen(name) + 1] = 0; appendpos--; } } // Ask to split a file BOOL AskToSplitFile(void) { if (options.AlwaysSplitVar) return TRUE; AdvDlgInit(100, 52, "PowerComPress", B_NO, B_YES, TRUE, save_int_1); // Add dialog elements AdvDlgAdd(AD_TEXT, "Warning!", NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, "The GroupFile cannot hold", NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, "all files you selected.", NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, "Split GroupFile?", NULL, 0, 0, 0, TXT_STANDARD); // Execute Dialog if (!AdvDlgDo()) { return FALSE; } else { return TRUE; } } // Ask for a name BOOL GetGroupName(char *varname, char *buffer) { char msg[40]; do { // Initialize dialog AdvDlgInit(120, 70, "PowerComPress", B_ESC, B_OK, TRUE, save_int_1); // Add dialog elements if (!isfolder) { sprintf(msg, "Add %s to", varname); } else { sprintf(msg, "Add %s%s to", varname, append); } AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_INPUT, NULL, buffer, 17, INPUT_STR, 0, 0); AdvDlgAdd(AD_NONE, NULL, NULL, 0, 0, 0, 0); AdvDlgAdd(AD_TEXT, "Options:", NULL, 0, 0, 0, TXT_STANDARD); if (!isfolder) sprintf(msg, "Delete %s", varname); else strcpy(msg, "Delete single files"); AdvDlgAdd(AD_CHECKBOX, msg, NULL, 0, 0, options.AlwaysDelVar, 0); AdvDlgAdd(AD_CHECKBOX, "Archive GroupFile", NULL, 0, 0, options.AlwaysArcVar, 0); // Execute Dialog if (!AdvDlgDo()) { return FALSE; } } while (!buffer[0]); return TRUE; } // View the contents of a GroupFile short ViewGroupEntries(char *grpname) { FILE *group; char tname[18], arrow[3], gtype[6]; char *names, *types, *sizes, *csizes; short counter = 0, splitted = 0, i; GROUPHEADER gheader; BYTE header[HEADER_SIZE]; size_t compsize; fpos_t pos; memset(&gheader, 0, sizeof(GROUPHEADER)); // Is the file a GroupFile? VarTypeToStr(DerefSym(SymFind(SYMSTR(grpname))), gtype); if (strncmp(gtype, ".pcp", 4)) { return PARENT; } // Allocate memory if ((names = malloc(sizeof(char)*255*13)) == NULL) { ExitPCP(OUTOFMEM); } if ((types = malloc(sizeof(char)*255*6)) == NULL) { free(names); ExitPCP(OUTOFMEM); } if ((sizes = malloc(sizeof(char)*255*6)) == NULL) { free(names); free(types); ExitPCP(OUTOFMEM); } if ((csizes = malloc(sizeof(char)*255*6)) == NULL) { free(names); free(types); free(sizes); ExitPCP(OUTOFMEM); } isfolder = FALSE; isgroup = TRUE; strcpy(tname, grpname); if ((group = fopen(tname, "rb")) == NULL) { free(names); free(types); free(sizes); free(csizes); return PARENT; } fgetc(group); // Read from header while ((fread(&gheader, 1, sizeof(GROUPHEADER), group)) == sizeof(GROUPHEADER)) { //ShowHeader(&gheader); if (gheader.hcode != 0x636C8F1A) { free(names); free(types); free(sizes); free(csizes); fclose(group); AdvDlgMessage("PowerComPress - Error", "Corrupted GroupFile", B_OK); return PARENT; } strcpy(&types[counter*6], gheader.type); sprintf(&sizes[counter*6], "%lu", gheader.varsize); GetGroupEntryName(gheader.varname); strcpy(&names[counter*13], gheader.varname); counter++; fgetpos(group, &pos); // The end of the file is reached! fread(arrow, 1, sizeof(char)*3, group); if (!strncmp(arrow, "-->", 3)) { fread(tname, 1, sizeof(tname), group); fclose(group); //AdvDlgMessage("PowerComPress", tname, B_OK); if ((group = fopen(tname, "rb")) == NULL) { free(names); free(types); free(sizes); free(csizes); AdvDlgMessage("PowerComPress - Error", "Unable to read data", B_OK); return PARENT; } splitted++; fseek(group, 1, SEEK_CUR); fgetpos(group, &pos); } else { fsetpos(group, &pos); } // Read from block header while (fread(header, 1, HEADER_SIZE, group) == HEADER_SIZE) { // Verify values in header if (get_uint32(header + 0*4) != 0x636C8F1B || get_uint32(header + 1*4) > blz_max_packed_size(BLOCK_SIZE) || get_uint32(header + 3*4) > BLOCK_SIZE) { break; } // Move file pointer forward if (fseek(group, (long)get_uint32(header + 1*4), SEEK_CUR)) { free(names); free(types); free(sizes); free(csizes); fclose(group); AdvDlgMessage("PowerComPress - Error", "Unable to read data", B_OK); return PARENT; } fgetpos(group, &pos); // The end of the file is reached! fread(arrow, 1, sizeof(char)*3, group); if (!strncmp(arrow, "-->", 3)) { fread(tname, 1, sizeof(tname), group); fclose(group); //AdvDlgMessage("PowerComPress", tname, B_OK); if ((group = fopen(tname, "rb")) == NULL) { free(names); free(types); free(sizes); free(csizes); AdvDlgMessage("PowerComPress - Error", "Unable to read data", B_OK); return PARENT; } splitted++; fseek(group, 1, SEEK_CUR); fgetpos(group, &pos); } else { fsetpos(group, &pos); } } fsetpos(group, &pos); fread(&compsize, 1, sizeof(size_t), group); sprintf(&csizes[(counter-1)*6], "%lu", (unsigned long)compsize); } fclose(group); //sprintf(tname, "%lX", pos); //AdvDlgMessage(tname, arrow, B_OK); item = 0; showfirst = 0; i = Browse(grpname, names, types, sizes, csizes, counter); free(types); free(sizes); free(csizes); if (i == EXTRACT_VAR) { strncpy(tname, &names[((item+showfirst)*13)], 13); free(names); ExtractGroup(grpname, tname); i = REDRAW; } else { free(names); } if (i == EXIT) { ExitPCP(NORMAL); } item = 0; showfirst = 0; return i; } // Decompresses a whole group (or just a variable if its name is given) short ExtractGroup(char *grpname, char *varname) { FILE *group; FILE *var; char tname[18], vname[18], arrow[3], gtype[6], msg[40], msg2[40]; short splitted = 0, mode = 1; GROUPHEADER gheader; BYTE header[HEADER_SIZE]; fpos_t pos; BYTE *data, *packed; size_t compsize, groupsize; BOOL skip; // Is the file a GroupFile? VarTypeToStr(DerefSym(SymFind(SYMSTR(grpname))), gtype); if (strncmp(gtype, ".pcp", 4)) { return REDRAW; } if (varname == NULL) { mode = 0; // Initialize dialog AdvDlgInit(100, 60, "PowerComPress", B_ESC, B_OK, TRUE, save_int_1); sprintf(msg, "Extract %s", grpname); // Add dialog elements AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_NONE, NULL, NULL, 0, 0, 0, 0); AdvDlgAdd(AD_TEXT, "Options:", NULL, 0, 0, 0, TXT_STANDARD); sprintf(msg, "Delete %s", grpname); AdvDlgAdd(AD_CHECKBOX, msg, NULL, 0, 0, FALSE, 0); AdvDlgAdd(AD_CHECKBOX, "Archive output files", NULL, 0, 0, TRUE, 0); // Execute Dialog if (!AdvDlgDo()) { return REDRAW; } } else { // Initialize dialog AdvDlgInit(100, 60, "PowerComPress", B_ESC, B_OK, TRUE, save_int_1); sprintf(msg, "Extract %s", varname); sprintf(msg2, "from %s", grpname); // Add dialog elements AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, msg2, NULL, 0, 0, 0, 0); AdvDlgAdd(AD_NONE, NULL, NULL, 0, 0, 0, 0); AdvDlgAdd(AD_TEXT, "Options:", NULL, 0, 0, 0, TXT_STANDARD); sprintf(msg, "Archive %s", varname); AdvDlgAdd(AD_CHECKBOX, msg, NULL, 0, 0, options.AlwaysArcVar, 0); // Execute Dialog if (!AdvDlgDo()) { return REDRAW; } AD_CHECKED[1] = AD_CHECKED[0]; AD_CHECKED[0] = FALSE; } // Determine the size of all GroupFiles BOOL split; strcpy(tname, grpname); groupsize = 0; do { groupsize += GetVarSize(DerefSym(SymFind(SYMSTR(tname)))); if ((group = fopen(tname, "rb")) == NULL) { AdvDlgMessage("PowerComPress - Error", "Unable to open GroupFile", B_OK); return REDRAW; } if ((split = fgetc(group))) { if (splitnum++ > 0) fseek(group, -19, SEEK_END); else fseek(group, -18, SEEK_END); fread(tname, 1, 18, group); if (!SymFind(SYMSTR(tname)).folder) { if (splitnum > 1) fseek(group, -13, SEEK_END); else fseek(group, -12, SEEK_END); fread(tname, 1, 9, group); } } fseek(group, 0, SEEK_SET); fclose(group); } while (split); strcpy(tname, grpname); groupcount_compressed = 0; // Allocate memory if ((data = (byte *) malloc(BLOCK_SIZE)) == NULL) { AdvDlgMessage("PowerComPress - Error", "Not enough memory", B_OK); return REDRAW; } if ((packed = (byte *) malloc(blz_max_packed_size(BLOCK_SIZE))) == NULL) { free(data); AdvDlgMessage("PowerComPress - Error", "Not enough memory", B_OK); return REDRAW; } if ((group = fopen(tname, "rb")) == NULL) { free(data); free(packed); AdvDlgMessage("PowerComPress - Error", "Unable to open GroupFile", B_OK); return REDRAW; } fgetc(group); /* Show the ProgressBar ProgressBarInit("PowerComPress", NULL, NULL, 0, 0, TRUE); Wait(1); ProgressBarDraw(0, 0, 0); */ // Read from header while ((fread(&gheader, 1, sizeof(GROUPHEADER), group)) == sizeof(GROUPHEADER)) { if (gheader.hcode != 0x636C8F1A) { free(data); free(packed); fclose(group); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "Corrupted GroupFile", B_OK); return REDRAW; } fgetpos(group, &pos); // The end of the file is reached! fread(arrow, 1, sizeof(char)*3, group); if (!strcmp(arrow, "-->")) { fread(tname, 1, sizeof(tname), group); fclose(group); if ((group = fopen(tname, "rb")) == NULL) { free(data); free(packed); fclose(var); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "Unable to read data", B_OK); return PARENT; } fgetc(group); splitted++; fgetpos(group, &pos); } else { fsetpos(group, &pos); } filecount = 0; skip = FALSE; sprintf(msg, "Extracting %s", gheader.varname); sprintf(msg2, "From %s", tname); // Extract only a single variable if (mode == 2) { free(data); free(packed); fclose(group); return REDRAW; } if (mode == 1) { strcpy(vname, gheader.varname); GetGroupEntryName(vname); if (!strcmp(varname, vname)) { skip = FALSE; mode = 2; } else { skip = TRUE; } } // Test for new folder if (!skip) { if (!TestFolder(gheader.varname)) { free(data); free(packed); fclose(group); AdvDlgMessage("PowerComPress - Error", "Unable to open output file", B_OK); return REDRAW; } } fgetpos(group, &pos); compsize = 0; while (fread(header, 1, HEADER_SIZE, group) == HEADER_SIZE) { // Verify values in header if (get_uint32(header + 0*4) != 0x636C8F1B || get_uint32(header + 1*4) > blz_max_packed_size(BLOCK_SIZE) || get_uint32(header + 3*4) > BLOCK_SIZE) { break; } compsize += (size_t)get_uint32(header + 1*4) - HEADER_SIZE; // Move file pointer forward if (fseek(group, (long)get_uint32(header + 1*4), SEEK_CUR)) { free(data); free(packed); fclose(group); AdvDlgMessage("PowerComPress - Error", "Unable to read data", B_OK); return PARENT; } } if (mode == 2) { groupsize = compsize; groupcount_compressed = 0; } fsetpos(group, &pos); // Open output file if (!skip) { ProgressBarInit("PowerComPress", msg, msg2, compsize, groupsize, FALSE); Wait(1); if ((var = fopen(gheader.varname, "wb")) == NULL) { // Ask to overwrite file AdvDlgInit(110, 45, "PowerComPress - Warning", B_NONE, B_NONE, TRUE, save_int_1); AdvDlgAdd(AD_TEXT, gheader.varname, NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, "already exists.", NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, "[ENTER] = Overwrite", NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, "[ESC] = Skip file", NULL, 0, 0, 0, TXT_STANDARD); if (!AdvDlgDo()) { skip = TRUE; } else { // Try to delete the original file if (!DeleteVar(gheader.varname)) { // Ask to skip file AdvDlgInit(110, 45, "PowerComPress - Error", B_NONE, B_NONE, TRUE, save_int_1); AdvDlgAdd(AD_TEXT, "Unable to overwrite", NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, gheader.varname, NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, "[ENTER] = Skip file", NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, "[ESC] = Cancel action", NULL, 0, 0, 0, TXT_STANDARD); if (AdvDlgDo()) { skip = TRUE; } else { free(data); free(packed); fclose(group); return REDRAW; } } // Reopen file if ((var = fopen(gheader.varname, "wb")) == NULL) { free(data); free(packed); fclose(group); return REDRAW; AdvDlgMessage("PowerComPress - Error", "Unable to write data", B_OK); } } } } fgetpos(group, &pos); // Read from block header while (fread(header, 1, HEADER_SIZE, group) == HEADER_SIZE) { size_t hdr_packedsize, hdr_depackedsize, depackedsize; /*char msg[10]; sprintf(msg, "%lu", get_uint32(header + 1*4)); AdvDlgMessage(NULL, msg, B_NONE); */ // Verify values in header if (get_uint32(header + 0*4) != 0x636C8F1B || get_uint32(header + 1*4) > blz_max_packed_size(BLOCK_SIZE) || get_uint32(header + 3*4) > BLOCK_SIZE) { break; } hdr_packedsize = (size_t) get_uint32(header + 1*4); hdr_depackedsize = (size_t) get_uint32(header + 3*4); if (mode != 1) { ProgressBarDraw(filecount, 0, groupcount_compressed); } // Start decompressing if (!skip) { // Decompress data or just extract it if (!get_uint32(header + 5*4)) { if (fread(packed, 1, hdr_depackedsize, group) != hdr_depackedsize) { free(data); free(packed); fclose(var); fclose(group); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "Unable to read data", B_OK); return REDRAW; } memcpy(data, packed, hdr_depackedsize); depackedsize = hdr_depackedsize; } else { if (fread(packed, 1, hdr_packedsize, group) != hdr_packedsize) { free(data); free(packed); fclose(var); fclose(group); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "Unable to read data", B_OK); return REDRAW; } if (get_uint32(header + 2*4) != blz_crc32(packed, hdr_packedsize, 0)) { free(data); free(packed); fclose(var); fclose(group); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "Compressed data CRC error", B_OK); return REDRAW; } depackedsize = blz_depack(packed, data, hdr_depackedsize); if (depackedsize != hdr_depackedsize) { free(data); free(packed); fclose(var); fclose(group); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "Decompressing failed", B_OK); return REDRAW; } if (get_uint32(header + 4*4) != blz_crc32(data, depackedsize, 0)) { free(data); free(packed); fclose(var); fclose(group); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "Decompressed file CRC error", B_OK); return REDRAW; } } if ((fwrite(data, 1, depackedsize, var)) != depackedsize) { free(data); free(packed); fclose(var); fclose(group); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "Unable to write data", B_OK); return REDRAW; } } // Move file pointer forward if file should be skipped else { if (fseek(group, (long)get_uint32(header + 1*4), SEEK_CUR)) { free(data); free(packed); fclose(group); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "Unable to read data", B_OK); return PARENT; } } filecount += hdr_packedsize + HEADER_SIZE; groupcount_compressed += hdr_packedsize + HEADER_SIZE; if (mode != 1) { ProgressBarDraw(filecount, 0, groupcount_compressed); } fgetpos(group, &pos); // The end of the file is reached! fread(arrow, 1, sizeof(char)*3, group); if (!strcmp(arrow, "-->")) { fread(tname, 1, sizeof(tname), group); fclose(group); if ((group = fopen(tname, "rb")) == NULL) { free(data); free(packed); fclose(var); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "Unable to read data", B_OK); return PARENT; } fgetc(group); ProgressBarClose(); // Show the ProgressBar sprintf(msg, "Extracting %s", gheader.varname); sprintf(msg2, "From %s", tname); if (mode != 1) { ProgressBarInit("PowerComPress", msg, msg2, gheader.varsize, groupsize, FALSE); Wait(1); } splitted++; fgetpos(group, &pos); } else { fsetpos(group, &pos); } } fsetpos(group, &pos); fread(&compsize, 1, sizeof(size_t), group); ProgressBarClose(); if (AD_CHECKED[1]) { EM_moveSymToExtMem(SYMSTR(gheader.varname), HS_NULL); } } return REDRAW; } // Compresses a variable to a group BOOL AddVarToGroup(char *varname) { FILE *var, *group; char type[6], msg1[50], msg2[50], groupnamex[18]; BOOL compressed = TRUE, first = FALSE, split = FALSE; GROUPHEADER gheader; size_t n_read, packedsize, outsize; byte *data, *packed, *workmem, header[HEADER_SIZE]; filecount = 0; strcpy(groupnamex, groupname); memset(&gheader, 0, sizeof(GROUPHEADER)); // Ask for group name if needed if (!isfolder) { if (!GetGroupName(varname, groupnamex)) return 0; groupcount_compressed = 0; groupcount_uncompressed = 0; splitcount = 0; strcpy(groupname, groupnamex); } // The variable should be compressed to the opened folder if (strcspn(groupname, append) == strlen(groupname)) { sprintf(groupname, "%s%c%s", folder, append[0], groupnamex); strcpy(groupnamex, groupname); } // Check if the file exists if (!SymFind(SYMSTR(groupname)).folder) { first = TRUE; } else { // Determine type of the GroupFile VarTypeToStr(DerefSym(SymFind(SYMSTR(groupname))), type); if (strncmp(type, ".pcp", 4) && strncmp(type, ".part", 5)) { AdvDlgMessage("PowerComPress - Error", "Unable to open GroupFile", B_OK); return 0; } // Check if the GroupFile is splitted and find end of GroupFile do { if ((group = fopen(groupname, "rb")) == NULL) { AdvDlgMessage("PowerComPress - Error", "Unable to open GroupFile", B_OK); return 0; } // Get name of next part if ((split = fgetc(group))) { if (splitnum++ > 0) fseek(group, -19, SEEK_END); else fseek(group, -18, SEEK_END); fread(groupname, 1, 18, group); } fclose(group); } while (split); } EM_moveSymFromExtMem(SYMSTR(groupname), HS_NULL); // Test for new folder if (!TestFolder(groupname)) { AdvDlgMessage("PowerComPress - Error", "Unable to open GroupFile", B_OK); return 0; } // Allocate memory if ((data = malloc(BLOCK_SIZE)) == NULL) { AdvDlgMessage("PowerComPress - Error", "Not enough memory", B_OK); return 0; } if ((packed = malloc(blz_max_packed_size(BLOCK_SIZE))) == NULL) { free(data); AdvDlgMessage("PowerComPress - Error", "Not enough memory", B_OK); return 0; } if ((workmem = malloc(blz_workmem_size(BLOCK_SIZE))) == NULL) { free(data); free(packed); AdvDlgMessage("PowerComPress - Error", "Not enough memory", B_OK); return 0; } // Open variable if ((var = fopen(varname, "rb")) == NULL) { AdvDlgMessage("PowerComPress - Error", "Unable to open input file", B_OK); free(workmem); free(packed); free(data); return 0; } splitcount = GetVarSize(DerefSym(SymFind(SYMSTR(groupname)))); // Open group if ((group = fopen(groupname, "ab")) == NULL) { AdvDlgMessage("PowerComPress - Error", "Unable to open GroupFile", B_OK); free(workmem); free(packed); free(data); return 0; } if (first) { fputc(0, group); // Splitting information } else { if (!splitnum) fseek(group, -6, SEEK_CUR); else fseek(group, -7, SEEK_CUR); } // Set header values gheader.varsize = GetVarSize(SymFindPtr(SYMSTR(varname), 0)); strcpy(gheader.varname, varname); VarTypeToStr(DerefSym(SymFind(SYMSTR(varname))), gheader.type); gheader.hcode = 0x636C8F1A; if (!isfolder) groupsize = gheader.varsize; // Write header to file if ((fwrite(&gheader, 1, sizeof(GROUPHEADER), group)) != sizeof(GROUPHEADER)) { AdvDlgMessage("PowerComPress - Error", "Unable to write data", B_OK); free(workmem); free(packed); free(data); return 0; } // Show the ProgressBar sprintf(msg1, "Compressing %s", varname); sprintf(msg2, "Output: %s", groupname); ProgressBarInit("PowerComPress", msg1, msg2, gheader.varsize, groupsize, !isfolder); Wait(1); ProgressBarDraw(filecount, groupcount_uncompressed, groupcount_compressed); outsize = 0; // While we are able to read data from input file ... while ((n_read = fread(data, 1, BLOCK_SIZE, var)) > 0) { packedsize = 0; compressed = TRUE; // Compress data block packedsize = blz_pack(data, packed, n_read, workmem); // Check for compression error if (packedsize == 0) { free(workmem); free(packed); free(data); fclose(var); fclose(group); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "An error occured while comp.", B_OK); return 0; } // If the output is larger than the input if (packedsize > n_read) { compressed = FALSE; packedsize = n_read; } // Split of the GroupFile if needed if (((splitcount + packedsize + HEADER_SIZE) >= 65450) && (splitnum < 255)) { splitcount = 0; ProgressBarClose(); if (!AskToSplitFile()) { free(workmem); free(packed); free(data); fclose(var); fclose(group); return 0; } // Get new group name strcpy(groupnamex, groupname); GetSplitName(groupnamex, splitnum); splitnum++; // Write info about new groupname fputs("-->", group); fputs(groupname, group); // Add the file ID tag fputc(0, group); if (splitnum < 2) { fputs("PCP", group); } else { fputs("part", group); } fputc(0, group); fputc(OTH_TAG, group); // Add split information fseek(group, 0, SEEK_SET); fputc(1, group); //fseek(group, 0, SEEK_END); fclose(group); if (AD_CHECKED[1]) { EM_moveSymToExtMem(SYMSTR(groupnamex), HS_NULL); Wait(4); } sprintf(msg2, "Output: %s", groupname); ProgressBarInit("PowerComPress", msg1, msg2, gheader.varsize, groupsize, FALSE); // Open new group if ((group = fopen(groupname, "wb")) == NULL) { ProgressBarClose(); free(workmem); free(packed); free(data); fclose(var); AdvDlgMessage("PowerComPress - Error", "Unable to open GroupFile", B_OK); return 0; } fputc(0, group); } // Put block-specific values into header put_uint32(header + 0*4, 0x636C8F1B); put_uint32(header + 1*4, packedsize); put_uint32(header + 2*4, blz_crc32(packed, packedsize, 0)); put_uint32(header + 3*4, n_read); put_uint32(header + 4*4, blz_crc32(data, n_read, 0)); put_uint32(header + 5*4, compressed); // Write header and data fwrite(header, 1, HEADER_SIZE, group); if (compressed) { if (fwrite(packed, 1, packedsize, group) != packedsize) { fclose(var); fclose(group); free(workmem); free(packed); free(data); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "Unable to write data", B_OK); //SymDel(SYMSTR(groupname)); return 0; } } else { if (fwrite(data, 1, n_read, group) != n_read) { fclose(var); fclose(group); free(workmem); free(packed); free(data); ProgressBarClose(); AdvDlgMessage("PowerComPress - Error", "Unable to write data", B_OK); //SymDel(SYMSTR(groupname)); return 0; } } // Show ProgressBar filecount += n_read; groupcount_uncompressed += n_read; outsize += packedsize + HEADER_SIZE; groupcount_compressed += packedsize + HEADER_SIZE; splitcount += packedsize + HEADER_SIZE; ProgressBarDraw(filecount, groupcount_uncompressed, groupcount_compressed); } fclose(var); // Free memory free(workmem); free(packed); free(data); // Write outsize at the end of the entry if ((fwrite(&outsize, 1, sizeof(size_t), group)) != sizeof(size_t)) { ProgressBarClose(); fclose(group); AdvDlgMessage("PowerComPress - Error", "Unable to write data", B_OK); return 0; } // Add the file ID tag fputc(0, group); if (splitnum < 1) fputs("PCP", group); else fputs("part", group); fputc(0, group); fputc(OTH_TAG, group); // Close files fclose(group); if (!isfolder) { ProgressBarClose(); if (AD_CHECKED[1]) EM_moveSymToExtMem(SYMSTR(groupname), HS_NULL); } // Delete var if needed if (AD_CHECKED[0]) { EM_moveSymFromExtMem(SYMSTR(varname), HS_NULL); SymDel(SYMSTR(varname)); } return REDRAW; } // Compresses a whole folder to a variable short CompressFolder(char *foldername) { char varname[20]; splitnum = 0; ogroupname[0] = 0; groupsize = 0; groupcount_compressed = 0; groupcount_uncompressed = 0; if (!GetGroupName(foldername, ogroupname)) { return REDRAW; } // Search for files short counter = 0, i = 0; SYM_ENTRY *symptr = SymFindFirst(SYMSTR(foldername), FO_SINGLE_FOLDER); // How many files are there? while (symptr) { if (strncmp(symptr->name, "pcpress", 7) && strncmp(symptr->name, "pcpdata", 7) && strncmp(symptr->name, "pcpcfg", 7) && !symptr->flags.bits.twin && !symptr->flags.bits.local && !symptr->flags.bits.hidden) counter++; symptr = SymFindNext(); } if (!counter) { AdvDlgMessage("PowerComPress - Error", "Empty folder", B_OK); return REDRAW; } symptr = SymFindFirst(SYMSTR(foldername), FO_SINGLE_FOLDER); char names[counter][9]; // Get a list of the entries of folder "folder" while (symptr) { if (strncmp(symptr->name, "pcpress", 7) && strncmp(symptr->name, "pcpdata", 7) && strncmp(symptr->name, "pcpcfg", 7) && !symptr->flags.bits.twin && !symptr->flags.bits.local && !symptr->flags.bits.hidden) strcpy(names[i++], symptr->name); groupsize += GetVarSize(symptr); symptr = SymFindNext(); } ProgressBarInit("PowerComPress", NULL, NULL, 5, 5, TRUE); strcpy(groupname, ogroupname); // The variables should be compressed to the opened folder if (strcspn(ogroupname, append) == strlen(ogroupname)) { sprintf(ogroupname, "%s%c%s", folder, append[0], groupname); strcpy(groupname, ogroupname); } isfolder = TRUE; // Compress file by file for (i = 0; i < counter; i++) { memset(varname, 0, 20); sprintf(varname, "%s%c%s", foldername, 92, names[i]); if (!AddVarToGroup(varname)) { goto quit; } }; quit: // Optional things if (AD_CHECKED[1]) { EM_moveSymToExtMem(SYMSTR(groupname), HS_NULL); EM_moveSymToExtMem(SYMSTR(ogroupname), HS_NULL); } Wait(100); strcpy(groupname, ogroupname); ProgressBarClose(); isfolder = FALSE; return REDRAW; }