home *** CD-ROM | disk | FTP | other *** search
- /***
- **** QuBE --- .PAK file editing routines.
- ****
- **** Note that these are based partially on that posting on the Net.
- **** Would the author of that please contact me so I can give him some
- **** credit?
- ***/
-
- #include "qube.h"
- #include "pak.h"
-
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <errno.h>
-
- /* A single filename entry in a .PAK file */
-
- typedef struct {
- unsigned char filename[56];
- long pos, len;
- } pakentry;
-
- /* The .PAK file entries. 512 of them. This should be dynamically allocated
- in a linked list or something. Any volunteers? */
-
- static pakentry entries[512];
- static long entrycount = 0;
-
- static void extract(char *filename);
- static void makepath(unsigned char *path);
-
- /*
- ** PakXtract. Extract *all* files from a .PAK file.
- */
-
- void PakXtract(void)
- {
- extract("*");
- }
-
- /*
- ** PakXtract2. Extract file(s) from a .PAK file.
- */
-
- void PakXtract2(int argnum, char **argv)
- {
- extract(argv[argnum+1]);
- }
-
- static void extract(char *filename)
- {
- FILE *fo;
- long table, tablelen, dummy;
- long i, j, k;
- unsigned char *temp;
- int readsize;
-
- /* Make sure it's a .PAK file --- they start with "PACK" */
-
- if (header.id != 0x4B434150)
- Error("Not a valid .PAK file");
-
- /* Go back to the beginning, since we already read a header */
-
- fseek(fi, 0, SEEK_SET);
- fread(&dummy, sizeof(long), 1, fi);
- fread(&table, sizeof(long), 1, fi);
- fread(&tablelen, sizeof(long), 1, fi);
-
- fseek(fi, table, SEEK_SET);
-
- /* Load in the filename table. Like I said, this ought to be a
- linked list or something. */
-
- for (i = 0; i < tablelen / 64; i++)
- fread(entries+i, sizeof(pakentry), 1, fi);
-
- /* Temporary small buffer for copying files. We can't just allocate
- all the space because DOS has these memory limitation thingys. */
-
- temp = Qmalloc(32768);
-
- /* Do it. */
-
- for (i = 0; i < tablelen / 64; i++) {
-
- /* Match it. */
- if (MatchName(filename, entries[i].filename)) {
-
- /* Print it. */
-
- if (verbose)
- printf("Extracting %s, address %08lX (size %ld)\n",
- entries[i].filename, entries[i].pos, entries[i].len);
-
- /* Locate it. */
-
- makepath(entries[i].filename);
- if ((fo = fopen(entries[i].filename, "wb")) == NULL)
- Error("Unable to get permission to write files.");
- fseek(fi, entries[i].pos, SEEK_SET);
-
- /* Write it. */
-
- for (j = 0L; j < entries[i].len; j += 32768L) {
- if (entries[i].len - j >= 32768) k = 32768;
- else k = entries[i].len - j;
- readsize = fread(temp, sizeof(char), k, fi);
- fwrite(temp, sizeof(char), readsize, fo);
- }
-
- fclose(fo);
- }
- }
- Qfree(temp);
- }
-
- /*
- ** PakList. List all files in a .PAK file. Based on the above subroutine;
- ** see it for comments on how it works.
- */
-
- void PakList(void)
- {
- FILE *fo;
- long pos, len, dummy;
- long i, j, k;
- unsigned char *temp;
- int readsize;
-
- if (header.id != 0x4B434150)
- Error("Not a valid .PAK file");
-
- fseek(fi, 0, SEEK_SET);
- fread(&dummy, sizeof(long), 1, fi);
- fread(&pos, sizeof(long), 1, fi);
- fread(&len, sizeof(long), 1, fi);
- fseek(fi, pos, SEEK_SET);
-
- for (i = 0; i < len / 64; i++)
- fread(entries+i, sizeof(pakentry), 1, fi);
-
- if (verbose)
- printf("%-8s %-8s %-60s\n", "Address", "Size", "FileName");
-
- for (i = 0; i < len / 64; i++) {
- if (verbose)
- printf("%08lX %-8ld %s\n", entries[i].pos, entries[i].len, entries[i].filename);
- else printf("%s\n", entries[i].filename);
- }
- }
-
- /*
- ** PakDelete. Zorch file(s) from a .PAK file.
- */
-
- void PakDelete(int argnum, char **argv)
- {
- FILE *fo;
- long pos, len, dummy;
- long newpos, newlen;
- long i, j, k;
- unsigned char *temp;
- int readsize;
-
- if (header.id != 0x4B434150)
- Error("Not a valid .PAK file");
-
- fseek(fi, 0, SEEK_SET);
- fread(&dummy, sizeof(long), 1, fi);
- fread(&pos, sizeof(long), 1, fi);
- fread(&len, sizeof(long), 1, fi);
- fseek(fi, pos, SEEK_SET);
-
- for (i = 0; i < len / 64; i++)
- fread(entries+i, sizeof(pakentry), 1, fi);
-
- if ((fo = fopen("$$$_temp.pak", "wb")) == NULL)
- Error("Unable to get permission to write files.");
-
- k = fwrite(&dummy, 1, sizeof(long), fo);
- k += fwrite(&pos, 1, sizeof(long), fo);
- k += fwrite(&len, 1, sizeof(long), fo);
-
- if (k < 12) {
- fclose(fo);
- unlink("$$$_temp.pak");
- Error("Insufficient disk space");
- }
-
- newpos = 12L;
-
- temp = Qmalloc(32768);
-
- for (i = 0; i < len / 64; i++) {
- if (MatchName(argv[argnum+1], entries[i].filename)) {
- if (verbose)
- printf("Deleting %s\n", entries[i].filename, entries[i].pos, entries[i].len);
- }
- else {
- fseek(fi, entries[i].pos, SEEK_SET);
- if (verbose)
- printf("Keeping %s\n", entries[i].filename, entries[i].pos, entries[i].len);
- entries[i].pos = newpos;
- for (j = 0L; j < entries[i].len; j += 32768L) {
- if (entries[i].len - j >= 32768) k = 32768;
- else k = entries[i].len - j;
- readsize = fread(temp, sizeof(char), k, fi);
- newpos += (k = fwrite(temp, sizeof(char), readsize, fo));
- if (k < readsize) {
- fclose(fo);
- unlink("$$$_temp.pak");
- Error("Insufficient disk space");
- }
- }
- }
- }
-
- Qfree(temp);
-
- newlen = 0L;
-
- for (i = 0; i < len / 64; i++) {
- if (!MatchName(argv[argnum+1], entries[i].filename)) {
- k = fwrite(entries+i, 1, sizeof(pakentry), fo);
- if (k < sizeof(pakentry)) {
- fclose(fo);
- unlink("$$$_temp.pak");
- Error("Insufficient disk space");
- }
- newlen++;
- }
- }
-
- newlen *= 64;
-
- fseek(fo, 0, SEEK_SET);
- fwrite(&dummy, 1, sizeof(long), fo);
- fwrite(&newpos, 1, sizeof(long), fo);
- fwrite(&newlen, 1, sizeof(long), fo);
-
- fclose(fo);
- fclose(fi);
-
- unlink(argv[filenamearg]);
- rename("$$$_temp.pak", argv[filenamearg]);
- }
-
- /*
- ** PakAdd. Zorch file(s) from a .PAK file.
- */
-
- void PakAdd(int argnum, char **argv)
- {
- FILE *fo;
- long pos, len, dummy;
- long newpos, newlen;
- long i, j, k;
- unsigned char *temp;
- int readsize;
-
- if (justcreated) {
- pos = 12;
- len = 0;
- header.id = dummy = 0x4B434150;
- fwrite(&dummy, sizeof(long), 1, fi);
- fwrite(&pos, sizeof(long), 1, fi);
- fwrite(&len, sizeof(long), 1, fi);
- }
-
- if (header.id != 0x4B434150)
- Error("Not a valid .PAK file");
-
- if ((fi = freopen(argv[filenamearg], "r+b", fi)) == NULL)
- Error("Unable to get permission to update files.");
-
- fseek(fi, 0, SEEK_SET);
- fread(&dummy, sizeof(long), 1, fi);
- fread(&pos, sizeof(long), 1, fi);
- fread(&len, sizeof(long), 1, fi);
- fseek(fi, pos, SEEK_SET);
-
- for (i = 0; i < len / 64; i++)
- fread(entries+i, sizeof(pakentry), 1, fi);
-
- fseek(fi, pos, SEEK_SET);
-
- newlen = 0L;
-
- if ((fo = fopen(argv[argnum+1], "rb")) == NULL)
- Error(strerror(errno));
-
- temp = Qmalloc(32768);
-
- while (!feof(fo)) {
- readsize = fread(temp, sizeof(char), 32768, fo);
- newlen += (k = fwrite(temp, sizeof(char), readsize, fi));
- if (k < readsize) {
- fclose(fo);
- Error("Insufficient disk space");
- }
- }
- fclose(fo);
-
- Qfree(temp);
-
- entries[len/64].pos = pos;
- entries[len/64].len = newlen;
- strcpy(entries[len/64].filename, argv[argnum+1]);
- len += 64;
- pos += newlen;
-
- fseek(fi, 0, SEEK_SET);
- fwrite(&dummy, sizeof(long), 1, fi);
- fwrite(&pos, sizeof(long), 1, fi);
- fwrite(&len, sizeof(long), 1, fi);
- fseek(fi, pos, SEEK_SET);
-
- for (i = 0; i < len / 64; i++)
- fwrite(entries+i, sizeof(pakentry), 1, fi);
- }
-
- /*
- ** makepath. Create a pathname based on a path.
- */
-
- static void makepath(unsigned char *path)
- {
- unsigned char *temp2;
- unsigned char temp[64];
-
- strncpy(temp, path, 64);
- temp[63] = '\0';
-
- temp2 = temp;
-
- while (*temp2) {
- if(*temp2 == '/') {
- *temp2 = '\0';
- mkdir(temp);
- *temp2 = '/';
- }
- temp2++;
- }
- }
-
-