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 );
}
Exemplo n.º 2
0
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;
}