1 #include "dzip.h"
2 
dzExtractFile(uInt filepos,int testing)3 void dzExtractFile (uInt filepos, int testing)
4 {
5 	int inlen, blocksize;
6 	uInt eofptr, readptr;
7 	direntry_t *de = directory + filepos;
8 	char demomode;
9 #ifdef GUI
10 	char *action = testing ? "testing" : "extracting";
11 #else
12 	char *action = testing ? "checking" : "extracting";
13 #endif
14 
15 	static pakentry_t *pakdir;
16 	static uInt pakptr;
17 
18 	crcval = INITCRC;
19 	dzFile_Seek(de->ptr);
20 
21 	if (de->type == TYPE_PAK)
22 	{
23 		struct {
24 			int id;
25 			uInt offset;
26 			uInt size;
27 		} pakheader;
28 		int i;
29 
30 		printf("%s %s:\n", action, de->name);
31 		pakdir = Dzip_malloc(de->pak * sizeof(pakentry_t));
32 		memset(pakdir, 0, de->pak * sizeof(pakentry_t));
33 		pakptr = 12;
34 	/* write pak header */
35 		pakheader.id = pakid;
36 		pakheader.size = de->pak * sizeof(pakentry_t);
37 		pakheader.offset = de->real - pakheader.size;
38 		Outfile_Write(&pakheader, 12);
39 		for (i = 0; i < de->pak; i++)
40 		{
41 			printf(" %s", de[i + 1].name);
42 			dzExtractFile(filepos + i + 1, testing);
43 			if (AbortOp)
44 			{
45 				pakptr = 0;
46 				return;
47 			}
48 		}
49 		Outfile_Write(pakdir, de->pak * sizeof(pakentry_t));
50 		free(pakdir);
51 		pakptr = 0;
52 		return;
53 	}
54 
55 	if (de->type >= TYPE_LAST)
56 	{
57 		error("%s is unknown type of file: %i", de->name, de->type);
58 		return;
59 	}
60 	demomode = (de->type == TYPE_DEM || de->type == TYPE_NEHAHRA);
61 
62 	if (pakptr)
63 	{
64 		strcpy(pakdir[de->pak - 1].name, de->name);
65 		pakdir[de->pak - 1].len = de->real;
66 		pakdir[de->pak - 1].ptr = pakptr;
67 		pakptr += de->real;
68 	}
69 
70 #ifdef GUI
71 	if (pakptr || (testing && de->pak))
72 		GuiProgressMsg("%s %s [%s]", action, de[-de->pak].name, de->name);
73 	else
74 		GuiProgressMsg("%s %s", action, de->name);
75 #endif
76 
77 	if (!de->pak)
78 		printf("%s %s", action, de->name);
79 
80 	if (de->type == TYPE_STORE)
81 	{
82 		totalsize = de->real;
83 		while (totalsize && !AbortOp)
84 		{
85 			blocksize = (totalsize > p_blocksize * 2) ? p_blocksize * 2 : totalsize;
86 			dzFile_Read(inblk, blocksize);
87 			Outfile_Write(inblk, blocksize);
88 			totalsize -= blocksize;
89 		}
90 	}
91 	else
92 	{
93 		inlen = readptr = totalsize = 0;
94 		eofptr = de->inter;
95 		ztotal = de->size;
96 		inflateInit(&zs);	/* cant possibly fail with my modified zlib */
97 		zs.avail_in = 0;
98 
99 		if (demomode)
100 			dem_uncompress_init(de->type);
101 
102 		while (readptr < eofptr && !AbortOp)
103 		{
104 			if (!dzRead(inlen))
105 				break;	/* corrupt compressed stream */
106 
107 			if (demomode)
108 			{
109 				blocksize = dem_uncompress(eofptr - readptr);
110 				if (!blocksize)
111 					break;
112 			}
113 			else
114 			{
115 				blocksize = totalsize - readptr;
116 				if (totalsize >= eofptr)
117 					blocksize = eofptr - readptr;
118 				Outfile_Write(inblk, blocksize);
119 			}
120 			if (blocksize != p_blocksize)
121 				memcpy(inblk, inblk + blocksize, p_blocksize - blocksize);
122 			readptr += blocksize;
123 			inlen = p_blocksize - blocksize;
124 		}
125 		inflateEnd(&zs);
126 	}
127 
128 	if (!AbortOp && crcval != de->crc)
129 	{
130 #ifdef GUI
131 		error("CRC error in %s", de->name);
132 #else
133 		error(": CRC checksum error! Archive is broken!");
134 #endif
135 	} else if (testing) printf(": ok\n");
136 	else printf("\n");
137 }
138 
139 #ifndef GUI
140 
141 #include "dzipcon.h"
142 
setfiledate(char * filename,uInt date)143 void setfiledate (char *filename, uInt date)
144 {
145 #ifdef WIN32
146 	FILETIME ft1, ft2;
147 	HANDLE h = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
148 		NULL, OPEN_EXISTING, 0, NULL);
149 	DosDateTimeToFileTime(HIWORD(date + (1 << 21)), LOWORD(date), &ft1);
150 	LocalFileTimeToFileTime(&ft1, &ft2);
151 	SetFileTime(h, NULL, NULL, &ft2);
152 	CloseHandle(h);
153 #else
154 	struct tm timerec;
155 	struct utimbuf tbuf;
156 
157 	timerec.tm_hour = (date >> 11) & 0x1f;
158 	timerec.tm_min = (date >> 5) & 0x3f;
159 	timerec.tm_sec = (date & 0x1f) << 1;
160 	timerec.tm_mday = (date >> 16) & 0x1f;
161 	timerec.tm_mon = (date >> 21) & 0x0f;
162 	timerec.tm_year = ((date >> 25) & 0x7f) + 80;
163 	timerec.tm_isdst = -1;
164 	tbuf.actime = tbuf.modtime = mktime(&timerec);
165 	utime(filename,&tbuf);
166 #endif
167 }
168 
dzUncompress(char * src)169 void dzUncompress (char *src)
170 {
171 	direntry_t *de;
172 	int i;
173 
174 	if (!dzOpen(src, 0))
175 		return;
176 	printf("%s created using v%u.%u\n", src, maj_ver, min_ver);
177 
178 	if (maj_ver == 1)
179 		dzUncompressV1(flag[SW_VERIFY]);
180 	else
181 	for (i = 0; i < numfiles; i += de->pak + 1)
182 	{
183 		de = directory + i;
184 		if (de->type == TYPE_DIR)
185 		{
186 			if (!flag[SW_VERIFY])
187 			{
188 				printf("creating %s\n", de->name);
189 				CreateDir(de);
190 			}
191 			continue;
192 		}
193 
194 		if (flag[SW_VERIFY])
195 		{
196 			dzExtractFile(i, 1);
197 			continue;
198 		}
199 
200 		outfile = open_create(de->name);
201 		if (!outfile)
202 			continue;
203 
204 		dzExtractFile(i, 0);
205 		fclose(outfile);
206 		if (AbortOp)
207 		{	/* problem writing file */
208 			remove(de->name);
209 			break;
210 		}
211 
212 		setfiledate(de->name, de->date);
213 	}
214 	printf("\n");
215 	dzClose();
216 }
217 #endif