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.
328 lines
11 KiB
328 lines
11 KiB
/***************************************************************************
|
|
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 <sys/param.h>
|
|
#include <time.h>
|
|
#include "kmountman.h"
|
|
// KDE includes
|
|
#include <kmessagebox.h>
|
|
#include <kprocess.h>
|
|
#include <klocale.h>
|
|
#include <kpopupmenu.h>
|
|
#include <kdebug.h>
|
|
|
|
// Krusader includes
|
|
#include "../krusader.h"
|
|
#include "../defaults.h"
|
|
#include "../Dialogs/krdialogs.h"
|
|
#include "../krservices.h"
|
|
#include "kmountmangui.h"
|
|
#include <unistd.h>
|
|
#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, TQT_SIGNAL(result(TDEIO::Job* )), this, TQT_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, TQT_SIGNAL(result(TDEIO::Job* )), this, TQT_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
|
|
( ( KToolBarPopupAction* ) 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() + ")";
|
|
|
|
|
|
( ( KToolBarPopupAction* ) krMountMan ) ->popupMenu() ->insertItem( text, idx );
|
|
}
|
|
connect( ( ( KToolBarPopupAction* ) krMountMan ) ->popupMenu(), TQT_SIGNAL( activated( int ) ),
|
|
this, TQT_SLOT( delayedPerformAction( int ) ) );
|
|
|
|
}
|
|
|
|
void KMountMan::delayedPerformAction( int idx ) {
|
|
__delayedIdx = idx;
|
|
TQTimer::singleShot(0, this, TQT_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( ( ( KToolBarPopupAction* ) krMountMan ) ->popupMenu(), TQT_SIGNAL( activated( int ) ), 0, 0 );
|
|
}
|
|
|
|
#include "kmountman.moc"
|