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/MountMan/kmountman.cpp

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 <tdemessagebox.h>
#include <kprocess.h>
#include <tdelocale.h>
#include <tdepopupmenu.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, 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"