/zfile.cpp
C++ | 3521 lines | 3246 code | 238 blank | 37 comment | 1148 complexity | 4642264c93cd508c0e0245cc6d738082 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * UAE - The Un*x Amiga Emulator
- *
- * routines to handle compressed file automatically
- *
- * (c) 1996 Samuel Devulder, Tim Gunn
- * 2002-2007 Toni Wilen
- */
- #define RECURSIVE_ARCHIVES 1
- //#define ZFILE_DEBUG
- #include "sysconfig.h"
- #include "sysdeps.h"
- #include "options.h"
- #include "zfile.h"
- #include "disk.h"
- #include "gui.h"
- #include "crc32.h"
- #include "fsdb.h"
- #include "fsusage.h"
- #include "zarchive.h"
- #include "diskutil.h"
- #include "fdi2raw.h"
- #include "uae/io.h"
- #include "archivers/zip/unzip.h"
- #include "archivers/dms/pfile.h"
- #include "archivers/wrp/warp.h"
- static struct zfile *zlist = 0;
- const TCHAR *uae_archive_extensions[] = { _T("zip"), _T("rar"), _T("7z"), _T("lha"), _T("lzh"), _T("lzx"), _T("tar"), NULL };
- #define MAX_CACHE_ENTRIES 10
- struct zdisktrack
- {
- void *data;
- int len;
- };
- struct zdiskimage
- {
- int tracks;
- struct zdisktrack zdisktracks[2 * 84];
- };
- struct zcache
- {
- TCHAR *name;
- struct zdiskimage *zd;
- void *data;
- int size;
- struct zcache *next;
- time_t tm;
- };
- static struct zcache *zcachedata;
- static struct zcache *cache_get (const TCHAR *name)
- {
- struct zcache *zc = zcachedata;
- while (zc) {
- if (!_tcscmp (name, zc->name)) {
- zc->tm = time (NULL);
- return zc;
- }
- zc = zc->next;
- }
- return NULL;
- }
- static void zcache_flush (void)
- {
- }
- static void zcache_free_data (struct zcache *zc)
- {
- int i;
- if (zc->zd) {
- for (i = 0; i < zc->zd->tracks; i++) {
- xfree (zc->zd->zdisktracks[i].data);
- }
- xfree (zc->zd);
- }
- xfree (zc->data);
- xfree (zc->name);
- }
- static void zcache_free (struct zcache *zc)
- {
- struct zcache *pl = NULL;
- struct zcache *l = zcachedata;
- struct zcache *nxt;
- while (l != zc) {
- if (l == 0)
- return;
- pl = l;
- l = l->next;
- }
- if (l)
- nxt = l->next;
- zcache_free_data (zc);
- if (l == 0)
- return;
- if(!pl)
- zcachedata = nxt;
- else
- pl->next = nxt;
- }
- static void zcache_close (void)
- {
- struct zcache *zc = zcachedata;
- while (zc) {
- struct zcache *n = zc->next;
- zcache_free_data (zc);
- xfree (n);
- zc = n;
- }
- }
- static void zcache_check (void)
- {
- int cnt = 0;
- struct zcache *zc = zcachedata, *last = NULL;
- while (zc) {
- last = zc;
- zc = zc->next;
- cnt++;
- }
- write_log (_T("CACHE: %d\n"), cnt);
- if (cnt >= MAX_CACHE_ENTRIES && last)
- zcache_free (last);
- }
- static struct zcache *zcache_put (const TCHAR *name, struct zdiskimage *data)
- {
- struct zcache *zc;
-
- zcache_check ();
- zc = xcalloc (struct zcache, 1);
- zc->next = zcachedata;
- zcachedata = zc;
- zc->zd = data;
- zc->name = my_strdup (name);
- zc->tm = time (NULL);
- return zc;
- }
- static void checkarchiveparent (struct zfile *z)
- {
- // unpack completely if opened in PEEK mode
- if (z->archiveparent)
- archive_unpackzfile (z);
- }
- static struct zfile *zfile_create (struct zfile *prev, const TCHAR *originalname)
- {
- struct zfile *z;
- z = xmalloc (struct zfile, 1);
- if (!z)
- return 0;
- memset (z, 0, sizeof *z);
- z->next = zlist;
- zlist = z;
- z->opencnt = 1;
- if (prev && prev->originalname)
- z->originalname = my_strdup(prev->originalname);
- else if (originalname)
- z->originalname = my_strdup(originalname);
- if (prev) {
- z->zfdmask = prev->zfdmask;
- }
- return z;
- }
- static void zfile_free (struct zfile *f)
- {
- if (f->f)
- fclose (f->f);
- if (f->deleteafterclose) {
- _wunlink (f->name);
- write_log (_T("deleted temporary file '%s'\n"), f->name);
- }
- xfree (f->name);
- xfree (f->originalname);
- xfree (f->data);
- xfree (f->mode);
- xfree (f->userdata);
- xfree (f);
- }
- void zfile_exit (void)
- {
- struct zfile *l;
- while ((l = zlist)) {
- zlist = l->next;
- zfile_free (l);
- }
- }
- void zfile_fclose (struct zfile *f)
- {
- //write_log (_T("%p\n"), f);
- if (!f)
- return;
- if (f->opencnt < 0) {
- write_log (_T("zfile: tried to free already closed filehandle!\n"));
- return;
- }
- f->opencnt--;
- if (f->opencnt > 0)
- return;
- f->opencnt = -100;
- if (f->parent) {
- f->parent->opencnt--;
- if (f->parent->opencnt <= 0)
- zfile_fclose (f->parent);
- }
- if (f->archiveparent) {
- zfile_fclose (f->archiveparent);
- f->archiveparent = NULL;
- }
- struct zfile *pl = NULL;
- struct zfile *nxt;
- struct zfile *l = zlist;
- while (l != f) {
- if (l == 0) {
- write_log (_T("zfile: tried to free already freed or nonexisting filehandle!\n"));
- return;
- }
- pl = l;
- l = l->next;
- }
- if (l)
- nxt = l->next;
- zfile_free (f);
- if (l == 0)
- return;
- if(!pl)
- zlist = nxt;
- else
- pl->next = nxt;
- }
- static void removeext (TCHAR *s, const TCHAR *ext)
- {
- if (_tcslen (s) < _tcslen (ext))
- return;
- if (_tcsicmp (s + _tcslen (s) - _tcslen (ext), ext) == 0)
- s[_tcslen (s) - _tcslen (ext)] = 0;
- }
- static bool checkwrite (struct zfile *zf, int *retcode)
- {
- if (zfile_needwrite (zf)) {
- if (retcode)
- *retcode = -1;
- return true;
- }
- return false;
- }
- static uae_u8 exeheader[]={ 0x00,0x00,0x03,0xf3,0x00,0x00,0x00,0x00 };
- 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 };
- int zfile_gettype (struct zfile *z)
- {
- uae_u8 buf[8];
- TCHAR *ext;
- if (!z || !z->name)
- return ZFILE_UNKNOWN;
- ext = _tcsrchr (z->name, '.');
- if (ext != NULL) {
- int i;
- ext++;
- for (i = 0; diskimages[i]; i++) {
- if (strcasecmp (ext, diskimages[i]) == 0)
- return ZFILE_DISKIMAGE;
- }
- if (strcasecmp (ext, _T("roz")) == 0)
- return ZFILE_ROM;
- if (strcasecmp (ext, _T("uss")) == 0)
- return ZFILE_STATEFILE;
- if (strcasecmp (ext, _T("rom")) == 0)
- return ZFILE_ROM;
- if (strcasecmp (ext, _T("bin")) == 0)
- return ZFILE_ROM;
- if (strcasecmp (ext, _T("key")) == 0)
- return ZFILE_KEY;
- if (strcasecmp (ext, _T("nvr")) == 0)
- return ZFILE_NVR;
- if (strcasecmp (ext, _T("uae")) == 0)
- return ZFILE_CONFIGURATION;
- if (strcasecmp(ext, _T("cue")) == 0 || strcasecmp(ext, _T("iso")) == 0 || strcasecmp(ext, _T("ccd")) == 0 ||
- strcasecmp(ext, _T("mds")) == 0 || strcasecmp(ext, _T("chd")) == 0 || strcasecmp(ext, _T("nrg")) == 0)
- return ZFILE_CDIMAGE;
- }
- memset (buf, 0, sizeof (buf));
- zfile_fread (buf, 8, 1, z);
- zfile_fseek (z, -8, SEEK_CUR);
- if (!memcmp (buf, exeheader, sizeof (buf)))
- return ZFILE_DISKIMAGE;
- if (!memcmp (buf, "CAPS", 4))
- return ZFILE_DISKIMAGE;
- if (!memcmp (buf, "SCP", 3))
- return ZFILE_DISKIMAGE;
- if (!memcmp (buf, "UAE--ADF", 8))
- return ZFILE_DISKIMAGE;
- if (!memcmp (buf, "UAE-1ADF", 8))
- return ZFILE_DISKIMAGE;
- if (!memcmp (buf, "Formatte", 8))
- return ZFILE_DISKIMAGE;
- if (!memcmp (buf, "RDSK", 4))
- return ZFILE_HDFRDB;
- if (!memcmp (buf, "DOS", 3)) {
- if (z->size < 4 * 1024 * 1024)
- return ZFILE_DISKIMAGE;
- else
- return ZFILE_HDF;
- }
- if (ext != NULL) {
- if (strcasecmp (ext, _T("hdf")) == 0)
- return ZFILE_HDF;
- if (strcasecmp (ext, _T("hdz")) == 0)
- return ZFILE_HDF;
- if (strcasecmp (ext, _T("vhd")) == 0)
- return ZFILE_HDF;
- }
- return ZFILE_UNKNOWN;
- }
- #define VHD_DYNAMIC 3
- #define VHD_FIXED 2
- STATIC_INLINE uae_u32 gl (uae_u8 *p)
- {
- return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
- }
- static uae_u32 vhd_checksum (uae_u8 *p, int offset)
- {
- int i;
- uae_u32 sum;
- sum = 0;
- for (i = 0; i < 512; i++) {
- if (offset >= 0 && i >= offset && i < offset + 4)
- continue;
- sum += p[i];
- }
- return ~sum;
- }
- struct zfile_vhd
- {
- int vhd_type;
- uae_u64 virtsize;
- uae_u32 vhd_bamoffset;
- uae_u32 vhd_blocksize;
- uae_u8 *vhd_header, *vhd_sectormap;
- uae_u64 vhd_footerblock;
- uae_u32 vhd_bamsize;
- uae_u64 vhd_sectormapblock;
- uae_u32 vhd_bitmapsize;
- };
- static uae_u64 vhd_fread2 (struct zfile *zf, void *dataptrv, uae_u64 offset, uae_u64 len)
- {
- uae_u32 bamoffset;
- uae_u32 sectoroffset;
- uae_u64 read;
- struct zfile *zp = zf->parent;
- struct zfile_vhd *zvhd = (struct zfile_vhd*)zf->userdata;
- uae_u8 *dataptr = (uae_u8*)dataptrv;
- //write_log (_T("%08x %08x\n"), (uae_u32)offset, (uae_u32)len);
- read = 0;
- if (offset & 511)
- return read;
- if (len & 511)
- return read;
- while (len > 0) {
- bamoffset = (offset / zvhd->vhd_blocksize) * 4 + zvhd->vhd_bamoffset;
- sectoroffset = gl (zvhd->vhd_header + bamoffset);
- if (sectoroffset == 0xffffffff) {
- memset (dataptr, 0, 512);
- read += 512;
- } else {
- int bitmapoffsetbits;
- int bitmapoffsetbytes;
- int sectormapblock;
- bitmapoffsetbits = (offset / 512) % (zvhd->vhd_blocksize / 512);
- bitmapoffsetbytes = bitmapoffsetbits / 8;
- sectormapblock = sectoroffset * 512 + (bitmapoffsetbytes & ~511);
- if (zvhd->vhd_sectormapblock != sectormapblock) {
- // read sector bitmap
- //write_log (_T("BM %08x\n"), sectormapblock);
- zfile_fseek (zp, sectormapblock, SEEK_SET);
- if (zfile_fread (zvhd->vhd_sectormap, 1, 512, zp) != 512)
- return read;
- zvhd->vhd_sectormapblock = sectormapblock;
- }
- // block allocated in bitmap?
- if (zvhd->vhd_sectormap[bitmapoffsetbytes & 511] & (1 << (7 - (bitmapoffsetbits & 7)))) {
- // read data block
- int block = sectoroffset * 512 + zvhd->vhd_bitmapsize + bitmapoffsetbits * 512;
- //write_log (_T("DB %08x\n"), block);
- zfile_fseek (zp, block, SEEK_SET);
- if (zfile_fread (dataptr, 1, 512, zp) != 512)
- return read;
- } else {
- memset (dataptr, 0, 512);
- }
- read += 512;
- }
- len -= 512;
- dataptr += 512;
- offset += 512;
- }
- return read;
- }
- static uae_s64 vhd_fread (void *data, uae_u64 l1, uae_u64 l2, struct zfile *zf)
- {
- uae_u64 size = l1 * l2;
- uae_u64 out = 0;
- int len = 0;
- if (!l1 || !l2)
- return 0;
- if ((zf->seek & 511) || (size & 511)) {
- uae_u8 tmp[512];
- if (zf->seek & 511) {
- int s;
- s = 512 - (zf->seek & 511);
- vhd_fread2 (zf, tmp, zf->seek & ~511, 512);
- memcpy ((uae_u8*)data + len, tmp + 512 - s, s);
- len += s;
- out += s;
- zf->seek += s;
- }
- while (size > 0) {
- int s = size > 512 ? 512 : size;
- vhd_fread2 (zf, tmp, zf->seek, 512);
- memcpy ((uae_u8*)data + len, tmp, s);
- zf->seek += s;
- size -= s;
- out += s;
- }
- } else {
- out = vhd_fread2 (zf, data, zf->seek, size);
- zf->seek += out;
- out /= l1;
- }
- return out;
- }
- static struct zfile *vhd (struct zfile *z)
- {
- uae_u8 tmp[512], tmp2[512];
- uae_u32 v;
- struct zfile_vhd *zvhd;
- uae_u64 fsize;
- zvhd = xcalloc (struct zfile_vhd, 1);
- zfile_fseek (z, 0, SEEK_END);
- fsize = zfile_ftell (z);
- zfile_fseek (z, 0, SEEK_SET);
- if (zfile_fread (tmp, 1, 512, z) != 512)
- goto nonvhd;
- v = gl (tmp + 8); // features
- if ((v & 3) != 2)
- goto nonvhd;
- v = gl (tmp + 8 + 4); // version
- if ((v >> 16) != 1)
- goto nonvhd;
- zvhd->vhd_type = gl (tmp + 8 + 4 + 4 + 8 + 4 + 4 + 4 + 4 + 8 + 8 + 4);
- if (zvhd->vhd_type != VHD_FIXED && zvhd->vhd_type != VHD_DYNAMIC)
- goto nonvhd;
- v = gl (tmp + 8 + 4 + 4 + 8 + 4 + 4 + 4 + 4 + 8 + 8 + 4 + 4);
- if (v == 0)
- goto nonvhd;
- if (vhd_checksum (tmp, 8 + 4 + 4 + 8 + 4 + 4 + 4 + 4 + 8 + 8 + 4 + 4) != v)
- goto nonvhd;
- zfile_fseek (z, fsize - sizeof tmp2, SEEK_SET);
- if (zfile_fread (tmp2, 1, 512, z) != 512)
- goto end;
- if (memcmp (tmp, tmp2, sizeof tmp))
- goto nonvhd;
- zvhd->vhd_footerblock = fsize - 512;
- zvhd->virtsize = (uae_u64)(gl (tmp + 8 + 4 + 4 + 8 + 4 + 4 +4 + 4 + 8)) << 32;
- zvhd->virtsize |= gl (tmp + 8 + 4 + 4 + 8 + 4 + 4 +4 + 4 + 8 + 4);
- if (zvhd->vhd_type == VHD_DYNAMIC) {
- uae_u32 size;
- zvhd->vhd_bamoffset = gl (tmp + 8 + 4 + 4 + 4);
- if (zvhd->vhd_bamoffset == 0 || zvhd->vhd_bamoffset >= fsize)
- goto end;
- zfile_fseek (z, zvhd->vhd_bamoffset, SEEK_SET);
- if (zfile_fread (tmp, 1, 512, z) != 512)
- goto end;
- v = gl (tmp + 8 + 8 + 8 + 4 + 4 + 4);
- if (vhd_checksum (tmp, 8 + 8 + 8 + 4 + 4 + 4) != v)
- goto end;
- v = gl (tmp + 8 + 8 + 8);
- if ((v >> 16) != 1)
- goto end;
- zvhd->vhd_blocksize = gl (tmp + 8 + 8 + 8 + 4 + 4);
- zvhd->vhd_bamoffset = gl (tmp + 8 + 8 + 4);
- zvhd->vhd_bamsize = (((zvhd->virtsize + zvhd->vhd_blocksize - 1) / zvhd->vhd_blocksize) * 4 + 511) & ~511;
- size = zvhd->vhd_bamoffset + zvhd->vhd_bamsize;
- zvhd->vhd_header = xmalloc (uae_u8, size);
- zfile_fseek (z, 0, SEEK_SET);
- if (zfile_fread (zvhd->vhd_header, 1, size, z) != size)
- goto end;
- zvhd->vhd_sectormap = xmalloc (uae_u8, 512);
- zvhd->vhd_sectormapblock = -1;
- zvhd->vhd_bitmapsize = ((zvhd->vhd_blocksize / (8 * 512)) + 511) & ~511;
- }
- z = zfile_fopen_parent (z, NULL, 0, zvhd->virtsize);
- z->useparent = 0;
- z->dataseek = 1;
- z->userdata = zvhd;
- z->zfileread = vhd_fread;
- write_log (_T("%s is VHD %s image, virtual size=%lldK\n"),
- zfile_getname (z),
- zvhd->vhd_type == 2 ? _T("fixed") : _T("dynamic"),
- zvhd->virtsize / 1024);
- return z;
- nonvhd:
- end:
- return z;
- }
- static struct zfile *zfile_gunzip (struct zfile *z, int *retcode)
- {
- uae_u8 header[2 + 1 + 1 + 4 + 1 + 1];
- z_stream zs;
- int i, size, ret, first;
- uae_u8 flags;
- uae_s64 offset;
- TCHAR name[MAX_DPATH];
- uae_u8 buffer[8192];
- struct zfile *z2;
- uae_u8 b;
- if (checkwrite (z, retcode))
- return NULL;
- _tcscpy (name, z->name);
- memset (&zs, 0, sizeof (zs));
- memset (header, 0, sizeof (header));
- zfile_fread (header, sizeof (header), 1, z);
- flags = header[3];
- if (header[0] != 0x1f && header[1] != 0x8b)
- return NULL;
- if (flags & 2) /* multipart not supported */
- return NULL;
- if (flags & 32) /* encryption not supported */
- return NULL;
- if (flags & 4) { /* skip extra field */
- zfile_fread (&b, 1, 1, z);
- size = b;
- zfile_fread (&b, 1, 1, z);
- size |= b << 8;
- zfile_fseek (z, size + 2, SEEK_CUR);
- }
- if (flags & 8) { /* get original file name */
- uae_char aname[MAX_DPATH];
- i = 0;
- do {
- zfile_fread (aname + i, 1, 1, z);
- } while (i < MAX_DPATH - 1 && aname[i++]);
- aname[i] = 0;
- au_copy (name, MAX_DPATH, aname);
- }
- if (flags & 16) { /* skip comment */
- i = 0;
- do {
- b = 0;
- zfile_fread (&b, 1, 1, z);
- } while (b);
- }
- removeext (name, _T(".gz"));
- offset = zfile_ftell (z);
- zfile_fseek (z, -4, SEEK_END);
- zfile_fread (&b, 1, 1, z);
- size = b;
- zfile_fread (&b, 1, 1, z);
- size |= b << 8;
- zfile_fread (&b, 1, 1, z);
- size |= b << 16;
- zfile_fread (&b, 1, 1, z);
- size |= b << 24;
- if (size < 8 || size > 256 * 1024 * 1024) /* safety check */
- return NULL;
- zfile_fseek (z, offset, SEEK_SET);
- z2 = zfile_fopen_empty (z, name, size);
- if (!z2)
- return NULL;
- zs.next_out = z2->data;
- zs.avail_out = size;
- first = 1;
- ret = Z_STREAM_ERROR;
- do {
- zs.next_in = buffer;
- zs.avail_in = zfile_fread (buffer, 1, sizeof (buffer), z);
- if (first) {
- if (inflateInit2_ (&zs, -MAX_WBITS, ZLIB_VERSION, sizeof (z_stream)) != Z_OK)
- break;
- first = 0;
- }
- ret = inflate (&zs, 0);
- } while (ret == Z_OK);
- inflateEnd (&zs);
- if (ret != Z_STREAM_END || first != 0) {
- zfile_fclose (z2);
- return NULL;
- }
- zfile_fclose (z);
- return z2;
- }
- struct zfile *zfile_gunzip (struct zfile *z)
- {
- return zfile_gunzip (z, NULL);
- }
- static void truncate880k (struct zfile *z)
- {
- int i;
- uae_u8 *b;
- if (z == NULL || z->data == NULL)
- return;
- if (z->size < 880 * 512 * 2) {
- int size = 880 * 512 * 2 - z->size;
- b = xcalloc (uae_u8, size);
- zfile_fwrite (b, size, 1, z);
- xfree (b);
- return;
- }
- for (i = 880 * 512 * 2; i < z->size; i++) {
- if (z->data[i])
- return;
- }
- z->size = 880 * 512 * 2;
- }
- static struct zfile *extadf (struct zfile *z, int index, int *retcode)
- {
- int i, r;
- struct zfile *zo;
- uae_u16 *mfm;
- uae_u16 *amigamfmbuffer;
- uae_u8 writebuffer_ok[32], *outbuf;
- int tracks, len, offs, pos;
- uae_u8 buffer[2 + 2 + 4 + 4];
- int outsize;
- TCHAR newname[MAX_DPATH];
- TCHAR *ext;
- int cantrunc = 0;
- int done = 0;
- if (index > 1)
- return NULL;
- mfm = xcalloc (uae_u16, 32000 / 2);
- amigamfmbuffer = xcalloc (uae_u16, 32000 / 2);
- outbuf = xcalloc (uae_u8, 16384);
- zfile_fread (buffer, 1, 8, z);
- zfile_fread (buffer, 1, 4, z);
- tracks = buffer[2] * 256 + buffer[3];
- offs = 8 + 2 + 2 + tracks * (2 + 2 + 4 + 4);
- _tcscpy (newname, zfile_getname (z));
- ext = _tcsrchr (newname, '.');
- if (ext) {
- _tcscpy (newname + _tcslen (newname) - _tcslen (ext), _T(".std.adf"));
- } else {
- _tcscat (newname, _T(".std.adf"));
- }
- if (index > 0)
- _tcscpy (newname + _tcslen (newname) - 4, _T(".ima"));
- zo = zfile_fopen_empty (z, newname, 0);
- if (!zo)
- goto end;
- if (retcode)
- *retcode = 1;
- pos = 12;
- outsize = 0;
- for (i = 0; i < tracks; i++) {
- int type, bitlen;
- zfile_fseek (z, pos, SEEK_SET);
- zfile_fread (buffer, 2 + 2 + 4 + 4, 1, z);
- pos = zfile_ftell (z);
- type = buffer[2] * 256 + buffer[3];
- len = buffer[5] * 65536 + buffer[6] * 256 + buffer[7];
- bitlen = buffer[9] * 65536 + buffer[10] * 256 + buffer[11];
- zfile_fseek (z, offs, SEEK_SET);
- if (type == 1) {
- zfile_fread (mfm, len, 1, z);
- memset (writebuffer_ok, 0, sizeof writebuffer_ok);
- memset (outbuf, 0, 16384);
- if (index == 0) {
- r = isamigatrack (amigamfmbuffer, (uae_u8*)mfm, len, outbuf, writebuffer_ok, i, &outsize);
- if (r < 0 && i == 0) {
- zfile_seterror (_T("'%s' is not AmigaDOS formatted"), zo->name);
- goto end;
- }
- if (i == 0)
- done = 1;
- } else {
- r = ispctrack (amigamfmbuffer, (uae_u8*)mfm, len, outbuf, writebuffer_ok, i, &outsize);
- if (r < 0 && i == 0) {
- zfile_seterror (_T("'%s' is not PC formatted"), zo->name);
- goto end;
- }
- if (i == 0)
- done = 1;
- }
- } else {
- outsize = 512 * 11;
- if (bitlen / 8 > 18000)
- outsize *= 2;
- zfile_fread (outbuf, outsize, 1, z);
- cantrunc = 1;
- if (index == 0)
- done = 1;
- }
- zfile_fwrite (outbuf, outsize, 1, zo);
- offs += len;
- }
- if (done == 0)
- goto end;
- zfile_fclose (z);
- xfree (mfm);
- xfree (amigamfmbuffer);
- if (cantrunc)
- truncate880k (zo);
- return zo;
- end:
- zfile_fclose (zo);
- xfree (mfm);
- xfree (amigamfmbuffer);
- return NULL;
- }
- #include "fdi2raw.h"
- static struct zfile *fdi (struct zfile *z, int index, int *retcode)
- {
- int i, j, r;
- struct zfile *zo;
- TCHAR *orgname = zfile_getname (z);
- TCHAR *ext = _tcsrchr (orgname, '.');
- TCHAR newname[MAX_DPATH];
- uae_u16 *amigamfmbuffer;
- uae_u8 writebuffer_ok[32], *outbuf;
- int tracks, len, outsize;
- FDI *fdi;
- int startpos = 0;
- uae_u8 tmp[12];
- struct zcache *zc;
- if (checkwrite (z, retcode))
- return NULL;
- if (index > 2)
- return NULL;
- zc = cache_get (z->name);
- if (!zc) {
- uae_u16 *mfm;
- struct zdiskimage *zd;
- fdi = fdi2raw_header (z);
- if (!fdi)
- return NULL;
- mfm = xcalloc (uae_u16, 32000 / 2);
- zd = xcalloc (struct zdiskimage, 1);
- tracks = fdi2raw_get_last_track (fdi);
- zd->tracks = tracks;
- for (i = 0; i < tracks; i++) {
- uae_u8 *buf, *p;
- fdi2raw_loadtrack (fdi, mfm, NULL, i, &len, NULL, NULL, 1);
- len /= 8;
- buf = p = xmalloc (uae_u8, len);
- for (j = 0; j < len / 2; j++) {
- uae_u16 v = mfm[j];
- *p++ = v >> 8;
- *p++ = v;
- }
- zd->zdisktracks[i].data = buf;
- zd->zdisktracks[i].len = len;
- }
- fdi2raw_header_free (fdi);
- zc = zcache_put (z->name, zd);
- }
- amigamfmbuffer = xcalloc (uae_u16, 32000 / 2);
- outbuf = xcalloc (uae_u8, 16384);
- tracks = zc->zd->tracks;
- if (ext) {
- _tcscpy (newname, orgname);
- _tcscpy (newname + _tcslen (newname) - _tcslen (ext), _T(".adf"));
- } else {
- _tcscat (newname, _T(".adf"));
- }
- if (index == 1)
- _tcscpy (newname + _tcslen (newname) - 4, _T(".ima"));
- if (index == 2)
- _tcscpy (newname + _tcslen (newname) - 4, _T(".ext.adf"));
- zo = zfile_fopen_empty (z, newname, 0);
- if (!zo)
- goto end;
- if (retcode)
- *retcode = 1;
- if (index > 1) {
- zfile_fwrite ("UAE-1ADF", 8, 1, zo);
- tmp[0] = 0; tmp[1] = 0; /* flags (reserved) */
- tmp[2] = 0; tmp[3] = tracks; /* number of tracks */
- zfile_fwrite (tmp, 4, 1, zo);
- memset (tmp, 0, sizeof tmp);
- tmp[2] = 0; tmp[3] = 1; /* track type */
- startpos = zfile_ftell (zo);
- for (i = 0; i < tracks; i++)
- zfile_fwrite (tmp, sizeof tmp, 1, zo);
- }
- outsize = 0;
- for (i = 0; i < tracks; i++) {
- uae_u8 *p = (uae_u8*)zc->zd->zdisktracks[i].data;
- len = zc->zd->zdisktracks[i].len;
- memset (writebuffer_ok, 0, sizeof writebuffer_ok);
- memset (outbuf, 0, 16384);
- if (index == 0) {
- r = isamigatrack (amigamfmbuffer, p, len, outbuf, writebuffer_ok, i, &outsize);
- if (r < 0 && i == 0) {
- zfile_seterror (_T("'%s' is not AmigaDOS formatted"), orgname);
- goto end;
- }
- zfile_fwrite (outbuf, outsize, 1, zo);
- } else if (index == 1) {
- r = ispctrack (amigamfmbuffer, p, len, outbuf, writebuffer_ok, i, &outsize);
- if (r < 0 && i == 0) {
- zfile_seterror (_T("'%s' is not PC formatted"), orgname);
- goto end;
- }
- zfile_fwrite (outbuf, outsize, 1, zo);
- } else {
- int pos = zfile_ftell (zo);
- int maxlen = len > 12798 ? len : 12798;
- int lenb = len * 8;
- if (maxlen & 1)
- maxlen++;
- zfile_fseek (zo, startpos + i * 12 + 4, SEEK_SET);
- tmp[4] = 0; tmp[5] = 0; tmp[6] = maxlen >> 8; tmp[7] = maxlen;
- tmp[8] = lenb >> 24; tmp[9] = lenb >> 16; tmp[10] = lenb >> 8; tmp[11] = lenb;
- zfile_fwrite (tmp + 4, 2, 4, zo);
- zfile_fseek (zo, pos, SEEK_SET);
- zfile_fwrite (p, 1, len, zo);
- if (maxlen > len)
- zfile_fwrite (outbuf, 1, maxlen - len, zo);
- }
- }
- zfile_fclose (z);
- xfree (amigamfmbuffer);
- xfree (outbuf);
- if (index == 0)
- truncate880k (zo);
- return zo;
- end:
- zfile_fclose (zo);
- xfree (amigamfmbuffer);
- xfree (outbuf);
- return NULL;
- }
- #ifdef CAPS
- #include "caps/caps_win32.h"
- static struct zfile *ipf (struct zfile *z, int index, int *retcode)
- {
- int i, j, r;
- struct zfile *zo;
- TCHAR *orgname = zfile_getname (z);
- TCHAR *ext = _tcsrchr (orgname, '.');
- TCHAR newname[MAX_DPATH];
- uae_u16 *amigamfmbuffer;
- uae_u8 writebuffer_ok[32];
- int tracks, len;
- int outsize;
- int startpos = 0;
- uae_u8 *outbuf;
- uae_u8 tmp[12];
- struct zcache *zc;
- if (checkwrite (z, retcode))
- return NULL;
- if (index > 2)
- return NULL;
- zc = cache_get (z->name);
- if (!zc) {
- uae_u16 *mfm;
- struct zdiskimage *zd;
- if (!caps_loadimage (z, 0, &tracks))
- return NULL;
- mfm = xcalloc (uae_u16, 32000 / 2);
- zd = xcalloc (struct zdiskimage, 1);
- zd->tracks = tracks;
- for (i = 0; i < tracks; i++) {
- uae_u8 *buf, *p;
- int mrev, gapo;
- caps_loadtrack (mfm, NULL, 0, i, &len, &mrev, &gapo, NULL, true);
- //write_log (_T("%d: %d %d %d\n"), i, mrev, gapo, len);
- len /= 8;
- buf = p = xmalloc (uae_u8, len);
- for (j = 0; j < len / 2; j++) {
- uae_u16 v = mfm[j];
- *p++ = v >> 8;
- *p++ = v;
- }
- zd->zdisktracks[i].data = buf;
- zd->zdisktracks[i].len = len;
- }
- caps_unloadimage (0);
- zc = zcache_put (z->name, zd);
- }
- outbuf = xcalloc (uae_u8, 16384);
- amigamfmbuffer = xcalloc (uae_u16, 32000 / 2);
- if (ext) {
- _tcscpy (newname, orgname);
- _tcscpy (newname + _tcslen (newname) - _tcslen (ext), _T(".adf"));
- } else {
- _tcscat (newname, _T(".adf"));
- }
- if (index == 1)
- _tcscpy (newname + _tcslen (newname) - 4, _T(".ima"));
- if (index == 2)
- _tcscpy (newname + _tcslen (newname) - 4, _T(".ext.adf"));
- zo = zfile_fopen_empty (z, newname, 0);
- if (!zo)
- goto end;
- if (retcode)
- *retcode = 1;
- tracks = zc->zd->tracks;
- if (index > 1) {
- zfile_fwrite ("UAE-1ADF", 8, 1, zo);
- tmp[0] = 0; tmp[1] = 0; /* flags (reserved) */
- tmp[2] = 0; tmp[3] = tracks; /* number of tracks */
- zfile_fwrite (tmp, 4, 1, zo);
- memset (tmp, 0, sizeof tmp);
- tmp[2] = 0; tmp[3] = 1; /* track type */
- startpos = zfile_ftell (zo);
- for (i = 0; i < tracks; i++)
- zfile_fwrite (tmp, sizeof tmp, 1, zo);
- }
- outsize = 0;
- for (i = 0; i < tracks; i++) {
- uae_u8 *p = (uae_u8*)zc->zd->zdisktracks[i].data;
- len = zc->zd->zdisktracks[i].len;
- memset (writebuffer_ok, 0, sizeof writebuffer_ok);
- memset (outbuf, 0, 16384);
- if (index == 0) {
- r = isamigatrack (amigamfmbuffer, p, len, outbuf, writebuffer_ok, i, &outsize);
- if (r < 0 && i == 0) {
- zfile_seterror (_T("'%s' is not AmigaDOS formatted"), orgname);
- goto end;
- }
- zfile_fwrite (outbuf, 1, outsize, zo);
- } else if (index == 1) {
- r = ispctrack (amigamfmbuffer, p, len, outbuf, writebuffer_ok, i, &outsize);
- if (r < 0 && i == 0) {
- zfile_seterror (_T("'%s' is not PC formatted"), orgname);
- goto end;
- }
- zfile_fwrite (outbuf, outsize, 1, zo);
- } else {
- int pos = zfile_ftell (zo);
- int maxlen = len > 12798 ? len : 12798;
- int lenb = len * 8;
- if (maxlen & 1)
- maxlen++;
- zfile_fseek (zo, startpos + i * 12 + 4, SEEK_SET);
- tmp[4] = 0; tmp[5] = 0; tmp[6] = maxlen >> 8; tmp[7] = maxlen;
- tmp[8] = lenb >> 24; tmp[9] = lenb >> 16; tmp[10] = lenb >> 8; tmp[11] = lenb;
- zfile_fwrite (tmp + 4, 2, 4, zo);
- zfile_fseek (zo, pos, SEEK_SET);
- zfile_fwrite (p, 1, len, zo);
- if (maxlen > len)
- zfile_fwrite (outbuf, 1, maxlen - len, zo);
- }
- }
- zfile_fclose (z);
- xfree (amigamfmbuffer);
- xfree (outbuf);
- if (index == 0)
- truncate880k (zo);
- return zo;
- end:
- zfile_fclose (zo);
- xfree (amigamfmbuffer);
- xfree (outbuf);
- return NULL;
- }
- #endif
- #ifdef A_LZX
- static struct zfile *dsq (struct zfile *z, int lzx, int *retcode)
- {
- struct zfile *zi = NULL;
- struct zvolume *zv = NULL;
- if (checkwrite (z, retcode))
- return NULL;
- if (lzx) {
- zv = archive_directory_lzx (z);
- if (zv) {
- if (zv->root.child)
- zi = archive_access_lzx (zv->root.child);
- }
- } else {
- zi = z;
- }
- if (zi) {
- uae_u8 *buf = zfile_getdata (zi, 0, -1, NULL);
- if (!memcmp (buf, "PKD\x13", 4) || !memcmp (buf, "PKD\x11", 4)) {
- TCHAR *fn;
- int sectors = buf[18];
- int reserved = buf[15];
- int blocks = (buf[6] << 8) | buf[7];
- int blocksize = (buf[10] << 8) | buf[11];
- struct zfile *zo;
- int size = blocks * blocksize;
- int off;
- int i;
- uae_u8 *bitmap = NULL;
- uae_u8 *nullsector;
- nullsector = xcalloc (uae_u8, blocksize);
- sectors /= 2;
- if (buf[3] == 0x13) {
- off = 52;
- if (buf[off - 1] == 1) {
- bitmap = &buf[off];
- off += (blocks + 7) / 8;
- } else if (buf[off - 1] > 1) {
- write_log (_T("unknown DSQ extra header type %d\n"), buf[off - 1]);
- }
- } else {
- off = 32;
- }
- // some Amiga disk images are smaller than full adf for some reason
- if (sectors == 11 && size < 1760 * 512)
- size = 1760 * 512;
- if (zfile_getfilename (zi) && _tcslen (zfile_getfilename (zi))) {
- fn = xmalloc (TCHAR, (_tcslen (zfile_getfilename (zi)) + 5));
- _tcscpy (fn, zfile_getfilename (zi));
- _tcscat (fn, _T(".adf"));
- } else {
- fn = my_strdup (_T("dsq.adf"));
- }
- zo = zfile_fopen_empty (z, fn, size);
- xfree (fn);
- int seccnt = 0;
- for (i = 0; i < blocks; i++) {
- int bmoff = i - 2;
- int boff = -1;
- uae_u32 mask = 0;
- if (bitmap) {
- boff = (bmoff / 32) * 4;
- mask = (bitmap[boff] << 24) | (bitmap[boff + 1] << 16) | (bitmap[boff + 2] << 8) | (bitmap[boff + 3]);
- }
- if (bmoff >= 0 && boff >= 0 && (mask & (1 << (bmoff & 31)))) {
- zfile_fwrite (nullsector, blocksize, 1, zo);
- } else {
- zfile_fwrite (buf + off, blocksize, 1, zo);
- off += blocksize;
- seccnt++;
- }
- if ((i % sectors) == sectors - 1) {
- off += seccnt * 16;
- seccnt = 0;
- }
- }
- zfile_fclose_archive (zv);
- zfile_fclose (z);
- xfree (buf);
- xfree (nullsector);
- return zo;
- }
- xfree (buf);
- }
- if (lzx)
- zfile_fclose (zi);
- return z;
- }
- #endif
- #ifdef A_WRP
- static struct zfile *wrp (struct zfile *z, int *retcode)
- {
- if (zfile_needwrite (z)) {
- if (retcode)
- *retcode = -1;
- return NULL;
- }
- return unwarp (z);
- }
- #endif
- #ifdef A_7Z
- #include "7z/Xz.h"
- #include "7z/Lzmadec.h"
- #include "7z/7zCrc.h"
- static void *SzAlloc (void *p, size_t size)
- {
- return xmalloc (uae_u8, size);
- }
- static void SzFree(void *p, void *address)
- {
- xfree (address);
- }
- #define XZ_OUT_SIZE 10000
- #define XZ_IN_SIZE 10000
- static struct zfile *xz (struct zfile *z, int *retcode)
- {
- static bool iscrc;
- ISzAlloc allocImp;
- CXzUnpacker cx;
- ECoderStatus status;
- struct zfile *zo = NULL;
- uae_u8 out[XZ_OUT_SIZE], in[XZ_IN_SIZE];
- if (checkwrite (z, retcode))
- return NULL;
- memset (&cx, 0, sizeof cx);
- allocImp.Alloc = SzAlloc;
- allocImp.Free = SzFree;
- if (!iscrc)
- CrcGenerateTable ();
- iscrc = true;
- // if (XzUnpacker_Create (&cx, &allocImp) != SZ_OK)
- // return NULL;
- XzUnpacker_Construct (&cx, &allocImp);
- int outwritten = 0;
- int towrite = 0;
- bool first = true;
- for (;;) {
- int read = zfile_fread (in, 1, XZ_IN_SIZE, z);
- if (first) {
- if (!(in[0] == 0xfd && in[1] == 0x37 && in[2] == 0x7a && in[3] == 0x58 && in[4] == 0x5a && in[5] == 0))
- break;
- }
- first = false;
- if (read == 0)
- break;
- if (read < 0) {
- zfile_fclose (zo);
- zo = NULL;
- break;
- }
- if (!zo)
- zo = zfile_fopen_empty (z, z->name);
- if (!zo)
- break;
- uae_u8 *inp = in;
- for (;;) {
- SizeT srclen = read;
- SizeT outlen = XZ_OUT_SIZE;
- if (XzUnpacker_Code (&cx, out, &outlen, inp, &srclen, LZMA_FINISH_ANY, &status) != SZ_OK) {
- zfile_fclose (zo);
- zo = NULL;
- break;
- }
- if (status != CODER_STATUS_NEEDS_MORE_INPUT && status != CODER_STATUS_NOT_FINISHED) {
- zfile_fclose (zo);
- zo = NULL;
- break;
- }
- zfile_fwrite (out, outlen, 1, zo);
- if (status == CODER_STATUS_FINISHED_WITH_MARK)
- break;
- if (srclen == read)
- break;
- inp += srclen;
- read -= srclen;
- }
- }
- XzUnpacker_Free (&cx);
- return zo;
- }
- #endif
- #ifdef A_DMS
- static struct zfile *dms (struct zfile *z, int index, int *retcode)
- {
- int ret;
- struct zfile *zo;
- TCHAR *orgname = zfile_getname (z);
- TCHAR *ext = _tcsrchr (orgname, '.');
- TCHAR newname[MAX_DPATH];
- static int recursive;
- int i;
- struct zfile *zextra[DMS_EXTRA_SIZE] = { 0 };
- if (checkwrite (z, retcode))
- return NULL;
- if (recursive)
- return NULL;
- if (ext) {
- _tcscpy (newname, orgname);
- _tcscpy (newname + _tcslen (newname) - _tcslen (ext), _T(".adf"));
- } else {
- _tcscat (newname, _T(".adf"));
- }
- zo = zfile_fopen_empty (z, newname, 1760 * 512);
- if (!zo)
- return NULL;
- ret = DMS_Process_File (z, zo, CMD_UNPACK, OPT_VERBOSE, 0, 0, 0, zextra);
- if (ret == NO_PROBLEM || ret == DMS_FILE_END) {
- int off = zfile_ftell (zo);
- if (off >= 1760 * 512 / 3 && off <= 1760 * 512 * 3 / 4) { // possible split dms?
- if (_tcslen (orgname) > 5) {
- TCHAR *s = orgname + _tcslen (orgname) - 5;
- if (!_tcsicmp (s, _T("a.dms"))) {
- TCHAR *fn2 = my_strdup (orgname);
- struct zfile *z2;
- fn2[_tcslen (fn2) - 5]++;
- recursive++;
- z2 = zfile_fopen (fn2, _T("rb"), z->zfdmask);
- recursive--;
- if (z2) {
- ret = DMS_Process_File (z2, zo, CMD_UNPACK, OPT_VERBOSE, 0, 0, 1, NULL);
- zfile_fclose (z2);
- }
- xfree (fn2);
- }
- }
- }
- zfile_fseek (zo, 0, SEEK_SET);
- if (index > 0) {
- zfile_fclose (zo);
- zo = NULL;
- for (i = 0; i < DMS_EXTRA_SIZE && zextra[i]; i++);
- if (index > i)
- goto end;
- zo = zextra[index - 1];
- zextra[index - 1] = NULL;
- }
- if (retcode)
- *retcode = 1;
- zfile_fclose (z);
- z = NULL;
- } else {
- zfile_fclose (zo);
- zo = NULL;
- }
- end:
- for (i = 0; i < DMS_EXTRA_SIZE; i++)
- zfile_fclose (zextra[i]);
- return zo;
- }
- #endif
- const TCHAR *uae_ignoreextensions[] =
- { _T(".gif"), _T(".jpg"), _T(".png"), _T(".xml"), _T(".pdf"), _T(".txt"), 0 };
- const TCHAR *uae_diskimageextensions[] =
- { _T(".adf"), _T(".adz"), _T(".ipf"), _T(".scp"), _T(".fdi"), _T(".exe"), _T(".dms"), _T(".wrp"), _T(".dsq"), 0 };
- int zfile_is_ignore_ext (const TCHAR *name)
- {
- int i;
- const TCHAR *ext;
- ext = _tcsrchr (name, '.');
- if (!ext)
- return 0;
- for (i = 0; uae_ignoreextensions[i]; i++) {
- if (!strcasecmp (uae_ignoreextensions[i], ext))
- return 1;
- }
- return 0;
- }
- int zfile_is_diskimage (const TCHAR *name)
- {
- int i;
- const TCHAR *ext = _tcsrchr (name, '.');
- if (!ext)
- return 0;
- i = 0;
- while (uae_diskimageextensions[i]) {
- if (!strcasecmp (ext, uae_diskimageextensions[i]))
- return HISTORY_FLOPPY;
- i++;
- }
- if (!_tcsicmp (ext, _T(".cue")))
- return HISTORY_CD;
- return -1;
- }
- static const TCHAR *archive_extensions[] = {
- _T("7z"), _T("rar"), _T("zip"), _T("lha"), _T("lzh"), _T("lzx"),
- _T("adf"), _T("adz"), _T("dsq"), _T("dms"), _T("ipf"), _T("fdi"), _T("wrp"), _T("ima"),
- _T("hdf"), _T("tar"),
- NULL
- };
- 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 };
- #if defined(ARCHIVEACCESS)
- static const uae_char *plugins_7z_x[] = { "7z", "Rar!", "MK", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
- #endif
- static const int plugins_7z_t[] = {
- ArchiveFormat7Zip, ArchiveFormatRAR, ArchiveFormatZIP, ArchiveFormatLHA, ArchiveFormatLHA, ArchiveFormatLZX,
- ArchiveFormatADF, ArchiveFormatADF, ArchiveFormatADF, ArchiveFormatTAR
- };
- static const int plugins_7z_m[] = {
- ZFD_ARCHIVE, ZFD_ARCHIVE, ZFD_ARCHIVE, ZFD_ARCHIVE, ZFD_ARCHIVE, ZFD_ARCHIVE,
- ZFD_ADF, ZFD_ADF, ZFD_ADF, ZFD_ARCHIVE
- };
- static int iszip (struct zfile *z, int mask)
- {
- TCHAR *name = z->name;
- TCHAR *ext = _tcsrchr (name, '.');
- uae_u8 header[32];
- if (!ext)
- return 0;
- memset (header, 0, sizeof (header));
- zfile_fseek (z, 0, SEEK_SET);
- zfile_fread (header, sizeof (header), 1, z);
- zfile_fseek (z, 0, SEEK_SET);
- if (mask & ZFD_ARCHIVE) {
- if (!strcasecmp (ext, _T(".zip")) || !strcasecmp (ext, _T(".rp9"))) {
- if (header[0] == 'P' && header[1] == 'K')
- return ArchiveFormatZIP;
- return 0;
- }
- }
- if (mask & ZFD_ARCHIVE) {
- if (!strcasecmp (ext, _T(".7z"))) {
- if (header[0] == '7' && header[1] == 'z')
- return ArchiveFormat7Zip;
- return 0;
- }
- if (!strcasecmp (ext, _T(".rar"))) {
- if (header[0] == 'R' && header[1] == 'a' && header[2] == 'r' && header[3] == '!')
- return ArchiveFormatRAR;
- return 0;
- }
- if (!strcasecmp (ext, _T(".lha")) || !strcasecmp (ext, _T(".lzh"))) {
- if (header[2] == '-' && header[3] == 'l' && header[4] == 'h' && header[6] == '-')
- return ArchiveFormatLHA;
- return 0;
- }
- if (!strcasecmp (ext, _T(".lzx"))) {
- if (header[0] == 'L' && header[1] == 'Z' && header[2] == 'X')
- return ArchiveFormatLZX;
- return 0;
- }
- }
- if (mask & ZFD_ADF) {
- if (!strcasecmp (ext, _T(".adf"))) {
- if (header[0] == 'D' && header[1] == 'O' && header[2] == 'S' && (header[3] >= 0 && header[3] <= 7))
- return ArchiveFormatADF;
- if (isfat (header))
- return ArchiveFormatFAT;
- return 0;
- }
- if (!strcasecmp (ext, _T(".ima"))) {
- if (isfat (header))
- return ArchiveFormatFAT;
- }
- }
- if (mask & ZFD_HD) {
- if (!strcasecmp (ext, _T(".hdf"))) {
- if (header[0] == 'D' && header[1] == 'O' && header[2] == 'S' && (header[3] >= 0 && header[3] <= 7))
- return ArchiveFormatADF;
- if (header[0] == 'S' && header[1] == 'F' && header[2] == 'S')
- return ArchiveFormatADF;
- if (header[0] == 'R' && header[1] == 'D' && header[2] == 'S' && header[3] == 'K')
- return ArchiveFormatRDB;
- if (isfat (header))
- return ArchiveFormatFAT;
- return 0;
- }
- }
- #if defined(ARCHIVEACCESS)
- for (int i = 0; plugins_7z_x[i]; i++) {
- if ((plugins_7z_m[i] & mask) && plugins_7z_x[i] && !strcasecmp (ext + 1, plugins_7z[i]) &&
- !memcmp (header, plugins_7z_x[i], strlen (plugins_7z_x[i])))
- return plugins_7z_t[i];
- }
- #endif
- return 0;
- }
- int iszip (struct zfile *z)
- {
- return iszip (z, ZFD_NORMAL);
- }
- struct zfile *zuncompress (struct znode *parent, struct zfile *z, int dodefault, int mask, int *retcode, int index)
- {
- TCHAR *name = z->name;
- TCHAR *ext = NULL;
- uae_u8 header[32];
- if (retcode)
- *retcode = 0;
- if (!mask)
- return NULL;
- if (name) {
- ext = _tcsrchr (name, '.');
- if (ext)
- ext++;
- }
- if (ext != NULL) {
- if (mask & ZFD_ARCHIVE) {
- if (strcasecmp (ext, _T("7z")) == 0)
- return archive_access_select (parent, z, ArchiveFormat7Zip, dodefault, retcode, index);
- if (strcasecmp (ext, _T("zip")) == 0)
- return archive_access_select (parent, z, ArchiveFormatZIP, dodefault, retcode, index);
- if (strcasecmp (ext, _T("lha")) == 0 || strcasecmp (ext, _T("lzh")) == 0)
- return archive_access_select (parent, z, ArchiveFormatLHA, dodefault, retcode, index);
- if (strcasecmp (ext, _T("lzx")) == 0)
- return archive_access_select (parent, z, ArchiveFormatLZX, dodefault, retcode, index);
- if (strcasecmp (ext, _T("rar")) == 0)
- return archive_access_select (parent, z, ArchiveFormatRAR, dodefault, retcode, index);
- if (strcasecmp (ext, _T("tar")) == 0)
- return archive_access_select (parent, z, ArchiveFormatTAR, dodefault, retcode, index);
- }
- if (mask & ZFD_UNPACK) {
- if (index == 0) {
- if (strcasecmp (ext, _T("gz")) == 0)
- return zfile_gunzip (z, retcode);
- if (strcasecmp (ext, _T("adz")) == 0)
- return zfile_gunzip (z, retcode);
- if (strcasecmp (ext, _T("roz")) == 0)
- return zfile_gunzip (z, retcode);
- if (strcasecmp (ext, _T("hdz")) == 0)
- return zfile_gunzip (z, retcode);
- #ifdef A_WRP
- if (strcasecmp (ext, _T("wrp")) == 0)
- return wrp (z, retcode);
- #endif
- #ifdef A_7Z
- if (strcasecmp (ext, _T("xz")) == 0)
- return xz (z, retcode);
- #endif
- }
- #ifdef A_DMS
- if (strcasecmp (ext, _T("dms")) == 0)
- return dms (z, index, retcode);
- #endif
- }
- if (mask & ZFD_RAWDISK) {
- #ifdef CAPS
- if (strcasecmp (ext, _T("ipf")) == 0)
- return ipf (z, index, retcode);
- #endif
- if (strcasecmp (ext, _T("fdi")) == 0)
- return fdi (z, index, retcode);
- if (mask & (ZFD_RAWDISK_PC | ZFD_RAWDISK_AMIGA))
- return NULL;
- }
- #if defined(ARCHIVEACCESS)
- if (index == 0) {
- for (int i = 0; plugins_7z_x[i]; i++) {
- if ((plugins_7z_t[i] & mask) && strcasecmp (ext, plugins_7z[i]) == 0)
- return archive_access_arcacc_select (z, plugins_7z_t[i], retcode);
- }
- }
- #endif
- }
- memset (header, 0, sizeof (header));
- zfile_fseek (z, 0, SEEK_SET);
- zfile_fread (header, sizeof (header), 1, z);
- zfile_fseek (z, 0, SEEK_SET);
- if (!memcmp (header, "conectix", 8)) {
- if (index > 0)
- return NULL;
- return vhd (z);
- }
- if (mask & ZFD_UNPACK) {
- if (index == 0) {
- if (header[0] == 0x1f && header[1] == 0x8b)
- return zfile_gunzip (z, retcode);
- #ifdef A_LZX
- if (header[0] == 'P' && header[1] == 'K' && header[2] == 'D')
- return dsq (z, 0, retcode);
- #endif
- #ifdef A_7Z
- if (header[0] == 0xfd && header[1] == 0x37 && header[2] == 0x7a && header[3] == 0x58 && header[4] == 0x5a && header[5] == 0)
- return xz (z, retcode);
- #endif
- }
- #ifdef A_DMS
- if (header[0] == 'D' && header[1] == 'M' && header[2] == 'S' && header[3] == '!')
- return dms (z, index, retcode);
- #endif
- }
- if (mask & ZFD_RAWDISK) {
- #ifdef CAPS
- if (header[0] == 'C' && header[1] == 'A' && header[2] == 'P' && header[3] == 'S')
- return ipf (z, index, retcode);
- #endif
- if (!memcmp (header, "Formatte", 8))
- return fdi (z, index, retcode);
- if (!memcmp (header, "UAE-1ADF", 8))
- return extadf (z, index, retcode);
- }
- if (index > 0)
- return NULL;
- if (mask & ZFD_ARCHIVE) {
- if (header[0] == 'P' && header[1] == 'K')
- return archive_access_select (parent, z, ArchiveFormatZIP, dodefault, retcode, index);
- if (header[0] == 'R' && header[1] == 'a' && header[2] == 'r' && header[3] == '!')
- return archive_access_select (parent, z, ArchiveFormatRAR, dodefault, retcode, index);
- if (header[0] == 'L' && header[1] == 'Z' && header[2] == 'X')
- return archive_access_select (parent, z, ArchiveFormatLZX, dodefault, retcode, index);
- if (header[2] == '-' && header[3] == 'l' && header[4] == 'h' && header[6] == '-')
- return archive_access_select (parent, z, ArchiveFormatLHA, dodefault, retcode, index);
- }
- if (mask & ZFD_ADF) {
- if (header[0] == 'D' && header[1] == 'O' && header[2] == 'S' && (header[3] >= 0 && header[3] <= 7))
- return archive_access_select (parent, z, ArchiveFormatADF, dodefault, retcode, index);
- if (header[0] == 'S' && header[1] == 'F' && header[2] == 'S')
- return archive_access_select (parent, z, ArchiveFormatADF, dodefault, retcode, index);
- if (isfat (header))
- return archive_access_select (parent, z, ArchiveFormatFAT, dodefault, retcode, index);
- }
- if (ext) {
- if (mask & ZFD_UNPACK) {
- #ifdef A_LZX
- if (strcasecmp (ext, _T("dsq")) == 0)
- return dsq (z, 1, retcode);
- #endif
- }
- if (mask & ZFD_ADF) {
- if (strcasecmp (ext, _T("adf")) == 0 && !memcmp (header, "DOS", 3))
- return archive_access_select (parent, z, ArchiveFormatADF, dodefault, retcode, index);
- }
- }
- return NULL;
- }
- #ifdef SINGLEFILE
- extern uae_u8 singlefile_data[];
- static struct zfile *zfile_opensinglefile(struct zfile *l)
- {
- uae_u8 *p = singlefile_data;
- int size, offset;
- TCHAR tmp[256], *s;
- _tcscpy (tmp, l->name);
- s = tmp + _tcslen (tmp) - 1;
- while (*s != 0 && *s != '/' && *s != '\\')
- s--;
- if (s > tmp)
- s++;
- write_log (_T("loading from singlefile: '%s'\n"), tmp);
- while (*p++);
- offset = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|(p[3] << 0);
- p += 4;
- for (;;) {
- size = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|(p[3] << 0);
- if (!size)
- break;
- if (!strcmpi (tmp, p + 4)) {
- l->data = singlefile_data + offset;
- l->size = size;
- write_log (_T("found, size %d\n"), size);
- return l;
- }
- offset += size;
- p += 4;
- p += _tcslen (p) + 1;
- }
- write_log (_T("not found\n"));
- return 0;
- }
- #endif
- static struct zfile *zfile_fopen_nozip (const TCHAR *name, const TCHAR *mode)
- {
- struct zfile *l;
- FILE *f;
- if(*name == '\0')
- return NULL;
- l = zfile_create (NULL, name);
- l->name = my_strdup (name);
- l->mode = my_strdup (mode);
- f = uae_tfopen (name, mode);
- if (!f) {
- zfile_fclose (l);
- return 0;
- }
- l->f = f;
- return l;
- }
- static struct zfile *openzip (const TCHAR *pname)
- {
- int i, j;
- TCHAR v;
- TCHAR name[MAX_DPATH];
- TCHAR zippath[MAX_DPATH];
- zippath[0] = 0;
- _tcscpy (name, pname);
- i = _tcslen (name) - 2;
- while (i > 0) {
- if ((name[i] == '/' || name[i] == '\\') && i > 4) {
- v = name[i];
- name[i] = 0;
- for (j = 0; plugins_7z[j]; j++) {
- int len = _tcslen (plugins_7z[j]);
- if (name[i - len - 1] == '.' && !strcasecmp (name + i - len, plugins_7z[j])) {
- struct zfile *f = zfile_fopen_nozip (name, _T("rb"));
- if (f) {
- f->zipname = my_strdup (name + i + 1);
- return f;
- }
- break;
- }
- }
- name[i] = v;
- }
- i--;
- }
- return 0;
- }
- static bool writeneeded (const TCHAR *mode)
- {
- return _tcschr (mode, 'w') || _tcschr (mode, 'a') || _tcschr (mode, '+') || _tcschr (mode, 't');
- }
- bool zfile_needwrite (struct zfile *zf)
- {
- if (!zf->mode)
- return false;
- return writeneeded (zf->mode);
- }
- static struct zfile *zfile_fopen_2 (const TCHAR *name, const TCHAR *mode, int mask)
- {
- struct zfile *l;
- FILE *f;
- if(*name == '\0')
- return NULL;
- #ifdef SINGLEFILE
- if (zfile_opensinglefile (l))
- return l;
- #endif
- l = openzip (name);
- if (l) {
- if (writeneeded (mode)) {
- zfile_fclose (l);
- return 0;
- }
- l->zfdmask = mask;
- } else {
- struct mystat st;
- l = zfile_create (NULL, name);
- l->mode = my_strdup (mode);
- l->name = my_strdup (name);
- l->zfdmask = mask;
- if (!_tcsicmp (mode, _T("r"))) {
- f = my_opentext (l->name);
- l->textmode = 1;
- } else {
- f = uae_tfopen (l->name, mode);
- }
- if (!f) {
- zfile_fclose (l);
- return 0;
- }
- if (my_stat (l->name, &st))
- l->size = st.size;
- l->f = f;
- }
- return l;
- }
- static void manglefilename(const TCHAR *in, TCHAR *out, int outsize)
- {
- if (!target_expand_environment(in, out, outsize))
- _tcscpy(out, in);
- for (int i = 0; i < _tcslen(out); i++) {
- // remove \\ or // in the middle of path
- if ((out[i] == '/' || out[i] == '\\') && (out[i + 1] == '/' || out[i + 1] == '\\') && i > 0) {
- memmove(out + i, out + i + 1, (_tcslen(out + i) + 1) * sizeof(TCHAR));
- i--;
- continue;
- }
- }
- }
- int zfile_zopen (const TCHAR *name, zfile_callback zc, void *user)
- {
- struct zfile *l;
- int ztype;
- TCHAR path[MAX_DPATH];
- manglefilename (name, path, sizeof path / sizeof(TCHAR));
- l = zfile_fopen_2 (path, _T("rb"), ZFD_NORMAL);
- if (!l)
- return 0;
- ztype = iszip (l);
- if (ztype == 0)
- zc (l, user);
- else
- archive_access_scan (l, zc, user, ztype);
- zfile_fclose (l);
- return 1;
- }
- /*
- * fopen() for a compressed file
- */
- static struct zfile *zfile_fopen_x (const TCHAR *name, const TCHAR *mode, int mask, int index)
- {
- int cnt = 10;
- struct zfile *l, *l2;
- TCHAR path[MAX_DPATH];
- if (_tcslen (name) == 0)
- return NULL;
- manglefilename(name, path, sizeof(path) / sizeof TCHAR);
- l = zfile_fopen_2 (path, mode, mask);
- if (!l)
- return 0;
- l2 = NULL;
- while (cnt-- > 0) {
- int rc;
- zfile_fseek (l, 0, SEEK_SET);
- l2 = zuncompress (NULL, l, 0, mask, &rc, index);
- if (!l2) {
- if (rc < 0) {
- zfile_fclose (l);
- return NULL;
- }
- zfile_fseek (l, 0, SEEK_SET);
- break;
- } else {
- if (l2->parent == l)
- l->opencnt--;
- }
- l = l2;
- }
- return l;
- }
- #ifdef _WIN32
- static int isinternetfile (const TCHAR *name)
- {
- if (!_tcsnicmp (name, _T("http://"), 7) || !_tcsnicmp (name, _T("https://"), 8))
- return 1;
- if (!_tcsnicmp (name, _T("ftp://"), 6))
- return -1;
- return 0;
- }
- #include <wininet.h>
- #include "win32.h"
- #define INETBUFFERLEN 1000000
- static struct zfile *zfile_fopen_internet (const TCHAR *name, const TCHAR *mode, int mask)
- {
- static HINTERNET hi;
- HINTERNET i = NULL;
- TCHAR tmp[MAX_DPATH];
- DWORD ierr = 0;
- DWORD outbuf = sizeof tmp / sizeof (TCHAR);
- uae_u8 *data = 0;
- int bufferlen = INETBUFFERLEN;
- int datalen;
- DWORD didread;
- struct zfile *zf = NULL;
- if (_tcschr (mode, 'w') || _tcschr (mode, 'a'))
- return NULL;
- tmp[0] = 0;
- if (!hi) {
- hi = InternetOpen (WINUAEAPPNAME, INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY, NULL, NULL, 0);
- if (hi == NULL) {
- write_log (_T("InternetOpen() failed, %d\n"), GetLastError ());
- return NULL;
- }
- }
- i = InternetOpenUrl (hi, name, NULL, 0, INTERNET_FLAG_NO_COOKIES, 0);
- if (i == NULL) {
- DWORD err = GetLastError ();
- if (err == ERROR_INTERNET_EXTENDED_ERROR)
- InternetGetLastResponseInfo (&ierr, tmp, &outbuf);
- write_log (_T("InternetOpenUrl(%s) failed %d (%d,%s)\n"), name, err, ierr, tmp);
- goto end;
- }
- if (isinternetfile (name) > 0) {
- DWORD statuscode;
- DWORD hindex = 0;
- DWORD size = sizeof statuscode;
- if (!HttpQueryInfo (i, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &statuscode, &size, &hindex)) {
- DWORD err = GetLastError ();
- write_log (_T("HttpQueryInfo(%s) failed %d\n"), name, err);
- goto end;
- }
- if (statuscode != 200) {
- write_log (_T("HttpQueryInfo(%s)=%d\n"), name, statuscode);
- goto end;
- }
- }
- if (mask & ZFD_CHECKONLY) {
- zf = zfile_create (NULL, name);
- goto end;
- }
- datalen = 0;
- data = xmalloc (uae_u8, bufferlen);
- for (;;) {
- if (!InternetReadFile (i, data + datalen, INETBUFFERLEN, &didread)) {
- DWORD err = GetLastError ();
- if (err == ERROR_INTERNET_EXTENDED_ERROR)
- InternetGetLastResponseInfo (&ierr, tmp, &outbuf);
- write_log (_T("InternetReadFile(%s) failed %d (%d,%s)\n"), name, err, ierr, tmp);
- break;
- }
- if (didread == 0)
- break;
- datalen += didread;
- if (datalen > bufferlen - INETBUFFERLEN) {
- bufferlen += INETBUFFERLEN;
- data = xrealloc (uae_u8, data, bufferlen);
- if (!data) {
- datalen = 0;
- break;
- }
- }
- }
- if (datalen > 0) {
- zf = zfile_create (NULL, name);
- if (zf) {
- zf->size = datalen;
- zf->data = data;
- data = NULL;
- }
- }
- end:
- if (i)
- InternetCloseHandle (i);
- free (data);
- return zf;
- }
- #endif
- static struct zfile *zfile_fopenx2 (const TCHAR *name, const TCHAR *mode, int mask, int index)
- {
- struct zfile *f;
- TCHAR tmp[MAX_DPATH];
- #ifdef _WIN32
- if (isinternetfile (name))
- return zfile_fopen_internet (name, mode, mask);
- #endif
- f = zfile_fopen_x (name, mode, mask, index);
- if (f)
- return f;
- if (_tcslen (name) <= 2)
- return NULL;
- if (name[1] != ':') {
- _tcscpy (tmp, start_path_data);
- _tcscat (tmp, name);
- f = zfile_fopen_x (tmp, mode, mask, index);
- if (f)
- return f;
- }
- #if 0
- name += 2;
- if (name[0] == '/' || name[0] == '\\')
- name++;
- for (;;) {
- _tcscpy (tmp, start_path_data);
- _tcscpy (tmp, name);
- f = zfile_fopen_x (tmp, mode, mask);
- if (f)
- return f;
- while (name[0]) {
- name++;
- if (name[-1] == '/' || name[-1] == '\\')
- break;
- }
- if (name[0] == 0)
- break;
- }
- #endif
- return NULL;
- }
- static struct zfile *zfile_fopenx (const TCHAR *name, const TCHAR *mode, int mask, int index)
- {
- struct zfile *zf;
- //write_log (_T("zfile_fopen('%s','%s',%08x,%d)\n"), name, mode, mask, index);
- zf = zfile_fopenx2 (name, mode, mask, index);
- //write_log (_T("=%p\n"), zf);
- return zf;
- }
- struct zfile *zfile_fopen (const TCHAR *name, const TCHAR *mode, int mask)
- {
- return zfile_fopenx (name, mode, mask, 0);
- }
- struct zfile *zfile_fopen (const TCHAR *name, const TCHAR *mode)
- {
- return zfile_fopenx (name, mode, 0, 0);
- }
- struct zfile *zfile_fopen (const TCHAR *name, const TCHAR *mode, int mask, int index)
- {
- return zfile_fopenx (name, mode, mask, index);
- }
- struct zfile *zfile_dup (struct zfile *zf)
- {
- struct zfile *nzf;
- if (!zf)
- return NULL;
- if (zf->archiveparent)
- checkarchiveparent (zf);
- if (zf->userdata)
- return NULL;
- if (!zf->data && zf->dataseek) {
- nzf = zfile_create (zf, NULL);
- } else if (zf->data) {
- nzf = zfile_create (zf, NULL);
- nzf->data = xmalloc (uae_u8, zf->size);
- if (!nzf->data) {
- write_log(_T("Out of memory: %s\n"), zfile_getname(zf));
- return NULL;
- }
- memcpy (nzf->data, zf->data, zf->size);
- nzf->size = zf->size;
- nzf->datasize = zf->datasize;
- } else if (zf->useparent) {
- nzf = zfile_fopen_parent(zf, zf->name, 0, zf->size);
- return nzf;
- } else {
- if (zf->zipname) {
- nzf = openzip (zf->name);
- if (nzf)
- return nzf;
- }
- if (!zf->name || !zf->mode)
- return NULL;
- FILE *ff = uae_tfopen (zf->name, zf->mode);
- if (!ff)
- return NULL;
- nzf = zfile_create (zf, NULL);
- nzf->f = ff;
- }
- zfile_fseek (nzf, zf->seek, SEEK_SET);
- if (zf->name)
- nzf->name = my_strdup (zf->name);
- if (nzf->zipname)
- nzf->zipname = my_strdup (zf->zipname);
- nzf->zfdmask = zf->zfdmask;
- nzf->mode = my_strdup (zf->mode);
- nzf->size = zf->size;
- return nzf;
- }
- int zfile_exists (const TCHAR *name)
- {
- struct zfile *z;
- if (my_existsfile (name))
- return 1;
- z = zfile_fopen (name, _T("rb"), ZFD_NORMAL | ZFD_CHECKONLY);
- if (!z)
- return 0;
- zfile_fclose (z);
- return 1;
- }
- int zfile_iscompressed (struct zfile *z)
- {
- return z->data ? 1 : 0;
- }
- struct zfile *zfile_fopen_empty (struct zfile *prev, const TCHAR *name, uae_u64 size)
- {
- struct zfile *l;
- l = zfile_create (prev, NULL);
- l->name = my_strdup (name ? name : _T(""));
- if (size) {
- l->data = xcalloc (uae_u8, size);
- if (!l->data) {
- xfree (l);
- return NULL;
- }
- l->size = size;
- l->datasize = size;
- l->allocsize = size;
- } else {
- l->data = xcalloc (uae_u8, 1000);
- l->size = 0;
- l->allocsize = 1000;
- }
- return l;
- }
- struct zfile *zfile_fopen_empty (struct zfile *prev, const TCHAR *name)
- {
- return zfile_fopen_empty (prev, name, 0);
- }
- struct zfile *zfile_fopen_parent (struct zfile *z, const TCHAR *name, uae…
Large files files are truncated, but you can click here to view the full file