[MPlayer-dev-eng] [PATCH] Use libunrar when available (2nd try)
Zuxy Meng
zuxy.meng at gmail.com
Wed May 31 12:53:12 CEST 2006
Hi,
This time temporary files are completely avoided, thanks to Eugene,
author of RAR. Also, libunique isn't completely discarded and
continues to work as a fallback of external libunrar.so/unrar.dll.
--
Zuxy
Beauty is truth,
While truth is beauty.
PGP KeyID: E8555ED6
-------------- next part --------------
--- main/unrarlib.c 2005-04-16 02:48:03.000000000 +0800
+++ main.new/unrarlib.c 2006-05-31 18:38:58.000000000 +0800
@@ -365,6 +365,11 @@
struct Decode *Dec,
int Size);
static int my_stricomp(char *Str1,char *Str2);
+static int libunrar_get(void** output,
+ unsigned long* size,
+ char* filename,
+ void* rarfile,
+ char* libpassword);
/* ------------------------------------------------------------------------ */
@@ -395,6 +400,10 @@
#endif
+ /* call libunrar.so first, use original code as a fallback */
+ if (libunrar_get(output, size, filename, rarfile, libpassword))
+ return TRUE;
+
InitCRC(); /* init some vars */
if(ArgName) free(ArgName);
@@ -2725,5 +2734,196 @@
****************************************************************************
************************************************************************** */
+/* -- The following code's added by MPlayer --------------------------------*/
+#ifndef _WIN32
+#define PASCAL
+#define CALLBACK
+#include <dlfcn.h>
+typedef void* HANDLE;
+#define LIBUNRAR_NAME "libunrar.so"
+#define PATHDELIMSTR "/"
+#else /* _WIN32 */
+#define dlopen(x, y) LoadLibraryA(x)
+#define dlsym GetProcAddress
+#define dlclose FreeLibrary
+#define LIBUNRAR_NAME "unrar.dll"
+#define PATHDELIMSTR "\\"
+#endif /* _WIN32 */
+
+#define ERAR_EOPEN 15
+#define RAR_OM_EXTRACT 1
+#define RAR_SKIP 0
+#define RAR_TEST 1
+
+struct RAROpenArchiveData
+{
+ char *ArcName;
+ unsigned int OpenMode;
+ unsigned int OpenResult;
+ char *CmtBuf;
+ unsigned int CmtBufSize;
+ unsigned int CmtSize;
+ unsigned int CmtState;
+};
+
+struct RARHeaderData
+{
+ char ArcName[260];
+ char FileName[260];
+ unsigned int Flags;
+ unsigned int PackSize;
+ unsigned int UnpSize;
+ unsigned int HostOS;
+ unsigned int FileCRC;
+ unsigned int FileTime;
+ unsigned int UnpVer;
+ unsigned int Method;
+ unsigned int FileAttr;
+ char *CmtBuf;
+ unsigned int CmtBufSize;
+ unsigned int CmtSize;
+ unsigned int CmtState;
+};
+
+enum UNRARCALLBACK_MESSAGES {
+ UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD
+};
+
+static HANDLE PASCAL (*RAROpenArchive)(struct RAROpenArchiveData *ArchiveData);
+static int PASCAL (*RARCloseArchive)(HANDLE hArcData);
+static int PASCAL (*RARReadHeader)(HANDLE hArcData,struct RARHeaderData *HeaderData);
+static int PASCAL (*RARProcessFile)(HANDLE hArcData,int Operation,char *DestPath,char *DestName);
+static void PASCAL (*RARSetPassword)(HANDLE hArcData,char *Password);
+static void PASCAL (*RARSetCallback)(
+ HANDLE hArcData,
+ int PASCAL (*CallbackProc)(unsigned msg, long UserData, long P1, long P2),
+ long UserData
+ );
+
+static int CALLBACK CallbackProc(unsigned msg, long UserData, long P1, long P2)
+{
+ char** p = (char**)UserData;
+ if (msg == UCM_PROCESSDATA)
+ {
+ memcpy(*p, (void*)P1, P2);
+ *p += P2;
+ }
+ return 0;
+}
+
+static void* init_func_pointers()
+{
+ void* libhdl = dlopen(LIBUNRAR_NAME, RTLD_LAZY);
+ if (!libhdl)
+ {
+#if 0
+#ifndef _WIN32
+ mp_msg(MSGT_VOBSUB, MSGL_DBG2, "UnRAR: Cannot load "LIBUNRAR_NAME": %s\n", dlerror());
+#else
+ mp_msg(
+ MSGT_VOBSUB,
+ MSGL_DBG2,
+ "UnRAR: Cannot load "LIBUNRAR_NAME", GetLastError() returns %d\n",
+ GetLastError());
+#endif /* _WIN32 */
+#endif
+ return NULL;
+ }
+
+ RAROpenArchive = dlsym(libhdl, "RAROpenArchive");
+ RARSetPassword = dlsym(libhdl, "RARSetPassword");
+ RARReadHeader = dlsym(libhdl, "RARReadHeader");
+ RARProcessFile = dlsym(libhdl, "RARProcessFile");
+ RARCloseArchive = dlsym(libhdl, "RARCloseArchive");
+ RARSetCallback = dlsym(libhdl, "RARSetCallback");
+
+ if (!RAROpenArchive || !RARSetPassword ||
+ !RARReadHeader || !RARProcessFile ||
+ !RARCloseArchive || !RARSetCallback)
+ {
+ dlclose(libhdl);
+#if 0
+#ifndef _WIN32
+ mp_msg(MSGT_VOBSUB, MSGL_DBG2, "UnRAR: dlsym failed: %s\n", dlerror());
+#else
+ mp_msg(
+ MSGT_VOBSUB,
+ MSGL_DBG2,
+ "UnRAR: GetProcAddress() failed, GetLastError() returns %d\n",
+ GetLastError());
+#endif /* _WIN32 */
+#endif
+ return NULL;
+ }
+
+ return libhdl;
+}
+
+static int libunrar_get(void **output,
+ unsigned long *size,
+ char *filename,
+ void *rarfile,
+ char *libpassword)
+{
+ struct RAROpenArchiveData opendata = {rarfile, RAR_OM_EXTRACT, ERAR_EOPEN, NULL, 0, 0, 0};
+ struct RARHeaderData headerdata;
+ int ret = 0;
+ HANDLE rarhdl;
+ void* libhdl;
+ void* p = NULL;
+
+ *output = NULL;
+ *size = 0;
+
+ /* No, we don't recurse into directories */
+ if (strstr(filename, PATHDELIMSTR))
+ return 0;
+
+ if ((libhdl = init_func_pointers()) == NULL)
+ return 0;
+
+ rarhdl = RAROpenArchive(&opendata);
+ if (!rarhdl || opendata.OpenResult)
+ goto byebye;
+
+ if (libpassword && strlen(libpassword))
+ RARSetPassword(rarhdl, libpassword);
+
+ headerdata.CmtBufSize = 0;
+
+ while (1)
+ {
+ if (RARReadHeader(rarhdl, &headerdata))
+ goto byebye;
+
+ // We won't extract subdirs
+ if (headerdata.Flags & 0xe0 == 0xe0 || strcasecmp(headerdata.FileName, filename))
+ {
+ if (RARProcessFile(rarhdl, RAR_SKIP, NULL, NULL))
+ break;
+ }
+ else
+ {
+ *size = headerdata.UnpSize;
+ p = *output = malloc(*size);
+ if (!output)
+ break;
+ RARSetCallback(rarhdl, CallbackProc, (long)&p);
+ if (!RARProcessFile(rarhdl, RAR_TEST, NULL, NULL))
+ ret = 1;
+ else
+ {
+ free(*output);
+ *output = NULL;
+ }
+ break;
+ }
+ }
+byebye:
+ RARCloseArchive(rarhdl);
+ dlclose(libhdl);
+ return ret;
+}
+/* -- End of MPlayer specific code --------------------------------- */
/* end of file urarlib.c */
More information about the MPlayer-dev-eng
mailing list