You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
krusader/krusader/VFS/arc_vfs.cpp

867 lines
27 KiB

/***************************************************************************
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 <tqregexp.h>
#include <tqdir.h>
#include <tqdatetime.h>
#include <tqfileinfo.h>
// KDE includes
#include <tdemessagebox.h>
#include <tdelocale.h>
#include <kprocess.h>
#include <tdeio/jobclasses.h>
#include <tqprogressdialog.h>
#include <tdeglobalsettings.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
//constructor
arc_vfs::arc_vfs(TQString origin,TQString type,TQObject* 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;
}
TQString password = TQString();
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 ";
TQString 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(TQRegExp(" "),"\\ ");
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(TDEProcess::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 ? TQString(KrServices::fullPathName( "rar" ) + " -r a ") : TQString("")) ;
getCmd = " x -y ";
ignoreLines = 8;
isWritable = (doRar && isWritable );
}
getDirs();
// set the cursor to normal mode
if (!quietMode) krApp->setCursor(KCursor::arrowCursor());
}
// return the working dir
TQString arc_vfs::vfs_workingDir(){
// get the path inside the archive
TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
if(path.left(1) != "/") path = "/"+path;
TQDir().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(TDEProcess::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(TDEProcess::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
TQFile temp(tmpDir+"/tempfilelist");
temp.open(IO_ReadOnly);
char buf[1000];
TQString 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 = TQString::fromLocal8Bit(buf);
if ( line.contains("----------") ) break;
parseLine(line.stripWhiteSpace(),&temp);
}
temp.close();
TQDir().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,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir, PreserveMode /*pmode*/ ){
if ( addCmd.isEmpty() ) return;
// get the path inside the archive
TQString 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= TQString(tmpDir+path+dir).find('/',i+1) ){
TQDir().mkdir(TQString(tmpDir+path+dir).left(i));
}
changed = true; //rescan the archive
KURL dest;
dest.setPath(tmpDir+path+dir);
TDEIO::Job* job = new TDEIO::CopyJob(*fileUrls,dest,mode,false,true);
connect(job,TQT_SIGNAL(result(TDEIO::Job*)),this,TQT_SLOT(vfs_refresh(TDEIO::Job*)) );
if(mode == TDEIO::CopyJob::Move) // notify the other panel
connect(job,TQT_SIGNAL(result(TDEIO::Job*)),toNotify,TQT_SLOT(vfs_refresh(TDEIO::Job*)) );
}
// remove a file from the vfs (physical)
void arc_vfs::vfs_delFiles(TQStringList *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;
TDEIO::Job *job = new TDEIO::CopyJob(*filesUrls,TDEGlobalSettings::trashPath(),TDEIO::CopyJob::Move,false,true );
connect(job,TQT_SIGNAL(result(TDEIO::Job*)),this,TQT_SLOT(vfs_refresh(TDEIO::Job*)));
}
// else we have to delete the files from both the archive and the temp dir
else {
// change dir to the temp dir
TQString save = getcwd(0,0);
chdir(tmpDir.local8Bit());
TQStringList files;
TDEIO::filesize_t totalSizeVal = 0;
unsigned long totalFilesVal = 0;
// names -> urls
for(TQStringList::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,TQT_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
krApp, TQT_SLOT(incProgress(TDEProcess*,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(TDEProcess::NotifyOnExit,TDEProcess::AllOutput);
proc2.start();
while( proc1.isRunning() || proc2.isRunning() ) tqApp->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 file
TQString arc_vfs::vfs_getFile(TQString name){
// get the current file path
TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
if(path.left(1)=="/") path.remove(0,1);
if(path != "") path = path+"/";
TQStringList temp(name);
vfs_getFiles(&temp);
return tmpDir+"/"+path+name;
}
KURL::List* arc_vfs::vfs_getFiles(TQStringList* names){
KURL url;
KURL::List* urls = new KURL::List();
// get the current file path
TQString 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
TQString save = getcwd(0,0);
chdir(tmpDir.local8Bit());
// names -> urls
TQStringList files;
TDEIO::filesize_t totalSize = 0;
unsigned long totalFiles = 0;
for(TQStringList::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(TQStringList::Iterator file = files.begin(); file != files.end(); ++file ){
if ( (*file).right(1)=="/" ){
TQDir(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,TQT_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
krApp, TQT_SLOT(incProgress(TDEProcess*,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(TDEProcess::NotifyOnExit,TDEProcess::AllOutput);
while( proc.isRunning() ) tqApp->processEvents();
proc.clearArguments();
proc << cmd << getCmd << "\""+arcFile+"\"";
}
}
getExtFiles(); // this will update the extFiles list.
krApp->stopWait();
}
// restore dir
chdir(save.local8Bit());
return urls;
}
// make dir
void arc_vfs::vfs_mkdir(TQString name){
TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
if(path.left(1)=="/") path.remove(0,1);
if(path != "") path = path+"/";
TQDir(tmpDir).mkdir(path+name);
changed = true; //rescan the archive
vfs_refresh(vfs_origin);
}
// rename file
void arc_vfs::vfs_rename(TQString fileName,TQString newName){
KURL::List temp;
temp.append(vfs_getFile(fileName));
TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
if(path.left(1)=="/") path.remove(0,1);
if(path != "") path = path+"/";
TQDir(tmpDir).mkdir(path);
changed = true; //rescan the archive
KURL dest;
dest.setPath(tmpDir+path+"/"+newName);
TDEIO::Job* job = new TDEIO::CopyJob(temp,dest,TDEIO::CopyJob::Move,false,false);
connect(job,TQT_SIGNAL(result(TDEIO::Job*)),this,TQT_SLOT(vfs_refresh(TDEIO::Job*)) );
}
bool arc_vfs::vfs_refresh(TQString origin){
if ( error ) return false;
if ( changed || origin == vfs_origin ){
repack(); // repack dirs only if needed
if ( !getDirs() ){
if (!quietMode) emit startUpdate();
return true;
}
changed = false;
}
vfs_origin = origin;
// get the directory...
TQString path = origin.right((origin.length()-origin.findRev('\\'))-1);
if(path.left(1) =="/") path.remove(0,1);
vfs_filesP = findDir(path);
if (!quietMode) emit startUpdate();
return true;
}
// service functions
TQString arc_vfs::nextWord(TQString &s,char d) {
s=s.stripWhiteSpace();
int j=s.find(d,0);
TQString temp=s.left(j); // find the leftmost word.
s.remove(0,j);
return temp;
}
void arc_vfs::getFilesToPack(TQStringList* filesToPack,TQString dir_name){
bool newDir = false;
vfileDict *vfs_filesP_backup = vfs_filesP; // save vfs_filesP
// init all the diffrent lists (and list pointers);
vfs_filesP=findDir(dir_name);
if ( vfs_filesP == 0) newDir = true;
if(dir_name != "") dir_name = dir_name+"/";
DIR* dir = opendir(tmpDir.local8Bit()+"/"+dir_name.local8Bit());
if(!dir) return ;
struct dirent* dirEnt;
TQString name;
KDE_struct_stat stat_p;
while( (dirEnt=readdir(dir)) != NULL ){
name = dirEnt->d_name;
if ( name == ".." || name == "." ) continue;
if( KDE_lstat(tmpDir.local8Bit()+"/"+dir_name.local8Bit()+name.local8Bit(),&stat_p) ) continue;
extFile temp(dir_name+name,stat_p.st_mtime,stat_p.st_size);
// add to the list file that are diffrent than the ones packed
if( S_ISDIR(stat_p.st_mode) ){ // recurse on all sub dirs
if( !findDir(dir_name+name) ){
// add to the list only new && empty dirs
if( newDir && TQDir(dir_name+name).entryList(TQDir::All | TQDir::AccessMask).count() <= 2 )
filesToPack->append( dir_name+name);
}
getFilesToPack(filesToPack,dir_name+name);
continue;
}
// if the file don't exist add it to the archive and to the extFiles
if( newDir || !extFiles.contains( dir_name+name ) ){
filesToPack->append( dir_name+name );
extFiles.append( temp );
} // else if the file exist but was modified - repack it;
else if( !extFiles.contains( temp ) ){
filesToPack->append( dir_name+name );
extFiles.remove( dir_name+name );
extFiles.append( temp );
}
}
vfs_filesP = vfs_filesP_backup; // restore vfs_filesP
}
void arc_vfs::getFilesToDelete(TQStringList* filesToDelete,TQString){
// sync the extFiles - and find out which files were deleted
TQString file;
for(unsigned int i=0 ; i<extFiles.count(); ){
file = tmpDir+"/"+(*extFiles.at(i)).url;
if( !KRpermHandler::fileExist(file) ){
filesToDelete->append( (*extFiles.at(i)).url );
extFiles.remove(extFiles.at(i));
}
else ++i;
}
}
void arc_vfs::getExtFiles(TQString dir_name){
DIR* dir = opendir(tmpDir.local8Bit()+"/"+dir_name.local8Bit());
if(!dir){
kdWarning() << "faild to opendir(): " << tmpDir.local8Bit()+"/"+dir_name.local8Bit() << endl;
return ;
}
if( dir_name != "") dir_name = dir_name+"/";
struct dirent* dirEnt;
TQString name;
KDE_struct_stat stat_p;
while( (dirEnt=readdir(dir)) != NULL ){
name = dirEnt->d_name;
if ( name == ".." || name == "." ) continue;
if( KDE_lstat(tmpDir.local8Bit()+"/"+dir_name.local8Bit()+name.local8Bit(),&stat_p) ) continue;
extFile temp(dir_name+name,stat_p.st_mtime,stat_p.st_size);
// recurse on all sub dirs
if( S_ISDIR(stat_p.st_mode) ){
getExtFiles(dir_name+name);
}
// if the file is not in extFiles - it is newly extracted.
// note: getFilesToPack() updates time + size !
else if( !extFiles.contains( dir_name+name ) ){
extFiles.append( temp );
}
}
}
void arc_vfs::repack(){
TQString save = getcwd(0,0);
chdir(tmpDir.local8Bit());
// delete from the archive files that were unpacked and deleted
if( vfs_isWritable() ){
TQStringList filesToDelete;
getFilesToDelete(&filesToDelete);
if( !filesToDelete.isEmpty() ){
KShellProcess delProc;
krApp->startWaiting(i18n("Deleting Files..."),filesToDelete.count()+ignoreLines);
connect(&delProc,TQT_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
krApp, TQT_SLOT(incProgress(TDEProcess*,char*,int)) );
delProc << delCmd << "\""+arcFile+"\"";
for( unsigned int i=0 ; i < filesToDelete.count() ;){
delProc << (*filesToDelete.at(i++));
if( i%MAX_FILES==0 || i==filesToDelete.count() ){
delProc.start(TDEProcess::NotifyOnExit,TDEProcess::AllOutput);
while( delProc.isRunning() ) tqApp->processEvents();
delProc.clearArguments();
delProc << delCmd << "\""+arcFile+"\"";
}
}
krApp->stopWait();
}
}
// finaly repack tmpDir
if( vfs_isWritable() || vfs_type=="gzip" || vfs_type=="zip2" ){
TQStringList filesToPack;
getFilesToPack(&filesToPack);
if( !filesToPack.isEmpty() ){
KShellProcess addProc;
krApp->startWaiting(i18n("Repacking..."),filesToPack.count()+ignoreLines);
connect(&addProc,TQT_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
krApp, TQT_SLOT(incProgress(TDEProcess*,char*,int)) );
if( vfs_type=="gzip" || vfs_type=="zip2" ){
addProc << addCmd << *filesToPack.at(0)<< ">" << "\""+arcFile+"\"";
addProc.start(TDEProcess::NotifyOnExit);
while( addProc.isRunning() ) tqApp->processEvents();
}
else {
addProc << addCmd << "\""+arcFile+"\"";
for( unsigned int i=0 ; i<filesToPack.count(); ){
addProc << "\""+prefix+(*filesToPack.at(i++))+"\"";
if( i%MAX_FILES==0 || i==filesToPack.count() ){
addProc.start(TDEProcess::NotifyOnExit,TDEProcess::AllOutput);
while( addProc.isRunning() ) tqApp->processEvents(); // busy wait - need to find something better...
addProc.clearArguments();
addProc << addCmd << "\""+arcFile+"\"";
}
}
}
krApp->stopWait();
}
}
chdir(save.local8Bit());
}
vfileDict* arc_vfs::findDir(TQString name){
for(arc_dir* temp = dirList.first();temp != 0 ; temp = dirList.next()){
if(temp->name == name) return &(temp->entries);
}
return 0;
}
arc_vfs::arc_dir* arc_vfs::findArcDir(TQString name){
for(arc_dir* temp = dirList.first();temp != 0 ; temp = dirList.next()){
if(temp->name == name) return temp;
}
return 0;
}
TQString arc_vfs::changeDir(TQString name){
if(name.left(2) == "./") {
prefix = "./";
name.remove(0,2);
}
if(!name.contains('/')){
vfs_filesP = findDir("");
return name;
}
// seperate the path from the name
TQString path = name.left(name.findRev('/'));
name = name.mid(name.findRev('/')+1);
// see if the path exists
if ((vfs_filesP=findDir(path)) == 0){
//create a new dir entry
TQString Pname = path.mid(path.findRev('/')+1);
if(Pname.isEmpty()) return name;
TQString tempName = arcFile;
TQFileInfo qfi(tempName.replace(TQRegExp("\\"),""));
vfile* vf=new vfile(Pname,0,"drwxr-xr-x",qfi.lastModified().toTime_t(),false,
qfi.owner(),qfi.group(),"inode/directory","",0 );
// add dirs if needed
changeDir(path);
vfile* vf2 = vfs_search(Pname);
if(vf2 != 0) vfs_removeFromList(vf2);
vfs_addToList(vf);
// add a new arc_dir
dirList.append(new arc_dir(path));
vfs_filesP = findDir(path);
}
return name;
}
// calculate space
void arc_vfs::vfs_calcSpace(TQString name ,TDEIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs,bool* stop){
if ( *stop ) return;
vfile* vf = vfs_search(name);
// get the path inside the archive
TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
path = path+"/";
if(path.left(1) == "/") path.remove(0,1);
if( !vf->vfile_isDir() ){ // single files are simple :)
++(*totalFiles);
(*totalSize) += vf->vfile_getSize();
}
else { // handle directories : (
++(*totalDirs);
TQString origin_backup = vfs_origin; // backup the vfs origin
vfs_origin = vfs_origin+"/"+name;
vfileDict* vfs_filesP_backup = vfs_filesP; // backup the vfs_filesP
vfs_filesP = findDir(path+name);
// process all the files in the directory.
for( vf = vfs_getFirstFile(); vf != 0; vf = vfs_getNextFile() ){
if (*stop) return;
vfs_calcSpace(vf->vfile_getName(),totalSize,totalFiles,totalDirs,stop);
}
vfs_origin = origin_backup; // restore origin
vfs_filesP = vfs_filesP_backup; // restore vfs_filesP
}
}
void arc_vfs::processName(const TQString& name, TQStringList *urls,TDEIO::filesize_t *totalSize,unsigned long *totalFiles ){
vfile* vf = vfs_search(name);
if ( vf == 0 ) return;
// get the path inside the archive
TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
path = path+"/";
if(path.left(1) == "/") path.remove(0,1);
if( !vf->vfile_isDir() || vf->vfile_isSymLink() ){ // single files are simple :)
++(*totalFiles);
(*totalSize) += vf->vfile_getSize();
urls->append(path+name);
} else { // handle directories : (
urls->append(path+name+"/");
TQString origin_backup = vfs_origin; // backup the vfs origin
vfs_origin = vfs_origin+"/"+name;
vfileDict* vfs_filesP_backup = vfs_filesP; // backup the vfs_filesP
vfs_filesP = findDir(path+name);
// process all the files in the directory.
for( vf = vfs_getFirstFile(); vf != 0; vf = vfs_getNextFile() )
processName(vf->vfile_getName(),urls,totalSize,totalFiles);
vfs_origin = origin_backup; // restore origin
vfs_filesP = vfs_filesP_backup; // restore vfs_filesP
}
}
void arc_vfs::parseLine(TQString line, TQFile* temp){
TQString name;
TDEIO::filesize_t size = 0;
TQString perm;
TQFileInfo qfi(arcFile);
time_t mtime = qfi.lastModified().toTime_t();
bool link = false;
uid_t owner = getuid();
gid_t group = getgid();
TQString dest = "";
mode_t mode = 0;
// parse gziped files
if(vfs_type == "gzip"){
KDE_struct_stat stat_p;
KDE_stat(arcFile.local8Bit(),&stat_p);
nextWord(line);
size = nextWord(line).toLong();
nextWord(line);
name = nextWord(line,'\n');
if(name.contains('/')) name = name.mid(name.findRev('/')+1,name.length());
perm = KRpermHandler::mode2TQString(stat_p.st_mode) ;
owner = KRpermHandler::user2uid(qfi.owner());
group = KRpermHandler::group2gid(qfi.group());
mode = stat_p.st_mode;
}
// parse bzip2ed files
if( vfs_type == "zip2" ){
KDE_struct_stat stat_p;
KDE_stat(arcFile.local8Bit(),&stat_p);
name = qfi.fileName();
name = name.left(name.findRev('.'));
//long size = qfi.size();
perm = KRpermHandler::mode2TQString(stat_p.st_mode) ;
owner = KRpermHandler::user2uid(qfi.owner());
group = KRpermHandler::group2gid(qfi.group());
mode = stat_p.st_mode;
}
// parse tar files
if(vfs_type == "-tar" || vfs_type == "-tbz" || vfs_type == "-tgz" ){
perm = nextWord(line);
TQString temp = nextWord(line);
owner = temp.left(temp.findRev('/')).toInt();
group = temp.mid(temp.find('/')+1,temp.length()).toInt();
size = nextWord(line).toLong();
temp = nextWord(line);
name = nextWord(line,'\n');
if (name.startsWith("/")) // fix full-paths problem in tar (thanks to Heiner!)
name.remove(0, 1);
if( name.contains(" -> ") ){
link = true;
dest = name.mid(name.find(" -> ")+4);
name = name.left(name.find(" -> "));
}
}
// parse zipped files
if(vfs_type == "-zip"){
perm = nextWord(line);
if(perm.length() != 10)
perm = (perm.at(0)=='d')? "drwxr-xr-x" : "-rw-r--r--" ;
if (nextWord(line).contains("file")) return;
nextWord(line);
size = nextWord(line).toLong();
nextWord(line);nextWord(line);
TQString temp = nextWord(line);
name = nextWord(line,'\n');
}
// parse cpio packages
if(vfs_type == "cpio" || vfs_type == "+rpm"){
perm = nextWord(line);
nextWord(line);nextWord(line);nextWord(line);
size = nextWord(line).toLong();
nextWord(line);nextWord(line);nextWord(line);
TQString tempName = arcFile;
TQFileInfo qfi(tempName.replace(TQRegExp("\\"),""));
name = nextWord(line,'\n');
if ( name.left(1) == "/" ) name.remove(0,1);
if( name.contains(" -> ") ){
link = true;
dest = name.mid(name.find(" -> ")+4);
name = name.left(name.find(" -> "));
}
}
// parse rared files
if(vfs_type == "-rar"){
name = nextWord(line,'\n');
temp->readLine(line,10000);
size = nextWord(line).toLong();
nextWord(line);
nextWord(line);
perm = nextWord(line);
if(perm.length() != 10)
perm = (perm.at(1)=='D')? "drwxr-xr-x" : "-rw-r--r--" ;
}
// parse rpm packages
if(vfs_type == "-rpm"){
name = nextWord(line);
if ( name.left(1) == "/" ) name.remove(0,1);
size = nextWord(line).toLong();
mtime = nextWord(line).toLong();
nextWord(line);
perm = KRpermHandler::mode2TQString(nextWord(line).toLong());
perm = (perm.at(0)=='d')? "drwxr-xr-x" : "-rw-r--r--" ;
}
if ( perm[0]=='d' && name.right(1) != "/" ) name = name+"/";
name = changeDir(name);
if(name.length() < 1) return;
TQString mime = KMimeType::findByURL( "/"+name,0,true,true)->name();
vfile* vf=new vfile(name,size,perm,mtime,link,owner,group,mime,dest,mode);
vfile* vf2 = vfs_search(name);
if(vf2 != 0) vfs_removeFromList(vf2);
vfs_addToList(vf);
}
#include "arc_vfs.moc"