arc_vfs.cpp
来自「LINUX 下, 以 QT/KDE 写的档案管理员」· C++ 代码 · 共 867 行 · 第 1/2 页
CPP
867 行
temp.append(vfs_getFile(fileName)); 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); changed = true; //rescan the archive KURL dest; dest.setPath(tmpDir+path+"/"+newName); KIO::Job* job = new KIO::CopyJob(temp,dest,KIO::CopyJob::Move,false,false); connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(vfs_refresh(KIO::Job*)) );}bool arc_vfs::vfs_refresh(QString 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... QString 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 functionsQString arc_vfs::nextWord(QString &s,char d) { s=s.stripWhiteSpace(); int j=s.find(d,0); QString temp=s.left(j); // find the leftmost word. s.remove(0,j); return temp;}void arc_vfs::getFilesToPack(QStringList* filesToPack,QString 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+"/"; register DIR* dir = opendir(tmpDir.local8Bit()+"/"+dir_name.local8Bit()); if(!dir) return ; register struct dirent* dirEnt; QString 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 && QDir(dir_name+name).entryList(QDir::All | QDir::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(QStringList* filesToDelete,QString){ // sync the extFiles - and find out which files were deleted QString 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(QString dir_name){ register 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+"/"; register struct dirent* dirEnt; QString 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(){ QString save = getcwd(0,0); chdir(tmpDir.local8Bit()); // delete from the archive files that were unpacked and deleted if( vfs_isWritable() ){ QStringList filesToDelete; getFilesToDelete(&filesToDelete); if( !filesToDelete.isEmpty() ){ KShellProcess delProc; krApp->startWaiting(i18n("Deleting Files..."),filesToDelete.count()+ignoreLines); connect(&delProc,SIGNAL(receivedStdout(KProcess*,char*,int)), krApp, SLOT(incProgress(KProcess*,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(KProcess::NotifyOnExit,KProcess::AllOutput); while( delProc.isRunning() ) qApp->processEvents(); delProc.clearArguments(); delProc << delCmd << "\""+arcFile+"\""; } } krApp->stopWait(); } } // finaly repack tmpDir if( vfs_isWritable() || vfs_type=="gzip" || vfs_type=="zip2" ){ QStringList filesToPack; getFilesToPack(&filesToPack); if( !filesToPack.isEmpty() ){ KShellProcess addProc; krApp->startWaiting(i18n("Repacking..."),filesToPack.count()+ignoreLines); connect(&addProc,SIGNAL(receivedStdout(KProcess*,char*,int)), krApp, SLOT(incProgress(KProcess*,char*,int)) ); if( vfs_type=="gzip" || vfs_type=="zip2" ){ addProc << addCmd << *filesToPack.at(0)<< ">" << "\""+arcFile+"\""; addProc.start(KProcess::NotifyOnExit); while( addProc.isRunning() ) qApp->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(KProcess::NotifyOnExit,KProcess::AllOutput); while( addProc.isRunning() ) qApp->processEvents(); // busy wait - need to find something better... addProc.clearArguments(); addProc << addCmd << "\""+arcFile+"\""; } } } krApp->stopWait(); } } chdir(save.local8Bit());}vfileDict* arc_vfs::findDir(QString 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(QString name){for(arc_dir* temp = dirList.first();temp != 0 ; temp = dirList.next()){ if(temp->name == name) return temp; } return 0;}QString arc_vfs::changeDir(QString name){ if(name.left(2) == "./") { prefix = "./"; name.remove(0,2); } if(!name.contains('/')){ vfs_filesP = findDir(""); return name; } // seperate the path from the name QString 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 QString Pname = path.mid(path.findRev('/')+1); if(Pname.isEmpty()) return name; QString tempName = arcFile; QFileInfo qfi(tempName.replace(QRegExp("\\"),"")); 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 spacevoid arc_vfs::vfs_calcSpace(QString name ,KIO::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 QString 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); QString 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 QString& name, QStringList *urls,KIO::filesize_t *totalSize,unsigned long *totalFiles ){ vfile* vf = vfs_search(name); if ( vf == 0 ) return; // get the path inside the archive QString 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+"/"); QString 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(QString line, QFile* temp){ QString name; KIO::filesize_t size = 0; QString perm; QFileInfo qfi(arcFile); time_t mtime = qfi.lastModified().toTime_t(); bool link = false; uid_t owner = getuid(); gid_t group = getgid(); QString 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::mode2QString(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::mode2QString(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); QString 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); QString 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); QString tempName = arcFile; QFileInfo qfi(tempName.replace(QRegExp("\\"),"")); 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::mode2QString(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; QString 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"
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?