PageRenderTime 70ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/zfile_archive.cpp

https://github.com/tonioni/WinUAE
C++ | 2188 lines | 1956 code | 197 blank | 35 comment | 464 complexity | 9c2d7655774818dd36de7bc72efc1954 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * UAE - The Un*x Amiga Emulator
  3. *
  4. * transparent archive handling
  5. *
  6. * 2007 Toni Wilen
  7. */
  8. #include "sysconfig.h"
  9. #include "sysdeps.h"
  10. #ifdef _WIN32
  11. #include <windows.h>
  12. #include "win32.h"
  13. #endif
  14. #include "options.h"
  15. #include "zfile.h"
  16. #include "archivers/zip/unzip.h"
  17. #include "archivers/dms/pfile.h"
  18. #include "crc32.h"
  19. #include "zarchive.h"
  20. #include "disk.h"
  21. #include <zlib.h>
  22. #define unpack_log write_log
  23. #undef unpack_log
  24. #define unpack_log(fmt, ...)
  25. static time_t fromdostime (uae_u32 dd)
  26. {
  27. struct tm tm;
  28. time_t t;
  29. memset (&tm, 0, sizeof tm);
  30. tm.tm_hour = (dd >> 11) & 0x1f;
  31. tm.tm_min = (dd >> 5) & 0x3f;
  32. tm.tm_sec = ((dd >> 0) & 0x1f) * 2;
  33. tm.tm_year = ((dd >> 25) & 0x7f) + 80;
  34. tm.tm_mon = ((dd >> 21) & 0x0f) - 1;
  35. tm.tm_mday = (dd >> 16) & 0x1f;
  36. t = mktime (&tm);
  37. t -= _timezone;
  38. return t;
  39. }
  40. static struct zvolume *getzvolume (struct znode *parent, struct zfile *zf, unsigned int id)
  41. {
  42. struct zvolume *zv = NULL;
  43. switch (id)
  44. {
  45. #ifdef A_ZIP
  46. case ArchiveFormatZIP:
  47. zv = archive_directory_zip (zf);
  48. break;
  49. #endif
  50. #ifdef A_7Z
  51. case ArchiveFormat7Zip:
  52. zv = archive_directory_7z (zf);
  53. break;
  54. #endif
  55. #ifdef A_RAR
  56. case ArchiveFormatRAR:
  57. zv = archive_directory_rar (zf);
  58. break;
  59. #endif
  60. #ifdef A_LHA
  61. case ArchiveFormatLHA:
  62. zv = archive_directory_lha (zf);
  63. break;
  64. #endif
  65. #ifdef A_LZX
  66. case ArchiveFormatLZX:
  67. zv = archive_directory_lzx (zf);
  68. break;
  69. #endif
  70. case ArchiveFormatPLAIN:
  71. zv = archive_directory_plain (zf);
  72. break;
  73. case ArchiveFormatADF:
  74. zv = archive_directory_adf (parent, zf);
  75. break;
  76. case ArchiveFormatRDB:
  77. zv = archive_directory_rdb (zf);
  78. break;
  79. case ArchiveFormatTAR:
  80. zv = archive_directory_tar (zf);
  81. break;
  82. case ArchiveFormatFAT:
  83. zv = archive_directory_fat (zf);
  84. break;
  85. }
  86. #ifdef ARCHIVEACCESS
  87. if (!zv)
  88. zv = archive_directory_arcacc (zf, id);
  89. #endif
  90. return zv;
  91. }
  92. struct zfile *archive_access_select (struct znode *parent, struct zfile *zf, unsigned int id, int dodefault, int *retcode, int index)
  93. {
  94. struct zvolume *zv;
  95. struct znode *zn;
  96. int zipcnt, first, select;
  97. TCHAR tmphist[MAX_DPATH];
  98. struct zfile *z = NULL;
  99. int we_have_file;
  100. int diskimg;
  101. int mask = zf->zfdmask;
  102. int canhistory = (mask & ZFD_DISKHISTORY) && !(mask & ZFD_CHECKONLY);
  103. int getflag = (mask & ZFD_DELAYEDOPEN) ? FILE_DELAYEDOPEN : 0;
  104. if (retcode)
  105. *retcode = 0;
  106. if (index > 0)
  107. return NULL;
  108. if (zfile_needwrite (zf)) {
  109. if (retcode)
  110. *retcode = -1;
  111. return NULL;
  112. }
  113. zv = getzvolume (parent, zf, id);
  114. if (!zv)
  115. return NULL;
  116. we_have_file = 0;
  117. tmphist[0] = 0;
  118. zipcnt = 1;
  119. first = 1;
  120. zn = &zv->root;
  121. while (zn) {
  122. int isok = 1;
  123. diskimg = -1;
  124. if (zn->type != ZNODE_FILE)
  125. isok = 0;
  126. if (zfile_is_ignore_ext (zn->fullname))
  127. isok = 0;
  128. diskimg = zfile_is_diskimage (zn->fullname);
  129. if (isok) {
  130. if (tmphist[0]) {
  131. #ifndef _CONSOLE
  132. if (diskimg >= 0 && canhistory)
  133. DISK_history_add (tmphist, -1, diskimg, 1);
  134. #endif
  135. tmphist[0] = 0;
  136. first = 0;
  137. }
  138. if (first) {
  139. if (diskimg >= 0)
  140. _tcscpy (tmphist, zn->fullname);
  141. } else {
  142. _tcscpy (tmphist, zn->fullname);
  143. #ifndef _CONSOLE
  144. if (diskimg >= 0 && canhistory)
  145. DISK_history_add (tmphist, -1, diskimg, 1);
  146. #endif
  147. tmphist[0] = 0;
  148. }
  149. select = 0;
  150. if (!zf->zipname)
  151. select = 1;
  152. if (zf->zipname && _tcslen (zn->fullname) >= _tcslen (zf->zipname) && !strcasecmp (zf->zipname, zn->fullname + _tcslen (zn->fullname) - _tcslen (zf->zipname)))
  153. select = -1;
  154. if (zf->zipname && zf->zipname[0] == '#' && _tstol (zf->zipname + 1) == zipcnt)
  155. select = -1;
  156. if (select && we_have_file < 10) {
  157. struct zfile *zt = NULL;
  158. TCHAR *ext = _tcsrchr (zn->fullname, '.');
  159. int whf = 1;
  160. int ft = 0;
  161. if (mask & ZFD_CD) {
  162. if (ext && !_tcsicmp (ext, _T(".iso"))) {
  163. whf = 2;
  164. ft = ZFILE_CDIMAGE;
  165. }
  166. if (ext && !_tcsicmp (ext, _T(".chd"))) {
  167. whf = 2;
  168. ft = ZFILE_CDIMAGE;
  169. }
  170. if (ext && !_tcsicmp (ext, _T(".ccd"))) {
  171. whf = 9;
  172. ft = ZFILE_CDIMAGE;
  173. }
  174. if (ext && !_tcsicmp (ext, _T(".cue"))) {
  175. whf = 10;
  176. ft = ZFILE_CDIMAGE;
  177. }
  178. } else {
  179. zt = archive_getzfile (zn, id, getflag);
  180. ft = zfile_gettype (zt);
  181. }
  182. if ((select < 0 || ft) && whf > we_have_file) {
  183. if (!zt)
  184. zt = archive_getzfile (zn, id, getflag);
  185. we_have_file = whf;
  186. if (z)
  187. zfile_fclose (z);
  188. z = zt;
  189. zt = NULL;
  190. }
  191. zfile_fclose (zt);
  192. }
  193. }
  194. zipcnt++;
  195. zn = zn->next;
  196. }
  197. #ifndef _CONSOLE
  198. diskimg = zfile_is_diskimage (zfile_getname (zf));
  199. if (diskimg >= 0 && first && tmphist[0] && canhistory)
  200. DISK_history_add (zfile_getname (zf), -1, diskimg, 1);
  201. #endif
  202. zfile_fclose_archive (zv);
  203. if (z) {
  204. zfile_fclose (zf);
  205. zf = z;
  206. } else if (!dodefault && zf->zipname && zf->zipname[0]) {
  207. if (retcode)
  208. *retcode = -1;
  209. zf = NULL;
  210. } else {
  211. zf = NULL;
  212. }
  213. return zf;
  214. }
  215. struct zfile *archive_access_arcacc_select (struct zfile *zf, unsigned int id, int *retcode)
  216. {
  217. if (zfile_needwrite (zf)) {
  218. if (retcode)
  219. *retcode = -1;
  220. return NULL;
  221. }
  222. return zf;
  223. }
  224. void archive_access_scan (struct zfile *zf, zfile_callback zc, void *user, unsigned int id)
  225. {
  226. struct zvolume *zv;
  227. struct znode *zn;
  228. zv = getzvolume (NULL, zf, id);
  229. if (!zv)
  230. return;
  231. zn = &zv->root;
  232. while (zn) {
  233. if (zn->type == ZNODE_FILE) {
  234. struct zfile *zf2 = archive_getzfile (zn, id, 0);
  235. if (zf2) {
  236. int ztype = iszip (zf2);
  237. if (ztype) {
  238. zfile_fclose (zf2);
  239. } else {
  240. int ret = zc (zf2, user);
  241. zfile_fclose (zf2);
  242. if (ret)
  243. break;
  244. }
  245. }
  246. }
  247. zn = zn->next;
  248. }
  249. zfile_fclose_archive (zv);
  250. }
  251. /* TAR */
  252. static void archive_close_tar (void *handle)
  253. {
  254. }
  255. struct zvolume *archive_directory_tar (struct zfile *z)
  256. {
  257. struct zvolume *zv;
  258. struct znode *zn;
  259. _tzset ();
  260. zv = zvolume_alloc (z, ArchiveFormatTAR, NULL, NULL);
  261. for (;;) {
  262. uae_u8 block[512];
  263. char name[MAX_DPATH];
  264. int ustar = 0;
  265. struct zarchive_info zai;
  266. int valid = 1;
  267. uae_u64 size;
  268. if (zfile_fread (block, 512, 1, z) != 1)
  269. break;
  270. if (block[0] == 0)
  271. break;
  272. if (!memcmp (block + 257, "ustar ", 8))
  273. ustar = 1;
  274. name[0] = 0;
  275. if (ustar)
  276. strcpy (name, (char*)block + 345);
  277. strcat (name, (char*)block);
  278. if (name[0] == 0)
  279. valid = 0;
  280. if (block[156] != '0')
  281. valid = 0;
  282. if (ustar && (block[256] != 0 && block[256] != '0'))
  283. valid = 0;
  284. size = _strtoui64 ((char*)block + 124, NULL, 8);
  285. if (valid) {
  286. memset (&zai, 0, sizeof zai);
  287. zai.name = au (name);
  288. zai.size = size;
  289. zai.tv.tv_sec = _strtoui64 ((char*)block + 136, NULL, 8);
  290. zai.tv.tv_sec += _timezone;
  291. if (_daylight)
  292. zai.tv.tv_sec -= 1 * 60 * 60;
  293. if (zai.name[_tcslen (zai.name) - 1] == '/') {
  294. zn = zvolume_adddir_abs (zv, &zai);
  295. } else {
  296. zn = zvolume_addfile_abs (zv, &zai);
  297. if (zn)
  298. zn->offset = zfile_ftell (z);
  299. }
  300. xfree (zai.name);
  301. }
  302. zfile_fseek (z, (size + 511) & ~511, SEEK_CUR);
  303. }
  304. zv->method = ArchiveFormatTAR;
  305. return zv;
  306. }
  307. struct zfile *archive_access_tar (struct znode *zn)
  308. {
  309. #if 0
  310. struct zfile *zf = zfile_fopen_empty (zn->volume->archive, zn->fullname, zn->size);
  311. zfile_fseek (zn->volume->archive, zn->offset, SEEK_SET);
  312. zfile_fwrite (zf->data, zn->size, 1, zn->volume->archive);
  313. return zf;
  314. #else
  315. return zfile_fopen_parent (zn->volume->archive, zn->fullname, zn->offset, zn->size);
  316. #endif
  317. }
  318. /* ZIP */
  319. #ifdef A_ZIP
  320. static void archive_close_zip (void *handle)
  321. {
  322. }
  323. struct zvolume *archive_directory_zip (struct zfile *z)
  324. {
  325. unzFile uz;
  326. unz_file_info file_info;
  327. struct zvolume *zv;
  328. int err;
  329. uz = unzOpen (z);
  330. if (!uz)
  331. return 0;
  332. if (unzGoToFirstFile (uz) != UNZ_OK)
  333. return 0;
  334. zv = zvolume_alloc (z, ArchiveFormatZIP, NULL, NULL);
  335. for (;;) {
  336. char filename_inzip2[MAX_DPATH];
  337. TCHAR c;
  338. struct zarchive_info zai;
  339. time_t t;
  340. unsigned int dd;
  341. TCHAR *filename_inzip;
  342. err = unzGetCurrentFileInfo (uz, &file_info, filename_inzip2, sizeof (filename_inzip2), NULL, 0, NULL, 0);
  343. if (err != UNZ_OK)
  344. return 0;
  345. if (file_info.flag & (1 << 11)) { // UTF-8 encoded
  346. filename_inzip = utf8u (filename_inzip2);
  347. } else {
  348. filename_inzip = au (filename_inzip2);
  349. }
  350. dd = file_info.dosDate;
  351. t = fromdostime (dd);
  352. memset (&zai, 0, sizeof zai);
  353. zai.name = filename_inzip;
  354. zai.tv.tv_sec = t;
  355. zai.flags = -1;
  356. c = filename_inzip[_tcslen (filename_inzip) - 1];
  357. if (c != '/' && c != '\\') {
  358. int err = unzOpenCurrentFile (uz);
  359. if (err == UNZ_OK) {
  360. struct znode *zn;
  361. zai.size = file_info.uncompressed_size;
  362. zn = zvolume_addfile_abs (zv, &zai);
  363. }
  364. } else {
  365. filename_inzip[_tcslen (filename_inzip) - 1] = 0;
  366. zvolume_adddir_abs (zv, &zai);
  367. }
  368. xfree (filename_inzip);
  369. err = unzGoToNextFile (uz);
  370. if (err != UNZ_OK)
  371. break;
  372. }
  373. unzClose (uz);
  374. zv->method = ArchiveFormatZIP;
  375. return zv;
  376. }
  377. static struct zfile *archive_do_zip (struct znode *zn, struct zfile *z, int flags)
  378. {
  379. unzFile uz;
  380. int i;
  381. TCHAR tmp[MAX_DPATH];
  382. TCHAR *name = z ? z->archiveparent->name : zn->volume->root.fullname;
  383. char *s;
  384. uz = unzOpen (z ? z->archiveparent : zn->volume->archive);
  385. if (!uz)
  386. return 0;
  387. if (z)
  388. _tcscpy (tmp, z->archiveparent->name);
  389. else
  390. _tcscpy (tmp, zn->fullname + _tcslen (zn->volume->root.fullname) + 1);
  391. if (unzGoToFirstFile (uz) != UNZ_OK)
  392. goto error;
  393. for (i = 0; tmp[i]; i++) {
  394. if (tmp[i] == '\\')
  395. tmp[i] = '/';
  396. }
  397. s = ua (tmp);
  398. if (unzLocateFile (uz, s, 1) != UNZ_OK) {
  399. xfree (s);
  400. for (i = 0; tmp[i]; i++) {
  401. if (tmp[i] == '/')
  402. tmp[i] = '\\';
  403. }
  404. s = ua (tmp);
  405. if (unzLocateFile (uz, s, 1) != UNZ_OK) {
  406. xfree (s);
  407. goto error;
  408. }
  409. }
  410. xfree (s);
  411. s = NULL;
  412. if (unzOpenCurrentFile (uz) != UNZ_OK)
  413. goto error;
  414. if (!z)
  415. z = zfile_fopen_empty (NULL, zn->fullname, zn->size);
  416. if (z) {
  417. int err = -1;
  418. if (!(flags & FILE_DELAYEDOPEN) || z->size <= PEEK_BYTES) {
  419. unpack_log (_T("ZIP: unpacking %s, flags=%d\n"), name, flags);
  420. err = unzReadCurrentFile (uz, z->data, z->datasize);
  421. unpack_log (_T("ZIP: unpacked, code=%d\n"), err);
  422. } else {
  423. z->archiveparent = zfile_dup (zn->volume->archive);
  424. if (z->archiveparent) {
  425. unpack_log (_T("ZIP: delayed open '%s'\n"), name);
  426. xfree (z->archiveparent->name);
  427. z->archiveparent->name = my_strdup (tmp);
  428. z->datasize = PEEK_BYTES;
  429. err = unzReadCurrentFile (uz, z->data, z->datasize);
  430. unpack_log (_T("ZIP: unpacked, code=%d\n"), err);
  431. } else {
  432. unpack_log (_T("ZIP: unpacking %s (failed DELAYEDOPEN)\n"), name);
  433. err = unzReadCurrentFile (uz, z->data, z->datasize);
  434. unpack_log (_T("ZIP: unpacked, code=%d\n"), err);
  435. }
  436. }
  437. }
  438. unzCloseCurrentFile (uz);
  439. unzClose (uz);
  440. return z;
  441. error:
  442. unzClose (uz);
  443. return NULL;
  444. }
  445. static struct zfile *archive_access_zip (struct znode *zn, int flags)
  446. {
  447. return archive_do_zip (zn, NULL, flags);
  448. }
  449. static struct zfile *archive_unpack_zip (struct zfile *zf)
  450. {
  451. return archive_do_zip (NULL, zf, 0);
  452. }
  453. #endif
  454. #ifdef A_7Z
  455. /* 7Z */
  456. #include "7z/7z.h"
  457. #include "7z/Alloc.h"
  458. #include "7z/7zFile.h"
  459. #include "7z/7zVersion.h"
  460. #include "7z/7zCrc.h"
  461. static void *SzAlloc (void *p, size_t size)
  462. {
  463. return xmalloc (uae_u8, size);
  464. }
  465. static void SzFree(void *p, void *address)
  466. {
  467. xfree (address);
  468. }
  469. static ISzAlloc allocImp;
  470. static ISzAlloc allocTempImp;
  471. static SRes SzFileReadImp (void *object, void *buffer, size_t *size)
  472. {
  473. CFileInStream *s = (CFileInStream *)object;
  474. struct zfile *zf = (struct zfile*)s->file.myhandle;
  475. *size = zfile_fread (buffer, 1, *size, zf);
  476. return SZ_OK;
  477. }
  478. static SRes SzFileSeekImp(void *object, Int64 *pos, ESzSeek origin)
  479. {
  480. CFileInStream *s = (CFileInStream *)object;
  481. struct zfile *zf = (struct zfile*)s->file.myhandle;
  482. int org = 0;
  483. switch (origin)
  484. {
  485. case SZ_SEEK_SET: org = SEEK_SET; break;
  486. case SZ_SEEK_CUR: org = SEEK_CUR; break;
  487. case SZ_SEEK_END: org = SEEK_END; break;
  488. }
  489. zfile_fseek (zf, *pos, org);
  490. *pos = zfile_ftell (zf);
  491. return SZ_OK;
  492. }
  493. static void init_7z (void)
  494. {
  495. static int initialized;
  496. if (initialized)
  497. return;
  498. initialized = 1;
  499. allocImp.Alloc = SzAlloc;
  500. allocImp.Free = SzFree;
  501. allocTempImp.Alloc = SzAlloc;
  502. allocTempImp.Free = SzFree;
  503. CrcGenerateTable ();
  504. _tzset ();
  505. }
  506. struct SevenZContext
  507. {
  508. CSzArEx db;
  509. CFileInStream archiveStream;
  510. CLookToRead lookStream;
  511. Byte *outBuffer;
  512. size_t outBufferSize;
  513. UInt32 blockIndex;
  514. };
  515. static void archive_close_7z (void *ctx)
  516. {
  517. struct SevenZContext *ctx7 = (struct SevenZContext*)ctx;
  518. SzArEx_Free (&ctx7->db, &allocImp);
  519. allocImp.Free (&allocImp, ctx7->outBuffer);
  520. xfree (ctx);
  521. }
  522. #define EPOCH_DIFF 0x019DB1DED53E8000LL /* 116444736000000000 nsecs */
  523. #define RATE_DIFF 10000000 /* 100 nsecs */
  524. struct zvolume *archive_directory_7z (struct zfile *z)
  525. {
  526. SRes res;
  527. struct zvolume *zv;
  528. int i;
  529. struct SevenZContext *ctx;
  530. init_7z ();
  531. ctx = xcalloc (struct SevenZContext, 1);
  532. ctx->blockIndex = 0xffffffff;
  533. ctx->archiveStream.s.Read = SzFileReadImp;
  534. ctx->archiveStream.s.Seek = SzFileSeekImp;
  535. ctx->archiveStream.file.myhandle = (void*)z;
  536. LookToRead_CreateVTable (&ctx->lookStream, False);
  537. ctx->lookStream.realStream = &ctx->archiveStream.s;
  538. LookToRead_Init (&ctx->lookStream);
  539. SzArEx_Init (&ctx->db);
  540. res = SzArEx_Open (&ctx->db, &ctx->lookStream.s, &allocImp, &allocTempImp);
  541. if (res != SZ_OK) {
  542. write_log (_T("7Z: SzArchiveOpen %s returned %d\n"), zfile_getname (z), res);
  543. xfree (ctx);
  544. return NULL;
  545. }
  546. zv = zvolume_alloc (z, ArchiveFormat7Zip, ctx, NULL);
  547. for (i = 0; i < ctx->db.db.NumFiles; i++) {
  548. CSzFileItem *f = ctx->db.db.Files + i;
  549. TCHAR *name = (TCHAR*)(ctx->db.FileNames.data + ctx->db.FileNameOffsets[i] * 2);
  550. struct zarchive_info zai;
  551. memset(&zai, 0, sizeof zai);
  552. zai.name = name;
  553. zai.flags = f->AttribDefined ? f->Attrib : -1;
  554. zai.size = f->Size;
  555. if (f->MTimeDefined) {
  556. uae_u64 t = (((uae_u64)f->MTime.High) << 32) | f->MTime.Low;
  557. if (t >= EPOCH_DIFF) {
  558. zai.tv.tv_sec = (t - EPOCH_DIFF) / RATE_DIFF;
  559. zai.tv.tv_sec -= _timezone;
  560. if (_daylight)
  561. zai.tv.tv_sec += 1 * 60 * 60;
  562. }
  563. }
  564. if (!f->IsDir) {
  565. struct znode *zn = zvolume_addfile_abs (zv, &zai);
  566. if (zn)
  567. zn->offset = i;
  568. }
  569. }
  570. zv->method = ArchiveFormat7Zip;
  571. return zv;
  572. }
  573. static struct zfile *archive_access_7z (struct znode *zn)
  574. {
  575. SRes res;
  576. struct zvolume *zv = zn->volume;
  577. struct zfile *z = NULL;
  578. size_t offset;
  579. size_t outSizeProcessed;
  580. struct SevenZContext *ctx;
  581. z = zfile_fopen_empty (NULL, zn->fullname, zn->size);
  582. if (!z)
  583. return NULL;
  584. ctx = (struct SevenZContext*)zv->handle;
  585. res = SzArEx_Extract (&ctx->db, &ctx->lookStream.s, zn->offset,
  586. &ctx->blockIndex, &ctx->outBuffer, &ctx->outBufferSize,
  587. &offset, &outSizeProcessed,
  588. &allocImp, &allocTempImp);
  589. if (res == SZ_OK) {
  590. zfile_fwrite (ctx->outBuffer + offset, zn->size, 1, z);
  591. } else {
  592. write_log (_T("7Z: SzExtract %s returned %d\n"), zn->fullname, res);
  593. zfile_fclose (z);
  594. z = NULL;
  595. }
  596. return z;
  597. }
  598. #endif
  599. /* RAR */
  600. #ifdef A_RAR
  601. /* copy and paste job? you are only imagining it! */
  602. static struct zfile *rarunpackzf; /* stupid unrar.dll */
  603. #include <unrar.h>
  604. typedef HANDLE (_stdcall* RAROPENARCHIVEEX)(struct RAROpenArchiveDataEx*);
  605. static RAROPENARCHIVEEX pRAROpenArchiveEx;
  606. typedef int (_stdcall* RARREADHEADEREX)(HANDLE,struct RARHeaderDataEx*);
  607. static RARREADHEADEREX pRARReadHeaderEx;
  608. typedef int (_stdcall* RARPROCESSFILE)(HANDLE,int,char*,char*);
  609. static RARPROCESSFILE pRARProcessFile;
  610. typedef int (_stdcall* RARCLOSEARCHIVE)(HANDLE);
  611. static RARCLOSEARCHIVE pRARCloseArchive;
  612. typedef void (_stdcall* RARSETCALLBACK)(HANDLE,UNRARCALLBACK,LONG);
  613. static RARSETCALLBACK pRARSetCallback;
  614. typedef int (_stdcall* RARGETDLLVERSION)(void);
  615. static RARGETDLLVERSION pRARGetDllVersion;
  616. static int canrar (void)
  617. {
  618. static int israr;
  619. if (israr == 0) {
  620. israr = -1;
  621. #ifdef _WIN32
  622. {
  623. HMODULE rarlib;
  624. rarlib = WIN32_LoadLibrary (_T("unrar.dll"));
  625. if (rarlib) {
  626. TCHAR tmp[MAX_DPATH];
  627. tmp[0] = 0;
  628. GetModuleFileName (rarlib, tmp, sizeof tmp / sizeof (TCHAR));
  629. pRAROpenArchiveEx = (RAROPENARCHIVEEX)GetProcAddress (rarlib, "RAROpenArchiveEx");
  630. pRARReadHeaderEx = (RARREADHEADEREX)GetProcAddress (rarlib, "RARReadHeaderEx");
  631. pRARProcessFile = (RARPROCESSFILE)GetProcAddress (rarlib, "RARProcessFile");
  632. pRARCloseArchive = (RARCLOSEARCHIVE)GetProcAddress (rarlib, "RARCloseArchive");
  633. pRARSetCallback = (RARSETCALLBACK)GetProcAddress (rarlib, "RARSetCallback");
  634. pRARGetDllVersion = (RARGETDLLVERSION)GetProcAddress (rarlib, "RARGetDllVersion");
  635. if (pRAROpenArchiveEx && pRARReadHeaderEx && pRARProcessFile && pRARCloseArchive && pRARSetCallback) {
  636. int version = -1;
  637. israr = 1;
  638. if (pRARGetDllVersion)
  639. version = pRARGetDllVersion ();
  640. write_log (_T("%s version %08X detected\n"), tmp, version);
  641. if (version < 4) {
  642. write_log (_T("Too old unrar.dll, must be at least version 4\n"));
  643. israr = -1;
  644. }
  645. }
  646. }
  647. }
  648. #endif
  649. }
  650. return israr < 0 ? 0 : 1;
  651. }
  652. static int CALLBACK RARCallbackProc (UINT msg, LPARAM UserData, LPARAM P1, LPARAM P2)
  653. {
  654. if (msg == UCM_PROCESSDATA) {
  655. zfile_fwrite ((uae_u8*)P1, 1, P2, rarunpackzf);
  656. return 0;
  657. }
  658. return -1;
  659. }
  660. struct RARContext
  661. {
  662. struct RAROpenArchiveDataEx OpenArchiveData;
  663. struct RARHeaderDataEx HeaderData;
  664. HANDLE hArcData;
  665. };
  666. static void archive_close_rar (void *ctx)
  667. {
  668. struct RARContext* rc = (struct RARContext*)ctx;
  669. xfree (rc);
  670. }
  671. struct zvolume *archive_directory_rar (struct zfile *z)
  672. {
  673. struct zvolume *zv;
  674. struct RARContext *rc;
  675. struct zfile *zftmp;
  676. int cnt;
  677. if (!canrar ())
  678. return archive_directory_arcacc (z, ArchiveFormatRAR);
  679. if (z->data)
  680. /* wtf? stupid unrar.dll only accept filename as an input.. */
  681. return archive_directory_arcacc (z, ArchiveFormatRAR);
  682. rc = xcalloc (struct RARContext, 1);
  683. zv = zvolume_alloc (z, ArchiveFormatRAR, rc, NULL);
  684. rc->OpenArchiveData.ArcNameW = z->name;
  685. rc->OpenArchiveData.OpenMode = RAR_OM_LIST;
  686. rc->hArcData = pRAROpenArchiveEx (&rc->OpenArchiveData);
  687. if (rc->OpenArchiveData.OpenResult != 0) {
  688. zfile_fclose_archive (zv);
  689. return archive_directory_arcacc (z, ArchiveFormatRAR);
  690. }
  691. pRARSetCallback (rc->hArcData, RARCallbackProc, 0);
  692. cnt = 0;
  693. while (pRARReadHeaderEx (rc->hArcData, &rc->HeaderData) == 0) {
  694. struct zarchive_info zai;
  695. struct znode *zn;
  696. memset (&zai, 0, sizeof zai);
  697. zai.name = rc->HeaderData.FileNameW;
  698. zai.size = rc->HeaderData.UnpSize;
  699. zai.flags = -1;
  700. zai.tv.tv_sec = fromdostime (rc->HeaderData.FileTime);
  701. zn = zvolume_addfile_abs (zv, &zai);
  702. if (zn)
  703. zn->offset = cnt++;
  704. pRARProcessFile (rc->hArcData, RAR_SKIP, NULL, NULL);
  705. }
  706. pRARCloseArchive (rc->hArcData);
  707. zftmp = zfile_fopen_empty (z, z->name, 0);
  708. zv->archive = zftmp;
  709. zv->method = ArchiveFormatRAR;
  710. return zv;
  711. }
  712. static struct zfile *archive_access_rar (struct znode *zn)
  713. {
  714. struct RARContext *rc = (struct RARContext*)zn->volume->handle;
  715. int i;
  716. struct zfile *zf = NULL;
  717. if (zn->volume->method != ArchiveFormatRAR)
  718. return archive_access_arcacc (zn);
  719. rc->OpenArchiveData.OpenMode = RAR_OM_EXTRACT;
  720. rc->hArcData = pRAROpenArchiveEx (&rc->OpenArchiveData);
  721. if (rc->OpenArchiveData.OpenResult != 0)
  722. return NULL;
  723. pRARSetCallback (rc->hArcData, RARCallbackProc, 0);
  724. for (i = 0; i <= zn->offset; i++) {
  725. if (pRARReadHeaderEx (rc->hArcData, &rc->HeaderData))
  726. return NULL;
  727. if (i < zn->offset) {
  728. if (pRARProcessFile (rc->hArcData, RAR_SKIP, NULL, NULL))
  729. goto end;
  730. }
  731. }
  732. zf = zfile_fopen_empty (zn->volume->archive, zn->fullname, zn->size);
  733. if (zf) {
  734. rarunpackzf = zf;
  735. if (pRARProcessFile (rc->hArcData, RAR_TEST, NULL, NULL)) {
  736. zfile_fclose (zf);
  737. zf = NULL;
  738. }
  739. }
  740. end:
  741. pRARCloseArchive(rc->hArcData);
  742. return zf;
  743. }
  744. #endif
  745. /* ArchiveAccess */
  746. #if defined(ARCHIVEACCESS)
  747. struct aaFILETIME
  748. {
  749. uae_u32 dwLowDateTime;
  750. uae_u32 dwHighDateTime;
  751. };
  752. typedef void* aaHandle;
  753. // This struct contains file information from an archive. The caller may store
  754. // this information for accessing this file after calls to findFirst, findNext
  755. #define FileInArchiveInfoStringSize 1024
  756. struct aaFileInArchiveInfo {
  757. int ArchiveHandle; // handle for Archive/class pointer
  758. uae_u64 CompressedFileSize;
  759. uae_u64 UncompressedFileSize;
  760. uae_u32 attributes;
  761. int IsDir;
  762. struct aaFILETIME LastWriteTime;
  763. char path[FileInArchiveInfoStringSize];
  764. };
  765. typedef HRESULT (__stdcall *aaReadCallback)(int StreamID, uae_u64 offset, uae_u32 count, void* buf, uae_u32 *processedSize);
  766. typedef HRESULT (__stdcall *aaWriteCallback)(int StreamID, uae_u64 offset, uae_u32 count, const void *buf, uae_u32 *processedSize);
  767. typedef aaHandle (__stdcall *aapOpenArchive)(aaReadCallback function, int StreamID, uae_u64 FileSize, int ArchiveType, int *result, TCHAR *password);
  768. typedef int (__stdcall *aapGetFileCount)(aaHandle ArchiveHandle);
  769. typedef int (__stdcall *aapGetFileInfo)(aaHandle ArchiveHandle, int FileNum, struct aaFileInArchiveInfo *FileInfo);
  770. typedef int (__stdcall *aapExtract)(aaHandle ArchiveHandle, int FileNum, int StreamID, aaWriteCallback WriteFunc, uae_u64 *written);
  771. typedef int (__stdcall *aapCloseArchive)(aaHandle ArchiveHandle);
  772. static aapOpenArchive aaOpenArchive;
  773. static aapGetFileCount aaGetFileCount;
  774. static aapGetFileInfo aaGetFileInfo;
  775. static aapExtract aaExtract;
  776. static aapCloseArchive aaCloseArchive;
  777. #ifdef _WIN32
  778. static HMODULE arcacc_mod;
  779. static void arcacc_free (void)
  780. {
  781. if (arcacc_mod)
  782. FreeLibrary (arcacc_mod);
  783. arcacc_mod = NULL;
  784. }
  785. static int arcacc_init (struct zfile *zf)
  786. {
  787. if (arcacc_mod)
  788. return 1;
  789. arcacc_mod = WIN32_LoadLibrary (_T("archiveaccess.dll"));
  790. if (!arcacc_mod) {
  791. write_log (_T("failed to open archiveaccess.dll ('%s')\n"), zfile_getname (zf));
  792. return 0;
  793. }
  794. aaOpenArchive = (aapOpenArchive) GetProcAddress (arcacc_mod, "aaOpenArchive");
  795. aaGetFileCount = (aapGetFileCount) GetProcAddress (arcacc_mod, "aaGetFileCount");
  796. aaGetFileInfo = (aapGetFileInfo) GetProcAddress (arcacc_mod, "aaGetFileInfo");
  797. aaExtract = (aapExtract) GetProcAddress (arcacc_mod, "aaExtract");
  798. aaCloseArchive = (aapCloseArchive) GetProcAddress (arcacc_mod, "aaCloseArchive");
  799. if (!aaOpenArchive || !aaGetFileCount || !aaGetFileInfo || !aaExtract || !aaCloseArchive) {
  800. write_log (_T("Missing functions in archiveaccess.dll. Old version?\n"));
  801. arcacc_free ();
  802. return 0;
  803. }
  804. return 1;
  805. }
  806. #endif
  807. #define ARCACC_STACKSIZE 10
  808. static struct zfile *arcacc_stack[ARCACC_STACKSIZE];
  809. static int arcacc_stackptr = -1;
  810. static int arcacc_push (struct zfile *f)
  811. {
  812. if (arcacc_stackptr == ARCACC_STACKSIZE - 1)
  813. return -1;
  814. arcacc_stackptr++;
  815. arcacc_stack[arcacc_stackptr] = f;
  816. return arcacc_stackptr;
  817. }
  818. static void arcacc_pop (void)
  819. {
  820. arcacc_stackptr--;
  821. }
  822. static HRESULT __stdcall readCallback (int StreamID, uae_u64 offset, uae_u32 count, void *buf, uae_u32 *processedSize)
  823. {
  824. struct zfile *f = arcacc_stack[StreamID];
  825. int ret;
  826. zfile_fseek (f, (long)offset, SEEK_SET);
  827. ret = zfile_fread (buf, 1, count, f);
  828. if (processedSize)
  829. *processedSize = ret;
  830. return 0;
  831. }
  832. static HRESULT __stdcall writeCallback (int StreamID, uae_u64 offset, uae_u32 count, const void *buf, uae_u32 *processedSize)
  833. {
  834. struct zfile *f = arcacc_stack[StreamID];
  835. int ret;
  836. ret = zfile_fwrite ((void*)buf, 1, count, f);
  837. if (processedSize)
  838. *processedSize = ret;
  839. if (ret != count)
  840. return -1;
  841. return 0;
  842. }
  843. struct zvolume *archive_directory_arcacc (struct zfile *z, unsigned int id)
  844. {
  845. aaHandle ah;
  846. int id_r, status;
  847. int fc, f;
  848. struct zvolume *zv;
  849. int skipsize = 0;
  850. if (!arcacc_init (z))
  851. return NULL;
  852. zv = zvolume_alloc (z, ArchiveFormatAA, NULL, NULL);
  853. id_r = arcacc_push (z);
  854. ah = aaOpenArchive (readCallback, id_r, zv->archivesize, id, &status, NULL);
  855. if (!status) {
  856. zv->handle = ah;
  857. fc = aaGetFileCount (ah);
  858. for (f = 0; f < fc; f++) {
  859. struct aaFileInArchiveInfo fi;
  860. TCHAR *name;
  861. struct znode *zn;
  862. struct zarchive_info zai;
  863. memset (&fi, 0, sizeof (fi));
  864. aaGetFileInfo (ah, f, &fi);
  865. if (fi.IsDir)
  866. continue;
  867. name = au (fi.path);
  868. memset (&zai, 0, sizeof zai);
  869. zai.name = name;
  870. zai.flags = -1;
  871. zai.size = (unsigned int)fi.UncompressedFileSize;
  872. zn = zvolume_addfile_abs (zv, &zai);
  873. if (zn) {
  874. zn->offset = f;
  875. zn->method = id;
  876. }
  877. xfree(name);
  878. if (id == ArchiveFormat7Zip) {
  879. if (fi.CompressedFileSize)
  880. skipsize = 0;
  881. skipsize += (int)fi.UncompressedFileSize;
  882. }
  883. }
  884. aaCloseArchive (ah);
  885. }
  886. arcacc_pop ();
  887. zv->method = ArchiveFormatAA;
  888. return zv;
  889. }
  890. static struct zfile *archive_access_arcacc (struct znode *zn)
  891. {
  892. struct zfile *zf = NULL;
  893. struct zfile *z = zn->volume->archive;
  894. int status, id_r, id_w;
  895. aaHandle ah;
  896. int ok = 0;
  897. id_r = arcacc_push (z);
  898. ah = aaOpenArchive (readCallback, id_r, zn->volume->archivesize, zn->method, &status, NULL);
  899. if (!status) {
  900. int err;
  901. uae_u64 written = 0;
  902. struct aaFileInArchiveInfo fi;
  903. memset (&fi, 0, sizeof (fi));
  904. aaGetFileInfo (ah, zn->offset, &fi);
  905. zf = zfile_fopen_empty (z, zn->fullname, zn->size);
  906. id_w = arcacc_push (zf);
  907. err = aaExtract(ah, zn->offset, id_w, writeCallback, &written);
  908. if (zf->seek == fi.UncompressedFileSize)
  909. ok = 1;
  910. arcacc_pop();
  911. }
  912. aaCloseArchive(ah);
  913. arcacc_pop();
  914. if (ok)
  915. return zf;
  916. zfile_fclose(zf);
  917. return NULL;
  918. }
  919. #endif
  920. /* plain single file */
  921. static struct znode *addfile (struct zvolume *zv, struct zfile *zf, const TCHAR *path, uae_u8 *data, int size)
  922. {
  923. struct zarchive_info zai;
  924. struct znode *zn;
  925. struct zfile *z;
  926. z = zfile_fopen_empty (zf, path, size);
  927. if (!z)
  928. return NULL;
  929. zfile_fwrite (data, size, 1, z);
  930. memset (&zai, 0, sizeof zai);
  931. zai.name = my_strdup (path);
  932. zai.flags = -1;
  933. zai.size = size;
  934. zn = zvolume_addfile_abs (zv, &zai);
  935. if (zn)
  936. zn->f = z;
  937. else
  938. zfile_fclose (z);
  939. xfree (zai.name);
  940. return zn;
  941. }
  942. static uae_u8 exeheader[]={0x00,0x00,0x03,0xf3,0x00,0x00,0x00,0x00};
  943. struct zvolume *archive_directory_plain (struct zfile *z)
  944. {
  945. struct zfile *zf, *zf2;
  946. struct zvolume *zv;
  947. struct znode *zn;
  948. struct zarchive_info zai;
  949. uae_u8 id[8];
  950. int rc, index;
  951. memset (&zai, 0, sizeof zai);
  952. zv = zvolume_alloc (z, ArchiveFormatPLAIN, NULL, NULL);
  953. memset(id, 0, sizeof id);
  954. zai.name = zfile_getfilename (z);
  955. zai.flags = -1;
  956. zfile_fseek(z, 0, SEEK_END);
  957. zai.size = zfile_ftell (z);
  958. zfile_fseek(z, 0, SEEK_SET);
  959. zfile_fread(id, sizeof id, 1, z);
  960. zfile_fseek(z, 0, SEEK_SET);
  961. zn = zvolume_addfile_abs (zv, &zai);
  962. if (!memcmp (id, exeheader, sizeof id)) {
  963. char *an = ua (zai.name);
  964. char *data = xmalloc (char, 1 + strlen (an) + 1 + 1 + 1);
  965. sprintf (data, "\"%s\"\n", an);
  966. zn = addfile (zv, z, _T("s/startup-sequence"), (uae_u8*)data, strlen (data));
  967. xfree (data);
  968. xfree (an);
  969. }
  970. index = 0;
  971. for (;;) {
  972. zf = zfile_dup (z);
  973. if (!zf)
  974. break;
  975. zf2 = zuncompress (NULL, zf, 0, ZFD_ALL & ~ZFD_ADF, &rc, index);
  976. if (zf2) {
  977. zf = NULL;
  978. zai.name = zfile_getfilename (zf2);
  979. zai.flags = -1;
  980. zfile_fseek (zf2, 0, SEEK_END);
  981. zai.size = zfile_ftell (zf2);
  982. zfile_fseek (zf2, 0, SEEK_SET);
  983. zn = zvolume_addfile_abs (zv, &zai);
  984. if (zn)
  985. zn->f = zf2;
  986. // if (zn)
  987. // zn->offset = index + 1;
  988. // zfile_fclose (zf2);
  989. } else {
  990. if (rc == 0) {
  991. zfile_fclose (zf);
  992. break;
  993. }
  994. }
  995. index++;
  996. zfile_fclose (zf);
  997. }
  998. return zv;
  999. }
  1000. static struct zfile *archive_access_plain (struct znode *zn)
  1001. {
  1002. struct zfile *z;
  1003. if (zn->offset) {
  1004. struct zfile *zf;
  1005. z = zfile_fopen_empty (zn->volume->archive, zn->fullname, zn->size);
  1006. zf = zfile_fopen (zfile_getname (zn->volume->archive), _T("rb"), zn->volume->archive->zfdmask & ~ZFD_ADF, zn->offset - 1);
  1007. if (zf) {
  1008. zfile_fread (z->data, zn->size, 1, zf);
  1009. zfile_fclose (zf);
  1010. }
  1011. } else {
  1012. z = zfile_fopen_empty (zn->volume->archive, zn->fullname, zn->size);
  1013. if (z) {
  1014. zfile_fseek (zn->volume->archive, 0, SEEK_SET);
  1015. zfile_fread (z->data, zn->size, 1, zn->volume->archive);
  1016. }
  1017. }
  1018. return z;
  1019. }
  1020. struct adfhandle {
  1021. int size;
  1022. int highblock;
  1023. int blocksize;
  1024. int rootblock;
  1025. struct zfile *z;
  1026. uae_u8 block[65536];
  1027. uae_u32 dostype;
  1028. };
  1029. static int dos_checksum (uae_u8 *p, int blocksize)
  1030. {
  1031. uae_u32 cs = 0;
  1032. int i;
  1033. for (i = 0; i < blocksize; i += 4)
  1034. cs += (p[i] << 24) | (p[i + 1] << 16) | (p[i + 2] << 8) | (p[i + 3] << 0);
  1035. return cs;
  1036. }
  1037. static int sfs_checksum (uae_u8 *p, int blocksize, int sfs2)
  1038. {
  1039. uae_u32 cs = sfs2 ? 2 : 1;
  1040. int i;
  1041. for (i = 0; i < blocksize; i += 4)
  1042. cs += (p[i] << 24) | (p[i + 1] << 16) | (p[i + 2] << 8) | (p[i + 3] << 0);
  1043. return cs;
  1044. }
  1045. static TCHAR *getBSTR (uae_u8 *bstr)
  1046. {
  1047. int n = *bstr++;
  1048. uae_char buf[257];
  1049. int i;
  1050. for (i = 0; i < n; i++)
  1051. buf[i] = *bstr++;
  1052. buf[i] = 0;
  1053. return au (buf);
  1054. }
  1055. static uae_u32 gl (struct adfhandle *adf, int off)
  1056. {
  1057. uae_u8 *p = adf->block + off;
  1058. return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
  1059. }
  1060. static uae_u32 glx (uae_u8 *p)
  1061. {
  1062. return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
  1063. }
  1064. static uae_u32 gwx (uae_u8 *p)
  1065. {
  1066. return (p[0] << 8) | (p[1] << 0);
  1067. }
  1068. static const int secs_per_day = 24 * 60 * 60;
  1069. static const int diff = (8 * 365 + 2) * (24 * 60 * 60);
  1070. static const int diff2 = (-8 * 365 - 2) * (24 * 60 * 60);
  1071. static time_t put_time (long days, long mins, long ticks)
  1072. {
  1073. time_t t;
  1074. if (days < 0)
  1075. days = 0;
  1076. if (days > 9900 * 365)
  1077. days = 9900 * 365; // in future far enough?
  1078. if (mins < 0 || mins >= 24 * 60)
  1079. mins = 0;
  1080. if (ticks < 0 || ticks >= 60 * 50)
  1081. ticks = 0;
  1082. t = ticks / 50;
  1083. t += mins * 60;
  1084. t += ((uae_u64)days) * secs_per_day;
  1085. t += diff;
  1086. return t;
  1087. }
  1088. static int adf_read_block (struct adfhandle *adf, int block)
  1089. {
  1090. memset (adf->block, 0, adf->blocksize);
  1091. if (block >= adf->highblock || block < 0)
  1092. return 0;
  1093. zfile_fseek (adf->z, block * adf->blocksize, SEEK_SET);
  1094. zfile_fread (adf->block, adf->blocksize, 1, adf->z);
  1095. return 1;
  1096. }
  1097. static void recurseadf (struct znode *zn, int root, TCHAR *name)
  1098. {
  1099. int i;
  1100. struct zvolume *zv = zn->volume;
  1101. struct adfhandle *adf = (struct adfhandle*)zv->handle;
  1102. TCHAR name2[MAX_DPATH];
  1103. int bs = adf->blocksize;
  1104. for (i = 0; i < bs / 4 - 56; i++) {
  1105. int block;
  1106. if (!adf_read_block (adf, root))
  1107. return;
  1108. block = gl (adf, (i + 6) * 4);
  1109. while (block > 0 && block < adf->size / bs) {
  1110. struct zarchive_info zai;
  1111. TCHAR *fname;
  1112. uae_u32 size, secondary;
  1113. if (!adf_read_block (adf, block))
  1114. return;
  1115. if (gl (adf, 0) != 2)
  1116. break;
  1117. if (gl (adf, 1 * 4) != block)
  1118. break;
  1119. secondary = gl (adf, bs - 1 * 4);
  1120. if (secondary != -3 && secondary != 2)
  1121. break;
  1122. memset (&zai, 0, sizeof zai);
  1123. fname = getBSTR (adf->block + bs - 20 * 4);
  1124. size = gl (adf, bs - 47 * 4);
  1125. name2[0] = 0;
  1126. if (name[0]) {
  1127. TCHAR sep[] = { FSDB_DIR_SEPARATOR, 0 };
  1128. _tcscpy (name2, name);
  1129. _tcscat (name2, sep);
  1130. }
  1131. _tcscat (name2, fname);
  1132. zai.name = name2;
  1133. if (size < 0 || size > 0x7fffffff)
  1134. size = 0;
  1135. zai.size = size;
  1136. zai.flags = gl (adf, bs - 48 * 4);
  1137. amiga_to_timeval (&zai.tv, gl (adf, bs - 23 * 4), gl (adf, bs - 22 * 4),gl (adf, bs - 21 * 4), 50);
  1138. if (secondary == -3) {
  1139. struct znode *znnew = zvolume_addfile_abs (zv, &zai);
  1140. if (znnew)
  1141. znnew->offset = block;
  1142. } else {
  1143. struct znode *znnew = zvolume_adddir_abs (zv, &zai);
  1144. if (znnew) {
  1145. znnew->offset = block;
  1146. recurseadf (znnew, block, name2);
  1147. }
  1148. if (!adf_read_block (adf, block))
  1149. return;
  1150. }
  1151. xfree (fname);
  1152. block = gl (adf, bs - 4 * 4);
  1153. }
  1154. }
  1155. }
  1156. static void recursesfs (struct znode *zn, int root, TCHAR *name, int sfs2)
  1157. {
  1158. struct zvolume *zv = zn->volume;
  1159. struct adfhandle *adf = (struct adfhandle*)zv->handle;
  1160. TCHAR name2[MAX_DPATH];
  1161. int block;
  1162. uae_u8 *p, *s;
  1163. struct zarchive_info zai;
  1164. block = root;
  1165. while (block) {
  1166. if (!adf_read_block (adf, block))
  1167. return;
  1168. p = adf->block + 12 + 3 * 4;
  1169. while (glx (p + 4) && p < adf->block + adf->blocksize - 27) {
  1170. TCHAR *fname;
  1171. int i;
  1172. int align;
  1173. memset (&zai, 0, sizeof zai);
  1174. zai.flags = glx (p + 8) ^ 0x0f;
  1175. s = p + (sfs2 ? 27 : 25);
  1176. fname = au ((char*)s);
  1177. i = 0;
  1178. while (*s) {
  1179. s++;
  1180. i++;
  1181. }
  1182. s++;
  1183. i++;
  1184. if (*s)
  1185. zai.comment = au ((char*)s);
  1186. while (*s) {
  1187. s++;
  1188. i++;
  1189. }
  1190. s++;
  1191. i++;
  1192. i += sfs2 ? 27 : 25;
  1193. align = i & 1;
  1194. name2[0] = 0;
  1195. if (name[0]) {
  1196. TCHAR sep[] = { FSDB_DIR_SEPARATOR, 0 };
  1197. _tcscpy (name2, name);
  1198. _tcscat (name2, sep);
  1199. }
  1200. _tcscat (name2, fname);
  1201. zai.name = name2;
  1202. if (sfs2)
  1203. zai.tv.tv_sec = glx (p + 22) - diff2;
  1204. else
  1205. zai.tv.tv_sec = glx (p + 20) - diff;
  1206. if (p[sfs2 ? 26 : 24] & 0x80) { // dir
  1207. struct znode *znnew = zvolume_adddir_abs (zv, &zai);
  1208. int newblock = glx (p + 16);
  1209. if (newblock) {
  1210. znnew->offset = block;
  1211. recursesfs (znnew, newblock, name2, sfs2);
  1212. }
  1213. if (!adf_read_block (adf, block))
  1214. return;
  1215. } else {
  1216. struct znode *znnew;
  1217. if (sfs2) {
  1218. uae_u64 b1 = p[16];
  1219. uae_u64 b2 = p[17];
  1220. zai.size = (b1 << 40) | (b2 << 32) | glx (p + 18) ;
  1221. } else {
  1222. zai.size = glx (p + 16);
  1223. }
  1224. znnew = zvolume_addfile_abs (zv, &zai);
  1225. if (znnew) {
  1226. znnew->offset = block;
  1227. znnew->offset2 = p - adf->block;
  1228. }
  1229. }
  1230. xfree (zai.comment);
  1231. xfree (fname);
  1232. p += i + align;
  1233. }
  1234. block = gl (adf, 12 + 4);
  1235. }
  1236. }
  1237. struct zvolume *archive_directory_adf (struct znode *parent, struct zfile *z)
  1238. {
  1239. struct zvolume *zv;
  1240. struct adfhandle *adf;
  1241. TCHAR name[MAX_DPATH];
  1242. int gotroot = 0;
  1243. adf = xcalloc (struct adfhandle, 1);
  1244. zfile_fseek (z, 0, SEEK_END);
  1245. adf->size = zfile_ftell (z);
  1246. zfile_fseek (z, 0, SEEK_SET);
  1247. adf->blocksize = 512;
  1248. if (parent && parent->offset2) {
  1249. if (parent->offset2 == 1024 || parent->offset2 == 2048 || parent->offset2 == 4096 || parent->offset2 == 8192 ||
  1250. parent->offset2 == 16384 || parent->offset2 == 32768 || parent->offset2 == 65536) {
  1251. adf->blocksize = parent->offset2;
  1252. gotroot = 1;
  1253. }
  1254. }
  1255. adf->highblock = adf->size / adf->blocksize;
  1256. adf->z = z;
  1257. if (!adf_read_block (adf, 0))
  1258. goto fail;
  1259. adf->dostype = gl (adf, 0);
  1260. if ((adf->dostype & 0xffffff00) == MCC('D', 'O', 'S', '\0')) {
  1261. int bs = adf->blocksize;
  1262. int res;
  1263. adf->rootblock = ((adf->size / bs) - 1 + 2) / 2;
  1264. if (!gotroot) {
  1265. for (res = 2; res >= 1; res--) {
  1266. for (bs = 512; bs < 65536; bs <<= 1) {
  1267. adf->blocksize = bs;
  1268. adf->rootblock = ((adf->size / bs) - 1 + res) / 2;
  1269. if (!adf_read_block (adf, adf->rootblock))
  1270. continue;
  1271. if (gl (adf, 0) != 2 || gl (adf, bs - 1 * 4) != 1)
  1272. continue;
  1273. if (dos_checksum (adf->block, bs) != 0)
  1274. continue;
  1275. gotroot = 1;
  1276. break;
  1277. }
  1278. if (gotroot)
  1279. break;
  1280. }
  1281. }
  1282. if (!gotroot) {
  1283. bs = adf->blocksize = 512;
  1284. if (adf->size < 2000000 && adf->rootblock != 880) {
  1285. adf->rootblock = 880;
  1286. if (!adf_read_block (adf, adf->rootblock))
  1287. goto fail;
  1288. if (gl (adf, 0) != 2 || gl (adf, bs - 1 * 4) != 1)
  1289. goto fail;
  1290. if (dos_checksum (adf->block, bs) != 0)
  1291. goto fail;
  1292. }
  1293. }
  1294. if (!adf_read_block (adf, adf->rootblock))
  1295. goto fail;
  1296. if (gl (adf, 0) != 2 || gl (adf, bs - 1 * 4) != 1)
  1297. goto fail;
  1298. if (dos_checksum (adf->block, adf->blocksize) != 0)
  1299. goto fail;
  1300. adf->blocksize = bs;
  1301. adf->highblock = adf->size / adf->blocksize;
  1302. zv = zvolume_alloc (z, ArchiveFormatADF, NULL, NULL);
  1303. zv->method = ArchiveFormatADF;
  1304. zv->handle = adf;
  1305. zv->volumename = getBSTR (adf->block + adf->blocksize - 20 * 4);
  1306. name[0] = 0;
  1307. recurseadf (&zv->root, adf->rootblock, name);
  1308. } else if ((adf->dostype & 0xffffff00) == MCC('S', 'F', 'S', '\0')) {
  1309. uae_u16 version, sfs2;
  1310. for (;;) {
  1311. for (;;) {
  1312. version = gl (adf, 12) >> 16;
  1313. sfs2 = version > 3;
  1314. if (version > 4)
  1315. break;
  1316. adf->rootblock = gl (adf, 104);
  1317. if (!adf_read_block (adf, adf->rootblock))
  1318. break;
  1319. if (gl (adf, 0) != MCC('O', 'B', 'J', 'C'))
  1320. break;
  1321. if (sfs_checksum (adf->block, adf->blocksize, sfs2))
  1322. break;
  1323. adf->rootblock = gl (adf, 40);
  1324. if (!adf_read_block (adf, adf->rootblock))
  1325. break;
  1326. if (gl (adf, 0) != MCC('O', 'B', 'J', 'C'))
  1327. break;
  1328. if (sfs_checksum (adf->block, adf->blocksize, sfs2))
  1329. break;
  1330. gotroot = 1;
  1331. break;
  1332. }
  1333. if (gotroot)
  1334. break;
  1335. adf->blocksize <<= 1;
  1336. if (adf->blocksize == 65536)
  1337. break;
  1338. }
  1339. if (!gotroot)
  1340. goto fail;
  1341. zv = zvolume_alloc (z, ArchiveFormatADF, NULL, NULL);
  1342. zv->method = ArchiveFormatADF;
  1343. zv->handle = adf;
  1344. name[0] = 0;
  1345. recursesfs (&zv->root, adf->rootblock, name, version > 3);
  1346. } else {
  1347. goto fail;
  1348. }
  1349. return zv;
  1350. fail:
  1351. xfree (adf);
  1352. return NULL;
  1353. }
  1354. struct sfsblock
  1355. {
  1356. int block;
  1357. int length;
  1358. };
  1359. static int sfsfindblock (struct adfhandle *adf, int btree, int theblock, struct sfsblock **sfsb, int *sfsblockcnt, int *sfsmaxblockcnt, int sfs2)
  1360. {
  1361. int nodecount, isleaf, nodesize;
  1362. int i;
  1363. uae_u8 *p;
  1364. if (!btree)
  1365. return 0;
  1366. if (!adf_read_block (adf, btree))
  1367. return 0;
  1368. if (memcmp (adf->block, "BNDC", 4))
  1369. return 0;
  1370. nodecount = gwx (adf->block + 12);
  1371. isleaf = adf->block[14];
  1372. nodesize = adf->block[15];
  1373. p = adf->block + 16;
  1374. for (i = 0; i < nodecount; i++) {
  1375. if (isleaf) {
  1376. uae_u32 key = glx (p);
  1377. uae_u32 next = glx (p + 4);
  1378. uae_u32 prev = glx (p + 8);
  1379. uae_u32 blocks;
  1380. if (sfs2)
  1381. blocks = glx (p + 12);
  1382. else
  1383. blocks = gwx (p + 12);
  1384. if (key == theblock) {
  1385. struct sfsblock *sb;
  1386. if (*sfsblockcnt >= *sfsmaxblockcnt) {
  1387. *sfsmaxblockcnt += 100;
  1388. *sfsb = xrealloc (struct sfsblock, *sfsb, *sfsmaxblockcnt);
  1389. }
  1390. sb = *sfsb + (*sfsblockcnt);
  1391. sb->block = key;
  1392. sb->length = blocks;
  1393. (*sfsblockcnt)++;
  1394. return next;
  1395. }
  1396. } else {
  1397. uae_u32 key = glx (p);
  1398. uae_u32 data = glx (p + 4);
  1399. int newblock = sfsfindblock (adf, data, theblock, sfsb, sfsblockcnt, sfsmaxblockcnt, sfs2);
  1400. if (newblock)
  1401. return newblock;
  1402. if (!adf_read_block (adf, btree))
  1403. return 0;
  1404. if (memcmp (adf->block, "BNDC", 4))
  1405. return 0;
  1406. }
  1407. p += nodesize;
  1408. }
  1409. return 0;
  1410. }
  1411. static struct zfile *archive_access_adf (struct znode *zn)
  1412. {
  1413. struct zfile *z = NULL;
  1414. int root, ffs;
  1415. struct adfhandle *adf = (struct adfhandle*)zn->volume->handle;
  1416. uae_s64 size;
  1417. int i, bs;
  1418. uae_u8 *dst;
  1419. size = zn->size;
  1420. bs = adf->blocksize;
  1421. z = zfile_fopen_empty (zn->volume->archive, zn->fullname, size);
  1422. if (!z)
  1423. return NULL;
  1424. if ((adf->dostype & 0xffffff00) == MCC('D', 'O', 'S', '\0')) {
  1425. ffs = adf->dostype & 1;
  1426. root = zn->offset;
  1427. dst = z->data;
  1428. for (;;) {
  1429. adf_read_block (adf, root);
  1430. for (i = bs / 4 - 51; i >= 6; i--) {
  1431. uae_s64 bsize = ffs ? bs : bs - 24;
  1432. int block = gl (adf, i * 4);
  1433. if (size < bsize)
  1434. bsize = size;
  1435. if (ffs)
  1436. zfile_fseek (adf->z, block * adf->blocksize, SEEK_SET);
  1437. else
  1438. zfile_fseek (adf->z, block * adf->blocksize + 24, SEEK_SET);
  1439. zfile_fread (dst, bsize, 1, adf->z);
  1440. size -= bsize;
  1441. dst += bsize;
  1442. if (size <= 0)
  1443. break;
  1444. }
  1445. if (size <= 0)
  1446. break;
  1447. root = gl (adf, bs - 2 * 4);
  1448. }
  1449. } else if ((adf->dostype & 0xffffff00) == MCC('S', 'F', 'S', '\0')) {
  1450. struct sfsblock *sfsblocks;
  1451. int sfsblockcnt, sfsmaxblockcnt, i;
  1452. uae_s64 bsize;
  1453. int block = zn->offset;
  1454. int dblock;
  1455. int btree, version, sfs2;
  1456. uae_u8 *p;
  1457. if (!adf_read_block (adf, 0))
  1458. goto end;
  1459. btree = glx (adf->block + 108);
  1460. version = gwx (adf->block + 12);
  1461. sfs2 = version > 3;
  1462. if (!adf_read_block (adf, block))
  1463. goto end;
  1464. p = adf->block + zn->offset2;
  1465. dblock = glx (p + 12);
  1466. sfsblockcnt = 0;
  1467. sfsmaxblockcnt = 0;
  1468. sfsblocks = NULL;
  1469. if (size > 0) {
  1470. int nextblock = dblock;
  1471. while (nextblock) {
  1472. nextblock = sfsfindblock (adf, btree, nextblock, &sfsblocks, &sfsblockcnt, &sfsmaxblockcnt, sfs2);
  1473. }
  1474. }
  1475. bsize = 0;
  1476. for (i = 0; i < sfsblockcnt; i++)
  1477. bsize += sfsblocks[i].length * adf->blocksize;
  1478. if (bsize < size)
  1479. write_log (_T("SFS extracting error, %s size mismatch %d<%d\n"), z->name, bsize, size);
  1480. dst = z->data;
  1481. block = zn->offset;
  1482. for (i = 0; i < sfsblockcnt; i++) {
  1483. block = sfsblocks[i].block;
  1484. bsize = sfsblocks[i].length * adf->blocksize;
  1485. zfile_fseek (adf->z, block * adf->blocksize, SEEK_SET);
  1486. if (bsize > size)
  1487. bsize = size;
  1488. zfile_fread (dst, bsize, 1, adf->z);
  1489. dst += bsize;
  1490. size -= bsize;
  1491. }
  1492. xfree (sfsblocks);
  1493. }
  1494. return z;
  1495. end:
  1496. zfile_fclose (z);
  1497. return NULL;
  1498. }
  1499. static void archive_close_adf (void *v)
  1500. {
  1501. struct adfhandle *adf = (struct adfhandle*)v;
  1502. xfree (adf);
  1503. }
  1504. static int rl (uae_u8 *p)
  1505. {
  1506. return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
  1507. }
  1508. static TCHAR *tochar (uae_u8 *s, int len)
  1509. {
  1510. int i, j;
  1511. uae_char tmp[256];
  1512. j = 0;
  1513. for (i = 0; i < len; i++) {
  1514. uae_char c = *s++;
  1515. if (c >= 0 && c <= 9) {
  1516. tmp[j++] = FSDB_DIR_SEPARATOR;
  1517. tmp[j++] = '0' + c;
  1518. } else if (c < ' ' || c > 'z') {
  1519. tmp[j++] = '.';
  1520. } else {
  1521. tmp[j++] = c;
  1522. }
  1523. tmp[j] = 0;
  1524. }
  1525. return au (tmp);
  1526. }
  1527. struct zvolume *archive_directory_rdb (struct zfile *z)
  1528. {
  1529. uae_u8 buf[512] = { 0 };
  1530. int partnum, bs;
  1531. TCHAR *devname;
  1532. struct zvolume *zv;
  1533. struct zarchive_info zai;
  1534. uae_u8 *p;
  1535. struct znode *zn;
  1536. zv = zvolume_alloc (z, ArchiveFormatRDB, NULL, NULL);
  1537. zfile_fseek (z, 0, SEEK_SET);
  1538. zfile_fread (buf, 1, 512, z);
  1539. partnum = 0;
  1540. for (;;) {
  1541. int partblock;
  1542. TCHAR tmp[MAX_DPATH];
  1543. int surf, spt, spb, lowcyl, highcyl, reserved;
  1544. int size, block, blocksize, rootblock;
  1545. TCHAR comment[81], *dos;
  1546. if (partnum == 0)
  1547. partblock = rl (buf + 28);
  1548. else
  1549. partblock = rl (buf + 4 * 4);
  1550. partnum++;
  1551. if (partblock <= 0)
  1552. break;
  1553. zfile_fseek (z, partblock * 512, SEEK_SET);
  1554. zfile_fread (buf, 1, 512, z);
  1555. if (memcmp (buf, "PART", 4))
  1556. break;
  1557. p = buf + 128 - 16;
  1558. surf = rl (p + 28);
  1559. spb = rl (p + 32);
  1560. spt = rl (p + 36);
  1561. reserved = rl (p + 40);
  1562. lowcyl = rl (p + 52);
  1563. highcyl = rl (p + 56);
  1564. blocksize = rl (p + 20) * 4 * spb;
  1565. block = lowcyl * surf * spt;
  1566. size = (highcyl - lowcyl + 1) * surf * spt;
  1567. size *= blocksize;
  1568. dos = tochar (buf + 192, 4);
  1569. if (!memcmp (dos, _T("DOS"), 3))
  1570. rootblock = ((size / blocksize) - 1 + 2) / 2;
  1571. else
  1572. rootblock = 0;
  1573. devname = getBSTR (buf + 36);
  1574. _stprintf (tmp, _T("%s.hdf"), devname);
  1575. memset (&zai, 0, sizeof zai);
  1576. _stprintf (comment, _T("FS=%s LO=%d HI=%d HEADS=%d SPT=%d RES=%d BLOCK=%d ROOT=%d"),
  1577. dos, lowcyl, highcyl, surf, spt, reserved, blocksize, rootblock);
  1578. zai.comment = comment;
  1579. xfree (dos);
  1580. zai.name = tmp;
  1581. zai.size = size;
  1582. zai.flags = -1;
  1583. zn = zvolume_addfile_abs (zv, &zai);
  1584. if (zn) {
  1585. zn->offset = partblock;
  1586. zn->offset2 = blocksize; // abuse of offset2..
  1587. }
  1588. }
  1589. zfile_fseek (z, 0, SEEK_SET);
  1590. p = buf;
  1591. zfile_fread (buf, 1, 512, z);
  1592. zai.name = my_strdup(_T("rdb_dump.dat"));
  1593. bs = rl (p + 16);
  1594. zai.size = rl (p + 140) * bs;
  1595. zai.comment = NULL;
  1596. zn = zvolume_addfile_abs (zv, &zai);
  1597. zn->offset = 0;
  1598. zv->method = ArchiveFormatRDB;
  1599. return zv;
  1600. }
  1601. static struct zfile *archive_access_rdb (struct znode *zn)
  1602. {
  1603. struct zfile *z = zn->volume->archive;
  1604. struct zfile *zf;
  1605. uae_u8 buf[512] = { 0 };
  1606. int surf, spb, spt, lowcyl, highcyl;
  1607. int block, blocksize;
  1608. uae_s64 size;
  1609. uae_u8 *p;
  1610. if (zn->offset) {
  1611. zfile_fseek (z, zn->offset * 512, SEEK_SET);
  1612. zfile_fread (buf, 1, 512, z);
  1613. p = buf + 128 - 16;
  1614. surf = rl (p + 28);
  1615. spb = rl (p + 32);
  1616. spt = rl (p + 36);
  1617. lowcyl = rl (p + 52);
  1618. highcyl = rl (p + 56);
  1619. blocksize = rl (p + 20) * 4;
  1620. block = lowcyl * surf * spt;
  1621. size = (highcyl - lowcyl + 1) * surf * spt;
  1622. size *= blocksize;
  1623. } else {
  1624. zfile_fseek (z, 0, SEEK_SET);
  1625. zfile_fread (buf, 1, 512, z);
  1626. p = buf;
  1627. blocksize = rl (p + 16);
  1628. block = 0;
  1629. size = zn->size;
  1630. }
  1631. zf = zfile_fopen_parent (z, zn->fullname, block * blocksize, size);
  1632. return zf;
  1633. }
  1634. int isfat (uae_u8 *p)
  1635. {
  1636. int i, b;
  1637. if ((p[0x15] & 0xf0) != 0xf0)
  1638. return 0;
  1639. if (p[0x0b] != 0x00 || p[0x0c] != 0x02)
  1640. return 0;
  1641. b = 0;
  1642. for (i = 0; i < 8; i++) {
  1643. if (p[0x0d] & (1 << i))
  1644. b++;
  1645. }
  1646. if (b != 1)
  1647. return 0;
  1648. if (p[0x0f] != 0)
  1649. return 0;
  1650. if (p[0x0e] > 8 || p[0x0e] == 0)
  1651. return 0;
  1652. if (p[0x10] == 0 || p[0x10] > 8)
  1653. return 0;
  1654. b = (p[0x12] << 8) | p[0x11];
  1655. if (b > 8192 || b <= 0)
  1656. return 0;
  1657. b = p[0x16] | (p[0x17] << 8);
  1658. if (b == 0 || b > 8192)
  1659. return 0;
  1660. return 1;
  1661. }
  1662. /*
  1663. * The epoch of FAT timestamp is 1980.
  1664. * : bits : value
  1665. * date: 0 - 4: day (1 - 31)
  1666. * date: 5 - 8: month (1 - 12)
  1667. * date: 9 - 15: year (0 - 127) from 1980
  1668. * time: 0 - 4: sec (0 - 29) 2sec counts
  1669. * time: 5 - 10: min (0 - 59)
  1670. * time: 11 - 15: hour (0 - 23)
  1671. */
  1672. #define SECS_PER_MIN 60
  1673. #define SECS_PER_HOUR (60 * 60)
  1674. #define SECS_PER_DAY (SECS_PER_HOUR * 24)
  1675. #define UNIX_SECS_1980 315532800L
  1676. #if BITS_PER_LONG == 64
  1677. #define UNIX_SECS_2108 4354819200L
  1678. #endif
  1679. /* days between 1.1.70 and 1.1.80 (2 leap days) */
  1680. #define DAYS_DELTA (365 * 10 + 2)
  1681. /* 120 (2100 - 1980) isn't leap year */
  1682. #define YEAR_2100 120
  1683. #define IS_LEAP_YEAR(y) (!((y) & 3) && (y) != YEAR_2100)
  1684. /* Linear day numbers of the respective 1sts in non-leap years. */
  1685. static time_t days_in_year[] = {
  1686. /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
  1687. 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0,
  1688. };
  1689. /* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
  1690. static time_t fat_time_fat2unix (uae_u16 time, uae_u16 date, int fat12)
  1691. {
  1692. time_t second, day, leap_day, month, year;
  1693. if (0 && fat12) {
  1694. year = date & 0x7f;
  1695. month = (date >> 7) & 0x0f;
  1696. day = (date >> 11);
  1697. } else {
  1698. year = date >> 9;
  1699. month = max(1, (date >> 5) & 0xf);
  1700. day = max(1, date & 0x1f) - 1;
  1701. }
  1702. leap_day = (year + 3) / 4;
  1703. if (year > YEAR_2100) /* 2100 isn't leap year */
  1704. leap_day--;
  1705. if (IS_LEAP_YEAR(year) && month > 2)
  1706. leap_day++;
  1707. second = (time & 0x1f) << 1;
  1708. second += ((time >> 5) & 0x3f) * SECS_PER_MIN;
  1709. second += (time >> 11) * SECS_PER_HOUR;
  1710. second += (year * 365 + leap_day
  1711. + days_in_year[month] + day
  1712. + DAYS_DELTA) * SECS_PER_DAY;
  1713. return second;
  1714. }
  1715. static int getcluster (struct zfile *z, int cluster, int fatstart, int fatbits)
  1716. {
  1717. uae_u32 fat = 0;
  1718. uae_u8 p[4];
  1719. int offset = cluster * fatbits;
  1720. zfile_fseek (z, fatstart * 512 + offset / 8, SEEK_SET);
  1721. if (fatbits == 12) {
  1722. zfile_fread (p, 2, 1, z);
  1723. if ((offset & 4))
  1724. fat = ((p[0] & 0xf0) >> 4) | (p[1] << 4);
  1725. else
  1726. fat = (p[0]) | ((p[1] & 0x0f) << 8);
  1727. if (fat >= 0xff0)
  1728. return -1;
  1729. } else if (fatbits == 16) {
  1730. zfile_fread (p, 2, 1, z);
  1731. fat = p[0] | (p[1] << 8);
  1732. if (fat >= 0xfff0)
  1733. return -1;
  1734. } else if (fatbits == 32) {
  1735. zfile_fread (p, 4, 1, z);
  1736. fat = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
  1737. fat &= ~0x0fffffff;
  1738. if (fat >= 0x0ffffff0)
  1739. return -1;
  1740. }
  1741. return fat;
  1742. }
  1743. static void fatdirectory (struct zfile *z, struct zvolume *zv, const TCHAR *name, int startblock, int entries, int sectorspercluster, int fatstart, int dataregion, int fatbits)
  1744. {
  1745. struct zarchive_info zai;
  1746. struct znode *znnew;
  1747. int i, j;
  1748. for (i = 0; i < entries; i++) {
  1749. TCHAR name2[MAX_DPATH], *fname;
  1750. uae_s64 size;
  1751. uae_u8 fatname[16];
  1752. uae_u8 buf[32];
  1753. int attr, cnt, ext;
  1754. int startcluster;
  1755. memset (buf, 0, sizeof buf);
  1756. memset (&zai, 0, sizeof zai);
  1757. zfile_fseek (z, startblock * 512 + i * 32, SEEK_SET);
  1758. zfile_fread (buf, 32, 1, z);
  1759. if (buf[0] == 0)
  1760. break;
  1761. if (buf[0] == 0xe5)
  1762. continue;
  1763. if (buf[0] == 0x05)
  1764. buf[0] = 0xe5;
  1765. size = buf[0x1c] | (buf[0x1d] << 8) | (buf[0x1e] << 16) | (buf[0x1f] << 24);
  1766. attr = buf[0x0b];
  1767. startcluster = buf[0x1a] | (buf[0x1b] << 8);
  1768. if ((attr & (0x4 | 0x2)) == 0x06) // system+hidden
  1769. continue;
  1770. if (attr & 8) // disk name
  1771. continue;
  1772. if (attr & 1) // read-only
  1773. zai.flags |= 1 << 3;
  1774. if (!(attr & 32)) // archive
  1775. zai.flags |= 1 << 4;
  1776. cnt = 0;
  1777. ext = 0;
  1778. for (j = 0; j < 8 && buf[j] != 0x20 && buf[j] != 0; j++)
  1779. fatname[cnt++] = buf[j];
  1780. for (j = 0; j < 3 && buf[8 + j] != 0x20 && buf[8 + j] != 0; j++) {
  1781. if (ext == 0)
  1782. fatname[cnt++] = '.';
  1783. ext = 1;
  1784. fatname[cnt++] = buf[8 + j];
  1785. }
  1786. fatname[cnt] = 0;
  1787. fname = au ((char*)fatname);
  1788. name2[0] = 0;
  1789. if (name[0]) {
  1790. TCHAR sep[] = { FSDB_DIR_SEPARATOR, 0 };
  1791. _tcscpy (name2, name);
  1792. _tcscat (name2, sep);
  1793. }
  1794. _tcscat (name2, fname);
  1795. zai.name = name2;
  1796. zai.tv.tv_sec = fat_time_fat2unix (buf[0x16] | (buf[0x17] << 8), buf[0x18] | (buf[0x19] << 8), 1);
  1797. if (attr & (16 | 8)) {
  1798. int nextblock, cluster;
  1799. nextblock = dataregion + (startcluster - 2) * sectorspercluster;
  1800. cluster = getcluster (z, startcluster, fatstart, fatbits);
  1801. if ((cluster < 0 || cluster >= 3) && nextblock != startblock) {
  1802. znnew = zvolume_adddir_abs (zv, &zai);
  1803. fatdirectory (z, zv, name2, nextblock, sectorspercluster * 512 / 32, sectorspercluster, fatstart, dataregion, fatbits);
  1804. while (cluster >= 3) {
  1805. nextblock = dataregion + (cluster - 2) * sectorspercluster;
  1806. fatdirectory (z, zv, name2, nextblock, sectorspercluster * 512 / 32, sectorspercluster, fatstart, dataregion, fatbits);
  1807. cluster = getcluster (z, cluster, fatstart, fatbits);
  1808. }
  1809. }
  1810. } else {
  1811. zai.size = size;
  1812. znnew = zvolume_addfile_abs (zv, &zai);
  1813. if (znnew) {
  1814. znnew->offset = startcluster;
  1815. }
  1816. }
  1817. xfree (fname);
  1818. }
  1819. }
  1820. struct zvolume *archive_directory_fat (struct zfile *z)
  1821. {
  1822. uae_u8 buf[512] = { 0 };
  1823. int fatbits = 12;
  1824. struct zvolume *zv;
  1825. int rootdir, reserved, sectorspercluster;
  1826. int numfats, sectorsperfat, rootentries;
  1827. int dataregion;
  1828. zfile_fseek (z, 0, SEEK_SET);
  1829. zfile_fread (buf, 1, 512, z);
  1830. if (!isfat (buf))
  1831. return NULL;
  1832. reserved = buf[0x0e] | (buf[0x0f] << 8);
  1833. numfats = buf[0x10];
  1834. sectorsperfat = buf[0x16] | (buf[0x17] << 8);
  1835. rootentries = buf[0x11] | (buf[0x12] << 8);
  1836. sectorspercluster = buf[0x0d];
  1837. rootdir = reserved + numfats * sectorsperfat;
  1838. dataregion = rootdir + rootentries * 32 / 512;
  1839. zv = zvolume_alloc (z, ArchiveFormatFAT, NULL, NULL);
  1840. fatdirectory (z, zv, _T(""), rootdir, rootentries, sectorspercluster, reserved, dataregion, fatbits);
  1841. zv->method = ArchiveFormatFAT;
  1842. return zv;
  1843. }
  1844. static struct zfile *archive_access_fat (struct znode *zn)
  1845. {
  1846. uae_u8 buf[512] = { 0 };
  1847. int fatbits = 12;
  1848. uae_s64 size = zn->size;
  1849. struct zfile *sz, *dz;
  1850. int rootdir, reserved, sectorspercluster;
  1851. int numfats, sectorsperfat, rootentries;
  1852. int dataregion, cluster;
  1853. uae_s64 offset;
  1854. sz = zn->volume->archive;
  1855. zfile_fseek (sz, 0, SEEK_SET);
  1856. zfile_fread (buf, 1, 512, sz);
  1857. if (!isfat (buf))
  1858. return NULL;

Large files files are truncated, but you can click here to view the full file