summaryrefslogtreecommitdiffstats
path: root/tdeioslave/media/mediamanager
diff options
context:
space:
mode:
Diffstat (limited to 'tdeioslave/media/mediamanager')
-rw-r--r--tdeioslave/media/mediamanager/CMakeLists.txt65
-rw-r--r--tdeioslave/media/mediamanager/Makefile.am32
-rw-r--r--tdeioslave/media/mediamanager/backendbase.cpp26
-rw-r--r--tdeioslave/media/mediamanager/backendbase.h35
-rw-r--r--tdeioslave/media/mediamanager/decryptdialog.ui201
-rw-r--r--tdeioslave/media/mediamanager/dialog.cpp68
-rw-r--r--tdeioslave/media/mediamanager/dialog.h61
-rw-r--r--tdeioslave/media/mediamanager/fstabbackend.cpp483
-rw-r--r--tdeioslave/media/mediamanager/fstabbackend.h68
-rw-r--r--tdeioslave/media/mediamanager/halbackend.cpp1858
-rw-r--r--tdeioslave/media/mediamanager/halbackend.h232
-rw-r--r--tdeioslave/media/mediamanager/linuxcdpolling.cpp585
-rw-r--r--tdeioslave/media/mediamanager/linuxcdpolling.h86
-rw-r--r--tdeioslave/media/mediamanager/mediadirnotify.cpp124
-rw-r--r--tdeioslave/media/mediamanager/mediadirnotify.h47
-rw-r--r--tdeioslave/media/mediamanager/medialist.cpp303
-rw-r--r--tdeioslave/media/mediamanager/medialist.h80
-rw-r--r--tdeioslave/media/mediamanager/mediamanager.cpp423
-rw-r--r--tdeioslave/media/mediamanager/mediamanager.desktop141
-rw-r--r--tdeioslave/media/mediamanager/mediamanager.h94
-rw-r--r--tdeioslave/media/mediamanager/removablebackend.cpp180
-rw-r--r--tdeioslave/media/mediamanager/removablebackend.h52
-rw-r--r--tdeioslave/media/mediamanager/tdehardwarebackend.cpp1376
-rw-r--r--tdeioslave/media/mediamanager/tdehardwarebackend.h171
24 files changed, 6791 insertions, 0 deletions
diff --git a/tdeioslave/media/mediamanager/CMakeLists.txt b/tdeioslave/media/mediamanager/CMakeLists.txt
new file mode 100644
index 000000000..5a73f3708
--- /dev/null
+++ b/tdeioslave/media/mediamanager/CMakeLists.txt
@@ -0,0 +1,65 @@
+#################################################
+#
+# (C) 2010-2011 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/tdeioslave/media/libmediacommon
+ ${CMAKE_SOURCE_DIR}/tdeioslave/media/libmediacommon
+ ${CMAKE_BINARY_DIR}
+ ${TDE_INCLUDE_DIR}
+ ${TQT_INCLUDE_DIRS}
+ ${HAL_INCLUDE_DIRS}
+ ${DBUS_TQT_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+ ${DBUS_TQT_LIBRARY_DIRS}
+)
+
+
+##### other data ################################
+
+install( FILES mediamanager.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kded )
+
+
+##### kded_mediamanager (module) ################
+
+set( target kded_mediamanager )
+
+if( WITH_HAL )
+ set( ${target}_SRCS
+ mediamanager.cpp mediamanager.skel medialist.cpp
+ backendbase.cpp fstabbackend.cpp removablebackend.cpp
+ mediadirnotify.cpp mediadirnotify.skel
+ decryptdialog.ui dialog.cpp
+ halbackend.cpp linuxcdpolling.cpp tdehardwarebackend.cpp
+ )
+
+ tde_add_kpart( ${target} AUTOMOC
+ SOURCES ${${target}_SRCS}
+ LINK mediacommon-static tdeinit_kded-shared ${HAL_LIBRARIES} -lhal-storage ${DBUS_TQT_LIBRARIES}
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+ )
+else( )
+ set( ${target}_SRCS
+ mediamanager.cpp mediamanager.skel medialist.cpp
+ backendbase.cpp fstabbackend.cpp removablebackend.cpp
+ decryptdialog.ui dialog.cpp
+ mediadirnotify.cpp mediadirnotify.skel tdehardwarebackend.cpp
+ )
+
+ tde_add_kpart( ${target} AUTOMOC
+ SOURCES ${${target}_SRCS}
+ LINK mediacommon-static tdeinit_kded-shared
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+ )
+endif( )
diff --git a/tdeioslave/media/mediamanager/Makefile.am b/tdeioslave/media/mediamanager/Makefile.am
new file mode 100644
index 000000000..45289a9eb
--- /dev/null
+++ b/tdeioslave/media/mediamanager/Makefile.am
@@ -0,0 +1,32 @@
+kde_module_LTLIBRARIES = kded_mediamanager.la
+
+if include_media_halbackend
+HALBACKEND_INCS = $(HAL_INCS) $(DBUS_INCS) $(DBUSQT_INCS)
+endif
+
+METASOURCES = AUTO
+INCLUDES = -I$(srcdir)/../libmediacommon -I../libmediacommon $(HALBACKEND_INCS) $(all_includes)
+
+if include_media_halbackend
+HALBACKEND_LIB = libhalbackend.la
+libhalbackend_la_SOURCES = halbackend.cpp
+libhalbackend_la_LDFLAGS = -avoid-version $(all_libraries) -no-undefined
+libhalbackend_la_LIBADD = $(HAL_LIBS) $(DBUS_LIBS) $(DBUSQT_LIBS)
+endif
+
+if include_media_linuxcdpolling
+LINUXCDPOLLING_LIB = liblinuxcdpolling.la
+liblinuxcdpolling_la_SOURCES = linuxcdpolling.cpp
+liblinuxcdpolling_la_LDFLAGS = -avoid-version $(all_libraries) -no-undefined
+endif
+
+noinst_LTLIBRARIES = $(LINUXCDPOLLING_LIB) $(HALBACKEND_LIB)
+
+kded_mediamanager_la_SOURCES = mediamanager.cpp mediamanager.skel medialist.cpp backendbase.cpp fstabbackend.cpp removablebackend.cpp mediadirnotify.cpp mediadirnotify.skel
+kded_mediamanager_la_LDFLAGS = $(all_libraries) -module -avoid-version
+kded_mediamanager_la_LIBADD = $(LIB_KSYCOCA) ../libmediacommon/libmediacommon.la $(HALBACKEND_LIB) $(LINUXCDPOLLING_LIB)
+
+
+servicesdir = $(kde_servicesdir)/kded
+services_DATA = mediamanager.desktop
+
diff --git a/tdeioslave/media/mediamanager/backendbase.cpp b/tdeioslave/media/mediamanager/backendbase.cpp
new file mode 100644
index 000000000..157acfca5
--- /dev/null
+++ b/tdeioslave/media/mediamanager/backendbase.cpp
@@ -0,0 +1,26 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ 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 "backendbase.h"
+
+BackendBase::BackendBase(MediaList &list)
+ : m_mediaList(list)
+{
+
+}
+
diff --git a/tdeioslave/media/mediamanager/backendbase.h b/tdeioslave/media/mediamanager/backendbase.h
new file mode 100644
index 000000000..689522d1f
--- /dev/null
+++ b/tdeioslave/media/mediamanager/backendbase.h
@@ -0,0 +1,35 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 K�vin Ottens <ervin ipsquad net>
+
+ 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 _BACKENDBASE_H_
+#define _BACKENDBASE_H_
+
+#include "medialist.h"
+
+class BackendBase
+{
+protected:
+ BackendBase(MediaList &list);
+public:
+ virtual ~BackendBase() { }
+
+protected:
+ MediaList &m_mediaList;
+};
+
+#endif
diff --git a/tdeioslave/media/mediamanager/decryptdialog.ui b/tdeioslave/media/mediamanager/decryptdialog.ui
new file mode 100644
index 000000000..939f0a36a
--- /dev/null
+++ b/tdeioslave/media/mediamanager/decryptdialog.ui
@@ -0,0 +1,201 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>DecryptDialog</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>DecryptDialog</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>207</width>
+ <height>172</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Decrypting Storage Device</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>encryptedIcon</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>48</width>
+ <height>48</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ <property name="alignment">
+ <set>AlignTop</set>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>41</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>descLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;p&gt;&lt;b&gt;%1&lt;/b&gt; is an encrypted storage device.&lt;/p&gt;
+&lt;p&gt;Please enter the password to decrypt the storage device.&lt;/p&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignTop</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Password:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>passwordEdit</cstring>
+ </property>
+ </widget>
+ <widget class="TQLineEdit">
+ <property name="name">
+ <cstring>passwordEdit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="echoMode">
+ <enum>Password</enum>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQGroupBox" row="2" column="0">
+ <property name="name">
+ <cstring>errorBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Error</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>errorLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignTop</set>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/tdeioslave/media/mediamanager/dialog.cpp b/tdeioslave/media/mediamanager/dialog.cpp
new file mode 100644
index 000000000..40e99a84d
--- /dev/null
+++ b/tdeioslave/media/mediamanager/dialog.cpp
@@ -0,0 +1,68 @@
+/* This file is part of the KDE project
+ * Copyright (C) 2007 Jan Klötzke <jan kloetzke at freenet de>
+ *
+ * Based on kryptomedia- Another KDE cryto media application.
+ * Copyright (C) 2006 Daniel Gollub <[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 "dialog.h"
+
+Dialog::Dialog(TQString url, TQString iconName) :
+ KDialogBase(NULL, "Dialog", true, "Decrypt Storage Device", (Cancel|User1), User1, false, KGuiItem(i18n("Decrypt"), "decrypted" ))
+{
+ decryptDialog = new DecryptDialog(this);
+
+ decryptDialog->errorBox->hide();
+ decryptDialog->descLabel->setText(decryptDialog->descLabel->text().arg(url));
+ decryptDialog->descLabel->adjustSize();
+ decryptDialog->adjustSize();
+
+ enableButton( User1, false );
+
+ TQPixmap pixmap = TDEGlobal::iconLoader()->loadIcon(iconName, KIcon::NoGroup, KIcon::SizeLarge);
+ decryptDialog->encryptedIcon->setPixmap( pixmap );
+
+ connect(decryptDialog->passwordEdit, TQT_SIGNAL (textChanged(const TQString &)), this, TQT_SLOT (slotPasswordChanged(const TQString &)));
+
+ setMainWidget(decryptDialog);
+}
+
+Dialog::~Dialog()
+{
+ delete decryptDialog;
+}
+
+TQString Dialog::getPassword()
+{
+ return decryptDialog->passwordEdit->text();
+}
+
+void Dialog::slotDialogError(TQString errorMsg)
+{
+ kdDebug() << __func__ << "(" << errorMsg << " )" << endl;
+
+ decryptDialog->errorLabel->setText(TQString("<b>%1</b>").arg(errorMsg));
+ decryptDialog->errorBox->show();
+}
+
+void Dialog::slotPasswordChanged(const TQString &text)
+{
+ enableButton( User1, !text.isEmpty() );
+}
+
+#include "dialog.moc"
diff --git a/tdeioslave/media/mediamanager/dialog.h b/tdeioslave/media/mediamanager/dialog.h
new file mode 100644
index 000000000..dc1d552d8
--- /dev/null
+++ b/tdeioslave/media/mediamanager/dialog.h
@@ -0,0 +1,61 @@
+/* This file is part of the KDE project
+ * Copyright (C) 2007 Jan Klötzke <jan kloetzke at freenet de>
+ *
+ * Based on kryptomedia- Another KDE cryto media application.
+ * Copyright (C) 2006 Daniel Gollub <[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.
+ */
+
+#ifndef DIALOG_H_
+#define DIALOG_H_
+
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <tdeconfig.h>
+#include <kdebug.h>
+#include <kdialogbase.h>
+#include <kiconloader.h>
+
+#include <tqlineedit.h>
+#include <tqlabel.h>
+#include <tqgroupbox.h>
+
+#include "decryptdialog.h"
+
+class KryptoMedia;
+
+class Dialog : public KDialogBase
+{
+
+Q_OBJECT
+
+public:
+ Dialog(TQString url, TQString iconName);
+ ~Dialog();
+
+ TQString getPassword();
+
+public slots:
+ void slotDialogError(TQString errorMsg);
+ void slotPasswordChanged(const TQString &text);
+
+private:
+ DecryptDialog *decryptDialog;
+};
+
+#endif // DIALOG_H_
+
diff --git a/tdeioslave/media/mediamanager/fstabbackend.cpp b/tdeioslave/media/mediamanager/fstabbackend.cpp
new file mode 100644
index 000000000..0069a8e8e
--- /dev/null
+++ b/tdeioslave/media/mediamanager/fstabbackend.cpp
@@ -0,0 +1,483 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+ Linux CD/DVD detection
+ Copyright (c) 2005 Bernhard Rosenkraenzer <bero arklinux org>
+
+ 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 "fstabbackend.h"
+
+#ifdef __linux__
+// For CD/DVD drive detection
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stdint.h>
+#define CDROM_GET_CAPABILITY 0x5331
+#define CDSL_CURRENT ((int) (~0U>>1))
+#define CDC_DVD_R 0x10000 /* drive can write DVD-R */
+#define CDC_DVD_RAM 0x20000 /* drive can write DVD-RAM */
+#define CDC_CD_R 0x2000 /* drive is a CD-R */
+#define CDC_CD_RW 0x4000 /* drive is a CD-RW */
+#define CDC_DVD 0x8000 /* drive is a DVD */
+#include <tqfile.h>
+#endif
+
+#include <klocale.h>
+#include <tdeio/job.h>
+#include <tdeio/netaccess.h>
+#include <kdebug.h>
+#include <kdirwatch.h>
+#include <kurl.h>
+#include <kmountpoint.h>
+#include <kstandarddirs.h>
+
+#ifdef _OS_SOLARIS_
+#define FSTAB "/etc/vfstab"
+#define MTAB "/etc/mnttab"
+#else
+#define FSTAB "/etc/fstab"
+#define MTAB "/etc/mtab"
+#endif
+
+
+
+FstabBackend::FstabBackend(MediaList &list, bool networkSharesOnly)
+ : TQObject(), BackendBase(list), m_networkSharesOnly(networkSharesOnly)
+{
+ KDirWatch::self()->addFile(MTAB);
+ KDirWatch::self()->addFile(FSTAB);
+
+ connect( KDirWatch::self(), TQT_SIGNAL( dirty(const TQString&) ),
+ this, TQT_SLOT( slotDirty(const TQString&) ) );
+
+ handleFstabChange(false);
+ handleMtabChange(false);
+
+ KDirWatch::self()->startScan();
+
+#ifdef Q_OS_FREEBSD
+ connect( &m_mtabTimer, TQT_SIGNAL( timeout() ),
+ this, TQT_SLOT( handleMtabChange() ) );
+ m_mtabTimer.start(250);
+#endif
+}
+
+FstabBackend::~FstabBackend()
+{
+ TQStringList::iterator it = m_mtabIds.begin();
+ TQStringList::iterator end = m_mtabIds.end();
+
+ for (; it!=end; ++it)
+ {
+ m_mediaList.removeMedium(*it, false);
+ }
+
+ it = m_fstabIds.begin();
+ end = m_fstabIds.end();
+
+ for (; it!=end; ++it)
+ {
+ m_mediaList.removeMedium(*it, false);
+ }
+ KDirWatch::self()->removeFile(FSTAB);
+ KDirWatch::self()->removeFile(MTAB);
+}
+
+TQString FstabBackend::mount( const TQString &_udi )
+{
+ const Medium* medium = m_mediaList.findById(_udi);
+ if (!medium)
+ return i18n("No such medium: %1").arg(_udi);
+ TDEIO::Job* job = TDEIO::mount( false, 0, medium->deviceNode(), medium->mountPoint());
+ TDEIO::NetAccess::synchronousRun( job, 0 );
+ return TQString::null;
+}
+
+TQString FstabBackend::unmount( const TQString &_udi )
+{
+ const Medium* medium = m_mediaList.findById(_udi);
+ if (!medium)
+ return i18n("No such medium: %1").arg(_udi);
+ TDEIO::Job* job = TDEIO::unmount( medium->mountPoint(), false);
+ TDEIO::NetAccess::synchronousRun( job, 0 );
+ return TQString::null;
+}
+
+void FstabBackend::slotDirty(const TQString &path)
+{
+ if (path==MTAB)
+ {
+ handleMtabChange();
+ }
+ else if (path==FSTAB)
+ {
+ handleFstabChange();
+ }
+}
+
+bool inExclusionPattern(KMountPoint *mount, bool networkSharesOnly)
+{
+ if ( mount->mountType() == "swap"
+ || mount->mountType() == "tmpfs"
+ || mount->mountType() == "sysfs"
+ || mount->mountType() == "fdescfs"
+ || mount->mountType() == "kernfs"
+ || mount->mountType() == "usbfs"
+ || mount->mountType().contains( "proc" )
+ || mount->mountType() == "unknown"
+ || mount->mountType() == "none"
+ || mount->mountType() == "sunrpc"
+ || mount->mountedFrom() == "none"
+ || mount->mountedFrom() == "tmpfs"
+ || mount->mountedFrom().find("shm") != -1
+ || mount->mountPoint() == "/dev/swap"
+ || mount->mountPoint() == "/dev/pts"
+ || mount->mountPoint().find("/proc") == 0
+ || mount->mountPoint().find("/sys") == 0
+
+ // We might want to display only network shares
+ // since HAL doesn't handle them
+ || ( networkSharesOnly
+ && mount->mountType().find( "smb" ) == -1
+ && mount->mountType().find( "cifs" ) == -1
+ && mount->mountType().find( "nfs" ) == -1
+ )
+ )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+void FstabBackend::handleMtabChange(bool allowNotification)
+{
+ TQStringList new_mtabIds;
+ KMountPoint::List mtab = KMountPoint::currentMountPoints();
+
+ KMountPoint::List::iterator it = mtab.begin();
+ KMountPoint::List::iterator end = mtab.end();
+
+ for (; it!=end; ++it)
+ {
+ TQString dev = (*it)->mountedFrom();
+ TQString mp = (*it)->mountPoint();
+ TQString fs = (*it)->mountType();
+
+ if ( ::inExclusionPattern(*it, m_networkSharesOnly) ) continue;
+
+ /* Did we know this already before ? If yes, then
+ nothing has changed, do not stat the mount point. Avoids
+ hang if network shares are stalling */
+ TQString mtabEntry = dev + "*" + mp + "*" + fs;
+ if(m_mtabEntries.contains(mtabEntry)) {
+ new_mtabIds += m_mtabEntries[mtabEntry];
+ continue;
+ }
+
+ TQString id = generateId(dev, mp);
+ new_mtabIds+=id;
+ m_mtabEntries[mtabEntry] = id;
+
+ if ( !m_mtabIds.contains(id) && m_fstabIds.contains(id) )
+ {
+ TQString mime, icon, label;
+ guess(dev, mp, fs, true, mime, icon, label);
+ m_mediaList.changeMediumState(id, true, false,
+ mime, icon, label);
+ }
+#if 0
+ else if ( !m_mtabIds.contains(id) )
+ {
+ TQString name = generateName(dev, fs);
+
+ Medium *m = new Medium(id, name);
+
+ m->mountableState(dev, mp, fs, true);
+
+ TQString mime, icon, label;
+ guess(dev, mp, fs, true, mime, icon, label);
+
+ m->setMimeType(mime);
+ m->setIconName(icon);
+ m->setLabel(label);
+
+ m_mediaList.addMedium(m, notificationAllowed);
+ }
+#endif
+ }
+
+ TQStringList::iterator it2 = m_mtabIds.begin();
+ TQStringList::iterator end2 = m_mtabIds.end();
+
+ for (; it2!=end2; ++it2)
+ {
+ if ( !new_mtabIds.contains(*it2) && m_fstabIds.contains(*it2) )
+ {
+ const Medium *medium = m_mediaList.findById(*it2);
+
+ TQString dev = medium->deviceNode();
+ TQString mp = medium->mountPoint();
+ TQString fs = medium->fsType();
+
+
+ TQString mtabEntry = dev + "*" + mp + "*" + fs;
+ m_mtabEntries.remove(mtabEntry);
+
+ TQString mime, icon, label;
+ guess(dev, mp, fs, false, mime, icon, label);
+
+ m_mediaList.changeMediumState(*it2, false, false,
+ mime, icon, label);
+ }
+#if 0
+ else if ( !new_mtabIds.contains(*it2) )
+ {
+ m_mediaList.removeMedium(*it2, allowNotification);
+ }
+#endif
+ }
+
+ m_mtabIds = new_mtabIds;
+}
+
+void FstabBackend::handleFstabChange(bool allowNotification)
+{
+ TQStringList new_fstabIds;
+ KMountPoint::List fstab = KMountPoint::possibleMountPoints();
+
+ KMountPoint::List::iterator it = fstab.begin();
+ KMountPoint::List::iterator end = fstab.end();
+
+ for (; it!=end; ++it)
+ {
+ TQString dev = (*it)->mountedFrom();
+ TQString mp = (*it)->mountPoint();
+ TQString fs = (*it)->mountType();
+
+ if ( ::inExclusionPattern(*it, m_networkSharesOnly) ) continue;
+
+ TQString id = generateId(dev, mp);
+ new_fstabIds+=id;
+
+ if ( !m_fstabIds.contains(id) )
+ {
+ TQString name = generateName(dev, fs);
+
+ Medium *m = new Medium(id, id, name);
+
+ m->mountableState(dev, mp, fs, false);
+
+ TQString mime, icon, label;
+ guess(dev, mp, fs, false, mime, icon, label);
+
+ m->setMimeType(mime);
+ m->setIconName(icon);
+ m->setLabel(label);
+
+ m_mediaList.addMedium(m, allowNotification);
+ }
+ }
+
+ TQStringList::iterator it2 = m_fstabIds.begin();
+ TQStringList::iterator end2 = m_fstabIds.end();
+
+ for (; it2!=end2; ++it2)
+ {
+ if ( !new_fstabIds.contains(*it2) )
+ {
+ m_mediaList.removeMedium(*it2, allowNotification);
+ }
+ }
+
+ m_fstabIds = new_fstabIds;
+}
+
+TQString FstabBackend::generateId(const TQString &devNode,
+ const TQString &mountPoint)
+{
+ TQString d = KStandardDirs::realFilePath(devNode);
+ TQString m = KStandardDirs::realPath(mountPoint);
+
+ return "/org/kde/mediamanager/fstab/"
+ +d.replace("/", "")
+ +m.replace("/", "");
+}
+
+TQString FstabBackend::generateName(const TQString &devNode, const TQString &fsType)
+{
+ KURL url( devNode );
+
+ if ( url.isValid() )
+ {
+ return url.fileName();
+ }
+ else // surely something nfs or samba based
+ {
+ return fsType;
+ }
+}
+
+void FstabBackend::guess(const TQString &devNode, const TQString &mountPoint,
+ const TQString &fsType, bool mounted,
+ TQString &mimeType, TQString &iconName, TQString &label)
+{
+ enum { UNKNOWN, CD, CDWRITER, DVD, DVDWRITER } devType = UNKNOWN;
+#ifdef __linux__
+ // Guessing device types by mount point is not exactly accurate...
+ // Do something accurate first, and fall back if necessary.
+ int device=open(TQFile::encodeName(devNode), O_RDONLY|O_NONBLOCK);
+ if(device>=0)
+ {
+ bool isCd=false;
+ TQString devname=devNode.section('/', -1);
+ if(devname.startsWith("scd") || devname.startsWith("sr"))
+ {
+ // SCSI CD/DVD drive
+ isCd=true;
+ }
+ else if(devname.startsWith("hd"))
+ {
+ // IDE device -- we can't tell if this is a
+ // CD/DVD drive or harddisk by just looking at the
+ // filename
+ TQFile m(TQString("/proc/ide/") + devname + "/media");
+ if(m.open(IO_ReadOnly))
+ {
+ TQString buf;
+ m.readLine(buf, 1024);
+ if(buf.contains("cdrom"))
+ isCd=true;
+ m.close();
+ }
+ }
+ if(isCd)
+ {
+ int drv=ioctl(device, CDROM_GET_CAPABILITY, CDSL_CURRENT);
+ if(drv>=0)
+ {
+ if((drv & CDC_DVD_R) || (drv & CDC_DVD_RAM))
+ devType = DVDWRITER;
+ else if((drv & CDC_CD_R) || (drv & CDC_CD_RW))
+ devType = CDWRITER;
+ else if(drv & CDC_DVD)
+ devType = DVD;
+ else
+ devType = CD;
+ }
+ }
+ close(device);
+ }
+#endif
+ if ( devType == CDWRITER
+ || devNode.find("cdwriter")!=-1 || mountPoint.find("cdwriter")!=-1
+ || devNode.find("cdrecorder")!=-1 || mountPoint.find("cdrecorder")!=-1
+ || devNode.find("cdburner")!=-1 || mountPoint.find("cdburner")!=-1
+ || devNode.find("cdrw")!=-1 || mountPoint.find("cdrw")!=-1
+ || devNode.find("graveur")!=-1
+ )
+ {
+ mimeType = "media/cdwriter";
+ label = i18n("CD Recorder");
+ }
+ else if ( devType == DVD || devType == DVDWRITER
+ || devNode.find("dvd")!=-1 || mountPoint.find("dvd")!=-1 )
+ {
+ mimeType = "media/dvd";
+ label = i18n("DVD");
+ }
+ else if ( devType == CD
+ || devNode.find("cdrom")!=-1 || mountPoint.find("cdrom")!=-1
+ // LINUX SPECIFIC
+ || devNode.find("/dev/scd")!=-1 || devNode.find("/dev/sr")!=-1
+ // FREEBSD SPECIFIC
+ || devNode.find("/acd")!=-1 || devNode.find("/scd")!=-1
+ )
+ {
+ mimeType = "media/cdrom";
+ label = i18n("CD-ROM");
+ }
+ else if ( devNode.find("fd")!=-1 || mountPoint.find("fd")!=-1
+ || devNode.find("floppy")!=-1 || mountPoint.find("floppy")!=-1 )
+ {
+ if ( devNode.find("360")!=-1 || devNode.find("1200")!=-1 )
+ {
+ mimeType = "media/floppy5";
+ }
+ else
+ {
+ mimeType = "media/floppy";
+ }
+ label = i18n("Floppy");
+ }
+ else if ( mountPoint.find("zip")!=-1
+ // FREEBSD SPECIFIC
+ || devNode.find("/afd")!=-1
+ )
+ {
+ mimeType = "media/zip";
+ label = i18n("Zip Disk");
+ }
+ else if ( mountPoint.find("removable")!=-1
+ || mountPoint.find("hotplug")!=-1
+ || mountPoint.find("usb")!=-1
+ || mountPoint.find("firewire")!=-1
+ || mountPoint.find("ieee1394")!=-1
+ || devNode.find("/usb/")!= -1
+ )
+ {
+ mimeType = "media/removable";
+ label = i18n("Removable Device");
+ }
+ else if ( fsType.find("nfs")!=-1 )
+ {
+ mimeType = "media/nfs";
+ label = i18n("Remote Share");
+ }
+ else if ( fsType.find("smb")!=-1 || fsType.find("cifs")!=-1
+ || devNode.find("//")!=-1 )
+ {
+ mimeType = "media/smb";
+ label = i18n("Remote Share");
+ }
+ else
+ {
+ mimeType = "media/hdd";
+ label = i18n("Hard Disk");
+ }
+
+ if ( mimeType=="media/nfs" || mimeType=="media/smb" )
+ {
+ label+= " (" + devNode + ")";
+ }
+ else
+ {
+ TQString tmp = devNode;
+ if ( tmp.startsWith("/dev/") )
+ {
+ tmp = tmp.mid(5);
+ }
+ label+= " (" + tmp + ")";
+ }
+ mimeType+= (mounted ? "_mounted" : "_unmounted");
+ iconName = TQString::null;
+}
+
+#include "fstabbackend.moc"
diff --git a/tdeioslave/media/mediamanager/fstabbackend.h b/tdeioslave/media/mediamanager/fstabbackend.h
new file mode 100644
index 000000000..e43ed48c0
--- /dev/null
+++ b/tdeioslave/media/mediamanager/fstabbackend.h
@@ -0,0 +1,68 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 K�vin Ottens <ervin ipsquad net>
+
+ 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 _FSTABBACKEND_H_
+#define _FSTABBACKEND_H_
+
+#include "backendbase.h"
+
+#include <tqobject.h>
+#include <tqstringlist.h>
+#include <tqmap.h>
+
+#ifdef Q_OS_FREEBSD
+#include <tqtimer.h>
+#endif
+
+class FstabBackend : public TQObject, public BackendBase
+{
+Q_OBJECT
+
+public:
+ FstabBackend(MediaList &list, bool networkSharesOnly = false);
+ virtual ~FstabBackend();
+
+ static void guess(const TQString &devNode, const TQString &mountPoint,
+ const TQString &fsType, bool mounted,
+ TQString &mimeType, TQString &iconName,
+ TQString &label);
+
+ TQString mount(const TQString &id);
+ TQString unmount(const TQString &id);
+
+private slots:
+ void slotDirty(const TQString &path);
+ void handleFstabChange(bool allowNotification = true);
+ void handleMtabChange(bool allowNotification = true);
+
+private:
+ static TQString generateId(const TQString &devNode,
+ const TQString &mountPoint);
+ static TQString generateName(const TQString &devNode,
+ const TQString &fsType);
+
+ bool m_networkSharesOnly;
+ TQStringList m_mtabIds;
+ TQMap<TQString, TQString> m_mtabEntries;
+ TQStringList m_fstabIds;
+#ifdef Q_OS_FREEBSD
+ TQTimer m_mtabTimer;
+#endif
+};
+
+#endif
diff --git a/tdeioslave/media/mediamanager/halbackend.cpp b/tdeioslave/media/mediamanager/halbackend.cpp
new file mode 100644
index 000000000..aba2b0175
--- /dev/null
+++ b/tdeioslave/media/mediamanager/halbackend.cpp
@@ -0,0 +1,1858 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004-2005 Jérôme Lodewyck <jerome dot lodewyck at normalesup dot org>
+ Copyright (c) 2006 Valentine Sinitsyn <[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 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 "halbackend.h"
+#include "linuxcdpolling.h"
+
+#include <stdlib.h>
+#include <locale.h>
+
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <tqeventloop.h>
+#include <tqfile.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <kdebug.h>
+#include <kprocess.h>
+#include <tdeconfig.h>
+#include <tqstylesheet.h>
+#include <kmountpoint.h>
+#include <kmessagebox.h>
+#include <tdeio/job.h>
+#include <kprotocolinfo.h>
+#include <kstandarddirs.h>
+#include <kprocess.h>
+
+#define MOUNT_SUFFIX ( \
+ (medium->isMounted() ? TQString("_mounted") : TQString("_unmounted")) + \
+ (medium->isEncrypted() ? (halClearVolume ? "_decrypted" : "_encrypted") : "" ) \
+ )
+#define MOUNT_ICON_SUFFIX ( \
+ (medium->isMounted() ? TQString("_mount") : TQString("_unmount")) + \
+ (medium->isEncrypted() ? (halClearVolume ? "_decrypt" : "_encrypt") : "" ) \
+ )
+
+/* Static instance of this class, for static HAL callbacks */
+static HALBackend* s_HALBackend;
+
+/* A macro function to convert HAL string properties to TQString */
+TQString libhal_device_get_property_QString(LibHalContext *ctx, const char* udi, const char *key)
+{
+ char* _ppt_string;
+ TQString _ppt_QString;
+ _ppt_string = libhal_device_get_property_string(ctx, udi, key, NULL);
+ if ( _ppt_string )
+ _ppt_QString = _ppt_string;
+ libhal_free_string(_ppt_string);
+ return _ppt_QString;
+}
+
+/* Constructor */
+HALBackend::HALBackend(MediaList &list, TQObject* parent)
+ : TQObject()
+ , BackendBase(list)
+ , m_halContext(NULL)
+ , m_halStoragePolicy(NULL)
+ , m_parent(parent)
+{
+ s_HALBackend = this;
+}
+
+/* Destructor */
+HALBackend::~HALBackend()
+{
+ /* Close HAL connection */
+ if (m_halContext)
+ {
+ const TQPtrList<Medium> medlist = m_mediaList.list();
+ TQPtrListIterator<Medium> it (medlist);
+ for ( const Medium *current_medium = it.current(); current_medium; current_medium = ++it)
+ {
+ if( !current_medium->id().startsWith( "/org/kde" ))
+ unmount(current_medium->id());
+ }
+
+
+ /* Remove all the registered media first */
+ int numDevices;
+ char** halDeviceList = libhal_get_all_devices( m_halContext, &numDevices, NULL );
+
+ if ( halDeviceList )
+ {
+ for ( int i = 0; i < numDevices; i++ )
+ {
+ m_mediaList.removeMedium( halDeviceList[i], false );
+ }
+ }
+
+ libhal_free_string_array( halDeviceList );
+
+ DBusError error;
+ dbus_error_init(&error);
+ libhal_ctx_shutdown(m_halContext, &error);
+ libhal_ctx_free(m_halContext);
+ }
+
+ if (m_halStoragePolicy)
+ libhal_storage_policy_free(m_halStoragePolicy);
+}
+
+/* Connect to the HAL */
+bool HALBackend::InitHal()
+{
+ kdDebug(1219) << "Context new" << endl;
+ m_halContext = libhal_ctx_new();
+ if (!m_halContext)
+ {
+ kdDebug(1219) << "Failed to initialize HAL!" << endl;
+ return false;
+ }
+
+ // Main loop integration
+ kdDebug(1219) << "Main loop integration" << endl;
+ DBusError error;
+ dbus_error_init(&error);
+ dbus_connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
+
+ if (!dbus_connection || dbus_error_is_set(&error)) {
+ dbus_error_free(&error);
+ libhal_ctx_free(m_halContext);
+ m_halContext = NULL;
+ return false;
+ }
+
+ dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
+
+ MainLoopIntegration(dbus_connection);
+ libhal_ctx_set_dbus_connection(m_halContext, dbus_connection);
+
+ // HAL callback functions
+ kdDebug(1219) << "Callback functions" << endl;
+ libhal_ctx_set_device_added(m_halContext, HALBackend::hal_device_added);
+ libhal_ctx_set_device_removed(m_halContext, HALBackend::hal_device_removed);
+ libhal_ctx_set_device_new_capability (m_halContext, NULL);
+ libhal_ctx_set_device_lost_capability (m_halContext, NULL);
+ libhal_ctx_set_device_property_modified (m_halContext, HALBackend::hal_device_property_modified);
+ libhal_ctx_set_device_condition(m_halContext, HALBackend::hal_device_condition);
+
+ kdDebug(1219) << "Context Init" << endl;
+ if (!libhal_ctx_init(m_halContext, &error))
+ {
+ if (dbus_error_is_set(&error))
+ dbus_error_free(&error);
+ libhal_ctx_free(m_halContext);
+ m_halContext = NULL;
+ kdDebug(1219) << "Failed to init HAL context!" << endl;
+ return false;
+ }
+
+ /** @todo customize watch policy */
+ kdDebug(1219) << "Watch properties" << endl;
+ if (!libhal_device_property_watch_all(m_halContext, &error))
+ {
+ kdDebug(1219) << "Failed to watch HAL properties!" << endl;
+ return false;
+ }
+
+ /* libhal-storage initialization */
+ kdDebug(1219) << "Storage Policy" << endl;
+ m_halStoragePolicy = libhal_storage_policy_new();
+ /** @todo define libhal-storage icon policy */
+
+ /* List devices at startup */
+ return ListDevices();
+}
+
+/* List devices (at startup)*/
+bool HALBackend::ListDevices()
+{
+ kdDebug(1219) << "ListDevices" << endl;
+
+ int numDevices;
+ char** halDeviceList = libhal_get_all_devices(m_halContext, &numDevices, NULL);
+
+ if (!halDeviceList)
+ return false;
+
+ kdDebug(1219) << "HALBackend::ListDevices : " << numDevices << " devices found" << endl;
+ for (int i = 0; i < numDevices; i++)
+ AddDevice(halDeviceList[i], false);
+
+ libhal_free_string_array( halDeviceList );
+
+ return true;
+}
+
+/* Create a media instance for the HAL device "udi".
+ This functions checks whether the device is worth listing */
+void HALBackend::AddDevice(const char *udi, bool allowNotification)
+{
+ /* We don't deal with devices that do not expose their capabilities.
+ If we don't check this, we will get a lot of warning messages from libhal */
+ if (!libhal_device_property_exists(m_halContext, udi, "info.capabilities", NULL))
+ return;
+
+ /* If the device is already listed, do not process.
+ This should not happen, but who knows... */
+ /** @todo : refresh properties instead ? */
+ if (m_mediaList.findById(udi))
+ return;
+
+ if (libhal_device_get_property_bool(m_halContext, "/org/freedesktop/Hal/devices/computer", "storage.disable_volume_handling", NULL))
+ allowNotification=false;
+
+ /* Add volume block devices */
+ if (libhal_device_query_capability(m_halContext, udi, "volume", NULL))
+ {
+ /* We only list volumes that...
+ * - are encrypted with LUKS or
+ * - have a filesystem or
+ * - have an audio track
+ */
+ if ( ( libhal_device_get_property_QString(m_halContext, udi, "volume.fsusage") != "crypto" ||
+ libhal_device_get_property_QString(m_halContext, udi, "volume.fstype") != "crypto_LUKS"
+ ) &&
+ libhal_device_get_property_QString(m_halContext, udi, "volume.fsusage") != "filesystem" &&
+ !libhal_device_get_property_bool(m_halContext, udi, "volume.disc.has_audio", NULL) &&
+ !libhal_device_get_property_bool(m_halContext, udi, "volume.disc.is_blank", NULL) )
+ return;
+
+ /* Query drive udi */
+ TQString driveUdi = libhal_device_get_property_QString(m_halContext, udi, "block.storage_device");
+ if ( driveUdi.isNull() ) // no storage - no fun
+ return;
+
+ // if the device is locked do not act upon it
+ if (libhal_device_get_property_bool(m_halContext, driveUdi.ascii(), "info.locked", NULL))
+ allowNotification=false;
+
+ // if the device is locked do not act upon it
+ if (libhal_device_get_property_bool(m_halContext, driveUdi.ascii(), "storage.partition_table_changed", NULL))
+ allowNotification=false;
+
+ /** @todo check exclusion list **/
+
+ /* Special handling for clear crypto volumes */
+ LibHalVolume* halVolume = libhal_volume_from_udi(m_halContext, udi);
+ if (!halVolume)
+ return;
+ const char* backingVolumeUdi = libhal_volume_crypto_get_backing_volume_udi(halVolume);
+ if ( backingVolumeUdi != NULL )
+ {
+ /* The crypto drive was unlocked and may now be mounted... */
+ kdDebug(1219) << "HALBackend::AddDevice : ClearVolume appeared for " << backingVolumeUdi << endl;
+ ResetProperties(backingVolumeUdi, allowNotification);
+ libhal_volume_free(halVolume);
+ return;
+ }
+ libhal_volume_free(halVolume);
+
+ /* Create medium */
+ Medium* medium = new Medium(udi, udi, "");
+ setVolumeProperties(medium);
+
+ if ( isInFstab( medium ).isNull() )
+ {
+ // if it's not mountable by user and not by HAL, don't show it at all
+ if ( ( libhal_device_get_property_QString(m_halContext, udi, "volume.fsusage") == "filesystem" &&
+ !libhal_device_get_property_bool(m_halContext, udi, "volume.is_mounted", NULL ) ) &&
+ ( libhal_device_get_property_bool(m_halContext, udi, "volume.ignore", NULL ) ) )
+ {
+ delete medium;
+ return;
+ }
+ }
+
+ // instert medium into list
+ m_mediaList.addMedium(medium, allowNotification);
+
+ // finally check for automount
+ TQMap<TQString,TQString> options = MediaManagerUtils::splitOptions(mountoptions(udi));
+ kdDebug() << "automount " << options["automount"] << endl;
+ if (options["automount"] == "true" && allowNotification ) {
+ TQString error = mount(medium);
+ if (!error.isEmpty())
+ kdDebug() << "error " << error << endl;
+ }
+
+ return;
+ }
+
+ /* Floppy & zip drives */
+ if (libhal_device_query_capability(m_halContext, udi, "storage", NULL))
+ if ((libhal_device_get_property_QString(m_halContext, udi, "storage.drive_type") == "floppy") ||
+ (libhal_device_get_property_QString(m_halContext, udi, "storage.drive_type") == "zip") ||
+ (libhal_device_get_property_QString(m_halContext, udi, "storage.drive_type") == "jaz"))
+ {
+ if (! libhal_device_get_property_bool(m_halContext, udi, "storage.removable.media_available", NULL) )
+ allowNotification = false;
+ /* Create medium */
+ Medium* medium = new Medium(udi, udi, "");
+ // if the storage has a volume, we ignore it
+ if ( setFloppyProperties(medium) )
+ m_mediaList.addMedium(medium, allowNotification);
+ else
+ delete medium;
+ return;
+ }
+
+ /* Camera handled by gphoto2*/
+ if (libhal_device_query_capability(m_halContext, udi, "camera", NULL) &&
+ ((libhal_device_get_property_QString(m_halContext, udi, "camera.access_method")=="ptp") ||
+
+ (libhal_device_property_exists(m_halContext, udi, "camera.libgphoto2.support", NULL) &&
+ libhal_device_get_property_bool(m_halContext, udi, "camera.libgphoto2.support", NULL)))
+ )
+ {
+ /* Create medium */
+ Medium* medium = new Medium(udi, udi, "");
+ setCameraProperties(medium);
+ m_mediaList.addMedium(medium, allowNotification);
+ return;
+ }
+}
+
+void HALBackend::RemoveDevice(const char *udi)
+{
+ const Medium *medium = m_mediaList.findByClearUdi(udi);
+ if (medium) {
+ ResetProperties(medium->id().ascii());
+ } else {
+ m_mediaList.removeMedium(udi, true);
+ }
+}
+
+void HALBackend::ModifyDevice(const char *udi, const char* key)
+{
+ kdDebug(1219) << "HALBackend::ModifyDevice for '" << udi << "' on '" << key << "'\n";
+
+ const char* mediumUdi = findMediumUdiFromUdi(udi);
+ if (!mediumUdi)
+ return;
+ bool allowNotification = false;
+ if (strcmp(key, "storage.removable.media_available") == 0)
+ allowNotification = libhal_device_get_property_bool(m_halContext, udi, key, NULL);
+ ResetProperties(mediumUdi, allowNotification);
+}
+
+void HALBackend::DeviceCondition(const char* udi, const char* condition)
+{
+ TQString conditionName = TQString(condition);
+ kdDebug(1219) << "Processing device condition " << conditionName << " for " << udi << endl;
+
+ if (conditionName == "EjectPressed") {
+ const Medium* medium = m_mediaList.findById(udi);
+ if (!medium) {
+ /* the ejectpressed appears on the drive and we need to find the volume */
+ const TQPtrList<Medium> medlist = m_mediaList.list();
+ TQPtrListIterator<Medium> it (medlist);
+ for ( const Medium *current_medium = it.current(); current_medium; current_medium = ++it)
+ {
+ if( current_medium->id().startsWith( "/org/kde" ))
+ continue;
+ TQString driveUdi = libhal_device_get_property_QString(m_halContext, current_medium->id().latin1(), "block.storage_device");
+ if (driveUdi == udi)
+ {
+ medium = current_medium;
+ break;
+ }
+ }
+ }
+ if (medium) {
+ TDEProcess p;
+ p << "kio_media_mounthelper" << "-e" << medium->name();
+ p.start(TDEProcess::DontCare);
+ }
+ }
+
+ const char* mediumUdi = findMediumUdiFromUdi(udi);
+ kdDebug() << "findMedumUdiFromUdi " << udi << " returned " << mediumUdi << endl;
+ if (!mediumUdi)
+ return;
+
+ /* TODO: Warn the user that (s)he should unmount devices before unplugging */
+ if (conditionName == "VolumeUnmountForced")
+ ResetProperties(mediumUdi);
+
+ /* Reset properties after mounting */
+ if (conditionName == "VolumeMount")
+ ResetProperties(mediumUdi);
+
+ /* Reset properties after unmounting */
+ if (conditionName == "VolumeUnmount")
+ ResetProperties(mediumUdi);
+
+}
+
+void HALBackend::MainLoopIntegration(DBusConnection *dbusConnection)
+{
+ m_dBusQtConnection = new DBusQt::Connection(m_parent);
+ m_dBusQtConnection->dbus_connection_setup_with_qt_main(dbusConnection);
+}
+
+/******************************************
+ ** Properties attribution **
+ ******************************************/
+
+/* Return the medium udi that should be updated when recieving a call for
+ device udi */
+const char* HALBackend::findMediumUdiFromUdi(const char* udi)
+{
+ /* Easy part : this Udi is already registered as a device */
+ const Medium* medium = m_mediaList.findById(udi);
+ if (medium)
+ return medium->id().ascii();
+
+ /* Hard part : this is a volume whose drive is registered */
+ if (libhal_device_property_exists(m_halContext, udi, "info.capabilities", NULL))
+ if (libhal_device_query_capability(m_halContext, udi, "volume", NULL))
+ {
+ /* check if this belongs to an encrypted volume */
+ LibHalVolume* halVolume = libhal_volume_from_udi(m_halContext, udi);
+ if (!halVolume) return NULL;
+ const char* backingUdi = libhal_volume_crypto_get_backing_volume_udi(halVolume);
+ if (backingUdi != NULL) {
+ const char* result = findMediumUdiFromUdi(backingUdi);
+ libhal_volume_free(halVolume);
+ return result;
+ }
+ libhal_volume_free(halVolume);
+
+ /* this is a volume whose drive is registered */
+ TQString driveUdi = libhal_device_get_property_QString(m_halContext, udi, "block.storage_device");
+ return findMediumUdiFromUdi(driveUdi.ascii());
+ }
+
+ return NULL;
+}
+
+void HALBackend::ResetProperties(const char* mediumUdi, bool allowNotification)
+{
+ kdDebug(1219) << "HALBackend::setProperties" << endl;
+ if ( TQString::fromLatin1( mediumUdi ).startsWith( "/org/kde/" ) )
+ {
+ const Medium *cmedium = m_mediaList.findById(mediumUdi);
+ if ( cmedium )
+ {
+ Medium m( *cmedium );
+ if ( setFstabProperties( &m ) ) {
+ kdDebug() << "setFstabProperties worked" << endl;
+ m_mediaList.changeMediumState(m, allowNotification);
+ }
+ return;
+ }
+ }
+
+ Medium* m = new Medium(mediumUdi, mediumUdi, "");
+
+ if (libhal_device_query_capability(m_halContext, mediumUdi, "volume", NULL))
+ setVolumeProperties(m);
+ if (libhal_device_query_capability(m_halContext, mediumUdi, "storage", NULL))
+ setFloppyProperties(m);
+ if (libhal_device_query_capability(m_halContext, mediumUdi, "camera", NULL))
+ setCameraProperties(m);
+
+ m_mediaList.changeMediumState(*m, allowNotification);
+
+ delete m;
+}
+
+void HALBackend::setVolumeProperties(Medium* medium)
+{
+ kdDebug(1219) << "HALBackend::setVolumeProperties for " << medium->id() << endl;
+
+ const char* udi = medium->id().ascii();
+ /* Check if the device still exists */
+ if (!libhal_device_exists(m_halContext, udi, NULL))
+ return;
+
+ /* Get device information from libhal-storage */
+ LibHalVolume* halVolume = libhal_volume_from_udi(m_halContext, udi);
+ if (!halVolume)
+ return;
+ TQString driveUdi = libhal_volume_get_storage_device_udi(halVolume);
+ LibHalDrive* halDrive = 0;
+ if ( !driveUdi.isNull() )
+ halDrive = libhal_drive_from_udi(m_halContext, driveUdi.ascii());
+ if (!halDrive) {
+ // at times HAL sends an UnmountForced event before the device is removed
+ libhal_volume_free(halVolume);
+ return;
+ }
+
+ medium->setName(
+ generateName(libhal_volume_get_device_file(halVolume)) );
+
+ LibHalVolume* halClearVolume = NULL;
+ if ( libhal_device_get_property_QString(m_halContext, udi, "volume.fsusage") == "crypto" )
+ {
+ kdDebug(1219) << "HALBackend::setVolumeProperties : crypto volume" << endl;
+
+ medium->setEncrypted(true);
+ char* clearUdi = libhal_volume_crypto_get_clear_volume_udi(m_halContext, halVolume);
+ TQString clearUdiString;
+ if (clearUdi != NULL) {
+ kdDebug(1219) << "HALBackend::setVolumeProperties : crypto clear volume avail - " << clearUdi << endl;
+ halClearVolume = libhal_volume_from_udi(m_halContext, clearUdi);
+ // ignore if halClearVolume is NULL -> just not decrypted in this case
+ clearUdiString = clearUdi;
+ libhal_free_string(clearUdi);
+ }
+
+ if (halClearVolume)
+ medium->mountableState(
+ libhal_volume_get_device_file(halVolume), /* Device node */
+ clearUdiString,
+ libhal_volume_get_mount_point(halClearVolume), /* Mount point */
+ libhal_volume_get_fstype(halClearVolume), /* Filesystem type */
+ libhal_volume_is_mounted(halClearVolume) ); /* Mounted ? */
+ else
+ medium->mountableState(
+ libhal_volume_get_device_file(halVolume), /* Device node */
+ TQString::null,
+ TQString::null, /* Mount point */
+ TQString::null, /* Filesystem type */
+ false ); /* Mounted ? */
+ }
+ else
+ {
+ kdDebug(1219) << "HALBackend::setVolumeProperties : normal volume" << endl;
+ medium->mountableState(
+ libhal_volume_get_device_file(halVolume), /* Device node */
+ libhal_volume_get_mount_point(halVolume), /* Mount point */
+ libhal_volume_get_fstype(halVolume), /* Filesystem type */
+ libhal_volume_is_mounted(halVolume) ); /* Mounted ? */
+ }
+
+
+ char* name = libhal_volume_policy_compute_display_name(halDrive, halVolume, m_halStoragePolicy);
+ TQString volume_name = TQString::fromUtf8(name);
+ TQString media_name = volume_name;
+ medium->setLabel(media_name);
+ free(name);
+
+ TQString mimeType;
+ if (libhal_volume_is_disc(halVolume))
+ {
+ mimeType = "media/cdrom" + MOUNT_SUFFIX;
+
+ LibHalVolumeDiscType discType = libhal_volume_get_disc_type(halVolume);
+ if ((discType == LIBHAL_VOLUME_DISC_TYPE_CDROM) ||
+ (discType == LIBHAL_VOLUME_DISC_TYPE_CDR) ||
+ (discType == LIBHAL_VOLUME_DISC_TYPE_CDRW))
+ if (libhal_volume_disc_is_blank(halVolume))
+ {
+ mimeType = "media/blankcd";
+ medium->unmountableState("");
+ }
+ else
+ mimeType = "media/cdwriter" + MOUNT_SUFFIX;
+
+ if ((discType == LIBHAL_VOLUME_DISC_TYPE_DVDROM) || (discType == LIBHAL_VOLUME_DISC_TYPE_DVDRAM) ||
+ (discType == LIBHAL_VOLUME_DISC_TYPE_DVDR) || (discType == LIBHAL_VOLUME_DISC_TYPE_DVDRW) ||
+ (discType == LIBHAL_VOLUME_DISC_TYPE_DVDPLUSR) || (discType == LIBHAL_VOLUME_DISC_TYPE_DVDPLUSRW) )
+ if (libhal_volume_disc_is_blank(halVolume))
+ {
+ mimeType = "media/blankdvd";
+ medium->unmountableState("");
+ }
+ else
+ mimeType = "media/dvd" + MOUNT_SUFFIX;
+
+ if (libhal_volume_disc_has_audio(halVolume) && !libhal_volume_disc_has_data(halVolume))
+ {
+ mimeType = "media/audiocd";
+ medium->unmountableState( "audiocd:/?device=" + TQString(libhal_volume_get_device_file(halVolume)) );
+ }
+
+ medium->setIconName(TQString::null);
+
+ /* check if the disc id a vcd or a video dvd */
+ DiscType type = LinuxCDPolling::identifyDiscType(libhal_volume_get_device_file(halVolume));
+ switch (type)
+ {
+ case DiscType::VCD:
+ mimeType = "media/vcd";
+ break;
+ case DiscType::SVCD:
+ mimeType = "media/svcd";
+ break;
+ case DiscType::DVD:
+ mimeType = "media/dvdvideo";
+ break;
+ }
+ }
+ else
+ {
+ mimeType = "media/hdd" + MOUNT_SUFFIX;
+ medium->setIconName(TQString::null); // reset icon
+ if (libhal_drive_is_hotpluggable(halDrive))
+ {
+ mimeType = "media/removable" + MOUNT_SUFFIX;
+ medium->needMounting();
+ switch (libhal_drive_get_type(halDrive)) {
+ case LIBHAL_DRIVE_TYPE_COMPACT_FLASH:
+ medium->setIconName("compact_flash" + MOUNT_ICON_SUFFIX);
+ break;
+ case LIBHAL_DRIVE_TYPE_MEMORY_STICK:
+ medium->setIconName("memory_stick" + MOUNT_ICON_SUFFIX);
+ break;
+ case LIBHAL_DRIVE_TYPE_SMART_MEDIA:
+ medium->setIconName("smart_media" + MOUNT_ICON_SUFFIX);
+ break;
+ case LIBHAL_DRIVE_TYPE_SD_MMC:
+ medium->setIconName("sd_mmc" + MOUNT_ICON_SUFFIX);
+ break;
+ case LIBHAL_DRIVE_TYPE_PORTABLE_AUDIO_PLAYER:
+ {
+ medium->setIconName("ipod" + MOUNT_ICON_SUFFIX);
+
+ if (libhal_device_get_property_QString(m_halContext, driveUdi.latin1(), "info.product") == "iPod" &&
+ KProtocolInfo::isKnownProtocol( TQString("ipod") ) )
+ {
+ medium->unmountableState( "ipod:/" );
+ medium->mountableState( libhal_volume_is_mounted(halVolume) );
+ }
+ break;
+ }
+ case LIBHAL_DRIVE_TYPE_CAMERA:
+ {
+ mimeType = "media/camera" + MOUNT_SUFFIX;
+ const char *physdev = libhal_drive_get_physical_device_udi(halDrive);
+ // get model from camera
+ if (physdev && libhal_device_query_capability(m_halContext, physdev, "camera", NULL))
+ {
+ if (libhal_device_property_exists(m_halContext, physdev, "usb_device.product", NULL))
+ medium->setLabel(libhal_device_get_property_QString(m_halContext, physdev, "usb_device.product"));
+ else if (libhal_device_property_exists(m_halContext, physdev, "usb.product", NULL))
+ medium->setLabel(libhal_device_get_property_QString(m_halContext, physdev, "usb.product"));
+ }
+ break;
+ }
+ case LIBHAL_DRIVE_TYPE_TAPE:
+ medium->setIconName(TQString::null); //FIXME need icon
+ break;
+ default:
+ medium->setIconName(TQString::null);
+ }
+
+ if (medium->isMounted() && TQFile::exists(medium->mountPoint() + "/dcim"))
+ {
+ mimeType = "media/camera" + MOUNT_SUFFIX;
+ }
+ }
+ }
+ medium->setMimeType(mimeType);
+
+ libhal_drive_free(halDrive);
+ libhal_volume_free(halVolume);
+}
+
+bool HALBackend::setFstabProperties( Medium *medium )
+{
+ TQString mp = isInFstab(medium);
+
+ if (!mp.isNull() && !medium->id().startsWith( "/org/kde" ) )
+ {
+ // now that we know it's in fstab, we have to find out if it's mounted
+ KMountPoint::List mtab = KMountPoint::currentMountPoints();
+
+ KMountPoint::List::iterator it = mtab.begin();
+ KMountPoint::List::iterator end = mtab.end();
+
+ bool mounted = false;
+
+ for (; it!=end; ++it)
+ {
+ if ((*it)->mountedFrom() == medium->deviceNode() && (*it)->mountPoint() == mp )
+ {
+ mounted = true;
+ break;
+ }
+ }
+
+ kdDebug() << mp << " " << mounted << " " << medium->deviceNode() << " " << endl;
+ TQString fstype = medium->fsType();
+ if ( fstype.isNull() )
+ fstype = "auto";
+
+ medium->mountableState(
+ medium->deviceNode(),
+ mp, /* Mount point */
+ fstype, /* Filesystem type */
+ mounted ); /* Mounted ? */
+
+ return true;
+ }
+
+ return false;
+
+}
+
+// Handle floppies and zip drives
+bool HALBackend::setFloppyProperties(Medium* medium)
+{
+ kdDebug(1219) << "HALBackend::setFloppyProperties for " << medium->id() << endl;
+
+ const char* udi = medium->id().ascii();
+ /* Check if the device still exists */
+ if (!libhal_device_exists(m_halContext, udi, NULL))
+ return false;
+
+ LibHalDrive* halDrive = libhal_drive_from_udi(m_halContext, udi);
+ if (!halDrive)
+ return false;
+
+ TQString drive_type = libhal_device_get_property_QString(m_halContext, udi, "storage.drive_type");
+
+ if (drive_type == "zip") {
+ int numVolumes;
+ char** volumes = libhal_drive_find_all_volumes(m_halContext, halDrive, &numVolumes);
+ libhal_free_string_array(volumes);
+ kdDebug(1219) << " found " << numVolumes << " volumes" << endl;
+ if (numVolumes)
+ {
+ libhal_drive_free(halDrive);
+ return false;
+ }
+ }
+
+ medium->setName( generateName(libhal_drive_get_device_file(halDrive)) );
+ medium->setLabel(i18n("Unknown Drive"));
+
+ // HAL hates floppies - so we have to do it twice ;(
+ medium->mountableState(libhal_drive_get_device_file(halDrive), TQString::null, TQString::null, false);
+ setFloppyMountState(medium);
+
+ if (drive_type == "floppy")
+ {
+ if (medium->isMounted()) // don't use _SUFFIX here as it accesses the volume
+ medium->setMimeType("media/floppy_mounted" );
+ else
+ medium->setMimeType("media/floppy_unmounted");
+ medium->setLabel(i18n("Floppy Drive"));
+ }
+ else if (drive_type == "zip")
+ {
+ if (medium->isMounted())
+ medium->setMimeType("media/zip_mounted" );
+ else
+ medium->setMimeType("media/zip_unmounted");
+ medium->setLabel(i18n("Zip Drive"));
+ }
+
+ /** @todo And mimtype for JAZ drives ? */
+
+ medium->setIconName(TQString::null);
+
+ libhal_drive_free(halDrive);
+
+ return true;
+}
+
+void HALBackend::setFloppyMountState( Medium *medium )
+{
+ if ( !medium->id().startsWith( "/org/kde" ) )
+ {
+ KMountPoint::List mtab = KMountPoint::currentMountPoints();
+ KMountPoint::List::iterator it = mtab.begin();
+ KMountPoint::List::iterator end = mtab.end();
+
+ TQString fstype;
+ TQString mountpoint;
+ for (; it!=end; ++it)
+ {
+ if ((*it)->mountedFrom() == medium->deviceNode() )
+ {
+ fstype = (*it)->mountType().isNull() ? (*it)->mountType() : "auto";
+ mountpoint = (*it)->mountPoint();
+ medium->mountableState( medium->deviceNode(), mountpoint, fstype, true );
+ return;
+ }
+ }
+ }
+}
+
+void HALBackend::setCameraProperties(Medium* medium)
+{
+ kdDebug(1219) << "HALBackend::setCameraProperties for " << medium->id() << endl;
+
+ const char* udi = medium->id().ascii();
+ /* Check if the device still exists */
+ if (!libhal_device_exists(m_halContext, udi, NULL))
+ return;
+
+ /** @todo find name */
+ medium->setName("camera");
+
+ TQString device = "camera:/";
+
+ char *cam = libhal_device_get_property_string(m_halContext, udi, "camera.libgphoto2.name", NULL);
+ DBusError error;
+ dbus_error_init(&error);
+ if (cam &&
+ libhal_device_property_exists(m_halContext, udi, "usb.linux.device_number", NULL) &&
+ libhal_device_property_exists(m_halContext, udi, "usb.bus_number", NULL))
+ device.sprintf("camera://%s@[usb:%03d,%03d]/", cam,
+ libhal_device_get_property_int(m_halContext, udi, "usb.bus_number", &error),
+ libhal_device_get_property_int(m_halContext, udi, "usb.linux.device_number", &error));
+
+ libhal_free_string(cam);
+
+ /** @todo find the rest of this URL */
+ medium->unmountableState(device);
+ medium->setMimeType("media/gphoto2camera");
+ medium->setIconName(TQString::null);
+ if (libhal_device_property_exists(m_halContext, udi, "usb_device.product", NULL))
+ medium->setLabel(libhal_device_get_property_QString(m_halContext, udi, "usb_device.product"));
+ else if (libhal_device_property_exists(m_halContext, udi, "usb.product", NULL))
+ medium->setLabel(libhal_device_get_property_QString(m_halContext, udi, "usb.product"));
+ else
+ medium->setLabel(i18n("Camera"));
+}
+
+TQString HALBackend::generateName(const TQString &devNode)
+{
+ return KURL(devNode).fileName();
+}
+
+/******************************************
+ ** HAL CALL-BACKS **
+ ******************************************/
+
+void HALBackend::hal_device_added(LibHalContext *ctx, const char *udi)
+{
+ kdDebug(1219) << "HALBackend::hal_device_added " << udi << endl;
+ Q_UNUSED(ctx);
+ s_HALBackend->AddDevice(udi);
+}
+
+void HALBackend::hal_device_removed(LibHalContext *ctx, const char *udi)
+{
+ kdDebug(1219) << "HALBackend::hal_device_removed " << udi << endl;
+ Q_UNUSED(ctx);
+ s_HALBackend->RemoveDevice(udi);
+}
+
+void HALBackend::hal_device_property_modified(LibHalContext *ctx, const char *udi,
+ const char *key, dbus_bool_t is_removed, dbus_bool_t is_added)
+{
+ kdDebug(1219) << "HALBackend::hal_property_modified " << udi << " -- " << key << endl;
+ Q_UNUSED(ctx);
+ Q_UNUSED(is_removed);
+ Q_UNUSED(is_added);
+ s_HALBackend->ModifyDevice(udi, key);
+}
+
+void HALBackend::hal_device_condition(LibHalContext *ctx, const char *udi,
+ const char *condition_name,
+ const char* message
+ )
+{
+ kdDebug(1219) << "HALBackend::hal_device_condition " << udi << " -- " << condition_name << endl;
+ Q_UNUSED(ctx);
+ Q_UNUSED(message);
+ s_HALBackend->DeviceCondition(udi, condition_name);
+}
+
+TQStringList HALBackend::getHALmountoptions(TQString udi)
+{
+ const char* _ppt_string;
+ LibHalVolume* volume;
+ LibHalDrive* drive;
+
+ TQString _ppt_TQString;
+
+ volume = libhal_volume_from_udi( m_halContext, udi.latin1() );
+ if( volume )
+ drive = libhal_drive_from_udi( m_halContext, libhal_volume_get_storage_device_udi( volume ) );
+ else
+ drive = libhal_drive_from_udi( m_halContext, udi.latin1() );
+
+ if( !drive )
+ return TQString::null;
+
+ if( volume )
+ _ppt_string = libhal_volume_policy_get_mount_options ( drive, volume, NULL );
+ else
+ _ppt_string = libhal_drive_policy_get_mount_options ( drive, NULL );
+
+ _ppt_TQString = TQString(_ppt_string ? _ppt_string : "");
+
+ return TQStringList::split(",",_ppt_TQString);
+}
+
+TQStringList HALBackend::mountoptions(const TQString &name)
+{
+ const Medium* medium = m_mediaList.findById(name);
+ if (!medium)
+ return TQStringList(); // we don't know about that one
+ if (!isInFstab(medium).isNull())
+ return TQStringList(); // not handled by HAL - fstab entry
+
+ TQString volume_udi = name;
+ if (medium->isEncrypted()) {
+ // see if we have a clear volume
+ LibHalVolume* halVolume = libhal_volume_from_udi(m_halContext, medium->id().latin1());
+ if (halVolume) {
+ char* clearUdi = libhal_volume_crypto_get_clear_volume_udi(m_halContext, halVolume);
+ if (clearUdi != NULL) {
+ volume_udi = clearUdi;
+ libhal_free_string(clearUdi);
+ } else {
+ // if not decrypted yet then no mountoptions
+ return TQStringList();
+ }
+ libhal_volume_free(halVolume);
+ } else {
+ // strange...
+ return TQStringList();
+ }
+ }
+
+ TDEConfig config("mediamanagerrc");
+
+ bool use_defaults = true;
+ if (config.hasGroup(name))
+ {
+ config.setGroup(name);
+ use_defaults = config.readBoolEntry("use_defaults", false);
+ }
+
+ if (use_defaults)
+ config.setGroup("DefaultOptions");
+
+ char ** array = libhal_device_get_property_strlist(m_halContext, volume_udi.latin1(), "volume.mount.valid_options", NULL);
+ TQMap<TQString,bool> valids;
+
+ for (int index = 0; array && array[index]; ++index) {
+ TQString t = array[index];
+ if (t.endsWith("="))
+ t = t.left(t.length() - 1);
+ valids[t] = true;
+ kdDebug() << "valid " << t << endl;
+ }
+ libhal_free_string_array(array);
+ TQStringList result;
+ TQString tmp;
+
+ result << TQString("use_defaults=%1").arg(use_defaults ? "true" : "false");
+
+ TQString fstype = libhal_device_get_property_QString(m_halContext, volume_udi.latin1(), "volume.fstype");
+ if (fstype.isNull())
+ fstype = libhal_device_get_property_QString(m_halContext, volume_udi.latin1(), "volume.policy.mount_filesystem");
+
+ TQString drive_udi = libhal_device_get_property_QString(m_halContext, volume_udi.latin1(), "block.storage_device");
+
+ bool removable = false;
+ if ( !drive_udi.isNull() )
+ removable = libhal_device_get_property_bool(m_halContext, drive_udi.latin1(), "storage.removable", NULL)
+ || libhal_device_get_property_bool(m_halContext, drive_udi.latin1(), "storage.hotpluggable", NULL);
+
+ bool value;
+ if (use_defaults)
+ {
+ value = config.readBoolEntry("automount", false);
+ }
+ else
+ {
+ QString current_group = config.group();
+ config.setGroup(drive_udi);
+ value = config.readBoolEntry("automount", false);
+ config.setGroup(current_group);
+ }
+
+ if (libhal_device_get_property_bool(m_halContext, volume_udi.latin1(), "volume.disc.is_blank", NULL)
+ || libhal_device_get_property_bool(m_halContext, volume_udi.latin1(), "volume.disc.is_vcd", NULL)
+ || libhal_device_get_property_bool(m_halContext, volume_udi.latin1(), "volume.disc.is_svcd", NULL)
+ || libhal_device_get_property_bool(m_halContext, volume_udi.latin1(), "volume.disc.is_videodvd", NULL)
+ || libhal_device_get_property_bool(m_halContext, volume_udi.latin1(), "volume.disc.has_audio", NULL))
+ value = false;
+
+ result << TQString("automount=%1").arg(value ? "true" : "false");
+
+ if (valids.contains("ro"))
+ {
+ value = config.readBoolEntry("ro", false);
+ tmp = TQString("ro=%1").arg(value ? "true" : "false");
+ if (fstype != "iso9660") // makes no sense
+ result << tmp;
+ }
+
+ if (valids.contains("quiet"))
+ {
+ value = config.readBoolEntry("quiet", false);
+ tmp = TQString("quiet=%1").arg(value ? "true" : "false");
+ if (fstype != "iso9660") // makes no sense
+ result << tmp;
+ }
+
+ if (valids.contains("flush"))
+ {
+ value = config.readBoolEntry("flush", fstype.endsWith("fat"));
+ tmp = TQString("flush=%1").arg(value ? "true" : "false");
+ result << tmp;
+ }
+
+ if (valids.contains("uid"))
+ {
+ value = config.readBoolEntry("uid", true);
+ tmp = TQString("uid=%1").arg(value ? "true" : "false");
+ result << tmp;
+ }
+
+ if (valids.contains("utf8"))
+ {
+ value = config.readBoolEntry("utf8", true);
+ tmp = TQString("utf8=%1").arg(value ? "true" : "false");
+ result << tmp;
+ }
+
+ if (valids.contains("shortname"))
+ {
+ TQString svalue = config.readEntry("shortname", "lower").lower();
+ if (svalue == "winnt")
+ result << "shortname=winnt";
+ else if (svalue == "win95")
+ result << "shortname=win95";
+ else if (svalue == "mixed")
+ result << "shortname=mixed";
+ else
+ result << "shortname=lower";
+ }
+
+ // pass our locale to the ntfs-3g driver so it can translate local characters
+ if (valids.contains("locale") && fstype == "ntfs-3g")
+ {
+ // have to obtain LC_CTYPE as returned by the `locale` command
+ // check in the same order as `locale` does
+ char *cType;
+ if ( (cType = getenv("LC_ALL")) || (cType = getenv("LC_CTYPE")) || (cType = getenv("LANG")) ) {
+ result << TQString("locale=%1").arg(cType);
+ }
+ }
+
+ if (valids.contains("sync"))
+ {
+ value = config.readBoolEntry("sync", ( valids.contains("flush") && !fstype.endsWith("fat") ) && removable);
+ tmp = TQString("sync=%1").arg(value ? "true" : "false");
+ if (fstype != "iso9660") // makes no sense
+ result << tmp;
+ }
+
+ if (valids.contains("noatime"))
+ {
+ value = config.readBoolEntry("atime", !fstype.endsWith("fat"));
+ tmp = TQString("atime=%1").arg(value ? "true" : "false");
+ if (fstype != "iso9660") // makes no sense
+ result << tmp;
+ }
+
+ TQString mount_point = libhal_device_get_property_QString(m_halContext, volume_udi.latin1(), "volume.mount_point");
+ if (mount_point.isEmpty())
+ mount_point = libhal_device_get_property_QString(m_halContext, volume_udi.latin1(), "volume.policy.desired_mount_point");
+
+ mount_point = config.readEntry("mountpoint", mount_point);
+
+ if (!mount_point.startsWith("/"))
+ mount_point = "/media/" + mount_point;
+
+ result << TQString("mountpoint=%1").arg(mount_point);
+ result << TQString("filesystem=%1").arg(fstype);
+
+ if (valids.contains("data"))
+ {
+ TQString svalue = config.readEntry("journaling").lower();
+ if (svalue == "ordered")
+ result << "journaling=ordered";
+ else if (svalue == "writeback")
+ result << "journaling=writeback";
+ else if (svalue == "data")
+ result << "journaling=data";
+ else
+ result << "journaling=ordered";
+ }
+
+ return result;
+}
+
+bool HALBackend::setMountoptions(const TQString &name, const TQStringList &options )
+{
+ kdDebug() << "setMountoptions " << name << " " << options << endl;
+
+ TDEConfig config("mediamanagerrc");
+ config.setGroup(name);
+
+ TQMap<TQString,TQString> valids = MediaManagerUtils::splitOptions(options);
+
+ const char *names[] = { "use_defaults", "ro", "quiet", "atime", "uid", "utf8", "flush", "sync", 0 };
+ for (int index = 0; names[index]; ++index)
+ if (valids.contains(names[index]))
+ config.writeEntry(names[index], valids[names[index]] == "true");
+
+ if (valids.contains("shortname"))
+ config.writeEntry("shortname", valids["shortname"]);
+
+ if (valids.contains("journaling"))
+ config.writeEntry("journaling", valids["journaling"]);
+
+ if (!mountoptions(name).contains(TQString("mountpoint=%1").arg(valids["mountpoint"])))
+ config.writeEntry("mountpoint", valids["mountpoint"]);
+
+ if (valids.contains("automount")) {
+ TQString drive_udi = libhal_device_get_property_QString(m_halContext, name.latin1(), "block.storage_device");
+ config.setGroup(drive_udi);
+ config.writeEntry("automount", valids["automount"]);
+ }
+
+ return true;
+}
+
+TQString startKdeSudoProcess(const TQString& tdesudoPath, const TQString& command,
+ const TQString& dialogCaption, const TQString& dialogComment)
+{
+ TDEProcess tdesudoProcess;
+
+ tdesudoProcess << tdesudoPath
+ << "-d"
+ << "--noignorebutton"
+ << "--caption" << dialogCaption
+ << "--comment" << dialogComment
+ << "-c" << command;
+
+ // @todo handle tdesudo output
+ tdesudoProcess.start(TDEProcess::Block);
+
+ return TQString();
+}
+
+TQString startKdeSuProcess(const TQString& tdesuPath, const TQString& command,
+ const TQString& dialogCaption)
+{
+ TDEProcess tdesuProcess;
+
+ tdesuProcess << tdesuPath
+ << "-d"
+ << "--noignorebutton"
+ << "--caption" << dialogCaption
+ << "-c" << command;
+
+ // @todo handle tdesu output
+ tdesuProcess.start(TDEProcess::Block);
+
+ return TQString();
+}
+
+TQString startPrivilegedProcess(const TQString& command, const TQString& dialogCaption, const TQString& dialogComment)
+{
+ TQString error;
+
+ TQString tdesudoPath = KStandardDirs::findExe("tdesudo");
+
+ if (!tdesudoPath.isEmpty())
+ error = startKdeSudoProcess(tdesudoPath, command, dialogCaption, dialogComment);
+ else {
+ TQString tdesuPath = KStandardDirs::findExe("tdesu");
+
+ if (!tdesuPath.isEmpty())
+ error = startKdeSuProcess(tdesuPath, command, dialogCaption);
+ }
+
+ return error;
+}
+
+TQString privilegedMount(const char* udi, const char* mountPoint, const char** options, int numberOfOptions)
+{
+ TQString error;
+
+ kdDebug() << "run privileged mount for " << udi << endl;
+
+ TQString dbusSendPath = KStandardDirs::findExe("dbus-send");
+
+ // @todo return error message
+ if (dbusSendPath.isEmpty())
+ return TQString();
+
+ TQString mountOptions;
+ TQTextOStream optionsStream(&mountOptions);
+ for (int optionIndex = 0; optionIndex < numberOfOptions; optionIndex++) {
+ optionsStream << options[optionIndex];
+ if (optionIndex < numberOfOptions - 1)
+ optionsStream << ",";
+ }
+
+ TQString command;
+ TQTextOStream(&command) << dbusSendPath
+ << " --system --print-reply --dest=org.freedesktop.Hal " << udi
+ << " org.freedesktop.Hal.Device.Volume.Mount string:" << mountPoint
+ << " string: array:string:" << mountOptions;
+
+ kdDebug() << "command: " << command << endl;
+
+ error = startPrivilegedProcess(command,
+ i18n("Authenticate"),
+ i18n("<big><b>System policy prevents mounting internal media</b></big><br/>Authentication is required to perform this action. Please enter your password to verify."));
+
+ return error;
+}
+
+TQString privilegedUnmount(const char* udi)
+{
+ TQString error;
+
+ kdDebug() << "run privileged unmount for " << udi << endl;
+
+ TQString dbusSendPath = KStandardDirs::findExe("dbus-send");
+
+ // @todo return error message
+ if (dbusSendPath.isEmpty())
+ return TQString();
+
+ TQString command;
+ TQTextOStream(&command) << dbusSendPath
+ << " --system --print-reply --dest=org.freedesktop.Hal " << udi
+ << " org.freedesktop.Hal.Device.Volume.Unmount array:string:force";
+
+ kdDebug() << "command: " << command << endl;
+
+ error = startPrivilegedProcess(command,
+ i18n("Authenticate"),
+ i18n("<big><b>System policy prevents unmounting media mounted by other users</b></big><br/>Authentication is required to perform this action. Please enter your password to verify."));
+
+ return error;
+}
+
+static TQString mount_priv(const char *udi, const char *mount_point, const char **poptions, int noptions,
+ DBusConnection *dbus_connection)
+{
+ DBusMessage *dmesg, *reply;
+ DBusError error;
+
+ const char *fstype = "";
+ if (!(dmesg = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
+ "org.freedesktop.Hal.Device.Volume",
+ "Mount"))) {
+ kdDebug() << "mount failed for " << udi << ": could not create dbus message\n";
+ return i18n("Internal Error");
+ }
+
+ if (!dbus_message_append_args (dmesg, DBUS_TYPE_STRING, &mount_point, DBUS_TYPE_STRING, &fstype,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &poptions, noptions,
+ DBUS_TYPE_INVALID))
+ {
+ kdDebug() << "mount failed for " << udi << ": could not append args to dbus message\n";
+ dbus_message_unref (dmesg);
+ return i18n("Internal Error");
+ }
+
+ TQString qerror;
+
+ dbus_error_init (&error);
+ if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, dmesg, -1, &error)))
+ {
+ TQString qerror = error.message;
+ kdError() << "mount failed for " << udi << ": " << error.name << " - " << qerror << endl;
+ if ( !strcmp(error.name, "org.freedesktop.Hal.Device.Volume.UnknownFilesystemType"))
+ qerror = i18n("Invalid filesystem type");
+ else if ( !strcmp(error.name, "org.freedesktop.Hal.Device.Volume.PermissionDenied"))
+ qerror = i18n("Permission denied<p>Please ensure that:<br>1. You have permission to access this device.<br>2. This device node is not listed in /etc/fstab.</p>");
+ else if ( !strcmp(error.name, "org.freedesktop.Hal.Device.PermissionDeniedByPolicy"))
+ qerror = privilegedMount(udi, mount_point, poptions, noptions);
+ else if ( !strcmp(error.name, "org.freedesktop.Hal.Device.Volume.AlreadyMounted"))
+ qerror = i18n("Device is already mounted.");
+ else if ( !strcmp(error.name, "org.freedesktop.Hal.Device.Volume.InvalidMountpoint") && strlen(mount_point)) {
+ dbus_message_unref (dmesg);
+ dbus_error_free (&error);
+ return mount_priv(udi, "", poptions, noptions, dbus_connection);
+ }
+ dbus_message_unref (dmesg);
+ dbus_error_free (&error);
+ return qerror;
+ }
+
+ kdDebug() << "mount queued for " << udi << endl;
+
+ dbus_message_unref (dmesg);
+ dbus_message_unref (reply);
+
+ return qerror;
+
+}
+
+TQString HALBackend::listUsingProcesses(const Medium* medium)
+{
+ TQString proclist, fullmsg;
+ TQString cmdline = TQString("/usr/bin/env fuser -vm %1 2>&1").arg(TDEProcess::quote(medium->mountPoint()));
+ FILE *fuser = popen(cmdline.latin1(), "r");
+
+ uint counter = 0;
+ if (fuser) {
+ proclist += "<pre>";
+ TQTextIStream is(fuser);
+ TQString tmp;
+ while (!is.atEnd()) {
+ tmp = is.readLine();
+ tmp = TQStyleSheet::escape(tmp) + "\n";
+
+ proclist += tmp;
+ if (counter++ > 10)
+ {
+ proclist += "...";
+ break;
+ }
+ }
+ proclist += "</pre>";
+ (void)pclose( fuser );
+ }
+ if (counter) {
+ fullmsg = i18n("Moreover, programs still using the device "
+ "have been detected. They are listed below. You have to "
+ "close them or change their working directory before "
+ "attempting to unmount the device again.");
+ fullmsg += "<br>" + proclist;
+ return fullmsg;
+ } else {
+ return TQString::null;
+ }
+}
+
+TQString HALBackend::killUsingProcesses(const Medium* medium)
+{
+ TQString proclist, fullmsg;
+ TQString cmdline = TQString("/usr/bin/env fuser -vmk %1 2>&1").arg(TDEProcess::quote(medium->mountPoint()));
+ FILE *fuser = popen(cmdline.latin1(), "r");
+
+ uint counter = 0;
+ if (fuser) {
+ proclist += "<pre>";
+ TQTextIStream is(fuser);
+ TQString tmp;
+ while (!is.atEnd()) {
+ tmp = is.readLine();
+ tmp = TQStyleSheet::escape(tmp) + "\n";
+
+ proclist += tmp;
+ if (counter++ > 10)
+ {
+ proclist += "...";
+ break;
+ }
+ }
+ proclist += "</pre>";
+ (void)pclose( fuser );
+ }
+ if (counter) {
+ fullmsg = i18n("Programs that were still using the device "
+ "have been forcibly terminated. They are listed below.");
+ fullmsg += "<br>" + proclist;
+ return fullmsg;
+ } else {
+ return TQString::null;
+ }
+}
+
+void HALBackend::slotResult(TDEIO::Job *job)
+{
+ kdDebug() << "slotResult " << mount_jobs[job] << endl;
+
+ struct mount_job_data *data = mount_jobs[job];
+ TQString& qerror = data->errorMessage;
+ const Medium* medium = data->medium;
+
+ if (job->error() == TDEIO::ERR_COULD_NOT_UNMOUNT) {
+ TQString proclist(listUsingProcesses(medium));
+
+ qerror = "<qt>";
+ qerror += "<p>" + i18n("Unfortunately, the device <b>%1</b> (%2) named <b>'%3'</b> and "
+ "currently mounted at <b>%4</b> could not be unmounted. ").arg(
+ "system:/media/" + medium->name(),
+ medium->deviceNode(),
+ medium->prettyLabel(),
+ medium->prettyBaseURL().pathOrURL()) + "</p>";
+ qerror += "<p>" + i18n("The following error was returned by umount command:");
+ qerror += "</p><pre>" + job->errorText() + "</pre>";
+
+ if (!proclist.isEmpty()) {
+ qerror += proclist;
+ }
+ qerror += "</qt>";
+ } else if (job->error()) {
+ qerror = job->errorText();
+ }
+
+ ResetProperties( medium->id().latin1() );
+ mount_jobs.remove(job);
+
+ /* Job completed. Notify the caller */
+ data->error = job->error();
+ data->completed = true;
+ kapp->eventLoop()->exitLoop();
+}
+
+TQString HALBackend::isInFstab(const Medium *medium)
+{
+ KMountPoint::List fstab = KMountPoint::possibleMountPoints(KMountPoint::NeedMountOptions|KMountPoint::NeedRealDeviceName);
+
+ KMountPoint::List::iterator it = fstab.begin();
+ KMountPoint::List::iterator end = fstab.end();
+
+ for (; it!=end; ++it)
+ {
+ TQString reald = (*it)->realDeviceName();
+ if ( reald.endsWith( "/" ) )
+ reald = reald.left( reald.length() - 1 );
+ kdDebug() << "isInFstab -" << medium->deviceNode() << "- -" << reald << "- -" << (*it)->mountedFrom() << "-" << endl;
+ if ((*it)->mountedFrom() == medium->deviceNode() || ( !medium->deviceNode().isEmpty() && reald == medium->deviceNode() ) )
+ {
+ TQStringList opts = (*it)->mountOptions();
+ if (opts.contains("user") || opts.contains("users"))
+ return (*it)->mountPoint();
+ }
+ }
+
+ return TQString::null;
+}
+
+TQString HALBackend::mount(const Medium *medium)
+{
+ if (medium->isMounted())
+ return TQString(); // that was easy
+
+ TQString mountPoint = isInFstab(medium);
+ if (!mountPoint.isNull())
+ {
+ struct mount_job_data data;
+ data.completed = false;
+ data.medium = medium;
+
+ kdDebug() << "triggering user mount " << medium->deviceNode() << " " << mountPoint << " " << medium->id() << endl;
+ TDEIO::Job *job = TDEIO::mount( false, 0, medium->deviceNode(), mountPoint );
+ connect(job, TQT_SIGNAL( result (TDEIO::Job *)),
+ TQT_SLOT( slotResult( TDEIO::Job *)));
+ mount_jobs[job] = &data;
+ // The caller expects the device to be mounted when the function
+ // completes. Thus block until the job completes.
+ while (!data.completed) {
+ kapp->eventLoop()->enterLoop();
+ }
+ // Return the error message (if any) to the caller
+ return (data.error) ? data.errorMessage : TQString::null;
+
+ } else if (medium->id().startsWith("/org/kde/") )
+ return i18n("Permission denied");
+
+ TQStringList soptions;
+
+ kdDebug() << "mounting " << medium->id() << "..." << endl;
+
+ TQMap<TQString,TQString> valids = MediaManagerUtils::splitOptions(mountoptions(medium->id()));
+ if (valids["flush"] == "true")
+ soptions << "flush";
+
+ if ((valids["uid"] == "true") && (medium->fsType() != "ntfs"))
+ {
+ soptions << TQString("uid=%1").arg(getuid());
+ }
+
+ if (valids["ro"] == "true")
+ soptions << "ro";
+
+ if (valids["atime"] != "true")
+ soptions << "noatime";
+
+ if (valids["quiet"] == "true")
+ soptions << "quiet";
+
+ if (valids["utf8"] == "true")
+ soptions << "utf8";
+
+ if (valids["sync"] == "true")
+ soptions << "sync";
+
+ if (medium->fsType() == "ntfs") {
+ TQString fsLocale("locale=");
+ fsLocale += setlocale(LC_ALL, "");
+
+ soptions << fsLocale;
+ }
+
+ TQString mount_point = valids["mountpoint"];
+ if (mount_point.startsWith("/media/"))
+ mount_point = mount_point.mid(7);
+
+ if (valids.contains("shortname"))
+ {
+ soptions << TQString("shortname=%1").arg(valids["shortname"]);
+ }
+
+ if (valids.contains("locale"))
+ {
+ soptions << TQString("locale=%1").arg(valids["locale"]);
+ }
+
+ if (valids.contains("journaling"))
+ {
+ TQString option = valids["journaling"];
+ if (option == "data")
+ soptions << TQString("data=journal");
+ else if (option == "writeback")
+ soptions << TQString("data=writeback");
+ else
+ soptions << TQString("data=ordered");
+ }
+
+ TQStringList hal_mount_options = getHALmountoptions(medium->id());
+ for (TQValueListIterator<TQString> it=hal_mount_options.begin();it!=hal_mount_options.end();it++)
+ {
+ soptions << *it;
+ kdDebug()<<"HALOption: "<<*it<<endl;
+ if ((*it).startsWith("iocharset="))
+ {
+ soptions.remove("utf8");
+ kdDebug()<<"\"iocharset=\" found. Removing \"utf8\" from options."<<endl;
+ }
+ }
+
+
+ const char **options = new const char*[soptions.size() + 1];
+ uint noptions = 0;
+ for (TQStringList::ConstIterator it = soptions.begin(); it != soptions.end(); ++it, ++noptions)
+ {
+ options[noptions] = (*it).latin1();
+ kdDebug()<<"Option: "<<*it<<endl;
+ }
+ options[noptions] = NULL;
+
+ TQString qerror = i18n("Cannot mount encrypted drives!");
+
+ if (!medium->isEncrypted()) {
+ // normal volume
+ qerror = mount_priv(medium->id().latin1(), mount_point.utf8(), options, noptions, dbus_connection);
+ } else {
+ // see if we have a clear volume
+ LibHalVolume* halVolume = libhal_volume_from_udi(m_halContext, medium->id().latin1());
+ if (halVolume) {
+ char* clearUdi = libhal_volume_crypto_get_clear_volume_udi(m_halContext, halVolume);
+ if (clearUdi != NULL) {
+ qerror = mount_priv(clearUdi, mount_point.utf8(), options, noptions, dbus_connection);
+ libhal_free_string(clearUdi);
+ }
+ libhal_volume_free(halVolume);
+ }
+ }
+
+ if (!qerror.isEmpty()) {
+ kdError() << "mounting " << medium->id() << " returned " << qerror << endl;
+ return qerror;
+ }
+
+ medium->setHalMounted(true);
+ ResetProperties(medium->id().latin1());
+
+ return TQString();
+}
+
+TQString HALBackend::mount(const TQString &_udi)
+{
+ const Medium* medium = m_mediaList.findById(_udi);
+ if (!medium)
+ return i18n("No such medium: %1").arg(_udi);
+
+ return mount(medium);
+}
+
+TQString HALBackend::unmount(const TQString &_udi)
+{
+ const Medium* medium = m_mediaList.findById(_udi);
+ if (!medium)
+ { // now we get fancy: if the udi is no volume, it _might_ be a device with only one
+ // volume on it (think CDs) - so we're so nice to the caller to unmount that volume
+ LibHalDrive* halDrive = libhal_drive_from_udi(m_halContext, _udi.latin1());
+ if (halDrive)
+ {
+ int numVolumes;
+ char** volumes = libhal_drive_find_all_volumes(m_halContext, halDrive, &numVolumes);
+ if (numVolumes == 1)
+ medium = m_mediaList.findById( volumes[0] );
+ }
+ }
+
+ if ( !medium )
+ return i18n("No such medium: %1").arg(_udi);
+
+ if (!medium->isMounted())
+ return TQString(); // that was easy
+
+ TQString mountPoint = isInFstab(medium);
+ if (!mountPoint.isNull())
+ {
+ struct mount_job_data data;
+ data.completed = false;
+ data.medium = medium;
+
+ kdDebug() << "triggering user unmount " << medium->deviceNode() << " " << mountPoint << endl;
+ TDEIO::Job *job = TDEIO::unmount( medium->mountPoint(), false );
+ connect(job, TQT_SIGNAL( result (TDEIO::Job *)),
+ TQT_SLOT( slotResult( TDEIO::Job *)));
+ mount_jobs[job] = &data;
+ // The caller expects the device to be unmounted when the function
+ // completes. Thus block until the job completes.
+ while (!data.completed) {
+ kapp->eventLoop()->enterLoop();
+ }
+ // Return the error message (if any) to the caller
+ return (data.error) ? data.errorMessage : TQString::null;
+ }
+
+ DBusMessage *dmesg, *reply;
+ DBusError error;
+ const char *options[2];
+ TQString udi = TQString::null;
+
+ if (!medium->isEncrypted()) {
+ // normal volume
+ udi = medium->id();
+ } else {
+ // see if we have a clear volume
+ LibHalVolume* halVolume = libhal_volume_from_udi(m_halContext, medium->id().latin1());
+ if (halVolume) {
+ char *clearUdi = libhal_volume_crypto_get_clear_volume_udi(m_halContext, halVolume);
+ udi = clearUdi;
+ libhal_free_string(clearUdi);
+ libhal_volume_free(halVolume);
+ }
+ }
+ if (udi.isNull()) {
+ kdDebug() << "unmount failed: no udi" << endl;
+ return i18n("Internal Error");
+ }
+
+ kdDebug() << "unmounting " << udi << "..." << endl;
+
+ dbus_error_init(&error);
+ DBusConnection *dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ if (dbus_error_is_set(&error))
+ {
+ dbus_error_free(&error);
+ return false;
+ }
+
+ if (!(dmesg = dbus_message_new_method_call ("org.freedesktop.Hal", udi.latin1(),
+ "org.freedesktop.Hal.Device.Volume",
+ "Unmount"))) {
+ kdDebug() << "unmount failed for " << udi << ": could not create dbus message\n";
+ return i18n("Internal Error");
+ }
+
+ options[0] = "force";
+ options[1] = 0;
+
+ if (!dbus_message_append_args (dmesg, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, 0,
+ DBUS_TYPE_INVALID))
+ {
+ kdDebug() << "unmount failed for " << udi << ": could not append args to dbus message\n";
+ dbus_message_unref (dmesg);
+ return i18n("Internal Error");
+ }
+
+ char thisunmounthasfailed = 0;
+ dbus_error_init (&error);
+ if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, dmesg, -1, &error)))
+ {
+ thisunmounthasfailed = 1;
+ TQString qerror, reason, origqerror;
+
+ if (!strcmp(error.name, "org.freedesktop.Hal.Device.PermissionDeniedByPolicy")) {
+ qerror = privilegedUnmount(udi.latin1());
+
+ if (qerror.isEmpty()) {
+ dbus_message_unref(dmesg);
+ dbus_error_free(&error);
+ return TQString();
+ }
+
+ // @todo handle unmount error message
+ }
+
+ kdDebug() << "unmount failed for " << udi << ": " << error.name << " " << error.message << endl;
+ qerror = "<qt>";
+ qerror += "<p>" + i18n("Unfortunately, the device <b>%1</b> (%2) named <b>'%3'</b> and "
+ "currently mounted at <b>%4</b> could not be unmounted. ").arg(
+ "system:/media/" + medium->name(),
+ medium->deviceNode(),
+ medium->prettyLabel(),
+ medium->prettyBaseURL().pathOrURL()) + "</p>";
+ qerror += "<p>" + i18n("Unmounting failed due to the following error:") + "</p>";
+ if (!strcmp(error.name, "org.freedesktop.Hal.Device.Volume.Busy")) {
+ reason = i18n("Device is Busy:");
+ thisunmounthasfailed = 2;
+ } else if (!strcmp(error.name, "org.freedesktop.Hal.Device.Volume.NotMounted")) {
+ // this is faking. The error is that the device wasn't mounted by hal (but by the system)
+ reason = i18n("Permission denied<p>Please ensure that:<br>1. You have permission to access this device.<br>2. This device was originally mounted using TDE.</p>");
+ } else {
+ reason = error.message;
+ }
+ qerror += "<p><b>" + reason + "</b></p>";
+ origqerror = qerror;
+
+ // Include list of processes (if any) using the device in the error message
+ reason = listUsingProcesses(medium);
+ if (!reason.isEmpty()) {
+ qerror += reason;
+ if (thisunmounthasfailed == 2) { // Failed as BUSY
+ if (KMessageBox::warningYesNo(0, i18n("%1<p><b>Would you like to forcibly terminate these processes?</b><br><i>All unsaved data would be lost</i>").arg(qerror)) == KMessageBox::Yes) {
+ qerror = origqerror;
+ reason = killUsingProcesses(medium);
+ qerror = HALBackend::unmount(udi);
+ if (qerror.isNull()) {
+ thisunmounthasfailed = 0;
+ }
+ }
+ }
+ }
+
+ if (thisunmounthasfailed != 0) {
+ dbus_message_unref (dmesg);
+ dbus_error_free (&error);
+ return qerror;
+ }
+ }
+
+ kdDebug() << "unmount queued for " << udi << endl;
+
+ dbus_message_unref (dmesg);
+ dbus_message_unref (reply);
+
+ medium->setHalMounted(false);
+ ResetProperties(medium->id().latin1());
+
+ while (dbus_connection_dispatch(dbus_connection) == DBUS_DISPATCH_DATA_REMAINS) ;
+
+ return TQString();
+}
+
+TQString HALBackend::decrypt(const TQString &_udi, const TQString &password)
+{
+ const Medium* medium = m_mediaList.findById(_udi);
+ if (!medium)
+ return i18n("No such medium: %1").arg(_udi);
+
+ if (!medium->isEncrypted() || !medium->clearDeviceUdi().isNull())
+ return TQString();
+
+ const char *udi = medium->id().latin1();
+ DBusMessage *msg = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ kdDebug() << "Setting up " << udi << " for crypto\n" <<endl;
+
+ msg = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
+ "org.freedesktop.Hal.Device.Volume.Crypto",
+ "Setup");
+ if (msg == NULL) {
+ kdDebug() << "decrypt failed for " << udi << ": could not create dbus message\n";
+ return i18n("Internal Error");
+ }
+
+ TQCString pwdUtf8 = password.utf8();
+ const char *pwd_utf8 = pwdUtf8;
+ if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, &pwd_utf8, DBUS_TYPE_INVALID)) {
+ kdDebug() << "decrypt failed for " << udi << ": could not append args to dbus message\n";
+ dbus_message_unref (msg);
+ return i18n("Internal Error");
+ }
+
+ dbus_error_init (&error);
+ if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, msg, -1, &error)) ||
+ dbus_error_is_set (&error))
+ {
+ TQString qerror = i18n("Internal Error");
+ kdDebug() << "decrypt failed for " << udi << ": " << error.name << " " << error.message << endl;
+ if (strcmp (error.name, "org.freedesktop.Hal.Device.Volume.Crypto.SetupPasswordError") == 0) {
+ qerror = i18n("Wrong password");
+ }
+ dbus_error_free (&error);
+ dbus_message_unref (msg);
+ while (dbus_connection_dispatch(dbus_connection) == DBUS_DISPATCH_DATA_REMAINS) ;
+ return qerror;
+ }
+
+ dbus_message_unref (msg);
+ dbus_message_unref (reply);
+
+ while (dbus_connection_dispatch(dbus_connection) == DBUS_DISPATCH_DATA_REMAINS) ;
+
+ return TQString();
+}
+
+TQString HALBackend::undecrypt(const TQString &_udi)
+{
+ const Medium* medium = m_mediaList.findById(_udi);
+ if (!medium)
+ return i18n("No such medium: %1").arg(_udi);
+
+ if (!medium->isEncrypted() || medium->clearDeviceUdi().isNull())
+ return TQString();
+
+ const char *udi = medium->id().latin1();
+ DBusMessage *msg = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ kdDebug() << "Tear down " << udi << "\n" <<endl;
+
+ msg = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
+ "org.freedesktop.Hal.Device.Volume.Crypto",
+ "Teardown");
+ if (msg == NULL) {
+ kdDebug() << "teardown failed for " << udi << ": could not create dbus message\n";
+ return i18n("Internal Error");
+ }
+
+ if (!dbus_message_append_args (msg, DBUS_TYPE_INVALID)) {
+ kdDebug() << "teardown failed for " << udi << ": could not append args to dbus message\n";
+ dbus_message_unref (msg);
+ return i18n("Internal Error");
+ }
+
+ dbus_error_init (&error);
+ if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, msg, -1, &error)) ||
+ dbus_error_is_set (&error))
+ {
+ TQString qerror = i18n("Internal Error");
+ kdDebug() << "teardown failed for " << udi << ": " << error.name << " " << error.message << endl;
+ dbus_error_free (&error);
+ dbus_message_unref (msg);
+ while (dbus_connection_dispatch(dbus_connection) == DBUS_DISPATCH_DATA_REMAINS) ;
+ return qerror;
+ }
+
+ dbus_message_unref (msg);
+ dbus_message_unref (reply);
+
+ ResetProperties(udi);
+
+ while (dbus_connection_dispatch(dbus_connection) == DBUS_DISPATCH_DATA_REMAINS) ;
+
+ return TQString();
+}
+
+#include "halbackend.moc"
diff --git a/tdeioslave/media/mediamanager/halbackend.h b/tdeioslave/media/mediamanager/halbackend.h
new file mode 100644
index 000000000..8c8bbfce6
--- /dev/null
+++ b/tdeioslave/media/mediamanager/halbackend.h
@@ -0,0 +1,232 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004-2005 Jérôme Lodewyck <jerome dot lodewyck at normalesup dot org>
+
+ 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.
+*/
+
+/**
+* This is a media:/ backend for the freedesktop Hardware Abstraction Layer
+* Usage : create an instance of HALBackend, then call InitHal(). A false
+* result from the later function means that something went wrong and that
+* the backend shall not be used.
+*
+* @author Jérôme Lodewyck <jerome dot lodewyck at normalesup dot org>
+* @short media:/ backend for the HAL
+*/
+
+#ifndef _HALBACKEND_H_
+#define _HALBACKEND_H_
+
+#include "backendbase.h"
+
+#include <tqobject.h>
+#include <tqstringlist.h>
+#include <tqstring.h>
+
+#include <config.h>
+
+/* We acknowledge the the dbus API is unstable */
+#define DBUS_API_SUBJECT_TO_CHANGE
+/* DBus-Qt bindings */
+#include <dbus/connection.h>
+/* HAL libraries */
+#include <libhal.h>
+#include <libhal-storage.h>
+
+namespace TDEIO {
+ class Job;
+}
+
+class HALBackend : public TQObject, public BackendBase
+{
+Q_OBJECT
+
+public:
+ /**
+ * Constructor
+ */
+ HALBackend(MediaList &list, TQObject* parent);
+
+ /**
+ * Destructor
+ */
+ ~HALBackend();
+
+ /**
+ * Perform HAL initialization.
+ *
+ * @return true if succeded. If not, rely on some other backend
+ */
+ bool InitHal();
+
+ /**
+ * List all devices and append them to the media device list (called only once, at startup).
+ *
+ * @return true if succeded, false otherwise
+ */
+ bool ListDevices();
+
+ TQStringList mountoptions(const TQString &id);
+
+ bool setMountoptions(const TQString &id, const TQStringList &options);
+
+ TQString mount(const TQString &id);
+ TQString mount(const Medium *medium);
+ TQString unmount(const TQString &id);
+ TQString decrypt(const TQString &id, const TQString &password);
+ TQString undecrypt(const TQString &id);
+
+private:
+ /**
+ * Append a device in the media list. This function will check if the device
+ * is worth listing.
+ *
+ * @param udi Universal Device Id
+ * @param allowNotification Indicates if this event will be notified to the user
+ */
+ void AddDevice(const char* udi, bool allowNotification=true);
+
+ /**
+ * Remove a device from the device list
+ *
+ * @param udi Universal Device Id
+ */
+ void RemoveDevice(const char* udi);
+
+ /**
+ * A device has changed, update it
+ *
+ * @param udi Universal Device Id
+ */
+ void ModifyDevice(const char *udi, const char* key);
+
+ /**
+ * HAL informed that a special action has occured
+ * (e.g. device unplugged without unmounting)
+ *
+ * @param udi Universal Device Id
+ */
+ void DeviceCondition(const char *udi, const char *condition);
+
+ /**
+ * Integrate the DBus connection within qt main loop
+ */
+ void MainLoopIntegration(DBusConnection *dbusConnection);
+
+/* Set media properties */
+private:
+ /**
+ * Reset properties for the given medium
+ */
+ void ResetProperties(const char* MediumUdi, bool allowNotification=false);
+
+ /**
+ * Find the medium that is concerned with device udi
+ */
+ const char* findMediumUdiFromUdi(const char* udi);
+
+ void setVolumeProperties(Medium* medium);
+ bool setFloppyProperties(Medium* medium);
+ void setFloppyMountState( Medium* medium );
+ bool setFstabProperties(Medium* medium);
+ void setCameraProperties(Medium* medium);
+ TQString generateName(const TQString &devNode);
+ static TQString isInFstab(const Medium *medium);
+ static TQString listUsingProcesses(const Medium *medium);
+ static TQString killUsingProcesses(const Medium *medium);
+
+private slots:
+ void slotResult(TDEIO::Job *job);
+
+/* Hal call-backs -- from gvm*/
+public:
+ /** Invoked when a device is added to the Global Device List.
+ *
+ * @param ctx LibHal context
+ * @param udi Universal Device Id
+ */
+ static void hal_device_added(LibHalContext *ctx, const char *udi);
+
+ /** Invoked when a device is removed from the Global Device List.
+ *
+ * @param ctx LibHal context
+ * @param udi Universal Device Id
+ */
+ static void hal_device_removed(LibHalContext *ctx, const char *udi);
+
+ /** Invoked when a property of a device in the Global Device List is
+ * changed, and we have we have subscribed to changes for that device.
+ *
+ * @param ctx LibHal context
+ * @param udi Univerisal Device Id
+ * @param key Key of property
+ */
+ static void hal_device_property_modified(LibHalContext *ctx, const char *udi, const char *key,
+ dbus_bool_t is_removed, dbus_bool_t is_added);
+
+ /** Type for callback when a non-continuos condition occurs on a device
+ *
+ * @param udi Univerisal Device Id
+ * @param condition_name Name of the condition
+ * @param message D-BUS message with variable parameters depending on condition
+ */
+ static void hal_device_condition(LibHalContext *ctx, const char *udi,
+ const char *condition_name,
+ const char* message
+ );
+
+ TQStringList getHALmountoptions(TQString udi);
+/* HAL and DBus structures */
+private:
+ /**
+ * The HAL context connecting the whole application to the HAL
+ */
+ LibHalContext* m_halContext;
+
+ /**
+ * libhal-storage HAL policy, e.g. for icon names
+ */
+ LibHalStoragePolicy* m_halStoragePolicy;
+
+ /**
+ * The DBus-Qt bindings connection for mainloop integration
+ */
+ DBusQt::Connection* m_dBusQtConnection;
+
+ /**
+ * Object for the kded module
+ */
+ TQObject* m_parent;
+
+ DBusConnection *dbus_connection;
+
+ /**
+ * Data structure for fstab mount/unmount jobs
+ */
+ struct mount_job_data {
+ // [in] Medium, which is being mounted/unmounted by the job
+ const Medium* medium;
+ // [in,out] Should be set to true when the job completes
+ bool completed;
+ // [out] TDEIO::Error if an error occured during operation. Otherwise, 0
+ int error;
+ // [out] Error message to be displayed to the user
+ TQString errorMessage;
+ };
+
+ TQMap<TDEIO::Job *, struct mount_job_data*> mount_jobs;
+};
+
+#endif /* _HALBACKEND_H_ */
diff --git a/tdeioslave/media/mediamanager/linuxcdpolling.cpp b/tdeioslave/media/mediamanager/linuxcdpolling.cpp
new file mode 100644
index 000000000..0fcda8d0f
--- /dev/null
+++ b/tdeioslave/media/mediamanager/linuxcdpolling.cpp
@@ -0,0 +1,585 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2003 Gav Wood <gav kde org>
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ 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.
+*/
+
+/* Some code of this file comes from kdeautorun */
+
+#include "linuxcdpolling.h"
+
+#include <tqthread.h>
+#include <tqmutex.h>
+#include <tqfile.h>
+
+#include <kdebug.h>
+
+#include "fstabbackend.h"
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+// Never ever include directly a kernel header!
+// #include <linux/cdrom.h>
+// Instead we redefine the necessary (copied from the header)
+
+/* This struct is used by the CDROMREADTOCHDR ioctl */
+struct cdrom_tochdr
+{
+ unsigned char cdth_trk0; /* start track */
+ unsigned char cdth_trk1; /* end track */
+};
+
+#define CDROMREADTOCHDR 0x5305 /* Read TOC header
+ (struct cdrom_tochdr) */
+#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
+#define CDROM_DISC_STATUS 0x5327 /* Get disc type, etc. */
+
+/* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */
+#define CDS_NO_INFO 0 /* if not implemented */
+#define CDS_NO_DISC 1
+#define CDS_TRAY_OPEN 2
+#define CDS_DRIVE_NOT_READY 3
+#define CDS_DISC_OK 4
+
+/* return values for the CDROM_DISC_STATUS ioctl */
+/* can also return CDS_NO_[INFO|DISC], from above */
+#define CDS_AUDIO 100
+#define CDS_DATA_1 101
+#define CDS_DATA_2 102
+#define CDS_XA_2_1 103
+#define CDS_XA_2_2 104
+#define CDS_MIXED 105
+
+#define CDSL_CURRENT ((int) (~0U>>1))
+
+// -------
+
+
+
+DiscType::DiscType(Type type)
+ : m_type(type)
+{
+}
+
+bool DiscType::isKnownDisc() const
+{
+ return m_type != None
+ && m_type != Unknown
+ && m_type != UnknownType
+ && m_type != Broken;
+}
+
+bool DiscType::isDisc() const
+{
+ return m_type != None
+ && m_type != Unknown
+ && m_type != Broken;
+}
+
+bool DiscType::isNotDisc() const
+{
+ return m_type == None;
+}
+
+bool DiscType::isData() const
+{
+ return m_type == Data;
+}
+
+DiscType::operator int() const
+{
+ return (int)m_type;
+}
+
+
+class PollingThread : public TQThread
+{
+public:
+ PollingThread(const TQCString &devNode) : m_dev(devNode)
+ {
+ kdDebug(1219) << "PollingThread::PollingThread("
+ << devNode << ")" << endl;
+ m_stop = false;
+ m_currentType = DiscType::None;
+ m_lastPollType = DiscType::None;
+ }
+
+
+ void stop()
+ {
+ TQMutexLocker locker(&m_mutex);
+ m_stop = true;
+ }
+
+ bool hasChanged()
+ {
+ TQMutexLocker locker(&m_mutex);
+
+ return m_currentType!=m_lastPollType;
+ }
+
+ DiscType type()
+ {
+ TQMutexLocker locker(&m_mutex);
+ m_currentType = m_lastPollType;
+ return m_currentType;
+ }
+
+protected:
+ virtual void run()
+ {
+ kdDebug(1219) << "PollingThread(" << m_dev << ") start" << endl;
+ while (!m_stop && m_lastPollType!=DiscType::Broken)
+ {
+ m_mutex.lock();
+ DiscType type = m_lastPollType;
+ m_mutex.unlock();
+
+ type = LinuxCDPolling::identifyDiscType(m_dev, type);
+
+ m_mutex.lock();
+ m_lastPollType = type;
+ m_mutex.unlock();
+
+ msleep(500);
+ }
+ kdDebug(1219) << "PollingThread(" << m_dev << ") stop" << endl;
+ }
+
+private:
+ TQMutex m_mutex;
+ bool m_stop;
+ const TQCString m_dev;
+ DiscType m_currentType;
+ DiscType m_lastPollType;
+};
+
+
+LinuxCDPolling::LinuxCDPolling(MediaList &list)
+ : TQObject(), BackendBase(list)
+{
+ connect(&m_mediaList, TQT_SIGNAL(mediumAdded(const TQString &,
+ const TQString &, bool)),
+ this, TQT_SLOT(slotMediumAdded(const TQString &)) );
+
+ connect(&m_mediaList, TQT_SIGNAL(mediumRemoved(const TQString &,
+ const TQString &, bool)),
+ this, TQT_SLOT(slotMediumRemoved(const TQString &)) );
+
+ connect(&m_mediaList, TQT_SIGNAL(mediumStateChanged(const TQString &,
+ const TQString &, bool, bool)),
+ this, TQT_SLOT(slotMediumStateChanged(const TQString &)) );
+
+ connect(&m_timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotTimeout()));
+}
+
+LinuxCDPolling::~LinuxCDPolling()
+{
+ TQMap<TQString, PollingThread*>::iterator it = m_threads.begin();
+ TQMap<TQString, PollingThread*>::iterator end = m_threads.end();
+
+ for(; it!=end; ++it)
+ {
+ PollingThread *thread = it.data();
+ thread->stop();
+ thread->wait();
+ delete thread;
+ }
+}
+
+void LinuxCDPolling::slotMediumAdded(const TQString &id)
+{
+ kdDebug(1219) << "LinuxCDPolling::slotMediumAdded(" << id << ")" << endl;
+
+ if (m_threads.contains(id)) return;
+
+ const Medium *medium = m_mediaList.findById(id);
+
+ TQString mime = medium->mimeType();
+ kdDebug(1219) << "mime == " << mime << endl;
+
+ if (mime.find("dvd")==-1 && mime.find("cd")==-1) return;
+
+ if (!medium->isMounted())
+ {
+ m_excludeNotification.append( id );
+
+ TQCString dev = TQFile::encodeName( medium->deviceNode() ).data();
+ PollingThread *thread = new PollingThread(dev);
+ m_threads[id] = thread;
+ thread->start();
+ m_timer.start(500);
+ }
+}
+
+void LinuxCDPolling::slotMediumRemoved(const TQString &id)
+{
+ kdDebug(1219) << "LinuxCDPolling::slotMediumRemoved(" << id << ")" << endl;
+
+ if (!m_threads.contains(id)) return;
+
+ PollingThread *thread = m_threads[id];
+ m_threads.remove(id);
+ thread->stop();
+ thread->wait();
+ delete thread;
+
+ m_excludeNotification.remove(id);
+}
+
+void LinuxCDPolling::slotMediumStateChanged(const TQString &id)
+{
+ kdDebug(1219) << "LinuxCDPolling::slotMediumStateChanged("
+ << id << ")" << endl;
+
+ const Medium *medium = m_mediaList.findById(id);
+
+ TQString mime = medium->mimeType();
+ kdDebug(1219) << "mime == " << mime << endl;
+
+ if (mime.find("dvd")==-1 && mime.find("cd")==-1) return;
+
+ if (!m_threads.contains(id) && !medium->isMounted())
+ {
+ // It is just a mount state change, no need to notify
+ m_excludeNotification.append( id );
+
+ TQCString dev = TQFile::encodeName( medium->deviceNode() ).data();
+ PollingThread *thread = new PollingThread(dev);
+ m_threads[id] = thread;
+ thread->start();
+ m_timer.start(500);
+ }
+ else if (m_threads.contains(id) && medium->isMounted())
+ {
+ PollingThread *thread = m_threads[id];
+ m_threads.remove(id);
+ thread->stop();
+ thread->wait();
+ delete thread;
+ }
+}
+
+void LinuxCDPolling::slotTimeout()
+{
+ //kdDebug(1219) << "LinuxCDPolling::slotTimeout()" << endl;
+
+ if (m_threads.isEmpty())
+ {
+ m_timer.stop();
+ return;
+ }
+
+ TQMap<TQString, PollingThread*>::iterator it = m_threads.begin();
+ TQMap<TQString, PollingThread*>::iterator end = m_threads.end();
+
+ for(; it!=end; ++it)
+ {
+ TQString id = it.key();
+ PollingThread *thread = it.data();
+
+ if (thread->hasChanged())
+ {
+ DiscType type = thread->type();
+ const Medium *medium = m_mediaList.findById(id);
+ applyType(type, medium);
+ }
+ }
+}
+
+static TQString baseType(const Medium *medium)
+{
+ kdDebug(1219) << "baseType(" << medium->id() << ")" << endl;
+
+ TQString devNode = medium->deviceNode();
+ TQString mountPoint = medium->mountPoint();
+ TQString fsType = medium->fsType();
+ bool mounted = medium->isMounted();
+
+ TQString mimeType, iconName, label;
+
+ FstabBackend::guess(devNode, mountPoint, fsType, mounted,
+ mimeType, iconName, label);
+
+ if (devNode.find("dvd")!=-1)
+ {
+ kdDebug(1219) << "=> dvd" << endl;
+ return "dvd";
+ }
+ else
+ {
+ kdDebug(1219) << "=> cd" << endl;
+ return "cd";
+ }
+}
+
+static void restoreEmptyState(MediaList &list, const Medium *medium,
+ bool allowNotification)
+{
+ kdDebug(1219) << "restoreEmptyState(" << medium->id() << ")" << endl;
+
+ TQString id = medium->id();
+ TQString devNode = medium->deviceNode();
+ TQString mountPoint = medium->mountPoint();
+ TQString fsType = medium->fsType();
+ bool mounted = medium->isMounted();
+
+ TQString mimeType, iconName, label;
+
+ FstabBackend::guess(devNode, mountPoint, fsType, mounted,
+ mimeType, iconName, label);
+
+ list.changeMediumState(id, devNode, mountPoint, fsType, mounted,
+ allowNotification, mimeType, iconName, label);
+}
+
+
+void LinuxCDPolling::applyType(DiscType type, const Medium *medium)
+{
+ kdDebug(1219) << "LinuxCDPolling::applyType(" << type << ", "
+ << medium->id() << ")" << endl;
+
+ TQString id = medium->id();
+ TQString dev = medium->deviceNode();
+
+ bool notify = !m_excludeNotification.contains(id);
+ m_excludeNotification.remove(id);
+
+ switch (type)
+ {
+ case DiscType::Data:
+ restoreEmptyState(m_mediaList, medium, notify);
+ break;
+ case DiscType::Audio:
+ case DiscType::Mixed:
+ m_mediaList.changeMediumState(id, "audiocd:/?device="+dev,
+ notify, "media/audiocd");
+ break;
+ case DiscType::VCD:
+ m_mediaList.changeMediumState(id, false, notify, "media/vcd");
+ break;
+ case DiscType::SVCD:
+ m_mediaList.changeMediumState(id, false, notify, "media/svcd");
+ break;
+ case DiscType::DVD:
+ m_mediaList.changeMediumState(id, false, notify, "media/dvdvideo");
+ break;
+ case DiscType::Blank:
+ if (baseType(medium)=="dvd")
+ {
+ m_mediaList.changeMediumState(id, false,
+ notify, "media/blankdvd");
+ }
+ else
+ {
+ m_mediaList.changeMediumState(id, false,
+ notify, "media/blankcd");
+ }
+ break;
+ case DiscType::None:
+ case DiscType::Unknown:
+ case DiscType::UnknownType:
+ restoreEmptyState(m_mediaList, medium, false);
+ break;
+ }
+}
+
+DiscType LinuxCDPolling::identifyDiscType(const TQCString &devNode,
+ const DiscType &current)
+{
+ //kdDebug(1219) << "LinuxCDPolling::identifyDiscType("
+ // << devNode << ")" << endl;
+
+ int fd;
+ struct cdrom_tochdr th;
+
+ // open the device
+ fd = open(devNode, O_RDONLY | O_NONBLOCK);
+ if (fd < 0) return DiscType::Broken;
+
+ switch (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT))
+ {
+ case CDS_DISC_OK:
+ {
+ if (current.isDisc())
+ {
+ close(fd);
+ return current;
+ }
+
+ // see if we can read the disc's table of contents (TOC).
+ if (ioctl(fd, CDROMREADTOCHDR, &th))
+ {
+ close(fd);
+ return DiscType::Blank;
+ }
+
+ // read disc status info
+ int status = ioctl(fd, CDROM_DISC_STATUS, CDSL_CURRENT);
+
+ // release the device
+ close(fd);
+
+ switch (status)
+ {
+ case CDS_AUDIO:
+ return DiscType::Audio;
+ case CDS_DATA_1:
+ case CDS_DATA_2:
+ if (hasDirectory(devNode, "video_ts"))
+ {
+ return DiscType::DVD;
+ }
+ else if (hasDirectory(devNode, "vcd"))
+ {
+ return DiscType::VCD;
+ }
+ else if (hasDirectory(devNode, "svcd"))
+ {
+ return DiscType::SVCD;
+ }
+ else
+ {
+ return DiscType::Data;
+ }
+ case CDS_MIXED:
+ return DiscType::Mixed;
+ default:
+ return DiscType::UnknownType;
+ }
+ }
+ case CDS_NO_INFO:
+ close(fd);
+ return DiscType::Unknown;
+ default:
+ close(fd);
+ return DiscType::None;
+ }
+}
+
+bool LinuxCDPolling::hasDirectory(const TQCString &devNode, const TQCString &dir)
+{
+ bool ret = false; // return value
+ int fd = 0; // file descriptor for drive
+ unsigned short bs; // the discs block size
+ unsigned short ts; // the path table size
+ unsigned int tl; // the path table location (in blocks)
+ unsigned char len_di = 0; // length of the directory name in current path table entry
+ unsigned int parent = 0; // the number of the parent directory's path table entry
+ char dirname[256]; // filename for the current path table entry
+ int pos = 0; // our position into the path table
+ int curr_record = 1; // the path table record we're on
+ TQCString fixed_directory = dir.upper(); // the uppercase version of the "directory" parameter
+
+ // open the drive
+ fd = open(devNode, O_RDONLY | O_NONBLOCK);
+ if (fd == -1) return false;
+
+ // read the block size
+ lseek(fd, 0x8080, SEEK_CUR);
+ if (read(fd, &bs, 2) != 2)
+ {
+ close(fd);
+ return false;
+ }
+ if (Q_BYTE_ORDER != Q_LITTLE_ENDIAN)
+ bs = ((bs << 8) & 0xFF00) | ((bs >> 8) & 0xFF);
+
+ // read in size of path table
+ lseek(fd, 2, SEEK_CUR);
+ if (read(fd, &ts, 2) != 2)
+ {
+ close(fd);
+ return false;
+ }
+ if (Q_BYTE_ORDER != Q_LITTLE_ENDIAN)
+ ts = ((ts << 8) & 0xFF00) | ((ts >> 8) & 0xFF);
+
+ // read in which block path table is in
+ lseek(fd, 6, SEEK_CUR);
+ if (read(fd, &tl, 4) != 4)
+ {
+ close(fd);
+ return false;
+ }
+ if (Q_BYTE_ORDER != Q_LITTLE_ENDIAN)
+ tl = ((tl << 24) & 0xFF000000) | ((tl << 8) & 0xFF0000) |
+ ((tl >> 8) & 0xFF00) | ((tl >> 24) & 0xFF);
+
+ // seek to the path table
+ lseek(fd, bs * tl, SEEK_SET);
+
+ // loop through the path table entries
+ while (pos < ts)
+ {
+ // get the length of the filename of the current entry
+ if (read(fd, &len_di, 1) != 1)
+ {
+ ret = false;
+ break;
+ }
+
+ // get the record number of this entry's parent
+ // i'm pretty sure that the 1st entry is always the top directory
+ lseek(fd, 5, SEEK_CUR);
+ if (read(fd, &parent, 2) != 2)
+ {
+ ret = false;
+ break;
+ }
+ if (Q_BYTE_ORDER != Q_LITTLE_ENDIAN)
+ parent = ((parent << 8) & 0xFF00) | ((parent >> 8) & 0xFF);
+
+ // read the name
+ if (read(fd, dirname, len_di) != len_di)
+ {
+ ret = false;
+ break;
+ }
+ dirname[len_di] = 0;
+ qstrcpy(dirname, TQCString(dirname).upper());
+
+ // if we found a folder that has the root as a parent, and the directory name matches
+ // then return success
+ if ((parent == 1) && (dirname == fixed_directory))
+ {
+ ret = true;
+ break;
+ }
+
+ // all path table entries are padded to be even, so if this is an odd-length table, seek a byte to fix it
+ if (len_di%2 == 1)
+ {
+ lseek(fd, 1, SEEK_CUR);
+ pos++;
+ }
+
+ // update our position
+ pos += 8 + len_di;
+ curr_record++;
+ }
+
+ close(fd);
+ return ret;
+}
+
+
+#include "linuxcdpolling.moc"
diff --git a/tdeioslave/media/mediamanager/linuxcdpolling.h b/tdeioslave/media/mediamanager/linuxcdpolling.h
new file mode 100644
index 000000000..3dec7e3ee
--- /dev/null
+++ b/tdeioslave/media/mediamanager/linuxcdpolling.h
@@ -0,0 +1,86 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 K�vin Ottens <ervin ipsquad net>
+
+ 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 _LINUXCDPOLLING_H_
+#define _LINUXCDPOLLING_H_
+
+#include "backendbase.h"
+
+#include <tqobject.h>
+#include <tqcstring.h>
+#include <tqmap.h>
+#include <tqtimer.h>
+
+class DiscType
+{
+public:
+ enum Type { None, Unknown, Audio, Data, DVD, Mixed,
+ Blank, VCD, SVCD, UnknownType, Broken };
+
+ DiscType(Type type = Unknown);
+
+ bool isKnownDisc() const;
+ bool isDisc() const;
+ bool isNotDisc() const;
+ bool isData() const;
+
+ operator int() const;
+
+private:
+ Type m_type;
+};
+
+class PollingThread;
+
+class LinuxCDPolling : public TQObject, public BackendBase
+{
+Q_OBJECT
+
+public:
+
+ LinuxCDPolling(MediaList &list);
+ virtual ~LinuxCDPolling();
+
+ /**
+ * Find the disc type of the medium inserted in a drive
+ * (considered to be a cdrom or dvdrom)
+ *
+ * @param devNode the path to the device to test
+ * @param current the current known state of the drive
+ * @return the disc type
+ */
+ static DiscType identifyDiscType(const TQCString &devNode,
+ const DiscType &current = DiscType::Unknown);
+
+private slots:
+ void slotMediumAdded(const TQString &id);
+ void slotMediumRemoved(const TQString &id);
+ void slotMediumStateChanged(const TQString &id);
+ void slotTimeout();
+
+private:
+ void applyType(DiscType type, const Medium *medium);
+
+ static bool hasDirectory(const TQCString &devNode, const TQCString &dir);
+
+ TQMap<TQString, PollingThread*> m_threads;
+ TQStringList m_excludeNotification;
+ TQTimer m_timer;
+};
+
+#endif
diff --git a/tdeioslave/media/mediamanager/mediadirnotify.cpp b/tdeioslave/media/mediamanager/mediadirnotify.cpp
new file mode 100644
index 000000000..9e6658153
--- /dev/null
+++ b/tdeioslave/media/mediamanager/mediadirnotify.cpp
@@ -0,0 +1,124 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ 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 "mediadirnotify.h"
+
+#include <kdebug.h>
+
+#include <kdirnotify_stub.h>
+
+#include "medium.h"
+
+MediaDirNotify::MediaDirNotify(const MediaList &list)
+ : m_mediaList(list)
+{
+
+}
+
+KURL::List MediaDirNotify::toMediaURL(const KURL &url)
+{
+ kdDebug(1219) << "MediaDirNotify::toMediaURL(" << url << ")" << endl;
+
+ KURL::List result;
+
+ const TQPtrList<Medium> list = m_mediaList.list();
+
+ TQPtrList<Medium>::const_iterator it = list.begin();
+ TQPtrList<Medium>::const_iterator end = list.end();
+
+ for (; it!=end; ++it)
+ {
+ const Medium *m = *it;
+ KURL base = m->prettyBaseURL();
+
+ if ( base.isParentOf(url) )
+ {
+ TQString path = KURL::relativePath(base.path(),
+ url.path());
+
+ KURL new_url("media:/"+m->name()+"/"+path );
+ new_url.cleanPath();
+
+ result.append(new_url);
+ }
+ }
+
+ kdDebug(1219) << result << endl;
+ return result;
+}
+
+KURL::List MediaDirNotify::toMediaURLList(const KURL::List &list)
+{
+ KURL::List new_list;
+
+ KURL::List::const_iterator it = list.begin();
+ KURL::List::const_iterator end = list.end();
+
+ for (; it!=end; ++it)
+ {
+ KURL::List urls = toMediaURL(*it);
+
+ if (!urls.isEmpty())
+ {
+ new_list += urls;
+ }
+ }
+
+ return new_list;
+}
+
+ASYNC MediaDirNotify::FilesAdded(const KURL &directory)
+{
+ KURL::List new_urls = toMediaURL(directory);
+
+ if (!new_urls.isEmpty())
+ {
+ KDirNotify_stub notifier("*", "*");
+
+ KURL::List::const_iterator it = new_urls.begin();
+ KURL::List::const_iterator end = new_urls.end();
+
+ for (; it!=end; ++it)
+ {
+ notifier.FilesAdded(*it);
+ }
+ }
+}
+
+ASYNC MediaDirNotify::FilesRemoved(const KURL::List &fileList)
+{
+ KURL::List new_list = toMediaURLList(fileList);
+
+ if (!new_list.isEmpty())
+ {
+ KDirNotify_stub notifier("*", "*");
+ notifier.FilesRemoved( new_list );
+ }
+}
+
+ASYNC MediaDirNotify::FilesChanged(const KURL::List &fileList)
+{
+ KURL::List new_list = toMediaURLList(fileList);
+
+ if (!new_list.isEmpty())
+ {
+ KDirNotify_stub notifier("*", "*");
+ notifier.FilesChanged( new_list );
+ }
+}
+
diff --git a/tdeioslave/media/mediamanager/mediadirnotify.h b/tdeioslave/media/mediamanager/mediadirnotify.h
new file mode 100644
index 000000000..beb1b8849
--- /dev/null
+++ b/tdeioslave/media/mediamanager/mediadirnotify.h
@@ -0,0 +1,47 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 K�vin Ottens <ervin ipsquad net>
+
+ 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 _MEDIADIRNOTIFY_H_
+#define _MEDIADIRNOTIFY_H_
+
+#include <kurl.h>
+#include <kdirnotify.h>
+
+#include "medialist.h"
+
+
+class MediaDirNotify : public KDirNotify
+{
+K_DCOP
+
+public:
+ MediaDirNotify(const MediaList &list);
+
+k_dcop:
+ virtual ASYNC FilesAdded (const KURL &directory);
+ virtual ASYNC FilesRemoved (const KURL::List &fileList);
+ virtual ASYNC FilesChanged (const KURL::List &fileList);
+
+private:
+ KURL::List toMediaURL(const KURL &url);
+ KURL::List toMediaURLList(const KURL::List &list);
+
+ const MediaList &m_mediaList;
+};
+
+#endif
diff --git a/tdeioslave/media/mediamanager/medialist.cpp b/tdeioslave/media/mediamanager/medialist.cpp
new file mode 100644
index 000000000..6ac7dc341
--- /dev/null
+++ b/tdeioslave/media/mediamanager/medialist.cpp
@@ -0,0 +1,303 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ 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 "medialist.h"
+
+#include <kdebug.h>
+
+MediaList::MediaList()
+{
+ kdDebug(1219) << "MediaList::MediaList()" << endl;
+
+ m_media.setAutoDelete(true);
+}
+
+const TQPtrList<Medium> MediaList::list() const
+{
+ kdDebug(1219) << "MediaList::list()" << endl;
+
+ return m_media;
+}
+
+const Medium *MediaList::findById(const TQString &id) const
+{
+ kdDebug(1219) << "MediaList::findById(" << id << ")" << endl;
+
+ if ( !m_idMap.contains(id) ) return 0L;
+
+ return m_idMap[id];
+}
+
+const Medium *MediaList::findByName(const TQString &name) const
+{
+ kdDebug(1219) << "MediaList::findByName(" << name << ")" << endl;
+
+ if ( !m_nameMap.contains(name) ) return 0L;
+
+ return m_nameMap[name];
+}
+
+const Medium *MediaList::findByClearUdi(const TQString &name)
+{
+ kdDebug(1219) << "MediaList::findByClearUdi(" << name << ")" << endl;
+
+ Medium *medium;
+ for (medium = m_media.first(); medium; medium = m_media.next()) {
+ if (medium->clearDeviceUdi() == name) return medium;
+ }
+
+ return 0L;
+}
+
+
+TQString MediaList::addMedium(Medium *medium, bool allowNotification)
+{
+ kdDebug(1219) << "MediaList::addMedium(@" << medium->id() << ")" << endl;
+
+ TQString id = medium->id();
+ if ( m_idMap.contains(id) ) return TQString::null;
+
+ m_media.append( medium );
+ m_idMap[id] = medium;
+
+ TQString name = medium->name();
+ if ( !m_nameMap.contains(name) )
+ {
+ m_nameMap[name] = medium;
+
+ kdDebug(1219) << "MediaList emits mediumAdded(" << id << ", "
+ << name << ")" << endl;
+ emit mediumAdded(id, name, allowNotification);
+
+ return name;
+ }
+
+ TQString base_name = name+"_";
+ int i = 1;
+
+ while ( m_nameMap.contains(base_name+TQString::number(i)) )
+ {
+ i++;
+ }
+
+ name = base_name+TQString::number(i);
+ medium->setName(name);
+ m_nameMap[name] = medium;
+
+ kdDebug(1219) << "MediaList emits mediumAdded(" << id << ", "
+ << name << ")" << endl;
+ emit mediumAdded(id, name, allowNotification);
+ return name;
+}
+
+bool MediaList::removeMedium(const TQString &id, bool allowNotification)
+{
+ kdDebug(1219) << "MediaList::removeMedium(" << id << ")" << endl;
+
+ if ( !m_idMap.contains(id) ) return false;
+
+ Medium *medium = m_idMap[id];
+ TQString name = medium->name();
+
+ m_idMap.remove(id);
+ m_nameMap.remove( medium->name() );
+ m_media.remove( medium );
+
+ emit mediumRemoved(id, name, allowNotification);
+ return true;
+}
+
+bool MediaList::changeMediumState(const Medium &medium, bool allowNotification)
+{
+ kdDebug(1219) << "MediaList::changeMediumState(const Medium &)" << endl;
+
+ if ( !m_idMap.contains(medium.id()) ) return false;
+
+ Medium *m = m_idMap[medium.id()];
+
+ if ( medium.isMountable() )
+ {
+ TQString device_node = medium.deviceNode();
+ TQString clear_device_udi = medium.clearDeviceUdi();
+ TQString mount_point = medium.mountPoint();
+ TQString fs_type = medium.fsType();
+ bool mounted = medium.isMounted();
+
+ m->mountableState( device_node, clear_device_udi, mount_point,
+ fs_type, mounted );
+ }
+ else
+ {
+ m->unmountableState( medium.baseURL() );
+ }
+
+
+ if (!medium.mimeType().isEmpty())
+ {
+ m->setMimeType( medium.mimeType() );
+ }
+
+ if (!medium.iconName().isEmpty())
+ {
+ m->setIconName( medium.iconName() );
+ }
+
+ if (!medium.label().isEmpty())
+ {
+ m->setLabel( medium.label() );
+ }
+
+ m->setHidden(medium.hidden());
+
+ emit mediumStateChanged(m->id(), m->name(), !m->needMounting(), allowNotification);
+ return true;
+}
+
+bool MediaList::changeMediumState(const TQString &id,
+ const TQString &baseURL,
+ bool allowNotification,
+ const TQString &mimeType,
+ const TQString &iconName,
+ const TQString &label)
+{
+ kdDebug(1219) << "MediaList::changeMediumState(" << id << ", "
+ << baseURL << ", " << mimeType << ", " << iconName << ")"
+ << endl;
+
+ if ( !m_idMap.contains(id) ) return false;
+
+ Medium *medium = m_idMap[id];
+
+ medium->unmountableState( baseURL );
+
+ if (!mimeType.isEmpty())
+ {
+ medium->setMimeType( mimeType );
+ }
+
+ if (!iconName.isEmpty())
+ {
+ medium->setIconName( iconName );
+ }
+
+ if (!label.isEmpty())
+ {
+ medium->setLabel( label );
+ }
+
+ emit mediumStateChanged(id, medium->name(),
+ !medium->needMounting(),
+ allowNotification);
+ return true;
+}
+
+bool MediaList::changeMediumState(const TQString &id,
+ const TQString &deviceNode,
+ const TQString &mountPoint,
+ const TQString &fsType, bool mounted,
+ bool allowNotification,
+ const TQString &mimeType,
+ const TQString &iconName,
+ const TQString &label)
+{
+ kdDebug(1219) << "MediaList::changeMediumState(" << id << ", "
+ << deviceNode << ", " << mountPoint << ", " << fsType << ", "
+ << mounted << ", " << mimeType << ", " << iconName << ")"
+ << endl;
+
+ if ( !m_idMap.contains(id) ) return false;
+
+ Medium *medium = m_idMap[id];
+
+ medium->mountableState( deviceNode, mountPoint, fsType, mounted );
+
+ if (!mimeType.isEmpty())
+ {
+ medium->setMimeType( mimeType );
+ }
+
+ if (!iconName.isEmpty())
+ {
+ medium->setIconName( iconName );
+ }
+
+ if (!label.isEmpty())
+ {
+ medium->setLabel( label );
+ }
+
+ emit mediumStateChanged(id, medium->name(),
+ !medium->needMounting(),
+ allowNotification);
+ return true;
+}
+
+bool MediaList::changeMediumState(const TQString &id, bool mounted,
+ bool allowNotification,
+ const TQString &mimeType,
+ const TQString &iconName,
+ const TQString &label)
+{
+ kdDebug(1219) << "MediaList::changeMediumState(" << id << ", "
+ << mounted << ", " << mimeType << ", " << iconName << ")"
+ << endl;
+
+ if ( !m_idMap.contains(id) ) return false;
+
+ Medium *medium = m_idMap[id];
+
+ if ( !medium->mountableState( mounted ) ) return false;
+
+ if (!mimeType.isEmpty())
+ {
+ medium->setMimeType( mimeType );
+ }
+
+ if (!iconName.isEmpty())
+ {
+ medium->setIconName( iconName );
+ }
+
+ if (!label.isEmpty())
+ {
+ medium->setLabel( label );
+ }
+
+ emit mediumStateChanged(id, medium->name(),
+ !medium->needMounting(),
+ allowNotification);
+ return true;
+}
+
+bool MediaList::setUserLabel(const TQString &name, const TQString &label)
+{
+ kdDebug(1219) << "MediaList::setUserLabel(" << name << ", "
+ << label << ")" << endl;
+
+ if ( !m_nameMap.contains(name) ) return false;
+
+ Medium *medium = m_nameMap[name];
+ medium->setUserLabel(label);
+
+ emit mediumStateChanged(medium->id(), name,
+ !medium->needMounting(),
+ false);
+ return true;
+}
+
+#include "medialist.moc"
diff --git a/tdeioslave/media/mediamanager/medialist.h b/tdeioslave/media/mediamanager/medialist.h
new file mode 100644
index 000000000..59ddb6bd2
--- /dev/null
+++ b/tdeioslave/media/mediamanager/medialist.h
@@ -0,0 +1,80 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 K�vin Ottens <ervin ipsquad net>
+
+ 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 _MEDIALIST_H_
+#define _MEDIALIST_H_
+
+#include <tqobject.h>
+
+#include "medium.h"
+
+class MediaList : public QObject
+{
+Q_OBJECT
+
+public:
+ MediaList();
+
+ // FIXME: should be <const Medium> or something similar...
+ const TQPtrList<Medium> list() const;
+ const Medium *findById(const TQString &id) const;
+ const Medium *findByName(const TQString &name) const;
+ const Medium *findByClearUdi(const TQString &name);
+
+public:
+ TQString addMedium(Medium *medium, bool allowNotification = true);
+ bool removeMedium(const TQString &id, bool allowNotification = true);
+
+ bool changeMediumState(const Medium &medium, bool allowNotification);
+ bool changeMediumState(const TQString &id,
+ const TQString &baseURL,
+ bool allowNotification = true,
+ const TQString &mimeType = TQString::null,
+ const TQString &iconName = TQString::null,
+ const TQString &label = TQString::null);
+ bool changeMediumState(const TQString &id,
+ const TQString &deviceNode,
+ const TQString &mountPoint,
+ const TQString &fsType, bool mounted,
+ bool allowNotification = true,
+ const TQString &mimeType = TQString::null,
+ const TQString &iconName = TQString::null,
+ const TQString &label = TQString::null);
+ bool changeMediumState(const TQString &id, bool mounted,
+ bool allowNotification = true,
+ const TQString &mimeType = TQString::null,
+ const TQString &iconName = TQString::null,
+ const TQString &label = TQString::null);
+
+ bool setUserLabel(const TQString &name, const TQString &label);
+
+signals:
+ void mediumAdded(const TQString &id, const TQString &name,
+ bool allowNotification);
+ void mediumRemoved(const TQString &id, const TQString &name,
+ bool allowNotification);
+ void mediumStateChanged(const TQString &id, const TQString &name,
+ bool mounted, bool allowNotification);
+
+private:
+ TQPtrList<Medium> m_media;
+ TQMap<TQString,Medium*> m_nameMap;
+ TQMap<TQString,Medium*> m_idMap;
+};
+
+#endif
diff --git a/tdeioslave/media/mediamanager/mediamanager.cpp b/tdeioslave/media/mediamanager/mediamanager.cpp
new file mode 100644
index 000000000..db2c12a71
--- /dev/null
+++ b/tdeioslave/media/mediamanager/mediamanager.cpp
@@ -0,0 +1,423 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ 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 "mediamanager.h"
+
+#include <config.h>
+#include <tqtimer.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+#include <kdirnotify_stub.h>
+#include <kstandarddirs.h>
+
+#include "mediamanagersettings.h"
+
+#include "fstabbackend.h"
+
+#ifdef COMPILE_TDEHARDWAREBACKEND
+#include "tdehardwarebackend.h"
+#endif // COMPILE_TDEHARDWAREBACKEND
+
+#ifdef COMPILE_HALBACKEND
+#include "halbackend.h"
+#endif //COMPILE_HALBACKEND
+
+#ifdef COMPILE_LINUXCDPOLLING
+#include "linuxcdpolling.h"
+#endif //COMPILE_LINUXCDPOLLING
+
+
+MediaManager::MediaManager(const TQCString &obj)
+ : KDEDModule(obj), m_dirNotify(m_mediaList)
+{
+ connect( &m_mediaList, TQT_SIGNAL(mediumAdded(const TQString&, const TQString&, bool)),
+ TQT_SLOT(slotMediumAdded(const TQString&, const TQString&, bool)) );
+ connect( &m_mediaList, TQT_SIGNAL(mediumRemoved(const TQString&, const TQString&, bool)),
+ TQT_SLOT(slotMediumRemoved(const TQString&, const TQString&, bool)) );
+ connect( &m_mediaList,
+ TQT_SIGNAL(mediumStateChanged(const TQString&, const TQString&, bool, bool)),
+ TQT_SLOT(slotMediumChanged(const TQString&, const TQString&, bool, bool)) );
+
+ TQTimer::singleShot( 10, this, TQT_SLOT( loadBackends() ) );
+}
+
+MediaManager::~MediaManager()
+{
+ while ( !m_backends.isEmpty() )
+ {
+ BackendBase *b = m_backends.first();
+ m_backends.remove( b );
+ delete b;
+ }
+}
+
+void MediaManager::loadBackends()
+{
+ m_mediaList.blockSignals(true);
+
+ while ( !m_backends.isEmpty() )
+ {
+ BackendBase *b = m_backends.first();
+ m_backends.remove( b );
+ delete b;
+ }
+
+ mp_removableBackend = 0L;
+ m_halbackend = 0L;
+ m_tdebackend = 0L;
+ m_fstabbackend = 0L;
+
+#ifdef COMPILE_HALBACKEND
+ if ( MediaManagerSettings::self()->halBackendEnabled() )
+ {
+ m_mediaList.blockSignals(false);
+ m_halbackend = new HALBackend(m_mediaList, this);
+ if (m_halbackend->InitHal())
+ {
+ m_backends.append( m_halbackend );
+ m_fstabbackend = new FstabBackend(m_mediaList, true);
+ m_backends.append( m_fstabbackend );
+ // No need to load something else...
+ m_mediaList.blockSignals(false);
+ return;
+ }
+ else
+ {
+ delete m_halbackend;
+ m_halbackend = 0;
+ m_mediaList.blockSignals(true);
+ }
+ }
+#endif // COMPILE_HALBACKEND
+
+#ifdef COMPILE_TDEHARDWAREBACKEND
+ if ( MediaManagerSettings::self()->tdeHardwareBackendEnabled() )
+ {
+ m_mediaList.blockSignals(false);
+ m_tdebackend = new TDEBackend(m_mediaList, this);
+ m_backends.append( m_tdebackend );
+ m_fstabbackend = new FstabBackend(m_mediaList, true);
+ m_backends.append( m_fstabbackend );
+ // No need to load something else...
+ m_mediaList.blockSignals(false);
+ return;
+ }
+#endif // COMPILE_TDEHARDWAREBACKEND
+
+ mp_removableBackend = new RemovableBackend(m_mediaList);
+ m_backends.append( mp_removableBackend );
+
+#ifdef COMPILE_LINUXCDPOLLING
+ if ( MediaManagerSettings::self()->cdPollingEnabled() )
+ {
+ m_backends.append( new LinuxCDPolling(m_mediaList) );
+ }
+#endif //COMPILE_LINUXCDPOLLING
+
+ m_fstabbackend = new FstabBackend(m_mediaList);
+ m_backends.append( m_fstabbackend );
+ m_mediaList.blockSignals(false);
+}
+
+
+TQStringList MediaManager::fullList()
+{
+ TQPtrList<Medium> list = m_mediaList.list();
+
+ TQStringList result;
+
+ TQPtrList<Medium>::const_iterator it = list.begin();
+ TQPtrList<Medium>::const_iterator end = list.end();
+ for (; it!=end; ++it)
+ {
+ result+= (*it)->properties();
+ result+= Medium::SEPARATOR;
+ }
+
+ return result;
+}
+
+TQStringList MediaManager::properties(const TQString &name)
+{
+ const Medium *m = m_mediaList.findByName(name);
+
+ if (!m)
+ {
+ KURL u(name);
+ kdDebug() << "Media::prop " << name << " " << u.isValid() << endl;
+ if (u.isValid())
+ {
+ if (u.protocol() == "system")
+ {
+ TQString path = u.path();
+ if (path.startsWith("/media/"))
+ path = path.mid(strlen("/media/"));
+ m = m_mediaList.findByName(path);
+ kdDebug() << "findByName " << path << m << endl;
+ }
+ else if (u.protocol() == "media")
+ {
+ m = m_mediaList.findByName(u.filename());
+ kdDebug() << "findByName " << u.filename() << m << endl;
+ }
+ else if (u.protocol() == "file")
+ {
+ // look for the mount point
+ TQPtrList<Medium> list = m_mediaList.list();
+ TQPtrList<Medium>::const_iterator it = list.begin();
+ TQPtrList<Medium>::const_iterator end = list.end();
+ TQString path;
+
+ for (; it!=end; ++it)
+ {
+ path = KStandardDirs::realFilePath(u.path());
+ kdDebug() << "comparing " << (*it)->mountPoint() << " " << path << " " << (*it)->deviceNode() << endl;
+ if ((*it)->mountPoint() == path || (*it)->deviceNode() == path) {
+ m = *it;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (m) {
+ return m->properties();
+ }
+ else {
+ return TQStringList();
+ }
+}
+
+TQStringList MediaManager::mountoptions(const TQString &name)
+{
+#ifdef COMPILE_HALBACKEND
+ if (!m_halbackend)
+ return TQStringList();
+ return m_halbackend->mountoptions(name);
+#else // COMPILE_HALBACKEND
+ #ifdef COMPILE_TDEHARDWAREBACKEND
+ if (!m_tdebackend)
+ return TQStringList();
+ return m_tdebackend->mountoptions(name);
+ #else // COMPILE_TDEHARDWAREBACKEND
+ return TQStringList();
+ #endif // COMPILE_TDEHARDWAREBACKEND
+#endif // COMPILE_HALBACKEND
+}
+
+bool MediaManager::setMountoptions(const TQString &name, const TQStringList &options)
+{
+#ifdef COMPILE_HALBACKEND
+ if (!m_halbackend)
+ return false;
+ return m_halbackend->setMountoptions(name, options);
+#else // COMPILE_HALBACKEND
+ #ifdef COMPILE_TDEHARDWAREBACKEND
+ if (!m_tdebackend)
+ return false;
+ return m_tdebackend->setMountoptions(name, options);
+ #else // COMPILE_TDEHARDWAREBACKEND
+ return false;
+ #endif // COMPILE_TDEHARDWAREBACKEND
+#endif // COMPILE_HALBACKEND
+}
+
+TQString MediaManager::mount(const TQString &name)
+{
+#ifdef COMPILE_HALBACKEND
+ if (!m_halbackend)
+ return i18n("Feature only available with HAL");
+ return m_halbackend->mount(name);
+#else // COMPILE_HALBACKEND
+ #ifdef COMPILE_TDEHARDWAREBACKEND
+ if (!m_tdebackend)
+ return i18n("Feature only available with the TDE hardware backend");
+ return m_tdebackend->mount(name);
+ #else // COMPILE_TDEHARDWAREBACKEND
+ if ( !m_fstabbackend ) // lying :)
+ return i18n("Feature only available with HAL or TDE hardware backend");
+ return m_fstabbackend->mount( name );
+ #endif // COMPILE_TDEHARDWAREBACKEND
+#endif // COMPILE_HALBACKEND
+}
+
+TQString MediaManager::unmount(const TQString &name)
+{
+#ifdef COMPILE_HALBACKEND
+ if (!m_halbackend)
+ return i18n("Feature only available with HAL");
+ return m_halbackend->unmount(name);
+#else // COMPILE_HALBACKEND
+ #ifdef COMPILE_TDEHARDWAREBACKEND
+ if (!m_tdebackend)
+ return i18n("Feature only available with HAL or TDE hardware backend");
+ return m_tdebackend->unmount(name);
+ #else // COMPILE_TDEHARDWAREBACKEND
+ if ( !m_fstabbackend ) // lying :)
+ return i18n("Feature only available with HAL or TDE hardware backend");
+ return m_fstabbackend->unmount( name );
+ #endif // COMPILE_TDEHARDWAREBACKEND
+#endif // COMPILE_HALBACKEND
+}
+
+TQString MediaManager::decrypt(const TQString &name, const TQString &password)
+{
+#ifdef COMPILE_HALBACKEND
+ if (!m_halbackend)
+ return i18n("Feature only available with HAL");
+ return m_halbackend->decrypt(name, password);
+#else // COMPILE_HALBACKEND
+// #ifdef COMPILE_TDEHARDWAREBACKEND
+// if (!m_tdebackend)
+// return i18n("Feature only available with HAL or TDE hardware backend");
+// return m_tdebackend->decrypt(name, password);
+// #else // COMPILE_TDEHARDWAREBACKEND
+ return i18n("Feature only available with HAL");
+// #endif // COMPILE_TDEHARDWAREBACKEND
+#endif // COMPILE_HALBACKEND
+}
+
+TQString MediaManager::undecrypt(const TQString &name)
+{
+#ifdef COMPILE_HALBACKEND
+ if (!m_halbackend)
+ return i18n("Feature only available with HAL");
+ return m_halbackend->undecrypt(name);
+#else // COMPILE_HALBACKEND
+// #ifdef COMPILE_TDEHARDWAREBACKEND
+// if (!m_tdebackend)
+// return i18n("Feature only available with HAL or TDE hardware backend");
+// return m_tdebackend->undecrypt(name);
+// #else // COMPILE_TDEHARDWAREBACKEND
+ return i18n("Feature only available with HAL");
+// #endif // COMPILE_TDEHARDWAREBACKEND
+#endif // COMPILE_HALBACKEND
+}
+
+TQString MediaManager::nameForLabel(const TQString &label)
+{
+ const TQPtrList<Medium> media = m_mediaList.list();
+
+ TQPtrList<Medium>::const_iterator it = media.begin();
+ TQPtrList<Medium>::const_iterator end = media.end();
+ for (; it!=end; ++it)
+ {
+ const Medium *m = *it;
+
+ if (m->prettyLabel()==label)
+ {
+ return m->name();
+ }
+ }
+
+ return TQString::null;
+}
+
+ASYNC MediaManager::setUserLabel(const TQString &name, const TQString &label)
+{
+ m_mediaList.setUserLabel(name, label);
+}
+
+ASYNC MediaManager::reloadBackends()
+{
+ MediaManagerSettings::self()->readConfig();
+ loadBackends();
+}
+
+bool MediaManager::removablePlug(const TQString &devNode, const TQString &label)
+{
+ if (mp_removableBackend)
+ {
+ return mp_removableBackend->plug(devNode, label);
+ }
+ return false;
+}
+
+bool MediaManager::removableUnplug(const TQString &devNode)
+{
+ if (mp_removableBackend)
+ {
+ return mp_removableBackend->unplug(devNode);
+ }
+ return false;
+}
+
+bool MediaManager::removableCamera(const TQString &devNode)
+{
+ if (mp_removableBackend)
+ {
+ return mp_removableBackend->camera(devNode);
+ }
+ return false;
+}
+
+
+void MediaManager::slotMediumAdded(const TQString &/*id*/, const TQString &name,
+ bool allowNotification)
+{
+ kdDebug(1219) << "MediaManager::slotMediumAdded: " << name << endl;
+
+ KDirNotify_stub notifier("*", "*");
+ notifier.FilesAdded( KURL("media:/") );
+
+ emit mediumAdded(name, allowNotification);
+ emit mediumAdded(name);
+}
+
+void MediaManager::slotMediumRemoved(const TQString &/*id*/, const TQString &name,
+ bool allowNotification)
+{
+ kdDebug(1219) << "MediaManager::slotMediumRemoved: " << name << endl;
+
+ KDirNotify_stub notifier("*", "*");
+ notifier.FilesRemoved( KURL("media:/"+name) );
+
+ emit mediumRemoved(name, allowNotification);
+ emit mediumRemoved(name);
+}
+
+void MediaManager::slotMediumChanged(const TQString &/*id*/, const TQString &name,
+ bool mounted, bool allowNotification)
+{
+ kdDebug(1219) << "MediaManager::slotMediumChanged: " << name << endl;
+
+ KDirNotify_stub notifier("*", "*");
+ if (!mounted)
+ {
+ notifier.FilesRemoved( KURL("media:/"+name) );
+ }
+ notifier.FilesChanged( KURL("media:/"+name) );
+
+ emit mediumChanged(name, allowNotification);
+ emit mediumChanged(name);
+}
+
+
+extern "C" {
+ KDE_EXPORT KDEDModule *create_mediamanager(const TQCString &obj)
+ {
+ TDEGlobal::locale()->insertCatalogue("kio_media");
+ return new MediaManager(obj);
+ }
+}
+
+#include "mediamanager.moc"
diff --git a/tdeioslave/media/mediamanager/mediamanager.desktop b/tdeioslave/media/mediamanager/mediamanager.desktop
new file mode 100644
index 000000000..48261e428
--- /dev/null
+++ b/tdeioslave/media/mediamanager/mediamanager.desktop
@@ -0,0 +1,141 @@
+[Desktop Entry]
+Type=Service
+Name=KDED Media Manager
+Name[af]=KDED Media Bestuurder
+Name[ar]=مسيير الوسائط KDED
+Name[az]=KDED Mediya İdarəcisi
+Name[be]=Кіраўнік носьбітаў KDED
+Name[bg]=Управление на устройствата KDED
+Name[bn]=কে.ডি.ই.ডি. মিডিয়া ম্যানেজার
+Name[bs]=KDED upravitelj medijima
+Name[ca]=Gestor de suports KDED
+Name[cs]=KDED správce médií
+Name[csb]=Menedżer zôpisownëch mediów dlô KDED
+Name[da]=KDED Mediehåndtering
+Name[de]=Medienverwaltung
+Name[el]=Διαχειριστής μέσων KDED
+Name[eo]=KDatumportila administrilo
+Name[es]=Gestor de dispositivos KDED
+Name[et]=KDED andmekandjate haldur
+Name[eu]=KDED media kudeatzailea
+Name[fa]=مدیر رسانه KDED
+Name[fi]=KDED-tallennusmedianhallinta
+Name[fr]=Gestionnaire de média KDED
+Name[fy]=KDEDED-mediabehearder
+Name[ga]=Bainisteoir Meán KDED
+Name[gl]=Xestor de Meios de KDED
+Name[he]=מנהל המדיה של KDED
+Name[hi]=केडीईडी मीडिया प्रबंधक
+Name[hr]=KDED upravitelj medija
+Name[hu]=KDED médiakezelő
+Name[is]=KDED miðilstjóri
+Name[it]=Gestore dei supporti KDED
+Name[ja]=KDED メディアマネージャ
+Name[ka]=მატარებლების მმართველი KDED
+Name[kk]=KDED ауыстырмалы тасушыларды басқару
+Name[km]=កម្មវិធី​គ្រប់គ្រង​ព័ត៌មាន KDED
+Name[ko]=KDE 창 관리자
+Name[lv]=KDED Datu nesēju menedžeris
+Name[mk]=Менаџер на носачи KDED
+Name[ms]=Pengurus Media KDED
+Name[nb]=KDED mediebehandler
+Name[nds]=KDED-Medienpleeg
+Name[ne]=KDED मिडिया प्रबन्धक
+Name[nl]=KDED-Mediabeheerder
+Name[nn]=KDED Mediehandsamar
+Name[pa]=KDED ਮਾਧਿਅਮ ਮੈਨੇਜਰ
+Name[pl]=Menedżer nośników danych dla KDED
+Name[pt]=Gestor de Dispositivos KDED
+Name[pt_BR]=Gerenciador de Mídia
+Name[ro]=Manager multimedia KDED
+Name[ru]=Управление подключаемыми устройствами
+Name[rw]=Mugenga Igihuza KDED
+Name[se]=KDED-mediagieđahalli
+Name[sk]=KDED správca médií
+Name[sl]=Upravitelj medijev KDED
+Name[sr]=Менаџер медијума, KDED
+Name[sr@Latn]=Menadžer medijuma, KDED
+Name[sv]=KDED-mediahanterare
+Name[ta]=KDED மீடியா மேலாளர்
+Name[te]=కెడిఈడి మాధ్యమ అభికర్త
+Name[th]=เครื่องมือจัดการสื่อบันทึก KDED
+Name[tr]=KDED Ortam Yöneticisi
+Name[tt]=KDED Media İdäräçe
+Name[uk]=Менеджер носіїв інформації для KDED
+Name[uz]=KDED saqlash uskunalarni boshqaruvchi
+Name[uz@cyrillic]=KDED сақлаш ускуналарни бошқарувчи
+Name[vi]=Trình quản lí Ổ lưu trữ KDED
+Name[wa]=Manaedjeu di fitchîs KDED
+Name[zh_CN]=KDED 介质管理器
+Name[zh_TW]=KDED 媒體管理程式
+Comment=Keep track of media activities and allow to (un)mount (media:/)
+Comment[af]=Hou tred van media aktiwiteite en laat die (ont)koppel van 'media:/' toe
+Comment[ar]=يتتبع نشاطات الوسائط و يسمح بتكيبها/إزالة تركيبها (media:/)
+Comment[be]=Вядзе інфармацыю аб медыяносьбітах і дазваляе прымацоўваць/адмацоўваць іх (media:/)
+Comment[bg]=Наблюдение на устройствата и разрешаване на монтиране/демонтиране на (media:/)
+Comment[bn]=কোথায় কী মিডিয়া ব্যবহার করা হচ্ছে খেয়াল রাখুন এবং (আন)মাউন্ট করুন (media:/)
+Comment[bs]=Prati aktivnosti montiranja uređaja za smještaj podataka (media:/)
+Comment[ca]=Fa el seguiment de les activitats dels suports i permet muntar i desmuntar (media:/)
+Comment[cs]=Udržuje přehled o připojených zařízeních
+Comment[csb]=Dozérô zdarzeniów sparłączonëch z mediama pòdôwków ë zezwôlô je (òd)mòntowac (media:/)
+Comment[da]=Hold styr på medieaktiviteter og tillad at (af)montere (media:/)
+Comment[de]=Überwacht Medien-Aktivität und ermöglicht das Einbinden/Lösen von Einbindungen (media:/)
+Comment[el]=Έλεγχος ενεργειών των μέσων και δυνατότητα (από)προσάρτησης (media:/)
+Comment[eo]=Sekvu spurojn de datumportilaj aktivoj kaj permesu (de/sur)meti (media:/)
+Comment[es]=Monitoriza las actividades de los recursos y permite (des)montarlos (media:/)
+Comment[et]=Hoiab silma peal andmekandjate aktiivsusel ja võimaldab neid ühendada/lahutada (media:/)
+Comment[eu]=Montatzeak begiztatzen ditu (media:/) eta desmontatzen uzten du
+Comment[fa]=حفظ رد فعالیتهای رسانه و اجازۀ سوار(پیاده) کردن (media:/)
+Comment[fi]=Pidä kirjaa tallennustapahtumista ja salli tallennusvälineen liittäminen/irrotus (devices:/)
+Comment[fr]=Gardez une trace des montages et permettre le (dé)montage (media:/)
+Comment[fy]=Hâld de media-aktiviteiten by en stien ta om media oan- en ôf te keppelje (media:/)
+Comment[gl]=Seguemento das actividades dos meios e permite-lle (des)montar (media:/)
+Comment[he]=מנטר אחר פעילויות מדיה, ומאפשר לחבר או לנתק התקנים (media:/)
+Comment[hi]=मीडिया क्रियाओं की जानकारी रखे तथा (अन)माउन्ट करने दे (मीडिया:/)
+Comment[hr]=Praćenje aktivnosti medija i omogućavanje pristupanja i napuštanja
+Comment[hu]=Az adathordozók követése, csatlakoztatása és leválasztása (media:/)
+Comment[is]=Fylgjast með breytingum á tækjum og bjóða upp á (af)tengingu (media:/)
+Comment[it]=Tiene traccia delle attività dei supporti e permette di montarli o smontarli (device:/)
+Comment[ja]=メディアの活動を追跡し、(media:/) をマウントしたりアンマウントします
+Comment[ka]=თვალყურს ადევნებს მედიის აქტიურობას და საშუალებას აძლევს (დე)მონტირების გაკეთებას (media:/)
+Comment[kk]=Тасушылардың белсендігін байқап тіркеуге не тіркеуден шығаруға мүмкіндік береді: (un)mount (media:/)
+Comment[km]=តាមដាន​សកម្មភាព​ព័ត៌មាន និង​អនុញ្ញាត​ឲ្យ​រៀបចំ (មិន​រៀបចំ) (media:/)
+Comment[lt]=Stebi laikmenose vykdomus veiksmus ir leidžia (iš)montuoti (media:/)
+Comment[lv]=Seko datu nesēju aktivitātēm un ļauj montēt/nomontēt tos (media:/)
+Comment[mk]=Води сметка за активностите на носачите и дозволува (од)монтирање (media:/)
+Comment[ms]=Ikuti perkembangan aktiviti media dan benarkan untuk (nyah)lekap (media:/)
+Comment[mt]=Żomm kont ta' attivitajiet ta' mmuntar u ippermetti (un)mount (media:/)
+Comment[nb]=Holder styr på monteringsaktiviteter og lar deg (av)montere (media:/)
+Comment[nds]=Blifft bi all Medienaktiviteten op'n Stand un verlöövt dat In- un Afhangen (media:/)
+Comment[ne]=मिडिया क्रियाकलापको मार्ग राख्नुहोस् र (अन)माउन्ट (media:/) गर्न अनुमति दिनुहोस्
+Comment[nl]=Houdt de media-activiteiten bij en staat u toe om media aan- en af te koppelen (media:/)
+Comment[nn]=Held styr på medieaktivitetar og lèt deg montera og avmontera (media:/)
+Comment[pa]=ਮਾਊਟ ਕਾਰਵਾਈਆਂ ਦੀ ਜਾਣਕਾਰੀ ਰੱਖੋ ਅਤੇ ਅਨ-ਮਾਊਟ ਕਰਨ ਦਿਓ (ਜੰਤਰ:/)
+Comment[pl]=Śledzi zdarzenia związane z nośnikami danych i pozwala je (od)montować (media:/)
+Comment[pt]=Manter o registo das actividades de dispositivos e permitir a (des)montagem (media:/)
+Comment[pt_BR]=Monitora as atividades de mídias e permite a (des)montagem (media:/)
+Comment[ro]=Urmărește activitățile multimedia și permite (de)montarea media:/
+Comment[ru]=Автоматическое подключение устройств (media:/)
+Comment[rw]=Kugumana inzira y'ibikorwa by'ibitangazamakuru no kwemerera gushyiramo(gukuramo) (ibitangazamakuru:/)
+Comment[se]=Gozit mii dáhpáhuvvá median ja diktá du gálgat ja čadnat daid (media:/)
+Comment[sk]=Sledovanie pripojenia/odpojenia medií (media:/)
+Comment[sl]=Nadzoruj dejanja medija in dovilo priklop/odklop (media:/)
+Comment[sr]=Прати активност медијума и омогућава (де)монтирање (media:/)
+Comment[sr@Latn]=Prati aktivnost medijuma i omogućava (de)montiranje (media:/)
+Comment[sv]=Håll reda på mediaaktiviteter och tillåt (av)montering (media:/)
+Comment[ta]=இடைக்காலத்திற்குரிய நடவடிக்கைகளின் வைத்திரு. (சாதனம்:/)த்தை ஏற்ற(இறக்க)கவும் அனுமதி
+Comment[th]=จะคอยติดตามกิจกรรมของสื่อบันทึก และอนุญาตให้เมานท์หรือยกเลิกการเมานท์ (media:/)
+Comment[tr]=Ortam işlemlerini takip et ve bağlanma işlemlerine izin ver(media:/)
+Comment[tt]=Cıhazlarnıñ totaşuın/ayırıluın sizüçe närsä (media:/)
+Comment[uk]=Спостерігає за змінами серед носіїв інформації та дозволяє (роз)монтування (media:/)
+Comment[vi]=Theo dõi các hoạt động của ổ lưu trữ và cho phép lắp đặt hay gỡ bỏ chúng ở thư mục "media:/"
+Comment[wa]=Wåde li trace des activités media eyet permete di (dis)monter (media:/)
+Comment[zh_CN]=跟踪介质活动并允许挂载或卸载(media:/)
+Comment[zh_TW]=持續追蹤媒體活動並允許(解除)掛載 (media:/)
+ServiceTypes=KDEDModule
+X-TDE-ModuleType=Library
+X-TDE-Library=mediamanager
+X-TDE-FactoryName=mediamanager
+X-TDE-Kded-autoload=true
+X-TDE-Kded-load-on-demand=true
+X-TDE-Kded-phase=1
diff --git a/tdeioslave/media/mediamanager/mediamanager.h b/tdeioslave/media/mediamanager/mediamanager.h
new file mode 100644
index 000000000..256d11bf8
--- /dev/null
+++ b/tdeioslave/media/mediamanager/mediamanager.h
@@ -0,0 +1,94 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 K�vin Ottens <ervin ipsquad net>
+
+ 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 _MEDIAMANAGER_H_
+#define _MEDIAMANAGER_H_
+
+#include <kdedmodule.h>
+#include <tqstring.h>
+#include <tqstringlist.h>
+
+#include "medialist.h"
+#include "backendbase.h"
+#include "removablebackend.h"
+#include "mediadirnotify.h"
+
+class HALBackend;
+class TDEBackend;
+class FstabBackend;
+
+class MediaManager : public KDEDModule
+{
+Q_OBJECT
+K_DCOP
+public:
+ MediaManager(const TQCString &obj);
+ ~MediaManager();
+
+k_dcop:
+ TQStringList fullList();
+ TQStringList properties(const TQString &name);
+ TQStringList mountoptions(const TQString &name);
+ bool setMountoptions(const TQString &name, const TQStringList &options);
+
+ TQString mount(const TQString &uid);
+ TQString unmount(const TQString &uid);
+ TQString decrypt(const TQString &uid, const TQString &password);
+ TQString undecrypt(const TQString &uid);
+
+ TQString nameForLabel(const TQString &label);
+ ASYNC setUserLabel(const TQString &name, const TQString &label);
+
+ ASYNC reloadBackends();
+
+ // Removable media handling (for people not having HAL)
+ bool removablePlug(const TQString &devNode, const TQString &label);
+ bool removableUnplug(const TQString &devNode);
+ bool removableCamera(const TQString &devNode);
+
+k_dcop_signals:
+ void mediumAdded(const TQString &name, bool allowNotification);
+ void mediumRemoved(const TQString &name, bool allowNotification);
+ void mediumChanged(const TQString &name, bool allowNotification);
+
+ // For compatibility purpose, not needed for KDE4
+ void mediumAdded(const TQString &name);
+ void mediumRemoved(const TQString &name);
+ void mediumChanged(const TQString &name);
+
+private slots:
+ void loadBackends();
+
+ void slotMediumAdded(const TQString &id, const TQString &name,
+ bool allowNotification);
+ void slotMediumRemoved(const TQString &id, const TQString &name,
+ bool allowNotification);
+ void slotMediumChanged(const TQString &id, const TQString &name,
+ bool mounted, bool allowNotification);
+
+private:
+ MediaList m_mediaList;
+ TQValueList<BackendBase*> m_backends;
+ RemovableBackend *mp_removableBackend;
+ HALBackend *m_halbackend;
+ TDEBackend *m_tdebackend;
+ MediaDirNotify m_dirNotify;
+ FstabBackend *m_fstabbackend;
+};
+
+#endif
diff --git a/tdeioslave/media/mediamanager/removablebackend.cpp b/tdeioslave/media/mediamanager/removablebackend.cpp
new file mode 100644
index 000000000..6b83ae1ea
--- /dev/null
+++ b/tdeioslave/media/mediamanager/removablebackend.cpp
@@ -0,0 +1,180 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 Kévin Ottens <ervin ipsquad net>
+
+ 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 "removablebackend.h"
+
+#include <klocale.h>
+#include <kdirwatch.h>
+#include <kurl.h>
+#include <kmountpoint.h>
+#include <kstandarddirs.h>
+
+#ifdef _OS_SOLARIS_
+#define MTAB "/etc/mnttab"
+#else
+#define MTAB "/etc/mtab"
+#endif
+
+
+
+RemovableBackend::RemovableBackend(MediaList &list)
+ : TQObject(), BackendBase(list)
+{
+ KDirWatch::self()->addFile(MTAB);
+
+ connect( KDirWatch::self(), TQT_SIGNAL( dirty(const TQString&) ),
+ this, TQT_SLOT( slotDirty(const TQString&) ) );
+ KDirWatch::self()->startScan();
+}
+
+RemovableBackend::~RemovableBackend()
+{
+ TQStringList::iterator it = m_removableIds.begin();
+ TQStringList::iterator end = m_removableIds.end();
+
+ for (; it!=end; ++it)
+ {
+ m_mediaList.removeMedium(*it, false);
+ }
+
+ KDirWatch::self()->removeFile(MTAB);
+}
+
+bool RemovableBackend::plug(const TQString &devNode, const TQString &label)
+{
+ TQString name = generateName(devNode);
+ TQString id = generateId(devNode);
+
+ if (!m_removableIds.contains(id))
+ {
+ Medium *medium = new Medium(id, id, name);
+ medium->mountableState(devNode, TQString::null,
+ TQString::null, false);
+
+ TQStringList words = TQStringList::split(" ", label);
+
+ TQStringList::iterator it = words.begin();
+ TQStringList::iterator end = words.end();
+
+ TQString tmp = (*it).lower();
+ tmp[0] = tmp[0].upper();
+ TQString new_label = tmp;
+
+ ++it;
+ for (; it!=end; ++it)
+ {
+ tmp = (*it).lower();
+ tmp[0] = tmp[0].upper();
+ new_label+= " "+tmp;
+ }
+
+ medium->setLabel(new_label);
+ medium->setMimeType("media/removable_unmounted");
+
+ m_removableIds.append(id);
+ return !m_mediaList.addMedium(medium).isNull();
+ }
+ return false;
+}
+
+bool RemovableBackend::unplug(const TQString &devNode)
+{
+ TQString id = generateId(devNode);
+ if (m_removableIds.contains(id))
+ {
+ m_removableIds.remove(id);
+ return m_mediaList.removeMedium(id);
+ }
+ return false;
+}
+
+bool RemovableBackend::camera(const TQString &devNode)
+{
+ TQString id = generateId(devNode);
+ if (m_removableIds.contains(id))
+ {
+ return m_mediaList.changeMediumState(id,
+ TQString("camera:/"), false, "media/gphoto2camera");
+ }
+ return false;
+}
+
+void RemovableBackend::slotDirty(const TQString &path)
+{
+ if (path==MTAB)
+ {
+ handleMtabChange();
+ }
+}
+
+
+void RemovableBackend::handleMtabChange()
+{
+ TQStringList new_mtabIds;
+ KMountPoint::List mtab = KMountPoint::currentMountPoints();
+
+ KMountPoint::List::iterator it = mtab.begin();
+ KMountPoint::List::iterator end = mtab.end();
+
+ for (; it!=end; ++it)
+ {
+ TQString dev = (*it)->mountedFrom();
+ TQString mp = (*it)->mountPoint();
+ TQString fs = (*it)->mountType();
+
+ TQString id = generateId(dev);
+ new_mtabIds+=id;
+
+ if ( !m_mtabIds.contains(id)
+ && m_removableIds.contains(id) )
+ {
+ m_mediaList.changeMediumState(id, dev, mp, fs, true,
+ false, "media/removable_mounted");
+ }
+ }
+
+ TQStringList::iterator it2 = m_mtabIds.begin();
+ TQStringList::iterator end2 = m_mtabIds.end();
+
+ for (; it2!=end2; ++it2)
+ {
+ if ( !new_mtabIds.contains(*it2)
+ && m_removableIds.contains(*it2) )
+ {
+ m_mediaList.changeMediumState(*it2, false,
+ false, "media/removable_unmounted");
+ }
+ }
+
+ m_mtabIds = new_mtabIds;
+}
+
+TQString RemovableBackend::generateId(const TQString &devNode)
+{
+ TQString dev = KStandardDirs::realFilePath(devNode);
+
+ return "/org/kde/mediamanager/removable/"
+ +dev.replace("/", "");
+}
+
+TQString RemovableBackend::generateName(const TQString &devNode)
+{
+ return KURL(devNode).fileName();
+}
+
+#include "removablebackend.moc"
diff --git a/tdeioslave/media/mediamanager/removablebackend.h b/tdeioslave/media/mediamanager/removablebackend.h
new file mode 100644
index 000000000..fa16a391b
--- /dev/null
+++ b/tdeioslave/media/mediamanager/removablebackend.h
@@ -0,0 +1,52 @@
+/* This file is part of the KDE Project
+ Copyright (c) 2004 K�vin Ottens <ervin ipsquad net>
+
+ 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 _REMOVABLEBACKEND_H_
+#define _REMOVABLEBACKEND_H_
+
+#include "backendbase.h"
+
+#include <tqobject.h>
+#include <tqstringlist.h>
+
+class RemovableBackend : public TQObject, public BackendBase
+{
+Q_OBJECT
+
+public:
+ RemovableBackend(MediaList &list);
+ virtual ~RemovableBackend();
+
+ bool plug(const TQString &devNode, const TQString &label);
+ bool unplug(const TQString &devNode);
+ bool camera(const TQString &devNode);
+
+private slots:
+ void slotDirty(const TQString &path);
+
+private:
+ void handleMtabChange();
+
+ static TQString generateId(const TQString &devNode);
+ static TQString generateName(const TQString &devNode);
+
+ TQStringList m_removableIds;
+ TQStringList m_mtabIds;
+};
+
+#endif
diff --git a/tdeioslave/media/mediamanager/tdehardwarebackend.cpp b/tdeioslave/media/mediamanager/tdehardwarebackend.cpp
new file mode 100644
index 000000000..32ed746cf
--- /dev/null
+++ b/tdeioslave/media/mediamanager/tdehardwarebackend.cpp
@@ -0,0 +1,1376 @@
+/* This file is part of the TDE Project
+ Copyright (c) 2012 Timothy Pearson <[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 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 "tdehardwarebackend.h"
+
+#include <tqfile.h>
+#include <tqfileinfo.h>
+#include <tqeventloop.h>
+#include <tqstylesheet.h>
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <tdeconfig.h>
+#include <tdeio/job.h>
+#include <kprocess.h>
+#include <kmimetype.h>
+#include <kmountpoint.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kprotocolinfo.h>
+
+#include "dialog.h"
+
+#define MOUNT_SUFFIX ( \
+ (medium->isMounted() ? TQString("_mounted") : TQString("_unmounted")) + \
+ (medium->isEncrypted() ? (sdevice->isDiskOfType(TDEDiskDeviceType::UnlockedCrypt) ? "_decrypted" : "_encrypted") : "" ) \
+ )
+#define MOUNT_ICON_SUFFIX ( \
+ (medium->isMounted() ? TQString("_mount") : TQString("_unmount")) + \
+ (medium->isEncrypted() ? (sdevice->isDiskOfType(TDEDiskDeviceType::UnlockedCrypt) ? "_decrypt" : "_encrypt") : "" ) \
+ )
+
+#define CHECK_FOR_AND_EXECUTE_AUTOMOUNT(udi, medium, allowNotification) { \
+ TQMap<TQString,TQString> options = MediaManagerUtils::splitOptions(mountoptions(udi)); \
+ kdDebug(1219) << "automount " << options["automount"] << endl; \
+ if (options["automount"] == "true" && allowNotification ) { \
+ TQString error = mount(medium); \
+ if (!error.isEmpty()) \
+ kdDebug(1219) << "error " << error << endl; \
+ } \
+ }
+
+/* Constructor */
+TDEBackend::TDEBackend(MediaList &list, TQObject* parent)
+ : TQObject()
+ , BackendBase(list)
+ , m_decryptDialog(0)
+ , m_parent(parent)
+{
+ // Initialize the TDE device manager
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+
+ // Connect device monitoring signals/slots
+ connect(hwdevices, TQT_SIGNAL(hardwareAdded(TDEGenericDevice*)), this, TQT_SLOT(AddDeviceHandler(TDEGenericDevice*)));
+ connect(hwdevices, TQT_SIGNAL(hardwareRemoved(TDEGenericDevice*)), this, TQT_SLOT(RemoveDeviceHandler(TDEGenericDevice*)));
+ connect(hwdevices, TQT_SIGNAL(hardwareUpdated(TDEGenericDevice*)), this, TQT_SLOT(ModifyDeviceHandler(TDEGenericDevice*)));
+
+ // List devices at startup
+ ListDevices();
+}
+
+/* Destructor */
+TDEBackend::~TDEBackend()
+{
+ // Remove all media from the media list
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+ TDEGenericHardwareList hwlist = hwdevices->listAllPhysicalDevices();
+ TDEGenericDevice *hwdevice;
+ for ( hwdevice = hwlist.first(); hwdevice; hwdevice = hwlist.next() ) {
+ if (hwdevice->type() == TDEGenericDeviceType::Disk) {
+ TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(hwdevice);
+ RemoveDevice(sdevice);
+ }
+ }
+}
+
+void TDEBackend::AddDeviceHandler(TDEGenericDevice *device) {
+ if (device->type() == TDEGenericDeviceType::Disk) {
+ TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(device);
+ AddDevice(sdevice);
+ }
+}
+
+void TDEBackend::RemoveDeviceHandler(TDEGenericDevice *device) {
+ if (device->type() == TDEGenericDeviceType::Disk) {
+ TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(device);
+ RemoveDevice(sdevice);
+ }
+}
+
+void TDEBackend::ModifyDeviceHandler(TDEGenericDevice *device) {
+ if (device->type() == TDEGenericDeviceType::Disk) {
+ TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(device);
+ ModifyDevice(sdevice);
+ }
+}
+
+// List devices (at startup)
+bool TDEBackend::ListDevices()
+{
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+ TDEGenericHardwareList hwlist = hwdevices->listAllPhysicalDevices();
+ TDEGenericDevice *hwdevice;
+ for ( hwdevice = hwlist.first(); hwdevice; hwdevice = hwlist.next() ) {
+ if (hwdevice->type() == TDEGenericDeviceType::Disk) {
+ TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(hwdevice);
+ AddDevice(sdevice, false);
+ }
+ }
+
+ return true;
+}
+
+// Create a media instance for a new storage device
+void TDEBackend::AddDevice(TDEStorageDevice * sdevice, bool allowNotification)
+{
+ kdDebug(1219) << "TDEBackend::AddDevice for " << sdevice->uniqueID() << endl;
+
+ // If the device is already listed, do not process it
+ // This should not happen, but who knows...
+ /** @todo : refresh properties instead ? */
+ if (m_mediaList.findById(sdevice->uniqueID())) {
+ kdDebug(1219) << "TDEBackend::AddDevice for " << sdevice->uniqueID() << " found existing entry in media list" << endl;
+ return;
+ }
+
+ // Add volume block devices
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::HDD)) {
+ /* We only list volumes that...
+ * - are encrypted with LUKS or
+ * - have a filesystem or
+ * - have an audio track
+ */
+ if (!(sdevice->isDiskOfType(TDEDiskDeviceType::LUKS))
+ && !(sdevice->checkDiskStatus(TDEDiskDeviceStatus::ContainsFilesystem))
+ && !(sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio))
+ && !(sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank))
+ ) {
+ //
+ }
+ else {
+ // Create medium
+ Medium* medium = new Medium(sdevice->uniqueID(), driveUDIFromDeviceUID(sdevice->uniqueID()), "");
+ setVolumeProperties(medium);
+
+ // Do not list the LUKS backend device if it has been unlocked elsewhere
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::LUKS)) {
+ if (sdevice->holdingDevices().count() > 0) {
+ medium->setHidden(true);
+ }
+ else {
+ medium->setHidden(false);
+ }
+ }
+
+ // Insert medium into list
+ m_mediaList.addMedium(medium, allowNotification);
+
+ kdDebug(1219) << "TDEBackend::AddDevice inserted hard medium for " << sdevice->uniqueID() << endl;
+
+ // Automount if enabled
+ CHECK_FOR_AND_EXECUTE_AUTOMOUNT(sdevice->uniqueID(), medium, allowNotification)
+ }
+ }
+
+ // Add CD drives
+ if ((sdevice->isDiskOfType(TDEDiskDeviceType::CDROM))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::CDRW))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDROM))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRAM))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRW))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::BDROM))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::BDRW))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::CDVideo))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDVideo))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::BDVideo))
+ ) {
+
+ // Create medium
+ Medium* medium = new Medium(sdevice->uniqueID(), driveUDIFromDeviceUID(sdevice->uniqueID()), "");
+ setVolumeProperties(medium);
+
+ // Insert medium into list
+ m_mediaList.addMedium(medium, allowNotification);
+
+ kdDebug(1219) << "TDEBackend::AddDevice inserted optical medium for " << sdevice->uniqueID() << endl;
+
+ // Automount if enabled
+ CHECK_FOR_AND_EXECUTE_AUTOMOUNT(sdevice->uniqueID(), medium, allowNotification)
+ }
+
+ // Floppy & zip drives
+ if ((sdevice->isDiskOfType(TDEDiskDeviceType::Floppy)) ||
+ (sdevice->isDiskOfType(TDEDiskDeviceType::Zip)) ||
+ (sdevice->isDiskOfType(TDEDiskDeviceType::Jaz))
+ ) {
+ if ((sdevice->checkDiskStatus(TDEDiskDeviceStatus::Removable)) && (!(sdevice->checkDiskStatus(TDEDiskDeviceStatus::Inserted)))) {
+ allowNotification = false;
+ }
+
+ /* We only list volumes that...
+ * - are encrypted with LUKS or
+ * - have a filesystem or
+ * - are a floppy disk
+ */
+ if (!(sdevice->isDiskOfType(TDEDiskDeviceType::LUKS))
+ && !(sdevice->checkDiskStatus(TDEDiskDeviceStatus::ContainsFilesystem))
+ && !(sdevice->isDiskOfType(TDEDiskDeviceType::Floppy))
+ && !(sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank))
+ ) {
+ //
+ }
+ else {
+ // Create medium
+ Medium* medium = new Medium(sdevice->uniqueID(), driveUDIFromDeviceUID(sdevice->uniqueID()), "");
+
+ setFloppyProperties(medium);
+
+ // Do not list the LUKS backend device if it has been unlocked elsewhere
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::LUKS)) {
+ if (sdevice->holdingDevices().count() > 0) {
+ medium->setHidden(true);
+ }
+ else {
+ medium->setHidden(false);
+ }
+ }
+
+ m_mediaList.addMedium(medium, allowNotification);
+
+ kdDebug(1219) << "TDEBackend::AddDevice inserted floppy medium for " << sdevice->uniqueID() << endl;
+
+ return;
+ }
+ }
+
+ // PTP camera
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::Camera)) {
+ // PTP cameras are handled by the "camera" tdeioslave
+ if (KProtocolInfo::isKnownProtocol( TQString("camera") ) )
+ {
+ // Create medium
+ Medium* medium = new Medium(sdevice->uniqueID(), driveUDIFromDeviceUID(sdevice->uniqueID()), "");
+ setCameraProperties(medium);
+ m_mediaList.addMedium(medium, allowNotification);
+
+ kdDebug(1219) << "TDEBackend::AddDevice inserted camera medium for " << sdevice->uniqueID() << endl;
+
+ return;
+ }
+ }
+}
+
+void TDEBackend::RemoveDevice(TDEStorageDevice * sdevice)
+{
+ kdDebug(1219) << "TDEBackend::RemoveDevice for " << sdevice->uniqueID() << endl;
+
+ if (!m_mediaList.findById(sdevice->uniqueID())) {
+ kdDebug(1219) << "TDEBackend::RemoveDevice for " << sdevice->uniqueID() << " existing entry in media list was not found" << endl;
+ return;
+ }
+
+ m_mediaList.removeMedium(sdevice->uniqueID(), true);
+}
+
+void TDEBackend::ModifyDevice(TDEStorageDevice * sdevice)
+{
+ kdDebug(1219) << "TDEBackend::ModifyDevice for " << sdevice->uniqueID() << endl;
+
+ bool allowNotification = false;
+ ResetProperties(sdevice, allowNotification);
+}
+
+void TDEBackend::ResetProperties(TDEStorageDevice * sdevice, bool allowNotification, bool overrideIgnoreList)
+{
+ kdDebug(1219) << "TDEBackend::ResetProperties for " << sdevice->uniqueID() << " allowNotification: " << allowNotification << " overrideIgnoreList: " << overrideIgnoreList << endl;
+
+ if (!m_mediaList.findById(sdevice->uniqueID())) {
+ // This device is not currently in the device list, so add it and exit
+ kdDebug(1219) << "TDEBackend::ResetProperties for " << sdevice->uniqueID() << " existing entry in media list was not found" << endl;
+ AddDevice(sdevice);
+ return;
+ }
+
+ // If we should ignore device change events for this device, do so
+ if (overrideIgnoreList == false) {
+ if (m_ignoreDeviceChangeEvents.contains(sdevice->uniqueID())) {
+ return;
+ }
+ }
+
+ Medium* m = new Medium(sdevice->uniqueID(), driveUDIFromDeviceUID(sdevice->uniqueID()), "");
+
+ // Keep these conditions in sync with ::AddDevice above, OR ELSE!!!
+ // BEGIN
+
+ if (!(sdevice->isDiskOfType(TDEDiskDeviceType::LUKS))
+ && !(sdevice->checkDiskStatus(TDEDiskDeviceStatus::ContainsFilesystem))
+ && !(sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio))
+ && !(sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank))
+ ) {
+ }
+ else {
+ // Do not list the LUKS backend device if it has been unlocked elsewhere
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::LUKS)) {
+ if (sdevice->holdingDevices().count() > 0) {
+ m->setHidden(true);
+ }
+ else {
+ m->setHidden(false);
+ }
+ }
+ setVolumeProperties(m);
+ }
+
+ if ((sdevice->isDiskOfType(TDEDiskDeviceType::CDROM))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::CDRW))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDROM))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRAM))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRW))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::BDROM))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::BDRW))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::CDVideo))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDVideo))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::BDVideo))
+ ) {
+ setVolumeProperties(m);
+ }
+
+ // Floppy & zip drives
+ if ((sdevice->isDiskOfType(TDEDiskDeviceType::Floppy)) ||
+ (sdevice->isDiskOfType(TDEDiskDeviceType::Zip)) ||
+ (sdevice->isDiskOfType(TDEDiskDeviceType::Jaz))
+ ) {
+
+ if (!(sdevice->isDiskOfType(TDEDiskDeviceType::LUKS))
+ && !(sdevice->checkDiskStatus(TDEDiskDeviceStatus::ContainsFilesystem))
+ && !(sdevice->isDiskOfType(TDEDiskDeviceType::Floppy))
+ && !(sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank))
+ ) {
+ //
+ }
+ else {
+ // Do not list the LUKS backend device if it has been unlocked elsewhere
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::LUKS)) {
+ if (sdevice->holdingDevices().count() > 0) {
+ m->setHidden(true);
+ }
+ else {
+ m->setHidden(false);
+ }
+ }
+
+ setFloppyProperties(m);
+ }
+ }
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::Camera)) {
+ setCameraProperties(m);
+ }
+
+ // END
+
+ if ((sdevice->checkDiskStatus(TDEDiskDeviceStatus::Removable)) && (!(sdevice->checkDiskStatus(TDEDiskDeviceStatus::Inserted)))) {
+ kdDebug(1219) << "TDEBackend::ResetProperties for " << sdevice->uniqueID() << " device was removed from system" << endl;
+ RemoveDevice(sdevice);
+ return;
+ }
+
+ m_mediaList.changeMediumState(*m, allowNotification);
+
+ delete m;
+}
+
+void TDEBackend::setVolumeProperties(Medium* medium)
+{
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+
+ TDEStorageDevice * sdevice = hwdevices->findDiskByUID(medium->id());
+ if (!sdevice) {
+ return;
+ }
+
+ medium->setName(generateName(sdevice->deviceNode()));
+ if ((sdevice->isDiskOfType(TDEDiskDeviceType::LUKS)) || (sdevice->isDiskOfType(TDEDiskDeviceType::UnlockedCrypt))) {
+ medium->setEncrypted(true);
+ }
+ else {
+ medium->setEncrypted(false);
+ }
+
+ // USAGE: mountableState(Device node, Mount point, Filesystem type, Mounted ?)
+ medium->mountableState(sdevice->deviceNode(), sdevice->mountPath(), sdevice->fileSystemName(), !sdevice->mountPath().isNull());
+
+ TQString diskLabel = sdevice->diskLabel();
+ if (diskLabel.isNull()) {
+ diskLabel = i18n("%1 Removable Device").arg(sdevice->deviceFriendlySize());
+ }
+
+ TQString mimeType;
+
+ if ((sdevice->isDiskOfType(TDEDiskDeviceType::CDROM))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::CDRW))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDROM))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRAM))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRW))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::BDROM))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::BDRW))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::CDVideo))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDVideo))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::BDVideo))
+ ) {
+ // This device is a CD drive of some sort
+
+ // Default
+ mimeType = "media/cdrom" + MOUNT_SUFFIX;
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::CDROM)) {
+ mimeType = "media/cdrom" + MOUNT_SUFFIX;
+ if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) {
+ mimeType = "media/blankcd";
+ medium->unmountableState("");
+ diskLabel = i18n("Blank CDROM");
+ }
+ }
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::CDRW)) {
+ mimeType = "media/cdwriter" + MOUNT_SUFFIX;
+ if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) {
+ mimeType = "media/blankcd";
+ medium->unmountableState("");
+ diskLabel = i18n("Blank CDRW");
+ }
+ }
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::DVDROM)) {
+ mimeType = "media/dvd" + MOUNT_SUFFIX;
+ if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) {
+ mimeType = "media/blankdvd";
+ medium->unmountableState("");
+ diskLabel = i18n("Blank DVDROM");
+ }
+ }
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRAM)) {
+ mimeType = "media/dvd" + MOUNT_SUFFIX;
+ if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) {
+ mimeType = "media/blankdvd";
+ medium->unmountableState("");
+ diskLabel = i18n("Blank DVDRAM");
+ }
+ }
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRW)) {
+ mimeType = "media/dvd" + MOUNT_SUFFIX;
+ if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) {
+ mimeType = "media/blankdvd" + MOUNT_SUFFIX;
+ medium->unmountableState("");
+ diskLabel = i18n("Blank DVDRW");
+ }
+ }
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::BDROM)) {
+ mimeType = "media/bluray" + MOUNT_SUFFIX;
+ if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) {
+ mimeType = "media/blankbd" + MOUNT_SUFFIX;
+ medium->unmountableState("");
+ diskLabel = i18n("Blank BDROM");
+ }
+ }
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::BDRW)) {
+ mimeType = "media/bluray" + MOUNT_SUFFIX;
+ if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) {
+ mimeType = "media/blankbd" + MOUNT_SUFFIX;
+ medium->unmountableState("");
+ diskLabel = i18n("Blank BDRW");
+ }
+ }
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio)) {
+ mimeType = "media/audiocd";
+ medium->unmountableState("audiocd:/?device=" + sdevice->deviceNode());
+ diskLabel = i18n("Audio CD");
+ }
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::CDVideo)) {
+ mimeType = "media/vcd";
+ }
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::DVDVideo)) {
+ mimeType = "media/dvdvideo";
+ }
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::BDVideo)) {
+ mimeType = "media/bdvideo";
+ }
+
+ medium->setIconName(TQString::null);
+ }
+ else {
+ // This device is a hard or flash disk of some kind
+
+ // Default
+ mimeType = "media/hdd" + MOUNT_SUFFIX;
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::USB)) {
+ mimeType = "media/removable" + MOUNT_SUFFIX;
+ medium->needMounting();
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::CompactFlash)) {
+ medium->setIconName("compact_flash" + MOUNT_ICON_SUFFIX);
+ }
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::MemoryStick)) {
+ medium->setIconName("memory_stick" + MOUNT_ICON_SUFFIX);
+ }
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::SmartMedia)) {
+ medium->setIconName("smart_media" + MOUNT_ICON_SUFFIX);
+ }
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::SDMMC)) {
+ medium->setIconName("sd_mmc" + MOUNT_ICON_SUFFIX);
+ }
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::MediaDevice)) {
+ medium->setIconName("ipod" + MOUNT_ICON_SUFFIX);
+
+ if (sdevice->vendorModel().upper().contains("IPOD") && KProtocolInfo::isKnownProtocol( TQString("ipod") ) )
+ {
+ medium->unmountableState( "ipod:/" );
+ medium->mountableState(!sdevice->mountPath().isNull());
+ }
+ }
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::Tape)) {
+ medium->setIconName("magnetic_tape" + MOUNT_ICON_SUFFIX);
+ }
+ if (medium->isMounted() && TQFile::exists(medium->mountPoint() + "/dcim"))
+ {
+ mimeType = "media/camera" + MOUNT_SUFFIX;
+ }
+ }
+ }
+
+ if (!medium->needMounting()) {
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::LUKS)) {
+ if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::UsedByDevice)) {
+ // Encrypted base devices must be set to this mimetype or they won't open when the base device node is passed to the tdeioslave
+ mimeType = "media/removable_mounted";
+ }
+ }
+ }
+
+ medium->setLabel(diskLabel);
+ medium->setMimeType(mimeType);
+}
+
+// Handle floppies and zip drives
+bool TDEBackend::setFloppyProperties(Medium* medium)
+{
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+
+ TDEStorageDevice * sdevice = hwdevices->findDiskByUID(medium->id());
+ if (!sdevice) {
+ return false;
+ }
+
+ medium->setName(generateName(sdevice->deviceNode()));
+ medium->setLabel(i18n("Unknown Drive"));
+
+ // Certain disks have a lot in common with hard drives
+ // FIXME
+ // Any more?
+ if ((sdevice->isDiskOfType(TDEDiskDeviceType::Zip)) || (sdevice->isDiskOfType(TDEDiskDeviceType::Jaz))) {
+ medium->setName(generateName(sdevice->deviceNode()));
+ if ((sdevice->isDiskOfType(TDEDiskDeviceType::LUKS)) || (sdevice->isDiskOfType(TDEDiskDeviceType::UnlockedCrypt))) {
+ medium->setEncrypted(true);
+ }
+ else {
+ medium->setEncrypted(false);
+ }
+
+ // USAGE: mountableState(Device node, Mount point, Filesystem type, Mounted ?)
+ medium->mountableState(sdevice->deviceNode(), sdevice->mountPath(), sdevice->fileSystemName(), !sdevice->mountPath().isNull());
+ }
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::Floppy)) {
+ setFloppyMountState(medium);
+
+ // We don't use the routine above as floppy disks are extremely slow (we don't want them accessed at all during media listing)
+ medium->mountableState(sdevice->deviceNode(), sdevice->mountPath(), sdevice->fileSystemName(), !sdevice->mountPath().isNull());
+
+ if (sdevice->mountPath().isNull()) {
+ medium->setMimeType("media/floppy_unmounted");
+ }
+ else {
+ medium->setMimeType("media/floppy_mounted" );
+ }
+ medium->setLabel(i18n("Floppy Drive"));
+ }
+
+ if (sdevice->isDiskOfType(TDEDiskDeviceType::Zip)) {
+ if (sdevice->mountPath().isNull()) {
+ medium->setMimeType("media/zip_unmounted");
+ }
+ else {
+ medium->setMimeType("media/zip_mounted" );
+ }
+
+ // Set label
+ TQString diskLabel = sdevice->diskLabel();
+ if (diskLabel.isNull()) {
+ diskLabel = i18n("%1 Zip Disk").arg(sdevice->deviceFriendlySize());
+ }
+ medium->setLabel(diskLabel);
+ }
+
+ /** @todo Mimetype for JAZ drives ? */
+
+ medium->setIconName(TQString::null);
+
+ return true;
+}
+
+void TDEBackend::setCameraProperties(Medium* medium)
+{
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+
+ TDEStorageDevice * sdevice = hwdevices->findDiskByUID(medium->id());
+ if (!sdevice) {
+ return;
+ }
+
+ TQString cameraName = sdevice->friendlyName();
+ cameraName.replace("/", "_");
+ medium->setName(cameraName);
+
+ TQString device = "camera:/";
+
+ TQStringList devNodeList = TQStringList::split("/", sdevice->deviceNode(), TRUE);
+ TQString devNode0 = devNodeList[devNodeList.count()-2];
+ TQString devNode1 = devNodeList[devNodeList.count()-1];
+
+ if ((devNode0 != "") && (devNode1 != "")) {
+ device.sprintf("camera://@[usb:%s,%s]/", devNode0.ascii(), devNode1.ascii());
+ }
+
+ medium->unmountableState(device);
+ medium->setMimeType("media/gphoto2camera");
+ medium->setIconName(TQString::null);
+
+ if (sdevice->friendlyName() != "") {
+ medium->setLabel(sdevice->friendlyName());
+ }
+ else {
+ medium->setLabel(i18n("Camera"));
+ }
+}
+
+void TDEBackend::setFloppyMountState( Medium *medium )
+{
+ KMountPoint::List mtab = KMountPoint::currentMountPoints();
+ KMountPoint::List::iterator it = mtab.begin();
+ KMountPoint::List::iterator end = mtab.end();
+
+ TQString fstype;
+ TQString mountpoint;
+ for (; it!=end; ++it) {
+ if ((*it)->mountedFrom() == medium->deviceNode() ) {
+ fstype = (*it)->mountType().isNull() ? (*it)->mountType() : "auto";
+ mountpoint = (*it)->mountPoint();
+ medium->mountableState( medium->deviceNode(), mountpoint, fstype, true );
+ return;
+ }
+ }
+}
+
+TQStringList TDEBackend::mountoptions(const TQString &name)
+{
+ const Medium* medium = m_mediaList.findById(name);
+ if (!medium) {
+ return TQStringList(); // we know nothing about that device
+ }
+ if (!isInFstab(medium).isNull()) {
+ return TQStringList(); // device is listed in fstab, therefore is not handled by us
+ }
+
+ if (medium->isEncrypted()) {
+ // if not decrypted yet then there are no mountoptions
+ return TQStringList();
+ }
+
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+
+ TDEStorageDevice * sdevice = hwdevices->findDiskByUID(medium->id());
+ if (!sdevice) {
+ return TQStringList(); // we can't get the information needed in order to process mount options
+ }
+
+ TQStringList result;
+
+ // Allow only those options which are valid for the given device
+ // pmount only allows a subset of options, and those are given in the map below
+ // FIXME
+ TQMap<TQString,bool> valids;
+ valids["ro"] = true;
+ //valids["quiet"] = false;
+ //valids["flush"] = false;
+ //valids["uid"] = false;
+ valids["utf8"] = true;
+ //valids["shortname"] = false;
+ valids["locale"] = true;
+ valids["sync"] = true;
+ valids["noatime"] = true;
+ //valids["data"] = false;
+
+ TQString drive_udi = driveUDIFromDeviceUID(medium->id());
+
+ TDEConfig config("mediamanagerrc");
+
+ bool use_defaults = true;
+ if (config.hasGroup(drive_udi)) {
+ config.setGroup(drive_udi);
+ use_defaults = config.readBoolEntry("use_defaults", false);
+ }
+ if (use_defaults) {
+ config.setGroup("DefaultOptions");
+ }
+ result << TQString("use_defaults=%1").arg(use_defaults ? "true" : "false");
+
+ bool removable = false;
+ if (!drive_udi.isNull()) {
+ removable = ((sdevice->checkDiskStatus(TDEDiskDeviceStatus::Removable)) || (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)));
+ }
+
+ TQString tmp;
+ bool value;
+ if (use_defaults) {
+ value = config.readBoolEntry("automount", false);
+ }
+ else {
+ QString current_group = config.group();
+ config.setGroup(drive_udi);
+ value = config.readBoolEntry("automount", false);
+ config.setGroup(current_group);
+ }
+
+ if ((sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::CDVideo))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDVideo))
+ || (sdevice->isDiskOfType(TDEDiskDeviceType::BDVideo))
+ ) {
+ value = false;
+ }
+
+ result << TQString("automount=%1").arg(value ? "true" : "false");
+
+ if (valids.contains("ro")) {
+ value = config.readBoolEntry("ro", false);
+ tmp = TQString("ro=%1").arg(value ? "true" : "false");
+ if (sdevice->fileSystemName() != "iso9660") {
+ result << tmp;
+ }
+ }
+
+ if (valids.contains("quiet")) {
+ value = config.readBoolEntry("quiet", false);
+ tmp = TQString("quiet=%1").arg(value ? "true" : "false");
+ if (sdevice->fileSystemName() != "iso9660") {
+ result << tmp;
+ }
+ }
+
+ if (valids.contains("flush")) {
+ value = config.readBoolEntry("flush", sdevice->fileSystemName().endsWith("fat"));
+ tmp = TQString("flush=%1").arg(value ? "true" : "false");
+ result << tmp;
+ }
+
+ if (valids.contains("uid")) {
+ value = config.readBoolEntry("uid", true);
+ tmp = TQString("uid=%1").arg(value ? "true" : "false");
+ result << tmp;
+ }
+
+ if (valids.contains("utf8")) {
+ value = config.readBoolEntry("utf8", true);
+ tmp = TQString("utf8=%1").arg(value ? "true" : "false");
+ result << tmp;
+ }
+
+ if (valids.contains("shortname")) {
+ TQString svalue = config.readEntry("shortname", "lower").lower();
+ if (svalue == "winnt") {
+ result << "shortname=winnt";
+ }
+ else if (svalue == "win95") {
+ result << "shortname=win95";
+ }
+ else if (svalue == "mixed") {
+ result << "shortname=mixed";
+ }
+ else {
+ result << "shortname=lower";
+ }
+ }
+
+ // pass our locale to the ntfs-3g driver so it can translate local characters
+ if (valids.contains("locale") && (sdevice->fileSystemName() == "ntfs-3g")) {
+ // have to obtain LC_CTYPE as returned by the `locale` command
+ // check in the same order as `locale` does
+ char *cType;
+ if ( (cType = getenv("LC_ALL")) || (cType = getenv("LC_CTYPE")) || (cType = getenv("LANG")) ) {
+ result << TQString("locale=%1").arg(cType);
+ }
+ }
+
+ if (valids.contains("sync")) {
+ value = config.readBoolEntry("sync", ( valids.contains("flush") && !sdevice->fileSystemName().endsWith("fat") ) && removable);
+ tmp = TQString("sync=%1").arg(value ? "true" : "false");
+ if (sdevice->fileSystemName() != "iso9660") {
+ result << tmp;
+ }
+ }
+
+ if (valids.contains("noatime")) {
+ value = config.readBoolEntry("atime", !sdevice->fileSystemName().endsWith("fat"));
+ tmp = TQString("atime=%1").arg(value ? "true" : "false");
+ if (sdevice->fileSystemName() != "iso9660") {
+ result << tmp;
+ }
+ }
+
+ TQString mount_point;
+ mount_point = config.readEntry("mountpoint", TQString::null);
+
+ if (!mount_point.startsWith("/")) {
+ mount_point = "/media/" + mount_point;
+ }
+ if (mount_point != "") {
+ result << TQString("mountpoint=%1").arg(mount_point);
+ }
+
+ TQString file_system_name;
+ file_system_name = sdevice->fileSystemName();
+ if (file_system_name != "") {
+ result << TQString("filesystem=%1").arg(file_system_name);
+ }
+
+ if (valids.contains("data")) {
+ TQString svalue = config.readEntry("journaling").lower();
+ if (svalue == "ordered") {
+ result << "journaling=ordered";
+ }
+ else if (svalue == "writeback") {
+ result << "journaling=writeback";
+ }
+ else if (svalue == "data") {
+ result << "journaling=data";
+ }
+ else {
+ result << "journaling=ordered";
+ }
+ }
+
+ return result;
+}
+
+bool TDEBackend::setMountoptions(const TQString &name, const TQStringList &options )
+{
+ const Medium* medium = m_mediaList.findById(name);
+ if (!medium) {
+ return false; // we know nothing about that device
+ }
+ if (!isInFstab(medium).isNull()) {
+ return false; // device is listed in fstab, therefore is not handled by us
+ }
+
+ TQString drive_udi = driveUDIFromDeviceUID(medium->id());
+
+ kdDebug(1219) << "setMountoptions " << name << " " << options << endl;
+
+ TDEConfig config("mediamanagerrc");
+ config.setGroup(drive_udi);
+
+ TQMap<TQString,TQString> valids = MediaManagerUtils::splitOptions(options);
+
+ const char *names[] = { "use_defaults", "ro", "quiet", "atime", "uid", "utf8", "flush", "sync", 0 };
+ for (int index = 0; names[index]; ++index) {
+ if (valids.contains(names[index])) {
+ config.writeEntry(names[index], valids[names[index]] == "true");
+ }
+ }
+
+ if (valids.contains("shortname")) {
+ config.writeEntry("shortname", valids["shortname"]);
+ }
+
+ if (valids.contains("journaling")) {
+ config.writeEntry("journaling", valids["journaling"]);
+ }
+
+ if (!mountoptions(name).contains(TQString("mountpoint=%1").arg(valids["mountpoint"]))) {
+ config.writeEntry("mountpoint", valids["mountpoint"]);
+ }
+
+ if (valids.contains("automount")) {
+ config.setGroup(drive_udi);
+ config.writeEntry("automount", valids["automount"]);
+ }
+
+ return true;
+}
+
+void TDEBackend::slotPasswordReady() {
+ m_decryptionPassword = m_decryptDialog->getPassword();
+ m_decryptPasswordValid = true;
+}
+
+void TDEBackend::slotPasswordCancel() {
+ m_decryptionPassword = TQString::null;
+ m_decryptPasswordValid = true;
+}
+
+TQString TDEBackend::mount(const Medium *medium)
+{
+ if (medium->isMounted()) {
+ return TQString(); // that was easy
+ }
+
+ TQString mountPoint = isInFstab(medium);
+ if (!mountPoint.isNull())
+ {
+ struct mount_job_data data;
+ data.completed = false;
+ data.medium = medium;
+
+ TDEIO::Job *job = TDEIO::mount( false, 0, medium->deviceNode(), mountPoint );
+ connect(job, TQT_SIGNAL( result (TDEIO::Job *)), TQT_SLOT( slotResult( TDEIO::Job *)));
+ mount_jobs[job] = &data;
+ // The caller expects the device to be mounted when the function
+ // completes. Thus block until the job completes.
+ while (!data.completed) {
+ kapp->eventLoop()->enterLoop();
+ }
+ // Return the error message (if any) to the caller
+ return (data.error) ? data.errorMessage : TQString::null;
+
+ }
+
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+
+ TDEStorageDevice * sdevice = hwdevices->findDiskByUID(medium->id());
+ if (!sdevice) {
+ return i18n("Internal error");
+ }
+
+ TQString optionString;
+ TQString diskLabel;
+
+ TQMap<TQString,TQString> valids = MediaManagerUtils::splitOptions(mountoptions(medium->id()));
+ if (valids["ro"] == "true") {
+ optionString.append(" -r");
+ }
+
+ if (valids["atime"] != "true") {
+ optionString.append(" -A");
+ }
+
+ if (valids["utf8"] == "true") {
+ optionString.append(" -c utf8");
+ }
+
+ if (valids["sync"] == "true") {
+ optionString.append(" -s");
+ }
+
+ TQString mount_point = valids["mountpoint"];
+ if (mount_point.startsWith("/media/")) {
+ diskLabel = mount_point.mid(7);
+ }
+
+ if (valids.contains("filesystem")) {
+ optionString.append(TQString(" -t %1").arg(valids["filesystem"]));
+ }
+
+ if (valids.contains("locale")) {
+ optionString.append(TQString(" -c %1").arg(valids["locale"]));
+ }
+
+ if (diskLabel == "") {
+ // Try to use a pretty mount point if possible
+ TQStringList pieces = TQStringList::split("/", sdevice->deviceNode(), FALSE);
+ TQString node = pieces[pieces.count()-1];
+ diskLabel = medium->label() + " (" + node + ")";
+ diskLabel.replace("/", "_");
+ }
+
+ TQString qerror = i18n("Cannot mount encrypted drives!");
+
+ if (!medium->isEncrypted()) {
+ // normal volume
+ TQString mountMessages;
+ TQString mountedPath = sdevice->mountDevice(diskLabel, optionString, &mountMessages);
+ if (mountedPath.isNull()) {
+ qerror = i18n("<qt>Unable to mount this device.<p>Potential reasons include:<br>Improper device and/or user privilege level<br>Corrupt data on storage device");
+ if (!mountMessages.isNull()) {
+ qerror.append(i18n("<p>Technical details:<br>").append(mountMessages));
+ }
+ qerror.append("</qt>");
+ }
+ else {
+ qerror = "";
+ }
+ }
+ else {
+ TQString iconName = medium->iconName();
+ if (iconName.isEmpty())
+ {
+ TQString mime = medium->mimeType();
+ iconName = KMimeType::mimeType(mime)->icon(mime, false);
+ }
+
+ bool continue_trying_to_decrypt = true;
+ while (continue_trying_to_decrypt == true) {
+ m_decryptPasswordValid = false;
+
+ m_decryptDialog = new Dialog(sdevice->deviceNode(), iconName);
+ m_decryptDialog->show();
+
+ connect(m_decryptDialog, TQT_SIGNAL (user1Clicked()), this, TQT_SLOT (slotPasswordReady()));
+ connect(m_decryptDialog, TQT_SIGNAL (cancelClicked()), this, TQT_SLOT (slotPasswordCancel()));
+ connect(this, TQT_SIGNAL (signalDecryptionPasswordError(TQString)), m_decryptDialog, TQT_SLOT (slotDialogError(TQString)));
+
+ while (m_decryptPasswordValid == false) {
+ tqApp->processEvents();
+ }
+
+ m_decryptDialog->setEnabled(false);
+ tqApp->processEvents();
+
+ if (m_decryptionPassword.isNull()) {
+ delete m_decryptDialog;
+ return TQString("Decryption aborted");
+ }
+ else {
+ // Just for some added fun, if udev emits a medium change event, which I then forward, with mounted==0, it stops the MediaProtocol::listDir method dead in its tracks,
+ // and therefore the media:/ tdeioslave won't refresh after the encrypted device mount
+ // Therefore, I need to ignore all change events on this device during the mount process and hope nothing bad happens as a result!
+ if (!m_ignoreDeviceChangeEvents.contains(sdevice->uniqueID())) {
+ m_ignoreDeviceChangeEvents.append(sdevice->uniqueID());
+ }
+
+ // mount encrypted volume with password
+ int mountRetcode;
+ TQString mountMessages;
+ TQString mountedPath = sdevice->mountEncryptedDevice(m_decryptionPassword, diskLabel, optionString, &mountMessages, &mountRetcode);
+ if (mountedPath.isNull()) {
+ if (mountRetcode == 0) {
+ // Mounting was successful
+ // Because the TDE hardware backend is event driven it might take a little while for the new unencrypted mapped device to show up
+ // Wait up to 30 seconds for it to appear...
+ for (int i=0;i<300;i++) {
+ mountedPath = sdevice->mountPath();
+ if (!mountedPath.isNull()) {
+ break;
+ }
+ tqApp->processEvents(50);
+ usleep(50000);
+ }
+ }
+ }
+ if (mountedPath.isNull()) {
+ if (mountRetcode == 25600) {
+ // Probable LUKS failure
+ // Retry
+ m_decryptDialog->setEnabled(true);
+ continue_trying_to_decrypt = true;
+ }
+ else {
+ qerror = i18n("<qt>Unable to mount this device.<p>Potential reasons include:<br>Improper device and/or user privilege level<br>Corrupt data on storage device<br>Incorrect encryption password");
+ if (!mountMessages.isNull()) {
+ qerror.append(i18n("<p>Technical details:<br>").append(mountMessages));
+ }
+ qerror.append("</qt>");
+ continue_trying_to_decrypt = false;
+ }
+ }
+ else {
+ qerror = "";
+ continue_trying_to_decrypt = false;
+ }
+
+ delete m_decryptDialog;
+ }
+ }
+ }
+
+ if (!qerror.isEmpty()) {
+ return qerror;
+ }
+
+ ResetProperties(sdevice, false, true);
+
+ if (m_ignoreDeviceChangeEvents.contains(sdevice->uniqueID())) {
+ m_ignoreDeviceChangeEvents.remove(sdevice->uniqueID());
+ }
+
+ return TQString();
+}
+
+TQString TDEBackend::mount(const TQString &_udi)
+{
+ const Medium* medium = m_mediaList.findById(_udi);
+ if (!medium)
+ return i18n("No such medium: %1").arg(_udi);
+
+ return mount(medium);
+}
+
+TQString TDEBackend::unmount(const TQString &_udi)
+{
+ const Medium* medium = m_mediaList.findById(_udi);
+
+ if ( !medium )
+ return i18n("No such medium: %1").arg(_udi);
+
+ if (!medium->isMounted())
+ return TQString(); // that was easy
+
+ TQString mountPoint = isInFstab(medium);
+ if (!mountPoint.isNull())
+ {
+ struct mount_job_data data;
+ data.completed = false;
+ data.medium = medium;
+
+ TDEIO::Job *job = TDEIO::unmount( medium->mountPoint(), false );
+ connect(job, TQT_SIGNAL( result (TDEIO::Job *)), TQT_SLOT( slotResult( TDEIO::Job *)));
+ mount_jobs[job] = &data;
+ // The caller expects the device to be unmounted when the function
+ // completes. Thus block until the job completes.
+ while (!data.completed) {
+ kapp->eventLoop()->enterLoop();
+ }
+ // Return the error message (if any) to the caller
+ return (data.error) ? data.errorMessage : TQString::null;
+ }
+
+ TQString udi = TQString::null;
+
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+
+ TDEStorageDevice * sdevice = hwdevices->findDiskByUID(medium->id());
+ if (!sdevice) {
+ return i18n("Internal error");
+ }
+
+ TQString qerror;
+ TQString origqerror;
+
+ // Save these for later
+ TQString uid = sdevice->uniqueID();
+ TQString node = sdevice->deviceNode();
+
+ TQString unmountMessages;
+ int unmountRetcode = 0;
+ if (!sdevice->unmountDevice(&unmountMessages, &unmountRetcode)) {
+ // Unmount failed!
+ qerror = "<qt>" + i18n("Unfortunately, the device <b>%1</b> (%2) named <b>'%3'</b> and currently mounted at <b>%4</b> could not be unmounted. ").arg("system:/media/" + medium->name(), medium->deviceNode(), medium->prettyLabel(), medium->prettyBaseURL().pathOrURL());
+ if (!unmountMessages.isNull()) {
+ qerror.append(i18n("<p>Technical details:<br>").append(unmountMessages));
+ }
+ qerror.append("</qt>");
+ }
+ else {
+ qerror = "";
+ }
+
+ if (unmountRetcode == 1280) {
+ // Failed as BUSY
+ TQString processesUsingDev = listUsingProcesses(medium);
+ if (!processesUsingDev.isNull()) {
+ if (KMessageBox::warningYesNo(0, i18n("<qt>The device <b>%1</b> (%2) named <b>'%3'</b> and currently mounted at <b>%4</b> can not be unmounted at this time.<p>%5<p><b>Would you like to forcibly terminate these processes?</b><br><i>All unsaved data would be lost</i>").arg("system:/media/" + medium->name()).arg(medium->deviceNode()).arg(medium->prettyLabel()).arg(medium->prettyBaseURL().pathOrURL()).arg(processesUsingDev)) == KMessageBox::Yes) {
+ killUsingProcesses(medium);
+ if (!sdevice->unmountDevice(&unmountMessages, &unmountRetcode)) {
+ // Unmount failed!
+ qerror = "<qt>" + i18n("Unfortunately, the device <b>%1</b> (%2) named <b>'%3'</b> and currently mounted at <b>%4</b> could not be unmounted. ").arg("system:/media/" + medium->name(), medium->deviceNode(), medium->prettyLabel(), medium->prettyBaseURL().pathOrURL());
+ if (!unmountMessages.isNull()) {
+ qerror.append(i18n("<p>Technical details:<br>").append(unmountMessages));
+ }
+ qerror.append("</qt>");
+ }
+ else {
+ qerror = "";
+ }
+ }
+ }
+ }
+
+ if (qerror != "") {
+ return qerror;
+ }
+
+ // There is a possibility that the storage device was unceremoniously removed from the system immediately after it was unmounted
+ // There is no reliable way to know if this happened either!
+ // For now, see if the device node still exists
+ TQFileInfo checkDN(node);
+ if (!checkDN.exists()) {
+ m_mediaList.removeMedium(uid, true);
+ }
+ else {
+ TQString mountedPath = sdevice->mountPath();
+ if (!mountedPath.isNull()) {
+ // Because the TDE hardware backend is event driven it might take a little while for the device to show up as unmounted
+ // Wait up to 30 seconds for the mount to disappear...
+ for (int i=0;i<300;i++) {
+ mountedPath = sdevice->mountPath();
+ if (mountedPath.isNull()) {
+ break;
+ }
+ tqApp->processEvents(50);
+ usleep(50000);
+ }
+ }
+
+ ResetProperties(sdevice, false);
+ }
+
+ return TQString();
+}
+
+TQString TDEBackend::isInFstab(const Medium *medium)
+{
+ KMountPoint::List fstab = KMountPoint::possibleMountPoints(KMountPoint::NeedMountOptions|KMountPoint::NeedRealDeviceName);
+
+ KMountPoint::List::iterator it = fstab.begin();
+ KMountPoint::List::iterator end = fstab.end();
+
+ for (; it!=end; ++it)
+ {
+ TQString reald = (*it)->realDeviceName();
+ if ( reald.endsWith( "/" ) ) {
+ reald = reald.left( reald.length() - 1 );
+ }
+ if ((*it)->mountedFrom() == medium->deviceNode() || ( !medium->deviceNode().isEmpty() && reald == medium->deviceNode() ) )
+ {
+ TQStringList opts = (*it)->mountOptions();
+ if (opts.contains("user") || opts.contains("users")) {
+ return (*it)->mountPoint();
+ }
+ }
+ }
+
+ return TQString::null;
+}
+
+TQString TDEBackend::listUsingProcesses(const Medium* medium)
+{
+ TQString proclist, fullmsg;
+ TQString cmdline = TQString("/usr/bin/env fuser -vm %1 2>&1").arg(TDEProcess::quote(medium->mountPoint()));
+ FILE *fuser = popen(cmdline.latin1(), "r");
+
+ uint counter = 0;
+ if (fuser) {
+ proclist += "<pre>";
+ TQTextIStream is(fuser);
+ TQString tmp;
+ while (!is.atEnd()) {
+ tmp = is.readLine();
+ tmp = TQStyleSheet::escape(tmp) + "\n";
+
+ proclist += tmp;
+ if (counter++ > 10) {
+ proclist += "...";
+ break;
+ }
+ }
+ proclist += "</pre>";
+ (void)pclose( fuser );
+ }
+ if (counter) {
+ fullmsg = i18n("Programs still using the device "
+ "have been detected. They are listed below. You have to "
+ "close them or change their working directory before "
+ "attempting to unmount the device again.");
+ fullmsg += "<br>" + proclist;
+ return fullmsg;
+ }
+ else {
+ return TQString::null;
+ }
+}
+
+TQString TDEBackend::killUsingProcesses(const Medium* medium)
+{
+ TQString proclist, fullmsg;
+ TQString cmdline = TQString("/usr/bin/env fuser -vmk %1 2>&1").arg(TDEProcess::quote(medium->mountPoint()));
+ FILE *fuser = popen(cmdline.latin1(), "r");
+
+ uint counter = 0;
+ if (fuser) {
+ proclist += "<pre>";
+ TQTextIStream is(fuser);
+ TQString tmp;
+ while (!is.atEnd()) {
+ tmp = is.readLine();
+ tmp = TQStyleSheet::escape(tmp) + "\n";
+
+ proclist += tmp;
+ if (counter++ > 10) {
+ proclist += "...";
+ break;
+ }
+ }
+ proclist += "</pre>";
+ (void)pclose( fuser );
+ }
+ if (counter) {
+ fullmsg = i18n("Programs that were still using the device "
+ "have been forcibly terminated. They are listed below.");
+ fullmsg += "<br>" + proclist;
+ return fullmsg;
+ }
+ else {
+ return TQString::null;
+ }
+}
+
+TQString TDEBackend::generateName(const TQString &devNode)
+{
+ return KURL(devNode).fileName();
+}
+
+TQString TDEBackend::driveUDIFromDeviceUID(TQString uuid) {
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+
+ TDEStorageDevice * sdevice = hwdevices->findDiskByUID(uuid);
+ TQString ret;
+ if (sdevice) {
+ ret = sdevice->diskUUID();
+ if (ret != "") {
+ ret = "volume_uuid_" + ret;
+ }
+ else {
+ ret = sdevice->deviceNode();
+ if (ret != "") {
+ ret = "device_node_" + ret;
+ }
+ else {
+ ret = sdevice->uniqueID();
+ }
+ }
+ }
+ if (ret == "") {
+ return TQString::null;
+ }
+ else {
+ return ret;
+ }
+}
+
+#include "tdehardwarebackend.moc" \ No newline at end of file
diff --git a/tdeioslave/media/mediamanager/tdehardwarebackend.h b/tdeioslave/media/mediamanager/tdehardwarebackend.h
new file mode 100644
index 000000000..9b5407d8f
--- /dev/null
+++ b/tdeioslave/media/mediamanager/tdehardwarebackend.h
@@ -0,0 +1,171 @@
+/* This file is part of the TDE Project
+ Copyright (c) 2012 Timothy Pearson <[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 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.
+*/
+
+/**
+* This is a media:/ backend for the builtin TDE hardware library
+*
+* @author Timothy Pearson <[email protected]>
+* @short media:/ backend for the TDE hardware library
+*/
+
+#ifndef _TDEBACKEND_H_
+#define _TDEBACKEND_H_
+
+#include "backendbase.h"
+
+#include <tqobject.h>
+#include <tqstringlist.h>
+#include <tqstring.h>
+
+#include <config.h>
+
+#include <tdehardwaredevices.h>
+
+namespace TDEIO {
+ class Job;
+}
+
+class Dialog;
+
+class TDEBackend : public TQObject, public BackendBase
+{
+Q_OBJECT
+
+public:
+ /**
+ * Constructor
+ */
+ TDEBackend(MediaList &list, TQObject* parent);
+
+ /**
+ * Destructor
+ */
+ ~TDEBackend();
+
+ /**
+ * List all devices and append them to the media device list (called only once, at startup).
+ *
+ * @return true if succeded, false otherwise
+ */
+ bool ListDevices();
+
+ TQStringList mountoptions(const TQString &id);
+
+ bool setMountoptions(const TQString &id, const TQStringList &options);
+
+ TQString mount(const TQString &id);
+ TQString mount(const Medium *medium);
+ TQString unmount(const TQString &id);
+// TQString decrypt(const TQString &id, const TQString &password);
+// TQString undecrypt(const TQString &id);
+
+private:
+ /**
+ * Append a device in the media list. This function will check if the device
+ * is worth listing.
+ *
+ * @param sdevice A pointer to a TDEStorageDevice object
+ * @param allowNotification Indicates if this event will be notified to the user
+ */
+ void AddDevice(TDEStorageDevice * sdevice, bool allowNotification=true);
+
+ /**
+ * Remove a device from the device list
+ *
+ * @param sdevice A pointer to a TDEStorageDevice object
+ */
+ void RemoveDevice(TDEStorageDevice * sdevice);
+
+ /**
+ * A device has changed, update it
+ *
+ * @param sdevice A pointer to a TDEStorageDevice object
+ */
+ void ModifyDevice(TDEStorageDevice * sdevice);
+
+private slots:
+ void AddDeviceHandler(TDEGenericDevice* device);
+ void RemoveDeviceHandler(TDEGenericDevice* device);
+ void ModifyDeviceHandler(TDEGenericDevice* device);
+
+ void slotPasswordReady();
+ void slotPasswordCancel();
+
+signals:
+ void signalDecryptionPasswordError(TQString);
+
+/* Set media properties */
+private:
+ /**
+ * Reset properties for the given medium
+ *
+ * @param sdevice A pointer to a TDEStorageDevice objec
+ * @param allowNotification Indicates if this event will be notified to the user
+ * @param overrideIgnoreList If true, override event ignore requests for the current device node
+ */
+ void ResetProperties(TDEStorageDevice * sdevice, bool allowNotification=false, bool overrideIgnoreList=false);
+
+ /**
+ * Find the medium that is concerned with device udi
+ */
+// const char* findMediumUdiFromUdi(const char* udi);
+
+ void setVolumeProperties(Medium* medium);
+ bool setFloppyProperties(Medium* medium);
+ void setFloppyMountState( Medium* medium );
+// bool setFstabProperties(Medium* medium);
+ void setCameraProperties(Medium* medium);
+ TQString generateName(const TQString &devNode);
+ static TQString isInFstab(const Medium *medium);
+ static TQString listUsingProcesses(const Medium *medium);
+ static TQString killUsingProcesses(const Medium *medium);
+
+ TQString driveUDIFromDeviceUID(TQString uuid);
+
+ // Decryption
+ Dialog* m_decryptDialog;
+ TQString m_decryptionPassword;
+ bool m_decryptPasswordValid;
+
+/* TDE structures */
+private:
+ /**
+ * Object for the kded module
+ */
+ TQObject* m_parent;
+
+ /**
+ * Data structure for fstab mount/unmount jobs
+ */
+ struct mount_job_data {
+ // [in] Medium, which is being mounted/unmounted by the job
+ const Medium* medium;
+ // [in,out] Should be set to true when the job completes
+ bool completed;
+ // [out] TDEIO::Error if an error occured during operation. Otherwise, 0
+ int error;
+ // [out] Error message to be displayed to the user
+ TQString errorMessage;
+ };
+
+ TQMap<TDEIO::Job *, struct mount_job_data*> mount_jobs;
+
+ TQStringList m_ignoreDeviceChangeEvents;
+};
+
+#endif /* _TDEBACKEND_H_ */