diff options
Diffstat (limited to 'src/app/MountMan')
-rw-r--r-- | src/app/MountMan/Makefile.am | 10 | ||||
-rw-r--r-- | src/app/MountMan/kdiskfreesp.cpp | 168 | ||||
-rw-r--r-- | src/app/MountMan/kdiskfreesp.h | 89 | ||||
-rw-r--r-- | src/app/MountMan/kmountman.cpp | 327 | ||||
-rw-r--r-- | src/app/MountMan/kmountman.h | 103 | ||||
-rw-r--r-- | src/app/MountMan/kmountmangui.cpp | 396 | ||||
-rw-r--r-- | src/app/MountMan/kmountmangui.h | 199 |
7 files changed, 1292 insertions, 0 deletions
diff --git a/src/app/MountMan/Makefile.am b/src/app/MountMan/Makefile.am new file mode 100644 index 0000000..3e3f35c --- /dev/null +++ b/src/app/MountMan/Makefile.am @@ -0,0 +1,10 @@ +noinst_LIBRARIES = libMountMan.a + +INCLUDES = $(all_includes) + +libMountMan_a_METASOURCES = AUTO + +libMountMan_a_SOURCES = \ + kmountmangui.cpp \ + kmountman.cpp \ + kdiskfreesp.cpp diff --git a/src/app/MountMan/kdiskfreesp.cpp b/src/app/MountMan/kdiskfreesp.cpp new file mode 100644 index 0000000..b29304e --- /dev/null +++ b/src/app/MountMan/kdiskfreesp.cpp @@ -0,0 +1,168 @@ +/* + * kdiskfreesp.cpp + * + * Copyright (c) 1999 Michael Kropfberger <michael.kropfberger@gmx.net> + * + * Requires the TQt widget libraries, available at no cost at + * http://www.troll.no/ + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "kdiskfreesp.h" +#include <tqfile.h> +#include <tqtextstream.h> + +#include <kdebug.h> +#include <kprocess.h> +#include <tdeio/global.h> + +#include "kdiskfreesp.moc" + +#define DF_COMMAND "df" +#define DF_ARGS "-k" +#define NO_FS_TYPE true + +#define BLANK ' ' +#define FULL_PERCENT 95.0 + +/*************************************************************************** + * constructor +**/ +KDiskFreeSp::KDiskFreeSp(TQObject *parent, const char *name) + : TQObject(parent,name) +{ + dfProc = new TDEProcess(); TQ_CHECK_PTR(dfProc); + dfProc->setEnvironment("LANGUAGE", "C"); + connect( dfProc, TQ_SIGNAL(receivedStdout(TDEProcess *, char *, int) ), + this, TQ_SLOT (receivedDFStdErrOut(TDEProcess *, char *, int)) ); + connect(dfProc,TQ_SIGNAL(processExited(TDEProcess *) ), + this, TQ_SLOT(dfDone() ) ); + + readingDFStdErrOut=false; +} + + +/*************************************************************************** + * destructor +**/ +KDiskFreeSp::~KDiskFreeSp() +{ + delete dfProc; +} + +/*************************************************************************** + * is called, when the df-command writes on StdOut +**/ +void KDiskFreeSp::receivedDFStdErrOut(TDEProcess *, char *data, int len) +{ + TQCString tmp(data,len+1); // adds a zero-byte + dfStringErrOut.append(tmp); +} + +/*************************************************************************** + * reads the df-commands results +**/ +int KDiskFreeSp::readDF( const TQString & mountPoint ) +{ + if (readingDFStdErrOut || dfProc->isRunning()) + return -1; + m_mountPoint = mountPoint; + dfStringErrOut=""; // yet no data received + dfProc->clearArguments(); + (*dfProc) << TQString::fromLocal8Bit(DF_COMMAND) << TQString::fromLocal8Bit(DF_ARGS) << mountPoint; + if (!dfProc->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput )) + kdError() << "could not execute ["<< DF_COMMAND << "]" << endl; + return 1; +} + + +/*************************************************************************** + * is called, when the df-command has finished +**/ +void KDiskFreeSp::dfDone() +{ + readingDFStdErrOut=true; + + TQTextStream t (dfStringErrOut, IO_ReadOnly); + TQString s=t.readLine(); + if ( (s.isEmpty()) || ( s.left(10) != TQString::fromLatin1("Filesystem") ) ) + kdError() << "Error running df command... got [" << s << "]" << endl; + while ( !t.eof() ) { + TQString u,v; + s=t.readLine(); + s=s.simplifyWhiteSpace(); + if ( !s.isEmpty() ) { + //kdDebug(tdefile_area) << "GOT: [" << s << "]" << endl; + + if (s.find(BLANK)<0) // devicename was too long, rest in next line + if ( !t.eof() ) { // just appends the next line + v=t.readLine(); + s=s.append(v); + s=s.simplifyWhiteSpace(); + //kdDebug(tdefile_area) << "SPECIAL GOT: [" << s << "]" << endl; + }//if silly linefeed + + //kdDebug(tdefile_area) << "[" << s << "]" << endl; + + //TQString deviceName = s.left(s.find(BLANK)); + s=s.remove(0,s.find(BLANK)+1 ); + //kdDebug(tdefile_area) << " DeviceName: [" << deviceName << "]" << endl; + + if (!NO_FS_TYPE) + s=s.remove(0,s.find(BLANK)+1 ); // eat fs type + + u=s.left(s.find(BLANK)); + unsigned long kBSize = u.toULong(); + s=s.remove(0,s.find(BLANK)+1 ); + //kdDebug(tdefile_area) << " Size: [" << kBSize << "]" << endl; + + u=s.left(s.find(BLANK)); + unsigned long kBUsed = u.toULong(); + s=s.remove(0,s.find(BLANK)+1 ); + //kdDebug(tdefile_area) << " Used: [" << kBUsed << "]" << endl; + + u=s.left(s.find(BLANK)); + unsigned long kBAvail = u.toULong(); + s=s.remove(0,s.find(BLANK)+1 ); + //kdDebug(tdefile_area) << " Avail: [" << kBAvail << "]" << endl; + + + s=s.remove(0,s.find(BLANK)+1 ); // delete the capacity 94% + TQString mountPoint = s.stripWhiteSpace(); + //kdDebug(tdefile_area) << " MountPoint: [" << mountPoint << "]" << endl; + + if ( mountPoint == m_mountPoint ) + { + //kdDebug(tdefile_area) << "Found mount point. Emitting" << endl; + emit foundMountPoint( mountPoint, kBSize, kBUsed, kBAvail ); + emit foundMountPoint( kBSize, kBUsed, kBAvail, mountPoint ); // sic! + } + }//if not header + }//while further lines available + + readingDFStdErrOut=false; + emit done(); + delete this; +} + +KDiskFreeSp * KDiskFreeSp::findUsageInfo( const TQString & path ) +{ + KDiskFreeSp * job = new KDiskFreeSp; + TQString mountPoint = TDEIO::findPathMountPoint( path ); + job->readDF( mountPoint ); + return job; +} diff --git a/src/app/MountMan/kdiskfreesp.h b/src/app/MountMan/kdiskfreesp.h new file mode 100644 index 0000000..0102c2a --- /dev/null +++ b/src/app/MountMan/kdiskfreesp.h @@ -0,0 +1,89 @@ +/* + * kdiskfreesp.h + * + * Copyright (c) 1999 Michael Kropfberger <michael.kropfberger@gmx.net> + * + * Requires the TQt widget libraries, available at no cost at + * http://www.troll.no/ + * + * Modifed for Krusader by shie erlich, October 2004 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef __KDISKFREESP_H__ +#define __KDISKFREESP_H__ + +#include <tqobject.h> +#include <tqstring.h> + +class TDEProcess; + +/** + * This class parses the output of "df" to find the disk usage + * information for a given partition (mount point). + */ +class KDiskFreeSp : public TQObject +{ TQ_OBJECT + +public: + KDiskFreeSp( TQObject *parent=0, const char *name=0 ); + /** + * Destructor - this object autodeletes itself when it's done + */ + ~KDiskFreeSp(); + /** + * Call this to fire a search on the disk usage information + * for @p mountPoint. foundMountPoint will be emitted + * if this mount point is found, with the info requested. + * done is emitted in any case. + */ + int readDF( const TQString & mountPoint ); + + /** + * Call this to fire a search on the disk usage information + * for the mount point containing @p path. + * foundMountPoint will be emitted + * if this mount point is found, with the info requested. + * done is emitted in any case. + */ + static KDiskFreeSp * findUsageInfo( const TQString & path ); + +signals: + void foundMountPoint( const TQString & mountPoint, unsigned long kBSize, unsigned long kBUsed, unsigned long kBAvail ); + + // This one is a hack around a weird (compiler?) bug. In the former signal, + // the slot in KPropsDlg would get 0L, 0L as the last two parameters. + // When using const ulong& instead, all is ok. + void foundMountPoint( const unsigned long&, const unsigned long&, const unsigned long&, const TQString& ); + void done(); + +private slots: + void receivedDFStdErrOut(TDEProcess *, char *data, int len); + void dfDone(); + +private: + TDEProcess *dfProc; + TQCString dfStringErrOut; + TQString m_mountPoint; + bool readingDFStdErrOut; + class KDiskFreeSpPrivate; + KDiskFreeSpPrivate * d; +}; +/***************************************************************************/ + + +#endif diff --git a/src/app/MountMan/kmountman.cpp b/src/app/MountMan/kmountman.cpp new file mode 100644 index 0000000..a9fc946 --- /dev/null +++ b/src/app/MountMan/kmountman.cpp @@ -0,0 +1,327 @@ +/*************************************************************************** + 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" +// TDE 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" diff --git a/src/app/MountMan/kmountman.h b/src/app/MountMan/kmountman.h new file mode 100644 index 0000000..1503544 --- /dev/null +++ b/src/app/MountMan/kmountman.h @@ -0,0 +1,103 @@ +/*************************************************************************** + kmountman.h + ------------------- + begin : Thu May 4 2000 + 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 + + H e a d e r 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. * +* * +***************************************************************************/ +#ifndef KMOUNTMAN_H +#define KMOUNTMAN_H + +// TQt includes +#include <tqobject.h> +#include <tqstring.h> + +// TDE includes +#include <tdeversion.h> +#include <tdeio/jobclasses.h> +#include <tdeio/job.h> +#include <tdeio/global.h> +#include <kmountpoint.h> + +// krusader includes +#include <stdlib.h> +#include <math.h> + +class KMountManGUI; + +class KMountMan : public TQObject { + TQ_OBJECT + + friend class KMountManGUI; + +public: + enum mntStatus {DOESNT_EXIST, NOT_MOUNTED, MOUNTED}; + + inline bool operational() { + return Operational; + } // check this 1st + + void mainWindow(); // opens up the GUI + void mount( TQString mntPoint, bool blocking=true ); // this is probably what you need for mount + void unmount( TQString mntPoint, bool blocking=true ); // this is probably what you need for unmount + mntStatus getStatus( TQString mntPoint ); // return the status of a mntPoint (if any) + void autoMount( TQString path ); // just call it before refreshing into a dir + static void eject( TQString mntPoint ); + bool ejectable( TQString path ); + TQString convertSize( TDEIO::filesize_t size ); + bool invalidFilesystem(TQString type); + bool nonmountFilesystem(TQString type, TQString mntPoint); + + KMountMan(); + ~KMountMan(); + +public slots: + void delayedPerformAction( int idx ); + void performAction( int idx ); + void quickList(); + +protected slots: + void jobResult(TDEIO::Job *job); + +protected: + // used internally + static KMountPoint *findInListByMntPoint(KMountPoint::List &lst, TQString value); + void toggleMount( TQString mntPoint ); + +private: + TQString *_actions; + +private: + bool Operational; // if false, something went terribly wrong on startup + bool waiting; // used to block krusader while waiting for (un)mount operation + KMountManGUI *mountManGui; + // the following is the FS type + TQStringList invalid_fs; + TQStringList nonmount_fs; + // the following is the FS name + TQStringList nonmount_fs_mntpoint; +}; + +#endif diff --git a/src/app/MountMan/kmountmangui.cpp b/src/app/MountMan/kmountmangui.cpp new file mode 100644 index 0000000..338d2e0 --- /dev/null +++ b/src/app/MountMan/kmountmangui.cpp @@ -0,0 +1,396 @@ +/*************************************************************************** + kmountmangui.cpp + ------------------- + copyright : (C) 2000 by Shie Erlich & Rafi Yanai + e-mail : krusader@users.sourceforge.net + web site : http://krusader.sourceforge.net +--------------------------------------------------------------------------- +Description +*************************************************************************** + +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 "kmountmangui.h" +#include "kmountman.h" +#include "../krusader.h" +#include "../Dialogs/krspecialwidgets.h" +#include "../kicons.h" +#include "../defaults.h" +#include "../VFS/vfs.h" +#include <tdelocale.h> +#include <tqpixmap.h> +#include <tdepopupmenu.h> +#include <tqbitmap.h> +#include <tdemessagebox.h> +#include <tqlayout.h> +#include <tqgroupbox.h> +#include <kprocess.h> +#include <tqcursor.h> +#include <kdebug.h> +#include <kguiitem.h> +#include <tqfileinfo.h> +#include <sys/param.h> + +#if defined(BSD) +#include <kmountpoint.h> +#include <kmdcodec.h> +#else +#define MTAB "/etc/mtab" +#endif + +// use our version of it until kde fixes theirs +#include "kdiskfreesp.h" + +KMountManGUI::KMountManGUI() : KDialogBase( krApp, 0, true, "Mount.Man" ), +info( 0 ), mountList( 0 ) { + watcher = new TQTimer( this ); + connect( watcher, TQ_SIGNAL( timeout() ), this, TQ_SLOT( checkMountChange() ) ); + + connect( this, TQ_SIGNAL( finishedGettingSpaceData() ), this, TQ_SLOT( updateList() ) ); + setButtonOK( i18n( "&Close" ) ); + showButtonApply( false ); showButtonCancel( false ); + setPlainCaption( i18n( "MountMan - Your Mount-Manager" ) ); + widget = new KJanusWidget( this, 0, KJanusWidget::Tabbed ); + createLayout(); + setMainWidget( widget ); + widget->setMinimumSize( widget->sizeHint().width() + mountList->columnWidth( 5 ), + widget->sizeHint().height() ); + setMinimumSize( widget->minimumSize().width(), widget->minimumSize().height() ); + resize( minimumSize() ); + + // connections + connect( mountList, TQ_SIGNAL( doubleClicked( TQListViewItem * ) ), this, + TQ_SLOT( doubleClicked( TQListViewItem* ) ) ); + connect( mountList, TQ_SIGNAL( contextMenuRequested( TQListViewItem *, const TQPoint &, int ) ), + this, TQ_SLOT( clicked( TQListViewItem*, const TQPoint&, int ) ) ); + connect( mountList, TQ_SIGNAL( clicked( TQListViewItem * ) ), this, + TQ_SLOT( changeActive( TQListViewItem * ) ) ); + connect( mountList, TQ_SIGNAL( selectionChanged( TQListViewItem * ) ), this, + TQ_SLOT( changeActive( TQListViewItem * ) ) ); + + getSpaceData(); + exec(); +} + +KMountManGUI::~KMountManGUI() { + watcher->stop(); + delete watcher; +} + +void KMountManGUI::createLayout() { + mainPage = widget->addPage( i18n( "Filesystems" ), 0 ); + createMainPage(); + widget->showPage( Filesystems ); +} + +void KMountManGUI::createMainPage() { + // check if we need to clean up first! + if ( mountList != 0 ) { + mountList->hide(); + delete mountList; + mountList = 0; + } + // clean up is finished... + TQGridLayout *layout = new TQGridLayout( mainPage, 1, 1 ); + mountList = new TQListView( mainPage ); // create the main container + krConfig->setGroup( "Look&Feel" ); + mountList->setFont( krConfig->readFontEntry( "Filelist Font", _FilelistFont ) ); + mountList->setAllColumnsShowFocus( true ); + mountList->setMultiSelection( false ); + mountList->setSelectionMode( TQListView::Single ); + mountList->setVScrollBarMode( TQScrollView::AlwaysOn ); + mountList->setHScrollBarMode( TQScrollView::Auto ); + mountList->setShowSortIndicator( true ); + int i = TQFontMetrics( mountList->font() ).width( "W" ); + int j = TQFontMetrics( mountList->font() ).width( "0" ); + j = ( i > j ? i : j ); + mountList->addColumn( i18n( "Name" ), j * 8 ); + mountList->addColumn( i18n( "Type" ), j * 4 ); + mountList->addColumn( i18n( "Mnt.Point" ), j * 6 ); + mountList->addColumn( i18n( "Total Size" ), j * 6 ); + mountList->addColumn( i18n( "Free Size" ), j * 6 ); + mountList->addColumn( i18n( "Free %" ), j * 5 ); + mountList->setColumnWidthMode( 0, TQListView::Maximum ); + mountList->setColumnWidthMode( 1, TQListView::Maximum ); + mountList->setColumnWidthMode( 2, TQListView::Maximum ); + mountList->setColumnWidthMode( 3, TQListView::Maximum ); + mountList->setColumnWidthMode( 4, TQListView::Maximum ); + mountList->setColumnWidthMode( 5, TQListView::Maximum ); + // now the list is created, time to fill it with data. + //=>krMtMan.forceUpdate(); + TQGroupBox *box = new TQGroupBox( "MountMan.Info", mainPage ); + box->setAlignment( TQt::AlignHCenter ); + info = new KRFSDisplay( box ); + info->resize( info->width(), height() ); + layout->addWidget( box, 0, 0 ); + layout->addWidget( mountList, 0, 1 ); +} + +void KMountManGUI::getSpaceData() { + fileSystemsTemp.clear(); + KrMountDetector::getInstance()->hasMountsChanged(); + + mounted = KMountPoint::currentMountPoints(); + possible = KMountPoint::possibleMountPoints(); + if ( mounted.size() == 0 ) { // nothing is mounted + updateList(); // let's continue + return ; + } + + numOfMountPoints = mounted.size(); + for ( KMountPoint::List::iterator it = mounted.begin(); it != mounted.end(); ++it ) { + // don't bother with invalid file systems + if (krMtMan.invalidFilesystem((*it)->mountType())) { + --numOfMountPoints; + continue; + } + KDiskFreeSp *sp = KDiskFreeSp::findUsageInfo( ( *it ) ->mountPoint() ); + connect( sp, TQ_SIGNAL( foundMountPoint( const TQString &, unsigned long, unsigned long, unsigned long ) ), + this, TQ_SLOT( gettingSpaceData( const TQString&, unsigned long, unsigned long, unsigned long ) ) ); + connect( sp, TQ_SIGNAL( done() ), this, TQ_SLOT( gettingSpaceData() ) ); + } +} + +// this decrements the counter, while the following uses the data +// used when certain filesystem (/dev, /sys) can't have the needed stats +void KMountManGUI::gettingSpaceData() { + if ( --numOfMountPoints == 0 ) { + fileSystems = fileSystemsTemp; + emit finishedGettingSpaceData(); + } +} + +void KMountManGUI::gettingSpaceData( const TQString &mountPoint, unsigned long kBSize, + unsigned long /*kBUsed*/, unsigned long kBAvail ) { + KMountPoint *m = KMountMan::findInListByMntPoint( mounted, mountPoint ); + if ( !m ) { // this should never never never happen! + KMessageBox::error( 0, i18n( "Critical Error" ), + i18n( "Internal error in MountMan\nPlease email the developers" ) ); + exit( 1 ); + } + fsData data; + data.setMntPoint( mountPoint ); + data.setMounted( true ); + data.setTotalBlks( kBSize ); + data.setFreeBlks( kBAvail ); + data.setName( m->mountedFrom() ); + data.setType( m->mountType() ); + fileSystemsTemp.append( data ); +} + +void KMountManGUI::addItemToMountList( TQListView *lst, fsData &fs ) { + bool mtd = fs.mounted(); + + TQString tSize = TQString( "%1" ).arg( TDEIO::convertSizeFromKB( fs.totalBlks() ) ); + TQString fSize = TQString( "%1" ).arg( TDEIO::convertSizeFromKB( fs.freeBlks() ) ); + TQString sPrct = TQString( "%1%" ).arg( 100 - ( fs.usedPerct() ) ); + TQListViewItem *item = new TQListViewItem( lst, fs.name(), + fs.type(), fs.mntPoint(), + ( mtd ? tSize : TQString( "N/A" ) ), ( mtd ? fSize : TQString( "N/A" ) ), + ( mtd ? sPrct : TQString( "N/A" ) ) ); + + TQString id = fs.name().left(7); // only works assuming devices start with "/dev/XX" + TQPixmap *icon = 0; + if ( id == "/dev/fd") { + icon = new TQPixmap( LOADICON( mtd ? "media-floppy-3_5-mounted" : "media-floppy-3_5-unmounted" ) ); + } else if ( id == "/dev/cd" || fs.type() == "iso9660" ) { + icon = new TQPixmap( LOADICON( mtd ? "media-optical-cdrom-mounted" : "media-optical-cdrom-unmounted" ) ); + } else if ( fs.type() == "nfs" || fs.type() == "smbfs" ) { + icon = new TQPixmap( LOADICON( mtd ? "nfs-mounted" : "nfs-unmounted" ) ); + } else icon = new TQPixmap( LOADICON( mtd ? "drive-harddisk-mounted" : "drive-harddisk-unmounted" ) ); + + item->setPixmap( 0, *icon ); + delete icon; +} + +void KMountManGUI::updateList() { + mountList->clear(); + // this handles the mounted ones + for ( TQValueList<fsData>::iterator it = fileSystems.begin(); it != fileSystems.end() ; ++it ) { + if (krMtMan.invalidFilesystem((*it).type())) { + continue; + } + addItemToMountList( mountList, *it ); + } + + // now, handle the non-mounted ones + for (KMountPoint::List::iterator it = possible.begin(); it != possible.end(); ++it) { + // make sure we don't add things we've already added + if (KMountMan::findInListByMntPoint(mounted, (*it)->mountPoint())) { + continue; + } else { + fsData data; + data.setMntPoint((*it)->mountPoint()); + data.setMounted(false); + data.setType((*it)->mountType()); + data.setName((*it)->mountedFrom()); + fileSystems.append(data); + + if (krMtMan.invalidFilesystem(data.type())) continue; + addItemToMountList(mountList, data); + } + } + + mountList->clearSelection(); + if ( info ) { + info->setEmpty( true ); + info->repaint(); + } + watcher->start( WATCHER_DELAY, true ); // starting the watch timer ( single shot ) +} + +void KMountManGUI::checkMountChange() { + if (KrMountDetector::getInstance()->hasMountsChanged()) + getSpaceData(); + watcher->start( WATCHER_DELAY, true ); // starting the watch timer ( single shot ) +} + +void KMountManGUI::doubleClicked( TQListViewItem *i ) { + if ( !i ) + return; // we don't want to refresh to swap, do we ? + + // change the active panel to this mountpoint + connect( ( TQObject* ) this, TQ_SIGNAL( refreshPanel( const KURL & ) ), ( TQObject* ) SLOTS, + TQ_SLOT( refresh( const KURL & ) ) ); + emit refreshPanel( vfs::fromPathOrURL( i->text(2) ) ); // text(2) ? so ugly ... + disconnect( this, TQ_SIGNAL( refreshPanel( const KURL & ) ), 0, 0 ); + slotClose(); +} + +// when user clicks on a filesystem, change information +void KMountManGUI::changeActive( TQListViewItem *i ) { + if ( !i ) return ; + fsData *system = 0; + + for (TQValueList<fsData>::Iterator it = fileSystems.begin(); it != fileSystems.end(); ++it) { + // the only thing which is unique is the mount point + if ((*it).mntPoint() == i->text(2)) { // text(2) ? ugly ugly ugly + system = &(*it); + break; + } + } + + if (system == 0) { + KMessageBox::error(0, i18n("Critical Error"), i18n("Internal error in MountMan\nCall the developers")); + exit(1); + } + info->setAlias( system->mntPoint() ); + info->setRealName( system->name() ); + info->setMounted( system->mounted() ); + info->setEmpty( false ); + info->setTotalSpace( system->totalBlks() ); + info->setFreeSpace( system->freeBlks() ); + info->repaint(); +} + +// called when right-clicked on a filesystem +void KMountManGUI::clicked( TQListViewItem *item, const TQPoint& pos, int /* col */ ) { + // these are the values that will exist in the menu +#define MOUNT_ID 90 +#define UNMOUNT_ID 91 +#define FORMAT_ID 93 +#define EJECT_ID 94 + ////////////////////////////////////////////////////////// + if ( !item ) return ; + + fsData *system = 0; + for (TQValueList<fsData>::Iterator it = fileSystems.begin(); it != fileSystems.end(); ++it) { + // the only thing which is unique is the mount point + if ((*it).mntPoint() == item->text(2)) { // text(2) ? ugly ugly ugly + system = &(*it); + break; + } + } + + if ( !system ) { + KMessageBox::error( 0, i18n( "MountMan has an internal error. Please notify the developers. Thank you." ) ); + exit( 0 ); + } + // create the menu + TDEPopupMenu popup; + popup.insertTitle( i18n( "MountMan" ) ); + if ( !system->mounted() ) { + popup.insertItem( i18n( "Mount" ), MOUNT_ID ); + bool enable = !(krMtMan.nonmountFilesystem(system->type(), system->mntPoint())); + popup.setItemEnabled( MOUNT_ID, enable); + } else { + popup.insertItem( i18n( "Unmount" ), UNMOUNT_ID ); + bool enable = !(krMtMan.nonmountFilesystem(system->type(), system->mntPoint())); + popup.setItemEnabled( UNMOUNT_ID, enable); + } + if ( krMtMan.ejectable( system->mntPoint() ) ) + // if (system->type()=="iso9660" || krMtMan.followLink(system->name()).left(2)=="cd") + popup.insertItem( i18n( "Eject" ), EJECT_ID ); + else { + popup.insertItem( i18n( "Format" ), FORMAT_ID ); + popup.setItemEnabled( FORMAT_ID, false ); + } + + TQString mountPoint = system->mntPoint(); + + int result = popup.exec( pos ); + // check out the user's option + switch ( result ) { + case - 1 : return ; // the user clicked outside of the menu + case MOUNT_ID : + case UNMOUNT_ID : + krMtMan.toggleMount( mountPoint ); + break; + case FORMAT_ID : + break; + case EJECT_ID : + KMountMan::eject( mountPoint ); + break; + } +} + +KrMountDetector::KrMountDetector() { + hasMountsChanged(); +} + +bool KrMountDetector::hasMountsChanged() { +#if defined(BSD) + KMountPoint::List mountPoints = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName); + KMD5 md5; + for(KMountPoint::List::iterator i = mountPoints.begin(); i != mountPoints.end(); ++i) { + md5.update((*i)->mountedFrom().utf8()); + md5.update((*i)->realDeviceName().utf8()); + md5.update((*i)->mountPoint().utf8()); + md5.update((*i)->mountType().utf8()); + } + TQString s = md5.hexDigest(); + bool result = s != checksum; + checksum = s; +#else + bool result = TQFileInfo(MTAB).lastModified() != lastMtab; + lastMtab = TQFileInfo(MTAB).lastModified(); +#endif + return result; +} + +KrMountDetector krMountDetector; +KrMountDetector * KrMountDetector::getInstance() { + return & krMountDetector; +} + +#include "kmountmangui.moc" diff --git a/src/app/MountMan/kmountmangui.h b/src/app/MountMan/kmountmangui.h new file mode 100644 index 0000000..72fe8d2 --- /dev/null +++ b/src/app/MountMan/kmountmangui.h @@ -0,0 +1,199 @@ +/*************************************************************************** + kmountmangui.h + ------------------- + begin : Thu May 4 2000 + copyright : (C) 2000 by Shie Erlich & Rafi Yanai + e-mail : krusader@users.sourceforge.net + web site : http://krusader.sourceforge.net +--------------------------------------------------------------------------- + Description +*************************************************************************** + + 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 + + H e a d e r 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. * +* * +***************************************************************************/ + + +#ifndef KMOUNTMANGUI_H +#define KMOUNTMANGUI_H + +#include <sys/param.h> +#include <kdialogbase.h> +#include <tqlistview.h> +#include <kjanuswidget.h> +#include <tqtimer.h> +#include <kurl.h> +#include <tqvaluelist.h> +#include <kmountpoint.h> +#include <tqdatetime.h> +#include "kmountman.h" + +#define WATCHER_DELAY 3000 + +class KRFSDisplay; +class KRdirWatch; + + +// forward definitions +class fsData; + +class KMountManGUI : public KDialogBase { + TQ_OBJECT + + + enum Pages { + Filesystems = 0 + }; + +public: + KMountManGUI(); + ~KMountManGUI(); + void createLayout(); // calls the various tab layout-creators + void createMainPage(); // creator of the main page - filesystems + +protected slots: + void doubleClicked( TQListViewItem * ); + void clicked( TQListViewItem *, const TQPoint& pos, int col ); + void changeActive( TQListViewItem * ); + void checkMountChange(); // check whether the mount table was changed + + void updateList(); // fill-up the filesystems list + void getSpaceData(); + void gettingSpaceData(); + void gettingSpaceData(const TQString &mountPoint, unsigned long kBSize, + unsigned long kBUsed, unsigned long kBAvail); + +protected: + void addItemToMountList( TQListView *lst, fsData &fs ); + +signals: + void refreshPanel( const KURL & ); + void finishedGettingSpaceData(); + +private: + KRFSDisplay *info; + TQFrame *mainPage; + KJanusWidget *widget; + TQListView *mountList; + TQTimer *watcher; + TQDateTime lastMtab; + // used for the getSpace - gotSpace functions + KMountPoint::List possible, mounted; + TQValueList<fsData> fileSystems; + TQValueList<fsData> fileSystemsTemp; // first collect to a temporary place + int numOfMountPoints; +}; + + +// Data container for a single-filesystem data +// maximum size supported is 2GB of 1kb blocks == 2048GB, enough. +// not really needed, but kept for backward compatiblity +///////////////////////////////////////////////////////////////// +class fsData { +public: + fsData() : Name( 0 ), Type( 0 ), MntPoint( 0 ), TotalBlks( 0 ), + FreeBlks( 0 ), Mounted( false ) {} + + // get information + inline TQString name() { + return Name; + } + inline TQString shortName() { + return Name.right( Name.length() - Name.find( "/", 1 ) - 1 ); + } + inline TQString type() { + return Type; + } + inline TQString mntPoint() { + return MntPoint; + } + inline long totalBlks() { + return TotalBlks; + } + inline long freeBlks() { + return FreeBlks; + } + inline TDEIO::filesize_t totalBytes() { + return TotalBlks * 1024; + } + inline TDEIO::filesize_t freeBytes() { + return FreeBlks * 1024; + } + //////////////////// insert a good round function here ///////////////// + int usedPerct() { + if ( TotalBlks == 0 ) + return 0; + float res = ( ( float ) ( TotalBlks - FreeBlks ) ) / ( ( float ) TotalBlks ) * 100; + if ( ( res - ( int ) res ) > 0.5 ) + return ( int ) res + 1; + else + return ( int ) res; + } + inline bool mounted() { + return Mounted; + } + + // set information + inline void setName( TQString n_ ) { + Name = n_; + } + inline void setType( TQString t_ ) { + Type = t_; + } + inline void setMntPoint( TQString m_ ) { + MntPoint = m_; + } + inline void setTotalBlks( long t_ ) { + TotalBlks = t_; + } + inline void setFreeBlks( long f_ ) { + FreeBlks = f_; + } + inline void setMounted( bool m_ ) { + Mounted = m_; + } + +private: + TQString Name; // i.e: /dev/cdrom + TQString Type; // i.e: iso9600 + TQString MntPoint; // i.e: /mnt/cdrom + long TotalBlks; // measured in 1024bytes per block + long FreeBlks; + bool Mounted; // true if filesystem is mounted + + // additional attributes of a filesystem, parsed from fstab +public: + TQString options; // additional fstab options +}; + +class KrMountDetector { +#if defined(BSD) + TQString checksum; +#else + TQDateTime lastMtab; +#endif +public: + KrMountDetector(); + static KrMountDetector * getInstance(); + bool hasMountsChanged(); +}; + + + +#endif |