/*************************************************************************** kmountman.cpp ------------------- copyright : (C) 2000 by Shie Erlich & 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 #include #include "kmountman.h" // KDE includes #include #include #include #include #include // Krusader includes #include "../krusader.h" #include "../defaults.h" #include "../Dialogs/krdialogs.h" #include "../krservices.h" #include "kmountmangui.h" #include #include "../Dialogs/krprogress.h" #include "../VFS/krpermhandler.h" #ifdef _OS_SOLARIS_ #define FSTAB "/etc/vfstab" #else #define FSTAB "/etc/fstab" #endif static int __delayedIdx; // ugly: pass the processEvents deadlock KMountMan::KMountMan() : TQObject(), Operational( false ), waiting(false), mountManGui( 0 ) { _actions = 0L; // added as a precaution, although we use kde services now if( !KrServices::cmdExist( "df" ) || !KrServices::cmdExist( "mount" ) ) { Operational = false; } else { Operational = true; } // list of FS that we don't manage at all invalid_fs << "swap" << "/dev/pts" << "tmpfs" << "devpts" << "sysfs" << "rpc_pipefs" << "usbfs" << "binfmt_misc"; #if defined(BSD) invalid_fs << "procfs"; #else invalid_fs << "proc"; #endif // list of FS that we don't allow to mount/unmount nonmount_fs << "supermount"; { TDEConfigGroupSaver saver(krConfig, "Advanced"); TQStringList nonmount = TQStringList::split(",", krConfig->readEntry("Nonmount Points", _NonMountPoints)); nonmount_fs_mntpoint += nonmount; // simplify the white space for ( TQStringList::Iterator it = nonmount_fs_mntpoint.begin(); it != nonmount_fs_mntpoint.end(); ++it ) { *it = (*it).simplifyWhiteSpace(); } } } KMountMan::~KMountMan() {} bool KMountMan::invalidFilesystem(TQString type) { return (invalid_fs.contains(type) > 0); } // this is an ugly hack, but type can actually be a mountpoint. oh well... bool KMountMan::nonmountFilesystem(TQString type, TQString mntPoint) { return((nonmount_fs.contains(type) > 0) || (nonmount_fs_mntpoint.contains(mntPoint) > 0)); } void KMountMan::mainWindow() { mountManGui = new KMountManGUI(); delete mountManGui; /* as KMountManGUI is modal, we can now delete it */ mountManGui = 0; /* for sanity */ } KMountPoint *KMountMan::findInListByMntPoint(KMountPoint::List &lst, TQString value) { KMountPoint *m; for (KMountPoint::List::iterator it = lst.begin(); it != lst.end(); ++it) { m = *it; if (m->mountPoint() == value) return m; } return 0; } void KMountMan::jobResult(TDEIO::Job *job) { waiting = false; if ( job->error() ) job->showErrorDialog( 0 ); } void KMountMan::mount( TQString mntPoint, bool blocking ) { KMountPoint::List possible = KMountPoint::possibleMountPoints(KMountPoint::NeedMountOptions); KMountPoint *m = findInListByMntPoint(possible, mntPoint); if (!m) return; if (blocking) waiting = true; // prepare to block TDEIO::SimpleJob *job = TDEIO::mount(false, m->mountType().local8Bit(), m->mountedFrom(), m->mountPoint(), false); new KrProgress(job); connect(job, TQ_SIGNAL(result(TDEIO::Job* )), this, TQ_SLOT(jobResult(TDEIO::Job* ))); while (blocking && waiting) { tqApp->processEvents(); usleep( 1000 ); } } void KMountMan::unmount( TQString mntPoint, bool blocking ) { if (blocking) waiting = true; // prepare to block TDEIO::SimpleJob *job = TDEIO::unmount(mntPoint, false); new KrProgress(job); connect(job, TQ_SIGNAL(result(TDEIO::Job* )), this, TQ_SLOT(jobResult(TDEIO::Job* ))); while (blocking && waiting) { tqApp->processEvents(); usleep( 1000 ); } } KMountMan::mntStatus KMountMan::getStatus( TQString mntPoint ) { KMountPoint::List::iterator it; KMountPoint *m; // 1: is it already mounted KMountPoint::List current = KMountPoint::currentMountPoints(); m = findInListByMntPoint(current, mntPoint); if (m) return MOUNTED; // 2: is it a mount point but not mounted? KMountPoint::List possible = KMountPoint::possibleMountPoints(); m = findInListByMntPoint(possible, mntPoint); if (m) return NOT_MOUNTED; // 3: unknown return DOESNT_EXIST; } void KMountMan::toggleMount( TQString mntPoint ) { mntStatus status = getStatus(mntPoint); switch (status) { case MOUNTED: unmount(mntPoint); break; case NOT_MOUNTED: mount(mntPoint); break; case DOESNT_EXIST: // do nothing: no-op to make the compiler quiet ;-) break; } } void KMountMan::autoMount( TQString path ) { if ( getStatus( path ) == NOT_MOUNTED ) mount( path ); } void KMountMan::eject( TQString mntPoint ) { KShellProcess proc; proc << KrServices::fullPathName( "eject" ) << "'" + mntPoint + "'"; proc.start( TDEProcess::Block ); if ( !proc.normalExit() || proc.exitStatus() != 0 ) // if we failed with eject KMessageBox::information( 0, i18n( "Error ejecting device! You need to have 'eject' in your path." ), i18n( "Error" ), "CantExecuteEjectWarning" ); } // returns true if the path is an ejectable mount point (at the moment CDROM and DVD) bool KMountMan::ejectable( TQString path ) { #if !defined(BSD) && !defined(_OS_SOLARIS_) KMountPoint::List possible = KMountPoint::possibleMountPoints(); KMountPoint *m = findInListByMntPoint(possible, path); if (m && (m->mountType()=="iso9660" || m->mountedFrom().left(7)=="/dev/cd" || m->mountedFrom().left(8)=="/dev/dvd")) return KrServices::cmdExist( "eject" ); #endif return false; } // a mountMan special version of TDEIO::convertSize, which deals // with large filesystems ==> >4GB, it actually recieve size in // a minimum block of 1024 ==> data is KB not bytes TQString KMountMan::convertSize( TDEIO::filesize_t size ) { float fsize; TQString s; // Tera-byte if ( size >= 1073741824 ) { fsize = ( float ) size / ( float ) 1073741824; if ( fsize > 1024 ) // no name for something bigger than tera byte // let's call it Zega-Byte, who'll ever find out? :-) s = i18n( "%1 ZB" ).arg( TDEGlobal::locale() ->formatNumber( fsize / ( float ) 1024, 1 ) ); else s = i18n( "%1 TB" ).arg( TDEGlobal::locale() ->formatNumber( fsize, 1 ) ); } // Giga-byte else if ( size >= 1048576 ) { fsize = ( float ) size / ( float ) 1048576; s = i18n( "%1 GB" ).arg( TDEGlobal::locale() ->formatNumber( fsize, 1 ) ); } // Mega-byte else if ( size > 1024 ) { fsize = ( float ) size / ( float ) 1024; s = i18n( "%1 MB" ).arg( TDEGlobal::locale() ->formatNumber( fsize, 1 ) ); } // Kilo-byte else { fsize = ( float ) size; s = i18n( "%1 KB" ).arg( TDEGlobal::locale() ->formatNumber( fsize, 0 ) ); } return s; } // populate the pop-up menu of the mountman tool-button with actions void KMountMan::quickList() { if ( !Operational ) { KMessageBox::error( 0, i18n( "MountMan is not operational. Sorry" ) ); return ; } // clear the popup menu ( ( TDEToolBarPopupAction* ) krMountMan ) ->popupMenu() ->clear(); // create lists of current and possible mount points KMountPoint::List current = KMountPoint::currentMountPoints(); KMountPoint::List possible = KMountPoint::possibleMountPoints(); // create a popupmenu, displaying mountpoints with possible actions // also, populate a small array with the actions if ( _actions ) delete[] _actions; _actions = new TQString[ possible.size() ]; KMountPoint::List::iterator it; KMountPoint *m; int idx; for ( it = possible.begin(), idx = 0; it != possible.end(); ++it, ++idx ) { m = *it; // skip nonmountable file systems if (nonmountFilesystem(m->mountType(), m->mountPoint()) || invalidFilesystem(m->mountType())) continue; // does the mountpoint exist in current list? if so, it can only // be umounted, otherwise, it can be mounted bool needUmount = false; KMountPoint::List::iterator otherIt; for ( otherIt = current.begin(); otherIt != current.end(); ++otherIt ) { if ( ( *otherIt ) ->mountPoint() == m->mountPoint() ) { // found it, in needs umount needUmount = true; break; } } // add the item to the menu _actions[ idx ] = TQString( needUmount ? "_U_" : "_M_" ) + m->mountPoint(); TQString text = TQString( ( needUmount ? i18n( "Unmount" ) : i18n( "Mount" ) ) ) + " " + m->mountPoint() + " (" + m->mountedFrom() + ")"; ( ( TDEToolBarPopupAction* ) krMountMan ) ->popupMenu() ->insertItem( text, idx ); } connect( ( ( TDEToolBarPopupAction* ) krMountMan ) ->popupMenu(), TQ_SIGNAL( activated( int ) ), this, TQ_SLOT( delayedPerformAction( int ) ) ); } void KMountMan::delayedPerformAction( int idx ) { __delayedIdx = idx; TQTimer::singleShot(0, this, TQ_SLOT(performAction(int))); } void KMountMan::performAction( int idx ) { while ( tqApp->hasPendingEvents() ) tqApp->processEvents(); // ugly !!! take idx from the value put there by delayedPerformAction so // as to NOT DIE because of a processEvents deadlock!!! @#$@!@ idx = __delayedIdx; if ( idx < 0 ) return ; bool domount = _actions[ idx ].left( 3 ) == "_M_"; TQString mountPoint = _actions[ idx ].mid( 3 ); if ( !domount ) { // umount unmount( mountPoint); } else { // mount mount( mountPoint); } // free memory delete[] _actions; _actions = 0L; disconnect( ( ( TDEToolBarPopupAction* ) krMountMan ) ->popupMenu(), TQ_SIGNAL( activated( int ) ), 0, 0 ); } #include "kmountman.moc"