summaryrefslogtreecommitdiff
path: root/unrar/unrar.c
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@users.sourceforge.net>2009-11-28 13:11:51 +0100
committerTomas Bzatek <tbzatek@users.sourceforge.net>2009-11-28 13:11:51 +0100
commit9382f127ccebdd59917c97c61d008ed0e127cd75 (patch)
tree0a48c8296199b343c76ef532eef014f908bc2e4d /unrar/unrar.c
parent70eeaa4ec712895539ca6ecd60a42b93ec9b0904 (diff)
downloadtuxcmd-modules-9382f127ccebdd59917c97c61d008ed0e127cd75.tar.xz
Engine and VFS API cleanupv0.6.72
Also enable symlink resolving by default.
Diffstat (limited to 'unrar/unrar.c')
-rw-r--r--unrar/unrar.c794
1 files changed, 414 insertions, 380 deletions
diff --git a/unrar/unrar.c b/unrar/unrar.c
index 0db1493..61ce4c4 100644
--- a/unrar/unrar.c
+++ b/unrar/unrar.c
@@ -1,6 +1,6 @@
/* UNRAR plugin for Tux Commander
- * version 0.3.7, designed for unrar v3.8.2
- * Copyright (C) 2008 Tomas Bzatek <tbzatek@users.sourceforge.net>
+ * version 0.4.0, designed for unrar v3.8.2
+ * Copyright (C) 2007-2009 Tomas Bzatek <tbzatek@users.sourceforge.net>
* Check for updates on tuxcmd.sourceforge.net
*
* Uses UNRAR sources
@@ -26,21 +26,17 @@
*/
#include <string.h>
+#include <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
-#include <sys/stat.h>
-#include <sys/types.h>
#include <errno.h>
-#include <dirent.h>
-#include <fnmatch.h>
#include <unistd.h>
#include <glib.h>
-#include "vfs_types.h"
+#include "tuxcmd-vfs.h"
#include "vfsutils.h"
#include "strutils.h"
-#include "treepathutils.h"
-#include "treepath_vfs.h"
+#include "filelist.h"
+#include "filelist-vfs-intf.h"
#define _UNIX
@@ -48,15 +44,20 @@
#include "unrar/dll.hpp"
-// Compatibility types from headers.hpp
+/* Compatibility types from headers.hpp */
enum HOST_SYSTEM {
- HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
- HOST_BEOS=5,HOST_MAX
+ HOST_MSDOS = 0,
+ HOST_OS2 = 1,
+ HOST_WIN32 = 2,
+ HOST_UNIX = 3,
+ HOST_MACOS = 4,
+ HOST_BEOS = 5,
+ HOST_MAX
};
-#define VERSION "0.3.7"
-#define BUILD_DATE "2009-10-25"
+#define VERSION "0.4.0"
+#define BUILD_DATE "2009-11-26"
#define DEFAULT_BLOCK_SIZE 65536
@@ -64,7 +65,7 @@ enum HOST_SYSTEM {
-// Declaration of the global plugin object
+/* Declaration of the global plugin object */
struct TVFSGlobs {
TVFSLogFunc log_func;
char *curr_dir;
@@ -75,15 +76,15 @@ struct TVFSGlobs {
gboolean volume_missing_abort;
char *password;
- unsigned long block_size;
+ guint32 block_size;
struct PathTree *files;
struct VfsFilelistData *vfs_filelist;
- int64_t total_size;
+ guint64 total_size;
- int64_t extract_file_size;
- int64_t extract_done;
+ guint64 extract_file_size;
+ guint64 extract_done;
gboolean extract_cancelled;
TVFSAskQuestionCallback callback_ask_question;
@@ -100,13 +101,13 @@ struct TVFSGlobs {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////
// Basic initialization functions
+
struct TVFSGlobs *
VFSNew (TVFSLogFunc log_func)
{
struct TVFSGlobs * globs;
- globs = (struct TVFSGlobs *) malloc (sizeof (struct TVFSGlobs));
- memset (globs, 0, sizeof (struct TVFSGlobs));
+ globs = g_malloc0 (sizeof (struct TVFSGlobs));
globs->block_size = DEFAULT_BLOCK_SIZE;
globs->need_password = FALSE;
@@ -120,7 +121,8 @@ VFSNew (TVFSLogFunc log_func)
globs->callback_progress = NULL;
globs->log_func = log_func;
- if (globs->log_func != NULL) globs->log_func("unrar plugin: VFSInit");
+ if (globs->log_func)
+ globs->log_func("unrar plugin: VFSInit");
return globs;
}
@@ -141,19 +143,23 @@ VFSSetCallbacks (struct TVFSGlobs *globs,
void
VFSFree (struct TVFSGlobs *globs)
{
- if (globs->log_func != NULL) globs->log_func("unrar plugin: VFSDestroy");
- free (globs);
+ if (globs->log_func)
+ globs->log_func("unrar plugin: VFSDestroy");
+ g_free (globs);
}
-int VFSVersion()
+int
+VFSVersion ()
{
return cVFSVersion;
}
struct TVFSInfo *
-VFSGetInfo()
+VFSGetInfo ()
{
- struct TVFSInfo *module_info = g_malloc0 (sizeof (struct TVFSInfo));
+ struct TVFSInfo *module_info;
+
+ module_info = g_malloc0 (sizeof (struct TVFSInfo));
module_info->ID = g_strdup ("unrar_plugin");
module_info->Name = g_strdup ("UNRAR plugin");
@@ -174,77 +180,79 @@ VFSGetArchiveExts ()
/**************************************************************************************************************************************/
/**************************************************************************************************************************************/
-int unrar_callback(UINT msg, LONG UserData, LONG P1, LONG P2)
+static int
+unrar_callback (UINT msg, LONG UserData, LONG P1, LONG P2)
{
+ struct TVFSGlobs *globs;
+
// fprintf(stderr, "(II) unrar_callback called: msg = %d, UserData = %lx, sizeof(UserData) = %ld, P1 = %ld, P2 = %ld\n", msg, UserData, sizeof(UserData), P1, P2);
if (! UserData) {
- fprintf(stderr, "(WW) unrar_callback: UserData == NULL, exiting!\n");
+ fprintf (stderr, "(WW) unrar_callback: UserData == NULL, exiting!\n");
return 0;
}
- struct TVFSGlobs *globs = (struct TVFSGlobs *)UserData;
+ globs = (struct TVFSGlobs *) UserData;
// >= 0 => Weiter, -1 => Stop
- switch(msg)
- {
+ switch (msg) {
case UCM_CHANGEVOLUME: {
if (P2 == RAR_VOL_ASK) {
- fprintf(stderr, " (II) unrar_callback: UCM_CHANGEVOLUME message, RAR_VOL_ASK, P1 = %ld, (char*)P1 = '%s' \n", P1, (char*)P1);
- if (P1) {
- if (globs->callback_ask_question) {
- static const char *choices[] = {
- "Abort", /* response = 0 */
- "Ignore", /* response = 1 */
- NULL
- };
- char *message, *s;
- int choice = -1;
-
- s = g_filename_to_utf8 ((char *)P1, -1, NULL, NULL, NULL);
- message = g_strdup_printf ("Archive is incomplete, volume missing: \n\n%s", s ? s : (char *)P1);
- globs->callback_ask_question (message, &choices[0], &choice, 0,
- globs->callback_data);
- g_free (message);
- if (s) g_free (s);
-
- if (choice != 1)
- globs->volume_missing_abort = TRUE;
- return -1;
- } else {
- if (access((char*)P1, R_OK) != 0) {
- fprintf(stderr, "(EE) unrar_callback: UCM_CHANGEVOLUME message, RAR_VOL_ASK: access test failed - missing part? Error = %s \n", strerror(errno));
- return -1;
- }
- }
- }
+ fprintf (stderr, " (II) unrar_callback: UCM_CHANGEVOLUME message, RAR_VOL_ASK, P1 = %ld, (char*)P1 = '%s' \n", P1, (char*)P1);
+ if (P1) {
+ if (globs->callback_ask_question) {
+ static const char *choices[] = {
+ "Abort", /* response = 0 */
+ "Ignore", /* response = 1 */
+ NULL
+ };
+ char *message, *s;
+ int choice = -1;
+
+ s = g_filename_display_name((char *)P1);
+ message = g_strdup_printf ("Archive is incomplete, volume missing: \n\n%s", s ? s : (char *)P1);
+ globs->callback_ask_question (message, &choices[0], &choice, 0,
+ globs->callback_data);
+ g_free (message);
+ g_free (s);
+
+ if (choice != 1)
+ globs->volume_missing_abort = TRUE;
+ return -1;
+ } else {
+ if (access((char*)P1, R_OK) != 0) {
+ fprintf (stderr, "(EE) unrar_callback: UCM_CHANGEVOLUME message, RAR_VOL_ASK: access test failed - missing part? Error = %s \n", strerror (errno));
+ return -1;
+ }
+ }
+ }
} else
if (P2 == RAR_VOL_NOTIFY) {
- fprintf(stderr, " (II) unrar_callback: UCM_CHANGEVOLUME message, RAR_VOL_NOTIFY, P1 = %ld, (char*)P1 = '%s' \n", P1, (char*)P1);
+ fprintf (stderr, " (II) unrar_callback: UCM_CHANGEVOLUME message, RAR_VOL_NOTIFY, P1 = %ld, (char*)P1 = '%s' \n", P1, (char*)P1);
}
break;
}
case UCM_PROCESSDATA: {
- fprintf(stderr, " (II) unrar_callback: UCM_PROCESSDATA message, P1 = %ld, P2 = %ld \n", P1, P2);
+ fprintf (stderr, " (II) unrar_callback: UCM_PROCESSDATA message, P1 = %ld, P2 = %ld \n", P1, P2);
// printf(" (II) unrar_callback: globs = 0x%lX, UserData = 0x%lX \n", (unsigned long int)globs, UserData);
- if ((globs) && (globs->callback_progress)) {
-// printf(" (II) unrar_callback: globs->extract_callback_func = 0x%lX, globs->extract_callback_data = 0x%lX \n", (unsigned long int)globs->extract_callback_func, (unsigned long int)globs->extract_callback_data);
-// long int res = globs->extract_callback_func((u_int64_t)P1, (u_int64_t)((u_int64_t)P1 + (u_int64_t)P2), globs->extract_callback_data);
-
- globs->extract_done += P2;
- int res = globs->callback_progress(globs->extract_done, globs->extract_file_size, globs->callback_data);
-
-// fprintf(stderr, " (II) unrar_callback: res = %d \n", res);
- if (! res ) {
- globs->extract_cancelled = TRUE;
- fprintf(stderr, "(WW) unrar_callback: received cancellation result\n");
- return -1; // Cancel operation
- }
+ if (globs && globs->callback_progress) {
+// printf(" (II) unrar_callback: globs->extract_callback_func = 0x%lX, globs->extract_callback_data = 0x%lX \n", (unsigned long int)globs->extract_callback_func, (unsigned long int)globs->extract_callback_data);
+// long int res = globs->extract_callback_func((u_int64_t)P1, (u_int64_t)((u_int64_t)P1 + (u_int64_t)P2), globs->extract_callback_data);
+
+ globs->extract_done += P2;
+ int res = globs->callback_progress(globs->extract_done, globs->extract_file_size, globs->callback_data);
+
+// fprintf(stderr, " (II) unrar_callback: res = %d \n", res);
+ if (! res ) {
+ globs->extract_cancelled = TRUE;
+ fprintf (stderr, "(WW) unrar_callback: received cancellation result\n");
+ return -1; // Cancel operation
+ }
}
break;
}
case UCM_NEEDPASSWORD: {
- fprintf(stderr, " (II) unrar_callback: UCM_NEEDPASSWORD message, P1 = %ld, P2 = %ld, (char*)P1 = '%s', maxlen = %ld \n", P1, P2, (char*)P1, P2);
+ fprintf (stderr, " (II) unrar_callback: UCM_NEEDPASSWORD message, P1 = %ld, P2 = %ld, (char*)P1 = '%s', maxlen = %ld \n", P1, P2, (char*)P1, P2);
char *passwd = NULL;
int res = FALSE;
@@ -258,8 +266,8 @@ int unrar_callback(UINT msg, LONG UserData, LONG P1, LONG P2)
if (res && passwd) {
fprintf(stderr, " (II) unrar_callback: setting password to '%s'\n", passwd);
if (strlen (passwd) > 0) {
- strncpy((char *)P1, passwd, P2);
- if (globs->password) g_free (globs->password);
+ strncpy ((char *)P1, passwd, P2);
+ g_free (globs->password);
globs->password = g_strdup (passwd);
}
g_free (passwd);
@@ -277,22 +285,25 @@ int unrar_callback(UINT msg, LONG UserData, LONG P1, LONG P2)
return 0;
}
-int PASCAL unrar_changevol_proc(char *ArcName, int Mode)
+static int PASCAL
+unrar_changevol_proc (char *ArcName, int Mode)
{
- fprintf(stderr, "(II) unrar_changevol_proc called: ArcName = '%s', Mode = %d\n", ArcName, Mode);
+ fprintf (stderr, "(II) unrar_changevol_proc called: ArcName = '%s', Mode = %d\n", ArcName, Mode);
return 0;
}
-int PASCAL unrar_process_data_proc(unsigned char *Addr, int Size)
+static int PASCAL
+unrar_process_data_proc (unsigned char *Addr, int Size)
{
- fprintf(stderr, "(II) unrar_process_data_proc called: Addr = '%s', Size = %d\n", Addr, Size);
+ fprintf (stderr, "(II) unrar_process_data_proc called: Addr = '%s', Size = %d\n", Addr, Size);
return 0;
}
-time_t rar_time_to_unix(unsigned int FileTime)
+static time_t
+rar_time_to_unix (unsigned int FileTime)
{
struct tm t;
t.tm_sec = (FileTime & 0x1f) * 2;
@@ -303,146 +314,155 @@ time_t rar_time_to_unix(unsigned int FileTime)
t.tm_year = (FileTime >> 25) + 80;
t.tm_isdst = -1;
// printf("date: %d-%.2d-%.2d %d:%.2d:%.2d \n", t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
- return(mktime(&t));
+ return (mktime(&t));
}
-TVFSResult VFSOpenArchive(struct TVFSGlobs *globs, char *sName)
+/* ----------------------------------------------------------------------------------------------------------- */
+
+TVFSResult
+VFSOpenArchive (struct TVFSGlobs *globs, const char *sName)
{
- TVFSResult Result = cVFS_OK;
+ TVFSResult Result;
+ HANDLE PASCAL handle;
+ struct RAROpenArchiveDataEx *archive_data;
- globs->files = filelist_tree_new();
- globs->vfs_filelist = vfs_filelist_new(globs->files);
+ Result = cVFS_OK;
+
+ globs->files = filelist_tree_new ();
+ globs->vfs_filelist = vfs_filelist_new (globs->files);
globs->curr_dir = NULL;
- globs->archive_path = strdup(sName);
+ globs->archive_path = g_strdup (sName);
globs->total_size = 0;
globs->failed_passwd_callback = FALSE;
globs->volume_missing_abort = FALSE;
- fprintf(stderr, "(--) VFSOpenArchive: trying to open archive '%s'...\n", globs->archive_path);
-
- HANDLE PASCAL handle;
- struct RAROpenArchiveDataEx *archive_data;
+ fprintf (stderr, "(--) VFSOpenArchive: trying to open archive '%s'...\n", globs->archive_path);
- archive_data = (struct RAROpenArchiveDataEx*) malloc(sizeof(struct RAROpenArchiveDataEx));
- memset(archive_data, 0, sizeof(struct RAROpenArchiveDataEx));
+ /* WARNING: do not use g_malloc0() here, leads to memory corruption */
+ archive_data = malloc (sizeof (struct RAROpenArchiveDataEx));
+ memset (archive_data, 0, sizeof (struct RAROpenArchiveDataEx));
archive_data->ArcName = globs->archive_path;
archive_data->CmtBuf = NULL;
archive_data->CmtBufSize = 0;
archive_data->OpenMode = RAR_OM_LIST;
- handle = RAROpenArchiveEx(archive_data);
+ handle = RAROpenArchiveEx (archive_data);
// printf(" handle = %lu \n", (unsigned long int)handle);
// printf(" archive_data->OpenResult = %d \n", archive_data->OpenResult);
// printf(" archive_data->CmtState = %d \n", archive_data->CmtState);
// printf(" archive_data->CmtSize = %d \n", archive_data->CmtSize);
- if ((handle) && (! archive_data->OpenResult))
- {
- // Set callbacks
- RARSetCallback(handle, unrar_callback, (LONG)globs);
-// RARSetChangeVolProc(handle, unrar_changevol_proc);
-// RARSetProcessDataProc(handle, unrar_process_data_proc);
-
- if (globs->password) {
- fprintf(stderr, "(II) VFSOpenArchive: Setting password... \n");
- RARSetPassword(handle, globs->password);
- }
-
- struct RARHeaderDataEx *header;
- header = (struct RARHeaderDataEx*) malloc(sizeof(struct RARHeaderDataEx));
- memset(header, 0, sizeof(struct RARHeaderDataEx));
- header->CmtBuf = NULL;
- header->CmtBufSize = 0;
-
- int PASCAL res = 0;
- while ((res = RARReadHeaderEx(handle, header)) == 0)
- {
-// printf(" header->FileName = '%s', Flags = 0x%x\n", header->FileName, header->Flags);
-
- // Create a TVFSItem entry and fill all info
- struct TVFSItem *item = (struct TVFSItem*)malloc(sizeof(struct TVFSItem));
- memset(item, 0, sizeof(struct TVFSItem));
-
- item->iSize = (int64_t)((int64_t)(header->UnpSizeHigh * 0x100000000) + (int64_t)header->UnpSize);
- item->iPackedSize = (int64_t)((int64_t)(header->PackSizeHigh * 0x100000000) + (int64_t)header->PackSize);
- globs->total_size += item->iSize;
- if ((header->Flags & 0x00e0 /* LHD_WINDOWMASK */ ) == 0x00e0 /* LHD_DIRECTORY */)
- item->ItemType = vDirectory;
- else item->ItemType = vRegular;
- if ((header->Flags & 0x0004) == 0x0004) globs->need_password = TRUE;
-
- switch (header->HostOS)
- {
- case HOST_MSDOS:
- case HOST_OS2:
- case HOST_WIN32:
- if (header->FileAttr & 0x10) header->FileAttr = 0x41ff | header->FileAttr;
- else
- if (header->FileAttr & 1) header->FileAttr = 0x8124 | header->FileAttr;
- else header->FileAttr = 0x81b6 | header->FileAttr;
- break;
- }
-
- item->iMode = header->FileAttr;
- item->iUID = geteuid();
- item->iGID = getegid();
- item->m_time = rar_time_to_unix(header->FileTime);
- item->c_time = item->m_time;
- item->a_time = item->m_time;
-
-// g_print (" valid = %d\n", g_utf8_validate (header->FileName, -1, NULL));
-
- char *s;
- if (g_utf8_validate (header->FileName, -1, NULL))
- s = g_strdup (header->FileName);
- else
- s = wide_to_utf8 (header->FileNameW);
-// g_print (" ansi = '%s'\n wide = '%ls'\n utf8 = '%s'\n", header->FileName, header->FileNameW, s);
-
- // Add item to the global list and continue with next file
- filelist_tree_add_item(globs->files, s, header->FileName, item, 0);
- g_free (s);
-
- int PASCAL res2 = RARProcessFile(handle, RAR_SKIP, NULL, NULL);
- if (res2) printf("RARProcessFile result = %d\n", res2);
- }
-// printf("\nRARReadHeader result = %d\n", res);
- if (res != ERAR_END_ARCHIVE || globs->volume_missing_abort) {
- fprintf(stderr, "(EE) VFSOpenArchive: RARReadHeader result = %d\n", res);
- Result = cVFS_Failed;
- if ((res == ERAR_MISSING_PASSWORD) || ((res == ERAR_BAD_DATA) && (globs->failed_passwd_callback)))
- Result = cVFS_BadPassword;
- }
- free(header);
-
- res = RARCloseArchive(handle);
- if (res) {
- fprintf(stderr, "(EE) VFSOpenArchive: RARCloseArchive result = %d\n", res);
- }
+ if (handle && ! archive_data->OpenResult) {
+ // Set callbacks
+ RARSetCallback (handle, unrar_callback, (LONG)globs);
+// RARSetChangeVolProc(handle, unrar_changevol_proc);
+// RARSetProcessDataProc(handle, unrar_process_data_proc);
+
+ if (globs->password) {
+ fprintf (stderr, "(II) VFSOpenArchive: Setting password... \n");
+ RARSetPassword (handle, globs->password);
+ }
+
+ struct RARHeaderDataEx *header;
+ /* WARNING: do not use g_malloc0() here, leads to memory corruption */
+ header = malloc (sizeof (struct RARHeaderDataEx));
+ memset (header, 0, sizeof (struct RARHeaderDataEx));
+
+ int PASCAL res = 0;
+ while ((res = RARReadHeaderEx(handle, header)) == 0) {
+// printf(" header->FileName = '%s', Flags = 0x%x\n", header->FileName, header->Flags);
+
+ /* Create a TVFSItem entry and fill all info */
+ struct TVFSItem *item = g_malloc0 (sizeof (struct TVFSItem));
+
+ item->iSize = (guint64)((guint64)(header->UnpSizeHigh * 0x100000000) + (guint64)header->UnpSize);
+ item->iPackedSize = (guint64)((guint64)(header->PackSizeHigh * 0x100000000) + (guint64)header->PackSize);
+ globs->total_size += item->iSize;
+ if ((header->Flags & 0x00e0 /* LHD_WINDOWMASK */ ) == 0x00e0 /* LHD_DIRECTORY */)
+ item->ItemType = vDirectory;
+ else
+ item->ItemType = vRegular;
+ if ((header->Flags & 0x0004) == 0x0004)
+ globs->need_password = TRUE;
+
+ switch (header->HostOS) {
+ case HOST_MSDOS:
+ case HOST_OS2:
+ case HOST_WIN32:
+ if (header->FileAttr & 0x10)
+ header->FileAttr = 0x41ff | header->FileAttr;
+ else
+ if (header->FileAttr & 1)
+ header->FileAttr = 0x8124 | header->FileAttr;
+ else
+ header->FileAttr = 0x81b6 | header->FileAttr;
+ break;
+ }
+
+ item->iMode = header->FileAttr;
+ item->iUID = geteuid ();
+ item->iGID = getegid ();
+ item->m_time = rar_time_to_unix (header->FileTime);
+ item->c_time = item->m_time;
+ item->a_time = item->m_time;
+
+// g_print (" valid = %d\n", g_utf8_validate (header->FileName, -1, NULL));
+
+ char *s;
+ if (g_utf8_validate (header->FileName, -1, NULL))
+ s = g_strdup (header->FileName);
+ else
+ s = wide_to_utf8 (header->FileNameW);
+// g_print (" ansi = '%s'\n wide = '%ls'\n utf8 = '%s'\n", header->FileName, header->FileNameW, s);
+
+ // Add item to the global list and continue with next file
+ filelist_tree_add_item (globs->files, s, item, header->FileName, 0);
+ g_free (s);
+
+ int PASCAL res2 = RARProcessFile (handle, RAR_SKIP, NULL, NULL);
+ if (res2)
+ printf ("RARProcessFile result = %d\n", res2);
+ }
+// printf("\nRARReadHeader result = %d\n", res);
+ if (res != ERAR_END_ARCHIVE || globs->volume_missing_abort) {
+ fprintf (stderr, "(EE) VFSOpenArchive: RARReadHeader result = %d\n", res);
+ Result = cVFS_Failed;
+ if (res == ERAR_MISSING_PASSWORD || (res == ERAR_BAD_DATA && globs->failed_passwd_callback))
+ Result = cVFS_BadPassword;
+ }
+ free (header);
+
+ res = RARCloseArchive(handle);
+ if (res)
+ fprintf (stderr, "(EE) VFSOpenArchive: RARCloseArchive result = %d\n", res);
} else {
- fprintf(stderr, "(EE) VFSOpenArchive: error occured when opening archive: OpenResult = %d\n", archive_data->OpenResult);
- Result = cVFS_Failed;
+ fprintf (stderr, "(EE) VFSOpenArchive: error occured when opening archive: OpenResult = %d\n", archive_data->OpenResult);
+ Result = cVFS_Failed;
}
- free(archive_data);
- fprintf(stderr, "(II) VFSOpenArchive: done. \n");
- if (globs->need_password) printf("Password present.\n");
- printf("\n\nList of items:\n");
- filelist_tree_print(globs->files);
+ free (archive_data);
+ fprintf (stderr, "(II) VFSOpenArchive: done. \n");
+ if (globs->need_password)
+ printf ("Password present.\n");
+ printf ("\n\nList of items:\n");
+ filelist_tree_print (globs->files);
return Result;
}
-TVFSResult VFSClose(struct TVFSGlobs *globs)
+TVFSResult
+VFSClose (struct TVFSGlobs *globs)
{
if (globs) {
- fprintf(stderr, "(II) VFSClose: Freeing objects...\n");
- if (globs->vfs_filelist) vfs_filelist_free(globs->vfs_filelist);
- if (globs->files) filelist_tree_free(globs->files);
- if (globs->archive_path) free(globs->archive_path);
- if (globs->curr_dir) free(globs->curr_dir);
- if (globs->password) free(globs->password);
+ fprintf (stderr, "(II) VFSClose: Freeing objects...\n");
+ if (globs->vfs_filelist)
+ vfs_filelist_free(globs->vfs_filelist);
+ if (globs->files)
+ filelist_tree_free(globs->files);
+ g_free (globs->archive_path);
+ g_free (globs->curr_dir);
+ g_free (globs->password);
}
return cVFS_OK;
}
@@ -453,42 +473,48 @@ VFSGetPath (struct TVFSGlobs *globs)
return include_trailing_path_sep (globs->curr_dir);
}
-u_int64_t VFSGetFileSystemFree(struct TVFSGlobs *globs, char *APath)
+TVFSResult
+VFSGetFileSystemInfo (struct TVFSGlobs *globs, const char *APath, gint64 *FSSize, gint64 *FSFree, char **FSLabel)
{
- return 0;
-}
-
-u_int64_t VFSGetFileSystemSize(struct TVFSGlobs *globs, char *APath)
-{
- return globs->total_size;
+ if (FSSize)
+ *FSSize = globs->total_size;
+ if (FSFree)
+ *FSFree = 0;
+ if (FSLabel)
+ *FSLabel = NULL;
+ return cVFS_OK;
}
-
-
/******************************************************************************************************/
-TVFSResult VFSChangeDir(struct TVFSGlobs *globs, char *NewPath)
+TVFSResult
+VFSChangeDir (struct TVFSGlobs *globs, const char *NewPath)
{
if (NewPath == NULL) {
- printf("(EE) VFSChangeDir: NewPath is NULL!\n");
+ printf ("(EE) VFSChangeDir: NewPath is NULL!\n");
return cVFS_Failed;
}
- globs->curr_dir = vfs_filelist_change_dir(globs->vfs_filelist, NewPath);
- if (globs->curr_dir) return cVFS_OK;
- else return cVFS_Failed;
+ globs->curr_dir = vfs_filelist_change_dir (globs->vfs_filelist, NewPath);
+ if (globs->curr_dir)
+ return cVFS_OK;
+ else
+ return cVFS_Failed;
}
-int VFSGetPasswordRequired(struct TVFSGlobs *globs)
+gboolean
+VFSGetPasswordRequired (struct TVFSGlobs *globs)
{
- if (globs) return globs->need_password;
+ if (globs)
+ return globs->need_password;
return FALSE;
}
-void VFSResetPassword(struct TVFSGlobs *globs)
+void
+VFSResetPassword (struct TVFSGlobs *globs)
{
- if (globs && globs->password) {
+ if (globs) {
g_free (globs->password);
globs->password = NULL;
}
@@ -497,40 +523,41 @@ void VFSResetPassword(struct TVFSGlobs *globs)
/******************************************************************************************************/
-TVFSResult VFSListFirst(struct TVFSGlobs *globs, char *sDir, struct TVFSItem *Item)
+TVFSResult
+VFSListFirst (struct TVFSGlobs *globs, const char *sDir, struct TVFSItem *Item, gboolean FollowSymlinks, gboolean AddFullPath)
{
if (sDir == NULL) {
- printf("(EE) VFSListFirst: sDir is NULL!\n");
+ printf ("(EE) VFSListFirst: sDir is NULL!\n");
return cVFS_Failed;
}
printf ("(--) VFSListFirst: Going to list all items in '%s'\n", sDir);
- return vfs_filelist_list_first(globs->vfs_filelist, sDir, Item);
+ return vfs_filelist_list_first (globs->vfs_filelist, sDir, Item, FollowSymlinks, AddFullPath);
}
-TVFSResult VFSListNext(struct TVFSGlobs *globs, char *sDir, struct TVFSItem *Item)
+TVFSResult
+VFSListNext (struct TVFSGlobs *globs, struct TVFSItem *Item)
{
- return vfs_filelist_list_next(globs->vfs_filelist, sDir, Item);
+ return vfs_filelist_list_next (globs->vfs_filelist, Item);
}
-TVFSResult VFSListClose(struct TVFSGlobs *globs)
+TVFSResult
+VFSListClose (struct TVFSGlobs *globs)
{
- return vfs_filelist_list_close(globs->vfs_filelist);
+ return vfs_filelist_list_close (globs->vfs_filelist);
}
/******************************************************************************************************/
-long VFSFileExists(struct TVFSGlobs *globs, const char *FileName, const long Use_lstat)
-{
- if (! globs) return FALSE;
- return vfs_filelist_file_exists(globs->vfs_filelist, FileName, Use_lstat);
-}
-TVFSResult VFSFileInfo(struct TVFSGlobs *globs, char *AFileName, struct TVFSItem *Item)
+TVFSResult
+VFSFileInfo (struct TVFSGlobs *globs, const char *AFileName, struct TVFSItem *Item, gboolean FollowSymlinks, gboolean AddFullPath)
{
- printf("(--) VFSFileInfo: requested info for object '%s'\n", AFileName);
- if (!globs) return cVFS_Failed;
- return vfs_filelist_file_info(globs->vfs_filelist, AFileName, Item);
+ printf ("(--) VFSFileInfo: requested info for object '%s'\n", AFileName);
+ if (! globs)
+ return cVFS_Failed;
+
+ return vfs_filelist_file_info (globs->vfs_filelist, AFileName, Item, FollowSymlinks, AddFullPath);
}
@@ -538,16 +565,21 @@ TVFSResult VFSFileInfo(struct TVFSGlobs *globs, char *AFileName, struct TVFSItem
/** Recursive tree size counting */
/************** ****************/
-u_int64_t VFSGetDirSize(struct TVFSGlobs *globs, char *APath)
+guint64
+VFSGetDirSize (struct TVFSGlobs *globs, const char *APath)
{
- if (! globs) return 0;
- return vfs_filelist_get_dir_size(globs->vfs_filelist, APath);
+ if (! globs)
+ return 0;
+
+ return vfs_filelist_get_dir_size (globs->vfs_filelist, APath);
}
-void VFSBreakGetDirSize(struct TVFSGlobs *globs)
+void
+VFSBreakGetDirSize (struct TVFSGlobs *globs)
{
- printf("(WW) VFSBreakGetDirSize: calling break\n");
- if (globs) vfs_filelist_get_dir_size_break(globs->vfs_filelist);
+ printf ("(WW) VFSBreakGetDirSize: calling break\n");
+ if (globs)
+ vfs_filelist_get_dir_size_break (globs->vfs_filelist);
}
@@ -555,45 +587,45 @@ void VFSBreakGetDirSize(struct TVFSGlobs *globs)
/** Methods modifying the archive */
/************** ****************/
-TVFSResult VFSMkDir(struct TVFSGlobs *globs, const char *sDirName)
+TVFSResult VFSMkDir (struct TVFSGlobs *globs, const char *sDirName)
{
- printf("(WW) VFSMkDir: Not supported in UNRAR plugin.\n");
+ printf ("(WW) VFSMkDir: Not supported in UNRAR plugin.\n");
return cVFS_Not_Supported;
}
-TVFSResult VFSRemove(struct TVFSGlobs *globs, const char *APath)
+TVFSResult VFSRemove (struct TVFSGlobs *globs, const char *APath)
{
- printf("(WW) VFSRemove: Not supported in UNRAR plugin.\n");
+ printf ("(WW) VFSRemove: Not supported in UNRAR plugin.\n");
return cVFS_Not_Supported;
}
-TVFSResult VFSRename(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName)
+TVFSResult VFSRename (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName)
{
- printf("(WW) VFSRename: Not supported in UNRAR plugin.\n");
+ printf ("(WW) VFSRename: Not supported in UNRAR plugin.\n");
return cVFS_Not_Supported;
}
-TVFSResult VFSMakeSymLink(struct TVFSGlobs *globs, const char *NewFileName, const char *PointTo)
+TVFSResult VFSMakeSymLink (struct TVFSGlobs *globs, const char *NewFileName, const char *PointTo)
{
- printf("(WW) VFSMakeSymLink: Not supported in UNRAR plugin.\n");
+ printf ("(WW) VFSMakeSymLink: Not supported in UNRAR plugin.\n");
return cVFS_Not_Supported;
}
-TVFSResult VFSChmod(struct TVFSGlobs *globs, const char *FileName, const uint Mode)
+TVFSResult VFSChmod (struct TVFSGlobs *globs, const char *FileName, guint32 Mode)
{
- printf("(WW) VFSChmod: Not supported in UNRAR plugin.\n");
+ printf ("(WW) VFSChmod: Not supported in UNRAR plugin.\n");
return cVFS_Not_Supported;
}
-TVFSResult VFSChown(struct TVFSGlobs *globs, const char *FileName, const uint UID, const uint GID)
+TVFSResult VFSChown (struct TVFSGlobs *globs, const char *FileName, guint32 UID, guint32 GID)
{
- printf("(WW) VFSChown: Not supported in UNRAR plugin.\n");
+ printf ("(WW) VFSChown: Not supported in UNRAR plugin.\n");
return cVFS_Not_Supported;
}
-TVFSResult VFSChangeTimes(struct TVFSGlobs *globs, char *APath, long mtime, long atime)
+TVFSResult VFSChangeTimes (struct TVFSGlobs *globs, const char *APath, guint32 mtime, guint32 atime)
{
- printf("(WW) VFSChangeTimes: Not supported in UNRAR plugin.\n");
+ printf ("(WW) VFSChangeTimes: Not supported in UNRAR plugin.\n");
return cVFS_Not_Supported;
}
@@ -631,21 +663,25 @@ int VFSWriteFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, void *Buff
return 0;
}
-void VFSSetBlockSize(struct TVFSGlobs *globs, int Value)
+void
+VFSSetBlockSize (struct TVFSGlobs *globs, guint32 Value)
{
- globs->block_size = Value;
+ if (globs)
+ globs->block_size = Value;
}
-int VFSIsOnSameFS(struct TVFSGlobs *globs, const char *Path1, const char *Path2)
+gboolean
+VFSIsOnSameFS (struct TVFSGlobs *globs, const char *Path1, const char *Path2, gboolean FollowSymlinks)
{
- printf("(WW) VFSIsOnSameFS: Not supported in UNRAR plugin.\n");
+ printf ("(WW) VFSIsOnSameFS: Not supported in UNRAR plugin.\n");
return TRUE;
}
-int VFSTwoSameFiles(struct TVFSGlobs *globs, const char *Path1, const char *Path2)
+gboolean
+VFSTwoSameFiles (struct TVFSGlobs *globs, const char *Path1, const char *Path2, gboolean FollowSymlinks)
{
- printf("(WW) VFSTwoSameFiles: Not supported in RAR archives, comparing by paths.\n");
- return compare_two_same_files(Path1, Path2);
+ printf ("(WW) VFSTwoSameFiles: Not supported in RAR archives, comparing by paths.\n");
+ return compare_two_same_files (Path1, Path2);
}
@@ -653,168 +689,166 @@ int VFSTwoSameFiles(struct TVFSGlobs *globs, const char *Path1, const char *Path
////////////////////////
-TVFSResult VFSCopyToLocal(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, int Append)
+TVFSResult
+VFSCopyToLocal (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, gboolean Append)
{
- if ((sSrcName == NULL) || (sDstName == NULL) || (strlen(sSrcName) < 1) || (strlen(sDstName) < 1)) {
- printf("(EE) VFSCopyToLocal: The value of 'sSrcName' or 'sDstName' is NULL or empty\n");
+ struct PathTree *node;
+ TVFSResult Result;
+ gboolean found;
+ char *src;
+
+ if (sSrcName == NULL || sDstName == NULL || strlen (sSrcName) < 1 || strlen (sDstName) < 1) {
+ printf ("(EE) VFSCopyToLocal: The value of 'sSrcName' or 'sDstName' is NULL or empty\n");
return cVFS_Failed;
}
- printf("(II) VFSCopyToLocal: copying file '%s' out to '%s'\n", sSrcName, sDstName);
+ printf ("(II) VFSCopyToLocal: copying file '%s' out to '%s'\n", sSrcName, sDstName);
- struct PathTree *node = filelist_tree_find_node_by_path(globs->files, sSrcName);
+ node = filelist_tree_find_node_by_path (globs->files, sSrcName);
if (! node) {
- fprintf(stderr, "(EE) VFSCopyToLocal: cannot find file '%s'\n", sSrcName);
+ fprintf (stderr, "(EE) VFSCopyToLocal: cannot find file '%s'\n", sSrcName);
return cVFS_ReadErr;
}
- TVFSResult Result = cVFS_OK;
- gboolean found = FALSE;
+ Result = cVFS_OK;
+ found = FALSE;
- char *src = node->original_pathstr;
+ src = node->original_pathstr;
if (! src) {
- fprintf(stderr, "(WW) VFSCopyToLocal: cannot determine original filename\n");
- src = (char *)sSrcName;
+ fprintf (stderr, "(WW) VFSCopyToLocal: cannot determine original filename\n");
+ src = (char *) sSrcName;
}
- printf("(II) VFSCopyToLocal: new src path: '%s'\n", src);
+ printf ("(II) VFSCopyToLocal: new src path: '%s'\n", src);
HANDLE PASCAL handle;
struct RAROpenArchiveDataEx *archive_data;
- archive_data = (struct RAROpenArchiveDataEx*) malloc(sizeof(struct RAROpenArchiveDataEx));
- memset(archive_data, 0, sizeof(struct RAROpenArchiveDataEx));
+ /* WARNING: do not use g_malloc0() here, leads to memory corruption */
+ archive_data = malloc (sizeof (struct RAROpenArchiveDataEx));
+ memset (archive_data, 0, sizeof (struct RAROpenArchiveDataEx));
archive_data->ArcName = globs->archive_path;
- archive_data->CmtBuf = NULL;
- archive_data->CmtBufSize = 0;
archive_data->OpenMode = RAR_OM_EXTRACT;
- handle = RAROpenArchiveEx(archive_data);
+ handle = RAROpenArchiveEx (archive_data);
// printf(" handle = %lu \n", (unsigned long int)handle);
// printf(" archive_data->OpenResult = %d \n", archive_data->OpenResult);
// printf(" archive_data->CmtState = %d \n", archive_data->CmtState);
// printf(" archive_data->CmtSize = %d \n", archive_data->CmtSize);
// printf("sizeof(TVFSResult) = %ld \n", sizeof(TVFSResult));
- if ((handle) && (! archive_data->OpenResult))
+ if (handle && ! archive_data->OpenResult)
{
- // Set callbacks
-// printf(" setting callback: globs = 0x%lX, (unsigned long int)globs = 0x%lX, (LONG)globs = 0x%lX\n", globs, (unsigned long int)globs, (LONG)globs);
- RARSetCallback(handle, unrar_callback, (LONG)globs);
-// RARSetChangeVolProc(handle, unrar_changevol_proc);
-// RARSetProcessDataProc(handle, unrar_process_data_proc);
-
- if (globs->password) {
- printf("(II) VFSCopyToLocal: Setting password... \n");
- RARSetPassword(handle, globs->password);
- }
-
- struct RARHeaderDataEx *header;
- header = (struct RARHeaderDataEx*) malloc(sizeof(struct RARHeaderDataEx));
- memset(header, 0, sizeof(struct RARHeaderDataEx));
- header->CmtBuf = NULL;
- header->CmtBufSize = 0;
-
- int res = 0;
- while ((res = RARReadHeaderEx(handle, header)) == 0)
- {
- char *ssrc = src;
- char *asrc = header->FileName;
- if (IS_DIR_SEP(*ssrc)) ssrc++;
- if (IS_DIR_SEP(*asrc)) asrc++;
- if (strcmp(ssrc, asrc) == 0) {
-// fprintf(stderr, "(II) VFSCopyToLocal: extract_file_path(sDstName) = '%s', extract_file_name(sDstName) = '%s' \n", extract_file_path(sDstName), extract_file_name(sDstName));
- globs->extract_done = 0;
- globs->extract_file_size = (int64_t)((int64_t)(header->UnpSizeHigh * 0x100000000) + (int64_t)header->UnpSize);
- globs->extract_cancelled = FALSE;
- found = TRUE;
-
- int res2 = RARProcessFile(handle, RAR_EXTRACT, NULL, (char *)sDstName);
-
- if (globs->extract_cancelled) {
- fprintf(stderr, "(WW) VFSCopyToLocal: cancelled !\n");
- Result = cVFS_Cancelled;
- }
- else
- if (res2) {
- fprintf(stderr, "(EE) VFSCopyToLocal: RARProcessFile result = %d\n", res2);
- Result = cVFS_ReadErr;
- }
- break;
- } else {
- int res2 = RARProcessFile(handle, RAR_SKIP, NULL, NULL);
- if (res2) {
- fprintf(stderr, "(EE) VFSCopyToLocal: RARProcessFile result = %d\n", res2);
- Result = cVFS_ReadErr;
- }
- }
- }
-
- if ((res != ERAR_END_ARCHIVE) && (res)) {
- if (globs->extract_cancelled) {
- fprintf(stderr, "(WW) VFSCopyToLocal: cancelled !\n");
- Result = cVFS_Cancelled;
- }
- else {
- fprintf(stderr, "(EE) VFSCopyToLocal: RARReadHeader result = %d\n", res);
- switch (res) {
- case ERAR_NO_MEMORY:
- case ERAR_SMALL_BUF:
- Result = cVFS_mallocFailed;
- break;
- case ERAR_BAD_DATA:
- case ERAR_BAD_ARCHIVE:
- case ERAR_UNKNOWN_FORMAT:
- case ERAR_EOPEN:
- case ERAR_ECLOSE:
- case ERAR_EREAD:
- Result = cVFS_ReadErr;
- break;
- case ERAR_ECREATE:
- case ERAR_EWRITE:
- Result = cVFS_WriteErr;
- break;
- case ERAR_MISSING_PASSWORD:
- Result = cVFS_BadPassword;
- if (globs->password) {
- g_free (globs->password);
- globs->password = NULL;
- }
- break;
- case ERAR_UNKNOWN:
- default:
- Result = cVFS_WriteErr;
- break;
- }
- }
- }
-
- free(header);
-
- res = RARCloseArchive(handle);
- if (res) {
- fprintf(stderr, "(EE) VFSCopyToLocal: RARCloseArchive result = %d\n", res);
- Result = cVFS_ReadErr;
- }
+ // Set callbacks
+// printf(" setting callback: globs = 0x%lX, (unsigned long int)globs = 0x%lX, (LONG)globs = 0x%lX\n", globs, (unsigned long int)globs, (LONG)globs);
+ RARSetCallback (handle, unrar_callback, (LONG)globs);
+// RARSetChangeVolProc(handle, unrar_changevol_proc);
+// RARSetProcessDataProc(handle, unrar_process_data_proc);
+
+ if (globs->password) {
+ printf ("(II) VFSCopyToLocal: Setting password... \n");
+ RARSetPassword (handle, globs->password);
+ }
+
+ struct RARHeaderDataEx *header;
+ /* WARNING: do not use g_malloc0() here, leads to memory corruption */
+ header = malloc (sizeof (struct RARHeaderDataEx));
+ memset (header, 0, sizeof (struct RARHeaderDataEx));
+
+ int res = 0;
+ while ((res = RARReadHeaderEx(handle, header)) == 0) {
+ if (g_strcmp0 (src, header->FileName) == 0) {
+// fprintf(stderr, "(II) VFSCopyToLocal: extract_file_path(sDstName) = '%s', extract_file_name(sDstName) = '%s' \n", extract_file_path(sDstName), extract_file_name(sDstName));
+ globs->extract_done = 0;
+ globs->extract_file_size = (guint64)((guint64)(header->UnpSizeHigh * 0x100000000) + (guint64)header->UnpSize);
+ globs->extract_cancelled = FALSE;
+ found = TRUE;
+
+ int res2 = RARProcessFile (handle, RAR_EXTRACT, NULL, (char *)sDstName);
+
+ if (globs->extract_cancelled) {
+ fprintf (stderr, "(WW) VFSCopyToLocal: cancelled !\n");
+ Result = cVFS_Cancelled;
+ }
+ else
+ if (res2) {
+ fprintf (stderr, "(EE) VFSCopyToLocal: RARProcessFile result = %d\n", res2);
+ Result = cVFS_ReadErr;
+ }
+ break;
+ } else {
+ int res2 = RARProcessFile (handle, RAR_SKIP, NULL, NULL);
+ if (res2) {
+ fprintf (stderr, "(EE) VFSCopyToLocal: RARProcessFile result = %d\n", res2);
+ Result = cVFS_ReadErr;
+ }
+ }
+ }
+
+ if (res != ERAR_END_ARCHIVE && res) {
+ if (globs->extract_cancelled) {
+ fprintf (stderr, "(WW) VFSCopyToLocal: cancelled !\n");
+ Result = cVFS_Cancelled;
+ }
+ else {
+ fprintf (stderr, "(EE) VFSCopyToLocal: RARReadHeader result = %d\n", res);
+ switch (res) {
+ case ERAR_NO_MEMORY:
+ case ERAR_SMALL_BUF:
+ Result = cVFS_mallocFailed;
+ break;
+ case ERAR_BAD_DATA:
+ case ERAR_BAD_ARCHIVE:
+ case ERAR_UNKNOWN_FORMAT:
+ case ERAR_EOPEN:
+ case ERAR_ECLOSE:
+ case ERAR_EREAD:
+ Result = cVFS_ReadErr;
+ break;
+ case ERAR_ECREATE:
+ case ERAR_EWRITE:
+ Result = cVFS_WriteErr;
+ break;
+ case ERAR_MISSING_PASSWORD:
+ Result = cVFS_BadPassword;
+ g_free (globs->password);
+ globs->password = NULL;
+ break;
+ case ERAR_UNKNOWN:
+ default:
+ Result = cVFS_WriteErr;
+ break;
+ }
+ }
+ }
+
+ free (header);
+
+ res = RARCloseArchive (handle);
+ if (res) {
+ fprintf (stderr, "(EE) VFSCopyToLocal: RARCloseArchive result = %d\n", res);
+ Result = cVFS_ReadErr;
+ }
} else {
- fprintf(stderr, "(EE) VFSCopyToLocal: error occured when opening archive: OpenResult = %d\n", archive_data->OpenResult);
- Result = cVFS_ReadErr;
+ fprintf (stderr, "(EE) VFSCopyToLocal: error occured when opening archive: OpenResult = %d\n", archive_data->OpenResult);
+ Result = cVFS_ReadErr;
}
- free(archive_data);
+ free (archive_data);
- if ((! found) && Result == cVFS_OK) {
- fprintf(stderr, "(EE) VFSCopyToLocal: file not found in archive.\n");
+ if (! found && Result == cVFS_OK) {
+ fprintf (stderr, "(EE) VFSCopyToLocal: file not found in archive.\n");
Result = cVFS_ReadErr;
}
- fprintf(stderr, "(II) VFSCopyToLocal: finished. \n");
+ fprintf (stderr, "(II) VFSCopyToLocal: finished. \n");
return Result;
}
-TVFSResult VFSCopyFromLocal(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, int Append)
+TVFSResult
+VFSCopyFromLocal (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, gboolean Append)
{
- printf("(WW) VFSCopyFromLocal: Not supported in UNRAR plugin.\n");
+ printf ("(WW) VFSCopyFromLocal: Not supported in UNRAR plugin.\n");
return cVFS_Not_Supported;
}
@@ -824,7 +858,7 @@ TVFSResult VFSCopyFromLocal(struct TVFSGlobs *globs, const char *sSrcName, const
/**********
* TODO:
*
- * - UTF-8, FName/FDisplayName and absolute/relative paths revision needed!
+ * DONE - UTF-8, FName/FDisplayName and absolute/relative paths revision needed!
* - find a reliable way to catch bad password errors and free the cached invalid password
* - no error reporting when archive is corrupted -- hopefully fixed by ask_question callback
* - archive testing (needs new VFS API)