kextract.cpp
1 // "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman 2 // Ken Silverman's official web site: "http://www.advsys.net/ken" 3 // See the included license file "BUILDLIC.TXT" for license info. 4 // 5 // This file has been modified from Ken Silverman's original release 6 // by Jonathon Fowler (jf@jonof.id.au) 7 8 #include "compat.h" 9 #include "kplib.h" 10 11 #include <utime.h> 12 13 #define MAXFILES 4096 14 15 static char buf[65536]; 16 17 static int numfiles, anyfiles4extraction; 18 static char marked4extraction[MAXFILES]; 19 static char filelist[MAXFILES][16]; 20 static int fileoffs[MAXFILES+1], fileleng[MAXFILES]; 21 22 void findfiles(const char *dafilespec) 23 { 24 char t[13]; 25 int i; 26 27 for(i=numfiles-1;i>=0;i--) 28 { 29 memcpy(t,filelist[i],12); 30 t[12] = 0; 31 32 if (Bwildmatch(t,dafilespec)) { 33 marked4extraction[i] = 1; 34 anyfiles4extraction = 1; 35 } 36 } 37 } 38 39 int main(int argc, char **argv) 40 { 41 int i, j, k, l, fil, fil2; 42 struct Bstat stbuf; 43 44 int onlylist = (argc==2); 45 46 if (argc < 2) 47 { 48 Bprintf("KEXTRACT <groupfile.grp> [@file or filespec...] by Kenneth Silverman\n"); 49 Bprintf(" This program extracts files from a previously grouped group file.\n"); 50 Bprintf(" You can extract files using the ? and * wildcards.\n"); 51 Bprintf(" Ex: kextract stuff.dat tiles000.art nukeland.map palette.dat\n"); 52 Bprintf(" (stuff.dat is the group file, the rest are the files to extract)\n"); 53 Bprintf(" kextract stuff.grp\n"); 54 Bprintf(" (simply lists the contents of stuff.grp)\n"); 55 return(0); 56 } 57 58 engineCreateAllocator(); 59 60 if ((fil = Bopen(argv[1],BO_BINARY|BO_RDONLY,BS_IREAD)) == -1) 61 { 62 Bprintf("Error: %s could not be opened\n",argv[1]); 63 return(0); 64 } 65 66 Bread(fil,buf,16); 67 if ((buf[0] != 'K') || (buf[1] != 'e') || (buf[2] != 'n') || 68 (buf[3] != 'S') || (buf[4] != 'i') || (buf[5] != 'l') || 69 (buf[6] != 'v') || (buf[7] != 'e') || (buf[8] != 'r') || 70 (buf[9] != 'm') || (buf[10] != 'a') || (buf[11] != 'n')) 71 { 72 Bclose(fil); 73 Bprintf("Error: %s not a valid group file\n",argv[1]); 74 return(0); 75 } 76 numfiles = *((int*)&buf[12]); numfiles = B_LITTLE32(numfiles); 77 78 Bread(fil,filelist,numfiles<<4); 79 80 j = 0; 81 for(i=0;i<numfiles;i++) 82 { 83 k = *((int*)&filelist[i][12]); k = B_LITTLE32(k); 84 filelist[i][12] = 0; 85 fileoffs[i] = j; 86 j += k; 87 } 88 fileoffs[numfiles] = j; 89 90 if (onlylist) 91 { 92 for (i=0; i<numfiles; i++) 93 Bprintf("%s\t\t%d\n", filelist[i], fileoffs[i+1]-fileoffs[i]); 94 95 return 0; 96 } 97 98 for(i=0;i<numfiles;i++) marked4extraction[i] = 0; 99 100 anyfiles4extraction = 0; 101 for(i=argc-1;i>1;i--) 102 { 103 if (argv[i][0] == '@') 104 { 105 if ((fil2 = Bopen(&argv[i][1],BO_BINARY|BO_RDONLY,BS_IREAD)) != -1) 106 { 107 l = Bread(fil2,buf,65536); 108 j = 0; 109 while ((j < l) && (buf[j] <= 32)) j++; 110 while (j < l) 111 { 112 k = j; 113 while ((k < l) && (buf[k] > 32)) k++; 114 115 buf[k] = 0; 116 findfiles(&buf[j]); 117 j = k+1; 118 119 while ((j < l) && (buf[j] <= 32)) j++; 120 } 121 Bclose(fil2); 122 } 123 } 124 else 125 findfiles(argv[i]); 126 } 127 128 if (anyfiles4extraction == 0) 129 { 130 Bclose(fil); 131 Bprintf("No files found in group file with those names\n"); 132 return(0); 133 } 134 135 if (Bfstat(fil, &stbuf) == -1) 136 stbuf.st_mtime = 0; 137 138 for(i=0;i<numfiles;i++) 139 { 140 if (marked4extraction[i] == 0) continue; 141 142 fileleng[i] = fileoffs[i+1]-fileoffs[i]; 143 144 if ((fil2 = Bopen(filelist[i],BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY,BS_IREAD|BS_IWRITE)) == -1) 145 { 146 Bprintf("Error: Could not write to %s\n",filelist[i]); 147 continue; 148 } 149 Bprintf("Extracting %s...\n",filelist[i]); 150 Blseek(fil,fileoffs[i]+((numfiles+1)<<4),SEEK_SET); 151 for(j=0;j<fileleng[i];j+=65536) 152 { 153 k = min(fileleng[i]-j,65536); 154 Bread(fil,buf,k); 155 if (Bwrite(fil2,buf,k) < k) 156 { 157 Bprintf("Write error (drive full?)\n"); 158 Bclose(fil2); 159 Bclose(fil); 160 return(0); 161 } 162 } 163 Bclose(fil2); 164 165 if (stbuf.st_mtime != 0) 166 { 167 struct utimbuf times; 168 169 times.modtime = stbuf.st_mtime; 170 times.actime = Btime(); 171 172 Butime(filelist[i],×); 173 } 174 } 175 Bclose(fil); 176 177 return 0; 178 } 179