summaryrefslogtreecommitdiffstats
path: root/smb4k/core/smb4kmounter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'smb4k/core/smb4kmounter.cpp')
-rw-r--r--smb4k/core/smb4kmounter.cpp1718
1 files changed, 1718 insertions, 0 deletions
diff --git a/smb4k/core/smb4kmounter.cpp b/smb4k/core/smb4kmounter.cpp
new file mode 100644
index 0000000..45ccc9c
--- /dev/null
+++ b/smb4k/core/smb4kmounter.cpp
@@ -0,0 +1,1718 @@
+/***************************************************************************
+ smb4kmounter.cpp - The core class that mounts the shares.
+ -------------------
+ begin : Die Jun 10 2003
+ copyright : (C) 2003-2007 by Alexander Reinholdt
+ email : dustpuppy@users.berlios.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * 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. *
+ * *
+ * This program 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 *
+ * General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
+ * MA 02110-1301 USA *
+ ***************************************************************************/
+
+// Qt includes
+#include <qapplication.h>
+#include <qdir.h>
+#include <qtextstream.h>
+#include <qfile.h>
+#include <qtextstream.h>
+
+// KDE includes
+#include <kapplication.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+// system includes
+#if !defined(__FreeBSD__) && !defined(__solaris__) && !defined(USE_SOLARIS)
+#include <sys/statfs.h>
+#elif defined(__solaris__) || defined(USE_SOLARIS)
+#include <sys/statvfs.h>
+#elif defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif
+#include <sys/types.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+
+#ifdef __FreeBSD__
+#include <sys/param.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+#include <qfileinfo.h>
+#endif
+
+// Application specific includes
+#include "smb4kmounter.h"
+#include "smb4kmounter_p.h"
+#include "smb4kauthinfo.h"
+#include "smb4ksambaoptionsinfo.h"
+#include "smb4kerror.h"
+#include "smb4kglobal.h"
+#include "smb4ksambaoptionshandler.h"
+#include "smb4kpasswordhandler.h"
+#include "smb4kshare.h"
+#include "smb4ksettings.h"
+
+using namespace Smb4KGlobal;
+
+
+Smb4KMounter::Smb4KMounter( QObject *parent, const char *name ) : QObject( parent, name )
+{
+ m_priv = new Smb4KMounterPrivate;
+
+ m_proc = new KProcess( this, "MounterProcess" );
+ m_proc->setUseShell( true );
+
+ m_working = false;
+
+ m_queue.setAutoDelete( true );
+
+ connect( m_proc, SIGNAL( processExited( KProcess * ) ),
+ this, SLOT( slotProcessExited( KProcess * ) ) );
+
+ connect( m_proc, SIGNAL( receivedStdout( KProcess *, char *, int ) ),
+ this, SLOT( slotReceivedStdout( KProcess *, char *, int ) ) );
+
+ connect( m_proc, SIGNAL( receivedStderr( KProcess *, char *, int ) ),
+ this, SLOT( slotReceivedStderr( KProcess *, char *, int ) ) );
+
+ connect( kapp, SIGNAL( shutDown() ),
+ this, SLOT( slotShutdown() ) );
+}
+
+
+Smb4KMounter::~Smb4KMounter()
+{
+ abort();
+
+ for ( QValueList<Smb4KShare *>::Iterator it = m_mounted_shares.begin(); it != m_mounted_shares.end(); ++it )
+ {
+ delete *it;
+ }
+
+ m_mounted_shares.clear();
+
+ delete m_priv;
+}
+
+
+void Smb4KMounter::init()
+{
+ m_queue.enqueue( new QString( QString( "%1:" ).arg( Import ) ) );
+ m_queue.enqueue( new QString( QString( "%1:" ).arg( Remount ) ) );
+
+ startTimer( TIMER_INTERVAL );
+}
+
+
+/***************************************************************************
+ Aborts any action of the mounter.
+***************************************************************************/
+
+
+void Smb4KMounter::abort()
+{
+ m_queue.clear();
+
+ if ( m_proc->isRunning() )
+ {
+ if ( Smb4KSettings::alwaysUseSuperUser() )
+ {
+ QString suid_program;
+
+ switch( Smb4KSettings::superUserProgram() )
+ {
+ case Smb4KSettings::EnumSuperUserProgram::Sudo:
+ {
+ suid_program = Smb4KSettings::sudo();
+
+ break;
+ }
+ case Smb4KSettings::EnumSuperUserProgram::Super:
+ {
+ suid_program = Smb4KSettings::super();
+
+ break;
+ }
+ default:
+ {
+ // FIXME: Throw an error?
+ return;
+ }
+ }
+
+ KProcess proc;
+ proc.setUseShell( true );
+ proc << QString( "%1 smb4k_kill %2" ).arg( suid_program ).arg( m_proc->pid() );
+ proc.start( KProcess::DontCare, KProcess::NoCommunication );
+ }
+ else
+ {
+ m_proc->kill();
+ }
+ }
+}
+
+
+/***************************************************************************
+ Mounts recently used shares.
+***************************************************************************/
+
+
+void Smb4KMounter::remount()
+{
+ if ( Smb4KSettings::remountShares() )
+ {
+ const QValueList<Smb4KSambaOptionsInfo *> *list = &(optionsHandler()->customOptionsList());
+
+ for ( QValueList<Smb4KSambaOptionsInfo *>::ConstIterator it = list->begin();
+ it != list->end(); ++it )
+ {
+ if ( (*it)->remount() )
+ {
+ QValueList<Smb4KShare> list = findShareByName( (*it)->itemName() );
+
+ bool mount = true;
+
+ if ( !list.isEmpty() )
+ {
+ for ( QValueList<Smb4KShare>::ConstIterator it = list.begin(); it != list.end(); ++it )
+ {
+ if ( !(*it).isForeign() )
+ {
+ mount = false;
+
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ }
+
+ if ( mount )
+ {
+#ifndef __FreeBSD__
+ mountShare( QString::null, (*it)->itemName().section( "/", 2, 2 ), QString::null, (*it)->itemName().section( "/", 3, 3 ) );
+#else
+ mountShare( QString::null, (*it)->itemName().section( "/", 2, 2 ).section( "@", 1, 1 ), QString::null, (*it)->itemName().section( "/", 3, 3 ) );
+#endif
+ }
+
+ // If the share is to be remounted the next time,
+ // slotShutdown() will tell the options handler.
+ (*it)->setRemount( false );
+
+ continue;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ m_working = false;
+ emit state( MOUNTER_STOP );
+ }
+ else
+ {
+ m_working = false;
+ emit state( MOUNTER_STOP );
+ }
+}
+
+
+/***************************************************************************
+ Imports all shares, that are mounted externally.
+***************************************************************************/
+
+void Smb4KMounter::import()
+{
+ QValueList<Smb4KShare *> shares;
+
+#ifndef __FreeBSD__
+
+ if ( m_proc_mounts.name().isEmpty() )
+ {
+ m_proc_mounts.setName( "/proc/mounts" );
+ }
+
+ if ( !QFile::exists( m_proc_mounts.name() ) )
+ {
+ if ( !m_proc_error )
+ {
+ m_proc_error = true;
+ Smb4KError::error( ERROR_FILE_NOT_FOUND, m_proc_mounts.name() );
+ }
+ else
+ {
+ // No need to do anything here
+ }
+ }
+ else
+ {
+ QStringList contents, list;
+
+ // Read /proc/mounts:
+
+ if ( m_proc_mounts.open( IO_ReadOnly ) )
+ {
+ QTextStream ts( &m_proc_mounts );
+ ts.setEncoding( QTextStream::Locale );
+
+ contents = QStringList::split( "\n", ts.read(), false );
+
+ m_proc_mounts.close();
+ }
+ else
+ {
+ Smb4KError::error( ERROR_OPENING_FILE, m_proc_mounts.name() );
+
+ return;
+ }
+
+ // Process the SMBFS and CIFS entries:
+
+ list += contents.grep( " smbfs ", true );
+ list += contents.grep( " cifs ", true );
+
+ if ( !list.isEmpty() )
+ {
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); it++ )
+ {
+ Smb4KShare *new_share = NULL;
+
+ if ( (*it).contains( " smbfs ", false ) != 0 )
+ {
+ QString share_and_path = (*it).section( " smbfs ", 0, 0 ).stripWhiteSpace();
+ QString name = share_and_path.section( " ", 0, 0 ).stripWhiteSpace().replace( "\\040", "\040" );
+ QString path = share_and_path.section( " ", 1, 1 ).stripWhiteSpace();
+
+ if ( path.contains( "\\040" ) != 0 || path.contains( "\040" ) != 0 )
+ {
+ name.replace( "_", "\040" );
+ path.replace( "\\040", "\040" );
+ }
+
+ int uid = (*it).section( "uid=", 1, 1 ).section( ",", 0, 0 ).stripWhiteSpace().toInt();
+ int gid = (*it).section( "gid=", 1, 1 ).section( ",", 0, 0 ).stripWhiteSpace().toInt();
+
+ new_share = new Smb4KShare( name, path, "smbfs", uid, gid );
+ }
+ else if ( (*it).contains( " cifs ", false ) != 0 )
+ {
+ QString share_and_path = (*it).section( " cifs ", 0, 0 ).stripWhiteSpace();
+ QString name = share_and_path.section( " ", 0, 0 ).stripWhiteSpace().replace( "\\040", "\040" );
+ QString path = share_and_path.section( " ", 1, 1 ).stripWhiteSpace();
+
+ if ( path.contains( "\\040" ) != 0 || path.contains( "\040" ) != 0 )
+ {
+ name.replace( "_", "\040" );
+ path.replace( "\\040", "\040" );
+ }
+
+ QString login = (*it).section( "username=", 1, 1 ).section( ",", 0, 0 ).stripWhiteSpace();
+
+ new_share = new Smb4KShare( name, path, "cifs", login );
+ }
+ else
+ {
+ continue;
+ }
+
+ if ( new_share )
+ {
+ // If the a representative of the new share is already in the list of
+ // mounted shares, replace the new with the old one.
+
+ Smb4KShare *existing_share = findShareByPath( new_share->path() );
+
+ if ( existing_share )
+ {
+ delete new_share;
+ new_share = new Smb4KShare( *existing_share );
+ }
+
+ // Check if the share is broken and/or foreign.
+
+ if ( (existing_share && !existing_share->isBroken()) || !existing_share )
+ {
+ checkAccessibility( new_share );
+ }
+ else
+ {
+ // Since new_share is a copy of existing_share, we do not need to do
+ // anything here.
+ }
+
+ if ( !existing_share && QString::compare( new_share->filesystem(), "cifs" ) == 0 )
+ {
+ bool foreign = true;
+
+ if ( (!new_share->isBroken() &&
+ (qstrncmp( new_share->canonicalPath(),
+ QDir( Smb4KSettings::mountPrefix() ).canonicalPath(),
+ QDir( Smb4KSettings::mountPrefix() ).canonicalPath().length() ) == 0 ||
+ qstrncmp( new_share->canonicalPath(),
+ QDir::home().canonicalPath(),
+ QDir::home().canonicalPath().length() ) == 0)) ||
+ (new_share->isBroken() &&
+ (qstrncmp( new_share->path(),
+ QDir::homeDirPath(),
+ QDir::homeDirPath().length() ) == 0 ||
+ qstrncmp( new_share->path(),
+ Smb4KSettings::mountPrefix(),
+ Smb4KSettings::mountPrefix().length() ) == 0)) )
+ {
+ foreign = false;
+ }
+
+ new_share->setForeign( foreign );
+ }
+
+ shares.append( new_share );
+ }
+ }
+ }
+ }
+
+#else
+
+ struct statfs *buf;
+ int count = getmntinfo( &buf, 0 );
+
+ if ( count == 0 )
+ {
+ int err_code = errno;
+
+ Smb4KError::error( ERROR_IMPORTING_SHARES, QString::null, strerror( err_code ) );
+
+ m_working = false;
+ return;
+ }
+
+ for ( int i = 0; i < count; ++i )
+ {
+ if ( !strcmp( buf[i].f_fstypename, "smbfs" ) )
+ {
+ QString share_name( buf[i].f_mntfromname );
+ QString path( buf[i].f_mntonname );
+ QString fs( buf[i].f_fstypename );
+
+ QFileInfo info( QString( buf[i].f_mntonname )+"/." );
+
+ int uid = (int)info.ownerId();
+ int gid = (int)info.groupId();
+
+ Smb4KShare *existing_share = findShareByPath( path );
+ Smb4KShare *new_share = NULL;
+
+ if ( existing_share )
+ {
+ new_share = new Smb4KShare( *existing_share );
+ }
+ else
+ {
+ new_share = new Smb4KShare( share_name, path, fs, uid, gid );
+ }
+
+ // Test if share is broken
+ if ( (existing_share && !existing_share->isBroken()) || !existing_share )
+ {
+ checkAccessibility( new_share );
+ }
+ else
+ {
+ // Since new_share is a copy of existing_share, we do not need to do
+ // anything here.
+ }
+
+ shares.append( new_share );
+ }
+ }
+
+ // Apparently, under FreeBSD we do not need to delete
+ // the pointer (see manual page).
+
+#endif
+
+ // Delete all entries of m_mounted_shares.
+ for ( QValueList<Smb4KShare *>::Iterator it = m_mounted_shares.begin(); it != m_mounted_shares.end(); ++it )
+ {
+ delete *it;
+ }
+
+ m_mounted_shares.clear();
+
+ m_mounted_shares = shares;
+
+ emit updated();
+
+ m_working = false;
+}
+
+
+/***************************************************************************
+ Mounts a share. (Public part)
+***************************************************************************/
+
+void Smb4KMounter::mountShare( const QString &workgroup, const QString &host, const QString &ip, const QString &share )
+{
+ QString share_name = QString::null;
+
+ if ( QString::compare( share, "homes" ) == 0 )
+ {
+ share_name = specifyUser( host, kapp->mainWidget() ? kapp->mainWidget() : 0, "SpecifyUser" );
+ }
+ else
+ {
+ share_name = share;
+ }
+
+ if ( !share_name.stripWhiteSpace().isEmpty() )
+ {
+ // Before doing anything else let's check that the
+ // share has not been mounted by the user already:
+ QValueList<Smb4KShare> list = findShareByName( QString( "//%1/%2" ).arg( host, share_name ) );
+
+ for ( QValueList<Smb4KShare>::ConstIterator it = list.begin(); it != list.end(); ++it )
+ {
+ if ( !(*it).isForeign() )
+ {
+ emit mountedShare( (*it).canonicalPath() );
+
+ return;
+ }
+ }
+
+ m_queue.enqueue( new QString( QString( "%1:%2:%3:%4:%5" ).arg( Mount )
+ .arg( workgroup, host )
+ .arg( ip, share_name ) ) );
+ }
+}
+
+
+
+/***************************************************************************
+ Mounts a share. (Private part)
+***************************************************************************/
+
+void Smb4KMounter::mount( const QString &workgroup, const QString &host, const QString &ip, const QString &share )
+{
+ m_priv->setWorkgroup( workgroup );
+ m_priv->setHost( host );
+ m_priv->setShare( share );
+ m_priv->setIP( ip );
+
+ // Create the mount point:
+ QDir *dir = new QDir( Smb4KSettings::mountPrefix() );
+
+ if ( !dir->exists() )
+ {
+ if ( !dir->mkdir( dir->canonicalPath() ) )
+ {
+ Smb4KError::error( ERROR_MKDIR_FAILED, dir->path() );
+ m_working = false;
+ emit state( MOUNTER_STOP );
+
+ return;
+ }
+ }
+
+ dir->setPath( dir->path() + "/" +
+ (Smb4KSettings::forceLowerCaseSubdirs() ?
+ m_priv->host().lower() :
+ m_priv->host()) );
+
+ if ( !dir->exists() )
+ {
+ if ( !dir->mkdir( dir->canonicalPath() ) )
+ {
+ Smb4KError::error( ERROR_MKDIR_FAILED, dir->path() );
+ m_working = false;
+ emit state( MOUNTER_STOP );
+
+ return;
+ }
+ }
+
+ dir->setPath( dir->path() + "/" +
+ (Smb4KSettings::forceLowerCaseSubdirs() ?
+ m_priv->share().lower() :
+ m_priv->share()) );
+
+ if ( !dir->exists() )
+ {
+ if ( !dir->mkdir( dir->canonicalPath() ) )
+ {
+ Smb4KError::error( ERROR_MKDIR_FAILED, dir->path() );
+ m_working = false;
+ emit state( MOUNTER_STOP );
+
+ return;
+ }
+ }
+
+ m_priv->setPath( QDir::cleanDirPath( dir->path() ) );
+
+ delete dir;
+
+ // Now we are prepared to mount the share:
+ QString command, suid_program;
+
+ switch ( Smb4KSettings::superUserProgram() )
+ {
+ case Smb4KSettings::EnumSuperUserProgram::Sudo:
+ {
+ suid_program = "sudo";
+
+ break;
+ }
+ case Smb4KSettings::EnumSuperUserProgram::Super:
+ {
+ suid_program = "super";
+
+ break;
+ }
+ default:
+ {
+ return;
+ }
+ }
+
+ Smb4KAuthInfo authInfo( m_priv->workgroup(), m_priv->host(), m_priv->share() );
+ (void) passwordHandler()->readAuth( &authInfo );
+
+#ifndef __FreeBSD__
+
+ // Let's see if the options handler knows the share:
+ Smb4KSambaOptionsInfo *info = optionsHandler()->findItem( QString( "//%1/%2" ).arg( m_priv->host(), m_priv->share() ), true );
+
+ // Determine the file system we have to use:
+ int filesystem;
+
+ if ( info )
+ {
+ filesystem = QString::compare( info->filesystem().lower(), "cifs" ) == 0 ?
+ Smb4KSettings::EnumFilesystem::CIFS :
+ Smb4KSettings::EnumFilesystem::SMBFS;
+ }
+ else
+ {
+ filesystem = Smb4KSettings::filesystem();
+ }
+
+ // Compile the mount command:
+ switch ( filesystem )
+ {
+ case Smb4KSettings::EnumFilesystem::CIFS:
+ {
+ command.append( Smb4KSettings::alwaysUseSuperUser() ? // FIXME: Check if suid program is installed
+ QString( "%1 smb4k_mount -s -t cifs " ).arg( suid_program ) :
+ "smb4k_mount -n -t cifs " );
+
+ command.append( "-o " );
+
+ command.append( optionsHandler()->mountOptions( QString( "//%1/%2" ).arg( m_priv->host(), m_priv->share() ) ) );
+
+ command.append( !m_priv->workgroup().stripWhiteSpace().isEmpty() ?
+ QString( "domain='%1'," ).arg( m_priv->workgroup() ) :
+ "" );
+
+ command.append( !m_priv->ip().stripWhiteSpace().isEmpty() ?
+ QString( "ip=%1," ).arg( m_priv->ip() ) :
+ "" );
+
+ command.append( !authInfo.user().isEmpty() ?
+ QString( "user=%1" ).arg( authInfo.user() ) :
+ "guest" );
+
+ command.append( " -- " );
+
+ command.append( QString( "//'%1'/'%2' '%3'" ).arg( m_priv->host(), m_priv->share(), m_priv->path() ) );
+
+ m_priv->setCIFSLogin( !authInfo.user().isEmpty() ?
+ authInfo.user() :
+ "guest" );
+
+ m_priv->setFileSystem( "cifs" );
+
+ break;
+ }
+ case Smb4KSettings::EnumFilesystem::SMBFS:
+ {
+ command.append( Smb4KSettings::alwaysUseSuperUser() ? // FIXME: Check if suid program is installed
+ QString( "%1 smb4k_mount -s -t smbfs " ).arg( suid_program ) :
+ "smb4k_mount -n -t smbfs " );
+
+ command.append( "-o " );
+
+ command.append( optionsHandler()->mountOptions( QString( "//%1/%2" ).arg( m_priv->host(), m_priv->share() ) ) );
+
+ command.append( !m_priv->workgroup().stripWhiteSpace().isEmpty() ?
+ QString( "workgroup='%1'," ).arg( m_priv->workgroup() ) :
+ "" );
+
+ command.append( !m_priv->ip().stripWhiteSpace().isEmpty() ?
+ QString( "ip=%1," ).arg( m_priv->ip() ) :
+ "" );
+
+ command.append( !authInfo.user().isEmpty() ?
+ QString( "username=%1" ).arg( authInfo.user() ) :
+ "guest" );
+
+ command.append( " -- " );
+
+ command.append( QString( "//'%1'/'%2' '%3'" ).arg( m_priv->host(), m_priv->share(), m_priv->path() ) );
+
+ m_priv->setFileSystem( "smbfs" );
+
+ break;
+ }
+ default:
+ {
+ return;
+ }
+ }
+
+ m_proc->setEnvironment( "PASSWD", !authInfo.password().isEmpty() ? authInfo.password() : "" );
+
+#else
+
+ Smb4KSambaOptionsInfo *info = optionsHandler()->findItem( "//"+m_priv->host()+"/"+m_priv->share() );
+
+ int port = info && info->port() != -1 ?
+ info->port() :
+ Smb4KSettings::remotePort();
+
+ command.append( Smb4KSettings::alwaysUseSuperUser() ? // FIXME: Check if suid program is installed
+ QString( "%1 smb4k_mount " ).arg( suid_program ) :
+ "smb4k_mount " );
+
+ command.append( optionsHandler()->mountOptions( QString( "//%1/%2" ).arg( m_priv->host(), m_priv->share() ) ) );
+
+ command.append( !m_priv->workgroup().stripWhiteSpace().isEmpty() ?
+ QString( " -W '%1'" ).arg( m_priv->workgroup() ) :
+ "" );
+
+ command.append( !m_priv->ip().stripWhiteSpace().isEmpty() ?
+ QString( " -I %1" ).arg( m_priv->ip() ) :
+ "" );
+
+ command.append( " -N" );
+
+ command.append( " -- " );
+
+ command.append( QString( "//%1@'%2':%3/'%4' '%5'" ).arg( !authInfo.user().isEmpty() ? authInfo.user() : "guest" )
+ .arg( m_priv->host() )
+ .arg( port )
+ .arg( m_priv->share(), m_priv->path() ) );
+
+#endif
+
+ // Start the mount process:
+ *m_proc << command;
+
+ startProcess( Mount );
+}
+
+
+/****************************************************************************
+ Unmount a share. (Public part)
+****************************************************************************/
+
+void Smb4KMounter::unmountShare( Smb4KShare *share, bool force, bool noMessage )
+{
+ // Do *not* change share->canonicalPath(). It is necessary for the
+ // checks below to work.
+ m_queue.enqueue( new QString( QString( "%1:%2:%3:%4" ).arg( Unmount )
+ .arg( share->canonicalPath() )
+ .arg( force, noMessage ) ) );
+}
+
+
+/***************************************************************************
+ Unmount a share. (Private part)
+***************************************************************************/
+
+void Smb4KMounter::unmount( const QString &mountpoint, bool force, bool noMessage )
+{
+ // First let's see if all requirements are fullfilled:
+
+ if ( force )
+ {
+ // Check that the user enabled the "Force Unmounting" ability:
+ if ( !Smb4KSettings::useForceUnmount() )
+ {
+ Smb4KError::error( ERROR_FEATURE_NOT_ENABLED );
+ m_working = false;
+ emit state( MOUNTER_STOP );
+
+ return;
+ }
+ }
+
+ // Compose the unmount command:
+ if ( !mountpoint.stripWhiteSpace().isEmpty() )
+ {
+ bool execute = false;
+
+ QString path = mountpoint;
+ m_priv->setPath( path.replace( '\044', "\044" ) );
+
+ QString suid_program, command;
+
+ if ( Smb4KSettings::useForceUnmount() || Smb4KSettings::alwaysUseSuperUser() )
+ {
+ switch ( Smb4KSettings::superUserProgram() )
+ {
+ case Smb4KSettings::EnumSuperUserProgram::Sudo:
+ {
+ suid_program = Smb4KSettings::sudo();
+
+ break;
+ }
+ case Smb4KSettings::EnumSuperUserProgram::Super:
+ {
+ suid_program = Smb4KSettings::super();
+
+ break;
+ }
+ default:
+ {
+ // FIXME: Throw an error?
+ return;
+ }
+ }
+ }
+
+ Smb4KShare *share = findShareByPath( mountpoint );
+
+ if ( share )
+ {
+ if ( !share->isForeign() )
+ {
+ if ( force )
+ {
+ if ( KMessageBox::questionYesNo( 0, i18n( "Do you really want to force the unmounting of this share?" ), QString::null, KStdGuiItem::yes(), KStdGuiItem::no(), "Dont Ask Forced", KMessageBox::Notify ) == KMessageBox::Yes )
+ {
+#ifdef __linux__
+ command.append( QString( "%1 smb4k_umount -s -l " ).arg( suid_program ) );
+#else
+#ifdef __FreeBSD__
+ command.append( QString( "%1 smb4k_umount " ).arg( suid_program ) );
+#else
+ command.append( QString( "%1 smb4k_umount -s " ).arg( suid_program ) );
+#endif
+#endif
+ execute = true;
+ }
+ else
+ {
+ m_working = false;
+ emit state( MOUNTER_STOP );
+
+ return;
+ }
+ }
+ else
+ {
+ if ( !Smb4KSettings::alwaysUseSuperUser() )
+ {
+#ifndef __FreeBSD__
+ command.append( "smb4k_umount -n " );
+#else
+ command.append( "smb4k_umount " );
+#endif
+ }
+ else
+ {
+#ifndef __FreeBSD__
+ command.append( QString( "%1 smb4k_umount -s " ).arg( suid_program ) );
+#else
+ command.append( QString( "%1 smb4k_umount " ).arg( suid_program ) );
+#endif
+ }
+ }
+ }
+ else
+ {
+ if ( Smb4KSettings::unmountForeignShares() )
+ {
+ if ( force )
+ {
+ if ( KMessageBox::questionYesNo( 0, i18n( "Do you really want to force the unmounting of this share?" ), QString::null, KStdGuiItem::yes(), KStdGuiItem::no(), "Dont Ask Forced", KMessageBox::Notify ) == KMessageBox::Yes )
+ {
+#ifdef __linux__
+ command.append( QString( "%1 smb4k_umount -s -l " ).arg( suid_program ) );
+#else
+#ifdef __FreeBSD__
+ command.append( QString( "%1 smb4k_umount " ).arg( suid_program ) );
+#else
+ command.append( QString( "%1 smb4k_umount -s " ).arg( suid_program ) );
+#endif
+#endif
+ execute = true;
+ }
+ else
+ {
+ m_working = false;
+ emit state( MOUNTER_STOP );
+
+ return;
+ }
+ }
+ else
+ {
+ if ( !Smb4KSettings::alwaysUseSuperUser() )
+ {
+#ifndef __FreeBSD__
+ command.append( "smb4k_umount -n " );
+#else
+ command.append( "smb4k_umount " );
+#endif
+ }
+ else
+ {
+#ifndef __FreeBSD__
+ command.append( QString( "%1 smb4k_umount -s " ).arg( suid_program ) );
+#else
+ command.append( QString( "%1 smb4k_umount " ).arg( suid_program ) );
+#endif
+ }
+ }
+ }
+ else
+ {
+ if ( !noMessage )
+ {
+ Smb4KError::error( ERROR_UNMOUNTING_NOT_ALLOWED );
+ }
+
+ m_working = false;
+ emit state( MOUNTER_STOP );
+
+ return;
+ }
+ }
+
+#ifndef __FreeBSD__
+ command.append( QString( "-t %1 " ).arg( share->filesystem() ) );
+#endif
+ command.append( QString( "'%1'" ).arg( m_priv->path() ) );
+
+ if ( force && !execute )
+ {
+ return;
+ }
+
+ emit aboutToUnmount( mountpoint );
+
+ *m_proc << command;
+ startProcess( Unmount );
+ }
+ else
+ {
+ // FIXME: Throw an error?
+ return;
+ }
+ }
+ else
+ {
+ Smb4KError::error( ERROR_MOUNTPOINT_EMPTY );
+ m_working = false;
+ emit state( MOUNTER_STOP );
+
+ return;
+ }
+}
+
+
+/***************************************************************************
+ Unmounts all shares at once. (Public part)
+***************************************************************************/
+
+void Smb4KMounter::unmountAllShares()
+{
+ m_queue.enqueue( new QString( QString( "%1" ).arg( UnmountAll ) ) );
+}
+
+
+/***************************************************************************
+ Unmounts all shares at once.
+***************************************************************************/
+
+void Smb4KMounter::unmountAll()
+{
+ for ( QValueListIterator<Smb4KShare *> it = m_mounted_shares.begin(); it != m_mounted_shares.end(); ++it )
+ {
+ unmountShare( *it, false, true );
+ }
+
+ m_working = false;
+}
+
+
+/***************************************************************************
+ Starts any process.
+***************************************************************************/
+
+void Smb4KMounter::startProcess( int state )
+{
+ m_buffer = QString::null;
+ m_state = state;
+
+ if ( m_state != Import )
+ {
+ QApplication::setOverrideCursor( waitCursor );
+ }
+
+ m_proc->start( KProcess::NotifyOnExit, KProcess::AllOutput );
+}
+
+
+/***************************************************************************
+ Ends any process. This functions tells the mounter what to do
+ afterwards.
+***************************************************************************/
+
+void Smb4KMounter::endProcess()
+{
+ switch ( m_state )
+ {
+ case Mount:
+ processMount();
+ break;
+ case Unmount:
+ processUnmount();
+ break;
+ default:
+ break;
+ }
+
+ m_state = Idle;
+
+ m_priv->clearData();
+
+ QApplication::restoreOverrideCursor();
+ m_proc->clearArguments();
+
+ m_working = false;
+ emit state( MOUNTER_STOP );
+}
+
+
+/***************************************************************************
+ Process mounts.
+***************************************************************************/
+
+void Smb4KMounter::processMount()
+{
+ Smb4KShare *share = NULL;
+
+#ifndef __FreeBSD__
+
+ if ( m_proc->normalExit() )
+ {
+ if ( m_buffer.contains( "smb4k_mount:", true ) == 0 &&
+ m_buffer.contains( "failed", true ) == 0 &&
+ m_buffer.contains( "ERR", true ) == 0 &&
+ m_buffer.contains( "/bin/sh:" ) == 0 &&
+ m_buffer.contains( "mount:", true ) == 0 &&
+ m_buffer.contains( "smbmnt" ) == 0 &&
+ m_buffer.contains( m_priv->path() ) == 0 &&
+ m_buffer.contains( "mount error" ) == 0 &&
+ m_buffer.contains( "bad user name" ) == 0 &&
+ m_buffer.contains( "bad group name" ) == 0 )
+ {
+ QString name = QString( "//%1/%2" ).arg( m_priv->host() ).arg( m_priv->share() );
+
+ // Check file system
+#if !defined(__solaris__)
+ struct statfs filesystem;
+#else
+ struct statvfs filesystem;
+#endif
+
+#if !defined(__solaris__) && !defined(__irix__)
+ if ( statfs( m_priv->path(), &filesystem ) == -1 )
+#elif defined(__irix__)
+ if ( statfs( m_priv->path(), &filesystem, sizeof( filesystem ), 0 ) == -1 )
+#else
+ if ( statvfs( m_priv->path(), &filesystem ) == -1 )
+#endif
+ {
+ // The query failed. Go with the file system already defined in m_priv.
+ if ( QString::compare( m_priv->filesystem(), "smbfs" ) == 0 )
+ {
+ share = new Smb4KShare( name, m_priv->path(), m_priv->filesystem(), (int)getuid(), (int)getgid() );
+ m_mounted_shares.append( share );
+ }
+ else if ( QString::compare( m_priv->filesystem(), "cifs" ) == 0 )
+ {
+ // The user name will be send if no login was specified.
+ QString cifs_login = !m_priv->cifsLogin().isEmpty() ?
+ m_priv->cifsLogin() :
+ getpwuid( getuid() )->pw_name;
+
+ share = new Smb4KShare( name, m_priv->path(), m_priv->filesystem(), cifs_login, false );
+ m_mounted_shares.append( share );
+ }
+ }
+ else
+ {
+#if !defined(__FreeBSD__) && !defined(__solaris__) && !defined(__irix__)
+ if ( (uint)filesystem.f_type == 0xFF534D42 /* CIFS */)
+ {
+ // The user name will be send if no login was specified.
+ QString cifs_login = !m_priv->cifsLogin().isEmpty() ?
+ m_priv->cifsLogin() :
+ getpwuid( getuid() )->pw_name;
+
+ share = new Smb4KShare( name, m_priv->path(), "cifs", cifs_login, false );
+ m_mounted_shares.append( share );
+ }
+ else if ( (uint)filesystem.f_type == 0x517B /* SMBFS */)
+ {
+ share = new Smb4KShare( name, m_priv->path(), "smbfs", (int)getuid(), (int)getgid() );
+ m_mounted_shares.append( share );
+ }
+#elif defined(__solaris__)
+ if ( (uint)filesystem.f_basetype == 0xFF534D42 /* CIFS */)
+ {
+ // The user name will be send if no login was specified.
+ QString cifs_login = !m_priv->cifsLogin().isEmpty() ?
+ m_priv->cifsLogin() :
+ getpwuid( getuid() )->pw_name;
+
+ share = new Smb4KShare( name, m_priv->path(), "cifs", cifs_login, false );
+ m_mounted_shares.append( share );
+ }
+ else if ( (uint)filesystem.f_basetype == 0x517B /* SMBFS */)
+ {
+ share = new Smb4KShare( name, m_priv->path(), "smbfs", (int)getuid(), (int)getgid() );
+ m_mounted_shares.append( share );
+ }
+#elif defined(__irix__)
+ if ( (uint)filesystem.f_fstyp == 0xFF534D42 /* CIFS */)
+ {
+ // The user name will be send if no login was specified.
+ QString cifs_login = !m_priv->cifsLogin().isEmpty() ?
+ m_priv->cifsLogin() :
+ getpwuid( getuid() )->pw_name;
+
+ share = new Smb4KShare( name, m_priv->path(), "cifs", cifs_login, false );
+ m_mounted_shares.append( share );
+ }
+ else if ( (uint)filesystem.f_basetype == 0x517B && !strncmp( fs, "smbfs", strlen( fs )+1 ) )
+ {
+ share = new Smb4KShare( name, m_priv->path(), "smbfs", (int)getuid(), (int)getgid() );
+ m_mounted_shares.append( share );
+ }
+#endif
+ else
+ {
+ // Error... We don't create a share.
+ }
+ }
+
+ if ( share )
+ {
+ // Check that the share is accessible:
+ checkAccessibility( share );
+
+ emit mountedShare( m_priv->path() );
+ }
+ }
+ else
+ {
+ if ( m_buffer.contains( "ERRbadpw" ) != 0 ||
+ m_buffer.contains( "ERRnoaccess" ) != 0 ||
+ m_buffer.contains( "mount error 13 = Permission denied" ) != 0 )
+ {
+ int state = Smb4KPasswordHandler::None;
+
+ if ( m_buffer.contains( "ERRbadpw" ) != 0 )
+ {
+ state = Smb4KPasswordHandler::BadPassword;
+ }
+ else if ( m_buffer.contains( "ERRnoaccess" ) != 0 )
+ {
+ state = Smb4KPasswordHandler::AccessDenied;
+ }
+ else if ( m_buffer.contains( "mount error 13 = Permission denied" ) != 0 )
+ {
+ state = Smb4KPasswordHandler::PermDenied;
+ }
+
+ // If the user supplied auth information, we will retry mounting.
+ if ( passwordHandler()->askpass( m_priv->workgroup(), m_priv->host(), m_priv->share(), state ) )
+ {
+ mountShare( m_priv->workgroup(), m_priv->host(), m_priv->ip(), m_priv->share() );
+ }
+ }
+ else if ( m_buffer.contains( "ERRnosuchshare" ) != 0 && m_priv->share().contains( "_" ) != 0 )
+ {
+ QString share_string = static_cast<QString>( m_priv->share() ).replace( "_", " " );
+ mountShare( m_priv->workgroup(), m_priv->host(), m_priv->ip(), share_string );
+ }
+ else
+ {
+ QString name = QString( "//%1/%2" ).arg( m_priv->host() ).arg( m_priv->share() );
+
+ Smb4KError::error( ERROR_MOUNTING_SHARE, name, m_buffer );
+ }
+ }
+ }
+
+#else
+
+ if ( m_proc->normalExit() )
+ {
+ if ( m_buffer.contains( "smb4k_mount:", true ) == 0 &&
+ m_buffer.contains( "syserr =", true ) == 0 &&
+ /* To make sure we catch all errors, also check for the following
+ strings. Maybe we can remove them?? */
+ m_buffer.contains( "Authentication error", true ) == 0 &&
+ m_buffer.contains( "Connection refused", true ) == 0 &&
+ m_buffer.contains( "Operation not permitted", true ) == 0 )
+ {
+ import(); // FIXME: *cough* What is this for???
+
+ Smb4KAuthInfo authInfo( m_priv->workgroup(), m_priv->host(), m_priv->share() );
+ (void) passwordHandler()->readAuth( &authInfo );
+
+ QString name = QString( "//%1@%2/%3" ).arg( authInfo.user().upper(), m_priv->host().upper(), m_priv->share().upper() );
+
+ share = new Smb4KShare( name, m_priv->path(), m_priv->filesystem(), (int)getuid(), (int)getgid() );
+ m_mounted_shares.append( share );
+
+ // Check that the share is accessible:
+ checkAccessibility( share );
+
+ emit mountedShare( m_priv->path() );
+ }
+ else
+ {
+ if ( m_buffer.contains( "Authentication error" ) != 0 )
+ {
+ // If the user supplied auth information, we will retry mounting.
+ if ( passwordHandler()->askpass( m_priv->workgroup(), m_priv->host(), m_priv->share(), Smb4KPasswordHandler::AuthError ) )
+ {
+ mountShare( m_priv->workgroup(), m_priv->host(), m_priv->ip() , m_priv->share() );
+ }
+ }
+ else
+ {
+ Smb4KAuthInfo authInfo( m_priv->workgroup(), m_priv->host(), m_priv->share() );
+ (void) passwordHandler()->readAuth( &authInfo );
+
+ QString name = QString( "//%1@%2/%3" ).arg( authInfo.user().upper(), m_priv->host().upper(), m_priv->share().upper() );
+
+ Smb4KError::error( ERROR_MOUNTING_SHARE, name, m_buffer );
+ }
+ }
+ }
+
+#endif
+
+ emit updated();
+}
+
+
+/***************************************************************************
+ Process unmounts.
+***************************************************************************/
+
+void Smb4KMounter::processUnmount()
+{
+ // Get the share:
+ Smb4KShare *share = findShareByPath( m_priv->path() );
+
+ if ( m_proc->normalExit() )
+ {
+ if ( m_buffer.isEmpty() )
+ {
+ if ( qstrncmp( share->canonicalPath(),
+ QDir( Smb4KSettings::mountPrefix() ).canonicalPath().local8Bit(),
+ QDir( Smb4KSettings::mountPrefix() ).canonicalPath().local8Bit().length() ) == 0 )
+ {
+ QDir dir( share->canonicalPath() );
+
+ if ( dir.rmdir( dir.canonicalPath(), true ) )
+ {
+ dir.cdUp();
+ dir.rmdir( dir.canonicalPath(), true );
+ }
+ }
+
+ m_mounted_shares.remove(share);
+ }
+ else
+ {
+ // If the user's computer is configured by a DHCP server, under
+ // rare circumstances it might occur that sudo reports an error,
+ // because it is not able to resolve the host. This error message
+ // will be removed, because it does not affect the unmounting:
+ if ( m_buffer.contains( "sudo: unable to resolve host", true ) != 0 )
+ {
+ size_t hostnamelen = 255;
+ char *hostname = new char[hostnamelen];
+
+ if ( gethostname( hostname, hostnamelen ) == -1 )
+ {
+ int error_number = errno;
+ Smb4KError::error( ERROR_GETTING_HOSTNAME, QString::null, strerror( error_number ) );
+ }
+ else
+ {
+ QString str = QString( "sudo: unable to resolve host %1\n" ).arg( hostname );
+
+ m_buffer.remove( str, false /* case insensitive */ );
+
+ if ( !m_buffer.isEmpty() )
+ {
+ Smb4KError::error( ERROR_UNMOUNTING_SHARE, share->name(), m_buffer );
+ }
+ else
+ {
+ if ( qstrncmp( share->canonicalPath(),
+ QDir( Smb4KSettings::mountPrefix() ).canonicalPath().local8Bit(),
+ QDir( Smb4KSettings::mountPrefix() ).canonicalPath().local8Bit().length() ) == 0 )
+ {
+ QDir dir( share->canonicalPath() );
+
+ if ( dir.rmdir( dir.canonicalPath(), true ) )
+ {
+ dir.cdUp();
+ dir.rmdir( dir.canonicalPath(), true );
+ }
+ }
+
+ m_mounted_shares.remove(share);
+ }
+ }
+
+ delete [] hostname;
+ }
+ else
+ {
+ Smb4KError::error( ERROR_UNMOUNTING_SHARE, share->name(), m_buffer );
+ }
+ }
+ }
+
+ emit updated();
+}
+
+
+/***************************************************************************
+ Check if a share is already mounted
+***************************************************************************/
+
+bool Smb4KMounter::isMounted( const QString &name, bool userOnly )
+{
+ QValueList<Smb4KShare> list = findShareByName( name );
+
+ bool mounted = false;
+
+ if ( !list.isEmpty() && userOnly )
+ {
+ for ( QValueList<Smb4KShare>::ConstIterator it = list.begin(); it != list.end(); ++it )
+ {
+ if ( !(*it).isForeign() )
+ {
+ mounted = true;
+
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ }
+ else
+ {
+ mounted = !list.isEmpty();
+ }
+
+ return mounted;
+}
+
+
+/***************************************************************************
+ Find a share in the list with its path
+***************************************************************************/
+
+Smb4KShare* Smb4KMounter::findShareByPath( const QString &path )
+{
+ if ( path.isEmpty() || m_mounted_shares.isEmpty() )
+ {
+ return NULL;
+ }
+
+ Smb4KShare *share = NULL;
+
+ for ( QValueListIterator<Smb4KShare *> it = m_mounted_shares.begin(); it != m_mounted_shares.end(); ++it )
+ {
+ if( QString::compare( path.upper(), QString::fromLocal8Bit( (*it)->path(), -1 ).upper() ) == 0 ||
+ QString::compare( path.upper(), QString::fromLocal8Bit( (*it)->canonicalPath(), -1 ).upper() ) == 0 )
+ {
+ share = *it;
+
+ break;
+ }
+ }
+
+ return share;
+}
+
+
+/***************************************************************************
+ Find the list of mounts of a share
+***************************************************************************/
+
+QValueList<Smb4KShare> Smb4KMounter::findShareByName( const QString &name )
+{
+ QValueList<Smb4KShare> list;
+
+ if ( name.isEmpty() || m_mounted_shares.isEmpty() )
+ {
+ return list; // is empty
+ }
+
+ QString n = name;
+
+ for ( QValueListIterator<Smb4KShare *> it = m_mounted_shares.begin(); it != m_mounted_shares.end(); ++it )
+ {
+ if( QString::compare( (*it)->name().upper(), name.upper() ) == 0 ||
+ QString::compare( (*it)->name().upper(), n.replace( " ", "_" ).upper() ) == 0 )
+ {
+ list.append( *(*it) );
+
+ continue;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ return list;
+}
+
+
+/***************************************************************************
+ Returns a list of mount points that belong to broken shares
+***************************************************************************/
+
+const QValueList<Smb4KShare *> Smb4KMounter::getBrokenShares()
+{
+ QValueList<Smb4KShare *> broken_shares;
+
+ for ( QValueListIterator<Smb4KShare *> it = m_mounted_shares.begin(); it != m_mounted_shares.end(); ++it )
+ {
+ if ( (*it)->isBroken() )
+ {
+ broken_shares.append( *it );
+
+ continue;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ return broken_shares;
+}
+
+
+void Smb4KMounter::prepareForShutdown()
+{
+ slotShutdown();
+}
+
+
+void Smb4KMounter::checkAccessibility( Smb4KShare *share )
+{
+ if ( share )
+ {
+ m_priv->thread.setMountpoint( share->path() );
+ m_priv->thread.start();
+ m_priv->thread.wait( THREAD_WAITING_TIME );
+ m_priv->thread.terminate();
+ m_priv->thread.wait();
+
+ share->setBroken( m_priv->thread.isBroken() );
+ share->setTotalDiskSpace( m_priv->thread.totalDiskSpace() );
+ share->setFreeDiskSpace( m_priv->thread.freeDiskSpace() );
+ }
+ else
+ {
+ // FIXME: Should we throw an error here?
+ }
+}
+
+
+void Smb4KMounter::timerEvent( QTimerEvent * )
+{
+ if ( !m_working && !m_queue.isEmpty() )
+ {
+ // Tell the mounter, that it is busy.
+ m_working = true;
+
+ QString *item = m_queue.dequeue();
+ int todo = item->section( ":", 0, 0 ).toInt();
+
+ switch ( todo )
+ {
+ case Remount:
+ {
+ remount();
+ break;
+ }
+ case Import:
+ {
+ import();
+ break;
+ }
+ case Mount:
+ {
+ emit state( MOUNTER_MOUNTING );
+ mount( item->section( ":", 1, 1 ), item->section( ":", 2, 2 ), item->section( ":", 3, 3 ), item->section( ":", 4, 4 ) );
+ break;
+ }
+ case Unmount:
+ {
+ emit state( MOUNTER_UNMOUNTING );
+ unmount( item->section( ":", 1, 1 ), (bool)item->section( ":", 2, 2 ).toInt() /* force */, (bool)item->section( ":", 3, 3 ).toInt() /* noMessage */);
+ break;
+ }
+ case UnmountAll:
+ {
+ unmountAll();
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ delete item;
+ }
+
+ m_priv->timerTicks++;
+
+ if ( m_priv->timerTicks * timerInterval() >= Smb4KSettings::checkInterval() /* msec */ &&
+ (!m_working || m_queue.isEmpty()) )
+ {
+ m_queue.enqueue( new QString( QString( "%1:" ).arg( Import ) ) );
+ m_priv->timerTicks = 0;
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// SLOT IMPLEMENTATIONS
+/////////////////////////////////////////////////////////////////////////////
+
+
+void Smb4KMounter::slotProcessExited( KProcess * )
+{
+ endProcess();
+}
+
+
+void Smb4KMounter::slotReceivedStdout( KProcess *, char *buf, int len )
+{
+ m_buffer.append( QString::fromLocal8Bit( buf, len ) );
+}
+
+
+void Smb4KMounter::slotReceivedStderr( KProcess *, char *buf, int len )
+{
+ m_buffer.append( QString::fromLocal8Bit( buf, len ) );
+}
+
+
+void Smb4KMounter::slotShutdown()
+{
+ // Abort any action:
+ abort();
+
+ // Prepare for shutdown:
+ if ( Smb4KSettings::remountShares() && !m_mounted_shares.isEmpty() )
+ {
+ for ( QValueList<Smb4KShare *>::ConstIterator it = m_mounted_shares.begin(); it != m_mounted_shares.end(); ++it )
+ {
+ optionsHandler()->remount( *it, !(*it)->isForeign() );
+ }
+ }
+
+ optionsHandler()->sync();
+
+ QDir dir;
+
+ dir.cd( Smb4KSettings::mountPrefix() );
+
+ QStringList dirs = dir.entryList( QDir::Dirs, QDir::DefaultSort );
+
+ QValueList<Smb4KShare *> broken_shares = getBrokenShares();
+
+ for ( QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it )
+ {
+ if ( QString::compare( *it, "." ) != 0 && QString::compare( *it, ".." ) != 0 )
+ {
+ bool broken = false;
+
+ for ( QValueListIterator<Smb4KShare *> bs = broken_shares.begin(); bs != broken_shares.end(); ++bs )
+ {
+ if ( qstrncmp( (*bs)->path(),
+ Smb4KSettings::mountPrefix()+*it,
+ (Smb4KSettings::mountPrefix()+*it).length() ) == 0 ||
+ qstrncmp( (*bs)->canonicalPath(),
+ Smb4KSettings::mountPrefix()+*it,
+ (Smb4KSettings::mountPrefix()+*it).length() ) == 0 )
+ {
+ broken = true;
+
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ if ( !broken )
+ {
+ dir.cd( *it );
+
+ QStringList subdirs = dir.entryList( QDir::Dirs, QDir::DefaultSort );
+
+ for ( QStringList::ConstIterator i = subdirs.begin(); i != subdirs.end(); ++i )
+ {
+ if ( QString::compare( *i, "." ) != 0 && QString::compare( *i, ".." ) != 0 )
+ {
+ dir.rmdir( *i );
+ }
+ }
+
+ dir.cdUp();
+ dir.rmdir( *it );
+ }
+ }
+ }
+
+ broken_shares.clear();
+
+ if ( Smb4KSettings::unmountSharesOnExit() )
+ {
+ QString suid_program, command;
+
+ switch( Smb4KSettings::superUserProgram() )
+ {
+ case Smb4KSettings::EnumSuperUserProgram::Sudo:
+ {
+ suid_program = Smb4KSettings::sudo();
+
+ break;
+ }
+ case Smb4KSettings::EnumSuperUserProgram::Super:
+ {
+ suid_program = Smb4KSettings::super();
+
+ break;
+ }
+ default:
+ {
+ // FIXME: Throw an error?
+ return;
+ }
+ }
+
+ KProcess proc;
+ proc.setUseShell( true );
+ proc.detach();
+
+ for ( QValueListIterator<Smb4KShare *> it = m_mounted_shares.begin(); it != m_mounted_shares.end(); ++it )
+ {
+ if ( !(*it)->isForeign() )
+ {
+ if ( Smb4KSettings::alwaysUseSuperUser() )
+ {
+#ifndef __FreeBSD__
+ command.append( QString( "%1 smb4k_umount -s -t %2 " ).arg( suid_program ).arg( (*it)->filesystem() ) );
+#else
+ command.append( QString( "%1 smb4k_umount " ).arg( suid_program ) );
+#endif
+ command.append( KProcess::quote( (*it)->path() ) );
+ command.append( " ; " );
+ }
+ else
+ {
+#ifndef __FreeBSD__
+ command.append( QString( "smb4k_umount -n -t %1 " ).arg( (*it)->filesystem() ) );
+#else
+ command.append( "smb4k_umount " );
+#endif
+ command.append( KProcess::quote( (*it)->path() ) );
+ command.append( " ; " );
+ }
+
+ dir.setPath( (*it)->canonicalPath() );
+
+#ifndef __FreeBSD__
+ command.append( "rmdir --ignore-fail-on-non-empty " );
+ command.append( KProcess::quote( dir.canonicalPath() ) );
+ command.append( " ; " );
+ command.append( "rmdir --ignore-fail-on-non-empty " );
+ dir.cdUp();
+ command.append( KProcess::quote( dir.canonicalPath() ) );
+ command.append( " ; " );
+#else
+ command.append( "rmdir " );
+ command.append( KProcess::quote( dir.canonicalPath() ) );
+ command.append( " ; " );
+ command.append( "rmdir " );
+ dir.cdUp();
+ command.append( KProcess::quote( dir.canonicalPath() ) );
+ command.append( " ; " );
+#endif
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ command.truncate( command.length() - 2 );
+
+ proc << command;
+ proc.start( KProcess::DontCare, KProcess::NoCommunication );
+ }
+}
+
+
+#include "smb4kmounter.moc"