mirror of
https://github.com/joel16/VitaShell.git
synced 2025-01-07 11:40:16 +00:00
171 lines
3.8 KiB
C++
171 lines
3.8 KiB
C++
// Misc functions outside the core interface
|
|
|
|
#include "unrar.h"
|
|
|
|
#include "rar.hpp"
|
|
#include <assert.h>
|
|
|
|
// This source code is a heavily modified version based on the unrar package.
|
|
// It may not be used to develop a RAR (WinRAR) compatible archiver.
|
|
// See unrar/license.txt for copyright and licensing.
|
|
|
|
void unrar_init()
|
|
{
|
|
if (CRCTab[1]==0)
|
|
InitCRC();
|
|
|
|
Unpack::init_tables();
|
|
}
|
|
|
|
struct unrar_extract_mem_t
|
|
{
|
|
char* out;
|
|
char* end;
|
|
};
|
|
|
|
extern "C" {
|
|
static unrar_err_t extract_write( void* user_data, const void* in, int count )
|
|
{
|
|
unrar_extract_mem_t* p = (unrar_extract_mem_t*) user_data;
|
|
|
|
unrar_pos_t remain = p->end - p->out;
|
|
if ( remain > 0 )
|
|
{
|
|
if ( count > remain )
|
|
count = remain;
|
|
|
|
memcpy( p->out, in, count );
|
|
p->out += count;
|
|
}
|
|
|
|
return unrar_ok;
|
|
}
|
|
}
|
|
|
|
unrar_err_t unrar_extract( unrar_t* p, void* out, unrar_pos_t size )
|
|
{
|
|
assert( !unrar_done( p ) );
|
|
|
|
unrar_extract_mem_t m;
|
|
m.out = (char*) out;
|
|
m.end = m.out + size;
|
|
return unrar_extract_custom( p, &extract_write, &m );
|
|
}
|
|
|
|
inline
|
|
static bool is_entire_file( const unrar_t* p, const void* in, int count )
|
|
{
|
|
return (count == p->Arc.NewLhd.UnpSize && p->Unp && in == p->Unp->window_wrptr());
|
|
}
|
|
|
|
extern "C" {
|
|
static unrar_err_t extract_mem( void* data, void const* in, int count )
|
|
{
|
|
unrar_t* p = (unrar_t*) data;
|
|
|
|
// We might have pointer to entire file
|
|
if ( !p->data_ && is_entire_file( p, in, count ) )
|
|
{
|
|
p->data_ = in;
|
|
return unrar_ok;
|
|
}
|
|
|
|
// We don't have it, so allocate memory to read entire file into
|
|
if ( !p->own_data_ )
|
|
{
|
|
assert( !p->data_ );
|
|
|
|
unrar_pos_t size = unrar_info( p )->size;
|
|
p->own_data_ = malloc( size ? size : 1 );
|
|
if ( !p->own_data_ )
|
|
return unrar_err_memory;
|
|
|
|
p->data_ = p->own_data_;
|
|
}
|
|
|
|
memcpy( (void*) p->data_, in, count );
|
|
p->data_ = (char*) p->data_ + count;
|
|
|
|
return unrar_ok;
|
|
}
|
|
}
|
|
|
|
unrar_err_t unrar_extract_mem( unrar_t* p, void const** out )
|
|
{
|
|
assert( !unrar_done( p ) );
|
|
|
|
*out = NULL;
|
|
|
|
if ( !p->data_ )
|
|
{
|
|
unrar_err_t err = unrar_extract_custom( p, &extract_mem, p );
|
|
if ( err )
|
|
return err;
|
|
}
|
|
|
|
*out = (p->own_data_ ? p->own_data_ : p->data_);
|
|
return unrar_ok;
|
|
}
|
|
|
|
const char* unrar_err_str( unrar_err_t err )
|
|
{
|
|
switch ( err )
|
|
{
|
|
case unrar_ok: return "";
|
|
case unrar_err_memory: return "out of memory";
|
|
case unrar_err_open: return "couldn't open RAR archive";
|
|
case unrar_err_not_arc: return "not a RAR archive";
|
|
case unrar_err_corrupt: return "RAR archive is corrupt";
|
|
case unrar_err_io: return "couldn't read/write";
|
|
case unrar_err_arc_eof: return "unexpected end of archive";
|
|
case unrar_err_encrypted: return "encryption not supported";
|
|
case unrar_err_segmented: return "segmentation not supported";
|
|
case unrar_err_huge: return "huge (2GB+) archives are not supported";
|
|
case unrar_err_old_algo: return "compressed using older algorithm than supported";
|
|
case unrar_err_new_algo: return "compressed using newer algorithm than supported";
|
|
}
|
|
|
|
assert( false );
|
|
return "problem with RAR";
|
|
}
|
|
|
|
int ComprDataIO::Read( void* p, int n )
|
|
{
|
|
unrar_err_t err = user_read( user_read_data, p, &n, Tell_ );
|
|
if ( err )
|
|
ReportError( err );
|
|
|
|
Tell_ += n;
|
|
if ( Tell_ < 0 )
|
|
ReportError( unrar_err_huge );
|
|
|
|
return n;
|
|
}
|
|
|
|
void ComprDataIO::UnpWrite( byte* out, uint count )
|
|
{
|
|
if ( !SkipUnpCRC )
|
|
{
|
|
if ( write_error == unrar_ok )
|
|
write_error = user_write( user_write_data, out, count );
|
|
|
|
if ( OldFormat )
|
|
UnpFileCRC = OldCRC( (ushort) UnpFileCRC, out, count );
|
|
else
|
|
UnpFileCRC = CRC( UnpFileCRC, out, count );
|
|
}
|
|
}
|
|
|
|
int ComprDataIO::UnpRead( byte* out, uint count )
|
|
{
|
|
if ( count <= 0 )
|
|
return 0;
|
|
|
|
if ( count > (uint) UnpPackedSize )
|
|
count = UnpPackedSize;
|
|
|
|
int result = Read( out, count );
|
|
UnpPackedSize -= result;
|
|
return result;
|
|
}
|