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 
10 #define MAXFILES 4096
11 
12 static char buf[65536];
13 
14 static int numfiles, anyfiles4extraction;
15 static char marked4extraction[MAXFILES];
16 static char filelist[MAXFILES][16];
17 static int fileoffs[MAXFILES+1], fileleng[MAXFILES];
18 
findfiles(const char * dafilespec)19 void findfiles(const char *dafilespec)
20 {
21 	char t[13];
22 	int i;
23 
24 	for(i=numfiles-1;i>=0;i--)
25 	{
26 		memcpy(t,filelist[i],12);
27 		t[12] = 0;
28 
29 		if (Bwildmatch(t,dafilespec)) {
30 			marked4extraction[i] = 1;
31 			anyfiles4extraction = 1;
32 		}
33 	}
34 }
35 
main(int argc,char ** argv)36 int main(int argc, char **argv)
37 {
38 	int i, j, k, l, fil, fil2;
39 
40 	if (argc < 3)
41 	{
42 		printf("KEXTRACT [grouped file][@file or filespec...]           by Kenneth Silverman\n");
43 		printf("   This program extracts files from a previously grouped group file.\n");
44 		printf("   You can extract files using the ? and * wildcards.\n");
45 		printf("   Ex: kextract stuff.dat tiles000.art nukeland.map palette.dat\n");
46 		printf("      (stuff.dat is the group file, the rest are the files to extract)\n");
47 		return(0);
48 	}
49 
50 	if ((fil = Bopen(argv[1],BO_BINARY|BO_RDONLY,BS_IREAD)) == -1)
51 	{
52 		printf("Error: %s could not be opened\n",argv[1]);
53 		return(0);
54 	}
55 
56 	Bread(fil,buf,16);
57 	if ((buf[0] != 'K') || (buf[1] != 'e') || (buf[2] != 'n') ||
58 		 (buf[3] != 'S') || (buf[4] != 'i') || (buf[5] != 'l') ||
59 		 (buf[6] != 'v') || (buf[7] != 'e') || (buf[8] != 'r') ||
60 		 (buf[9] != 'm') || (buf[10] != 'a') || (buf[11] != 'n'))
61 	{
62 		Bclose(fil);
63 		printf("Error: %s not a valid group file\n",argv[1]);
64 		return(0);
65 	}
66 	numfiles = *((int*)&buf[12]); numfiles = B_LITTLE32(numfiles);
67 
68 	Bread(fil,filelist,numfiles<<4);
69 
70 	j = 0;
71 	for(i=0;i<numfiles;i++)
72 	{
73 		k = *((int*)&filelist[i][12]); k = B_LITTLE32(k);
74 		filelist[i][12] = 0;
75 		fileoffs[i] = j;
76 		j += k;
77 	}
78 	fileoffs[numfiles] = j;
79 
80 	for(i=0;i<numfiles;i++) marked4extraction[i] = 0;
81 
82 	anyfiles4extraction = 0;
83 	for(i=argc-1;i>1;i--)
84 	{
85 		if (argv[i][0] == '@')
86 		{
87 			if ((fil2 = Bopen(&argv[i][1],BO_BINARY|BO_RDONLY,BS_IREAD)) != -1)
88 			{
89 				l = Bread(fil2,buf,65536);
90 				j = 0;
91 				while ((j < l) && (buf[j] <= 32)) j++;
92 				while (j < l)
93 				{
94 					k = j;
95 					while ((k < l) && (buf[k] > 32)) k++;
96 
97 					buf[k] = 0;
98 					findfiles(&buf[j]);
99 					j = k+1;
100 
101 					while ((j < l) && (buf[j] <= 32)) j++;
102 				}
103 				Bclose(fil2);
104 			}
105 		}
106 		else
107 			findfiles(argv[i]);
108 	}
109 
110 	if (anyfiles4extraction == 0)
111 	{
112 		Bclose(fil);
113 		printf("No files found in group file with those names\n");
114 		return(0);
115 	}
116 
117 	for(i=0;i<numfiles;i++)
118 	{
119 		if (marked4extraction[i] == 0) continue;
120 
121 		fileleng[i] = fileoffs[i+1]-fileoffs[i];
122 
123 		if ((fil2 = Bopen(filelist[i],BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY,BS_IREAD|BS_IWRITE)) == -1)
124 		{
125 			printf("Error: Could not write to %s\n",filelist[i]);
126 			continue;
127 		}
128 		printf("Extracting %s...\n",filelist[i]);
129 		Blseek(fil,fileoffs[i]+((numfiles+1)<<4),SEEK_SET);
130 		for(j=0;j<fileleng[i];j+=65536)
131 		{
132 			k = min(fileleng[i]-j,65536);
133 			Bread(fil,buf,k);
134 			if (Bwrite(fil2,buf,k) < k)
135 			{
136 				printf("Write error (drive full?)\n");
137 				Bclose(fil2);
138 				Bclose(fil);
139 				return(0);
140 			}
141 		}
142 		Bclose(fil2);
143 	}
144 	Bclose(fil);
145 
146 	return 0;
147 }
148 
149