diff options
Diffstat (limited to 'tdeioslave/media/mounthelper/tdeio_media_mounthelper.cpp')
-rw-r--r-- | tdeioslave/media/mounthelper/tdeio_media_mounthelper.cpp | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/tdeioslave/media/mounthelper/tdeio_media_mounthelper.cpp b/tdeioslave/media/mounthelper/tdeio_media_mounthelper.cpp new file mode 100644 index 000000000..3f0319f9f --- /dev/null +++ b/tdeioslave/media/mounthelper/tdeio_media_mounthelper.cpp @@ -0,0 +1,303 @@ +/* This file is part of the KDE project + Copyright (c) 2004 Kévin Ottens <ervin ipsquad net> + Parts of this file are + Copyright 2003 Waldo Bastian <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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 <tdecmdlineargs.h> +#include <tdelocale.h> +#include <tdeapplication.h> +#include <kurl.h> +#include <tdemessagebox.h> +#include <dcopclient.h> +#include <dcopref.h> +#include <tqtimer.h> +#include <stdlib.h> +#include <kdebug.h> +#include <tdeglobal.h> +#include <kprocess.h> +#include <tdestartupinfo.h> +#include <kmimetype.h> +#ifdef __TDE_HAVE_TDEHWLIB +#include <tdehardwaredevices.h> +#endif + +#include "dialog.h" +#include "tdeio_media_mounthelper.h" + +const Medium MountHelper::findMedium(const KURL &url) +{ + DCOPRef mediamanager("kded", "mediamanager"); + + // Try filename first + DCOPReply reply = mediamanager.call( "properties", url.fileName() ); + if ( !reply.isValid() ) { + m_errorStr = i18n("The TDE mediamanager is not running.")+"\n"; + return Medium(TQString::null, TQString::null, TQString::null); + } + const Medium& medium = Medium::create(reply); + if ( medium.id().isEmpty() ) { + // Try full URL now + reply = mediamanager.call( "properties", url.prettyURL() ); + if ( !reply.isValid() ) { + m_errorStr = i18n("Internal Error"); + return Medium(TQString::null, TQString::null, TQString::null); + } + return Medium::create(reply); + } else { + return medium; + } +} + +MountHelper::MountHelper() : TDEApplication() +{ + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + + m_errorStr = TQString::null; + + KURL url(args->url(0)); + const Medium medium = findMedium(url); + + if ( medium.id().isEmpty() ) + { + if (m_errorStr.isEmpty()) + m_errorStr+= i18n("%1 cannot be found.").arg(url.prettyURL()); + TQTimer::singleShot(0, this, TQT_SLOT(error()) ); + return; + } + + if ( !medium.isMountable() && !args->isSet("e") && !args->isSet("s")) + { + m_errorStr = i18n("%1 is not a mountable media.").arg(url.prettyURL()); + TQTimer::singleShot(0, this, TQT_SLOT(error()) ); + return; + } + + TQString device = medium.deviceNode(); + TQString mount_point = medium.mountPoint(); + + m_isCdrom = medium.mimeType().find("dvd")!=-1 + || medium.mimeType().find("cd")!=-1; + + if (args->isSet("d")) + { + if (!medium.isEncrypted()) + { + m_errorStr = i18n("%1 is not an encrypted media.").arg(url.prettyURL()); + TQTimer::singleShot(0, this, TQT_SLOT(error()) ); + return; + } + if (!medium.needDecryption()) + { + m_errorStr = i18n("%1 is already decrypted.").arg(url.prettyURL()); + TQTimer::singleShot(0, this, TQT_SLOT(error()) ); + return; + } + + TQString iconName = medium.iconName(); + if (iconName.isEmpty()) + { + TQString mime = medium.mimeType(); + iconName = KMimeType::mimeType(mime)->icon(mime, false); + } + + m_mediumId = medium.id(); + dialog = new Dialog(url.prettyURL(), iconName); + dialog->show(); + + connect(dialog, TQT_SIGNAL (user1Clicked()), this, TQT_SLOT (slotSendPassword())); + connect(dialog, TQT_SIGNAL (cancelClicked()), this, TQT_SLOT (slotCancel())); + connect(this, TQT_SIGNAL (signalPasswordError(TQString)), dialog, TQT_SLOT (slotDialogError(TQString))); + } + else if (args->isSet("u")) + { + DCOPRef mediamanager("kded", "mediamanager"); + DCOPReply reply = mediamanager.call( "unmount", medium.id()); + if (reply.isValid()) + reply.get(m_errorStr); + kdDebug() << "medium unmount " << m_errorStr << endl; + if (m_errorStr.isNull()) + ::exit(0); + else + error(); + } + else if (args->isSet("s") || args->isSet("e")) + { + DCOPRef mediamanager("kded", "mediamanager"); + + /* + * We want to call mediamanager unmount before invoking eject. That's + * because unmount would provide an informative error message in case of + * failure. However, there are cases when unmount would fail + * (supermount, slackware, see bug#116209) but eject would succeed. + * Thus if unmount fails, save unmount error message and invokeEject() + * anyway. Only if both unmount and eject fail, notify the user by + * displaying the saved error message (see ejectFinished()). + */ + if (medium.isMounted()) + { + DCOPReply reply = mediamanager.call( "unmount", medium.id()); + if (reply.isValid()) { + reply.get(m_errorStr); + } + } + + /* If this is a decrypted volume and there is no error yet + * we try to teardown the decryption */ + if (m_errorStr.isNull() && medium.isEncrypted() && !medium.clearDeviceUdi().isNull()) + { + DCOPReply reply = mediamanager.call( "undecrypt", medium.id()); + if (reply.isValid()) { + reply.get(m_errorStr); + } + } + + if (m_errorStr.isNull()) { + invokeEject(device, true); + } + else { + error(); + } + } + else + { + DCOPRef mediamanager("kded", "mediamanager"); + DCOPReply reply = mediamanager.call( "mount", medium.id()); + if (reply.isValid()) + reply.get(m_errorStr); + if (m_errorStr.isNull()) + ::exit(0); + else + error(); + } +} + +void MountHelper::invokeEject(const TQString &device, bool quiet) +{ +#ifdef __TDE_HAVE_TDEHWLIB + // Try TDE HW library eject first... + TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices(); + TDEGenericDevice *hwdevice = hwdevices->findByDeviceNode(device); + if (hwdevice->type() == TDEGenericDeviceType::Disk) { + TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(hwdevice); + if (sdevice->ejectDrive()) { + // Success! + ::exit(0); + } + } +#endif + + // Then fall back to tdeeject if needed + TDEProcess *proc = new TDEProcess(TQT_TQOBJECT(this)); + *proc << "tdeeject"; + if (quiet) + { + *proc << "-q"; + } + *proc << device; + connect( proc, TQT_SIGNAL(processExited(TDEProcess *)), + this, TQT_SLOT( ejectFinished(TDEProcess *) ) ); + proc->start(); +} + +void MountHelper::ejectFinished(TDEProcess* proc) +{ + /* + * If eject failed, report the error stored in m_errorStr + */ + if (proc->normalExit() && proc->exitStatus() == 0) { + ::exit(0); + } else { + if (m_errorStr.isEmpty()) { + if (m_isCdrom) + m_errorStr = i18n("The device was successfully unmounted, but the tray could not be opened"); + else + m_errorStr = i18n("The device was successfully unmounted, but could not be ejected"); + } +//X Comment this because the error is useless as long as the unmount is successful. +//X TQTimer::singleShot(0, this, TQT_SLOT(error())); + ::exit(0); + } +} + +void MountHelper::error() +{ + TQString prettyErrorString = m_errorStr; + if (m_errorStr.contains("<") && m_errorStr.contains(">")) { + if (!m_errorStr.contains("<qt>")) { + prettyErrorString = TQString("<qt>%1</qt>").arg(m_errorStr); + } + } + KMessageBox::error(0, prettyErrorString); + ::exit(1); +} + +void MountHelper::slotSendPassword() +{ + DCOPRef mediamanager("kded", "mediamanager"); + + DCOPReply reply = mediamanager.call( "decrypt", m_mediumId, dialog->getPassword() ); + if (!reply.isValid()) { + m_errorStr = i18n("The TDE mediamanager is not running."); + error(); + } else { + TQString errorMsg = reply; + if (errorMsg.isNull()) { + exit(0); + } else { + emit signalPasswordError(errorMsg); + } + } +} + +void MountHelper::slotCancel() +{ + exit(0); +} + +static TDECmdLineOptions options[] = +{ + { "d", I18N_NOOP("Decrypt given URL"), 0 }, + { "u", I18N_NOOP("Unmount given URL"), 0 }, + { "m", I18N_NOOP("Mount given URL (default)"), 0 }, + { "e", I18N_NOOP("Eject given URL via tdeeject"), 0}, + { "s", I18N_NOOP("Unmount and Eject given URL (necessary for some USB devices)"), 0}, + {"!+URL", I18N_NOOP("media:/ URL to mount/unmount/eject/remove"), 0 }, + TDECmdLineLastOption +}; + + +int main(int argc, char **argv) +{ + TDECmdLineArgs::init(argc, argv, "tdeio_media_mounthelper", + "tdeio_media_mounthelper", "tdeio_media_mounthelper", + "0.1"); + + TDECmdLineArgs::addCmdLineOptions( options ); + TDEGlobal::locale()->setMainCatalogue("tdeio_media"); + TDEApplication::addCmdLineOptions(); + + if (TDECmdLineArgs::parsedArgs()->count()==0) TDECmdLineArgs::usage(); + TDEApplication *app = new MountHelper(); + + TDEStartupInfo::appStarted(); + app->dcopClient()->attach(); + return app->exec(); +} + +#include "tdeio_media_mounthelper.moc" |