Merge pull request #176 from Mayoshiroi/rar

Add RAR archive support
This commit is contained in:
TheOfficialFloW 2017-01-04 17:34:49 +01:00 committed by GitHub
commit f72896cc49
21 changed files with 882 additions and 22 deletions

View File

@ -17,7 +17,7 @@ set(VITA_TITLEID "VITASHELL")
set(VITA_VERSION "01.43")
# Flags and includes
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -Wno-unused-variable -Wno-unused-but-set-variable -fno-lto")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -Wno-unused-variable -Wno-unused-but-set-variable ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions")
set(VITA_MKSFOEX_FLAGS "${VITA_MKSFOEX_FLAGS} -d PARENTAL_LEVEL=1")
set(VITA_MAKE_FSELF_FLAGS "${VITA_MAKE_FSELF_FLAGS} -a 0x2800000000000001")
@ -100,6 +100,8 @@ add_executable(VitaShell
libmad/stream.c
libmad/synth.c
libmad/timer.c
unrarlib/unrarlibutils.c
archiveRAR.c
)
target_link_libraries(VitaShell
@ -137,6 +139,8 @@ target_link_libraries(VitaShell
ScePower_stub
ScePromoterUtil_stub
SceTouch_stub
unrar
stdc++
)
# Create Vita artifacts

View File

@ -84,6 +84,7 @@ Be sure you pull request your customized design or language file there.
* ftpvitalib https://github.com/xerpi/ftpvitalib
* EasyRPG libraries: https://ci.easyrpg.org/view/Toolchains/job/toolchain-vita/
* Onigmo library https://github.com/k-takata/Onigmo
* UnRAR http://www.rarlab.com/
### Credits ###
* Team Molecule for HENkaku

219
archiveRAR.c Normal file
View File

@ -0,0 +1,219 @@
#include "archiveRAR.h"
#include "main.h"
static ArchiveFileNode* root = NULL;
static int32_t filePathLength = -1;
int archiveRAROpen(char *file) {
root = openRARFile(file);
if(!root) {
return -1;
}
filePathLength = strlen(file);
return 1;
}
int fileListGetRARArchiveEntries(FileList *list, char *path, int sort) {
if(!root)
return -1;
FileListEntry *entry = malloc(sizeof(FileListEntry));
strcpy(entry->name, DIR_UP);
entry->name_length = strlen(DIR_UP);
entry->is_folder = 1;
entry->type = FILE_TYPE_UNKNOWN;
fileListAddEntry(list, entry, sort);
ArchiveFileNode* node = NULL;
if(strlen(path) == (filePathLength + sizeof(char)))
node = root;
else
node = getFloderNodeFromPath(root,path + filePathLength + sizeof(char));
uint32_t i = 0;
for(; i < node->childCount; i++) {
ArchiveFileNode* _t = (ArchiveFileNode*)(node->childPt[i]);
FileListEntry * childentry = malloc(sizeof(FileListEntry));
strcpy(childentry->name,_t->nodeName);
childentry->name_length = strlen(childentry->name);
childentry->size = _t->data.UnpSize;
childentry->size2 = _t->data.PackSize;
sceRtcSetDosTime(&childentry->atime,_t->data.FileTime);
sceRtcSetDosTime(&childentry->ctime,_t->data.FileTime);
sceRtcSetDosTime(&childentry->mtime,_t->data.FileTime);
if(_t->data.Flags == 0x20) {
addEndSlash(childentry->name);
childentry->is_folder = 1;
list->folders++;
} else {
childentry->type = getFileType(childentry->name);
childentry->is_folder = 0;
list->files++;
}
fileListAddEntry(list, childentry, sort);
}
return 1;
}
int ReadArchiveRARFile(char *file, void *buf, int size) {
if(filePathLength < 0)
return -1;
char filepath[filePathLength + sizeof(char)];
strncpy(filepath,file,filePathLength);
filepath[filePathLength] = '\0';
struct ExtractHeader header = {memPtr:buf,offset:0,bufferSize:size,file:0,param:NULL};
if(extractRAR(filepath,file + (filePathLength + sizeof(char)),&header) > 0)
return header.offset;
else
return -1;
}
int archiveRARFileGetstat(const char *file, SceIoStat *stat) {
if(!root)
return -1;
const char* p = file + (filePathLength + sizeof(char));
uint32_t p_length = strlen(p);
if(p[p_length - 1] == '/')
return -1;
ArchiveFileNode* filenode = getFileNodeFromFilePath(root,p);
if(!filenode)
return -1;
if(stat) {
stat->st_size = filenode->data.UnpSize;
sceRtcSetDosTime(&stat->st_atime,filenode->data.FileTime);
sceRtcSetDosTime(&stat->st_ctime,filenode->data.FileTime);
sceRtcSetDosTime(&stat->st_mtime,filenode->data.FileTime);
}
return 1;
}
int getRARArchivePathInfo(char *path, uint64_t *size, uint32_t *folders, uint32_t *files) {
if(!root)
return -1;
SceIoStat stat;
memset(&stat, 0, sizeof(SceIoStat));
if (archiveRARFileGetstat(path, &stat) < 0) {
FileList list;
memset(&list, 0, sizeof(FileList));
fileListGetRARArchiveEntries(&list, path, SORT_NONE);
FileListEntry *entry = list.head->next; // Ignore ..
int i;
for (i = 0; i < list.length - 1; i++) {
char *new_path = malloc(strlen(path) + strlen(entry->name) + 2);
snprintf(new_path, MAX_PATH_LENGTH, "%s%s", path, entry->name);
getRARArchivePathInfo(new_path, size, folders, files);
free(new_path);
entry = entry->next;
}
if (folders)
(*folders)++;
fileListEmpty(&list);
} else {
if (size)
(*size) += stat.st_size;
if (files)
(*files)++;
}
return 0;
}
int extractRARArchivePath(char *src, char *dst, FileProcessParam *param) {
if(!root)
return -1;
SceIoStat stat;
memset(&stat, 0, sizeof(SceIoStat));
if (archiveRARFileGetstat(src, &stat) < 0) {
FileList list;
memset(&list, 0, sizeof(FileList));
fileListGetRARArchiveEntries(&list, src, SORT_NONE);
int ret = sceIoMkdir(dst, 0777);
if (ret < 0 && ret != SCE_ERROR_ERRNO_EEXIST) {
fileListEmpty(&list);
return ret;
}
if (param) {
if (param->value)
(*param->value) += DIRECTORY_SIZE;
if (param->SetProgress)
param->SetProgress(param->value ? *param->value : 0, param->max);
if (param->cancelHandler && param->cancelHandler()) {
fileListEmpty(&list);
return 0;
}
}
FileListEntry *entry = list.head->next; // Ignore ..
int i;
for (i = 0; i < list.length - 1; i++) {
char *src_path = malloc(strlen(src) + strlen(entry->name) + 2);
snprintf(src_path, MAX_PATH_LENGTH, "%s%s", src, entry->name);
char *dst_path = malloc(strlen(dst) + strlen(entry->name) + 2);
snprintf(dst_path, MAX_PATH_LENGTH, "%s%s", dst, entry->name);
int ret = extractRARArchivePath(src_path, dst_path, param);
free(dst_path);
free(src_path);
if (ret <= 0) {
fileListEmpty(&list);
return ret;
}
entry = entry->next;
}
fileListEmpty(&list);
} else {
char filepath[filePathLength + sizeof(char)];
strncpy(filepath,src,filePathLength);
filepath[filePathLength] = '\0';
SceUID fddst = sceIoOpen(dst, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777);
struct ExtractHeader header = {file:fddst,offset:0,memPtr:NULL,bufferSize:0,param:param};
int result = extractRAR(filepath,src + (filePathLength + sizeof(char)),&header);
sceIoClose(fddst);
return result;
}
return 1;
}
int archiveRARClose() {
filePathLength = -1;
if (!root) {
closeRARFile(root);
root = NULL;
}
return 1;
}

28
archiveRAR.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef ARCHIVERAR_H_INC
#define ARCHIVERAR_H_INC
#include <psp2/types.h>
#include <psp2/io/stat.h>
#include <psp2/rtc.h>
#include "file.h"
#include "unrarlib/unrarlibutils.h"
#include "utils.h"
int fileListGetRARArchiveEntries(FileList *list, char *path, int sort);
int getRARArchivePathInfo(char *path, uint64_t *size, uint32_t *folders, uint32_t *files);
int extractRARArchivePath(char *src, char *dst, FileProcessParam *param);
int archiveRARFileGetstat(const char *file, SceIoStat *stat);
int archiveRARFileOpen(const char *file, int flags, SceMode mode);
int archiveRARFileRead(SceUID fd, void *data, SceSize size);
int archiveRARFileClose(SceUID fd);
int ReadArchiveRARFile(char *file, void *buf, int size);
int archiveRARClose();
int archiveRAROpen(char *file);
#endif // ARCHIVERAR_H_INC

7
file.c
View File

@ -611,6 +611,7 @@ static ExtensionType extension_types[] = {
{ ".VPK", FILE_TYPE_VPK },
{ ".XML", FILE_TYPE_XML },
{ ".ZIP", FILE_TYPE_ZIP },
{ ".RAR", FILE_TYPE_RAR },
};
int getFileType(char *file) {
@ -976,7 +977,11 @@ int fileListGetDirectoryEntries(FileList *list, char *path, int sort) {
int fileListGetEntries(FileList *list, char *path, int sort) {
if (isInArchive()) {
return fileListGetArchiveEntries(list, path, sort);
enum FileTypes type = getArchiveType();
if(type == FILE_TYPE_ZIP)
return fileListGetArchiveEntries(list, path, sort);
else if(type == FILE_TYPE_RAR)
return fileListGetRARArchiveEntries(list,path,sort);
}
if (strcasecmp(path, HOME_PATH) == 0) {

1
file.h
View File

@ -45,6 +45,7 @@ enum FileTypes {
FILE_TYPE_VPK,
FILE_TYPE_XML,
FILE_TYPE_ZIP,
FILE_TYPE_RAR,
};
enum FileSortFlags {

13
hex.c
View File

@ -81,7 +81,18 @@ int hexViewer(char *file) {
int size = 0;
if (isInArchive()) {
size = ReadArchiveFile(file, buffer, BIG_BUFFER_SIZE);
enum FileTypes archiveType = getArchiveType();
switch(archiveType){
case FILE_TYPE_ZIP:
size = ReadArchiveFile(file, buffer, BIG_BUFFER_SIZE);
break;
case FILE_TYPE_RAR:
size = ReadArchiveRARFile(file,buffer,BIG_BUFFER_SIZE);
break;
default:
size = -1;
break;
}
} else {
size = ReadFile(file, buffer, BIG_BUFFER_SIZE);
}

View File

@ -19,6 +19,7 @@
#include "main.h"
#include "io_process.h"
#include "archive.h"
#include "archiveRAR.h"
#include "file.h"
#include "message_dialog.h"
#include "language.h"
@ -222,7 +223,17 @@ int copy_thread(SceSize args_size, CopyArguments *args) {
} else { // Copy
// Open archive, because when you copy from an archive, you leave the archive to paste
if (args->copy_mode == COPY_MODE_EXTRACT) {
int res = archiveOpen(args->archive_path);
int res = -1;
switch(args->file_type){
case FILE_TYPE_ZIP:
res = archiveOpen(args->archive_path);
break;
case FILE_TYPE_RAR:
res = archiveRAROpen(args->archive_path);
break;
default:
res = -1;
}
if (res < 0) {
closeWaitDialog();
errorDialog(res);
@ -241,7 +252,16 @@ int copy_thread(SceSize args_size, CopyArguments *args) {
snprintf(src_path, MAX_PATH_LENGTH, "%s%s", args->copy_list->path, copy_entry->name);
if (args->copy_mode == COPY_MODE_EXTRACT) {
getArchivePathInfo(src_path, &size, &folders, &files);
switch(args->file_type){
case FILE_TYPE_ZIP:
getArchivePathInfo(src_path, &size, &folders, &files);
break;
case FILE_TYPE_RAR:
getRARArchivePathInfo(src_path,&size,&folders,&files);
break;
default:
break;
}
} else {
getPathInfo(src_path, &size, &folders, &files, NULL);
}
@ -272,7 +292,17 @@ int copy_thread(SceSize args_size, CopyArguments *args) {
param.cancelHandler = cancelHandler;
if (args->copy_mode == COPY_MODE_EXTRACT) {
int res = extractArchivePath(src_path, dst_path, &param);
int res = -1;
switch(args->file_type){
case FILE_TYPE_ZIP:
res = extractArchivePath(src_path, dst_path, &param);
break;
case FILE_TYPE_RAR:
res = extractRARArchivePath(src_path,dst_path,&param);
break;
default:
break;
}
if (res <= 0) {
closeWaitDialog();
dialog_step = DIALOG_STEP_CANCELLED;
@ -294,7 +324,17 @@ int copy_thread(SceSize args_size, CopyArguments *args) {
// Close archive
if (args->copy_mode == COPY_MODE_EXTRACT) {
int res = archiveClose();
int res = -1;
switch(args->file_type){
case FILE_TYPE_ZIP:
res = archiveClose();
break;
case FILE_TYPE_RAR:
res = archiveRARClose();
break;
default:
break;
}
if (res < 0) {
closeWaitDialog();
errorDialog(res);

View File

@ -43,6 +43,7 @@ typedef struct {
FileList *copy_list;
char *archive_path;
int copy_mode;
int file_type;
} CopyArguments;
typedef struct {

View File

@ -139,6 +139,7 @@ void loadLanguage(int id) {
LANGUAGE_ENTRY(PROPERTY_TYPE_VPK),
LANGUAGE_ENTRY(PROPERTY_TYPE_XML),
LANGUAGE_ENTRY(PROPERTY_TYPE_ZIP),
LANGUAGE_ENTRY(PROPERTY_TYPE_RAR),
LANGUAGE_ENTRY(PROPERTY_TYPE_FSELF),
LANGUAGE_ENTRY(PROPERTY_FSELF_MODE_SAFE),
LANGUAGE_ENTRY(PROPERTY_FSELF_MODE_UNSAFE),

View File

@ -98,6 +98,7 @@ enum LanguageContainer {
PROPERTY_TYPE_VPK,
PROPERTY_TYPE_XML,
PROPERTY_TYPE_ZIP,
PROPERTY_TYPE_RAR,
PROPERTY_TYPE_FSELF,
PROPERTY_FSELF_MODE_SAFE,
PROPERTY_FSELF_MODE_UNSAFE,

29
main.c
View File

@ -38,6 +38,7 @@
#include "utils.h"
#include "sfo.h"
#include "list_dialog.h"
#include "archiveRAR.h"
#include "audio/vita_audio.h"
@ -66,10 +67,13 @@ static int dir_level = 0;
// Copy mode
static int copy_mode = COPY_MODE_NORMAL;
static int file_type = FILE_TYPE_UNKNOWN;
static char archive_copy_path[MAX_PATH_LENGTH];
// Archive
int is_in_archive = 0;
int dir_level_archive = -1;
enum FileTypes archive_type = FILE_TYPE_ZIP;
// FTP
static char vita_ip[16];
@ -102,6 +106,10 @@ void dirLevelUp() {
rel_pos = 0;
}
enum FileTypes getArchiveType(){
return archive_type;
}
int isInArchive() {
return is_in_archive;
}
@ -109,8 +117,12 @@ int isInArchive() {
void dirUpCloseArchive() {
if (isInArchive() && dir_level_archive >= dir_level) {
is_in_archive = 0;
enum FileTypes archiveType = getArchiveType();
if(archiveType == FILE_TYPE_RAR)
archiveRARClose();
else if(archiveType == FILE_TYPE_ZIP)
archiveClose();
dir_level_archive = -1;
dir_level_archive = -1;
}
}
@ -273,6 +285,7 @@ int handleFile(char *file, FileListEntry *entry) {
case FILE_TYPE_OGG:
case FILE_TYPE_VPK:
case FILE_TYPE_ZIP:
case FILE_TYPE_RAR:
if (isInArchive())
type = FILE_TYPE_UNKNOWN;
@ -306,7 +319,9 @@ int handleFile(char *file, FileListEntry *entry) {
case FILE_TYPE_ZIP:
res = archiveOpen(file);
break;
case FILE_TYPE_RAR:
res = archiveRAROpen(file);
break;
case FILE_TYPE_SFO:
res = SFOReader(file);
break;
@ -723,6 +738,9 @@ int contextMenuEnterCallback(int pos, void* context) {
} else {
copy_mode = isInArchive() ? COPY_MODE_EXTRACT : COPY_MODE_NORMAL;
}
file_type = getArchiveType();
strcpy(archive_copy_path,archive_path);
// Empty copy list at first
fileListEmpty(&copy_list);
@ -1136,8 +1154,9 @@ int dialogSteps() {
CopyArguments args;
args.file_list = &file_list;
args.copy_list = &copy_list;
args.archive_path = archive_path;
args.archive_path = archive_copy_path;
args.copy_mode = copy_mode;
args.file_type = file_type;
dialog_step = DIALOG_STEP_COPYING;
@ -1585,8 +1604,9 @@ int fileBrowserMenuCtrl() {
int type = handleFile(cur_file, file_entry);
// Archive mode
if (type == FILE_TYPE_ZIP) {
if ((type == FILE_TYPE_ZIP) | (type == FILE_TYPE_RAR)) {
is_in_archive = 1;
archive_type = type;
dir_level_archive = dir_level;
snprintf(archive_path, MAX_PATH_LENGTH, "%s%s", file_list.path, file_entry->name);
@ -1751,6 +1771,7 @@ int shellMain() {
case FILE_TYPE_VPK:
case FILE_TYPE_ZIP:
case FILE_TYPE_RAR:
color = ARCHIVE_COLOR;
icon = archive_icon;
break;

1
main.h
View File

@ -228,6 +228,7 @@ void drawScrollBar(int pos, int n);
void drawShellInfo(char *path);
int isInArchive();
enum FileTypes getArchiveType();
void ftpvita_PROM(ftpvita_client_info_t *client);
void install_unassisted_sync(char *path);

21
photo.c
View File

@ -29,11 +29,22 @@ vita2d_texture *loadImage(char *file, int type, char *buffer) {
if (isInArchive()) {
int size = 0;
if (isInArchive()) {
size = ReadArchiveFile(file, buffer, BIG_BUFFER_SIZE);
} else {
size = ReadFile(file, buffer, BIG_BUFFER_SIZE);
}
if (isInArchive()) {
enum FileTypes archiveType = getArchiveType();
switch(archiveType){
case FILE_TYPE_ZIP:
size = ReadArchiveFile(file, buffer, BIG_BUFFER_SIZE);
break;
case FILE_TYPE_RAR:
size = ReadArchiveRARFile(file,buffer,BIG_BUFFER_SIZE);
break;
default:
size = -1;
break;
}
} else {
size = ReadFile(file, buffer, BIG_BUFFER_SIZE);
}
if (size <= 0) {
return NULL;

View File

@ -18,6 +18,7 @@
#include "main.h"
#include "archive.h"
#include "archiveRAR.h"
#include "init.h"
#include "theme.h"
#include "language.h"
@ -185,7 +186,18 @@ int initPropertyDialog(char *path, FileListEntry *entry) {
uint32_t buffer[0x88/4];
if (isInArchive()) {
size = ReadArchiveFile(path, buffer, sizeof(buffer));
enum FileTypes archiveType = getArchiveType();
switch(archiveType){
case FILE_TYPE_ZIP:
size = ReadArchiveFile(path, buffer, sizeof(buffer));
break;
case FILE_TYPE_RAR:
size = ReadArchiveRARFile(path,buffer,sizeof(buffer));
break;
default:
size = -1;
break;
}
} else {
size = ReadFile(path, buffer, sizeof(buffer));
}
@ -256,6 +268,10 @@ int initPropertyDialog(char *path, FileListEntry *entry) {
case FILE_TYPE_ZIP:
type = PROPERTY_TYPE_ZIP;
break;
case FILE_TYPE_RAR:
type = PROPERTY_TYPE_RAR;
break;
}
width = copyStringLimited(property_type, language_container[type], PROPERTY_DIALOG_ENTRY_MAX_WIDTH);

View File

@ -78,6 +78,7 @@ PROPERTY_TYPE_TXT = "Text document"
PROPERTY_TYPE_VPK = "VPK package"
PROPERTY_TYPE_XML = "XML file"
PROPERTY_TYPE_ZIP = "ZIP archive"
PROPERTY_TYPE_RAR = "RAR archive"
PROPERTY_TYPE_FSELF = "FSELF file"
PROPERTY_FSELF_MODE_SAFE = "Safe"
PROPERTY_FSELF_MODE_UNSAFE = "Unsafe"

20
sfo.c
View File

@ -17,7 +17,8 @@
*/
#include "main.h"
#include "archive.h"
#include "archive.h"
#include "archiveRAR.h"
#include "file.h"
#include "text.h"
#include "hex.h"
@ -108,9 +109,20 @@ int SFOReader(char *file) {
int size = 0;
if (isInArchive()) {
size = ReadArchiveFile(file, buffer, BIG_BUFFER_SIZE);
} else {
if (isInArchive()) {
enum FileTypes archiveType = getArchiveType();
switch(archiveType){
case FILE_TYPE_ZIP:
size = ReadArchiveFile(file, buffer, BIG_BUFFER_SIZE);
break;
case FILE_TYPE_RAR:
size = ReadArchiveRARFile(file,buffer,BIG_BUFFER_SIZE);
break;
default:
size = -1;
break;
}
}else {
size = ReadFile(file, buffer, BIG_BUFFER_SIZE);
}

14
text.c
View File

@ -19,6 +19,7 @@
#include "main.h"
#include "context_menu.h"
#include "archive.h"
#include "archiveRAR.h"
#include "file.h"
#include "text.h"
#include "hex.h"
@ -531,7 +532,18 @@ int textViewer(char *file) {
s->edit_line = -1;
if (isInArchive()) {
s->size = ReadArchiveFile(file, buffer_base, BIG_BUFFER_SIZE);
enum FileTypes archiveType = getArchiveType();
switch(archiveType){
case FILE_TYPE_ZIP:
s->size = ReadArchiveFile(file, buffer_base, BIG_BUFFER_SIZE);
break;
case FILE_TYPE_RAR:
s->size = ReadArchiveRARFile(file,buffer_base,BIG_BUFFER_SIZE);
break;
default:
s->size = -1;
break;
}
s->modify_allowed = 0;
} else {
s->size = ReadFile(file, buffer_base, BIG_BUFFER_SIZE);

155
unrarlib/unrar_c_wrapper.h Normal file
View File

@ -0,0 +1,155 @@
#include <stdbool.h>
#ifndef _UNRAR_C_WRAPPER_H_INC
#define _UNRAR_C_WRAPPER_H_INC
#define ERAR_SUCCESS 0
#define ERAR_END_ARCHIVE 10
#define ERAR_NO_MEMORY 11
#define ERAR_BAD_DATA 12
#define ERAR_BAD_ARCHIVE 13
#define ERAR_UNKNOWN_FORMAT 14
#define ERAR_EOPEN 15
#define ERAR_ECREATE 16
#define ERAR_ECLOSE 17
#define ERAR_EREAD 18
#define ERAR_EWRITE 19
#define ERAR_SMALL_BUF 20
#define ERAR_UNKNOWN 21
#define ERAR_MISSING_PASSWORD 22
#define ERAR_EREFERENCE 23
#define ERAR_BAD_PASSWORD 24
#define RAR_OM_LIST 0
#define RAR_OM_EXTRACT 1
#define RAR_OM_LIST_INCSPLIT 2
#define RAR_SKIP 0
#define RAR_TEST 1
#define RAR_EXTRACT 2
#define RAR_VOL_ASK 0
#define RAR_VOL_NOTIFY 1
#define RAR_DLL_VERSION 6
#define RAR_HASH_NONE 0
#define RAR_HASH_CRC32 1
#define RAR_HASH_BLAKE2 2
#ifdef _UNIX
#define CALLBACK
#define PASCAL
#define LONG long
#define HANDLE void *
#define LPARAM long
#define UINT unsigned int
#endif
#define RHDF_SPLITBEFORE 0x01
#define RHDF_SPLITAFTER 0x02
#define RHDF_ENCRYPTED 0x04
#define RHDF_SOLID 0x10
#define RHDF_DIRECTORY 0x20
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;
};
struct RARHeaderDataEx
{
char ArcName[1024];
wchar_t ArcNameW[1024];
char FileName[1024];
wchar_t FileNameW[1024];
unsigned int Flags;
unsigned int PackSize;
unsigned int PackSizeHigh;
unsigned int UnpSize;
unsigned int UnpSizeHigh;
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;
unsigned int DictSize;
unsigned int HashType;
char Hash[32];
unsigned int Reserved[1014];
};
struct RAROpenArchiveData
{
char *ArcName;
unsigned int OpenMode;
unsigned int OpenResult;
char *CmtBuf;
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
};
typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2);
struct RAROpenArchiveDataEx
{
char *ArcName;
wchar_t *ArcNameW;
unsigned int OpenMode;
unsigned int OpenResult;
char *CmtBuf;
unsigned int CmtBufSize;
unsigned int CmtSize;
unsigned int CmtState;
unsigned int Flags;
UNRARCALLBACK Callback;
LPARAM UserData;
unsigned int Reserved[28];
};
enum UNRARCALLBACK_MESSAGES {
UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD,UCM_CHANGEVOLUMEW,
UCM_NEEDPASSWORDW
};
typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode);
typedef int (PASCAL *PROCESSDATAPROC)(unsigned char *Addr,int Size);
extern HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *ArchiveData);
extern HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *ArchiveData);
extern int PASCAL RARCloseArchive(HANDLE hArcData);
extern int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *HeaderData);
extern int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *HeaderData);
extern int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName, bool TestMode);
extern int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar_t *DestPath,wchar_t *DestName, bool TestMode);
extern void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData);
extern void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc);
extern void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc);
extern void PASCAL RARSetPassword(HANDLE hArcData,char *Password);
extern int PASCAL RARGetDllVersion();
#endif

267
unrarlib/unrarlibutils.c Normal file
View File

@ -0,0 +1,267 @@
#include "unrarlibutils.h"
static void* rar_open(const char *filename, unsigned int om) {
struct RAROpenArchiveData arc_open;
arc_open.ArcName = (char*)filename;
arc_open.OpenMode = om;
arc_open.CmtBuf = NULL;
HANDLE rar_file = RAROpenArchive(&arc_open);
if (arc_open.OpenResult != 0) {
return NULL;
}
return rar_file;
}
ArchiveFileNode* createNode(const char* name) {
ArchiveFileNode* node = malloc(sizeof(ArchiveFileNode));
node->nodeName = malloc((strlen(name) + 2) * sizeof(char));
strcpy(node->nodeName, name);
node->childCount = 0;
node->childPt = NULL;
node->fatherPt = NULL;
node->maxCount = 0;
return node;
}
void add_node(ArchiveFileNode* father,ArchiveFileNode* child) {
uint32_t count = father->childCount;
if( (count + 1) > father->maxCount ) {
if(father->maxCount == 0) {
father->maxCount = 16;
father->childPt = malloc(16 * sizeof(void*));
} else {
void* n_ptr = realloc((void*)father->childPt,2 * father->maxCount * sizeof(void*));
if(n_ptr) {
father->childPt = n_ptr;
father->maxCount *= 2;
}
}
}
father->childPt[count] = (void*)child;
father->childCount++;
child->fatherPt = father;
}
ArchiveFileNode* getChildNodeByName(ArchiveFileNode* node,char* name) {
if(node->childCount <= 0 )
return NULL;
uint32_t i;
for(i = 0; i < node->childCount; i++) {
ArchiveFileNode* _n = (ArchiveFileNode*)(node->childPt[i]);
if(strcmp(_n->nodeName,name) == 0) {
return _n;
}
}
return NULL;
}
void free_node(ArchiveFileNode* node) {
uint32_t count = node->childCount;
int i = 0;
for(; i < count; i++) {
ArchiveFileNode* _n = (ArchiveFileNode*)(node->childPt[i]);
free_node(_n);
}
if(node->childPt != NULL) {
free(node->childPt);
}
if(node->nodeName != NULL) {
free(node->nodeName);
}
free(node);
}
void parse_path(const char* name, struct filelayer* layer) {
char* p;
char _name[RARMAX_FILENAME];
strcpy(_name, name);
uint32_t depth = 0;
while(1) {
p = strrchr(_name, '/');
if(!p)
break;
strcpy(&(layer->name[depth][0]), p + sizeof(char));
layer->depth = ++depth;
*p = '\0';
}
strcpy(&(layer->name[depth][0]), _name);
}
ArchiveFileNode* openRARFile(char* filename) {
ArchiveFileNode* root = createNode("root");
HANDLE RARFile = rar_open(filename,RAR_OM_LIST);
if(!RARFile) {
free_node(root);
return NULL;
}
struct RARHeaderData data;
while (!RARReadHeader(RARFile, &data)) {
struct filelayer layer = {0};
parse_path(data.FileName,&layer);
ArchiveFileNode* _up = root;
int i = layer.depth;
for(; i > 0; i--) {
ArchiveFileNode* father = getChildNodeByName(_up, &(layer.name[i][0]));
if(!father) {
father = createNode(&(layer.name[i][0]));
add_node(_up,father);
}
_up = father;
}
ArchiveFileNode* filenode = getChildNodeByName(_up,&(layer.name[0][0]));
if(!filenode) {
filenode = createNode(&(layer.name[0][0]));
add_node(_up, filenode);
}
filenode->data = data;
RARProcessFile(RARFile, RAR_SKIP,NULL,NULL,false);
}
RARCloseArchive(RARFile);
return root;
}
int extractToMem(struct ExtractHeader* header,char* extractBuffer,uint64_t bufferSize) {
if(header->offset >= header->bufferSize)
return -1;
if((header->offset + bufferSize) > header->bufferSize)
bufferSize = (header->bufferSize - header->offset);//no enough memory
memcpy((header->memPtr + header->offset),extractBuffer,bufferSize);
header->offset += bufferSize;
return 1;
}
int extractToFile(struct ExtractHeader* header,char* extractBuffer,uint64_t bufferSize) {
if(!header->file)
return -1;
FileProcessParam* param = header->param;
if (param) {
if (param->value)
(*param->value) += bufferSize;
if (param->SetProgress)
param->SetProgress(param->value ? *param->value : 0, param->max);
if (param->cancelHandler && param->cancelHandler()) {
return -1;
}
}
sceIoLseek(header->file,header->offset,SCE_SEEK_SET);
sceIoWrite(header->file,extractBuffer,bufferSize);
header->offset += bufferSize;
return 1;
}
static int CALLBACK rarCallback(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2) {
struct ExtractHeader* header;
int rtn = 1;
switch(msg) {
case UCM_CHANGEVOLUME:
if(P2 != RAR_VOL_NOTIFY) {
rtn = -1;
}
break;
case UCM_PROCESSDATA:
header = (struct ExtractHeader*)UserData;
if(header->memPtr)
extractToMem(header,(char*)P1,P2);
else
rtn = extractToFile(header,(char*)P1,P2);
break;
default:
rtn = -1;
break;
}
return rtn;
}
int extractRAR(char* path,char* filename,struct ExtractHeader* header) {
HANDLE RARFile = rar_open(path,RAR_OM_EXTRACT);
if(!RARFile)
return -1;
struct RARHeaderData data;
int rtn = -1;
while (!RARReadHeader(RARFile, &data)) {
if(!(strcmp(data.FileName,filename))) {
rtn = 1;
break;
}
RARProcessFile(RARFile, RAR_SKIP,NULL,NULL,false);
}
if(rtn > 0) {
RARSetCallback(RARFile,rarCallback,(LPARAM)header);
int result = RARProcessFile(RARFile, RAR_TEST,NULL,NULL,false);
if(result >= 0)
rtn = 1;
else if(result == -2)
rtn = 0;
}
RARCloseArchive(RARFile);
return rtn;
}
ArchiveFileNode* getFileNodeFromFilePath(ArchiveFileNode* root,const char* filepath) {
struct filelayer layer = {0};
parse_path(filepath,&layer);
int i = layer.depth;
ArchiveFileNode* _up = root;
for(; i > 0; i--) {
_up = getChildNodeByName(_up, &(layer.name[i][0]));
if(!_up)
return NULL;
}
return getChildNodeByName(_up,&(layer.name[0][0]));
}
int getRARArchiveNodeInfo(ArchiveFileNode* root, uint64_t *size, uint32_t *folders, uint32_t *files) {
if(root->childCount > 0) {
uint32_t count = root->childCount;
int i = 0;
for(; i < count; i++) {
ArchiveFileNode* _n = (ArchiveFileNode*)(root->childPt[i]);
getRARArchiveNodeInfo(_n,size,folders,files);
}
}
if(root->data.Flags == 0x20) {
if(folders)
(*folders)++;
} else {
if(size)
(*size) += root->data.UnpSize;
if(files)
(*files) ++;
}
return 1;
}
ArchiveFileNode* getFloderNodeFromPath(ArchiveFileNode* root,const char* path) {
uint32_t pathlen = strlen(path);
char temp[pathlen];
strcpy(temp,path);
temp[pathlen - 1] ='\0';
return getFileNodeFromFilePath(root,temp);
}
void closeRARFile(ArchiveFileNode* root) {
free_node(root);
}

52
unrarlib/unrarlibutils.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef UNRARLIBUTILS_H_INC
#define UNRARLIBUTILS_H_INC
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <psp2/io/stat.h>
#include <psp2/io/fcntl.h>
#include "../file.h"
#define _UNIX
#include "unrar_c_wrapper.h"
#define RARMAX_HIERARCHY 32//max hierarchy for folder
#define RARMAX_FILENAME 262
typedef struct {
char* nodeName;
void* fatherPt;
void** childPt;
uint32_t childCount;
uint32_t maxCount;
struct RARHeaderData data;
} ArchiveFileNode;
struct filelayer {
uint32_t depth;
char name[RARMAX_HIERARCHY][RARMAX_FILENAME];
};
struct ExtractHeader {
SceUID file;
uint64_t offset;
char* memPtr;
uint64_t bufferSize;
FileProcessParam * param;
};
ArchiveFileNode* openRARFile(char* filename);//returns the number of files in the rar document archive
void closeRARFile(ArchiveFileNode* root);
ArchiveFileNode* createNode(const char* name);
ArchiveFileNode* getChildNodeByName(ArchiveFileNode* node,char* name);
int extractRAR(char* path,char* filename,struct ExtractHeader* header);
ArchiveFileNode* getFileNodeFromFilePath(ArchiveFileNode* root, const char* filepath);
int getRARArchiveNodeInfo(ArchiveFileNode* root, uint64_t *size, uint32_t *folders, uint32_t *files);
void free_node(ArchiveFileNode* node);
ArchiveFileNode* getFloderNodeFromPath(ArchiveFileNode* root,const char* path);
#endif // UNRARLIBUTILS_H_INC