clPtr<FS> clArchPlugin::OpenFS( clPtr<FS> Fs, FSPath& Path ) const { FSString Uri = Fs->Uri( Path ); struct archive* Arch = ArchOpen( Uri.GetUtf8() ); if ( Arch == nullptr ) { return nullptr; } FSArchNode RootDir; RootDir.fsStat.mode = S_IFDIR; FSPath NodePath; struct archive_entry* entry = archive_entry_new2( Arch ); int Res; while ( ( Res = archive_read_next_header2( Arch, entry ) ) == ARCHIVE_OK ) { NodePath.Set( CS_UTF8, archive_entry_pathname( entry ) ); FSString* ItemName = NodePath.GetItem( NodePath.Count() - 1 ); if ( NodePath.Count() == 1 && ( ItemName->IsDot() || ItemName->IsEmpty() ) ) { // skip root dir continue; } const mode_t Mode = archive_entry_mode( entry ); const int64_t Size = archive_entry_size( entry ); RootDir.entryOffset += Size; FSStat ItemStat; ItemStat.mode = S_ISREG( Mode ) ? Mode : S_IFDIR; ItemStat.size = Size; ItemStat.m_CreationTime = archive_entry_ctime( entry ); ItemStat.m_LastAccessTime = archive_entry_atime( entry ); ItemStat.m_LastWriteTime = archive_entry_mtime( entry ); ItemStat.m_ChangeTime = ItemStat.m_LastWriteTime; FSArchNode* Dir = ArchGetParentDir( &RootDir, NodePath, ItemStat ); FSArchNode* Item = Dir->Add( FSArchNode( ItemName->GetUtf8(), ItemStat ) ); if (Item) { Item->entryOffset = archive_read_header_position( Arch ); } } if ( Res != ARCHIVE_EOF ) { dbg_printf( "Couldn't read archive entry: %s\n", archive_error_string( Arch ) ); } archive_entry_free( entry ); ArchClose( Arch ); return new FSArch( RootDir, Uri ); }
extern "C" bool ArchCreateFromFolderA(char *lpstrZipFile,char *sourceFolder,LPSTR *fileMask,DWORD fileMaskCount,DWORD flags,char *lpPassword,int dwPasswordLen,int dwCompLevel) { HZIP hZip=CreateArchiveA(lpstrZipFile,lpPassword,dwPasswordLen,dwCompLevel); bool r=false; if (hZip) { r=ArchiveFolderA(hZip,sourceFolder,fileMask,fileMaskCount,flags); ArchClose(hZip); } return r; }
int FSArch::Close( int fd, int* err, FSCInfo* info ) { dbg_printf( "FSArch::Close\n" ); auto iter = m_OpenFiles.find( fd ); if ( iter != m_OpenFiles.end() ) { struct archive* Arch = iter->second; ArchClose( Arch ); } return 0; }
int FSArch::OpenRead( FSPath& path, int flags, int* err, FSCInfo* info ) { dbg_printf( "FSArch::Open\n" ); FSArchNode* Node = m_RootDir.findByFsPath( path ); if ( Node == nullptr ) { FS::SetError( err, FSARCH_ERROR_FILE_NOT_FOUND ); return -1; } struct archive* Arch = ArchOpen( m_Uri.GetUtf8() ); if ( Arch == nullptr ) { FS::SetError( err, FSARCH_ERROR_FILE_NOT_FOUND ); return -1; } struct archive_entry* entry = archive_entry_new2( Arch ); int Res; // seek to the entry while ( ( Res = archive_read_next_header2( Arch, entry ) ) == ARCHIVE_OK ) { int64_t EntryOffset = archive_read_header_position( Arch ); if ( EntryOffset == Node->entryOffset ) { break; } } archive_entry_free( entry ); if ( Res != ARCHIVE_OK ) { ArchClose( Arch ); dbg_printf( "Couldn't read archive entry: %s\n", archive_error_string( Arch ) ); FS::SetError( err, FSARCH_ERROR_FILE_NOT_FOUND ); return -1; } const int fd = g_NextArchFD++; m_OpenFiles[ fd ] = Arch; return fd; }
struct archive* ArchOpen( const char* FileName ) { struct archive* Arch = archive_read_new(); if ( Arch != nullptr ) { int Res = archive_read_support_filter_all( Arch ); if ( Res == ARCHIVE_OK ) { Res = archive_read_support_format_all( Arch ); if ( Res == ARCHIVE_OK ) { Res = archive_read_open_filename( Arch, FileName, 10240 ); if ( Res == ARCHIVE_OK ) { return Arch; } dbg_printf( "Couldn't open input archive: %s\n", archive_error_string( Arch ) ); } else { dbg_printf( "Couldn't enable read formats\n" ); } } else { dbg_printf( "Couldn't enable decompression\n" ); } } else { dbg_printf( "Couldn't create archive reader\n" ); } ArchClose( Arch ); return nullptr; }