示例#1
0
NPK_RESULT npk_package_remove_entity( NPK_PACKAGE package, NPK_ENTITY entity )
{
    NPK_ENTITYBODY* eb = entity;
    NPK_PACKAGEBODY* pb = package;

    if( !entity )
        return npk_error( NPK_ERROR_EntityIsNull );
    if( !package )
        return npk_error( NPK_ERROR_PackageIsNull );
    if( eb->owner_ != package )
        return npk_error( NPK_ERROR_EntityIsNotInThePackage );

    if( eb->prev_ )
        eb->prev_->next_ = eb->next_;
    if( eb->next_ )
        eb->next_->prev_ = eb->prev_;

    if( eb == pb->pEntityHead_ )
        pb->pEntityHead_ = eb->next_;
    if( eb == pb->pEntityTail_ )
        pb->pEntityTail_ = eb->prev_;

    pb->pEntityLatest_ = eb->next_;
    --pb->info_.entityCount_;

    NPK_SAFE_FREE( eb->name_ );
    NPK_SAFE_FREE( eb->localname_ );
    NPK_SAFE_FREE( eb );

    return NPK_SUCCESS;
}
示例#2
0
文件: npk.c 项目: keedi/npk
NPK_ENTITY npk_package_get_entity( NPK_PACKAGE package, NPK_CSTR entityname )
{
    NPK_ENTITYBODY* eb = NULL;
    NPK_PACKAGEBODY* pb = package;
    NPK_BUCKET* bucket = NULL;
    NPK_CHAR buf[512];

    if( !package )
    {
        npk_error( NPK_ERROR_PackageIsNull );
        return NULL;
    }

    if( NPK_SUCCESS != npk_prepare_entityname( entityname, buf, 512 ) )
        return NULL;

    if( pb->usingHashmap_ )
    {
        bucket = pb->bucket_[npk_get_bucket(buf)];
        if( bucket != NULL )
        {
            eb = bucket->pEntityHead_;
            while( eb != NULL )
            {
#ifdef NPK_CASESENSITIVE
                if( strcmp( eb->name_, buf ) == 0 )
#else
                if( stricmp( eb->name_, buf ) == 0 )
#endif
                {
                    pb->pEntityLatest_ = eb;
                    return eb;
                }
                eb = eb->nextInBucket_;
            }
        }
    }
    else /* not usingHashmap_ */
    {
        eb = pb->pEntityHead_;
        while( eb != NULL )
        {
#ifdef NPK_CASESENSITIVE
            if( strcmp( eb->name_, buf ) == 0 )
#else
            if( stricmp( eb->name_, buf ) == 0 )
#endif
            {
                pb->pEntityLatest_ = eb;
                return eb;
            }
            eb = eb->next_;
        }

    }
    npk_error( NPK_ERROR_CannotFindEntity );
    return NULL;
}
示例#3
0
文件: npk.c 项目: keedi/npk
bool npk_entity_read_partial( NPK_ENTITY entity, void* buf, NPK_SIZE offset, NPK_SIZE size )
{
    NPK_ENTITYBODY* eb = entity;
    NPK_PACKAGEBODY* pb = NULL;
    NPK_RESULT res;

    if( !entity )
    {
        npk_error( NPK_ERROR_EntityIsNull );
        return false;
    }

    if( eb->info_.flag_ & ( NPK_ENTITY_COMPRESS_ZLIB | NPK_ENTITY_COMPRESS_BZIP2 ) )
    {
        npk_error( NPK_ERROR_CantReadCompressedEntityByPartial );
        return false;
    }

    if( eb->info_.flag_ & ( NPK_ENTITY_ENCRYPT_TEA | NPK_ENTITY_ENCRYPT_XXTEA ) )
    {
        if( ( offset % 8 != 0 ) || ( ( size % 8 != 0 ) && ( offset + size != eb->info_.size_ ) ) )
        {
            npk_error( NPK_ERROR_ReadingEncryptedEntityByPartialShouldBeAligned );
            return false;
        }
    }

    pb = eb->owner_;
#ifdef NPK_PLATFORM_WINDOWS
    if( g_useCriticalSection )
        EnterCriticalSection( &pb->cs_ );
#endif
    npk_seek( pb->handle_, (long)(eb->info_.offset_ + offset)+pb->offsetJump_, SEEK_SET );

    res = npk_read( pb->handle_,
                    buf,
                    size,
                    g_callbackfp,
                    NPK_PROCESSTYPE_ENTITY,
                    g_callbackSize,
                    eb->name_ );

    if( eb->info_.flag_ & NPK_ENTITY_ENCRYPT_TEA )
        tea_decode_buffer(buf, size, pb->teakey_, (pb->info_.version_ >= NPK_VERSION_ENCRYPTREMAINS));
    if( eb->info_.flag_ & NPK_ENTITY_ENCRYPT_XXTEA )
        xxtea_decode_buffer(buf, size, pb->teakey_, (pb->info_.version_ >= NPK_VERSION_ENCRYPTREMAINS));

#ifdef NPK_PLATFORM_WINDOWS
    if( g_useCriticalSection )
        LeaveCriticalSection( &pb->cs_ );
#endif

    if( res != NPK_SUCCESS )
        return false;

    return true;
}
示例#4
0
文件: npk.c 项目: keedi/npk
bool npk_package_close( NPK_PACKAGE package )
{
    NPK_PACKAGEBODY* pb = (NPK_PACKAGEBODY*)package;
    NPK_RESULT res;
    int i;

    if( !package )
    {
        npk_error( NPK_ERROR_PackageIsNull );
        return false;
    }

    res = npk_package_remove_all_entity( pb );
    if( NPK_SUCCESS != res )
        return res;

#ifdef NPK_PLATFORM_WINDOWS
    DeleteCriticalSection( &pb->cs_ );
#endif

    if( false == pb->usingFdopen_ )
        npk_close( pb->handle_ );

    for( i = 0; i < NPK_HASH_BUCKETS; ++i )
        NPK_SAFE_FREE( pb->bucket_[i] );

    NPK_SAFE_FREE( pb );
    return true;
}
示例#5
0
NPK_RESULT npk_write( NPK_HANDLE handle, const void* buf, NPK_SIZE size,
                        NPK_CALLBACK cb, int cbprocesstype, NPK_SIZE cbsize, NPK_CSTR cbidentifier )
{
    NPK_SIZE currentwritten;
    NPK_SIZE totalwritten = 0;
    NPK_SIZE unit = cbsize;

    if( cb )
    {
        if( unit <= 0 )
            unit = size;

        do
        {
            if( (cb)( NPK_ACCESSTYPE_WRITE, cbprocesstype, cbidentifier, totalwritten, size ) == false )
                return( npk_error( NPK_ERROR_CancelByCallback ) );

            if( (int)( size - totalwritten ) < unit )
                unit = size - totalwritten;

            currentwritten = write( handle, (NPK_STR)buf + totalwritten, (unsigned int)unit );

            if( currentwritten < unit )
            {
                if( errno == EACCES )
                    return( npk_error( NPK_ERROR_PermissionDenied ) );
                else if( errno == ENOSPC )
                    return( npk_error( NPK_ERROR_NotEnoughDiscSpace ) );
                else
                    return( npk_error( NPK_ERROR_FileSaveError ) );
            }

            totalwritten += currentwritten;

        } while( totalwritten < size );

        if( (cb)( NPK_ACCESSTYPE_WRITE, cbprocesstype, cbidentifier, totalwritten, size ) == false )
            return( npk_error( NPK_ERROR_CancelByCallback ) );
    }
    else
    {
        currentwritten = write( handle, (NPK_STR)buf, size );

        if( currentwritten < size )
        {
            if( errno == EACCES )
                return( npk_error( NPK_ERROR_PermissionDenied ) );
            else if( errno == ENOSPC )
                return( npk_error( NPK_ERROR_NotEnoughDiscSpace ) );
            else
                return( npk_error( NPK_ERROR_FileSaveError ) );
        }
    }
    return NPK_SUCCESS;
}
示例#6
0
NPK_RESULT npk_entity_sub_flag( NPK_ENTITY entity, NPK_FLAG flag )
{
    NPK_ENTITYBODY* eb = entity;
    if( !eb )
        return npk_error( NPK_ERROR_EntityIsNull );

    eb->newflag_ &= ~flag;
    return NPK_SUCCESS;
}
示例#7
0
NPK_RESULT npk_entity_get_new_flag( NPK_ENTITY entity, NPK_FLAG* flag )
{
    NPK_ENTITYBODY* eb = entity;
    if( !eb )
        return npk_error( NPK_ERROR_EntityIsNull );

    *flag = eb->newflag_;
    return NPK_SUCCESS;
}
示例#8
0
文件: npk.c 项目: keedi/npk
NPK_SIZE npk_entity_get_packed_size( NPK_ENTITY entity )
{
    NPK_ENTITYBODY* eb = entity;
    if( !entity )
    {
        npk_error( NPK_ERROR_EntityIsNull );
        return 0;
    }
    return eb->info_.size_;
}
示例#9
0
文件: npk.c 项目: keedi/npk
NPK_SIZE npk_entity_get_offset( NPK_ENTITY entity )
{
    NPK_ENTITYBODY* eb = entity;
    if( !entity )
    {
        npk_error( NPK_ERROR_EntityIsNull );
        return 0;
    }
    return eb->info_.offset_;
}
示例#10
0
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;
}
示例#11
0
文件: npk.c 项目: keedi/npk
NPK_CSTR npk_entity_get_name( NPK_ENTITY entity )
{
    NPK_ENTITYBODY* eb = entity;
    if( !entity )
    {
        npk_error( NPK_ERROR_EntityIsNull );
        return 0;
    }
    return eb->name_;
}
示例#12
0
文件: npk.c 项目: keedi/npk
NPK_ENTITY npk_entity_next( NPK_ENTITY entity )
{
    NPK_ENTITYBODY* eb = entity;

    if( !entity )
    {
        npk_error( NPK_ERROR_EntityIsNull );
        return NULL;
    }

    return eb->next_;
}
示例#13
0
NPK_RESULT npk_alloc_copy_string( NPK_STR* dst, NPK_CSTR src )
{
    NPK_SIZE len = (NPK_SIZE)strlen(src);

    if( src == NULL )
        return( npk_error( NPK_ERROR_SourceStringisNull ) );

    if( *dst == src )
        return( npk_error( NPK_ERROR_CannotCopyToItself ) );

    if( *dst )
        free( *dst );

    *dst = malloc( sizeof(NPK_CHAR)*(len+1) );
    if( *dst == NULL )
        return( npk_error( NPK_ERROR_NotEnoughMemory ) );

    strncpy( *dst, src, len );
    (*dst)[len] = '\0';
    return NPK_SUCCESS;
}
示例#14
0
文件: npk.c 项目: keedi/npk
NPK_ENTITY npk_package_get_first_entity( NPK_PACKAGE package )
{
    NPK_PACKAGEBODY* pb = package;

    if( !package )
    {
        npk_error( NPK_ERROR_PackageIsNull );
        return NULL;
    }

    return pb->pEntityHead_;
}
示例#15
0
NPK_RESULT npk_set_filetime( NPK_CSTR filename, const NPK_TIME pft )
{
    struct stat __sbuf;
    struct utimbuf __ubuf;
    int result;
    
    result = stat( filename, &__sbuf );
    if( result != 0 )
    {
        switch( errno )
        {
        case ENOENT:
            return( npk_error( NPK_ERROR_FileNotFound ) );
        }
        return( npk_error( NPK_ERROR_FailToGetFiletime ) );
    }
    __ubuf.actime = __sbuf.st_atime;
    __ubuf.modtime = pft;
    utime( filename, &__ubuf );

    return NPK_SUCCESS;
}
示例#16
0
NPK_RESULT npk_package_clear( NPK_PACKAGE package )
{
    NPK_RESULT res;
    if( !package )
        return npk_error( NPK_ERROR_PackageIsNull );

    if( ( res = npk_package_remove_all_entity( package ) ) != NPK_SUCCESS )
        return res;

    if( ( res = npk_package_init( package ) ) != NPK_SUCCESS )
        return res;

    return NPK_SUCCESS;
}
示例#17
0
NPK_RESULT npk_get_filetime( NPK_CSTR filename, NPK_TIME* pft )
{
    struct stat __sbuf;
    int result;

    if( g_use_gluetime )
        *pft = g_gluetime;
    else
    {
        result = stat( filename, &__sbuf );
        if( result != 0 )
        {
            switch( errno )
            {
            case ENOENT:
                return( npk_error( NPK_ERROR_FileNotFound ) );
            }
            return( npk_error( NPK_ERROR_FailToGetFiletime ) );
        }
        *pft = (NPK_TIME)__sbuf.st_mtime;
    }

    return NPK_SUCCESS;
}
示例#18
0
NPK_RESULT npk_write_encrypt( NPK_TEAKEY* key, NPK_HANDLE handle, const void* buf, NPK_SIZE size,
                        NPK_CALLBACK cb, int cbprocesstype, NPK_SIZE cbsize, NPK_CSTR cbidentifier )
{
    NPK_RESULT res;
    void* bufferforencode = malloc( sizeof(char) * size );

    if( !bufferforencode )
        return npk_error( NPK_ERROR_NotEnoughMemory );

    memcpy( bufferforencode, buf, sizeof(char) * size );
    tea_encode_buffer( (NPK_STR)bufferforencode, size, key );

    res = npk_write( handle, bufferforencode, size, cb, cbprocesstype, cbsize, cbidentifier );
    free( bufferforencode );
    return res;
}
示例#19
0
文件: npk.c 项目: keedi/npk
bool npk_entity_is_ready( NPK_ENTITY entity )
{
    NPK_ENTITYBODY* eb = entity;
    NPK_PACKAGEBODY* pb = NULL;
    int res;
    struct stat buf;

    if( !entity )
    {
        npk_error( NPK_ERROR_EntityIsNull );
        return false;
    }

    pb = eb->owner_;
    res = fstat( pb->handle_, &buf );
    if( (long)( pb->offsetJump_ + eb->info_.offset_ + eb->info_.size_ ) <= buf.st_size )
        return true;

    return false;
}
示例#20
0
文件: npk.c 项目: keedi/npk
bool npk_entity_read( NPK_ENTITY entity, void* buf )
{
    NPK_ENTITYBODY* eb = entity;
    NPK_PACKAGEBODY* pb = NULL;
    void** lplpTarget = &buf;
    void* lpDecompressBuffer = NULL;
    //NPK_SIZE uncompLen = 0;
    unsigned long uncompLen = 0;
    NPK_RESULT res;

    if( !entity )
    {
        npk_error( NPK_ERROR_EntityIsNull );
        return false;
    }

    if( eb->info_.flag_ & ( NPK_ENTITY_COMPRESS_ZLIB | NPK_ENTITY_COMPRESS_BZIP2 ) )
    {
        lpDecompressBuffer = malloc( sizeof(char) * eb->info_.size_ );
        lplpTarget = &lpDecompressBuffer;
    }

    pb = eb->owner_;
#ifdef NPK_PLATFORM_WINDOWS
    if( g_useCriticalSection )
        EnterCriticalSection( &pb->cs_ );
#endif
    npk_seek( pb->handle_, (long)eb->info_.offset_+pb->offsetJump_, SEEK_SET );

    res = npk_read( pb->handle_,
                    (*lplpTarget),
                    eb->info_.size_,
                    g_callbackfp,
                    NPK_PROCESSTYPE_ENTITY,
                    g_callbackSize,
                    eb->name_ );
#ifdef NPK_PLATFORM_WINDOWS
    if( g_useCriticalSection )
        LeaveCriticalSection( &pb->cs_ );
#endif

    if( res != NPK_SUCCESS )
        goto npk_entity_read_return_null_with_free;

    // Decode before uncompress, after v21
    if( ( eb->info_.flag_ & NPK_ENTITY_ENCRYPT_TEA ) && ( eb->info_.flag_ & NPK_ENTITY_REVERSE ) )
        tea_decode_buffer((char*)(*lplpTarget), eb->info_.size_, pb->teakey_, (pb->info_.version_ >= NPK_VERSION_ENCRYPTREMAINS));

    if( eb->info_.flag_ & NPK_ENTITY_ENCRYPT_XXTEA )
        xxtea_decode_buffer((char*)(*lplpTarget), eb->info_.size_, pb->teakey_, (pb->info_.version_ >= NPK_VERSION_ENCRYPTREMAINS));

    if( eb->info_.flag_ & NPK_ENTITY_COMPRESS_ZLIB )
    {
        uncompLen = eb->info_.originalSize_;

        if( uncompLen >= NPK_MIN_SIZE_ZIPABLE )
        {
#ifdef Z_PREFIX
            if( Z_OK != z_uncompress((Bytef*)(buf), (z_uLong*)&uncompLen, (const Bytef*)lpDecompressBuffer, (z_uLong)eb->info_.size_ ) )
#else
            if( Z_OK != uncompress((Bytef*)(buf), (uLong*)&uncompLen, (const Bytef*)lpDecompressBuffer, (uLong)eb->info_.size_ ) )
#endif
            {
                npk_error( NPK_ERROR_FailToDecompress );
                goto npk_entity_read_return_null_with_free;
            }

            if( eb->info_.originalSize_ != uncompLen )
            {
                npk_error( NPK_ERROR_FailToDecompress );
                goto npk_entity_read_return_null_with_free;
            }
        }
        else
            memcpy( buf, lpDecompressBuffer, eb->info_.size_ );

        NPK_SAFE_FREE( lpDecompressBuffer );
        lplpTarget = &buf;
    }

    // Decode after uncompress, before v21
    if( ( eb->info_.flag_ & NPK_ENTITY_ENCRYPT_TEA ) && !( eb->info_.flag_ & NPK_ENTITY_REVERSE ) )
        tea_decode_buffer((char*)(*lplpTarget), eb->info_.originalSize_, pb->teakey_, false);

    return true;

npk_entity_read_return_null_with_free:
    NPK_SAFE_FREE( lpDecompressBuffer );
    return false;
}
示例#21
0
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;
}
示例#22
0
NPK_RESULT npk_package_save( NPK_PACKAGE package, NPK_CSTR filename, bool forceoverwrite )
{
    NPK_PACKAGEBODY*    pb = package;
    NPK_ENTITYBODY*     eb = NULL;
    NPK_RESULT          res;
    bool                bUseTemporaryFile = false;
    NPK_SIZE            len;
    int                 savecount = 0;
    NPK_STR             savefilename = NULL;
    int                 savefilehandle;
    NPK_CHAR*           buf;
    NPK_CHAR*           buf_pos;
    NPK_PACKAGEINFO_V23 header_v23;

    if( !package )
        return npk_error( NPK_ERROR_PackageIsNull );

    if( !filename )
        return npk_error( NPK_ERROR_PackageHasNoName );

    if( ( res = npk_open( &savefilehandle, filename, true, true ) ) == NPK_SUCCESS )
    {
        npk_alloc_copy_string( &savefilename, filename );
    }
    else
    {
        if( res != NPK_ERROR_FileAlreadyExists )
            return res;

        if( !forceoverwrite )
            return res;

        len = (NPK_SIZE)strlen( filename );
        savefilename = malloc( sizeof(NPK_CHAR)*(len+2) );
        if( savefilename == NULL )
            return( npk_error( NPK_ERROR_NotEnoughMemory ) );

        strncpy( savefilename, filename, len );
        savefilename[len+0] = '_';
        savefilename[len+1] = '\0';
        bUseTemporaryFile = true;

        if( ( res = npk_open( &savefilehandle, savefilename, true, false ) ) != NPK_SUCCESS )
            return res;
    }

    strncpy( pb->info_.signature_, NPK_SIGNATURE, sizeof(NPK_CHAR)*4 );
    pb->info_.version_ = NPK_VERSION_CURRENT;
    pb->info_.entityDataOffset_ = sizeof(NPK_PACKAGEINFO)
                                + sizeof(NPK_PACKAGEINFO_V23);

    npk_seek( savefilehandle, (long)pb->info_.entityDataOffset_, SEEK_SET );

    eb = pb->pEntityHead_;
    while( eb != NULL )
    {
        if( g_callbackfp )
            if( (g_callbackfp)( NPK_ACCESSTYPE_WRITE, NPK_PROCESSTYPE_PACKAGE, filename, savecount, pb->info_.entityCount_ ) == false )
                return( npk_error( NPK_ERROR_CancelByCallback ) );

        npk_entity_write( eb, savefilehandle );
        ++savecount;
        eb = eb->next_;
    }

    pb->info_.entityInfoOffset_ = npk_tell( savefilehandle );
    pb->info_.entityCount_ = savecount;

    eb = pb->pEntityHead_;

    // version 24, Take single encryption to whole entity headers
    buf = malloc( (sizeof(NPK_ENTITYINFO)+260)*savecount ); // 260 = MAX_PATH on windows, isn't it enough?
    if( !buf )
        return( npk_error( NPK_ERROR_NotEnoughMemory ) );
    buf_pos = buf;

    while( eb != NULL )
    {
        memcpy( buf_pos, &eb->info_, sizeof(NPK_ENTITYINFO) );
        buf_pos += sizeof(NPK_ENTITYINFO);
        memcpy( buf_pos, eb->name_, sizeof(NPK_CHAR)*eb->info_.nameLength_ );
        buf_pos += sizeof(NPK_CHAR)*eb->info_.nameLength_;
        eb = eb->next_;
    }
    if( ( res = npk_write_encrypt( pb->teakey_,
                            savefilehandle,
                            buf,
                            buf_pos - buf,
                            g_callbackfp,
                            NPK_PROCESSTYPE_ENTITYHEADER,
                            g_callbackSize,
                            savefilename ) ) != NPK_SUCCESS )
        return res;
    NPK_SAFE_FREE( buf );

    npk_seek( savefilehandle, 0, SEEK_SET );
    if( ( res = npk_write( savefilehandle,
                    &pb->info_,
                    sizeof(NPK_PACKAGEINFO),
                    g_callbackfp,
                    NPK_PROCESSTYPE_PACKAGEHEADER,
                    g_callbackSize,
                    savefilename ) ) != NPK_SUCCESS )
        return res;

    // version 23, Write the package timestamp for other applications
    // TODO:reveal the return type of 'time' function on 64bit mac os
    time( (time_t*)&header_v23.modified_ );

    if( ( res = npk_write( savefilehandle,
                    &header_v23,
                    sizeof(NPK_PACKAGEINFO_V23),
                    g_callbackfp,
                    NPK_PROCESSTYPE_PACKAGEHEADER,
                    g_callbackSize,
                    savefilename ) ) != NPK_SUCCESS )
        return res;

    npk_flush( savefilehandle );
    npk_close( pb->handle_ );

    if( bUseTemporaryFile )
    {
        npk_close( savefilehandle );
        remove( filename );
        rename( savefilename, filename );

        if( (res = npk_open( &pb->handle_, filename, false, false ) ) != NPK_SUCCESS )
            return res;
    }
    else
    {
        pb->handle_ = savefilehandle;
    }
    NPK_SAFE_FREE( savefilename );
    return NPK_SUCCESS;
}
示例#23
0
文件: npk.c 项目: keedi/npk
NPK_RESULT __npk_package_open( NPK_PACKAGEBODY* pb, const NPK_CHAR* filename, long filesize, NPK_TEAKEY teakey[4] )
{
    NPK_CHAR            buf[512];
    NPK_ENTITYBODY*     eb = NULL;
    NPK_ENTITYINFO_V21  oldinfo;
    NPK_SIZE            entityCount = 0;
    NPK_CHAR*           entityheaderbuf;
    NPK_CHAR*           pos;
    long                entityheadersize = 0;
    NPK_RESULT          res;

    if( filesize == 0 )
    {
        filesize = npk_seek( pb->handle_, 0, SEEK_END );
        npk_seek( pb->handle_, 0, SEEK_SET );
    }

    if( filesize < sizeof(NPK_PACKAGEINFO) )
        return( npk_error( NPK_ERROR_PackageIsNotReady ) );

    // Read common header
    res = npk_read( pb->handle_,
                    (void*)&pb->info_,
                    sizeof(NPK_PACKAGEINFO),
                    g_callbackfp,
                    NPK_PROCESSTYPE_PACKAGEHEADER,
                    g_callbackSize,
                    filename );
    if( res != NPK_SUCCESS ) return res;

    if( strncmp( pb->info_.signature_, NPK_SIGNATURE, 4 ) != 0 )
        if( strncmp( pb->info_.signature_, NPK_OLD_SIGNATURE, 4 ) != 0 )
            return( npk_error( NPK_ERROR_NotValidPackage ) );

    // version 18 / read own tea key
    if( pb->info_.version_ < NPK_VERSION_REFACTORING )
    {
        return ( npk_error( NPK_ERROR_NotSupportedVersion ) );
    }
    else
    {
        if( teakey == NULL )
        {
            return ( npk_error( NPK_ERROR_NeedSpecifiedTeaKey ) );
        }
        memcpy( pb->teakey_, teakey, sizeof(NPK_TEAKEY) * 4 );
    }

    // version 23 / package timestamp
    if( pb->info_.version_ >= NPK_VERSION_PACKAGETIMESTAMP )
    {
        res = npk_read( pb->handle_,
                        (void*)&pb->modified_,
                        sizeof(NPK_TIME),
                        g_callbackfp,
                        NPK_PROCESSTYPE_PACKAGEHEADER,
                        g_callbackSize,
                        filename );
        if( res != NPK_SUCCESS ) return res;
    }

    entityCount = pb->info_.entityCount_;
    pb->info_.entityCount_ = 0;

    if( pb->info_.version_ >= NPK_VERSION_SINGLEPACKHEADER )
    {
        if( pb->info_.version_ >= NPK_VERSION_STREAMABLE )
        {
            if( filesize < (long)pb->info_.entityDataOffset_ )
                return( npk_error( NPK_ERROR_PackageIsNotReady ) );
            entityheadersize = (long)pb->info_.entityDataOffset_ - (long)pb->info_.entityInfoOffset_;
        }
        else
        {
            entityheadersize = filesize - (long)pb->info_.entityInfoOffset_;
            npk_seek( pb->handle_, (long)pb->info_.entityInfoOffset_+pb->offsetJump_, SEEK_SET );
        }

        entityheaderbuf = malloc( entityheadersize );
        if( !entityheaderbuf )
            return( npk_error( NPK_ERROR_NotEnoughMemory ) );

        res = npk_read_encrypt( teakey,
                                pb->handle_,
                                (void*)entityheaderbuf,
                                entityheadersize,
                                g_callbackfp,
                                NPK_PROCESSTYPE_ENTITYHEADER,
                                g_callbackSize,
                                filename,
                                pb->info_.version_ >= NPK_VERSION_ENCRYPTREMAINS,
                                pb->info_.version_ >= NPK_VERSION_USEXXTEAONHEADER
                                );
        if( res != NPK_SUCCESS ) return res;

        pos = entityheaderbuf;
        
        while( entityCount > 0 )
        {
            --entityCount;

            res = npk_entity_alloc( (NPK_ENTITY*)&eb );
            if( res != NPK_SUCCESS )
                goto __npk_package_open_return_res_with_free;

            eb->owner_ = pb;
            memcpy( &eb->info_, pos, sizeof(NPK_ENTITYINFO) );
            pos += sizeof(NPK_ENTITYINFO);

            if( pb->info_.version_ < NPK_VERSION_STREAMABLE )
                if( eb->info_.offset_ >= pb->info_.entityInfoOffset_ )
                {
                    res = npk_error( NPK_ERROR_InvalidTeaKey );
                    goto __npk_package_open_return_res_with_free;
                }

            eb->newflag_ = eb->info_.flag_;
            eb->name_ = malloc( sizeof(NPK_CHAR)*(eb->info_.nameLength_+1) );
            if( !eb->name_ )
            {
                res = npk_error( NPK_ERROR_NotEnoughMemory );
                goto __npk_package_open_return_res_with_free;
            }
            eb->name_[eb->info_.nameLength_] = '\0';
            memcpy( eb->name_, pos, eb->info_.nameLength_ );
            pos += eb->info_.nameLength_;

            __npk_package_add_entity( pb, eb, false );
        }
        NPK_SAFE_FREE( entityheaderbuf );
    }
    else    // old style entity header
    {
        npk_seek( pb->handle_, (long)pb->info_.entityInfoOffset_+pb->offsetJump_, SEEK_SET );
        while( entityCount > 0 )
        {
            --entityCount;

            res = npk_entity_alloc( (NPK_ENTITY*)&eb );
            if( res != NPK_SUCCESS )
                goto __npk_package_open_return_res_with_free;

            eb->owner_ = pb;

            // read entity info
            if( pb->info_.version_ < NPK_VERSION_UNIXTIMESUPPORT )
            {
                res = npk_read_encrypt( teakey,
                                        pb->handle_,
                                        (void*)&oldinfo,
                                        sizeof(NPK_ENTITYINFO),
                                        g_callbackfp,
                                        NPK_PROCESSTYPE_ENTITYHEADER,
                                        g_callbackSize,
                                        filename,
                                        false,
                                        false );
                if( res != NPK_SUCCESS )
                    goto __npk_package_open_return_res_with_free;

                eb->info_.offset_ = oldinfo.offset_;
                eb->info_.size_ = oldinfo.size_;
                eb->info_.originalSize_ = oldinfo.originalSize_;
                eb->info_.flag_ = oldinfo.flag_;
                npk_filetime_to_unixtime( &oldinfo.modified_, &eb->info_.modified_ );
                eb->info_.nameLength_ = oldinfo.nameLength_;
            }
            else
            {
                res = npk_read_encrypt( teakey,
                                        pb->handle_,
                                        (void*)&eb->info_,
                                        sizeof(NPK_ENTITYINFO),
                                        g_callbackfp,
                                        NPK_PROCESSTYPE_ENTITYHEADER,
                                        g_callbackSize,
                                        filename,
                                        false,
                                        false );
                if( res != NPK_SUCCESS )
                    goto __npk_package_open_return_res_with_free;
            }

            if( eb->info_.offset_ >= pb->info_.entityInfoOffset_ )
            {
                res = npk_error( NPK_ERROR_InvalidTeaKey );
                goto __npk_package_open_return_res_with_free;
            }

            
            res = npk_read_encrypt( teakey,
                                    pb->handle_,
                                    (void*)buf,
                                    sizeof(char) * eb->info_.nameLength_,
                                    g_callbackfp,
                                    NPK_PROCESSTYPE_ENTITYHEADER,
                                    g_callbackSize,
                                    filename,
                                    false,
                                    false );
            if( res != NPK_SUCCESS )
                goto __npk_package_open_return_res_with_free;

            eb->newflag_ = eb->info_.flag_;

            // copy name into entity body
            buf[eb->info_.nameLength_] = '\0';
            res = npk_alloc_copy_string( &eb->name_, buf );
            if( res != NPK_SUCCESS )
                goto __npk_package_open_return_res_with_free;

            __npk_package_add_entity( pb, eb, false );
        }
    }
    return NPK_SUCCESS;

__npk_package_open_return_res_with_free:

    NPK_SAFE_FREE( eb );
    return res;
}
示例#24
0
NPK_RESULT npk_open( NPK_HANDLE* handle, NPK_CSTR fileName, bool createfile, bool bcheckexist )
{
    if(!__use_open)
    {
        if( createfile )
        {
#ifdef NPK_PLATFORM_WINDOWS
            if( bcheckexist )
            {
                *handle = open( fileName, O_CREAT | O_EXCL | O_RDWR | O_BINARY, S_IREAD | S_IWRITE );
            }
            else
            {
                *handle = creat( fileName, S_IREAD | S_IWRITE );
                if( errno == EACCES )
                    return( npk_error( NPK_ERROR_ReadOnlyFile ) );
                close( *handle );

                *handle = open( fileName, O_CREAT | O_RDWR | O_BINARY, S_IREAD | S_IWRITE );
            }
#else
            mode_t mask = umask(0);
            if( bcheckexist )
            {
                *handle = open( fileName, O_CREAT | O_EXCL | O_RDWR | O_BINARY, 0666 );
                if( *handle != -1 ) fchmod( *handle, 0666&~mask );
            }
            else
            {
                *handle = creat( fileName, S_IREAD | S_IWRITE );
                if( errno == EACCES )
                    return( npk_error( NPK_ERROR_ReadOnlyFile ) );
                close( *handle );

                *handle = open( fileName, O_CREAT | O_RDWR | O_BINARY, 0666 );
                if( *handle != -1 ) fchmod( *handle, 0666&~mask );
            }
            umask( mask );
#endif
        }
        else
            *handle = open( fileName, O_BINARY | O_RDONLY );

        if( *handle == -1 )
        {
            if( errno == ENOENT )
                return( npk_error( NPK_ERROR_FileNotFound ) );
            else if( errno == EEXIST )
                return( npk_error( NPK_ERROR_FileAlreadyExists ) );
            else
                return( npk_error( NPK_ERROR_FileOpenError ) );
        }
    }
    else
    {
        if( createfile )
            *handle = (NPK_HANDLE)__open( fileName, "wb+" );
        else
            *handle = (NPK_HANDLE)__open( fileName, "rb+" );

        if( *handle == -1 )
        {
            if( errno == ENOENT )
                return( npk_error( NPK_ERROR_FileNotFound ) );
            else if( errno == EEXIST )
                return( npk_error( NPK_ERROR_FileAlreadyExists ) );
            else
                return( npk_error( NPK_ERROR_FileOpenError ) );
        }
    }

    return NPK_SUCCESS;
}