diff options
Diffstat (limited to 'unrar/unrar.c')
| -rw-r--r-- | unrar/unrar.c | 734 |
1 files changed, 734 insertions, 0 deletions
diff --git a/unrar/unrar.c b/unrar/unrar.c new file mode 100644 index 0000000..6435aeb --- /dev/null +++ b/unrar/unrar.c @@ -0,0 +1,734 @@ +/* UNRAR plugin for Tux Commander + * version 0.2.2, designed for unrar v3.7.1 beta1 + * Copyright (C) 2008 Tomas Bzatek <tbzatek@users.sourceforge.net> + * Check for updates on tuxcmd.sourceforge.net + * + * Uses UNRAR sources + * UnRAR - free utility for RAR archives + * Copyright (C) Alexander L. Roshal + * http://www.rarlab.com/ + * + + + * This program 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 Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <string.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 "vfsutils.h" +#include "strutils.h" +#include "treepathutils.h" +#include "treepath_vfs.h" + +#define _UNIX + +#include "unrar/version.hpp" +#include "unrar/dll.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 +}; + + +#define VERSION "0.2.2" +#define BUILD_DATE "2008-05-11" +#define DEFAULT_BLOCK_SIZE 65536 + + + + + +/******************************************************************************************************/ +/** Auxiliary classes */ +/************** ****************/ + + + +// Declaration of the global plugin object +struct TVFSGlobs { + TVFSLogFunc log_func; + char *curr_dir; + char *archive_path; + + gboolean need_password; + gboolean passwd_callback; + char *password; + + unsigned long block_size; + + struct PathTree *files; + struct VfsFilelistData *vfs_filelist; + + u_int64_t total_size; + + void *extract_callback_data; + TVFSCopyCallBackFunc extract_callback_func; + u_int64_t extract_file_size; + u_int64_t extract_done; + gboolean extract_cancelled; +}; + + + + + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////// +// Basic initialization functions +int VFSAllocNeeded() +{ + return sizeof(struct TVFSGlobs); +} + +void VFSInit(struct TVFSGlobs *globs, TVFSLogFunc log_func) +{ + globs->block_size = DEFAULT_BLOCK_SIZE; + globs->extract_callback_data = NULL; + globs->extract_callback_func = NULL; + globs->need_password = FALSE; + globs->passwd_callback = FALSE; + + globs->log_func = log_func; + if (globs->log_func != NULL) globs->log_func((char*)"unrar plugin: VFSInit"); +} + +void VFSDestroy(struct TVFSGlobs *globs) +{ + if (globs->log_func != NULL) globs->log_func((char*)"unrar plugin: VFSDestroy"); +} + +int VFSVersion() +{ + return 3; +} + +struct TVFSInfo VFSGetInfo() +{ + struct TVFSInfo module_info; + module_info.Name = "UNRAR plugin"; + module_info.Description = "RAR archiving plugin"; + char *s = (char*)malloc(255); + snprintf(s, 255, "version %s, build date: %s\nusing unrar sources v%d.%d [%d-%.2d-%.2d]\n", + VERSION, BUILD_DATE, RARVER_MAJOR, RARVER_MINOR, RARVER_YEAR, RARVER_MONTH, RARVER_DAY); + module_info.About = strdup(s); + free(s); + s = (char*)malloc(255); + snprintf(s, 255, "Plugin Copyright (C) 2008 Tomáš Bžatek\nUNRAR sources Copyright (C) 2002-2007 Alexander Roshal"); + module_info.Copyright = strdup(s); + return module_info; +} + +char *VFSGetPrefix(struct TVFSGlobs *globs) +{ + return globs->archive_path; +// return (char*)"unrar"; +} + +char *VFSGetExts() +{ + return (char*)"rar;r00;r01;r02;r03;r04;r05;r06;r07;r08;r09;r10;r11;r12;r13;r14;r15;r16;r17;r18;r19;r20;r21;r22;r23;r24;r25;r26;r27;r28;r29;r30;r31;r32;r33;r34;r35;r36;r37;r38;r39;r40;r41;r42;r43;r44;r45;r46;r47;r48;r49;r50;r51;r52;r53;r54;r55;r56;r57;r58;r59;r60;r61;r62;r63;r64;r65;r66;r67;r68;r69;r70;r71;r72;r73;r74;r75;r76;r77;r78;r79;r80;r81;r82;r83;r84;r85;r86;r87;r88;r89;r90;r91;r92;r93;r94;r95;r96;r97;r98;r99"; +} + + +/**************************************************************************************************************************************/ +/**************************************************************************************************************************************/ + +int unrar_callback(UINT msg, LONG UserData, LONG P1, LONG P2) +{ +// fprintf(stderr, "(II) unrar_callback called: msg = %d, UserData = %lx, sizeof(UserData) = %ld, P1 = %ld, P2 = %ld\n", msg, UserData, sizeof(UserData), P1, P2); + + // >= 0 => Weiter, -1 => Stop + 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 (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); + } + break; + } + + case UCM_PROCESSDATA: { + fprintf(stderr, " (II) unrar_callback: UCM_PROCESSDATA message, P1 = %ld, P2 = %ld \n", P1, P2); + struct TVFSGlobs *globs = (struct TVFSGlobs *)UserData; +// printf(" (II) unrar_callback: globs = 0x%lX, UserData = 0x%lX \n", (unsigned long int)globs, UserData); + if ((globs) && (globs->extract_callback_func != NULL)) { +// 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->extract_callback_func(globs->extract_done, globs->extract_file_size, globs->extract_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); + struct TVFSGlobs *globs = (struct TVFSGlobs *)UserData; + if (globs) globs->passwd_callback = TRUE; + break; + } + } + + return 0; +} + +int PASCAL unrar_changevol_proc(char *ArcName, int 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) +{ + 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) +{ + struct tm t; + t.tm_sec = (FileTime & 0x1f) * 2; + t.tm_min = (FileTime >> 5) & 0x3f; + t.tm_hour = (FileTime >> 11) & 0x1f; + t.tm_mday = (FileTime >> 16) & 0x1f; + t.tm_mon = ((FileTime >> 21) & 0x0f)-1; + 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)); +} + + +TVFSResult VFSOpen(struct TVFSGlobs *globs, char *sName) +{ + TVFSResult 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->total_size = 0; + globs->passwd_callback = FALSE; + fprintf(stderr, "(--) VFSOpen: trying to open archive '%s'...\n", globs->archive_path); + + HANDLE PASCAL handle; + struct RAROpenArchiveDataEx *archive_data; + + archive_data = (struct RAROpenArchiveDataEx*) 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); +// 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) VFSOpen: 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 = (u_int64_t)((u_int64_t)(header->UnpSizeHigh * 0x100000000) + (u_int64_t)header->UnpSize); + 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; + + // Add item to the global list and continue with next file + filelist_tree_add_item(globs->files, header->FileName, item, 0); + 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) { + fprintf(stderr, "(EE) VFSOpen: RARReadHeader result = %d\n", res); + Result = cVFS_Failed; + if ((res == ERAR_MISSING_PASSWORD) || ((res == ERAR_BAD_DATA) && (globs->passwd_callback))) + Result = cVFS_BadPassword; + } + free(header); + + res = RARCloseArchive(handle); + if (res) { + fprintf(stderr, "(EE) VFSOpen: RARCloseArchive result = %d\n", res); + } + } else { + fprintf(stderr, "(EE) VFSOpen: error occured when opening archive: OpenResult = %d\n", archive_data->OpenResult); + Result = cVFS_Failed; + } + + free(archive_data); + fprintf(stderr, "(II) VFSOpen: 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) +{ + 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); + } + return cVFS_OK; +} + +char *VFSGetPath(struct TVFSGlobs *globs) +{ + return include_trailing_path_sep(globs->curr_dir); +} + +u_int64_t VFSGetFileSystemFree(struct TVFSGlobs *globs, char *APath) +{ + return 0; +} + +u_int64_t VFSGetFileSystemSize(struct TVFSGlobs *globs, char *APath) +{ + return globs->total_size; +} + + + + +/******************************************************************************************************/ + +TVFSResult VFSChangeDir(struct TVFSGlobs *globs, char *NewPath) +{ + if (NewPath == NULL) { + 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; +} + + +int VFSLogin(struct TVFSGlobs *globs, char *user, char *pass) +{ + return cVFS_Not_Supported; +} + +int VFSSetPassword(struct TVFSGlobs *globs, char *pass) +{ + printf ("(II) VFSSetPassword: Going to set the password...\n"); + if (globs->password) free(globs->password); + globs->password = strdup(pass); + return cVFS_OK; +} + +int VFSGetPasswordRequired(struct TVFSGlobs *globs) +{ + if (globs) return globs->need_password; + return FALSE; +} + + +/******************************************************************************************************/ + +TVFSResult VFSListFirst(struct TVFSGlobs *globs, char *sDir, struct TVFSItem *Item) +{ + if (sDir == NULL) { + 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); +} + +TVFSResult VFSListNext(struct TVFSGlobs *globs, char *sDir, struct TVFSItem *Item) +{ + return vfs_filelist_list_next(globs->vfs_filelist, sDir, Item); +} + +TVFSResult VFSListClose(struct TVFSGlobs *globs) +{ + 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) +{ + printf("(--) VFSFileInfo: requested info for object '%s'\n", AFileName); + if (!globs) return cVFS_Failed; + return vfs_filelist_file_info(globs->vfs_filelist, AFileName, Item); +} + + +/******************************************************************************************************/ +/** Recursive tree size counting */ +/************** ****************/ + +u_int64_t VFSGetDirSize(struct TVFSGlobs *globs, char *APath) +{ + if (! globs) return 0; + return vfs_filelist_get_dir_size(globs->vfs_filelist, APath); +} + +void VFSBreakGetDirSize(struct TVFSGlobs *globs) +{ + printf("(WW) VFSBreakGetDirSize: calling break\n"); + if (globs) vfs_filelist_get_dir_size_break(globs->vfs_filelist); +} + + +/******************************************************************************************************/ +/** Methods modifying the archive */ +/************** ****************/ + +TVFSResult VFSMkDir(struct TVFSGlobs *globs, const char *sDirName) +{ + printf("(WW) VFSMkDir: Not supported in UNRAR plugin.\n"); + return cVFS_Not_Supported; +} + +TVFSResult VFSRemove(struct TVFSGlobs *globs, const char *APath) +{ + printf("(WW) VFSRemove: Not supported in UNRAR plugin.\n"); + return cVFS_Not_Supported; +} + +TVFSResult VFSRename(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName) +{ + printf("(WW) VFSRename: Not supported in UNRAR plugin.\n"); + return cVFS_Not_Supported; +} + +TVFSResult VFSMakeSymLink(struct TVFSGlobs *globs, const char *NewFileName, const char *PointTo) +{ + printf("(WW) VFSMakeSymLink: Not supported in UNRAR plugin.\n"); + return cVFS_Not_Supported; +} + +TVFSResult VFSChmod(struct TVFSGlobs *globs, const char *FileName, const uint Mode) +{ + 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) +{ + printf("(WW) VFSChown: Not supported in UNRAR plugin.\n"); + return cVFS_Not_Supported; +} + +TVFSResult VFSChangeTimes(struct TVFSGlobs *globs, char *APath, long mtime, long atime) +{ + printf("(WW) VFSChangeTimes: Not supported in UNRAR plugin.\n"); + return cVFS_Not_Supported; +} + + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////// + +TVFSFileDes VFSOpenFile(struct TVFSGlobs *globs, const char *APath, int Mode, int *Error) +{ + *Error = cVFS_Not_Supported; + return (TVFSFileDes)0; +} + +TVFSResult VFSCloseFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor) +{ + return cVFS_Not_Supported; +} + +u_int64_t VFSFileSeek(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, u_int64_t AbsoluteOffset, int *Error) +{ + *Error = cVFS_Not_Supported; + return 0; +} + +int VFSReadFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, void *Buffer, int ABlockSize, int *Error) +{ + *Error = cVFS_Not_Supported; + return 0; +} + +int VFSWriteFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, void *Buffer, int BytesCount, int *Error) +{ + *Error = cVFS_Not_Supported; + return 0; +} + +void VFSSetBlockSize(struct TVFSGlobs *globs, int Value) +{ + globs->block_size = Value; +} + +int VFSIsOnSameFS(struct TVFSGlobs *globs, const char *Path1, const char *Path2) +{ + printf("(WW) VFSIsOnSameFS: Not supported in UNRAR plugin.\n"); + return TRUE; +} + +int VFSTwoSameFiles(struct TVFSGlobs *globs, const char *Path1, const char *Path2) +{ + printf("(WW) VFSTwoSameFiles: Not supported in ZIP archives, comparing by paths.\n"); + return compare_two_same_files(Path1, Path2); +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////// + + +TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append) +{ + if ((sSrcName == NULL) || (sDstName == NULL) || (strlen(sSrcName) < 1) || (strlen(sDstName) < 1)) { + printf("(EE) VFSCopyOut: The value of 'sSrcName' or 'sDstName' is NULL or empty\n"); + return cVFS_Failed; + } + + printf("(II) VFSCopyOut: copying file '%s' out to '%s'\n", sSrcName, sDstName); + + TVFSResult Result = cVFS_OK; + + char *src; + if (! IS_DIR_SEP(*sSrcName)) src = g_build_path("/", globs->curr_dir, sSrcName, NULL); + else src = g_strdup(sSrcName); + + printf("(II) VFSCopyOut: new src path: '%s'\n", src); + +// printf("(II) VFSCopyOut: pCallBackProgress = 0x%lX, data = 0x%lX\n", (unsigned long int)pCallBackProgress, (unsigned long int)data); + globs->extract_callback_data = data; + globs->extract_callback_func = pCallBackProgress; + + HANDLE PASCAL handle; + struct RAROpenArchiveDataEx *archive_data; + + archive_data = (struct RAROpenArchiveDataEx*) 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); +// 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)) + { + // 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) VFSCopyOut: 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) VFSCopyOut: 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 = (u_int64_t)((u_int64_t)(header->UnpSizeHigh * 0x100000000) + (u_int64_t)header->UnpSize); + globs->extract_cancelled = FALSE; + + int res2 = RARProcessFile(handle, RAR_EXTRACT, NULL, (char *)sDstName); + + if (globs->extract_cancelled) Result = cVFS_Cancelled; + else + if (res2) { + fprintf(stderr, "(EE) VFSCopyOut: RARProcessFile result = %d\n", res2); + Result = cVFS_ReadErr; + } + break; + } else { + int res2 = RARProcessFile(handle, RAR_SKIP, NULL, NULL); + if (res2) { + fprintf(stderr, "(EE) VFSCopyOut: RARProcessFile result = %d\n", res2); + Result = cVFS_ReadErr; + } + } + } + + if ((res != ERAR_END_ARCHIVE) && (res)) { + fprintf(stderr, "(EE) VFSCopyOut: 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; + break; + case ERAR_UNKNOWN: + default: + Result = cVFS_WriteErr; + break; + } + } + + free(header); + + res = RARCloseArchive(handle); + if (res) { + fprintf(stderr, "(EE) VFSCopyOut: RARCloseArchive result = %d\n", res); + Result = cVFS_ReadErr; + } + } else { + fprintf(stderr, "(EE) VFSCopyOut: error occured when opening archive: OpenResult = %d\n", archive_data->OpenResult); + Result = cVFS_ReadErr; + } + + free(archive_data); + g_free(src); + + fprintf(stderr, "(II) VFSCopyOut: finished. \n"); + return Result; +} + +TVFSResult VFSCopyIn(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append) +{ + printf("(WW) VFSCopyIn: Not supported in UNRAR plugin.\n"); + return cVFS_Not_Supported; +} + + + + +/********** + * TODO: + * - no error reporting when archive is corrupted + * - archive testing (needs new VFS API) + * + ***/ |
