MPackageFile(MPackageEnt ent) { m_size = npk_entity_get_size(ent); m_buffer = new char[m_size]; npk_entity_read(ent, m_buffer); m_pos = m_buffer; }
NPK_RESULT npk_entity_export( NPK_ENTITY entity, NPK_CSTR filename, bool forceoverwrite ) { void* buf; NPK_HANDLE handle; NPK_ENTITYBODY* eb = entity; NPK_RESULT res; if( !entity ) return npk_error( NPK_ERROR_EntityIsNull ); buf = malloc( eb->info_.originalSize_ ); if( !buf ) return npk_error( NPK_ERROR_NotEnoughMemory ); if( !( res = npk_entity_read( eb, buf ) ) ) return res; if( ( res = npk_open( &handle, filename, true, true ) ) != NPK_SUCCESS ) { if( !forceoverwrite ) return res; if( ( res = npk_open( &handle, filename, true, false ) ) != NPK_SUCCESS ) return res; } if( ( res = npk_write( handle, buf, eb->info_.originalSize_, g_callbackfp, NPK_PROCESSTYPE_ENTITY, g_callbackSize, eb->name_ ) ) != NPK_SUCCESS ) return res; if( ( res = npk_close( handle ) ) != NPK_SUCCESS ) return res; npk_set_filetime( filename, eb->info_.modified_ ); free( buf ); return NPK_SUCCESS; }
NPK_RESULT npk_entity_write( NPK_ENTITY entity, NPK_HANDLE handle ) { NPK_PACKAGEBODY* pb; NPK_ENTITYBODY* eb = entity; NPK_RESULT res; bool skipProcessing; void* buf = NULL; void* buf_for_zlib = NULL; NPK_SIZE size, endpos, startpos; int filehandle; int z_res; if( !eb ) return npk_error( NPK_ERROR_EntityIsNull ); pb = eb->owner_; skipProcessing = false; if( eb->localname_ != NULL ) { // read native file and write if( ( res = npk_open( &filehandle, eb->localname_, false, false ) ) != NPK_SUCCESS ) return res; endpos = npk_seek( filehandle, 0, SEEK_END ); startpos = npk_seek( filehandle, 0, SEEK_SET ); size = endpos - startpos; if( size == 0 ) return npk_error( NPK_ERROR_ZeroFileSize ); eb->info_.originalSize_ = size; buf = malloc( size ); if( ( res = npk_read( filehandle, buf, size, g_callbackfp, NPK_PROCESSTYPE_ENTITY, g_callbackSize, eb->name_ ) ) != NPK_SUCCESS ) goto npk_entity_write_return_with_free; npk_close( filehandle ); npk_get_filetime( eb->localname_, &eb->info_.modified_ ); NPK_SAFE_FREE( eb->localname_ ); } else { if( eb->newflag_ != eb->info_.flag_ ) { // read entity and write size = eb->info_.originalSize_; buf = malloc( size ); npk_entity_read( eb, buf ); } else { // just copy size = eb->info_.size_; buf = malloc( size ); npk_seek( pb->handle_, (long)eb->info_.offset_+pb->offsetJump_, SEEK_SET ); if( ( res = npk_read( pb->handle_, buf, size, g_callbackfp, NPK_PROCESSTYPE_ENTITY, g_callbackSize, eb->name_ ) ) != NPK_SUCCESS ) goto npk_entity_write_return_with_free; skipProcessing = true; } } if( !skipProcessing ) { // Encode before compress, before v21 if( ( eb->newflag_ & NPK_ENTITY_ENCRYPT ) && !( eb->newflag_ & NPK_ENTITY_REVERSE ) ) tea_encode_buffer((char*)buf, (int)size, pb->teakey_ ); if( eb->newflag_ & NPK_ENTITY_COMPRESS ) { if( size >= NPK_MIN_SIZE_ZIPABLE ) { unsigned long compressedSize = (unsigned long)(sizeof(char) * size * 1.1 + 12); // margin rules from zlib/compress.c buf_for_zlib = malloc( compressedSize ); #ifdef Z_PREFIX z_res = z_compress( (Bytef*)buf_for_zlib, (z_uLong*)&compressedSize, (const Bytef*)buf, (z_uLong)size ); #else z_res = compress( (Bytef*)buf_for_zlib, (uLong*)&compressedSize, (const Bytef*)buf, (uLong)size ); #endif if( ( z_res == Z_OK ) && ( compressedSize < size ) ) { free( buf ); buf = buf_for_zlib; buf_for_zlib = NULL; size = compressedSize; } else // not suitable to compress { free( buf_for_zlib ); eb->newflag_ &= !NPK_ENTITY_COMPRESS; } } } // Encode after compress, after v21 if( ( eb->newflag_ & NPK_ENTITY_ENCRYPT ) && ( eb->newflag_ & NPK_ENTITY_REVERSE ) ) tea_encode_buffer((char*)buf, (int)size, pb->teakey_ ); } eb->info_.size_ = size; eb->info_.offset_ = npk_tell( handle ); if( ( res = npk_write( handle, buf, size, g_callbackfp, NPK_PROCESSTYPE_ENTITY, g_callbackSize, eb->name_ ) ) != NPK_SUCCESS ) goto npk_entity_write_return_with_free; free( buf ); eb->info_.flag_ = eb->newflag_; return NPK_SUCCESS; npk_entity_write_return_with_free: NPK_SAFE_FREE( buf ); NPK_SAFE_FREE( buf_for_zlib ); return res; }
int libnpk_streamable( int argc, char * argv [] ) { int teakey[4] = {1,2,3,4}; NPK_PACKAGE pack; NPK_ENTITY entity; // create a pack CHECK( NPK_SUCCESS == npk_package_alloc( &pack, teakey ) ); CHECK( NPK_SUCCESS == npk_package_add_file( pack, "sample.txt", "sample.txt", &entity ) ); CHECK( NPK_SUCCESS == npk_package_add_file( pack, "sample.txt", "tea.txt", &entity ) ); CHECK( NPK_SUCCESS == npk_entity_set_flag( entity, NPK_ENTITY_ENCRYPT_TEA ) ); CHECK( NPK_SUCCESS == npk_package_add_file( pack, "sample.txt", "xxtea.txt", &entity ) ); CHECK( NPK_SUCCESS == npk_entity_set_flag( entity, NPK_ENTITY_ENCRYPT_XXTEA ) ); CHECK( NPK_SUCCESS == npk_package_add_file( pack, "sample.txt", "zip.txt", &entity ) ); CHECK( NPK_SUCCESS == npk_entity_set_flag( entity, NPK_ENTITY_COMPRESS_ZLIB ) ); CHECK( NPK_SUCCESS == npk_package_save( pack, "foo.npk", true ) ); npk_package_close( pack ); // simulate download int rh = open( "foo.npk", O_RDONLY | O_BINARY ); size_t filesize = npk_seek( rh, 0, SEEK_END ); npk_seek( rh, 0, SEEK_SET ); int wh = open( "foo_2.npk", O_CREAT | O_RDWR | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE ); // validation std::string entityNames[4] = { "sample.txt", "tea.txt", "xxtea.txt", "zip.txt" }; pack = 0; int i = 0; size_t offset = 0; char buf[255]; while( offset < filesize ) { size_t r = rand()%16; if( r + offset > filesize ) r = filesize - offset; read( rh, &buf, sizeof(char)*r ); write( wh, buf, sizeof(char)*r ); printf( "offset %ld, reading %ld byte(s).\n", offset, r ); offset += r; if( pack == 0 ) { pack = npk_package_open( "foo_2.npk", teakey ); if( pack != 0 ) printf( " package loaded.\n" ); } else { NPK_ENTITY entity = npk_package_get_entity( pack, entityNames[i].c_str() ); CHECK( entity != NULL ); NPK_SIZE size = npk_entity_get_size( entity ); if( npk_entity_is_ready( entity ) ) { printf( " entity %s ready.\n", entityNames[i].c_str() ); void* buf = malloc( size ); CHECK( npk_entity_read( entity, buf ) ); CHECK_EQUAL_STR_WITH_FILE( (const char*)buf, "sample.txt" ); free( buf ); ++i; } } } npk_package_close( pack ); close( wh ); close( rh ); return 0; }