📄 arc_vfs.cpp
字号:
/*************************************************************************** arc_vfs.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/#include <unistd.h>#include <sys/param.h>#include <sys/types.h>#include <dirent.h>#include <time.h>// QT includes#include <qregexp.h>#include <qdir.h>#include <qdatetime.h>#include <qfileinfo.h>// KDE includes#include <kmessagebox.h>#include <klocale.h>#include <kprocess.h>#include <kio/jobclasses.h>#include <qprogressdialog.h>#include <kglobalsettings.h>#include <kmimetype.h>#include <kcursor.h>#include <klargefile.h>// krusader includes#include "arc_vfs.h"#include "krpermhandler.h"#include "krarchandler.h"#include "../krusader.h"#include "../defaults.h"#include "../resources.h"#include "../Dialogs/krdialogs.h"#define MAX_FILES 500//constructorarc_vfs::arc_vfs(QString origin,QString type,QObject* panel,bool write): vfs(panel),arcFile(origin),changed(false),prefix(""),ignoreLines(0){ if ( type == "tarz" ) type = "-tgz"; // set the cursor to busy mode if (!quietMode) krApp->setCursor(KCursor::waitCursor()); // set the writable attribute isWritable = KRpermHandler::fileWriteable(origin); isWritable = ( write && isWritable ); vfs_type = vfs::ERROR; // create the temp dir.. tmpDir = krApp->getTempDir(); if( tmpDir.isEmpty() ){ error = true; return; } QString password = QString::null; krConfig->setGroup("Archives"); // fill the command options if( type == "gzip" ){ cmd = KrServices::fullPathName ( "gzip" ); listCmd = "-l"; delCmd = ""; addCmd = KrServices::fullPathName ( "gzip" ) + " -c"; getCmd = "-dc"; ignoreLines = -1; isWritable = false; } if(type == "zip2"){ cmd = KrServices::fullPathName( "bzip2" ); listCmd = ""; delCmd = ""; addCmd = KrServices::fullPathName( "bzip2" )+ " -c"; getCmd = "-dc"; ignoreLines = -1; isWritable = false; } if(type == "-tar"){ cmd = KrServices::fullPathName( "tar" ); listCmd = " -tvf"; delCmd = cmd+" --delete -vf"; addCmd = cmd+" -uvf"; getCmd = " -xvf"; } if(type == "-tgz"){ cmd = KrServices::fullPathName( "tar" ); listCmd = " -tzvf"; delCmd = ""; addCmd = cmd+" -uvzf"; getCmd = " -xzvf"; isWritable = false; } if(type == "-tbz"){ cmd = KrServices::fullPathName( "tar" ); listCmd = " -tjvf"; delCmd = ""; addCmd = cmd+" -uvjf"; getCmd = " -xjvf"; isWritable = false; } if(type == "-zip"){ password = KRarcHandler::getPassword(arcFile,type); cmd = KrServices::fullPathName( "unzip" ); listCmd = "-ZTs "; QString zipcmd = KrServices::fullPathName( "zip" ); delCmd = zipcmd+" -d"; addCmd = zipcmd+" -ry"; getCmd = " -o"; if( !password.isEmpty() ){ //listCmd = listCmd + " -P "+password; delCmd = delCmd + " -P "+password; addCmd = addCmd + " -P "+password; getCmd = getCmd + " -P "+password; } ignoreLines = 1; } // "-rpm" is used only to list the rpm - to extract files use "+rpm" if(type == "-rpm"){ //rpm can't handle files with " " in them so replace " " with "\ " arcFile.replace(QRegExp(" "),"\\ "); cmd = KrServices::fullPathName( "rpm" ); listCmd = " --dump -lpq "; delCmd = ""; addCmd = ""; getCmd = ""; isWritable = false; } if( type == "+rpm" ){ // extract the cpio archive from the rpm KShellProcess rpm; rpm << "rpm2cpio"<<"\""+arcFile+"\""+" > "+tmpDir+"/contents.cpio"; rpm.start(KProcess::Block); arcFile = tmpDir+"/contents.cpio"; } if(type == "cpio" || type == "+rpm" ){ cmd = KrServices::fullPathName( "cpio" ); listCmd = "-tvF "; delCmd = ""; addCmd = ""; getCmd = " --force-local --no-absolute-filenames -ivdF"; isWritable = false; } if(type == "-rar"){ bool doRar = krConfig->readBoolEntry("Do Rar",_DoRar); cmd = KrServices::fullPathName( "unrar" ); listCmd = " -c- v "; delCmd = ""; addCmd = (doRar ? QString(KrServices::fullPathName( "rar" ) + " -r a ") : QString("")) ; getCmd = " x -y "; ignoreLines = 8; isWritable = (doRar && isWritable ); } getDirs(); // set the cursor to normal mode if (!quietMode) krApp->setCursor(KCursor::arrowCursor());}// return the working dirQString arc_vfs::vfs_workingDir(){ // get the path inside the archive QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1); if(path.left(1) != "/") path = "/"+path; QDir().mkdir(tmpDir+path); return tmpDir+path;}arc_vfs::~arc_vfs(){ // set the cursor to busy mode if (!quietMode) krApp->setCursor(KCursor::waitCursor()); // don't touch messed-up archives if(!error) repack(); // delete the temp dir KShellProcess proc; proc<<"rm"<<"-rf"<<tmpDir; proc.start(KProcess::Block); // set the cursor to normal mode if (!quietMode) krApp->setCursor(KCursor::arrowCursor());} bool arc_vfs::getDirs(){ if( !listCmd.isEmpty() ){ // write the temp file KShellProcess proc; proc << cmd << listCmd << "\""+arcFile+"\"" <<" > " << tmpDir+"/tempfilelist"; proc.start(KProcess::Block); if( !proc.normalExit() || !proc.exitStatus() == 0 ){ if (!quietMode) KMessageBox::error(krApp, i18n("<qt>Can't read <b>%1</b>. Archive " "might be corrupted!</qt>").arg(arcFile.mid(arcFile.findRev('/')+1))); error = true; return false; } // clear the dir list dirList.clear(); // prepare the first dir entry - the "" entry arc_dir *tempdir = new arc_dir(""); vfs_filesP = &(tempdir->entries); dirList.append(tempdir); // parse the temp file QFile temp(tmpDir+"/tempfilelist"); temp.open(IO_ReadOnly); char buf[1000]; QString line; if(vfs_type == "gzip" || vfs_type == "-zip" ) temp.readLine(line,10000); // skip the first line - it's garbage if( vfs_type == "-rar" ){ while(temp.readLine(line,10000) != -1) if ( line.contains("----------") ) break; } while(temp.readLine(buf,1000) != -1){ line = QString::fromLocal8Bit(buf); if ( line.contains("----------") ) break; parseLine(line.stripWhiteSpace(),&temp); } temp.close(); QDir().remove(tmpDir+"/tempfilelist"); } else { // bzip2 // clear the dir list dirList.clear(); // prepare the first dir entry - the "" entry arc_dir *tempdir = new arc_dir(""); vfs_filesP = &(tempdir->entries); dirList.append(tempdir); parseLine("",0); } return true;}// copy a file to the vfs (physical)void arc_vfs::vfs_addFiles(KURL::List *fileUrls,KIO::CopyJob::CopyMode mode,QObject* toNotify,QString dir, PreserveMode /*pmode*/ ){ if ( addCmd.isEmpty() ) return; // get the path inside the archive QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1); path = path+"/"; if(dir != "" ) dir = "/"+dir; if(path.left(1) != "/") path = "/"+path; // make sure the destination exist for( int i=0; i >= 0 ; i= QString(tmpDir+path+dir).find('/',i+1) ){ QDir().mkdir(QString(tmpDir+path+dir).left(i)); } changed = true; //rescan the archive KURL dest; dest.setPath(tmpDir+path+dir); KIO::Job* job = new KIO::CopyJob(*fileUrls,dest,mode,false,true); connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(vfs_refresh(KIO::Job*)) ); if(mode == KIO::CopyJob::Move) // notify the other panel connect(job,SIGNAL(result(KIO::Job*)),toNotify,SLOT(vfs_refresh(KIO::Job*)) );} // remove a file from the vfs (physical)void arc_vfs::vfs_delFiles(QStringList *fileNames){ if ( delCmd.isEmpty() ) return; // if we move to trash - just extract files and move them to trash - // the repack() will delete them for us krConfig->setGroup("General"); if( krConfig->readBoolEntry("Move To Trash",_MoveToTrash) ) { KURL::List* filesUrls = vfs_getFiles(fileNames); // extract changed = true; KIO::Job *job = new KIO::CopyJob(*filesUrls,KGlobalSettings::trashPath(),KIO::CopyJob::Move,false,true ); connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(vfs_refresh(KIO::Job*))); } // else we have to delete the files from both the archive and the temp dir else { // change dir to the temp dir QString save = getcwd(0,0); chdir(tmpDir.local8Bit()); QStringList files; KIO::filesize_t totalSizeVal = 0; unsigned long totalFilesVal = 0; // names -> urls for(QStringList::Iterator name = fileNames->begin(); name != fileNames->end(); ++name ) processName(*name,&files,&totalSizeVal,&totalFilesVal); KShellProcess proc1 , proc2; krApp->startWaiting(i18n("Deleting Files..."),files.count()+ignoreLines); connect(&proc1,SIGNAL(receivedStdout(KProcess*,char*,int)), krApp, SLOT(incProgress(KProcess*,char*,int)) ); proc1 << delCmd << "\""+arcFile+"\""; proc2 << "rm -rf"; for(unsigned int i =0; i < files.count(); ){ proc1 << (prefix+*files.at(i)); proc2 << tmpDir+"/"+(*files.at(i)); extFiles.remove(*files.at(i++)); if ( i%MAX_FILES==0 || i==files.count() ){ proc1.start(KProcess::NotifyOnExit,KProcess::AllOutput); proc2.start(); while( proc1.isRunning() || proc2.isRunning() ) qApp->processEvents(); // busy wait - need to find something better... proc1.clearArguments() ; proc2.clearArguments(); proc1 << delCmd << "\""+arcFile+"\""; proc2 << "rm -rf"; } } krApp->stopWait(); changed = true; chdir (save.local8Bit()); vfs_refresh(vfs_origin); }} // return a path to the fileQString arc_vfs::vfs_getFile(QString name){ // get the current file path QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1); if(path.left(1)=="/") path.remove(0,1); if(path != "") path = path+"/"; QStringList temp(name); vfs_getFiles(&temp); return tmpDir+"/"+path+name;}KURL::List* arc_vfs::vfs_getFiles(QStringList* names){ KURL url; KURL::List* urls = new KURL::List(); // get the current file path QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1); if(path.left(1)=="/") path.remove(0,1); if(path != "") path = path+"/"; // change dir to the temp dir QString save = getcwd(0,0); chdir(tmpDir.local8Bit()); // names -> urls QStringList files; KIO::filesize_t totalSize = 0; unsigned long totalFiles = 0; for(QStringList::Iterator name = names->begin(); name != names->end(); ++name ){ processName(*name,&files,&totalSize,&totalFiles); url.setPath(tmpDir+"/"+path+(*name)); urls->append(url); } // check the urls for unpacked files and directories for(QStringList::Iterator file = files.begin(); file != files.end(); ++file ){ if ( (*file).right(1)=="/" ){ QDir(tmpDir).mkdir(*file); if( vfs_type == "-rar" ) file = files.remove(file--); } // don't unpack the same file twice else if( extFiles.contains(*file) ){ file = files.remove(file--); } } // unpack ( if needed ) if ( files.count() > 0 ){ krApp->startWaiting(i18n("Unpacking Files"),files.count()+ignoreLines); KShellProcess proc; connect(&proc,SIGNAL(receivedStdout(KProcess*,char*,int)), krApp, SLOT(incProgress(KProcess*,char*,int)) ); proc << cmd << getCmd << "\""+arcFile+"\""; if( vfs_type == "gzip" || vfs_type == "zip2" ) proc << ">"; for(unsigned int i=0 ; i < files.count() ; ){ proc << (prefix+*files.at(i++)); if ( i%MAX_FILES==0 || i==files.count() ){ proc.start(KProcess::NotifyOnExit,KProcess::AllOutput); while( proc.isRunning() ) qApp->processEvents(); proc.clearArguments(); proc << cmd << getCmd << "\""+arcFile+"\""; } } getExtFiles(); // this will update the extFiles list. krApp->stopWait(); } // restore dir chdir(save.local8Bit()); return urls;}// make dirvoid arc_vfs::vfs_mkdir(QString name){ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1); if(path.left(1)=="/") path.remove(0,1); if(path != "") path = path+"/"; QDir(tmpDir).mkdir(path+name); changed = true; //rescan the archive vfs_refresh(vfs_origin);} // rename filevoid arc_vfs::vfs_rename(QString fileName,QString newName){ KURL::List temp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -