PageRenderTime 64ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 1ms

/zfile.cpp

https://github.com/tonioni/WinUAE
C++ | 3521 lines | 3246 code | 238 blank | 37 comment | 1148 complexity | 4642264c93cd508c0e0245cc6d738082 MD5 | raw file
  1. /*
  2. * UAE - The Un*x Amiga Emulator
  3. *
  4. * routines to handle compressed file automatically
  5. *
  6. * (c) 1996 Samuel Devulder, Tim Gunn
  7. * 2002-2007 Toni Wilen
  8. */
  9. #define RECURSIVE_ARCHIVES 1
  10. //#define ZFILE_DEBUG
  11. #include "sysconfig.h"
  12. #include "sysdeps.h"
  13. #include "options.h"
  14. #include "zfile.h"
  15. #include "disk.h"
  16. #include "gui.h"
  17. #include "crc32.h"
  18. #include "fsdb.h"
  19. #include "fsusage.h"
  20. #include "zarchive.h"
  21. #include "diskutil.h"
  22. #include "fdi2raw.h"
  23. #include "uae/io.h"
  24. #include "archivers/zip/unzip.h"
  25. #include "archivers/dms/pfile.h"
  26. #include "archivers/wrp/warp.h"
  27. static struct zfile *zlist = 0;
  28. const TCHAR *uae_archive_extensions[] = { _T("zip"), _T("rar"), _T("7z"), _T("lha"), _T("lzh"), _T("lzx"), _T("tar"), NULL };
  29. #define MAX_CACHE_ENTRIES 10
  30. struct zdisktrack
  31. {
  32. void *data;
  33. int len;
  34. };
  35. struct zdiskimage
  36. {
  37. int tracks;
  38. struct zdisktrack zdisktracks[2 * 84];
  39. };
  40. struct zcache
  41. {
  42. TCHAR *name;
  43. struct zdiskimage *zd;
  44. void *data;
  45. int size;
  46. struct zcache *next;
  47. time_t tm;
  48. };
  49. static struct zcache *zcachedata;
  50. static struct zcache *cache_get (const TCHAR *name)
  51. {
  52. struct zcache *zc = zcachedata;
  53. while (zc) {
  54. if (!_tcscmp (name, zc->name)) {
  55. zc->tm = time (NULL);
  56. return zc;
  57. }
  58. zc = zc->next;
  59. }
  60. return NULL;
  61. }
  62. static void zcache_flush (void)
  63. {
  64. }
  65. static void zcache_free_data (struct zcache *zc)
  66. {
  67. int i;
  68. if (zc->zd) {
  69. for (i = 0; i < zc->zd->tracks; i++) {
  70. xfree (zc->zd->zdisktracks[i].data);
  71. }
  72. xfree (zc->zd);
  73. }
  74. xfree (zc->data);
  75. xfree (zc->name);
  76. }
  77. static void zcache_free (struct zcache *zc)
  78. {
  79. struct zcache *pl = NULL;
  80. struct zcache *l = zcachedata;
  81. struct zcache *nxt;
  82. while (l != zc) {
  83. if (l == 0)
  84. return;
  85. pl = l;
  86. l = l->next;
  87. }
  88. if (l)
  89. nxt = l->next;
  90. zcache_free_data (zc);
  91. if (l == 0)
  92. return;
  93. if(!pl)
  94. zcachedata = nxt;
  95. else
  96. pl->next = nxt;
  97. }
  98. static void zcache_close (void)
  99. {
  100. struct zcache *zc = zcachedata;
  101. while (zc) {
  102. struct zcache *n = zc->next;
  103. zcache_free_data (zc);
  104. xfree (n);
  105. zc = n;
  106. }
  107. }
  108. static void zcache_check (void)
  109. {
  110. int cnt = 0;
  111. struct zcache *zc = zcachedata, *last = NULL;
  112. while (zc) {
  113. last = zc;
  114. zc = zc->next;
  115. cnt++;
  116. }
  117. write_log (_T("CACHE: %d\n"), cnt);
  118. if (cnt >= MAX_CACHE_ENTRIES && last)
  119. zcache_free (last);
  120. }
  121. static struct zcache *zcache_put (const TCHAR *name, struct zdiskimage *data)
  122. {
  123. struct zcache *zc;
  124. zcache_check ();
  125. zc = xcalloc (struct zcache, 1);
  126. zc->next = zcachedata;
  127. zcachedata = zc;
  128. zc->zd = data;
  129. zc->name = my_strdup (name);
  130. zc->tm = time (NULL);
  131. return zc;
  132. }
  133. static void checkarchiveparent (struct zfile *z)
  134. {
  135. // unpack completely if opened in PEEK mode
  136. if (z->archiveparent)
  137. archive_unpackzfile (z);
  138. }
  139. static struct zfile *zfile_create (struct zfile *prev, const TCHAR *originalname)
  140. {
  141. struct zfile *z;
  142. z = xmalloc (struct zfile, 1);
  143. if (!z)
  144. return 0;
  145. memset (z, 0, sizeof *z);
  146. z->next = zlist;
  147. zlist = z;
  148. z->opencnt = 1;
  149. if (prev && prev->originalname)
  150. z->originalname = my_strdup(prev->originalname);
  151. else if (originalname)
  152. z->originalname = my_strdup(originalname);
  153. if (prev) {
  154. z->zfdmask = prev->zfdmask;
  155. }
  156. return z;
  157. }
  158. static void zfile_free (struct zfile *f)
  159. {
  160. if (f->f)
  161. fclose (f->f);
  162. if (f->deleteafterclose) {
  163. _wunlink (f->name);
  164. write_log (_T("deleted temporary file '%s'\n"), f->name);
  165. }
  166. xfree (f->name);
  167. xfree (f->originalname);
  168. xfree (f->data);
  169. xfree (f->mode);
  170. xfree (f->userdata);
  171. xfree (f);
  172. }
  173. void zfile_exit (void)
  174. {
  175. struct zfile *l;
  176. while ((l = zlist)) {
  177. zlist = l->next;
  178. zfile_free (l);
  179. }
  180. }
  181. void zfile_fclose (struct zfile *f)
  182. {
  183. //write_log (_T("%p\n"), f);
  184. if (!f)
  185. return;
  186. if (f->opencnt < 0) {
  187. write_log (_T("zfile: tried to free already closed filehandle!\n"));
  188. return;
  189. }
  190. f->opencnt--;
  191. if (f->opencnt > 0)
  192. return;
  193. f->opencnt = -100;
  194. if (f->parent) {
  195. f->parent->opencnt--;
  196. if (f->parent->opencnt <= 0)
  197. zfile_fclose (f->parent);
  198. }
  199. if (f->archiveparent) {
  200. zfile_fclose (f->archiveparent);
  201. f->archiveparent = NULL;
  202. }
  203. struct zfile *pl = NULL;
  204. struct zfile *nxt;
  205. struct zfile *l = zlist;
  206. while (l != f) {
  207. if (l == 0) {
  208. write_log (_T("zfile: tried to free already freed or nonexisting filehandle!\n"));
  209. return;
  210. }
  211. pl = l;
  212. l = l->next;
  213. }
  214. if (l)
  215. nxt = l->next;
  216. zfile_free (f);
  217. if (l == 0)
  218. return;
  219. if(!pl)
  220. zlist = nxt;
  221. else
  222. pl->next = nxt;
  223. }
  224. static void removeext (TCHAR *s, const TCHAR *ext)
  225. {
  226. if (_tcslen (s) < _tcslen (ext))
  227. return;
  228. if (_tcsicmp (s + _tcslen (s) - _tcslen (ext), ext) == 0)
  229. s[_tcslen (s) - _tcslen (ext)] = 0;
  230. }
  231. static bool checkwrite (struct zfile *zf, int *retcode)
  232. {
  233. if (zfile_needwrite (zf)) {
  234. if (retcode)
  235. *retcode = -1;
  236. return true;
  237. }
  238. return false;
  239. }
  240. static uae_u8 exeheader[]={ 0x00,0x00,0x03,0xf3,0x00,0x00,0x00,0x00 };
  241. static const TCHAR *diskimages[] = { _T("adf"), _T("adz"), _T("ipf"), _T("scp"), _T("fdi"), _T("dms"), _T("wrp"), _T("dsq"), _T("pkd"), _T("ima"), 0 };
  242. int zfile_gettype (struct zfile *z)
  243. {
  244. uae_u8 buf[8];
  245. TCHAR *ext;
  246. if (!z || !z->name)
  247. return ZFILE_UNKNOWN;
  248. ext = _tcsrchr (z->name, '.');
  249. if (ext != NULL) {
  250. int i;
  251. ext++;
  252. for (i = 0; diskimages[i]; i++) {
  253. if (strcasecmp (ext, diskimages[i]) == 0)
  254. return ZFILE_DISKIMAGE;
  255. }
  256. if (strcasecmp (ext, _T("roz")) == 0)
  257. return ZFILE_ROM;
  258. if (strcasecmp (ext, _T("uss")) == 0)
  259. return ZFILE_STATEFILE;
  260. if (strcasecmp (ext, _T("rom")) == 0)
  261. return ZFILE_ROM;
  262. if (strcasecmp (ext, _T("bin")) == 0)
  263. return ZFILE_ROM;
  264. if (strcasecmp (ext, _T("key")) == 0)
  265. return ZFILE_KEY;
  266. if (strcasecmp (ext, _T("nvr")) == 0)
  267. return ZFILE_NVR;
  268. if (strcasecmp (ext, _T("uae")) == 0)
  269. return ZFILE_CONFIGURATION;
  270. if (strcasecmp(ext, _T("cue")) == 0 || strcasecmp(ext, _T("iso")) == 0 || strcasecmp(ext, _T("ccd")) == 0 ||
  271. strcasecmp(ext, _T("mds")) == 0 || strcasecmp(ext, _T("chd")) == 0 || strcasecmp(ext, _T("nrg")) == 0)
  272. return ZFILE_CDIMAGE;
  273. }
  274. memset (buf, 0, sizeof (buf));
  275. zfile_fread (buf, 8, 1, z);
  276. zfile_fseek (z, -8, SEEK_CUR);
  277. if (!memcmp (buf, exeheader, sizeof (buf)))
  278. return ZFILE_DISKIMAGE;
  279. if (!memcmp (buf, "CAPS", 4))
  280. return ZFILE_DISKIMAGE;
  281. if (!memcmp (buf, "SCP", 3))
  282. return ZFILE_DISKIMAGE;
  283. if (!memcmp (buf, "UAE--ADF", 8))
  284. return ZFILE_DISKIMAGE;
  285. if (!memcmp (buf, "UAE-1ADF", 8))
  286. return ZFILE_DISKIMAGE;
  287. if (!memcmp (buf, "Formatte", 8))
  288. return ZFILE_DISKIMAGE;
  289. if (!memcmp (buf, "RDSK", 4))
  290. return ZFILE_HDFRDB;
  291. if (!memcmp (buf, "DOS", 3)) {
  292. if (z->size < 4 * 1024 * 1024)
  293. return ZFILE_DISKIMAGE;
  294. else
  295. return ZFILE_HDF;
  296. }
  297. if (ext != NULL) {
  298. if (strcasecmp (ext, _T("hdf")) == 0)
  299. return ZFILE_HDF;
  300. if (strcasecmp (ext, _T("hdz")) == 0)
  301. return ZFILE_HDF;
  302. if (strcasecmp (ext, _T("vhd")) == 0)
  303. return ZFILE_HDF;
  304. }
  305. return ZFILE_UNKNOWN;
  306. }
  307. #define VHD_DYNAMIC 3
  308. #define VHD_FIXED 2
  309. STATIC_INLINE uae_u32 gl (uae_u8 *p)
  310. {
  311. return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
  312. }
  313. static uae_u32 vhd_checksum (uae_u8 *p, int offset)
  314. {
  315. int i;
  316. uae_u32 sum;
  317. sum = 0;
  318. for (i = 0; i < 512; i++) {
  319. if (offset >= 0 && i >= offset && i < offset + 4)
  320. continue;
  321. sum += p[i];
  322. }
  323. return ~sum;
  324. }
  325. struct zfile_vhd
  326. {
  327. int vhd_type;
  328. uae_u64 virtsize;
  329. uae_u32 vhd_bamoffset;
  330. uae_u32 vhd_blocksize;
  331. uae_u8 *vhd_header, *vhd_sectormap;
  332. uae_u64 vhd_footerblock;
  333. uae_u32 vhd_bamsize;
  334. uae_u64 vhd_sectormapblock;
  335. uae_u32 vhd_bitmapsize;
  336. };
  337. static uae_u64 vhd_fread2 (struct zfile *zf, void *dataptrv, uae_u64 offset, uae_u64 len)
  338. {
  339. uae_u32 bamoffset;
  340. uae_u32 sectoroffset;
  341. uae_u64 read;
  342. struct zfile *zp = zf->parent;
  343. struct zfile_vhd *zvhd = (struct zfile_vhd*)zf->userdata;
  344. uae_u8 *dataptr = (uae_u8*)dataptrv;
  345. //write_log (_T("%08x %08x\n"), (uae_u32)offset, (uae_u32)len);
  346. read = 0;
  347. if (offset & 511)
  348. return read;
  349. if (len & 511)
  350. return read;
  351. while (len > 0) {
  352. bamoffset = (offset / zvhd->vhd_blocksize) * 4 + zvhd->vhd_bamoffset;
  353. sectoroffset = gl (zvhd->vhd_header + bamoffset);
  354. if (sectoroffset == 0xffffffff) {
  355. memset (dataptr, 0, 512);
  356. read += 512;
  357. } else {
  358. int bitmapoffsetbits;
  359. int bitmapoffsetbytes;
  360. int sectormapblock;
  361. bitmapoffsetbits = (offset / 512) % (zvhd->vhd_blocksize / 512);
  362. bitmapoffsetbytes = bitmapoffsetbits / 8;
  363. sectormapblock = sectoroffset * 512 + (bitmapoffsetbytes & ~511);
  364. if (zvhd->vhd_sectormapblock != sectormapblock) {
  365. // read sector bitmap
  366. //write_log (_T("BM %08x\n"), sectormapblock);
  367. zfile_fseek (zp, sectormapblock, SEEK_SET);
  368. if (zfile_fread (zvhd->vhd_sectormap, 1, 512, zp) != 512)
  369. return read;
  370. zvhd->vhd_sectormapblock = sectormapblock;
  371. }
  372. // block allocated in bitmap?
  373. if (zvhd->vhd_sectormap[bitmapoffsetbytes & 511] & (1 << (7 - (bitmapoffsetbits & 7)))) {
  374. // read data block
  375. int block = sectoroffset * 512 + zvhd->vhd_bitmapsize + bitmapoffsetbits * 512;
  376. //write_log (_T("DB %08x\n"), block);
  377. zfile_fseek (zp, block, SEEK_SET);
  378. if (zfile_fread (dataptr, 1, 512, zp) != 512)
  379. return read;
  380. } else {
  381. memset (dataptr, 0, 512);
  382. }
  383. read += 512;
  384. }
  385. len -= 512;
  386. dataptr += 512;
  387. offset += 512;
  388. }
  389. return read;
  390. }
  391. static uae_s64 vhd_fread (void *data, uae_u64 l1, uae_u64 l2, struct zfile *zf)
  392. {
  393. uae_u64 size = l1 * l2;
  394. uae_u64 out = 0;
  395. int len = 0;
  396. if (!l1 || !l2)
  397. return 0;
  398. if ((zf->seek & 511) || (size & 511)) {
  399. uae_u8 tmp[512];
  400. if (zf->seek & 511) {
  401. int s;
  402. s = 512 - (zf->seek & 511);
  403. vhd_fread2 (zf, tmp, zf->seek & ~511, 512);
  404. memcpy ((uae_u8*)data + len, tmp + 512 - s, s);
  405. len += s;
  406. out += s;
  407. zf->seek += s;
  408. }
  409. while (size > 0) {
  410. int s = size > 512 ? 512 : size;
  411. vhd_fread2 (zf, tmp, zf->seek, 512);
  412. memcpy ((uae_u8*)data + len, tmp, s);
  413. zf->seek += s;
  414. size -= s;
  415. out += s;
  416. }
  417. } else {
  418. out = vhd_fread2 (zf, data, zf->seek, size);
  419. zf->seek += out;
  420. out /= l1;
  421. }
  422. return out;
  423. }
  424. static struct zfile *vhd (struct zfile *z)
  425. {
  426. uae_u8 tmp[512], tmp2[512];
  427. uae_u32 v;
  428. struct zfile_vhd *zvhd;
  429. uae_u64 fsize;
  430. zvhd = xcalloc (struct zfile_vhd, 1);
  431. zfile_fseek (z, 0, SEEK_END);
  432. fsize = zfile_ftell (z);
  433. zfile_fseek (z, 0, SEEK_SET);
  434. if (zfile_fread (tmp, 1, 512, z) != 512)
  435. goto nonvhd;
  436. v = gl (tmp + 8); // features
  437. if ((v & 3) != 2)
  438. goto nonvhd;
  439. v = gl (tmp + 8 + 4); // version
  440. if ((v >> 16) != 1)
  441. goto nonvhd;
  442. zvhd->vhd_type = gl (tmp + 8 + 4 + 4 + 8 + 4 + 4 + 4 + 4 + 8 + 8 + 4);
  443. if (zvhd->vhd_type != VHD_FIXED && zvhd->vhd_type != VHD_DYNAMIC)
  444. goto nonvhd;
  445. v = gl (tmp + 8 + 4 + 4 + 8 + 4 + 4 + 4 + 4 + 8 + 8 + 4 + 4);
  446. if (v == 0)
  447. goto nonvhd;
  448. if (vhd_checksum (tmp, 8 + 4 + 4 + 8 + 4 + 4 + 4 + 4 + 8 + 8 + 4 + 4) != v)
  449. goto nonvhd;
  450. zfile_fseek (z, fsize - sizeof tmp2, SEEK_SET);
  451. if (zfile_fread (tmp2, 1, 512, z) != 512)
  452. goto end;
  453. if (memcmp (tmp, tmp2, sizeof tmp))
  454. goto nonvhd;
  455. zvhd->vhd_footerblock = fsize - 512;
  456. zvhd->virtsize = (uae_u64)(gl (tmp + 8 + 4 + 4 + 8 + 4 + 4 +4 + 4 + 8)) << 32;
  457. zvhd->virtsize |= gl (tmp + 8 + 4 + 4 + 8 + 4 + 4 +4 + 4 + 8 + 4);
  458. if (zvhd->vhd_type == VHD_DYNAMIC) {
  459. uae_u32 size;
  460. zvhd->vhd_bamoffset = gl (tmp + 8 + 4 + 4 + 4);
  461. if (zvhd->vhd_bamoffset == 0 || zvhd->vhd_bamoffset >= fsize)
  462. goto end;
  463. zfile_fseek (z, zvhd->vhd_bamoffset, SEEK_SET);
  464. if (zfile_fread (tmp, 1, 512, z) != 512)
  465. goto end;
  466. v = gl (tmp + 8 + 8 + 8 + 4 + 4 + 4);
  467. if (vhd_checksum (tmp, 8 + 8 + 8 + 4 + 4 + 4) != v)
  468. goto end;
  469. v = gl (tmp + 8 + 8 + 8);
  470. if ((v >> 16) != 1)
  471. goto end;
  472. zvhd->vhd_blocksize = gl (tmp + 8 + 8 + 8 + 4 + 4);
  473. zvhd->vhd_bamoffset = gl (tmp + 8 + 8 + 4);
  474. zvhd->vhd_bamsize = (((zvhd->virtsize + zvhd->vhd_blocksize - 1) / zvhd->vhd_blocksize) * 4 + 511) & ~511;
  475. size = zvhd->vhd_bamoffset + zvhd->vhd_bamsize;
  476. zvhd->vhd_header = xmalloc (uae_u8, size);
  477. zfile_fseek (z, 0, SEEK_SET);
  478. if (zfile_fread (zvhd->vhd_header, 1, size, z) != size)
  479. goto end;
  480. zvhd->vhd_sectormap = xmalloc (uae_u8, 512);
  481. zvhd->vhd_sectormapblock = -1;
  482. zvhd->vhd_bitmapsize = ((zvhd->vhd_blocksize / (8 * 512)) + 511) & ~511;
  483. }
  484. z = zfile_fopen_parent (z, NULL, 0, zvhd->virtsize);
  485. z->useparent = 0;
  486. z->dataseek = 1;
  487. z->userdata = zvhd;
  488. z->zfileread = vhd_fread;
  489. write_log (_T("%s is VHD %s image, virtual size=%lldK\n"),
  490. zfile_getname (z),
  491. zvhd->vhd_type == 2 ? _T("fixed") : _T("dynamic"),
  492. zvhd->virtsize / 1024);
  493. return z;
  494. nonvhd:
  495. end:
  496. return z;
  497. }
  498. static struct zfile *zfile_gunzip (struct zfile *z, int *retcode)
  499. {
  500. uae_u8 header[2 + 1 + 1 + 4 + 1 + 1];
  501. z_stream zs;
  502. int i, size, ret, first;
  503. uae_u8 flags;
  504. uae_s64 offset;
  505. TCHAR name[MAX_DPATH];
  506. uae_u8 buffer[8192];
  507. struct zfile *z2;
  508. uae_u8 b;
  509. if (checkwrite (z, retcode))
  510. return NULL;
  511. _tcscpy (name, z->name);
  512. memset (&zs, 0, sizeof (zs));
  513. memset (header, 0, sizeof (header));
  514. zfile_fread (header, sizeof (header), 1, z);
  515. flags = header[3];
  516. if (header[0] != 0x1f && header[1] != 0x8b)
  517. return NULL;
  518. if (flags & 2) /* multipart not supported */
  519. return NULL;
  520. if (flags & 32) /* encryption not supported */
  521. return NULL;
  522. if (flags & 4) { /* skip extra field */
  523. zfile_fread (&b, 1, 1, z);
  524. size = b;
  525. zfile_fread (&b, 1, 1, z);
  526. size |= b << 8;
  527. zfile_fseek (z, size + 2, SEEK_CUR);
  528. }
  529. if (flags & 8) { /* get original file name */
  530. uae_char aname[MAX_DPATH];
  531. i = 0;
  532. do {
  533. zfile_fread (aname + i, 1, 1, z);
  534. } while (i < MAX_DPATH - 1 && aname[i++]);
  535. aname[i] = 0;
  536. au_copy (name, MAX_DPATH, aname);
  537. }
  538. if (flags & 16) { /* skip comment */
  539. i = 0;
  540. do {
  541. b = 0;
  542. zfile_fread (&b, 1, 1, z);
  543. } while (b);
  544. }
  545. removeext (name, _T(".gz"));
  546. offset = zfile_ftell (z);
  547. zfile_fseek (z, -4, SEEK_END);
  548. zfile_fread (&b, 1, 1, z);
  549. size = b;
  550. zfile_fread (&b, 1, 1, z);
  551. size |= b << 8;
  552. zfile_fread (&b, 1, 1, z);
  553. size |= b << 16;
  554. zfile_fread (&b, 1, 1, z);
  555. size |= b << 24;
  556. if (size < 8 || size > 256 * 1024 * 1024) /* safety check */
  557. return NULL;
  558. zfile_fseek (z, offset, SEEK_SET);
  559. z2 = zfile_fopen_empty (z, name, size);
  560. if (!z2)
  561. return NULL;
  562. zs.next_out = z2->data;
  563. zs.avail_out = size;
  564. first = 1;
  565. ret = Z_STREAM_ERROR;
  566. do {
  567. zs.next_in = buffer;
  568. zs.avail_in = zfile_fread (buffer, 1, sizeof (buffer), z);
  569. if (first) {
  570. if (inflateInit2_ (&zs, -MAX_WBITS, ZLIB_VERSION, sizeof (z_stream)) != Z_OK)
  571. break;
  572. first = 0;
  573. }
  574. ret = inflate (&zs, 0);
  575. } while (ret == Z_OK);
  576. inflateEnd (&zs);
  577. if (ret != Z_STREAM_END || first != 0) {
  578. zfile_fclose (z2);
  579. return NULL;
  580. }
  581. zfile_fclose (z);
  582. return z2;
  583. }
  584. struct zfile *zfile_gunzip (struct zfile *z)
  585. {
  586. return zfile_gunzip (z, NULL);
  587. }
  588. static void truncate880k (struct zfile *z)
  589. {
  590. int i;
  591. uae_u8 *b;
  592. if (z == NULL || z->data == NULL)
  593. return;
  594. if (z->size < 880 * 512 * 2) {
  595. int size = 880 * 512 * 2 - z->size;
  596. b = xcalloc (uae_u8, size);
  597. zfile_fwrite (b, size, 1, z);
  598. xfree (b);
  599. return;
  600. }
  601. for (i = 880 * 512 * 2; i < z->size; i++) {
  602. if (z->data[i])
  603. return;
  604. }
  605. z->size = 880 * 512 * 2;
  606. }
  607. static struct zfile *extadf (struct zfile *z, int index, int *retcode)
  608. {
  609. int i, r;
  610. struct zfile *zo;
  611. uae_u16 *mfm;
  612. uae_u16 *amigamfmbuffer;
  613. uae_u8 writebuffer_ok[32], *outbuf;
  614. int tracks, len, offs, pos;
  615. uae_u8 buffer[2 + 2 + 4 + 4];
  616. int outsize;
  617. TCHAR newname[MAX_DPATH];
  618. TCHAR *ext;
  619. int cantrunc = 0;
  620. int done = 0;
  621. if (index > 1)
  622. return NULL;
  623. mfm = xcalloc (uae_u16, 32000 / 2);
  624. amigamfmbuffer = xcalloc (uae_u16, 32000 / 2);
  625. outbuf = xcalloc (uae_u8, 16384);
  626. zfile_fread (buffer, 1, 8, z);
  627. zfile_fread (buffer, 1, 4, z);
  628. tracks = buffer[2] * 256 + buffer[3];
  629. offs = 8 + 2 + 2 + tracks * (2 + 2 + 4 + 4);
  630. _tcscpy (newname, zfile_getname (z));
  631. ext = _tcsrchr (newname, '.');
  632. if (ext) {
  633. _tcscpy (newname + _tcslen (newname) - _tcslen (ext), _T(".std.adf"));
  634. } else {
  635. _tcscat (newname, _T(".std.adf"));
  636. }
  637. if (index > 0)
  638. _tcscpy (newname + _tcslen (newname) - 4, _T(".ima"));
  639. zo = zfile_fopen_empty (z, newname, 0);
  640. if (!zo)
  641. goto end;
  642. if (retcode)
  643. *retcode = 1;
  644. pos = 12;
  645. outsize = 0;
  646. for (i = 0; i < tracks; i++) {
  647. int type, bitlen;
  648. zfile_fseek (z, pos, SEEK_SET);
  649. zfile_fread (buffer, 2 + 2 + 4 + 4, 1, z);
  650. pos = zfile_ftell (z);
  651. type = buffer[2] * 256 + buffer[3];
  652. len = buffer[5] * 65536 + buffer[6] * 256 + buffer[7];
  653. bitlen = buffer[9] * 65536 + buffer[10] * 256 + buffer[11];
  654. zfile_fseek (z, offs, SEEK_SET);
  655. if (type == 1) {
  656. zfile_fread (mfm, len, 1, z);
  657. memset (writebuffer_ok, 0, sizeof writebuffer_ok);
  658. memset (outbuf, 0, 16384);
  659. if (index == 0) {
  660. r = isamigatrack (amigamfmbuffer, (uae_u8*)mfm, len, outbuf, writebuffer_ok, i, &outsize);
  661. if (r < 0 && i == 0) {
  662. zfile_seterror (_T("'%s' is not AmigaDOS formatted"), zo->name);
  663. goto end;
  664. }
  665. if (i == 0)
  666. done = 1;
  667. } else {
  668. r = ispctrack (amigamfmbuffer, (uae_u8*)mfm, len, outbuf, writebuffer_ok, i, &outsize);
  669. if (r < 0 && i == 0) {
  670. zfile_seterror (_T("'%s' is not PC formatted"), zo->name);
  671. goto end;
  672. }
  673. if (i == 0)
  674. done = 1;
  675. }
  676. } else {
  677. outsize = 512 * 11;
  678. if (bitlen / 8 > 18000)
  679. outsize *= 2;
  680. zfile_fread (outbuf, outsize, 1, z);
  681. cantrunc = 1;
  682. if (index == 0)
  683. done = 1;
  684. }
  685. zfile_fwrite (outbuf, outsize, 1, zo);
  686. offs += len;
  687. }
  688. if (done == 0)
  689. goto end;
  690. zfile_fclose (z);
  691. xfree (mfm);
  692. xfree (amigamfmbuffer);
  693. if (cantrunc)
  694. truncate880k (zo);
  695. return zo;
  696. end:
  697. zfile_fclose (zo);
  698. xfree (mfm);
  699. xfree (amigamfmbuffer);
  700. return NULL;
  701. }
  702. #include "fdi2raw.h"
  703. static struct zfile *fdi (struct zfile *z, int index, int *retcode)
  704. {
  705. int i, j, r;
  706. struct zfile *zo;
  707. TCHAR *orgname = zfile_getname (z);
  708. TCHAR *ext = _tcsrchr (orgname, '.');
  709. TCHAR newname[MAX_DPATH];
  710. uae_u16 *amigamfmbuffer;
  711. uae_u8 writebuffer_ok[32], *outbuf;
  712. int tracks, len, outsize;
  713. FDI *fdi;
  714. int startpos = 0;
  715. uae_u8 tmp[12];
  716. struct zcache *zc;
  717. if (checkwrite (z, retcode))
  718. return NULL;
  719. if (index > 2)
  720. return NULL;
  721. zc = cache_get (z->name);
  722. if (!zc) {
  723. uae_u16 *mfm;
  724. struct zdiskimage *zd;
  725. fdi = fdi2raw_header (z);
  726. if (!fdi)
  727. return NULL;
  728. mfm = xcalloc (uae_u16, 32000 / 2);
  729. zd = xcalloc (struct zdiskimage, 1);
  730. tracks = fdi2raw_get_last_track (fdi);
  731. zd->tracks = tracks;
  732. for (i = 0; i < tracks; i++) {
  733. uae_u8 *buf, *p;
  734. fdi2raw_loadtrack (fdi, mfm, NULL, i, &len, NULL, NULL, 1);
  735. len /= 8;
  736. buf = p = xmalloc (uae_u8, len);
  737. for (j = 0; j < len / 2; j++) {
  738. uae_u16 v = mfm[j];
  739. *p++ = v >> 8;
  740. *p++ = v;
  741. }
  742. zd->zdisktracks[i].data = buf;
  743. zd->zdisktracks[i].len = len;
  744. }
  745. fdi2raw_header_free (fdi);
  746. zc = zcache_put (z->name, zd);
  747. }
  748. amigamfmbuffer = xcalloc (uae_u16, 32000 / 2);
  749. outbuf = xcalloc (uae_u8, 16384);
  750. tracks = zc->zd->tracks;
  751. if (ext) {
  752. _tcscpy (newname, orgname);
  753. _tcscpy (newname + _tcslen (newname) - _tcslen (ext), _T(".adf"));
  754. } else {
  755. _tcscat (newname, _T(".adf"));
  756. }
  757. if (index == 1)
  758. _tcscpy (newname + _tcslen (newname) - 4, _T(".ima"));
  759. if (index == 2)
  760. _tcscpy (newname + _tcslen (newname) - 4, _T(".ext.adf"));
  761. zo = zfile_fopen_empty (z, newname, 0);
  762. if (!zo)
  763. goto end;
  764. if (retcode)
  765. *retcode = 1;
  766. if (index > 1) {
  767. zfile_fwrite ("UAE-1ADF", 8, 1, zo);
  768. tmp[0] = 0; tmp[1] = 0; /* flags (reserved) */
  769. tmp[2] = 0; tmp[3] = tracks; /* number of tracks */
  770. zfile_fwrite (tmp, 4, 1, zo);
  771. memset (tmp, 0, sizeof tmp);
  772. tmp[2] = 0; tmp[3] = 1; /* track type */
  773. startpos = zfile_ftell (zo);
  774. for (i = 0; i < tracks; i++)
  775. zfile_fwrite (tmp, sizeof tmp, 1, zo);
  776. }
  777. outsize = 0;
  778. for (i = 0; i < tracks; i++) {
  779. uae_u8 *p = (uae_u8*)zc->zd->zdisktracks[i].data;
  780. len = zc->zd->zdisktracks[i].len;
  781. memset (writebuffer_ok, 0, sizeof writebuffer_ok);
  782. memset (outbuf, 0, 16384);
  783. if (index == 0) {
  784. r = isamigatrack (amigamfmbuffer, p, len, outbuf, writebuffer_ok, i, &outsize);
  785. if (r < 0 && i == 0) {
  786. zfile_seterror (_T("'%s' is not AmigaDOS formatted"), orgname);
  787. goto end;
  788. }
  789. zfile_fwrite (outbuf, outsize, 1, zo);
  790. } else if (index == 1) {
  791. r = ispctrack (amigamfmbuffer, p, len, outbuf, writebuffer_ok, i, &outsize);
  792. if (r < 0 && i == 0) {
  793. zfile_seterror (_T("'%s' is not PC formatted"), orgname);
  794. goto end;
  795. }
  796. zfile_fwrite (outbuf, outsize, 1, zo);
  797. } else {
  798. int pos = zfile_ftell (zo);
  799. int maxlen = len > 12798 ? len : 12798;
  800. int lenb = len * 8;
  801. if (maxlen & 1)
  802. maxlen++;
  803. zfile_fseek (zo, startpos + i * 12 + 4, SEEK_SET);
  804. tmp[4] = 0; tmp[5] = 0; tmp[6] = maxlen >> 8; tmp[7] = maxlen;
  805. tmp[8] = lenb >> 24; tmp[9] = lenb >> 16; tmp[10] = lenb >> 8; tmp[11] = lenb;
  806. zfile_fwrite (tmp + 4, 2, 4, zo);
  807. zfile_fseek (zo, pos, SEEK_SET);
  808. zfile_fwrite (p, 1, len, zo);
  809. if (maxlen > len)
  810. zfile_fwrite (outbuf, 1, maxlen - len, zo);
  811. }
  812. }
  813. zfile_fclose (z);
  814. xfree (amigamfmbuffer);
  815. xfree (outbuf);
  816. if (index == 0)
  817. truncate880k (zo);
  818. return zo;
  819. end:
  820. zfile_fclose (zo);
  821. xfree (amigamfmbuffer);
  822. xfree (outbuf);
  823. return NULL;
  824. }
  825. #ifdef CAPS
  826. #include "caps/caps_win32.h"
  827. static struct zfile *ipf (struct zfile *z, int index, int *retcode)
  828. {
  829. int i, j, r;
  830. struct zfile *zo;
  831. TCHAR *orgname = zfile_getname (z);
  832. TCHAR *ext = _tcsrchr (orgname, '.');
  833. TCHAR newname[MAX_DPATH];
  834. uae_u16 *amigamfmbuffer;
  835. uae_u8 writebuffer_ok[32];
  836. int tracks, len;
  837. int outsize;
  838. int startpos = 0;
  839. uae_u8 *outbuf;
  840. uae_u8 tmp[12];
  841. struct zcache *zc;
  842. if (checkwrite (z, retcode))
  843. return NULL;
  844. if (index > 2)
  845. return NULL;
  846. zc = cache_get (z->name);
  847. if (!zc) {
  848. uae_u16 *mfm;
  849. struct zdiskimage *zd;
  850. if (!caps_loadimage (z, 0, &tracks))
  851. return NULL;
  852. mfm = xcalloc (uae_u16, 32000 / 2);
  853. zd = xcalloc (struct zdiskimage, 1);
  854. zd->tracks = tracks;
  855. for (i = 0; i < tracks; i++) {
  856. uae_u8 *buf, *p;
  857. int mrev, gapo;
  858. caps_loadtrack (mfm, NULL, 0, i, &len, &mrev, &gapo, NULL, true);
  859. //write_log (_T("%d: %d %d %d\n"), i, mrev, gapo, len);
  860. len /= 8;
  861. buf = p = xmalloc (uae_u8, len);
  862. for (j = 0; j < len / 2; j++) {
  863. uae_u16 v = mfm[j];
  864. *p++ = v >> 8;
  865. *p++ = v;
  866. }
  867. zd->zdisktracks[i].data = buf;
  868. zd->zdisktracks[i].len = len;
  869. }
  870. caps_unloadimage (0);
  871. zc = zcache_put (z->name, zd);
  872. }
  873. outbuf = xcalloc (uae_u8, 16384);
  874. amigamfmbuffer = xcalloc (uae_u16, 32000 / 2);
  875. if (ext) {
  876. _tcscpy (newname, orgname);
  877. _tcscpy (newname + _tcslen (newname) - _tcslen (ext), _T(".adf"));
  878. } else {
  879. _tcscat (newname, _T(".adf"));
  880. }
  881. if (index == 1)
  882. _tcscpy (newname + _tcslen (newname) - 4, _T(".ima"));
  883. if (index == 2)
  884. _tcscpy (newname + _tcslen (newname) - 4, _T(".ext.adf"));
  885. zo = zfile_fopen_empty (z, newname, 0);
  886. if (!zo)
  887. goto end;
  888. if (retcode)
  889. *retcode = 1;
  890. tracks = zc->zd->tracks;
  891. if (index > 1) {
  892. zfile_fwrite ("UAE-1ADF", 8, 1, zo);
  893. tmp[0] = 0; tmp[1] = 0; /* flags (reserved) */
  894. tmp[2] = 0; tmp[3] = tracks; /* number of tracks */
  895. zfile_fwrite (tmp, 4, 1, zo);
  896. memset (tmp, 0, sizeof tmp);
  897. tmp[2] = 0; tmp[3] = 1; /* track type */
  898. startpos = zfile_ftell (zo);
  899. for (i = 0; i < tracks; i++)
  900. zfile_fwrite (tmp, sizeof tmp, 1, zo);
  901. }
  902. outsize = 0;
  903. for (i = 0; i < tracks; i++) {
  904. uae_u8 *p = (uae_u8*)zc->zd->zdisktracks[i].data;
  905. len = zc->zd->zdisktracks[i].len;
  906. memset (writebuffer_ok, 0, sizeof writebuffer_ok);
  907. memset (outbuf, 0, 16384);
  908. if (index == 0) {
  909. r = isamigatrack (amigamfmbuffer, p, len, outbuf, writebuffer_ok, i, &outsize);
  910. if (r < 0 && i == 0) {
  911. zfile_seterror (_T("'%s' is not AmigaDOS formatted"), orgname);
  912. goto end;
  913. }
  914. zfile_fwrite (outbuf, 1, outsize, zo);
  915. } else if (index == 1) {
  916. r = ispctrack (amigamfmbuffer, p, len, outbuf, writebuffer_ok, i, &outsize);
  917. if (r < 0 && i == 0) {
  918. zfile_seterror (_T("'%s' is not PC formatted"), orgname);
  919. goto end;
  920. }
  921. zfile_fwrite (outbuf, outsize, 1, zo);
  922. } else {
  923. int pos = zfile_ftell (zo);
  924. int maxlen = len > 12798 ? len : 12798;
  925. int lenb = len * 8;
  926. if (maxlen & 1)
  927. maxlen++;
  928. zfile_fseek (zo, startpos + i * 12 + 4, SEEK_SET);
  929. tmp[4] = 0; tmp[5] = 0; tmp[6] = maxlen >> 8; tmp[7] = maxlen;
  930. tmp[8] = lenb >> 24; tmp[9] = lenb >> 16; tmp[10] = lenb >> 8; tmp[11] = lenb;
  931. zfile_fwrite (tmp + 4, 2, 4, zo);
  932. zfile_fseek (zo, pos, SEEK_SET);
  933. zfile_fwrite (p, 1, len, zo);
  934. if (maxlen > len)
  935. zfile_fwrite (outbuf, 1, maxlen - len, zo);
  936. }
  937. }
  938. zfile_fclose (z);
  939. xfree (amigamfmbuffer);
  940. xfree (outbuf);
  941. if (index == 0)
  942. truncate880k (zo);
  943. return zo;
  944. end:
  945. zfile_fclose (zo);
  946. xfree (amigamfmbuffer);
  947. xfree (outbuf);
  948. return NULL;
  949. }
  950. #endif
  951. #ifdef A_LZX
  952. static struct zfile *dsq (struct zfile *z, int lzx, int *retcode)
  953. {
  954. struct zfile *zi = NULL;
  955. struct zvolume *zv = NULL;
  956. if (checkwrite (z, retcode))
  957. return NULL;
  958. if (lzx) {
  959. zv = archive_directory_lzx (z);
  960. if (zv) {
  961. if (zv->root.child)
  962. zi = archive_access_lzx (zv->root.child);
  963. }
  964. } else {
  965. zi = z;
  966. }
  967. if (zi) {
  968. uae_u8 *buf = zfile_getdata (zi, 0, -1, NULL);
  969. if (!memcmp (buf, "PKD\x13", 4) || !memcmp (buf, "PKD\x11", 4)) {
  970. TCHAR *fn;
  971. int sectors = buf[18];
  972. int reserved = buf[15];
  973. int blocks = (buf[6] << 8) | buf[7];
  974. int blocksize = (buf[10] << 8) | buf[11];
  975. struct zfile *zo;
  976. int size = blocks * blocksize;
  977. int off;
  978. int i;
  979. uae_u8 *bitmap = NULL;
  980. uae_u8 *nullsector;
  981. nullsector = xcalloc (uae_u8, blocksize);
  982. sectors /= 2;
  983. if (buf[3] == 0x13) {
  984. off = 52;
  985. if (buf[off - 1] == 1) {
  986. bitmap = &buf[off];
  987. off += (blocks + 7) / 8;
  988. } else if (buf[off - 1] > 1) {
  989. write_log (_T("unknown DSQ extra header type %d\n"), buf[off - 1]);
  990. }
  991. } else {
  992. off = 32;
  993. }
  994. // some Amiga disk images are smaller than full adf for some reason
  995. if (sectors == 11 && size < 1760 * 512)
  996. size = 1760 * 512;
  997. if (zfile_getfilename (zi) && _tcslen (zfile_getfilename (zi))) {
  998. fn = xmalloc (TCHAR, (_tcslen (zfile_getfilename (zi)) + 5));
  999. _tcscpy (fn, zfile_getfilename (zi));
  1000. _tcscat (fn, _T(".adf"));
  1001. } else {
  1002. fn = my_strdup (_T("dsq.adf"));
  1003. }
  1004. zo = zfile_fopen_empty (z, fn, size);
  1005. xfree (fn);
  1006. int seccnt = 0;
  1007. for (i = 0; i < blocks; i++) {
  1008. int bmoff = i - 2;
  1009. int boff = -1;
  1010. uae_u32 mask = 0;
  1011. if (bitmap) {
  1012. boff = (bmoff / 32) * 4;
  1013. mask = (bitmap[boff] << 24) | (bitmap[boff + 1] << 16) | (bitmap[boff + 2] << 8) | (bitmap[boff + 3]);
  1014. }
  1015. if (bmoff >= 0 && boff >= 0 && (mask & (1 << (bmoff & 31)))) {
  1016. zfile_fwrite (nullsector, blocksize, 1, zo);
  1017. } else {
  1018. zfile_fwrite (buf + off, blocksize, 1, zo);
  1019. off += blocksize;
  1020. seccnt++;
  1021. }
  1022. if ((i % sectors) == sectors - 1) {
  1023. off += seccnt * 16;
  1024. seccnt = 0;
  1025. }
  1026. }
  1027. zfile_fclose_archive (zv);
  1028. zfile_fclose (z);
  1029. xfree (buf);
  1030. xfree (nullsector);
  1031. return zo;
  1032. }
  1033. xfree (buf);
  1034. }
  1035. if (lzx)
  1036. zfile_fclose (zi);
  1037. return z;
  1038. }
  1039. #endif
  1040. #ifdef A_WRP
  1041. static struct zfile *wrp (struct zfile *z, int *retcode)
  1042. {
  1043. if (zfile_needwrite (z)) {
  1044. if (retcode)
  1045. *retcode = -1;
  1046. return NULL;
  1047. }
  1048. return unwarp (z);
  1049. }
  1050. #endif
  1051. #ifdef A_7Z
  1052. #include "7z/Xz.h"
  1053. #include "7z/Lzmadec.h"
  1054. #include "7z/7zCrc.h"
  1055. static void *SzAlloc (void *p, size_t size)
  1056. {
  1057. return xmalloc (uae_u8, size);
  1058. }
  1059. static void SzFree(void *p, void *address)
  1060. {
  1061. xfree (address);
  1062. }
  1063. #define XZ_OUT_SIZE 10000
  1064. #define XZ_IN_SIZE 10000
  1065. static struct zfile *xz (struct zfile *z, int *retcode)
  1066. {
  1067. static bool iscrc;
  1068. ISzAlloc allocImp;
  1069. CXzUnpacker cx;
  1070. ECoderStatus status;
  1071. struct zfile *zo = NULL;
  1072. uae_u8 out[XZ_OUT_SIZE], in[XZ_IN_SIZE];
  1073. if (checkwrite (z, retcode))
  1074. return NULL;
  1075. memset (&cx, 0, sizeof cx);
  1076. allocImp.Alloc = SzAlloc;
  1077. allocImp.Free = SzFree;
  1078. if (!iscrc)
  1079. CrcGenerateTable ();
  1080. iscrc = true;
  1081. // if (XzUnpacker_Create (&cx, &allocImp) != SZ_OK)
  1082. // return NULL;
  1083. XzUnpacker_Construct (&cx, &allocImp);
  1084. int outwritten = 0;
  1085. int towrite = 0;
  1086. bool first = true;
  1087. for (;;) {
  1088. int read = zfile_fread (in, 1, XZ_IN_SIZE, z);
  1089. if (first) {
  1090. if (!(in[0] == 0xfd && in[1] == 0x37 && in[2] == 0x7a && in[3] == 0x58 && in[4] == 0x5a && in[5] == 0))
  1091. break;
  1092. }
  1093. first = false;
  1094. if (read == 0)
  1095. break;
  1096. if (read < 0) {
  1097. zfile_fclose (zo);
  1098. zo = NULL;
  1099. break;
  1100. }
  1101. if (!zo)
  1102. zo = zfile_fopen_empty (z, z->name);
  1103. if (!zo)
  1104. break;
  1105. uae_u8 *inp = in;
  1106. for (;;) {
  1107. SizeT srclen = read;
  1108. SizeT outlen = XZ_OUT_SIZE;
  1109. if (XzUnpacker_Code (&cx, out, &outlen, inp, &srclen, LZMA_FINISH_ANY, &status) != SZ_OK) {
  1110. zfile_fclose (zo);
  1111. zo = NULL;
  1112. break;
  1113. }
  1114. if (status != CODER_STATUS_NEEDS_MORE_INPUT && status != CODER_STATUS_NOT_FINISHED) {
  1115. zfile_fclose (zo);
  1116. zo = NULL;
  1117. break;
  1118. }
  1119. zfile_fwrite (out, outlen, 1, zo);
  1120. if (status == CODER_STATUS_FINISHED_WITH_MARK)
  1121. break;
  1122. if (srclen == read)
  1123. break;
  1124. inp += srclen;
  1125. read -= srclen;
  1126. }
  1127. }
  1128. XzUnpacker_Free (&cx);
  1129. return zo;
  1130. }
  1131. #endif
  1132. #ifdef A_DMS
  1133. static struct zfile *dms (struct zfile *z, int index, int *retcode)
  1134. {
  1135. int ret;
  1136. struct zfile *zo;
  1137. TCHAR *orgname = zfile_getname (z);
  1138. TCHAR *ext = _tcsrchr (orgname, '.');
  1139. TCHAR newname[MAX_DPATH];
  1140. static int recursive;
  1141. int i;
  1142. struct zfile *zextra[DMS_EXTRA_SIZE] = { 0 };
  1143. if (checkwrite (z, retcode))
  1144. return NULL;
  1145. if (recursive)
  1146. return NULL;
  1147. if (ext) {
  1148. _tcscpy (newname, orgname);
  1149. _tcscpy (newname + _tcslen (newname) - _tcslen (ext), _T(".adf"));
  1150. } else {
  1151. _tcscat (newname, _T(".adf"));
  1152. }
  1153. zo = zfile_fopen_empty (z, newname, 1760 * 512);
  1154. if (!zo)
  1155. return NULL;
  1156. ret = DMS_Process_File (z, zo, CMD_UNPACK, OPT_VERBOSE, 0, 0, 0, zextra);
  1157. if (ret == NO_PROBLEM || ret == DMS_FILE_END) {
  1158. int off = zfile_ftell (zo);
  1159. if (off >= 1760 * 512 / 3 && off <= 1760 * 512 * 3 / 4) { // possible split dms?
  1160. if (_tcslen (orgname) > 5) {
  1161. TCHAR *s = orgname + _tcslen (orgname) - 5;
  1162. if (!_tcsicmp (s, _T("a.dms"))) {
  1163. TCHAR *fn2 = my_strdup (orgname);
  1164. struct zfile *z2;
  1165. fn2[_tcslen (fn2) - 5]++;
  1166. recursive++;
  1167. z2 = zfile_fopen (fn2, _T("rb"), z->zfdmask);
  1168. recursive--;
  1169. if (z2) {
  1170. ret = DMS_Process_File (z2, zo, CMD_UNPACK, OPT_VERBOSE, 0, 0, 1, NULL);
  1171. zfile_fclose (z2);
  1172. }
  1173. xfree (fn2);
  1174. }
  1175. }
  1176. }
  1177. zfile_fseek (zo, 0, SEEK_SET);
  1178. if (index > 0) {
  1179. zfile_fclose (zo);
  1180. zo = NULL;
  1181. for (i = 0; i < DMS_EXTRA_SIZE && zextra[i]; i++);
  1182. if (index > i)
  1183. goto end;
  1184. zo = zextra[index - 1];
  1185. zextra[index - 1] = NULL;
  1186. }
  1187. if (retcode)
  1188. *retcode = 1;
  1189. zfile_fclose (z);
  1190. z = NULL;
  1191. } else {
  1192. zfile_fclose (zo);
  1193. zo = NULL;
  1194. }
  1195. end:
  1196. for (i = 0; i < DMS_EXTRA_SIZE; i++)
  1197. zfile_fclose (zextra[i]);
  1198. return zo;
  1199. }
  1200. #endif
  1201. const TCHAR *uae_ignoreextensions[] =
  1202. { _T(".gif"), _T(".jpg"), _T(".png"), _T(".xml"), _T(".pdf"), _T(".txt"), 0 };
  1203. const TCHAR *uae_diskimageextensions[] =
  1204. { _T(".adf"), _T(".adz"), _T(".ipf"), _T(".scp"), _T(".fdi"), _T(".exe"), _T(".dms"), _T(".wrp"), _T(".dsq"), 0 };
  1205. int zfile_is_ignore_ext (const TCHAR *name)
  1206. {
  1207. int i;
  1208. const TCHAR *ext;
  1209. ext = _tcsrchr (name, '.');
  1210. if (!ext)
  1211. return 0;
  1212. for (i = 0; uae_ignoreextensions[i]; i++) {
  1213. if (!strcasecmp (uae_ignoreextensions[i], ext))
  1214. return 1;
  1215. }
  1216. return 0;
  1217. }
  1218. int zfile_is_diskimage (const TCHAR *name)
  1219. {
  1220. int i;
  1221. const TCHAR *ext = _tcsrchr (name, '.');
  1222. if (!ext)
  1223. return 0;
  1224. i = 0;
  1225. while (uae_diskimageextensions[i]) {
  1226. if (!strcasecmp (ext, uae_diskimageextensions[i]))
  1227. return HISTORY_FLOPPY;
  1228. i++;
  1229. }
  1230. if (!_tcsicmp (ext, _T(".cue")))
  1231. return HISTORY_CD;
  1232. return -1;
  1233. }
  1234. static const TCHAR *archive_extensions[] = {
  1235. _T("7z"), _T("rar"), _T("zip"), _T("lha"), _T("lzh"), _T("lzx"),
  1236. _T("adf"), _T("adz"), _T("dsq"), _T("dms"), _T("ipf"), _T("fdi"), _T("wrp"), _T("ima"),
  1237. _T("hdf"), _T("tar"),
  1238. NULL
  1239. };
  1240. static const TCHAR *plugins_7z[] = { _T("7z"), _T("rar"), _T("zip"), _T("lha"), _T("lzh"), _T("lzx"), _T("adf"), _T("dsq"), _T("hdf"), _T("tar"), NULL };
  1241. #if defined(ARCHIVEACCESS)
  1242. static const uae_char *plugins_7z_x[] = { "7z", "Rar!", "MK", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  1243. #endif
  1244. static const int plugins_7z_t[] = {
  1245. ArchiveFormat7Zip, ArchiveFormatRAR, ArchiveFormatZIP, ArchiveFormatLHA, ArchiveFormatLHA, ArchiveFormatLZX,
  1246. ArchiveFormatADF, ArchiveFormatADF, ArchiveFormatADF, ArchiveFormatTAR
  1247. };
  1248. static const int plugins_7z_m[] = {
  1249. ZFD_ARCHIVE, ZFD_ARCHIVE, ZFD_ARCHIVE, ZFD_ARCHIVE, ZFD_ARCHIVE, ZFD_ARCHIVE,
  1250. ZFD_ADF, ZFD_ADF, ZFD_ADF, ZFD_ARCHIVE
  1251. };
  1252. static int iszip (struct zfile *z, int mask)
  1253. {
  1254. TCHAR *name = z->name;
  1255. TCHAR *ext = _tcsrchr (name, '.');
  1256. uae_u8 header[32];
  1257. if (!ext)
  1258. return 0;
  1259. memset (header, 0, sizeof (header));
  1260. zfile_fseek (z, 0, SEEK_SET);
  1261. zfile_fread (header, sizeof (header), 1, z);
  1262. zfile_fseek (z, 0, SEEK_SET);
  1263. if (mask & ZFD_ARCHIVE) {
  1264. if (!strcasecmp (ext, _T(".zip")) || !strcasecmp (ext, _T(".rp9"))) {
  1265. if (header[0] == 'P' && header[1] == 'K')
  1266. return ArchiveFormatZIP;
  1267. return 0;
  1268. }
  1269. }
  1270. if (mask & ZFD_ARCHIVE) {
  1271. if (!strcasecmp (ext, _T(".7z"))) {
  1272. if (header[0] == '7' && header[1] == 'z')
  1273. return ArchiveFormat7Zip;
  1274. return 0;
  1275. }
  1276. if (!strcasecmp (ext, _T(".rar"))) {
  1277. if (header[0] == 'R' && header[1] == 'a' && header[2] == 'r' && header[3] == '!')
  1278. return ArchiveFormatRAR;
  1279. return 0;
  1280. }
  1281. if (!strcasecmp (ext, _T(".lha")) || !strcasecmp (ext, _T(".lzh"))) {
  1282. if (header[2] == '-' && header[3] == 'l' && header[4] == 'h' && header[6] == '-')
  1283. return ArchiveFormatLHA;
  1284. return 0;
  1285. }
  1286. if (!strcasecmp (ext, _T(".lzx"))) {
  1287. if (header[0] == 'L' && header[1] == 'Z' && header[2] == 'X')
  1288. return ArchiveFormatLZX;
  1289. return 0;
  1290. }
  1291. }
  1292. if (mask & ZFD_ADF) {
  1293. if (!strcasecmp (ext, _T(".adf"))) {
  1294. if (header[0] == 'D' && header[1] == 'O' && header[2] == 'S' && (header[3] >= 0 && header[3] <= 7))
  1295. return ArchiveFormatADF;
  1296. if (isfat (header))
  1297. return ArchiveFormatFAT;
  1298. return 0;
  1299. }
  1300. if (!strcasecmp (ext, _T(".ima"))) {
  1301. if (isfat (header))
  1302. return ArchiveFormatFAT;
  1303. }
  1304. }
  1305. if (mask & ZFD_HD) {
  1306. if (!strcasecmp (ext, _T(".hdf"))) {
  1307. if (header[0] == 'D' && header[1] == 'O' && header[2] == 'S' && (header[3] >= 0 && header[3] <= 7))
  1308. return ArchiveFormatADF;
  1309. if (header[0] == 'S' && header[1] == 'F' && header[2] == 'S')
  1310. return ArchiveFormatADF;
  1311. if (header[0] == 'R' && header[1] == 'D' && header[2] == 'S' && header[3] == 'K')
  1312. return ArchiveFormatRDB;
  1313. if (isfat (header))
  1314. return ArchiveFormatFAT;
  1315. return 0;
  1316. }
  1317. }
  1318. #if defined(ARCHIVEACCESS)
  1319. for (int i = 0; plugins_7z_x[i]; i++) {
  1320. if ((plugins_7z_m[i] & mask) && plugins_7z_x[i] && !strcasecmp (ext + 1, plugins_7z[i]) &&
  1321. !memcmp (header, plugins_7z_x[i], strlen (plugins_7z_x[i])))
  1322. return plugins_7z_t[i];
  1323. }
  1324. #endif
  1325. return 0;
  1326. }
  1327. int iszip (struct zfile *z)
  1328. {
  1329. return iszip (z, ZFD_NORMAL);
  1330. }
  1331. struct zfile *zuncompress (struct znode *parent, struct zfile *z, int dodefault, int mask, int *retcode, int index)
  1332. {
  1333. TCHAR *name = z->name;
  1334. TCHAR *ext = NULL;
  1335. uae_u8 header[32];
  1336. if (retcode)
  1337. *retcode = 0;
  1338. if (!mask)
  1339. return NULL;
  1340. if (name) {
  1341. ext = _tcsrchr (name, '.');
  1342. if (ext)
  1343. ext++;
  1344. }
  1345. if (ext != NULL) {
  1346. if (mask & ZFD_ARCHIVE) {
  1347. if (strcasecmp (ext, _T("7z")) == 0)
  1348. return archive_access_select (parent, z, ArchiveFormat7Zip, dodefault, retcode, index);
  1349. if (strcasecmp (ext, _T("zip")) == 0)
  1350. return archive_access_select (parent, z, ArchiveFormatZIP, dodefault, retcode, index);
  1351. if (strcasecmp (ext, _T("lha")) == 0 || strcasecmp (ext, _T("lzh")) == 0)
  1352. return archive_access_select (parent, z, ArchiveFormatLHA, dodefault, retcode, index);
  1353. if (strcasecmp (ext, _T("lzx")) == 0)
  1354. return archive_access_select (parent, z, ArchiveFormatLZX, dodefault, retcode, index);
  1355. if (strcasecmp (ext, _T("rar")) == 0)
  1356. return archive_access_select (parent, z, ArchiveFormatRAR, dodefault, retcode, index);
  1357. if (strcasecmp (ext, _T("tar")) == 0)
  1358. return archive_access_select (parent, z, ArchiveFormatTAR, dodefault, retcode, index);
  1359. }
  1360. if (mask & ZFD_UNPACK) {
  1361. if (index == 0) {
  1362. if (strcasecmp (ext, _T("gz")) == 0)
  1363. return zfile_gunzip (z, retcode);
  1364. if (strcasecmp (ext, _T("adz")) == 0)
  1365. return zfile_gunzip (z, retcode);
  1366. if (strcasecmp (ext, _T("roz")) == 0)
  1367. return zfile_gunzip (z, retcode);
  1368. if (strcasecmp (ext, _T("hdz")) == 0)
  1369. return zfile_gunzip (z, retcode);
  1370. #ifdef A_WRP
  1371. if (strcasecmp (ext, _T("wrp")) == 0)
  1372. return wrp (z, retcode);
  1373. #endif
  1374. #ifdef A_7Z
  1375. if (strcasecmp (ext, _T("xz")) == 0)
  1376. return xz (z, retcode);
  1377. #endif
  1378. }
  1379. #ifdef A_DMS
  1380. if (strcasecmp (ext, _T("dms")) == 0)
  1381. return dms (z, index, retcode);
  1382. #endif
  1383. }
  1384. if (mask & ZFD_RAWDISK) {
  1385. #ifdef CAPS
  1386. if (strcasecmp (ext, _T("ipf")) == 0)
  1387. return ipf (z, index, retcode);
  1388. #endif
  1389. if (strcasecmp (ext, _T("fdi")) == 0)
  1390. return fdi (z, index, retcode);
  1391. if (mask & (ZFD_RAWDISK_PC | ZFD_RAWDISK_AMIGA))
  1392. return NULL;
  1393. }
  1394. #if defined(ARCHIVEACCESS)
  1395. if (index == 0) {
  1396. for (int i = 0; plugins_7z_x[i]; i++) {
  1397. if ((plugins_7z_t[i] & mask) && strcasecmp (ext, plugins_7z[i]) == 0)
  1398. return archive_access_arcacc_select (z, plugins_7z_t[i], retcode);
  1399. }
  1400. }
  1401. #endif
  1402. }
  1403. memset (header, 0, sizeof (header));
  1404. zfile_fseek (z, 0, SEEK_SET);
  1405. zfile_fread (header, sizeof (header), 1, z);
  1406. zfile_fseek (z, 0, SEEK_SET);
  1407. if (!memcmp (header, "conectix", 8)) {
  1408. if (index > 0)
  1409. return NULL;
  1410. return vhd (z);
  1411. }
  1412. if (mask & ZFD_UNPACK) {
  1413. if (index == 0) {
  1414. if (header[0] == 0x1f && header[1] == 0x8b)
  1415. return zfile_gunzip (z, retcode);
  1416. #ifdef A_LZX
  1417. if (header[0] == 'P' && header[1] == 'K' && header[2] == 'D')
  1418. return dsq (z, 0, retcode);
  1419. #endif
  1420. #ifdef A_7Z
  1421. if (header[0] == 0xfd && header[1] == 0x37 && header[2] == 0x7a && header[3] == 0x58 && header[4] == 0x5a && header[5] == 0)
  1422. return xz (z, retcode);
  1423. #endif
  1424. }
  1425. #ifdef A_DMS
  1426. if (header[0] == 'D' && header[1] == 'M' && header[2] == 'S' && header[3] == '!')
  1427. return dms (z, index, retcode);
  1428. #endif
  1429. }
  1430. if (mask & ZFD_RAWDISK) {
  1431. #ifdef CAPS
  1432. if (header[0] == 'C' && header[1] == 'A' && header[2] == 'P' && header[3] == 'S')
  1433. return ipf (z, index, retcode);
  1434. #endif
  1435. if (!memcmp (header, "Formatte", 8))
  1436. return fdi (z, index, retcode);
  1437. if (!memcmp (header, "UAE-1ADF", 8))
  1438. return extadf (z, index, retcode);
  1439. }
  1440. if (index > 0)
  1441. return NULL;
  1442. if (mask & ZFD_ARCHIVE) {
  1443. if (header[0] == 'P' && header[1] == 'K')
  1444. return archive_access_select (parent, z, ArchiveFormatZIP, dodefault, retcode, index);
  1445. if (header[0] == 'R' && header[1] == 'a' && header[2] == 'r' && header[3] == '!')
  1446. return archive_access_select (parent, z, ArchiveFormatRAR, dodefault, retcode, index);
  1447. if (header[0] == 'L' && header[1] == 'Z' && header[2] == 'X')
  1448. return archive_access_select (parent, z, ArchiveFormatLZX, dodefault, retcode, index);
  1449. if (header[2] == '-' && header[3] == 'l' && header[4] == 'h' && header[6] == '-')
  1450. return archive_access_select (parent, z, ArchiveFormatLHA, dodefault, retcode, index);
  1451. }
  1452. if (mask & ZFD_ADF) {
  1453. if (header[0] == 'D' && header[1] == 'O' && header[2] == 'S' && (header[3] >= 0 && header[3] <= 7))
  1454. return archive_access_select (parent, z, ArchiveFormatADF, dodefault, retcode, index);
  1455. if (header[0] == 'S' && header[1] == 'F' && header[2] == 'S')
  1456. return archive_access_select (parent, z, ArchiveFormatADF, dodefault, retcode, index);
  1457. if (isfat (header))
  1458. return archive_access_select (parent, z, ArchiveFormatFAT, dodefault, retcode, index);
  1459. }
  1460. if (ext) {
  1461. if (mask & ZFD_UNPACK) {
  1462. #ifdef A_LZX
  1463. if (strcasecmp (ext, _T("dsq")) == 0)
  1464. return dsq (z, 1, retcode);
  1465. #endif
  1466. }
  1467. if (mask & ZFD_ADF) {
  1468. if (strcasecmp (ext, _T("adf")) == 0 && !memcmp (header, "DOS", 3))
  1469. return archive_access_select (parent, z, ArchiveFormatADF, dodefault, retcode, index);
  1470. }
  1471. }
  1472. return NULL;
  1473. }
  1474. #ifdef SINGLEFILE
  1475. extern uae_u8 singlefile_data[];
  1476. static struct zfile *zfile_opensinglefile(struct zfile *l)
  1477. {
  1478. uae_u8 *p = singlefile_data;
  1479. int size, offset;
  1480. TCHAR tmp[256], *s;
  1481. _tcscpy (tmp, l->name);
  1482. s = tmp + _tcslen (tmp) - 1;
  1483. while (*s != 0 && *s != '/' && *s != '\\')
  1484. s--;
  1485. if (s > tmp)
  1486. s++;
  1487. write_log (_T("loading from singlefile: '%s'\n"), tmp);
  1488. while (*p++);
  1489. offset = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|(p[3] << 0);
  1490. p += 4;
  1491. for (;;) {
  1492. size = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|(p[3] << 0);
  1493. if (!size)
  1494. break;
  1495. if (!strcmpi (tmp, p + 4)) {
  1496. l->data = singlefile_data + offset;
  1497. l->size = size;
  1498. write_log (_T("found, size %d\n"), size);
  1499. return l;
  1500. }
  1501. offset += size;
  1502. p += 4;
  1503. p += _tcslen (p) + 1;
  1504. }
  1505. write_log (_T("not found\n"));
  1506. return 0;
  1507. }
  1508. #endif
  1509. static struct zfile *zfile_fopen_nozip (const TCHAR *name, const TCHAR *mode)
  1510. {
  1511. struct zfile *l;
  1512. FILE *f;
  1513. if(*name == '\0')
  1514. return NULL;
  1515. l = zfile_create (NULL, name);
  1516. l->name = my_strdup (name);
  1517. l->mode = my_strdup (mode);
  1518. f = uae_tfopen (name, mode);
  1519. if (!f) {
  1520. zfile_fclose (l);
  1521. return 0;
  1522. }
  1523. l->f = f;
  1524. return l;
  1525. }
  1526. static struct zfile *openzip (const TCHAR *pname)
  1527. {
  1528. int i, j;
  1529. TCHAR v;
  1530. TCHAR name[MAX_DPATH];
  1531. TCHAR zippath[MAX_DPATH];
  1532. zippath[0] = 0;
  1533. _tcscpy (name, pname);
  1534. i = _tcslen (name) - 2;
  1535. while (i > 0) {
  1536. if ((name[i] == '/' || name[i] == '\\') && i > 4) {
  1537. v = name[i];
  1538. name[i] = 0;
  1539. for (j = 0; plugins_7z[j]; j++) {
  1540. int len = _tcslen (plugins_7z[j]);
  1541. if (name[i - len - 1] == '.' && !strcasecmp (name + i - len, plugins_7z[j])) {
  1542. struct zfile *f = zfile_fopen_nozip (name, _T("rb"));
  1543. if (f) {
  1544. f->zipname = my_strdup (name + i + 1);
  1545. return f;
  1546. }
  1547. break;
  1548. }
  1549. }
  1550. name[i] = v;
  1551. }
  1552. i--;
  1553. }
  1554. return 0;
  1555. }
  1556. static bool writeneeded (const TCHAR *mode)
  1557. {
  1558. return _tcschr (mode, 'w') || _tcschr (mode, 'a') || _tcschr (mode, '+') || _tcschr (mode, 't');
  1559. }
  1560. bool zfile_needwrite (struct zfile *zf)
  1561. {
  1562. if (!zf->mode)
  1563. return false;
  1564. return writeneeded (zf->mode);
  1565. }
  1566. static struct zfile *zfile_fopen_2 (const TCHAR *name, const TCHAR *mode, int mask)
  1567. {
  1568. struct zfile *l;
  1569. FILE *f;
  1570. if(*name == '\0')
  1571. return NULL;
  1572. #ifdef SINGLEFILE
  1573. if (zfile_opensinglefile (l))
  1574. return l;
  1575. #endif
  1576. l = openzip (name);
  1577. if (l) {
  1578. if (writeneeded (mode)) {
  1579. zfile_fclose (l);
  1580. return 0;
  1581. }
  1582. l->zfdmask = mask;
  1583. } else {
  1584. struct mystat st;
  1585. l = zfile_create (NULL, name);
  1586. l->mode = my_strdup (mode);
  1587. l->name = my_strdup (name);
  1588. l->zfdmask = mask;
  1589. if (!_tcsicmp (mode, _T("r"))) {
  1590. f = my_opentext (l->name);
  1591. l->textmode = 1;
  1592. } else {
  1593. f = uae_tfopen (l->name, mode);
  1594. }
  1595. if (!f) {
  1596. zfile_fclose (l);
  1597. return 0;
  1598. }
  1599. if (my_stat (l->name, &st))
  1600. l->size = st.size;
  1601. l->f = f;
  1602. }
  1603. return l;
  1604. }
  1605. static void manglefilename(const TCHAR *in, TCHAR *out, int outsize)
  1606. {
  1607. if (!target_expand_environment(in, out, outsize))
  1608. _tcscpy(out, in);
  1609. for (int i = 0; i < _tcslen(out); i++) {
  1610. // remove \\ or // in the middle of path
  1611. if ((out[i] == '/' || out[i] == '\\') && (out[i + 1] == '/' || out[i + 1] == '\\') && i > 0) {
  1612. memmove(out + i, out + i + 1, (_tcslen(out + i) + 1) * sizeof(TCHAR));
  1613. i--;
  1614. continue;
  1615. }
  1616. }
  1617. }
  1618. int zfile_zopen (const TCHAR *name, zfile_callback zc, void *user)
  1619. {
  1620. struct zfile *l;
  1621. int ztype;
  1622. TCHAR path[MAX_DPATH];
  1623. manglefilename (name, path, sizeof path / sizeof(TCHAR));
  1624. l = zfile_fopen_2 (path, _T("rb"), ZFD_NORMAL);
  1625. if (!l)
  1626. return 0;
  1627. ztype = iszip (l);
  1628. if (ztype == 0)
  1629. zc (l, user);
  1630. else
  1631. archive_access_scan (l, zc, user, ztype);
  1632. zfile_fclose (l);
  1633. return 1;
  1634. }
  1635. /*
  1636. * fopen() for a compressed file
  1637. */
  1638. static struct zfile *zfile_fopen_x (const TCHAR *name, const TCHAR *mode, int mask, int index)
  1639. {
  1640. int cnt = 10;
  1641. struct zfile *l, *l2;
  1642. TCHAR path[MAX_DPATH];
  1643. if (_tcslen (name) == 0)
  1644. return NULL;
  1645. manglefilename(name, path, sizeof(path) / sizeof TCHAR);
  1646. l = zfile_fopen_2 (path, mode, mask);
  1647. if (!l)
  1648. return 0;
  1649. l2 = NULL;
  1650. while (cnt-- > 0) {
  1651. int rc;
  1652. zfile_fseek (l, 0, SEEK_SET);
  1653. l2 = zuncompress (NULL, l, 0, mask, &rc, index);
  1654. if (!l2) {
  1655. if (rc < 0) {
  1656. zfile_fclose (l);
  1657. return NULL;
  1658. }
  1659. zfile_fseek (l, 0, SEEK_SET);
  1660. break;
  1661. } else {
  1662. if (l2->parent == l)
  1663. l->opencnt--;
  1664. }
  1665. l = l2;
  1666. }
  1667. return l;
  1668. }
  1669. #ifdef _WIN32
  1670. static int isinternetfile (const TCHAR *name)
  1671. {
  1672. if (!_tcsnicmp (name, _T("http://"), 7) || !_tcsnicmp (name, _T("https://"), 8))
  1673. return 1;
  1674. if (!_tcsnicmp (name, _T("ftp://"), 6))
  1675. return -1;
  1676. return 0;
  1677. }
  1678. #include <wininet.h>
  1679. #include "win32.h"
  1680. #define INETBUFFERLEN 1000000
  1681. static struct zfile *zfile_fopen_internet (const TCHAR *name, const TCHAR *mode, int mask)
  1682. {
  1683. static HINTERNET hi;
  1684. HINTERNET i = NULL;
  1685. TCHAR tmp[MAX_DPATH];
  1686. DWORD ierr = 0;
  1687. DWORD outbuf = sizeof tmp / sizeof (TCHAR);
  1688. uae_u8 *data = 0;
  1689. int bufferlen = INETBUFFERLEN;
  1690. int datalen;
  1691. DWORD didread;
  1692. struct zfile *zf = NULL;
  1693. if (_tcschr (mode, 'w') || _tcschr (mode, 'a'))
  1694. return NULL;
  1695. tmp[0] = 0;
  1696. if (!hi) {
  1697. hi = InternetOpen (WINUAEAPPNAME, INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY, NULL, NULL, 0);
  1698. if (hi == NULL) {
  1699. write_log (_T("InternetOpen() failed, %d\n"), GetLastError ());
  1700. return NULL;
  1701. }
  1702. }
  1703. i = InternetOpenUrl (hi, name, NULL, 0, INTERNET_FLAG_NO_COOKIES, 0);
  1704. if (i == NULL) {
  1705. DWORD err = GetLastError ();
  1706. if (err == ERROR_INTERNET_EXTENDED_ERROR)
  1707. InternetGetLastResponseInfo (&ierr, tmp, &outbuf);
  1708. write_log (_T("InternetOpenUrl(%s) failed %d (%d,%s)\n"), name, err, ierr, tmp);
  1709. goto end;
  1710. }
  1711. if (isinternetfile (name) > 0) {
  1712. DWORD statuscode;
  1713. DWORD hindex = 0;
  1714. DWORD size = sizeof statuscode;
  1715. if (!HttpQueryInfo (i, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &statuscode, &size, &hindex)) {
  1716. DWORD err = GetLastError ();
  1717. write_log (_T("HttpQueryInfo(%s) failed %d\n"), name, err);
  1718. goto end;
  1719. }
  1720. if (statuscode != 200) {
  1721. write_log (_T("HttpQueryInfo(%s)=%d\n"), name, statuscode);
  1722. goto end;
  1723. }
  1724. }
  1725. if (mask & ZFD_CHECKONLY) {
  1726. zf = zfile_create (NULL, name);
  1727. goto end;
  1728. }
  1729. datalen = 0;
  1730. data = xmalloc (uae_u8, bufferlen);
  1731. for (;;) {
  1732. if (!InternetReadFile (i, data + datalen, INETBUFFERLEN, &didread)) {
  1733. DWORD err = GetLastError ();
  1734. if (err == ERROR_INTERNET_EXTENDED_ERROR)
  1735. InternetGetLastResponseInfo (&ierr, tmp, &outbuf);
  1736. write_log (_T("InternetReadFile(%s) failed %d (%d,%s)\n"), name, err, ierr, tmp);
  1737. break;
  1738. }
  1739. if (didread == 0)
  1740. break;
  1741. datalen += didread;
  1742. if (datalen > bufferlen - INETBUFFERLEN) {
  1743. bufferlen += INETBUFFERLEN;
  1744. data = xrealloc (uae_u8, data, bufferlen);
  1745. if (!data) {
  1746. datalen = 0;
  1747. break;
  1748. }
  1749. }
  1750. }
  1751. if (datalen > 0) {
  1752. zf = zfile_create (NULL, name);
  1753. if (zf) {
  1754. zf->size = datalen;
  1755. zf->data = data;
  1756. data = NULL;
  1757. }
  1758. }
  1759. end:
  1760. if (i)
  1761. InternetCloseHandle (i);
  1762. free (data);
  1763. return zf;
  1764. }
  1765. #endif
  1766. static struct zfile *zfile_fopenx2 (const TCHAR *name, const TCHAR *mode, int mask, int index)
  1767. {
  1768. struct zfile *f;
  1769. TCHAR tmp[MAX_DPATH];
  1770. #ifdef _WIN32
  1771. if (isinternetfile (name))
  1772. return zfile_fopen_internet (name, mode, mask);
  1773. #endif
  1774. f = zfile_fopen_x (name, mode, mask, index);
  1775. if (f)
  1776. return f;
  1777. if (_tcslen (name) <= 2)
  1778. return NULL;
  1779. if (name[1] != ':') {
  1780. _tcscpy (tmp, start_path_data);
  1781. _tcscat (tmp, name);
  1782. f = zfile_fopen_x (tmp, mode, mask, index);
  1783. if (f)
  1784. return f;
  1785. }
  1786. #if 0
  1787. name += 2;
  1788. if (name[0] == '/' || name[0] == '\\')
  1789. name++;
  1790. for (;;) {
  1791. _tcscpy (tmp, start_path_data);
  1792. _tcscpy (tmp, name);
  1793. f = zfile_fopen_x (tmp, mode, mask);
  1794. if (f)
  1795. return f;
  1796. while (name[0]) {
  1797. name++;
  1798. if (name[-1] == '/' || name[-1] == '\\')
  1799. break;
  1800. }
  1801. if (name[0] == 0)
  1802. break;
  1803. }
  1804. #endif
  1805. return NULL;
  1806. }
  1807. static struct zfile *zfile_fopenx (const TCHAR *name, const TCHAR *mode, int mask, int index)
  1808. {
  1809. struct zfile *zf;
  1810. //write_log (_T("zfile_fopen('%s','%s',%08x,%d)\n"), name, mode, mask, index);
  1811. zf = zfile_fopenx2 (name, mode, mask, index);
  1812. //write_log (_T("=%p\n"), zf);
  1813. return zf;
  1814. }
  1815. struct zfile *zfile_fopen (const TCHAR *name, const TCHAR *mode, int mask)
  1816. {
  1817. return zfile_fopenx (name, mode, mask, 0);
  1818. }
  1819. struct zfile *zfile_fopen (const TCHAR *name, const TCHAR *mode)
  1820. {
  1821. return zfile_fopenx (name, mode, 0, 0);
  1822. }
  1823. struct zfile *zfile_fopen (const TCHAR *name, const TCHAR *mode, int mask, int index)
  1824. {
  1825. return zfile_fopenx (name, mode, mask, index);
  1826. }
  1827. struct zfile *zfile_dup (struct zfile *zf)
  1828. {
  1829. struct zfile *nzf;
  1830. if (!zf)
  1831. return NULL;
  1832. if (zf->archiveparent)
  1833. checkarchiveparent (zf);
  1834. if (zf->userdata)
  1835. return NULL;
  1836. if (!zf->data && zf->dataseek) {
  1837. nzf = zfile_create (zf, NULL);
  1838. } else if (zf->data) {
  1839. nzf = zfile_create (zf, NULL);
  1840. nzf->data = xmalloc (uae_u8, zf->size);
  1841. if (!nzf->data) {
  1842. write_log(_T("Out of memory: %s\n"), zfile_getname(zf));
  1843. return NULL;
  1844. }
  1845. memcpy (nzf->data, zf->data, zf->size);
  1846. nzf->size = zf->size;
  1847. nzf->datasize = zf->datasize;
  1848. } else if (zf->useparent) {
  1849. nzf = zfile_fopen_parent(zf, zf->name, 0, zf->size);
  1850. return nzf;
  1851. } else {
  1852. if (zf->zipname) {
  1853. nzf = openzip (zf->name);
  1854. if (nzf)
  1855. return nzf;
  1856. }
  1857. if (!zf->name || !zf->mode)
  1858. return NULL;
  1859. FILE *ff = uae_tfopen (zf->name, zf->mode);
  1860. if (!ff)
  1861. return NULL;
  1862. nzf = zfile_create (zf, NULL);
  1863. nzf->f = ff;
  1864. }
  1865. zfile_fseek (nzf, zf->seek, SEEK_SET);
  1866. if (zf->name)
  1867. nzf->name = my_strdup (zf->name);
  1868. if (nzf->zipname)
  1869. nzf->zipname = my_strdup (zf->zipname);
  1870. nzf->zfdmask = zf->zfdmask;
  1871. nzf->mode = my_strdup (zf->mode);
  1872. nzf->size = zf->size;
  1873. return nzf;
  1874. }
  1875. int zfile_exists (const TCHAR *name)
  1876. {
  1877. struct zfile *z;
  1878. if (my_existsfile (name))
  1879. return 1;
  1880. z = zfile_fopen (name, _T("rb"), ZFD_NORMAL | ZFD_CHECKONLY);
  1881. if (!z)
  1882. return 0;
  1883. zfile_fclose (z);
  1884. return 1;
  1885. }
  1886. int zfile_iscompressed (struct zfile *z)
  1887. {
  1888. return z->data ? 1 : 0;
  1889. }
  1890. struct zfile *zfile_fopen_empty (struct zfile *prev, const TCHAR *name, uae_u64 size)
  1891. {
  1892. struct zfile *l;
  1893. l = zfile_create (prev, NULL);
  1894. l->name = my_strdup (name ? name : _T(""));
  1895. if (size) {
  1896. l->data = xcalloc (uae_u8, size);
  1897. if (!l->data) {
  1898. xfree (l);
  1899. return NULL;
  1900. }
  1901. l->size = size;
  1902. l->datasize = size;
  1903. l->allocsize = size;
  1904. } else {
  1905. l->data = xcalloc (uae_u8, 1000);
  1906. l->size = 0;
  1907. l->allocsize = 1000;
  1908. }
  1909. return l;
  1910. }
  1911. struct zfile *zfile_fopen_empty (struct zfile *prev, const TCHAR *name)
  1912. {
  1913. return zfile_fopen_empty (prev, name, 0);
  1914. }
  1915. struct zfile *zfile_fopen_parent (struct zfile *z, const TCHAR *name, uae_u64 offset, uae_u64 size)
  1916. {
  1917. struct zfile *l;
  1918. if (z == NULL)
  1919. return NULL;
  1920. l = zfile_create (z, NULL);
  1921. if (name)
  1922. l->name = my_strdup (name);
  1923. else if (z->name)
  1924. l->name = my_strdup (z->name);
  1925. l->size = size;
  1926. l->datasize = size;
  1927. l->offset = offset;
  1928. for (;;) {
  1929. l->parent = z;
  1930. l->useparent = 1;
  1931. if (!z->parent)
  1932. break;
  1933. l->offset += z->offset;
  1934. z = z->parent;
  1935. }
  1936. z->opencnt++;
  1937. return l;
  1938. }
  1939. struct zfile *zfile_fopen_load_zfile (struct zfile *f)
  1940. {
  1941. struct zfile *l = zfile_fopen_empty (f, f->name, f->size);
  1942. if (!l)
  1943. return NULL;
  1944. zfile_fseek (f, 0, SEEK_SET);
  1945. zfile_fread (l->data, f->size, 1, f);
  1946. return l;
  1947. }
  1948. struct zfile *zfile_fopen_data (const TCHAR *name, uae_u64 size, const uae_u8 *data)
  1949. {
  1950. struct zfile *l;
  1951. l = zfile_create (NULL, name);
  1952. l->name = my_strdup (name ? name : _T(""));
  1953. l->data = xmalloc (uae_u8, size);
  1954. l->size = size;
  1955. l->datasize = size;
  1956. memcpy (l->data, data, size);
  1957. return l;
  1958. }
  1959. /* dump file use only */
  1960. uae_u8 *zfile_get_data_pointer(struct zfile *z, int *len)
  1961. {
  1962. if (!z->data)
  1963. return NULL;
  1964. *len = z->size;
  1965. return z->data;
  1966. }
  1967. uae_u8 *zfile_load_data (const TCHAR *name, const uae_u8 *data,int datalen, int *outlen)
  1968. {
  1969. struct zfile *zf, *f;
  1970. int size;
  1971. uae_u8 *out;
  1972. zf = zfile_fopen_data (name, datalen, data);
  1973. f = zfile_gunzip (zf);
  1974. size = f->datasize;
  1975. zfile_fseek (f, 0, SEEK_SET);
  1976. out = xmalloc (uae_u8, size);
  1977. zfile_fread (out, 1, size, f);
  1978. zfile_fclose (f);
  1979. *outlen = size;
  1980. return out;
  1981. }
  1982. uae_u8 *zfile_load_file(const TCHAR *name, int *outlen)
  1983. {
  1984. struct zfile *zf;
  1985. int size;
  1986. uae_u8 *out;
  1987. zf = zfile_fopen(name, _T("rb"));
  1988. if (!zf)
  1989. return NULL;
  1990. size = zfile_size(zf);
  1991. out = xmalloc (uae_u8, size);
  1992. zfile_fread(out, 1, size, zf);
  1993. zfile_fclose(zf);
  1994. *outlen = size;
  1995. return out;
  1996. }
  1997. int zfile_truncate (struct zfile *z, uae_s64 size)
  1998. {
  1999. if (z->data) {
  2000. if (z->size > size) {
  2001. z->size = size;
  2002. if (z->datasize > z->size)
  2003. z->datasize = z->size;
  2004. if (z->seek > z->size)
  2005. z->seek = z->size;
  2006. return 1;
  2007. }
  2008. return 0;
  2009. } else {
  2010. /* !!! */
  2011. return 0;
  2012. }
  2013. }
  2014. uae_s64 zfile_size (struct zfile *z)
  2015. {
  2016. return z->size;
  2017. }
  2018. uae_s64 zfile_ftell (struct zfile *z)
  2019. {
  2020. if (z->data || z->dataseek || z->parent)
  2021. return z->seek;
  2022. return _ftelli64 (z->f);
  2023. }
  2024. uae_s64 zfile_fseek (struct zfile *z, uae_s64 offset, int mode)
  2025. {
  2026. if (z->zfileseek)
  2027. return z->zfileseek (z, offset, mode);
  2028. if (z->data || z->dataseek || (z->parent && z->useparent)) {
  2029. int ret = 0;
  2030. switch (mode)
  2031. {
  2032. case SEEK_SET:
  2033. z->seek = offset;
  2034. break;
  2035. case SEEK_CUR:
  2036. z->seek += offset;
  2037. break;
  2038. case SEEK_END:
  2039. z->seek = z->size + offset;
  2040. break;
  2041. }
  2042. if (z->seek < 0) {
  2043. z->seek = 0;
  2044. ret = 1;
  2045. }
  2046. if (z->seek > z->size) {
  2047. z->seek = z->size;
  2048. ret = 1;
  2049. }
  2050. return ret;
  2051. } else {
  2052. return _fseeki64 (z->f, offset, mode);
  2053. }
  2054. return 1;
  2055. }
  2056. size_t zfile_fread (void *b, size_t l1, size_t l2, struct zfile *z)
  2057. {
  2058. if (z->zfileread)
  2059. return z->zfileread (b, l1, l2, z);
  2060. if (z->data) {
  2061. if (z->datasize < z->size && z->seek + l1 * l2 > z->datasize) {
  2062. if (z->archiveparent) {
  2063. archive_unpackzfile (z);
  2064. return zfile_fread (b, l1, l2, z);
  2065. }
  2066. return 0;
  2067. }
  2068. if (z->seek + l1 * l2 > z->size) {
  2069. if (l1)
  2070. l2 = (z->size - z->seek) / l1;
  2071. else
  2072. l2 = 0;
  2073. if (l2 < 0)
  2074. l2 = 0;
  2075. }
  2076. memcpy (b, z->data + z->offset + z->seek, l1 * l2);
  2077. z->seek += l1 * l2;
  2078. return l2;
  2079. }
  2080. if (z->parent && z->useparent) {
  2081. size_t ret;
  2082. uae_s64 v;
  2083. uae_s64 size = z->size;
  2084. v = z->seek;
  2085. if (v + l1 * l2 > size) {
  2086. if (l1)
  2087. l2 = (size - v) / l1;
  2088. else
  2089. l2 = 0;
  2090. if (l2 < 0)
  2091. l2 = 0;
  2092. }
  2093. zfile_fseek (z->parent, z->seek + z->offset, SEEK_SET);
  2094. v = z->seek;
  2095. ret = zfile_fread (b, l1, l2, z->parent);
  2096. z->seek = v + l1 * ret;
  2097. return ret;
  2098. }
  2099. return fread (b, l1, l2, z->f);
  2100. }
  2101. size_t zfile_fwrite (const void *b, size_t l1, size_t l2, struct zfile *z)
  2102. {
  2103. if (z->archiveparent)
  2104. return 0;
  2105. if (z->zfilewrite)
  2106. return z->zfilewrite (b, l1, l2, z);
  2107. if (z->parent && z->useparent)
  2108. return 0;
  2109. if (z->data) {
  2110. uae_s64 off = z->seek + l1 * l2;
  2111. if (z->allocsize == 0) {
  2112. write_log (_T("zfile_fwrite(data,%s) but allocsize=0!\n"), z->name);
  2113. return 0;
  2114. }
  2115. if (off > z->allocsize) {
  2116. int inc = (z->size / 2 + l1 * l2 + 7) & ~3;
  2117. if (inc < 10000)
  2118. inc = 10000;
  2119. z->allocsize += inc;
  2120. z->data = xrealloc (uae_u8, z->data, z->allocsize);
  2121. }
  2122. memcpy (z->data + z->seek, b, l1 * l2);
  2123. z->seek += l1 * l2;
  2124. if (z->seek > z->size)
  2125. z->size = z->seek;
  2126. if (z->size > z->datasize)
  2127. z->datasize = z->size;
  2128. return l2;
  2129. }
  2130. return fwrite (b, l1, l2, z->f);
  2131. }
  2132. size_t zfile_fputs (struct zfile *z, const TCHAR *s)
  2133. {
  2134. char *s2 = ua (s);
  2135. size_t t;
  2136. t = zfile_fwrite (s2, strlen (s2), 1, z);
  2137. xfree (s2);
  2138. return t;
  2139. }
  2140. char *zfile_fgetsa (char *s, int size, struct zfile *z)
  2141. {
  2142. checkarchiveparent (z);
  2143. if (z->data) {
  2144. char *os = s;
  2145. int i;
  2146. for (i = 0; i < size - 1; i++) {
  2147. if (z->seek == z->size) {
  2148. if (i == 0)
  2149. return NULL;
  2150. break;
  2151. }
  2152. *s = z->data[z->seek++];
  2153. if (*s == '\n') {
  2154. s++;
  2155. break;
  2156. }
  2157. s++;
  2158. }
  2159. *s = 0;
  2160. return os;
  2161. } else {
  2162. return fgets (s, size, z->f);
  2163. }
  2164. }
  2165. TCHAR *zfile_fgets (TCHAR *s, int size, struct zfile *z)
  2166. {
  2167. checkarchiveparent (z);
  2168. if (z->data) {
  2169. char s2[MAX_DPATH];
  2170. char *p = s2;
  2171. int i;
  2172. for (i = 0; i < size - 1; i++) {
  2173. if (z->seek == z->size) {
  2174. if (i == 0)
  2175. return NULL;
  2176. break;
  2177. }
  2178. *p = z->data[z->seek++];
  2179. if (*p == 0 && i == 0)
  2180. return NULL;
  2181. if (*p == '\n' || *p == 0) {
  2182. p++;
  2183. break;
  2184. }
  2185. p++;
  2186. }
  2187. *p = 0;
  2188. if (size > strlen (s2) + 1)
  2189. size = strlen (s2) + 1;
  2190. au_copy (s, size, s2);
  2191. return s + size;
  2192. } else {
  2193. char s2[MAX_DPATH];
  2194. char *s1;
  2195. s1 = fgets (s2, size, z->f);
  2196. if (!s1)
  2197. return NULL;
  2198. if (size > strlen (s2) + 1)
  2199. size = strlen (s2) + 1;
  2200. au_copy (s, size, s2);
  2201. return s + size;
  2202. }
  2203. }
  2204. int zfile_putc (int c, struct zfile *z)
  2205. {
  2206. uae_u8 b = (uae_u8)c;
  2207. return zfile_fwrite (&b, 1, 1, z) ? 1 : -1;
  2208. }
  2209. int zfile_getc (struct zfile *z)
  2210. {
  2211. checkarchiveparent (z);
  2212. int out = -1;
  2213. if (z->data) {
  2214. if (z->seek < z->size) {
  2215. out = z->data[z->seek++];
  2216. }
  2217. } else {
  2218. out = fgetc (z->f);
  2219. }
  2220. return out;
  2221. }
  2222. int zfile_ferror (struct zfile *z)
  2223. {
  2224. return 0;
  2225. }
  2226. uae_u8 *zfile_getdata (struct zfile *z, uae_s64 offset, int len, int *outlen)
  2227. {
  2228. uae_s64 pos = zfile_ftell (z);
  2229. uae_u8 *b;
  2230. if (len < 0) {
  2231. zfile_fseek (z, 0, SEEK_END);
  2232. len = zfile_ftell (z);
  2233. zfile_fseek (z, 0, SEEK_SET);
  2234. }
  2235. b = xmalloc (uae_u8, len);
  2236. zfile_fseek (z, offset, SEEK_SET);
  2237. zfile_fread (b, len, 1, z);
  2238. zfile_fseek (z, pos, SEEK_SET);
  2239. if (outlen)
  2240. *outlen = len;
  2241. return b;
  2242. }
  2243. int zfile_zuncompress (void *dst, int dstsize, struct zfile *src, int srcsize)
  2244. {
  2245. z_stream zs;
  2246. int v;
  2247. uae_u8 inbuf[4096];
  2248. int incnt;
  2249. memset (&zs, 0, sizeof (zs));
  2250. if (inflateInit_ (&zs, ZLIB_VERSION, sizeof (z_stream)) != Z_OK)
  2251. return 0;
  2252. zs.next_out = (Bytef*)dst;
  2253. zs.avail_out = dstsize;
  2254. incnt = 0;
  2255. v = Z_OK;
  2256. while (v == Z_OK && zs.avail_out > 0) {
  2257. if (zs.avail_in == 0) {
  2258. int left = srcsize - incnt;
  2259. if (left == 0)
  2260. break;
  2261. if (left > sizeof (inbuf))
  2262. left = sizeof (inbuf);
  2263. zs.next_in = inbuf;
  2264. zs.avail_in = zfile_fread (inbuf, 1, left, src);
  2265. incnt += left;
  2266. }
  2267. v = inflate (&zs, 0);
  2268. }
  2269. inflateEnd (&zs);
  2270. return 0;
  2271. }
  2272. int zfile_zcompress (struct zfile *f, void *src, int size)
  2273. {
  2274. int v;
  2275. z_stream zs;
  2276. uae_u8 outbuf[4096];
  2277. memset (&zs, 0, sizeof (zs));
  2278. if (deflateInit_ (&zs, Z_DEFAULT_COMPRESSION, ZLIB_VERSION, sizeof (z_stream)) != Z_OK)
  2279. return 0;
  2280. zs.next_in = (Bytef*)src;
  2281. zs.avail_in = size;
  2282. v = Z_OK;
  2283. while (v == Z_OK) {
  2284. zs.next_out = outbuf;
  2285. zs.avail_out = sizeof (outbuf);
  2286. v = deflate (&zs, Z_NO_FLUSH | Z_FINISH);
  2287. if (sizeof (outbuf) - zs.avail_out > 0)
  2288. zfile_fwrite (outbuf, 1, sizeof (outbuf) - zs.avail_out, f);
  2289. }
  2290. deflateEnd (&zs);
  2291. return zs.total_out;
  2292. }
  2293. TCHAR *zfile_getname (struct zfile *f)
  2294. {
  2295. return f ? f->name : NULL;
  2296. }
  2297. TCHAR *zfile_getoriginalname (struct zfile *f)
  2298. {
  2299. return f ? f->originalname : NULL;
  2300. }
  2301. TCHAR *zfile_getfilename (struct zfile *f)
  2302. {
  2303. int i;
  2304. if (f->name == NULL)
  2305. return NULL;
  2306. for (i = _tcslen (f->name) - 1; i >= 0; i--) {
  2307. if (f->name[i] == '\\' || f->name[i] == '/' || f->name[i] == ':') {
  2308. i++;
  2309. return &f->name[i];
  2310. }
  2311. }
  2312. return f->name;
  2313. }
  2314. uae_u32 zfile_crc32 (struct zfile *f)
  2315. {
  2316. uae_u8 *p;
  2317. int pos, size;
  2318. uae_u32 crc;
  2319. if (!f)
  2320. return 0;
  2321. if (f->data)
  2322. return get_crc32 (f->data, f->size);
  2323. pos = zfile_ftell (f);
  2324. zfile_fseek (f, 0, SEEK_END);
  2325. size = zfile_ftell (f);
  2326. p = xmalloc (uae_u8, size);
  2327. if (!p)
  2328. return 0;
  2329. memset (p, 0, size);
  2330. zfile_fseek (f, 0, SEEK_SET);
  2331. zfile_fread (p, 1, size, f);
  2332. zfile_fseek (f, pos, SEEK_SET);
  2333. crc = get_crc32 (p, size);
  2334. xfree (p);
  2335. return crc;
  2336. }
  2337. static struct zvolume *zvolume_list;
  2338. static void recurparent (TCHAR *newpath, struct znode *zn, int recurse)
  2339. {
  2340. if (zn->parent && (&zn->volume->root != zn->parent || zn->volume->parentz == NULL)) {
  2341. if (&zn->volume->root == zn->parent && zn->volume->parentz == NULL && !_tcscmp (zn->name, zn->parent->name))
  2342. goto end;
  2343. recurparent (newpath, zn->parent, recurse);
  2344. } else {
  2345. struct zvolume *zv = zn->volume;
  2346. if (zv->parentz && recurse)
  2347. recurparent (newpath, zv->parentz, recurse);
  2348. }
  2349. end:
  2350. if (newpath[0])
  2351. _tcscat (newpath, FSDB_DIR_SEPARATOR_S);
  2352. _tcscat (newpath, zn->name);
  2353. }
  2354. static struct znode *znode_alloc (struct znode *parent, const TCHAR *name)
  2355. {
  2356. TCHAR fullpath[MAX_DPATH];
  2357. TCHAR tmpname[MAX_DPATH];
  2358. struct znode *zn = xcalloc (struct znode, 1);
  2359. struct znode *zn2;
  2360. _tcscpy (tmpname, name);
  2361. zn2 = parent->child;
  2362. while (zn2) {
  2363. if (!_tcscmp (zn2->name, tmpname)) {
  2364. TCHAR *ext = _tcsrchr (tmpname, '.');
  2365. if (ext && ext > tmpname + 2 && ext[-2] == '.') {
  2366. ext[-1]++;
  2367. } else if (ext) {
  2368. memmove (ext + 2, ext, (_tcslen (ext) + 1) * sizeof (TCHAR));
  2369. ext[0] = '.';
  2370. ext[1] = '1';
  2371. } else {
  2372. int len = _tcslen (tmpname);
  2373. tmpname[len] = '.';
  2374. tmpname[len + 1] = '1';
  2375. tmpname[len + 2] = 0;
  2376. }
  2377. zn2 = parent->child;
  2378. continue;
  2379. }
  2380. zn2 = zn2->sibling;
  2381. }
  2382. fullpath[0] = 0;
  2383. recurparent (fullpath, parent, FALSE);
  2384. _tcscat (fullpath, FSDB_DIR_SEPARATOR_S);
  2385. _tcscat (fullpath, tmpname);
  2386. #ifdef ZFILE_DEBUG
  2387. write_log (_T("znode_alloc vol='%s' parent='%s' name='%s'\n"), parent->volume->root.name, parent->name, name);
  2388. #endif
  2389. zn->fullname = my_strdup (fullpath);
  2390. zn->name = my_strdup (tmpname);
  2391. zn->volume = parent->volume;
  2392. zn->volume->last->next = zn;
  2393. zn->prev = zn->volume->last;
  2394. zn->volume->last = zn;
  2395. return zn;
  2396. }
  2397. static struct znode *znode_alloc_child (struct znode *parent, const TCHAR *name)
  2398. {
  2399. struct znode *zn = znode_alloc (parent, name);
  2400. if (!parent->child) {
  2401. parent->child = zn;
  2402. } else {
  2403. struct znode *pn = parent->child;
  2404. while (pn->sibling)
  2405. pn = pn->sibling;
  2406. pn->sibling = zn;
  2407. }
  2408. zn->parent = parent;
  2409. return zn;
  2410. }
  2411. static struct znode *znode_alloc_sibling (struct znode *sibling, const TCHAR *name)
  2412. {
  2413. struct znode *zn = znode_alloc (sibling->parent, name);
  2414. if (!sibling->sibling) {
  2415. sibling->sibling = zn;
  2416. } else {
  2417. struct znode *pn = sibling->sibling;
  2418. while (pn->sibling)
  2419. pn = pn->sibling;
  2420. pn->sibling = zn;
  2421. }
  2422. zn->parent = sibling->parent;
  2423. return zn;
  2424. }
  2425. static void zvolume_addtolist (struct zvolume *zv)
  2426. {
  2427. if (!zv)
  2428. return;
  2429. if (!zvolume_list) {
  2430. zvolume_list = zv;
  2431. } else {
  2432. struct zvolume *v = zvolume_list;
  2433. while (v->next)
  2434. v = v->next;
  2435. v->next = zv;
  2436. }
  2437. }
  2438. static struct zvolume *zvolume_alloc_2 (const TCHAR *name, struct zfile *z, unsigned int id, void *handle, const TCHAR *volname)
  2439. {
  2440. struct zvolume *zv = xcalloc (struct zvolume, 1);
  2441. struct znode *root;
  2442. uae_s64 pos;
  2443. int i;
  2444. root = &zv->root;
  2445. zv->last = root;
  2446. zv->archive = z;
  2447. zv->handle = handle;
  2448. zv->id = id;
  2449. if (z)
  2450. zv->zfdmask = z->zfdmask;
  2451. root->volume = zv;
  2452. root->type = ZNODE_DIR;
  2453. i = 0;
  2454. if (name[0] != '/' && name[0] != '\\' && _tcsncmp(name, _T(".\\"), 2) != 0 && _tcsncmp(name, _T("..\\"), 3) != 0) {
  2455. if (_tcschr (name, ':') == 0) {
  2456. for (i = _tcslen (name) - 1; i > 0; i--) {
  2457. if (name[i] == FSDB_DIR_SEPARATOR) {
  2458. i++;
  2459. break;
  2460. }
  2461. }
  2462. }
  2463. }
  2464. root->name = my_strdup (name + i);
  2465. root->fullname = my_strdup (name);
  2466. #ifdef ZFILE_DEBUG
  2467. write_log (_T("created zvolume: '%s' (%s)\n"), root->name, root->fullname);
  2468. #endif
  2469. if (volname)
  2470. zv->volumename = my_strdup (volname);
  2471. if (z) {
  2472. pos = zfile_ftell (z);
  2473. zfile_fseek (z, 0, SEEK_END);
  2474. zv->archivesize = zfile_ftell (z);
  2475. zfile_fseek (z, pos, SEEK_SET);
  2476. }
  2477. return zv;
  2478. }
  2479. struct zvolume *zvolume_alloc (struct zfile *z, unsigned int id, void *handle, const TCHAR *volumename)
  2480. {
  2481. return zvolume_alloc_2 (zfile_getname (z), z, id, handle, volumename);
  2482. }
  2483. static struct zvolume *zvolume_alloc_nofile (const TCHAR *name, unsigned int id, void *handle, const TCHAR *volumename)
  2484. {
  2485. return zvolume_alloc_2 (name, NULL, id, handle, volumename);
  2486. }
  2487. struct zvolume *zvolume_alloc_empty (struct zvolume *prev, const TCHAR *name)
  2488. {
  2489. struct zvolume *zv = zvolume_alloc_2(name, 0, 0, 0, NULL);
  2490. if (!zv)
  2491. return NULL;
  2492. if (prev)
  2493. zv->zfdmask = prev->zfdmask;
  2494. return zv;
  2495. }
  2496. static struct zvolume *get_zvolume (const TCHAR *path)
  2497. {
  2498. struct zvolume *zv = zvolume_list;
  2499. while (zv) {
  2500. TCHAR *s = zfile_getname (zv->archive);
  2501. if (!s)
  2502. s = zv->root.name;
  2503. if (_tcslen (path) >= _tcslen (s) && !memcmp (path, s, _tcslen (s) * sizeof (TCHAR)))
  2504. return zv;
  2505. zv = zv->next;
  2506. }
  2507. return NULL;
  2508. }
  2509. static struct zvolume *zfile_fopen_archive_ext (struct znode *parent, struct zfile *zf, int flags)
  2510. {
  2511. struct zvolume *zv = NULL;
  2512. TCHAR *name = zfile_getname (zf);
  2513. TCHAR *ext;
  2514. uae_u8 header[7];
  2515. if (!name)
  2516. return NULL;
  2517. memset (header, 0, sizeof (header));
  2518. zfile_fseek (zf, 0, SEEK_SET);
  2519. zfile_fread (header, sizeof (header), 1, zf);
  2520. zfile_fseek (zf, 0, SEEK_SET);
  2521. ext = _tcsrchr (name, '.');
  2522. if (ext != NULL) {
  2523. ext++;
  2524. if (flags & ZFD_ARCHIVE) {
  2525. #ifdef A_LHA
  2526. if (strcasecmp (ext, _T("lha")) == 0 || strcasecmp (ext, _T("lzh")) == 0)
  2527. zv = archive_directory_lha (zf);
  2528. #endif
  2529. #ifdef A_ZIP
  2530. if (strcasecmp (ext, _T("zip")) == 0)
  2531. zv = archive_directory_zip (zf);
  2532. #endif
  2533. #ifdef A_7Z
  2534. if (strcasecmp (ext, _T("7z")) == 0)
  2535. zv = archive_directory_7z (zf);
  2536. #endif
  2537. #ifdef A_LZX
  2538. if (strcasecmp (ext, _T("lzx")) == 0)
  2539. zv = archive_directory_lzx (zf);
  2540. #endif
  2541. #ifdef A_RAR
  2542. if (strcasecmp (ext, _T("rar")) == 0)
  2543. zv = archive_directory_rar (zf);
  2544. #endif
  2545. if (strcasecmp (ext, _T("tar")) == 0)
  2546. zv = archive_directory_tar (zf);
  2547. }
  2548. if (flags & ZFD_ADF) {
  2549. if (strcasecmp (ext, _T("adf")) == 0 && !memcmp (header, "DOS", 3))
  2550. zv = archive_directory_adf (parent, zf);
  2551. }
  2552. if (flags & ZFD_HD) {
  2553. if (strcasecmp (ext, _T("hdf")) == 0) {
  2554. if (!memcmp (header, "RDSK", 4))
  2555. zv = archive_directory_rdb (zf);
  2556. else
  2557. zv = archive_directory_adf (parent, zf);
  2558. }
  2559. }
  2560. }
  2561. return zv;
  2562. }
  2563. static struct zvolume *zfile_fopen_archive_data (struct znode *parent, struct zfile *zf, int flags)
  2564. {
  2565. struct zvolume *zv = NULL;
  2566. uae_u8 header[32];
  2567. memset (header, 0, sizeof (header));
  2568. zfile_fread (header, sizeof (header), 1, zf);
  2569. zfile_fseek (zf, 0, SEEK_SET);
  2570. if (flags & ZFD_ARCHIVE) {
  2571. #ifdef A_ZIP
  2572. if (header[0] == 'P' && header[1] == 'K')
  2573. zv = archive_directory_zip (zf);
  2574. #endif
  2575. #ifdef A_RAR
  2576. if (header[0] == 'R' && header[1] == 'a' && header[2] == 'r' && header[3] == '!')
  2577. zv = archive_directory_rar (zf);
  2578. #endif
  2579. #ifdef A_LZX
  2580. if (header[0] == 'L' && header[1] == 'Z' && header[2] == 'X')
  2581. zv = archive_directory_lzx (zf);
  2582. #endif
  2583. #ifdef A_LHA
  2584. if (header[2] == '-' && header[3] == 'l' && header[4] == 'h' && header[6] == '-')
  2585. zv = archive_directory_lha (zf);
  2586. #endif
  2587. }
  2588. if (flags & ZFD_ADF) {
  2589. if (header[0] == 'D' && header[1] == 'O' && header[2] == 'S' && (header[3] >= 0 && header[3] <= 7))
  2590. zv = archive_directory_adf (parent, zf);
  2591. }
  2592. if (flags & ZFD_HD) {
  2593. if (header[0] == 'R' && header[1] == 'D' && header[2] == 'S' && header[3] == 'K')
  2594. zv = archive_directory_rdb (zf);
  2595. if (isfat (header))
  2596. zv = archive_directory_fat (zf);
  2597. }
  2598. return zv;
  2599. }
  2600. static struct znode *get_znode (struct zvolume *zv, const TCHAR *ppath, int);
  2601. static void zfile_fopen_archive_recurse2 (struct zvolume *zv, struct znode *zn, int flags)
  2602. {
  2603. struct zvolume *zvnew;
  2604. struct znode *zndir;
  2605. TCHAR tmp[MAX_DPATH];
  2606. _stprintf (tmp, _T("%s.DIR"), zn->fullname + _tcslen (zv->root.name) + 1);
  2607. zndir = get_znode (zv, tmp, TRUE);
  2608. if (!zndir) {
  2609. struct zarchive_info zai = { 0 };
  2610. zvnew = zvolume_alloc_empty (zv, tmp);
  2611. zvnew->parentz = zn;
  2612. zai.name = tmp;
  2613. zai.tv.tv_sec = zn->mtime.tv_sec;
  2614. zai.tv.tv_usec = zn->mtime.tv_usec;
  2615. zai.comment = zv->volumename;
  2616. if (zn->flags < 0)
  2617. zai.flags = zn->flags;
  2618. zndir = zvolume_adddir_abs (zv, &zai);
  2619. zndir->type = ZNODE_VDIR;
  2620. zndir->vfile = zn;
  2621. zndir->vchild = zvnew;
  2622. zvnew->parent = zv;
  2623. zndir->offset = zn->offset;
  2624. zndir->offset2 = zn->offset2;
  2625. }
  2626. }
  2627. static int zfile_fopen_archive_recurse (struct zvolume *zv, int flags)
  2628. {
  2629. struct znode *zn;
  2630. int i, added;
  2631. added = 0;
  2632. zn = zv->root.child;
  2633. while (zn) {
  2634. int done = 0;
  2635. struct zfile *z;
  2636. TCHAR *ext = _tcsrchr (zn->name, '.');
  2637. if (ext && !zn->vchild && zn->type == ZNODE_FILE) {
  2638. for (i = 0; !done && archive_extensions[i]; i++) {
  2639. if (!strcasecmp (ext + 1, archive_extensions[i])) {
  2640. zfile_fopen_archive_recurse2 (zv, zn, flags);
  2641. done = 1;
  2642. }
  2643. }
  2644. }
  2645. if (!done) {
  2646. z = archive_getzfile (zn, zv->method, 0);
  2647. if (z && iszip (z))
  2648. zfile_fopen_archive_recurse2 (zv, zn, flags);
  2649. }
  2650. zn = zn->next;
  2651. }
  2652. return 0;
  2653. }
  2654. static struct zvolume *prepare_recursive_volume (struct zvolume *zv, const TCHAR *path, int flags)
  2655. {
  2656. struct zfile *zf = NULL;
  2657. struct zvolume *zvnew = NULL;
  2658. int done = 0;
  2659. #ifdef ZFILE_DEBUG
  2660. write_log (_T("unpacking '%s'\n"), path);
  2661. #endif
  2662. zf = zfile_open_archive (path, 0);
  2663. if (!zf)
  2664. goto end;
  2665. zvnew = zfile_fopen_archive_ext (zv->parentz, zf, flags);
  2666. if (!zvnew && !(flags & ZFD_NORECURSE)) {
  2667. #if 1
  2668. zvnew = archive_directory_plain (zf);
  2669. if (zvnew) {
  2670. zfile_fopen_archive_recurse (zvnew, flags);
  2671. done = 1;
  2672. }
  2673. #else
  2674. int rc;
  2675. int index;
  2676. struct zfile *zf2, *zf3;
  2677. TCHAR oldname[MAX_DPATH];
  2678. _tcscpy (oldname, zf->name);
  2679. index = 0;
  2680. for (;;) {
  2681. zf3 = zfile_dup (zf);
  2682. if (!zf3)
  2683. break;
  2684. zf2 = zuncompress (&zv->root, zf3, 0, ZFD_ALL, &rc, index);
  2685. if (zf2) {
  2686. zvnew = archive_directory_plain (zf2);
  2687. if (zvnew) {
  2688. zvnew->parent = zv->parent;
  2689. zfile_fopen_archive_recurse (zvnew);
  2690. done = 1;
  2691. }
  2692. } else {
  2693. zfile_fclose (zf3);
  2694. if (rc <= 0)
  2695. break;
  2696. }
  2697. index++;
  2698. break; // TODO
  2699. }
  2700. #endif
  2701. } else if (zvnew) {
  2702. zvnew->parent = zv->parent;
  2703. zfile_fopen_archive_recurse (zvnew, flags);
  2704. done = 1;
  2705. }
  2706. if (!done)
  2707. goto end;
  2708. zfile_fclose_archive (zv);
  2709. return zvnew;
  2710. end:
  2711. write_log (_T("unpack '%s' failed\n"), path);
  2712. zfile_fclose_archive (zvnew);
  2713. zfile_fclose (zf);
  2714. return NULL;
  2715. }
  2716. static struct znode *get_znode (struct zvolume *zv, const TCHAR *ppath, int recurse)
  2717. {
  2718. struct znode *zn;
  2719. TCHAR path[MAX_DPATH], zpath[MAX_DPATH];
  2720. if (!zv)
  2721. return NULL;
  2722. _tcscpy (path, ppath);
  2723. zn = &zv->root;
  2724. while (zn) {
  2725. zpath[0] = 0;
  2726. recurparent (zpath, zn, recurse);
  2727. if (zn->type == ZNODE_FILE) {
  2728. if (!_tcsicmp (zpath, path))
  2729. return zn;
  2730. } else {
  2731. int len = _tcslen (zpath);
  2732. if (_tcslen (path) >= len && (path[len] == 0 || path[len] == FSDB_DIR_SEPARATOR) && !_tcsnicmp (zpath, path, len)) {
  2733. if (path[len] == 0)
  2734. return zn;
  2735. if (zn->vchild) {
  2736. /* jump to separate tree, recursive archives */
  2737. struct zvolume *zvdeep = zn->vchild;
  2738. if (zvdeep->archive == NULL) {
  2739. TCHAR newpath[MAX_DPATH];
  2740. newpath[0] = 0;
  2741. recurparent (newpath, zn, recurse);
  2742. #ifdef ZFILE_DEBUG
  2743. write_log (_T("'%s'\n"), newpath);
  2744. #endif
  2745. zvdeep = prepare_recursive_volume (zvdeep, newpath, ZFD_ALL);
  2746. if (!zvdeep) {
  2747. write_log (_T("failed to unpack '%s'\n"), newpath);
  2748. return NULL;
  2749. }
  2750. /* replace dummy empty volume with real volume */
  2751. zn->vchild = zvdeep;
  2752. zvdeep->parentz = zn;
  2753. }
  2754. zn = zvdeep->root.child;
  2755. } else {
  2756. zn = zn->child;
  2757. }
  2758. continue;
  2759. }
  2760. }
  2761. zn = zn->sibling;
  2762. }
  2763. return NULL;
  2764. }
  2765. static void addvolumesize (struct zvolume *zv, uae_s64 size)
  2766. {
  2767. unsigned int blocks = (size + 511) / 512;
  2768. if (blocks == 0)
  2769. blocks++;
  2770. while (zv) {
  2771. zv->size += size;
  2772. zv = zv->parent;
  2773. }
  2774. }
  2775. static bool valid_zi(struct zarchive_info *zai)
  2776. {
  2777. if (_tcslen(zai->name) == 0) {
  2778. return false;
  2779. }
  2780. return true;
  2781. }
  2782. struct znode *znode_adddir (struct znode *parent, const TCHAR *name, struct zarchive_info *zai)
  2783. {
  2784. struct znode *zn;
  2785. TCHAR path[MAX_DPATH];
  2786. path[0] = 0;
  2787. recurparent (path, parent, FALSE);
  2788. _tcscat (path, FSDB_DIR_SEPARATOR_S);
  2789. _tcscat (path, name);
  2790. zn = get_znode (parent->volume, path, FALSE);
  2791. if (zn)
  2792. return zn;
  2793. zn = znode_alloc_child (parent, name);
  2794. zn->mtime.tv_sec = zai->tv.tv_sec;
  2795. zn->mtime.tv_usec = zai->tv.tv_usec;
  2796. zn->type = ZNODE_DIR;
  2797. if (zai->comment)
  2798. zn->comment = my_strdup (zai->comment);
  2799. if (zai->flags < 0)
  2800. zn->flags = zai->flags;
  2801. addvolumesize (parent->volume, 0);
  2802. return zn;
  2803. }
  2804. struct znode *zvolume_adddir_abs (struct zvolume *zv, struct zarchive_info *zai)
  2805. {
  2806. struct znode *zn2;
  2807. TCHAR *path = my_strdup (zai->name);
  2808. TCHAR *p, *p2;
  2809. int i;
  2810. if (_tcslen (path) > 0) {
  2811. /* remove possible trailing / or \ */
  2812. TCHAR last;
  2813. last = path[_tcslen (path) - 1];
  2814. if (last == '/' || last == '\\')
  2815. path[_tcslen (path) - 1] = 0;
  2816. }
  2817. if (!valid_zi(zai)) {
  2818. xfree(path);
  2819. return NULL;
  2820. }
  2821. zn2 = &zv->root;
  2822. p = p2 = path;
  2823. for (i = 0; path[i]; i++) {
  2824. if (path[i] == '/' || path[i] == '\\') {
  2825. path[i] = 0;
  2826. zn2 = znode_adddir (zn2, p, zai);
  2827. path[i] = FSDB_DIR_SEPARATOR;
  2828. p = p2 = &path[i + 1];
  2829. }
  2830. }
  2831. return znode_adddir (zn2, p, zai);
  2832. }
  2833. struct znode *zvolume_addfile_abs (struct zvolume *zv, struct zarchive_info *zai)
  2834. {
  2835. struct znode *zn = NULL, *zn2;
  2836. int i;
  2837. TCHAR *path = my_strdup(zai->name);
  2838. TCHAR *p, *p2;
  2839. zn2 = &zv->root;
  2840. p = p2 = path;
  2841. for (i = 0; path[i]; i++) {
  2842. if (path[i] == '/' || path[i] == '\\') {
  2843. path[i] = 0;
  2844. zn2 = znode_adddir (zn2, p, zai);
  2845. path[i] = FSDB_DIR_SEPARATOR;
  2846. p = p2 = &path[i + 1];
  2847. }
  2848. }
  2849. if (p2 && _tcslen(p2) > 0) {
  2850. zn = znode_alloc_child (zn2, p2);
  2851. zn->size = zai->size;
  2852. zn->type = ZNODE_FILE;
  2853. zn->mtime.tv_sec = zai->tv.tv_sec;
  2854. zn->mtime.tv_usec = zai->tv.tv_usec;
  2855. if (zai->comment)
  2856. zn->comment = my_strdup (zai->comment);
  2857. zn->flags = zai->flags;
  2858. addvolumesize (zn->volume, zai->size);
  2859. }
  2860. xfree (path);
  2861. return zn;
  2862. }
  2863. static struct zvolume *zfile_fopen_directory (const TCHAR *dirname)
  2864. {
  2865. struct zvolume *zv = NULL;
  2866. struct my_opendir_s *dir;
  2867. TCHAR fname[MAX_DPATH];
  2868. dir = my_opendir (dirname);
  2869. if (!dir)
  2870. return NULL;
  2871. zv = zvolume_alloc_nofile (dirname, ArchiveFormatDIR, NULL, NULL);
  2872. while (my_readdir (dir, fname)) {
  2873. TCHAR fullname[MAX_DPATH];
  2874. struct mystat statbuf;
  2875. struct zarchive_info zai = { 0 };
  2876. if (!_tcscmp (fname, _T(".")) || !_tcscmp (fname, _T("..")))
  2877. continue;
  2878. _tcscpy (fullname, dirname);
  2879. _tcscat (fullname, FSDB_DIR_SEPARATOR_S);
  2880. _tcscat (fullname, fname);
  2881. if (!my_stat (fullname, &statbuf))
  2882. continue;
  2883. zai.name = fname;
  2884. zai.size = statbuf.size;
  2885. zai.tv.tv_sec = statbuf.mtime.tv_sec;
  2886. zai.tv.tv_usec = statbuf.mtime.tv_usec;
  2887. if (statbuf.mode & FILEFLAG_DIR) {
  2888. zvolume_adddir_abs (zv, &zai);
  2889. } else {
  2890. struct znode *zn;
  2891. zn = zvolume_addfile_abs (zv, &zai);
  2892. //zfile_fopen_archive_recurse2 (zv, zn);
  2893. }
  2894. }
  2895. my_closedir (dir);
  2896. // zfile_fopen_archive_recurse (zv);
  2897. if (zv)
  2898. zvolume_addtolist (zv);
  2899. return zv;
  2900. }
  2901. struct zvolume *zfile_fopen_archive (const TCHAR *filename, int flags)
  2902. {
  2903. struct zvolume *zv = NULL;
  2904. struct zfile *zf = zfile_fopen_nozip (filename, _T("rb"));
  2905. if (!zf)
  2906. return NULL;
  2907. zf->zfdmask = flags;
  2908. zv = zfile_fopen_archive_ext (NULL, zf, flags);
  2909. if (!zv)
  2910. zv = zfile_fopen_archive_data (NULL, zf, flags);
  2911. #if 0
  2912. if (!zv) {
  2913. struct zfile *zf2 = zuncompress (zf, 0, 0);
  2914. if (zf2 != zf) {
  2915. zf = zf2;
  2916. zv = zfile_fopen_archive_ext (zf, flags);
  2917. if (!zv)
  2918. zv = zfile_fopen_archive_data (zf, flags);
  2919. }
  2920. }
  2921. #endif
  2922. /* pointless but who cares? */
  2923. if (!zv && !(flags & ZFD_NORECURSE))
  2924. zv = archive_directory_plain (zf);
  2925. #if RECURSIVE_ARCHIVES
  2926. if (zv && !(flags & ZFD_NORECURSE))
  2927. zfile_fopen_archive_recurse (zv, flags);
  2928. #endif
  2929. if (zv)
  2930. zvolume_addtolist (zv);
  2931. else
  2932. zfile_fclose (zf);
  2933. return zv;
  2934. }
  2935. struct zvolume *zfile_fopen_archive (const TCHAR *filename)
  2936. {
  2937. struct zvolume *zv = zfile_fopen_archive (filename, ZFD_ALL);
  2938. if (zv) {
  2939. zv->autofree = true;
  2940. }
  2941. return zv;
  2942. }
  2943. struct zvolume *zfile_fopen_archive_root (const TCHAR *filename, int flags)
  2944. {
  2945. TCHAR path[MAX_DPATH], *p1, *p2, *lastp;
  2946. struct zvolume *zv = NULL;
  2947. //int last = 0;
  2948. int num, i;
  2949. if (my_existsdir (filename))
  2950. return zfile_fopen_directory (filename);
  2951. num = 1;
  2952. lastp = NULL;
  2953. for (;;) {
  2954. _tcscpy (path, filename);
  2955. p1 = p2 = path;
  2956. for (i = 0; i < num; i++) {
  2957. while (*p1 != FSDB_DIR_SEPARATOR && *p1 != 0)
  2958. p1++;
  2959. if (*p1 == 0 && p1 == lastp)
  2960. return NULL;
  2961. if (i + 1 < num)
  2962. p1++;
  2963. }
  2964. *p1 = 0;
  2965. lastp = p1;
  2966. if (my_existsfile (p2))
  2967. return zfile_fopen_archive (p2, flags);
  2968. num++;
  2969. }
  2970. #if 0
  2971. while (!last) {
  2972. while (*p1 != FSDB_DIR_SEPARATOR && *p1 != 0)
  2973. p1++;
  2974. if (*p1 == 0)
  2975. last = 1;
  2976. *p1 = 0;
  2977. if (!zv) {
  2978. zv = zfile_fopen_archive (p2);
  2979. if (!zv)
  2980. return NULL;
  2981. } else {
  2982. struct znode *zn = get_znode (zv, p2);
  2983. if (!zn)
  2984. return NULL;
  2985. }
  2986. p2 = p1 + 1;
  2987. }
  2988. return zv;
  2989. #endif
  2990. }
  2991. void zfile_fclose_archive (struct zvolume *zv)
  2992. {
  2993. struct znode *zn;
  2994. struct zvolume *v;
  2995. if (!zv)
  2996. return;
  2997. zn = &zv->root;
  2998. while (zn) {
  2999. struct znode *zn2 = zn->next;
  3000. if (zn->vchild)
  3001. zfile_fclose_archive (zn->vchild);
  3002. xfree (zn->comment);
  3003. xfree (zn->fullname);
  3004. xfree (zn->name);
  3005. zfile_fclose (zn->f);
  3006. memset (zn, 0, sizeof (struct znode));
  3007. if (zn != &zv->root)
  3008. xfree (zn);
  3009. zn = zn2;
  3010. }
  3011. archive_access_close (zv->handle, zv->id);
  3012. if (zv->autofree) {
  3013. zfile_fclose(zv->archive);
  3014. }
  3015. if (zvolume_list == zv) {
  3016. zvolume_list = zvolume_list->next;
  3017. } else {
  3018. v = zvolume_list;
  3019. while (v) {
  3020. if (v->next == zv) {
  3021. v->next = zv->next;
  3022. break;
  3023. }
  3024. v = v->next;
  3025. }
  3026. }
  3027. xfree(zv->volumename);
  3028. xfree(zv);
  3029. }
  3030. struct zdirectory {
  3031. TCHAR *parentpath;
  3032. struct znode *first;
  3033. struct znode *n;
  3034. bool doclose;
  3035. struct zvolume *zv;
  3036. int cnt;
  3037. int offset;
  3038. TCHAR **filenames;
  3039. };
  3040. struct zdirectory *zfile_opendir_archive (const TCHAR *path, int flags)
  3041. {
  3042. struct zvolume *zv = get_zvolume (path);
  3043. bool created = false;
  3044. if (zv == NULL) {
  3045. zv = zfile_fopen_archive (path, flags);
  3046. created = true;
  3047. }
  3048. struct znode *zn = get_znode (zv, path, TRUE);
  3049. struct zdirectory *zd;
  3050. if (!zn || (!zn->child && !zn->vchild)) {
  3051. if (created)
  3052. zfile_fclose_archive (zv);
  3053. return NULL;
  3054. }
  3055. zd = xcalloc (struct zdirectory, 1);
  3056. if (created)
  3057. zd->zv = zv;
  3058. if (zn->child) {
  3059. zd->n = zn->child;
  3060. } else {
  3061. if (zn->vchild->archive == NULL) {
  3062. struct zvolume *zvnew = prepare_recursive_volume (zn->vchild, path, flags);
  3063. if (zvnew) {
  3064. zn->vchild = zvnew;
  3065. zvnew->parentz = zn;
  3066. }
  3067. }
  3068. zd->n = zn->vchild->root.next;
  3069. }
  3070. zd->parentpath = my_strdup (path);
  3071. zd->first = zd->n;
  3072. return zd;
  3073. }
  3074. struct zdirectory *zfile_opendir_archive (const TCHAR *path)
  3075. {
  3076. return zfile_opendir_archive (path, ZFD_ALL | ZFD_NORECURSE);
  3077. }
  3078. void zfile_closedir_archive (struct zdirectory *zd)
  3079. {
  3080. if (!zd)
  3081. return;
  3082. zfile_fclose_archive (zd->zv);
  3083. xfree (zd->parentpath);
  3084. xfree (zd->filenames);
  3085. xfree (zd);
  3086. }
  3087. int zfile_readdir_archive (struct zdirectory *zd, TCHAR *out, bool fullpath)
  3088. {
  3089. if (out)
  3090. out[0] = 0;
  3091. if (!zd->n || (zd->filenames != NULL && zd->offset >= zd->cnt))
  3092. return 0;
  3093. if (zd->filenames == NULL) {
  3094. struct znode *n = zd->first;
  3095. int cnt = 0;
  3096. while (n) {
  3097. cnt++;
  3098. n = n->sibling;
  3099. }
  3100. n = zd->first;
  3101. uae_u8 *buf = xmalloc (uae_u8, cnt * sizeof (TCHAR*));
  3102. zd->filenames = (TCHAR**)buf;
  3103. buf += cnt * sizeof (TCHAR*);
  3104. for (int i = 0; i < cnt; i++) {
  3105. zd->filenames[i] = n->name;
  3106. n = n->sibling;
  3107. }
  3108. for (int i = 0; i < cnt; i++) {
  3109. for (int j = i + 1; j < cnt; j++) {
  3110. if (_tcscmp (zd->filenames[i], zd->filenames[j]) > 0) {
  3111. TCHAR *tmp = zd->filenames[i];
  3112. zd->filenames[i] = zd->filenames[j];
  3113. zd->filenames[j] = tmp;
  3114. }
  3115. }
  3116. }
  3117. zd->cnt = cnt;
  3118. }
  3119. if (out == NULL)
  3120. return zd->cnt;
  3121. if (fullpath) {
  3122. _tcscpy (out, zd->parentpath);
  3123. _tcscat (out, FSDB_DIR_SEPARATOR_S);
  3124. }
  3125. _tcscat (out, zd->filenames[zd->offset]);
  3126. zd->offset++;
  3127. return 1;
  3128. }
  3129. int zfile_readdir_archive (struct zdirectory *zd, TCHAR *out)
  3130. {
  3131. return zfile_readdir_archive (zd, out, false);
  3132. }
  3133. struct zfile *zfile_readdir_archive_open (struct zdirectory *zd, const TCHAR *mode)
  3134. {
  3135. TCHAR path[MAX_DPATH];
  3136. if (!zfile_readdir_archive (zd, path, true))
  3137. return NULL;
  3138. return zfile_fopen (path, mode, ZFD_ARCHIVE | ZFD_NORECURSE);
  3139. }
  3140. void zfile_resetdir_archive (struct zdirectory *zd)
  3141. {
  3142. zd->offset = 0;
  3143. zd->n = zd->first;
  3144. }
  3145. int zfile_fill_file_attrs_archive (const TCHAR *path, int *isdir, int *flags, TCHAR **comment)
  3146. {
  3147. struct zvolume *zv = get_zvolume (path);
  3148. struct znode *zn = get_znode (zv, path, TRUE);
  3149. *isdir = 0;
  3150. *flags = 0;
  3151. if (comment)
  3152. *comment = 0;
  3153. if (!zn)
  3154. return 0;
  3155. if (zn->type == ZNODE_DIR)
  3156. *isdir = 1;
  3157. else if (zn->type == ZNODE_VDIR)
  3158. *isdir = -1;
  3159. *flags = zn->flags;
  3160. if (zn->comment && comment)
  3161. *comment = my_strdup (zn->comment);
  3162. return 1;
  3163. }
  3164. int zfile_fs_usage_archive (const TCHAR *path, const TCHAR *disk, struct fs_usage *fsp)
  3165. {
  3166. struct zvolume *zv = get_zvolume (path);
  3167. if (!zv)
  3168. return -1;
  3169. fsp->total = zv->size;
  3170. fsp->avail = 0;
  3171. return 0;
  3172. }
  3173. int zfile_stat_archive (const TCHAR *path, struct mystat *s)
  3174. {
  3175. struct zvolume *zv = get_zvolume (path);
  3176. struct znode *zn = get_znode (zv, path, TRUE);
  3177. memset (s, 0, sizeof (struct mystat));
  3178. if (!zn)
  3179. return 0;
  3180. s->size = zn->size;
  3181. s->mtime.tv_sec = zn->mtime.tv_sec;
  3182. s->mtime.tv_usec = zn->mtime.tv_usec;
  3183. return 1;
  3184. }
  3185. uae_s64 zfile_lseek_archive (struct zfile *d, uae_s64 offset, int whence)
  3186. {
  3187. uae_s64 old = zfile_ftell (d);
  3188. if (old < 0 || zfile_fseek (d, offset, whence))
  3189. return -1;
  3190. return old;
  3191. }
  3192. uae_s64 zfile_fsize_archive (struct zfile *d)
  3193. {
  3194. return zfile_size (d);
  3195. }
  3196. unsigned int zfile_read_archive (struct zfile *d, void *b, unsigned int size)
  3197. {
  3198. return zfile_fread (b, 1, size, d);
  3199. }
  3200. void zfile_close_archive (struct zfile *d)
  3201. {
  3202. /* do nothing, keep file cached */
  3203. }
  3204. struct zfile *zfile_open_archive (const TCHAR *path, int flags)
  3205. {
  3206. struct zvolume *zv = get_zvolume (path);
  3207. struct znode *zn = get_znode (zv, path, TRUE);
  3208. struct zfile *z;
  3209. if (!zn)
  3210. return 0;
  3211. if (zn->f) {
  3212. zfile_fseek (zn->f, 0, SEEK_SET);
  3213. return zn->f;
  3214. }
  3215. if (zn->vfile)
  3216. zn = zn->vfile;
  3217. z = archive_getzfile (zn, zn->volume->id, 0);
  3218. if (z)
  3219. zfile_fseek (z, 0, SEEK_SET);
  3220. zn->f = z;
  3221. return zn->f;
  3222. }
  3223. int zfile_exists_archive (const TCHAR *path, const TCHAR *rel)
  3224. {
  3225. TCHAR tmp[MAX_DPATH];
  3226. struct zvolume *zv;
  3227. struct znode *zn;
  3228. _stprintf (tmp, _T("%s%c%s"), path, FSDB_DIR_SEPARATOR, rel);
  3229. zv = get_zvolume (tmp);
  3230. zn = get_znode (zv, tmp, TRUE);
  3231. return zn ? 1 : 0;
  3232. }
  3233. int zfile_convertimage (const TCHAR *src, const TCHAR *dst)
  3234. {
  3235. struct zfile *s, *d;
  3236. int ret = 0;
  3237. s = zfile_fopen (src, _T("rb"), ZFD_NORMAL);
  3238. if (s) {
  3239. uae_u8 *b;
  3240. int size;
  3241. zfile_fseek (s, 0, SEEK_END);
  3242. size = zfile_ftell (s);
  3243. zfile_fseek (s, 0, SEEK_SET);
  3244. b = xcalloc (uae_u8, size);
  3245. if (b) {
  3246. if (zfile_fread (b, size, 1, s) == 1) {
  3247. d = zfile_fopen (dst, _T("wb"), 0);
  3248. if (d) {
  3249. if (zfile_fwrite (b, size, 1, d) == 1)
  3250. ret = 1;
  3251. zfile_fclose (d);
  3252. }
  3253. }
  3254. xfree (b);
  3255. }
  3256. zfile_fclose (s);
  3257. }
  3258. return ret;
  3259. }
  3260. #ifdef _CONSOLE
  3261. static TCHAR *zerror;
  3262. #define WRITE_LOG_BUF_SIZE 4096
  3263. void zfile_seterror (const TCHAR *format, ...)
  3264. {
  3265. int count;
  3266. if (!zerror) {
  3267. TCHAR buffer[WRITE_LOG_BUF_SIZE];
  3268. va_list parms;
  3269. va_start (parms, format);
  3270. count = _vsntprintf (buffer, WRITE_LOG_BUF_SIZE - 1, format, parms);
  3271. zerror = my_strdup (buffer);
  3272. va_end (parms);
  3273. }
  3274. }
  3275. TCHAR *zfile_geterror (void)
  3276. {
  3277. return zerror;
  3278. }
  3279. #else
  3280. void zfile_seterror (const TCHAR *format, ...)
  3281. {
  3282. }
  3283. #endif