summaryrefslogtreecommitdiffstats
path: root/src/app/VFS/normal_vfs.cpp
diff options
context:
space:
mode:
authorMichele Calgaro <michele.calgaro@yahoo.it>2025-08-28 22:44:34 +0900
committerMichele Calgaro <michele.calgaro@yahoo.it>2025-08-31 23:30:34 +0900
commitf9abd9d505434c9244c03eac708e29a0ca042f6b (patch)
tree30a197ab4c413849188bc131ff859212e636c821 /src/app/VFS/normal_vfs.cpp
parent14d42d284de233f9937becf3fc9ee0dabede3b21 (diff)
downloadkrusader-r14.1.x.tar.gz
krusader-r14.1.x.zip
Restructure source foldersr14.1.x
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it> (cherry picked from commit 086012dcad8a976a0dabbb7cbc20c9cb612cdfa9)
Diffstat (limited to 'src/app/VFS/normal_vfs.cpp')
-rw-r--r--src/app/VFS/normal_vfs.cpp437
1 files changed, 437 insertions, 0 deletions
diff --git a/src/app/VFS/normal_vfs.cpp b/src/app/VFS/normal_vfs.cpp
new file mode 100644
index 0000000..f81ab9a
--- /dev/null
+++ b/src/app/VFS/normal_vfs.cpp
@@ -0,0 +1,437 @@
+/***************************************************************************
+ normal_vfs.cpp
+ -------------------
+ copyright : (C) 2000 by Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+
+ ***************************************************************************
+
+ 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 <strings.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <dirent.h>
+// TQt includes
+#include <tqdir.h>
+#include <tqtimer.h>
+// TDE includes
+#include <tdemessagebox.h>
+#include <kmimetype.h>
+#include <tdeio/jobclasses.h>
+#include <tdelocale.h>
+#include <tdeglobalsettings.h>
+#include <kdebug.h>
+#include <klargefile.h>
+#include <tdefileitem.h>
+// Krusader includes
+#include "normal_vfs.h"
+#include "../Dialogs/krdialogs.h"
+#include "../MountMan/kmountman.h"
+#include "krpermhandler.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../resources.h"
+#include "../krslots.h"
+
+// header files for ACL
+#if KDE_IS_VERSION(3,5,0)
+#ifdef HAVE_POSIX_ACL
+#include <sys/acl.h>
+#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS
+#include <acl/libacl.h>
+#endif
+#endif
+#endif
+
+normal_vfs::normal_vfs(TQObject* panel):vfs(panel), watcher(0) {
+ vfs_type=NORMAL;
+}
+
+bool normal_vfs::populateVfsList(const KURL& origin, bool showHidden){
+ TQString path = origin.path(-1);
+
+ // set the writable attribute to true, if that's not the case - the TDEIO job
+ // will give the warnings and errors
+ isWritable = true;
+
+ if( watcher ) delete watcher; //stop watching the old dir
+ watcher = 0;
+
+ // set the origin...
+ vfs_origin = origin;
+ vfs_origin.adjustPath(-1);
+ vfs_origin.setProtocol("file"); // do not remove !
+ vfs_origin.cleanPath(-1);
+
+ // check that the new origin exists
+ if ( !TQDir(path).exists() )
+ {
+ if( !quietMode ) KMessageBox::error(krApp, i18n("Directory %1 does not exist!").arg( path ), i18n("Error"));
+ return false;
+ }
+
+ krConfig->setGroup("Advanced");
+ if (krConfig->readBoolEntry("AutoMount",_AutoMount)) krMtMan.autoMount(path);
+
+ DIR* dir = opendir(path.local8Bit());
+ if(!dir)
+ {
+ if( !quietMode ) KMessageBox::error(krApp, i18n("Can't open the %1 directory!").arg( path ), i18n("Error"));
+ return false;
+ }
+
+ // change directory to the new directory
+ TQString save = getcwd( 0, 0 );
+ if (chdir(path.local8Bit()) != 0) {
+ if( !quietMode ) KMessageBox::error(krApp, i18n("Access denied to")+path, i18n("Error"));
+ closedir(dir);
+ return false;
+ }
+
+ struct dirent* dirEnt;
+ TQString name;
+
+ while( (dirEnt=readdir(dir)) != NULL ){
+ name = TQString::fromLocal8Bit(dirEnt->d_name);
+
+ // show hidden files ?
+ if ( !showHidden && name.left(1) == "." ) continue ;
+ // we dont need the ".",".." enteries
+ if (name=="." || name == "..") continue;
+
+ vfile* temp = vfileFromName(name);
+ foundVfile(temp);
+ }
+ // clean up
+ closedir(dir);
+ chdir( save.local8Bit() );
+
+ if( panelConnected )
+ {
+ watcher = new KDirWatch();
+ // connect the watcher
+ connect(watcher,TQ_SIGNAL(dirty(const TQString&)),this,TQ_SLOT(vfs_slotDirty(const TQString&)));
+ connect(watcher,TQ_SIGNAL(created(const TQString&)),this, TQ_SLOT(vfs_slotCreated(const TQString&)));
+ connect(watcher,TQ_SIGNAL(deleted(const TQString&)),this, TQ_SLOT(vfs_slotDeleted(const TQString&)));
+ watcher->addDir(vfs_getOrigin().path(-1),true); //start watching the new dir
+ watcher->startScan(true);
+ }
+
+ return true;
+}
+
+// copy a file to the vfs (physical)
+void normal_vfs::vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir, PreserveMode pmode ){
+ //if( watcher ) watcher->stopScan(); // we will refresh manually this time...
+ if( watcher ) {
+ delete watcher; // stopScan is buggy, leaves reference on the directory, that's why we delete the watcher
+ watcher = 0;
+ }
+
+ KURL dest;
+ dest.setPath(vfs_workingDir()+"/"+dir);
+
+ TDEIO::Job* job = PreservingCopyJob::createCopyJob( pmode, *fileUrls,dest,mode,false,true );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh()) );
+ if(mode == TDEIO::CopyJob::Move) // notify the other panel
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),toNotify,TQ_SLOT(vfs_refresh(TDEIO::Job*)) );
+ else
+ job->setAutoErrorHandlingEnabled( true );
+}
+
+// remove a file from the vfs (physical)
+void normal_vfs::vfs_delFiles(TQStringList *fileNames){
+ KURL::List filesUrls;
+ KURL url;
+ TQDir local( vfs_workingDir() );
+ vfile* vf;
+
+// if( watcher ) watcher->stopScan(); // we will refresh manually this time...
+ if( watcher ) {
+ delete watcher; // stopScan is buggy, leaves reference on the directory, that's why we delete the watcher
+ watcher = 0;
+ }
+
+ // names -> urls
+ for(uint i=0 ; i<fileNames->count(); ++i){
+ TQString filename = (*fileNames)[i];
+ vf = vfs_search(filename);
+ url.setPath( vfs_workingDir()+"/"+filename);
+ filesUrls.append(url);
+ }
+ TDEIO::Job *job;
+
+ // delete of move to trash ?
+ krConfig->setGroup("General");
+ if( krConfig->readBoolEntry("Move To Trash",_MoveToTrash) ){
+#if KDE_IS_VERSION(3,4,0)
+ job = TDEIO::trash(filesUrls, true );
+#else
+ job = new TDEIO::CopyJob(filesUrls,TDEGlobalSettings::trashPath(),TDEIO::CopyJob::Move,false,true );
+#endif
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),SLOTS,TQ_SLOT(changeTrashIcon()));
+ }
+ else
+ job = new TDEIO::DeleteJob(filesUrls, false, true);
+
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh(TDEIO::Job*)));
+}
+
+// return a path to the file
+KURL normal_vfs::vfs_getFile(const TQString& name){
+ TQString url;
+ if ( vfs_workingDir() == "/" ) url = "/"+name;
+ else url = vfs_workingDir()+"/"+name;
+
+ return vfs::fromPathOrURL(url);
+}
+
+KURL::List* normal_vfs::vfs_getFiles(TQStringList* names){
+ KURL::List* urls = new KURL::List();
+ for(TQStringList::Iterator name = names->begin(); name != names->end(); ++name){
+ urls->append( vfs_getFile(*name) );
+ }
+ return urls;
+}
+
+void normal_vfs::vfs_mkdir(const TQString& name){
+ if (!TQDir(vfs_workingDir()).mkdir(name))
+ if (!quietMode) KMessageBox::sorry(krApp,i18n("Can't create a directory. Check your permissions."));
+ vfs::vfs_refresh();
+}
+
+void normal_vfs::vfs_rename(const TQString& fileName,const TQString& newName){
+ KURL::List fileUrls;
+ KURL url , dest;
+
+ //if( watcher ) watcher->stopScan(); // we will refresh manually this time...
+ if( watcher ) {
+ delete watcher; // stopScan is buggy, leaves reference on the directory, that's why we delete the watcher
+ watcher = 0;
+ }
+
+ url.setPath( vfs_workingDir()+"/"+fileName );
+ fileUrls.append(url);
+ dest.setPath(vfs_workingDir()+"/"+newName);
+
+ TDEIO::Job *job = new TDEIO::CopyJob(fileUrls,dest,TDEIO::CopyJob::Move,true,false );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh(TDEIO::Job*)));
+}
+
+vfile* normal_vfs::vfileFromName(const TQString& name){
+ TQString path = vfs_workingDir()+"/"+name;
+ TQCString fileName = path.local8Bit();
+
+ KDE_struct_stat stat_p;
+ KDE_lstat(fileName.data(),&stat_p);
+ TDEIO::filesize_t size = stat_p.st_size;
+ TQString perm = KRpermHandler::mode2TQString(stat_p.st_mode);
+ bool symLink= S_ISLNK(stat_p.st_mode);
+ if( S_ISDIR(stat_p.st_mode) ) perm[0] = 'd';
+
+ KURL mimeUrl = fromPathOrURL(path);
+ TQString mime=TQString();
+
+ char symDest[256];
+ bzero(symDest,256);
+ if( S_ISLNK(stat_p.st_mode) ){ // who the link is pointing to ?
+ int endOfName=0;
+ endOfName=readlink(fileName.data(),symDest,256);
+ if ( endOfName != -1 ){
+ if ( TQDir(TQString::fromLocal8Bit( symDest ) ).exists() ) perm[0] = 'd';
+ if ( !TQDir(vfs_workingDir()).exists( TQString::fromLocal8Bit ( symDest ) ) ) mime = "Broken Link !";
+ }
+ else krOut << "Failed to read link: "<< path<<endl;
+ }
+
+ int rwx = 0;
+ if( ::access( fileName.data(), R_OK ) == 0 )
+ rwx |= R_OK;
+ if( ::access( fileName.data(), W_OK ) == 0 )
+ rwx |= W_OK;
+ if( ::access( fileName.data(), X_OK ) == 0 )
+ rwx |= X_OK;
+
+ // create a new virtual file object
+ vfile* temp=new vfile(name,size,perm,stat_p.st_mtime,symLink,stat_p.st_uid,
+ stat_p.st_gid,mime,TQString::fromLocal8Bit( symDest ),stat_p.st_mode, rwx);
+ temp->vfile_setUrl( mimeUrl );
+ return temp;
+}
+
+void normal_vfs::getACL( vfile *file, TQString &acl, TQString &defAcl )
+{
+ acl = defAcl = TQString();
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ TQCString fileName = file->vfile_getUrl().path( -1 ).local8Bit();
+#if HAVE_NON_POSIX_ACL_EXTENSIONS
+ if ( acl_extended_file( fileName.data() ) )
+ {
+#endif
+ acl = getACL( fileName.data(), ACL_TYPE_ACCESS );
+ if( file->vfile_isDir() )
+ defAcl = getACL( fileName.data(), ACL_TYPE_DEFAULT );
+#if HAVE_NON_POSIX_ACL_EXTENSIONS
+ }
+#endif
+#endif
+}
+
+TQString normal_vfs::getACL( const TQString & path, int type )
+{
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ acl_t acl = 0;
+ // do we have an acl for the file, and/or a default acl for the dir, if it is one?
+ if ( ( acl = acl_get_file( path.ascii(), type ) ) != 0 )
+ {
+ bool aclExtended = false;
+
+#if HAVE_NON_POSIX_ACL_EXTENSIONS
+ aclExtended = acl_equiv_mode( acl, 0 );
+#else
+ acl_entry_t entry;
+ int ret = acl_get_entry( acl, ACL_FIRST_ENTRY, &entry );
+ while ( ret == 1 ) {
+ acl_tag_t currentTag;
+ acl_get_tag_type( entry, &currentTag );
+ if ( currentTag != ACL_USER_OBJ &&
+ currentTag != ACL_GROUP_OBJ &&
+ currentTag != ACL_OTHER )
+ {
+ aclExtended = true;
+ break;
+ }
+ ret = acl_get_entry( acl, ACL_NEXT_ENTRY, &entry );
+ }
+#endif
+
+ if ( !aclExtended )
+ {
+ acl_free( acl );
+ acl = 0;
+ }
+ }
+
+ if( acl == 0 )
+ return TQString();
+
+ char *aclString = acl_to_text( acl, 0 );
+ TQString ret = TQString::fromLatin1( aclString );
+ acl_free( (void*)aclString );
+ acl_free( acl );
+
+ return ret;
+#else
+ return TQString();
+#endif
+}
+
+void normal_vfs::vfs_slotRefresh()
+{
+ krConfig->setGroup("Advanced");
+ int maxRefreshFrequency = krConfig->readNumEntry("Max Refresh Frequency", 1000);
+ vfs_refresh();
+ disconnect( &refreshTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( vfs_slotRefresh() ) );
+ refreshTimer.start( maxRefreshFrequency, true );
+}
+
+bool normal_vfs::burstRefresh(const TQString& path ){
+ if( path == vfs_getOrigin().path(-1) ) {
+ if( !refreshTimer.isActive() ) {
+ // the directory itself is dirty - full refresh is needed
+ TQTimer::singleShot(0, this, TQ_SLOT( vfs_slotRefresh() ) ); // safety: dirty signal comes from KDirWatch!
+ return true;
+ }
+ disconnect( &refreshTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( vfs_slotRefresh() ) );
+ connect( &refreshTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( vfs_slotRefresh() ) );
+ postponedRefreshURL = fromPathOrURL(path);
+ return true;
+ }
+ return false;
+}
+
+void normal_vfs::vfs_slotDirty(const TQString& path){
+ if( disableRefresh ){
+ postponedRefreshURL = fromPathOrURL(path);
+ return;
+ }
+
+ if( burstRefresh( path ) )
+ return;
+
+ KURL url = fromPathOrURL(path);
+ TQString name = url.fileName();
+
+ // do we have it already ?
+ if( !vfs_search(name ) ) return vfs_slotCreated(path);
+
+ // we have an updated file..
+ removeFromList(name);
+ vfile* vf = vfileFromName(name);
+ addToList(vf);
+ emit updatedVfile(vf);
+}
+
+void normal_vfs::vfs_slotCreated(const TQString& path){
+ if( disableRefresh ){
+ postponedRefreshURL = fromPathOrURL(path);
+ return;
+ }
+
+ if( burstRefresh( path ) )
+ return;
+
+
+ KURL url = fromPathOrURL(path);
+ TQString name = url.fileName();
+ // if it's in the CVS - it's an update not new file
+ if( vfs_search(name) )
+ return vfs_slotDirty(path);
+
+ vfile* vf = vfileFromName(name);
+ addToList(vf);
+ emit addedVfile(vf);
+}
+
+void normal_vfs::vfs_slotDeleted(const TQString& path){
+ if( disableRefresh ){
+ postponedRefreshURL = fromPathOrURL(path);
+ return;
+ }
+
+ if( burstRefresh( path ) )
+ return;
+
+
+ KURL url = fromPathOrURL(path);
+ TQString name = url.fileName();
+
+ // if it's not in the CVS - do nothing
+ if( vfs_search(name) ){
+ emit deletedVfile(name);
+ removeFromList(name);
+ }
+}
+
+#include "normal_vfs.moc"