FSArchNode* ArchGetParentDir( FSArchNode* CurrDir, FSPath& ItemPath, const FSStat& ItemStat ) { for ( int i = 0; i < ItemPath.Count() - 1; i++ ) { FSString* Name = ItemPath.GetItem( i ); if ( i == 0 && ( Name->IsDot() || Name->IsEmpty() ) ) { // skip root dir continue; } FSArchNode* Dir = CurrDir->findByName( *Name ); if ( Dir == nullptr ) { FSStat Stat = ItemStat; Stat.mode = S_IFDIR; Stat.size = 0; Dir = CurrDir->Add( FSArchNode( Name->GetUtf8(), Stat ) ); } CurrDir = Dir; } return CurrDir; }
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 ); }
bool ParzeLink( FSPath& path, FSString& link ) { FSPath t( link ); if ( !path.IsAbsolute() && !t.IsAbsolute() ) { return false; } //не абсолютный путь int first = 0; if ( t.IsAbsolute() ) { path.Clear(); path.PushStr( FSString( "" ) ); first = 1; } for ( int i = first; i < t.Count(); i++ ) { FSString p = *( t.GetItem( i ) ); if ( p.IsDot() ) { continue; } if ( p.Is2Dot() ) { if ( path.Count() > 1 ) { path.Pop(); } } else { path.PushStr( p ); } } return true; }