diff options
Diffstat (limited to 'util/install/archive/qarchive.cpp')
-rw-r--r-- | util/install/archive/qarchive.cpp | 471 |
1 files changed, 0 insertions, 471 deletions
diff --git a/util/install/archive/qarchive.cpp b/util/install/archive/qarchive.cpp deleted file mode 100644 index dd51c65..0000000 --- a/util/install/archive/qarchive.cpp +++ /dev/null @@ -1,471 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the utils of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "qarchive.h" -#include <qdatastream.h> -#include <qfileinfo.h> -#include <qdir.h> -#include <qapplication.h> -#include "../../../src/3rdparty/zlib/zlib.h" -#include "../keygen/keyinfo.h" -#ifdef Q_OS_UNIX -# include <sys/stat.h> -# include <unistd.h> -# include <sys/types.h> -# include <utime.h> -#endif - -enum ChunkType { - ChunkDirectory = 0, - ChunkFile = 1, - ChunkSymlink = 2, - ChunkBeginHeader = 3, - ChunkEndHeader = 4 -}; - -static bool createDir( const QString& fullPath ) -{ - QStringList hierarchy = QStringList::split( QDir::separator(), fullPath ); - QString pathComponent, tmpPath; - QDir dirTmp; -#ifdef Q_OS_UNIX - dirTmp = "/"; -#endif - - for( QStringList::Iterator it = hierarchy.begin(); it != hierarchy.end(); ++it ) { - pathComponent = *it + QDir::separator(); - tmpPath += pathComponent; - if (!dirTmp.exists(tmpPath) && !dirTmp.mkdir(tmpPath)) - return false; - } - return true; -} - -QArchive::QArchive( const QString& archivePath ) -{ - setPath( archivePath ); - - bufferSize = 512 * 1024; -} - -QArchive::~QArchive() -{ -} - -void QArchive::setPath( const QString& archivePath ) -{ - QString fullName = archivePath; - if( fullName.right( 4 ) != ".arq" ) - fullName += ".arq"; - arcFile.setName( fullName ); -} - -bool QArchive::open( int mode ) -{ - switch( mode ) { - case IO_ReadOnly: - // Fallthrough intentional - case IO_WriteOnly: - if( arcFile.open( mode ) ) - return true; - break; - } - return false; -} - -void QArchive::close() -{ - if( arcFile.isOpen() ) - arcFile.close(); -} - -bool QArchive::writeFile( const QString& fileName, const QString& localPath ) -{ - if( arcFile.isOpen() ) { - QDataStream outStream( &arcFile ); - QFileInfo fi( fileName ); - - QFile inFile( fi.absFilePath() ); - QByteArray inBuffer; - QByteArray outBuffer( bufferSize ); - z_stream ztream; - bool continueCompressing; - - if(symbolicLinks() && fi.isSymLink()) { - outStream << (int)ChunkSymlink; - outStream << fi.fileName().latin1(); - outStream << fi.readLink().latin1(); - } else if( inFile.open( IO_ReadOnly ) ) { - if( inBuffer.resize( fi.size() ) ) { - outStream << (int)ChunkFile; - outStream << fi.fileName().latin1(); - outStream << fi.lastModified(); - { - int perm = -1; -#ifdef Q_OS_UNIX - struct stat st; - if(!::stat(fi.filePath().latin1(), &st)) - perm = (int)st.st_mode; -#endif - outStream << perm; - } - if( verbosityMode & Source ) - emit operationFeedback( "Deflating " + fi.absFilePath() + "..." ); - else if( verbosityMode & Destination ) - emit operationFeedback( "Deflating " + localPath + "/" + fi.fileName() + "..." ); - ztream.next_in = (unsigned char*)inBuffer.data(); - ztream.avail_in = inBuffer.size(); - ztream.total_in = 0; - ztream.next_out = (unsigned char*)outBuffer.data(); - ztream.avail_out = outBuffer.size(); - ztream.total_out = 0; - ztream.msg = NULL; - ztream.zalloc = (alloc_func)NULL; - ztream.zfree = (free_func)NULL; - ztream.opaque = (voidpf)NULL; - ztream.data_type = Z_BINARY; - deflateInit( &ztream, 9 ); - if ( inBuffer.data() ) - inFile.readBlock( inBuffer.data(), inBuffer.size() ); - - continueCompressing = true; - while( continueCompressing ) { - if(qApp) - qApp->processEvents(); - continueCompressing = ( deflate( &ztream, Z_FINISH ) == Z_OK ); - if( !ztream.avail_out ) { - if( !outBuffer.resize( outBuffer.size() + bufferSize ) ) - qFatal( "Could not allocate compression buffer!" ); - ztream.next_out = (unsigned char*)&outBuffer.data()[ ztream.total_out ]; - ztream.avail_out = bufferSize; - } - } - - emit operationFeedback( QString( "done. %1 => %2 (%3%)\n" ) - .arg( ztream.total_in ) - .arg( ztream.total_out ) - .arg( int( - double( ztream.total_out ) / double( ztream.total_in ) * 100 ) ) ); - deflateEnd( &ztream ); - // Now write the compressed data to the output - outStream << ztream.total_out; - outStream.writeRawBytes( outBuffer.data(), ztream.total_out ); - } - inFile.close(); - return true; - } else { - return false; - } - } - return false; -} - -bool QArchive::setDirectory( const QString& dirName ) -{ - if( arcFile.isOpen() ) { - QString fullName = dirName; - QDataStream outStream( &arcFile ); - if( fullName.right( 1 ) != "/" ) - fullName += "/"; - outStream << (int)ChunkDirectory; - outStream << fullName.latin1(); - return true; - } - return false; -} - -bool QArchive::writeHeader( const QArchiveHeader header ) -{ - if( arcFile.isOpen() ) { - QDataStream outStream( &arcFile ); - outStream << (int)ChunkBeginHeader; - outStream << header.mayorVersion(); - outStream << header.minorVersion(); - outStream << header.features(); - outStream << header.description(); - outStream << header.extraData; - outStream << (int)ChunkEndHeader; - return true; - } - return false; -} - -bool QArchive::writeDir( const QString &dirName1, bool includeLastComponent, const QString &localPath1 ) -{ - if( arcFile.isOpen() ) { - QString localPath = localPath1, dirName = dirName1; - if(localPath.right(1) == "/") - localPath.truncate(localPath.length()-1); - if(dirName.right(1) == "/") - dirName.truncate(dirName.length()-1); - - QFileInfo fi( dirName ); - - if( includeLastComponent ) - setDirectory( fi.fileName() ); - QDir dir( dirName ); - const QFileInfoList* dirEntries = dir.entryInfoList(); - QFileInfoListIterator dirIter( *dirEntries ); - QDataStream outStream( &arcFile ); - QFileInfo* pFi; - - dirIter.toLast(); - while( ( pFi = dirIter.current() ) ) { - if( pFi->fileName() != "." && pFi->fileName() != ".." ) { - if( pFi->isDir() ) - writeDir( pFi->absFilePath(), true, localPath + "/" + - pFi->fileName() ); // Subdirs should always get its name in the archive. - else - writeFile( pFi->absFilePath(), localPath ); - } - --dirIter; - } - setDirectory( ".." ); - return true; - } - return false; -} - -bool QArchive::writeFileList( const QStringList fileList ) -{ - for( QStringList::ConstIterator it = fileList.begin(); it != fileList.end(); ++it ) { - if( !writeFile( (*it) ) ) - return false; - } - return true; -} - -bool QArchive::writeDirList( const QStringList dirList, bool includeLastComponent ) -{ - for( QStringList::ConstIterator it = dirList.begin(); it != dirList.end(); ++it ) { - QString lastComponent = (*it).mid( (*it).findRev( "/" ) + 1 ); - if( !writeDir( (*it), includeLastComponent, lastComponent ) ) - return false; - } - return true; -} - -void QArchive::setVerbosity( int verbosity ) -{ - verbosityMode = verbosity; -} - -QArchiveHeader* QArchive::readArchiveHeader() -{ - QDataStream inStream( &arcFile ); - return readArchiveHeader( &inStream ); -} - -/* - Reads the archive header and returns it on success. If an error occurs, it - returns 0. The caller has to delete the object. -*/ -QArchiveHeader* QArchive::readArchiveHeader( QDataStream *inStream ) -{ - int chunktype; - QArchiveHeader *header = new QArchiveHeader; - - *inStream >> chunktype; - if( chunktype == ChunkBeginHeader ) { - *inStream >> header->_mayorVersion; - *inStream >> header->_minorVersion; - if ( header->mayorVersion()!=1 || header->minorVersion()!=0 ) { - emit operationFeedback( "Incompatible package version" ); - delete header; - return 0; - } - *inStream >> header->_features; - *inStream >> header->_description; - *inStream >> header->extraData; - *inStream >> chunktype; - if ( chunktype != ChunkEndHeader ) { - emit operationFeedback( "Invalid package header" ); - delete header; - return 0; - } - } else { - emit operationFeedback( "No package header found." ); - delete header; - return 0; - } - return header; -} - -bool QArchive::readArchive( const QString &outpath, const QString &key ) -{ - QDataStream inStream( &arcFile ); - return readArchive( &inStream, outpath, key ); -} - -bool QArchive::readArchive( QDataStream *inStream, const QString &outpath, const QString &key ) -{ - QDataStream outStream; - QFile outFile; - QDir outDir; - QByteArray inBuffer; - QByteArray outBuffer( bufferSize ); - z_stream ztream; - bool continueDeCompressing; - QString entryName, dirName, symName; - int entryLength, chunktype; - - //get the key - QArchiveHeader *header = readArchiveHeader( inStream ); - if ( header == 0 ) - return false; - uint infeatures = featuresForKey( key ); - if( (header->features() & infeatures) != header->features()) { - emit operationFeedback( "Invalid key" ); - return false; - } - - // Set up the initial directory. - // If the dir does not exist, try to create it - dirName = QDir::toNativeSeparators( outpath ); - outDir.setPath( dirName ); - if( !outDir.exists( dirName ) && !createDir( dirName ) ) - return false; - outDir.cd( dirName ); - - while( !inStream->atEnd() ) { - //get our type - *inStream >> chunktype; - if(chunktype == ChunkDirectory) { - *inStream >> entryLength; - inBuffer.resize( entryLength ); - inStream->readRawBytes( inBuffer.data(), entryLength ); - entryName = inBuffer.data(); - - if( verbosityMode & Source ) - emit operationFeedback( "Directory " + entryName + "... " ); - if( entryName == "../" ) { - outDir.cdUp(); - } else { - dirName = QDir::toNativeSeparators( outDir.absPath() + - QString( "/" ) + entryName.left( entryName.length() - 1 ) ); - if( verbosityMode & Destination ) - emit operationFeedback( "Directory " + dirName + "... " ); - - if( !outDir.exists( dirName ) && !createDir( dirName ) ) { - emit operationFeedback( "Cannot create directory: " + dirName ); - return false; - } - outDir.cd( dirName ); - } - } else if(chunktype == ChunkFile) { - *inStream >> entryLength; - inBuffer.resize( entryLength ); - inStream->readRawBytes( inBuffer.data(), entryLength ); - entryName = inBuffer.data(); - - int filePerm; - QDateTime timeStamp; - QString fileName = QDir::toNativeSeparators( outDir.absPath() + QString( "/" ) + entryName ); - outFile.setName( fileName ); - if( outFile.open( IO_WriteOnly ) ) { - *inStream >> timeStamp; // Get timestamp from the archive - *inStream >> filePerm; - outStream.setDevice( &outFile ); - *inStream >> entryLength; - if( verbosityMode & Source ) - emit operationFeedback( "Expanding " + entryName + "..." ); - else if( verbosityMode & Destination ) - emit operationFeedback( "Expanding " + fileName + "..." ); - inBuffer.resize( entryLength ); - inStream->readRawBytes( inBuffer.data(), entryLength ); - ztream.next_in = (unsigned char*)inBuffer.data(); - ztream.avail_in = entryLength; - ztream.total_in = 0; - ztream.msg = NULL; - ztream.zalloc = (alloc_func)0; - ztream.zfree = (free_func)0; - ztream.opaque = (voidpf)0; - ztream.data_type = Z_BINARY; - inflateInit( &ztream ); - continueDeCompressing = true; - while( continueDeCompressing ) { - ztream.next_out = (unsigned char*)outBuffer.data(); - ztream.avail_out = outBuffer.size(); - ztream.total_out = 0; - continueDeCompressing = ( inflate( &ztream, Z_NO_FLUSH ) == Z_OK ); - outStream.writeRawBytes( outBuffer.data(), ztream.total_out ); - } - inflateEnd( &ztream ); - outFile.close(); -#ifdef Q_OS_UNIX - QDateTime t; t.setTime_t(0); //epoch - struct utimbuf tb; - tb.actime = tb.modtime = t.secsTo(timeStamp); - utime(fileName.local8Bit(), &tb); - if(filePerm != -1) - chmod(fileName.local8Bit(), (mode_t)filePerm); -#endif - } else { - emit operationFeedback( "Cannot open: " + fileName ); - return false; - } - } else if(chunktype == ChunkSymlink) { - *inStream >> entryLength; - inBuffer.resize( entryLength ); - inStream->readRawBytes( inBuffer.data(), entryLength ); - entryName = inBuffer.data(); - QString fileName = QDir::toNativeSeparators( outDir.absPath() + QString( "/" ) + entryName ); - - *inStream >> entryLength; - inBuffer.resize( entryLength ); - inStream->readRawBytes( inBuffer.data(), entryLength ); - symName = inBuffer.data(); - if( verbosityMode & Source ) - emit operationFeedback( "Linking " + symName + "... " ); - else if( verbosityMode & Destination ) - emit operationFeedback( "Linking " + fileName + "... " ); -#ifdef Q_OS_UNIX - symlink( symName.local8Bit(), fileName.local8Bit() ); -#endif - } else { - if( verbosityMode & Source ) - emit operationFeedback( QString("Unknown chunk: %d") .arg(chunktype) ); - } - if( verbosityMode & Progress ) - emit operationFeedback( inStream->device()->at() ); - } - return true; -} - |