diff --git a/Makefile.common b/Makefile.common
index ffa0299863..41a323f107 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -747,15 +747,13 @@ ifeq ($(HAVE_7ZIP),1)
deps/7zip/Bcj2.o \
deps/7zip/7zCrc.o \
deps/7zip/Lzma2Dec.o \
- deps/7zip/7zBuf.o \
- decompress/7zip_support.o
+ deps/7zip/7zBuf.o
OBJ += $(7ZOBJ)
endif
OBJ += libretro-common/formats/tga/tga_decode.o
ifeq ($(HAVE_ZLIB), 1)
- ZLIB_OBJS = decompress/zip_support.o
OBJ += libretro-common/file/file_extract.o
OBJ += $(ZLIB_OBJS)
DEFINES += -DHAVE_ZLIB
diff --git a/decompress/7zip_support.c b/decompress/7zip_support.c
deleted file mode 100644
index 3efacda7e7..0000000000
--- a/decompress/7zip_support.c
+++ /dev/null
@@ -1,475 +0,0 @@
-/* RetroArch - A frontend for libretro.
- * Copyright (C) 2014-2015 - Timo Strunk
- * Copyright (C) 2011-2015 - Daniel De Matteis
- *
- * RetroArch is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Found-
- * ation, either version 3 of the License, or (at your option) any later version.
- *
- * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with RetroArch.
- * If not, see .
- */
-
-
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-#include "../deps/7zip/7z.h"
-#include "../deps/7zip/7zAlloc.h"
-#include "../deps/7zip/7zCrc.h"
-#include "../deps/7zip/7zFile.h"
-#include "../deps/7zip/7zVersion.h"
-
-/* Undefined at the end of the file
- * Don't use outside of this file
- */
-#define RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX 16384
-
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
-
-static int Buf_EnsureSize(CBuf *dest, size_t size)
-{
- if (dest->size >= size)
- return 1;
- Buf_Free(dest, &g_Alloc);
- return Buf_Create(dest, size, &g_Alloc);
-}
-
-#ifndef _WIN32
-
-static uint8_t kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-
-static Bool Utf16_To_Utf8(uint8_t *dest, size_t *destLen,
- const uint16_t *src, size_t srcLen)
-{
- size_t destPos = 0;
- size_t srcPos = 0;
-
- for (;;)
- {
- unsigned numAdds;
- uint32_t value;
-
- if (srcPos == srcLen)
- {
- *destLen = destPos;
- return True;
- }
- value = src[srcPos++];
- if (value < 0x80)
- {
- if (dest)
- dest[destPos] = (char)value;
- destPos++;
- continue;
- }
- if (value >= 0xD800 && value < 0xE000)
- {
- uint32_t c2;
-
- if (value >= 0xDC00 || srcPos == srcLen)
- break;
- c2 = src[srcPos++];
- if (c2 < 0xDC00 || c2 >= 0xE000)
- break;
- value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
- }
- for (numAdds = 1; numAdds < 5; numAdds++)
- if (value < (((uint32_t)1) << (numAdds * 5 + 6)))
- break;
- if (dest)
- dest[destPos] = (char)(kUtf8Limits[numAdds - 1]
- + (value >> (6 * numAdds)));
- destPos++;
- do
- {
- numAdds--;
- if (dest)
- dest[destPos] = (char)(0x80
- + ((value >> (6 * numAdds)) & 0x3F));
- destPos++;
- }while (numAdds != 0);
- }
- *destLen = destPos;
- return False;
-}
-
-static SRes Utf16_To_Utf8Buf(CBuf *dest,
- const uint16_t *src, size_t srcLen)
-{
- Bool res;
- size_t destLen = 0;
-
- Utf16_To_Utf8(NULL, &destLen, src, srcLen);
- destLen += 1;
-
- if (!Buf_EnsureSize(dest, destLen))
- return SZ_ERROR_MEM;
-
- res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen);
- dest->data[destLen] = 0;
-
- return res ? SZ_OK : SZ_ERROR_FAIL;
-}
-#endif
-
-static SRes Utf16_To_Char(CBuf *buf, const uint16_t *s, int fileMode)
-{
- int len = 0;
-
- for (len = 0; s[len] != '\0'; len++);
-
-#ifdef _WIN32
- {
- int size = len * 3 + 100;
- if (!Buf_EnsureSize(buf, size))
- return SZ_ERROR_MEM;
- {
- char defaultChar = '_';
- BOOL defUsed;
- int numChars = WideCharToMultiByte(fileMode ?
- (
-#ifdef UNDER_CE
- CP_ACP
-#else
- AreFileApisANSI() ? CP_ACP : CP_OEMCP
-#endif
- ) : CP_OEMCP,
- 0, (LPCWSTR)s, len, (char *)buf->data,
- size, &defaultChar, &defUsed);
- if (numChars == 0 || numChars >= size)
- return SZ_ERROR_FAIL;
- buf->data[numChars] = 0;
- return SZ_OK;
- }
- }
-#else
- (void)fileMode;
- return Utf16_To_Utf8Buf(buf, s, len);
-#endif
-}
-
-
-static SRes ConvertUtf16toCharString(const uint16_t *s, char *outstring)
-{
- CBuf buf;
- SRes res;
-
- Buf_Init(&buf);
- res = Utf16_To_Char(&buf, s, 0);
-
- if (res == SZ_OK)
- strncpy(outstring, (const char*)buf.data, PATH_MAX_LENGTH);
-
- Buf_Free(&buf, &g_Alloc);
- return res;
-}
-
-/* Extract the relative path relative_path from a 7z archive
- * archive_path and allocate a buf for it to write it in.
- * If optional_outfile is set, extract to that instead and don't alloc buffer.
- */
-int read_7zip_file(
- const char *archive_path,
- const char *relative_path, void **buf,
- const char *optional_outfile)
-{
- CFileInStream archiveStream;
- CLookToRead lookStream;
- CSzArEx db;
- SRes res;
- ISzAlloc allocImp;
- ISzAlloc allocTempImp;
- uint16_t *temp = NULL;
- size_t tempSize = 0;
- long outsize = -1;
- bool file_found = false;
-
- /*These are the allocation routines.
- * Currently using the non-standard 7zip choices. */
- allocImp.Alloc = SzAlloc;
- allocImp.Free = SzFree;
- allocTempImp.Alloc = SzAllocTemp;
- allocTempImp.Free = SzFreeTemp;
-
- if (InFile_Open(&archiveStream.file, archive_path))
- {
- RARCH_ERR("Could not open %s as 7z archive\n.",archive_path);
- return -1;
- }
- else
- {
- RARCH_LOG_OUTPUT("Openend archive %s. Now trying to extract %s\n",
- archive_path,relative_path);
- }
-
- FileInStream_CreateVTable(&archiveStream);
- LookToRead_CreateVTable(&lookStream, False);
- lookStream.realStream = &archiveStream.s;
- LookToRead_Init(&lookStream);
- CrcGenerateTable();
- SzArEx_Init(&db);
- res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
-
- if (res == SZ_OK)
- {
- uint32_t i;
- uint32_t blockIndex = 0xFFFFFFFF;
- uint8_t *outBuffer = 0;
- size_t outBufferSize = 0;
-
- for (i = 0; i < db.db.NumFiles; i++)
- {
- size_t len;
- char infile[PATH_MAX_LENGTH] = {0};
- size_t offset = 0;
- size_t outSizeProcessed = 0;
- const CSzFileItem *f = db.db.Files + i;
-
- if (f->IsDir)
- {
- /* We skip over everything which is not a directory.
- * FIXME: Why continue then if f->IsDir is true?*/
- continue;
- }
-
- len = SzArEx_GetFileNameUtf16(&db, i, NULL);
- if (len > tempSize)
- {
- free(temp);
- tempSize = len;
- temp = (uint16_t *)malloc(tempSize * sizeof(temp[0]));
- if (temp == 0)
- {
- res = SZ_ERROR_MEM;
- break;
- }
- }
- SzArEx_GetFileNameUtf16(&db, i, temp);
- res = ConvertUtf16toCharString(temp,infile);
-
- if (!strcmp(infile, relative_path))
- {
- /* C LZMA SDK does not support chunked extraction - see here:
- * sourceforge.net/p/sevenzip/discussion/45798/thread/6fb59aaf/
- * */
- file_found = true;
- res = SzArEx_Extract(&db, &lookStream.s, i,&blockIndex,
- &outBuffer, &outBufferSize,&offset, &outSizeProcessed,
- &allocImp, &allocTempImp);
- if (res != SZ_OK)
- {
- break; /* This goes to the error section. */
- }
- outsize = outSizeProcessed;
- if (optional_outfile != NULL)
- {
- FILE* outsink = fopen(optional_outfile,"wb");
- if (outsink == NULL)
- {
- RARCH_ERR("Could not open outfilepath %s.\n",
- optional_outfile);
- IAlloc_Free(&allocImp, outBuffer);
- SzArEx_Free(&db, &allocImp);
- free(temp);
- File_Close(&archiveStream.file);
- return -1;
- }
- fwrite(outBuffer+offset,1,outsize,outsink);
- fclose(outsink);
- }
- else
- {
- /*We could either use the 7Zip allocated buffer,
- * or create our own and use it.
- * We would however need to realloc anyways, because RetroArch
- * expects a \0 at the end, therefore we allocate new,
- * copy and free the old one. */
- *buf = malloc(outsize + 1);
- ((char*)(*buf))[outsize] = '\0';
- memcpy(*buf,outBuffer+offset,outsize);
- }
- IAlloc_Free(&allocImp, outBuffer);
- break;
- }
- }
- }
- SzArEx_Free(&db, &allocImp);
- free(temp);
-
- File_Close(&archiveStream.file);
-
- if (res == SZ_OK && file_found == true)
- return outsize;
-
- /* Error handling */
- if (!file_found)
- RARCH_ERR("File %s not found in %s\n",relative_path,archive_path);
- else if (res == SZ_ERROR_UNSUPPORTED)
- RARCH_ERR("7Zip decoder doesn't support this archive\n");
- else if (res == SZ_ERROR_MEM)
- RARCH_ERR("7Zip decoder could not allocate memory\n");
- else if (res == SZ_ERROR_CRC)
- RARCH_ERR("7Zip decoder encountered a CRC error in the archive\n");
- else
- RARCH_ERR("\nUnspecified error in 7-ZIP archive, error number was: #%d\n", res);
- return -1;
-}
-
-struct string_list *compressed_7zip_file_list_new(const char *path,
- const char* ext)
-{
- CFileInStream archiveStream;
- CLookToRead lookStream;
- CSzArEx db;
- SRes res;
- ISzAlloc allocImp;
- ISzAlloc allocTempImp;
- uint16_t *temp = NULL;
- size_t tempSize = 0;
- long outsize = -1;
-
- struct string_list *ext_list = NULL;
- struct string_list *list = string_list_new();
-
- if (!list)
- return NULL;
-
- if (ext)
- ext_list = string_split(ext, "|");
-
- (void)outsize;
-
- /* These are the allocation routines - currently using
- * the non-standard 7zip choices. */
- allocImp.Alloc = SzAlloc;
- allocImp.Free = SzFree;
- allocTempImp.Alloc = SzAllocTemp;
- allocTempImp.Free = SzFreeTemp;
-
- if (InFile_Open(&archiveStream.file, path))
- {
- RARCH_ERR("Could not open %s as 7z archive.\n",path);
- goto error;
- }
-
- FileInStream_CreateVTable(&archiveStream);
- LookToRead_CreateVTable(&lookStream, False);
- lookStream.realStream = &archiveStream.s;
- LookToRead_Init(&lookStream);
- CrcGenerateTable();
- SzArEx_Init(&db);
- res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
-
- if (res == SZ_OK)
- {
- uint32_t i;
- uint32_t blockIndex = 0xFFFFFFFF;
- uint8_t *outBuffer = 0;
- size_t outBufferSize = 0;
-
- (void)blockIndex;
- (void)outBufferSize;
- (void)outBuffer;
-
- for (i = 0; i < db.db.NumFiles; i++)
- {
- union string_list_elem_attr attr;
- const char *file_ext = NULL;
- char infile[PATH_MAX_LENGTH] = {0};
- size_t offset = 0;
- size_t outSizeProcessed = 0;
- size_t len = 0;
- bool supported_by_core = false;
- const CSzFileItem *f = db.db.Files + i;
-
- (void)offset;
- (void)outSizeProcessed;
-
- /* we skip over everything, which is a directory. */
- if (f->IsDir)
- continue;
-
- len = SzArEx_GetFileNameUtf16(&db, i, NULL);
-
- if (len > tempSize)
- {
- free(temp);
- tempSize = len;
- temp = (uint16_t *)malloc(tempSize * sizeof(temp[0]));
-
- if (temp == 0)
- {
- res = SZ_ERROR_MEM;
- break;
- }
- }
- SzArEx_GetFileNameUtf16(&db, i, temp);
- res = ConvertUtf16toCharString(temp, infile);
- file_ext = path_get_extension(infile);
-
- if (string_list_find_elem_prefix(ext_list, ".", file_ext))
- supported_by_core = true;
-
- /*
- * Currently we only support files without subdirs in the archives.
- * Folders are not supported (differences between win and lin.
- * Archives within archives should imho never be supported.
- */
-
- if (!supported_by_core)
- continue;
-
- attr.i = RARCH_COMPRESSED_FILE_IN_ARCHIVE;
-
- if (!string_list_append(list, infile, attr))
- goto error;
-
- }
- }
- SzArEx_Free(&db, &allocImp);
- free(temp);
- File_Close(&archiveStream.file);
-
- if (res != SZ_OK)
- {
- /* Error handling */
- if (res == SZ_ERROR_UNSUPPORTED)
- RARCH_ERR("7Zip decoder doesn't support this archive. \n");
- else if (res == SZ_ERROR_MEM)
- RARCH_ERR("7Zip decoder could not allocate memory. \n");
- else if (res == SZ_ERROR_CRC)
- RARCH_ERR("7Zip decoder encountered a CRC error in the archive. \n");
- else
- RARCH_ERR(
- "\nUnspecified error in 7-ZIP archive, error number was: #%d. \n",
- res);
- goto error;
- }
-
- string_list_free(ext_list);
- return list;
-
-error:
- RARCH_ERR("Failed to open compressed_file: \"%s\"\n", path);
- SzArEx_Free(&db, &allocImp);
- free(temp);
- File_Close(&archiveStream.file);
- string_list_free(list);
- string_list_free(ext_list);
- return NULL;
-}
-
-#undef RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX
diff --git a/decompress/7zip_support.h b/decompress/7zip_support.h
deleted file mode 100644
index 475332f17e..0000000000
--- a/decompress/7zip_support.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* RetroArch - A frontend for libretro.
- * Copyright (C) 2014-2015 - Timo Strunk
- * Copyright (C) 2011-2015 - Daniel De Matteis
- *
- * RetroArch is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Found-
- * ation, either version 3 of the License, or (at your option) any later version.
- *
- * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with RetroArch.
- * If not, see .
- */
-
-#ifndef __RARCH_7ZIP_SUPPORT_H
-#define __RARCH_7ZIP_SUPPORT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int read_7zip_file(const char * archive_path,
- const char *relative_path, void **buf, char const* optional_outfileq);
-
-struct string_list *compressed_7zip_file_list_new(const char *path,
- const char* ext);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/decompress/zip_support.c b/decompress/zip_support.c
deleted file mode 100644
index c7efe6316a..0000000000
--- a/decompress/zip_support.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/* RetroArch - A frontend for libretro.
- * Copyright (C) 2014-2015 - Timo Strunk
- * Copyright (C) 2011-2015 - Daniel De Matteis
- *
- * RetroArch is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Found-
- * ation, either version 3 of the License, or (at your option) any later version.
- *
- * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with RetroArch.
- * If not, see .
- */
-
-
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#include "../deps/zlib/unzip.h"
-
-/* Undefined at the end of the file
- * Don't use outside of this file
- */
-#define RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX 16384
-
-/* Extract the relative path relative_path from a
- * zip archive archive_path and allocate a buf for it to write it in. */
-/* This code is inspired by:
- * stackoverflow.com/questions/10440113/simple-way-to-unzip-a-zip-file-using-zlib
- *
- * optional_outfile if not NULL will be used to extract the file. buf will be 0
- * then.
- */
-
-int read_zip_file(const char *archive_path,
- const char *relative_path, void **buf,
- const char* optional_outfile)
-{
- uLong i;
- unz_global_info global_info;
- ssize_t bytes_read = -1;
- bool finished_reading = false;
- unzFile *zipfile = (unzFile*)unzOpen(archive_path);
-
- if (!zipfile)
- return -1;
-
- /* Get info about the zip file */
- if (unzGetGlobalInfo(zipfile, &global_info) != UNZ_OK)
- goto error;
-
- for ( i = 0; i < global_info.number_entry; ++i )
- {
- /* Get info about current file. */
- unz_file_info file_info;
- char filename[PATH_MAX_LENGTH] = {0};
- char last_char = ' ';
-
- if (unzGetCurrentFileInfo(
- zipfile,
- &file_info,
- filename,
- PATH_MAX_LENGTH,
- NULL, 0, NULL, 0 ) != UNZ_OK )
- goto error;
-
- /* Check if this entry is a directory or file. */
- last_char = filename[strlen(filename)-1];
-
- /* We skip directories */
- if ( last_char == '/' || last_char == '\\' ) { }
- else if (!strcmp(filename, relative_path))
- {
- /* We found the correct file in the zip,
- * now extract it to *buf. */
- if (unzOpenCurrentFile(zipfile) != UNZ_OK )
- goto error;
-
- if (optional_outfile == 0)
- {
- /* Allocate outbuffer */
- *buf = malloc(file_info.uncompressed_size + 1 );
- bytes_read = unzReadCurrentFile(zipfile, *buf, file_info.uncompressed_size);
-
- if (bytes_read != (ssize_t)file_info.uncompressed_size)
- {
- RARCH_ERR(
- "Tried to read %d bytes, but only got %d of file %s in ZIP %s.\n",
- (unsigned int) file_info.uncompressed_size, (int)bytes_read,
- relative_path, archive_path);
- free(*buf);
- goto close;
- }
- ((char*)(*buf))[file_info.uncompressed_size] = '\0';
- }
- else
- {
- char read_buffer[RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX] = {0};
- FILE* outsink = fopen(optional_outfile,"wb");
-
- if (outsink == NULL)
- goto close;
-
- bytes_read = 0;
-
- do
- {
- ssize_t fwrite_bytes;
-
- bytes_read = unzReadCurrentFile(zipfile, read_buffer,
- RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX );
- fwrite_bytes = fwrite(read_buffer, 1, bytes_read,outsink);
-
- if (fwrite_bytes == bytes_read)
- continue;
-
- /* couldn't write all bytes */
- RARCH_ERR("Error writing to %s.\n",optional_outfile);
- fclose(outsink);
- goto close;
- } while(bytes_read > 0);
-
- fclose(outsink);
- }
- finished_reading = true;
- }
-
- unzCloseCurrentFile(zipfile);
-
- if (finished_reading)
- break;
-
- if ((i + 1) < global_info.number_entry)
- {
- if (unzGoToNextFile(zipfile) == UNZ_OK)
- continue;
-
- goto error;
- }
- }
-
- unzClose(zipfile);
-
- if(!finished_reading)
- return -1;
-
- return bytes_read;
-
-close:
- unzCloseCurrentFile(zipfile);
-error:
- unzClose(zipfile);
- return -1;
-}
-
-#undef RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX
diff --git a/decompress/zip_support.h b/decompress/zip_support.h
deleted file mode 100644
index dd3e5efedd..0000000000
--- a/decompress/zip_support.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* RetroArch - A frontend for libretro.
- * Copyright (C) 2014-2015 - Timo Strunk
- * Copyright (C) 2011-2015 - Daniel De Matteis
- *
- * RetroArch is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Found-
- * ation, either version 3 of the License, or (at your option) any later version.
- *
- * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with RetroArch.
- * If not, see .
- */
-
-#ifndef __RARCH_ZIP_SUPPORT_H
-#define __RARCH_ZIP_SUPPORT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int read_zip_file(const char * archive_path,
- const char *relative_path, void **buf, const char* optional_outfile);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/file_ops.c b/file_ops.c
index e55113f431..7f3b3183d0 100644
--- a/file_ops.c
+++ b/file_ops.c
@@ -1,6 +1,7 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2015 - Daniel De Matteis
+ * Copyright (C) 2014-2015 - Timo Strunk
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
@@ -14,30 +15,605 @@
* If not, see .
*/
+#include
+#include
#include
-#include
+#include
#include
#include
#include
+#include
+
#include
#include
#include
#include
#include
+#include
#ifdef HAVE_COMPRESSION
#include
#endif
#include "file_ops.h"
-
#ifdef HAVE_7ZIP
-#include "decompress/7zip_support.h"
+#include "deps/7zip/7z.h"
+#include "deps/7zip/7zAlloc.h"
+#include "deps/7zip/7zCrc.h"
+#include "deps/7zip/7zFile.h"
+#include "deps/7zip/7zVersion.h"
+
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+static int Buf_EnsureSize(CBuf *dest, size_t size)
+{
+ if (dest->size >= size)
+ return 1;
+ Buf_Free(dest, &g_Alloc);
+ return Buf_Create(dest, size, &g_Alloc);
+}
+
+#ifndef _WIN32
+
+static uint8_t kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+static Bool Utf16_To_Utf8(uint8_t *dest, size_t *destLen,
+ const uint16_t *src, size_t srcLen)
+{
+ size_t destPos = 0;
+ size_t srcPos = 0;
+
+ for (;;)
+ {
+ unsigned numAdds;
+ uint32_t value;
+
+ if (srcPos == srcLen)
+ {
+ *destLen = destPos;
+ return True;
+ }
+ value = src[srcPos++];
+ if (value < 0x80)
+ {
+ if (dest)
+ dest[destPos] = (char)value;
+ destPos++;
+ continue;
+ }
+ if (value >= 0xD800 && value < 0xE000)
+ {
+ uint32_t c2;
+
+ if (value >= 0xDC00 || srcPos == srcLen)
+ break;
+ c2 = src[srcPos++];
+ if (c2 < 0xDC00 || c2 >= 0xE000)
+ break;
+ value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
+ }
+ for (numAdds = 1; numAdds < 5; numAdds++)
+ if (value < (((uint32_t)1) << (numAdds * 5 + 6)))
+ break;
+ if (dest)
+ dest[destPos] = (char)(kUtf8Limits[numAdds - 1]
+ + (value >> (6 * numAdds)));
+ destPos++;
+ do
+ {
+ numAdds--;
+ if (dest)
+ dest[destPos] = (char)(0x80
+ + ((value >> (6 * numAdds)) & 0x3F));
+ destPos++;
+ }while (numAdds != 0);
+ }
+ *destLen = destPos;
+ return False;
+}
+
+static SRes Utf16_To_Utf8Buf(CBuf *dest,
+ const uint16_t *src, size_t srcLen)
+{
+ Bool res;
+ size_t destLen = 0;
+
+ Utf16_To_Utf8(NULL, &destLen, src, srcLen);
+ destLen += 1;
+
+ if (!Buf_EnsureSize(dest, destLen))
+ return SZ_ERROR_MEM;
+
+ res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen);
+ dest->data[destLen] = 0;
+
+ return res ? SZ_OK : SZ_ERROR_FAIL;
+}
+#endif
+
+static SRes Utf16_To_Char(CBuf *buf, const uint16_t *s, int fileMode)
+{
+ int len = 0;
+
+ for (len = 0; s[len] != '\0'; len++);
+
+#ifdef _WIN32
+ {
+ int size = len * 3 + 100;
+ if (!Buf_EnsureSize(buf, size))
+ return SZ_ERROR_MEM;
+ {
+ char defaultChar = '_';
+ BOOL defUsed;
+ int numChars = WideCharToMultiByte(fileMode ?
+ (
+#ifdef UNDER_CE
+ CP_ACP
+#else
+ AreFileApisANSI() ? CP_ACP : CP_OEMCP
+#endif
+ ) : CP_OEMCP,
+ 0, (LPCWSTR)s, len, (char *)buf->data,
+ size, &defaultChar, &defUsed);
+ if (numChars == 0 || numChars >= size)
+ return SZ_ERROR_FAIL;
+ buf->data[numChars] = 0;
+ return SZ_OK;
+ }
+ }
+#else
+ (void)fileMode;
+ return Utf16_To_Utf8Buf(buf, s, len);
+#endif
+}
+
+
+static SRes ConvertUtf16toCharString(const uint16_t *s, char *outstring)
+{
+ CBuf buf;
+ SRes res;
+
+ Buf_Init(&buf);
+ res = Utf16_To_Char(&buf, s, 0);
+
+ if (res == SZ_OK)
+ strncpy(outstring, (const char*)buf.data, PATH_MAX_LENGTH);
+
+ Buf_Free(&buf, &g_Alloc);
+ return res;
+}
+
+/* Extract the relative path relative_path from a 7z archive
+ * archive_path and allocate a buf for it to write it in.
+ * If optional_outfile is set, extract to that instead and don't alloc buffer.
+ */
+static int read_7zip_file(
+ const char *archive_path,
+ const char *relative_path, void **buf,
+ const char *optional_outfile)
+{
+ CFileInStream archiveStream;
+ CLookToRead lookStream;
+ CSzArEx db;
+ SRes res;
+ ISzAlloc allocImp;
+ ISzAlloc allocTempImp;
+ uint16_t *temp = NULL;
+ size_t tempSize = 0;
+ long outsize = -1;
+ bool file_found = false;
+
+ /*These are the allocation routines.
+ * Currently using the non-standard 7zip choices. */
+ allocImp.Alloc = SzAlloc;
+ allocImp.Free = SzFree;
+ allocTempImp.Alloc = SzAllocTemp;
+ allocTempImp.Free = SzFreeTemp;
+
+ if (InFile_Open(&archiveStream.file, archive_path))
+ {
+ RARCH_ERR("Could not open %s as 7z archive\n.",archive_path);
+ return -1;
+ }
+ else
+ {
+ RARCH_LOG_OUTPUT("Openend archive %s. Now trying to extract %s\n",
+ archive_path,relative_path);
+ }
+
+ FileInStream_CreateVTable(&archiveStream);
+ LookToRead_CreateVTable(&lookStream, False);
+ lookStream.realStream = &archiveStream.s;
+ LookToRead_Init(&lookStream);
+ CrcGenerateTable();
+ SzArEx_Init(&db);
+ res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
+
+ if (res == SZ_OK)
+ {
+ uint32_t i;
+ uint32_t blockIndex = 0xFFFFFFFF;
+ uint8_t *outBuffer = 0;
+ size_t outBufferSize = 0;
+
+ for (i = 0; i < db.db.NumFiles; i++)
+ {
+ size_t len;
+ char infile[PATH_MAX_LENGTH] = {0};
+ size_t offset = 0;
+ size_t outSizeProcessed = 0;
+ const CSzFileItem *f = db.db.Files + i;
+
+ if (f->IsDir)
+ {
+ /* We skip over everything which is not a directory.
+ * FIXME: Why continue then if f->IsDir is true?*/
+ continue;
+ }
+
+ len = SzArEx_GetFileNameUtf16(&db, i, NULL);
+ if (len > tempSize)
+ {
+ free(temp);
+ tempSize = len;
+ temp = (uint16_t *)malloc(tempSize * sizeof(temp[0]));
+ if (temp == 0)
+ {
+ res = SZ_ERROR_MEM;
+ break;
+ }
+ }
+ SzArEx_GetFileNameUtf16(&db, i, temp);
+ res = ConvertUtf16toCharString(temp,infile);
+
+ if (!strcmp(infile, relative_path))
+ {
+ /* C LZMA SDK does not support chunked extraction - see here:
+ * sourceforge.net/p/sevenzip/discussion/45798/thread/6fb59aaf/
+ * */
+ file_found = true;
+ res = SzArEx_Extract(&db, &lookStream.s, i,&blockIndex,
+ &outBuffer, &outBufferSize,&offset, &outSizeProcessed,
+ &allocImp, &allocTempImp);
+ if (res != SZ_OK)
+ {
+ break; /* This goes to the error section. */
+ }
+ outsize = outSizeProcessed;
+ if (optional_outfile != NULL)
+ {
+ FILE* outsink = fopen(optional_outfile,"wb");
+ if (outsink == NULL)
+ {
+ RARCH_ERR("Could not open outfilepath %s.\n",
+ optional_outfile);
+ IAlloc_Free(&allocImp, outBuffer);
+ SzArEx_Free(&db, &allocImp);
+ free(temp);
+ File_Close(&archiveStream.file);
+ return -1;
+ }
+ fwrite(outBuffer+offset,1,outsize,outsink);
+ fclose(outsink);
+ }
+ else
+ {
+ /*We could either use the 7Zip allocated buffer,
+ * or create our own and use it.
+ * We would however need to realloc anyways, because RetroArch
+ * expects a \0 at the end, therefore we allocate new,
+ * copy and free the old one. */
+ *buf = malloc(outsize + 1);
+ ((char*)(*buf))[outsize] = '\0';
+ memcpy(*buf,outBuffer+offset,outsize);
+ }
+ IAlloc_Free(&allocImp, outBuffer);
+ break;
+ }
+ }
+ }
+ SzArEx_Free(&db, &allocImp);
+ free(temp);
+
+ File_Close(&archiveStream.file);
+
+ if (res == SZ_OK && file_found == true)
+ return outsize;
+
+ /* Error handling */
+ if (!file_found)
+ RARCH_ERR("File %s not found in %s\n",relative_path,archive_path);
+ else if (res == SZ_ERROR_UNSUPPORTED)
+ RARCH_ERR("7Zip decoder doesn't support this archive\n");
+ else if (res == SZ_ERROR_MEM)
+ RARCH_ERR("7Zip decoder could not allocate memory\n");
+ else if (res == SZ_ERROR_CRC)
+ RARCH_ERR("7Zip decoder encountered a CRC error in the archive\n");
+ else
+ RARCH_ERR("\nUnspecified error in 7-ZIP archive, error number was: #%d\n", res);
+ return -1;
+}
+
+static struct string_list *compressed_7zip_file_list_new(
+ const char *path, const char* ext)
+{
+ CFileInStream archiveStream;
+ CLookToRead lookStream;
+ CSzArEx db;
+ SRes res;
+ ISzAlloc allocImp;
+ ISzAlloc allocTempImp;
+ uint16_t *temp = NULL;
+ size_t tempSize = 0;
+ long outsize = -1;
+
+ struct string_list *ext_list = NULL;
+ struct string_list *list = string_list_new();
+
+ if (!list)
+ return NULL;
+
+ if (ext)
+ ext_list = string_split(ext, "|");
+
+ (void)outsize;
+
+ /* These are the allocation routines - currently using
+ * the non-standard 7zip choices. */
+ allocImp.Alloc = SzAlloc;
+ allocImp.Free = SzFree;
+ allocTempImp.Alloc = SzAllocTemp;
+ allocTempImp.Free = SzFreeTemp;
+
+ if (InFile_Open(&archiveStream.file, path))
+ {
+ RARCH_ERR("Could not open %s as 7z archive.\n",path);
+ goto error;
+ }
+
+ FileInStream_CreateVTable(&archiveStream);
+ LookToRead_CreateVTable(&lookStream, False);
+ lookStream.realStream = &archiveStream.s;
+ LookToRead_Init(&lookStream);
+ CrcGenerateTable();
+ SzArEx_Init(&db);
+ res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
+
+ if (res == SZ_OK)
+ {
+ uint32_t i;
+ uint32_t blockIndex = 0xFFFFFFFF;
+ uint8_t *outBuffer = 0;
+ size_t outBufferSize = 0;
+
+ (void)blockIndex;
+ (void)outBufferSize;
+ (void)outBuffer;
+
+ for (i = 0; i < db.db.NumFiles; i++)
+ {
+ union string_list_elem_attr attr;
+ const char *file_ext = NULL;
+ char infile[PATH_MAX_LENGTH] = {0};
+ size_t offset = 0;
+ size_t outSizeProcessed = 0;
+ size_t len = 0;
+ bool supported_by_core = false;
+ const CSzFileItem *f = db.db.Files + i;
+
+ (void)offset;
+ (void)outSizeProcessed;
+
+ /* we skip over everything, which is a directory. */
+ if (f->IsDir)
+ continue;
+
+ len = SzArEx_GetFileNameUtf16(&db, i, NULL);
+
+ if (len > tempSize)
+ {
+ free(temp);
+ tempSize = len;
+ temp = (uint16_t *)malloc(tempSize * sizeof(temp[0]));
+
+ if (temp == 0)
+ {
+ res = SZ_ERROR_MEM;
+ break;
+ }
+ }
+ SzArEx_GetFileNameUtf16(&db, i, temp);
+ res = ConvertUtf16toCharString(temp, infile);
+ file_ext = path_get_extension(infile);
+
+ if (string_list_find_elem_prefix(ext_list, ".", file_ext))
+ supported_by_core = true;
+
+ /*
+ * Currently we only support files without subdirs in the archives.
+ * Folders are not supported (differences between win and lin.
+ * Archives within archives should imho never be supported.
+ */
+
+ if (!supported_by_core)
+ continue;
+
+ attr.i = RARCH_COMPRESSED_FILE_IN_ARCHIVE;
+
+ if (!string_list_append(list, infile, attr))
+ goto error;
+
+ }
+ }
+ SzArEx_Free(&db, &allocImp);
+ free(temp);
+ File_Close(&archiveStream.file);
+
+ if (res != SZ_OK)
+ {
+ /* Error handling */
+ if (res == SZ_ERROR_UNSUPPORTED)
+ RARCH_ERR("7Zip decoder doesn't support this archive. \n");
+ else if (res == SZ_ERROR_MEM)
+ RARCH_ERR("7Zip decoder could not allocate memory. \n");
+ else if (res == SZ_ERROR_CRC)
+ RARCH_ERR("7Zip decoder encountered a CRC error in the archive. \n");
+ else
+ RARCH_ERR(
+ "\nUnspecified error in 7-ZIP archive, error number was: #%d. \n",
+ res);
+ goto error;
+ }
+
+ string_list_free(ext_list);
+ return list;
+
+error:
+ RARCH_ERR("Failed to open compressed_file: \"%s\"\n", path);
+ SzArEx_Free(&db, &allocImp);
+ free(temp);
+ File_Close(&archiveStream.file);
+ string_list_free(list);
+ string_list_free(ext_list);
+ return NULL;
+}
#endif
#ifdef HAVE_ZLIB
-#include "decompress/zip_support.h"
+#include "deps/zlib/unzip.h"
+
+#define RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX 16384
+
+/* Extract the relative path relative_path from a
+ * zip archive archive_path and allocate a buf for it to write it in. */
+/* This code is inspired by:
+ * stackoverflow.com/questions/10440113/simple-way-to-unzip-a-zip-file-using-zlib
+ *
+ * optional_outfile if not NULL will be used to extract the file. buf will be 0
+ * then.
+ */
+
+static int read_zip_file(const char *archive_path,
+ const char *relative_path, void **buf,
+ const char* optional_outfile)
+{
+ uLong i;
+ unz_global_info global_info;
+ ssize_t bytes_read = -1;
+ bool finished_reading = false;
+ unzFile *zipfile = (unzFile*)unzOpen(archive_path);
+
+ if (!zipfile)
+ return -1;
+
+ /* Get info about the zip file */
+ if (unzGetGlobalInfo(zipfile, &global_info) != UNZ_OK)
+ goto error;
+
+ for ( i = 0; i < global_info.number_entry; ++i )
+ {
+ /* Get info about current file. */
+ unz_file_info file_info;
+ char filename[PATH_MAX_LENGTH] = {0};
+ char last_char = ' ';
+
+ if (unzGetCurrentFileInfo(
+ zipfile,
+ &file_info,
+ filename,
+ PATH_MAX_LENGTH,
+ NULL, 0, NULL, 0 ) != UNZ_OK )
+ goto error;
+
+ /* Check if this entry is a directory or file. */
+ last_char = filename[strlen(filename)-1];
+
+ /* We skip directories */
+ if ( last_char == '/' || last_char == '\\' ) { }
+ else if (!strcmp(filename, relative_path))
+ {
+ /* We found the correct file in the zip,
+ * now extract it to *buf. */
+ if (unzOpenCurrentFile(zipfile) != UNZ_OK )
+ goto error;
+
+ if (optional_outfile == 0)
+ {
+ /* Allocate outbuffer */
+ *buf = malloc(file_info.uncompressed_size + 1 );
+ bytes_read = unzReadCurrentFile(zipfile, *buf, file_info.uncompressed_size);
+
+ if (bytes_read != (ssize_t)file_info.uncompressed_size)
+ {
+ RARCH_ERR(
+ "Tried to read %d bytes, but only got %d of file %s in ZIP %s.\n",
+ (unsigned int) file_info.uncompressed_size, (int)bytes_read,
+ relative_path, archive_path);
+ free(*buf);
+ goto close;
+ }
+ ((char*)(*buf))[file_info.uncompressed_size] = '\0';
+ }
+ else
+ {
+ char read_buffer[RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX] = {0};
+ FILE* outsink = fopen(optional_outfile,"wb");
+
+ if (outsink == NULL)
+ goto close;
+
+ bytes_read = 0;
+
+ do
+ {
+ ssize_t fwrite_bytes;
+
+ bytes_read = unzReadCurrentFile(zipfile, read_buffer,
+ RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX );
+ fwrite_bytes = fwrite(read_buffer, 1, bytes_read,outsink);
+
+ if (fwrite_bytes == bytes_read)
+ continue;
+
+ /* couldn't write all bytes */
+ RARCH_ERR("Error writing to %s.\n",optional_outfile);
+ fclose(outsink);
+ goto close;
+ } while(bytes_read > 0);
+
+ fclose(outsink);
+ }
+ finished_reading = true;
+ }
+
+ unzCloseCurrentFile(zipfile);
+
+ if (finished_reading)
+ break;
+
+ if ((i + 1) < global_info.number_entry)
+ {
+ if (unzGoToNextFile(zipfile) == UNZ_OK)
+ continue;
+
+ goto error;
+ }
+ }
+
+ unzClose(zipfile);
+
+ if(!finished_reading)
+ return -1;
+
+ return bytes_read;
+
+close:
+ unzCloseCurrentFile(zipfile);
+error:
+ unzClose(zipfile);
+ return -1;
+}
#endif
/**
diff --git a/griffin/griffin.c b/griffin/griffin.c
index 704633fb86..f6fdb6b9f6 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -43,7 +43,6 @@ CONSOLE EXTENSIONS
#ifdef HAVE_ZLIB
#include "../libretro-common/file/file_extract.c"
-#include "../decompress/zip_support.c"
#endif
/*============================================================
@@ -868,7 +867,6 @@ DEPENDENCIES
#include "../deps/7zip/7zCrc.c"
#include "../deps/7zip/Lzma2Dec.c"
#include "../deps/7zip/7zBuf.c"
-#include "../decompress/7zip_support.c"
#endif
/*============================================================