~ubuntu-branches/ubuntu/natty/kde4libs/natty-proposed

« back to all changes in this revision

Viewing changes to .pc/kubuntu_78_solid_trunk.diff/solid/solid/backends/hal/halstorageaccess.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell, Scott Kitterman, Jonathan Riddell
  • Date: 2010-11-22 17:59:02 UTC
  • mfrom: (1.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122175902-yubxubd0pg6hn11z
Tags: 4:4.5.80a-0ubuntu1
[ Scott Kitterman ]
* New upstream beta release
  - Refreshed all patches
  - Updated debian/patches/10_make_libkdeinit4_private.diff to use Qfile
    instead of Qstring in kdecore/kernel/kstandarddirs_unix.cpp
  - Updated debian/patches/kubuntu_01_kubuntu_useragent.diff to provide
    Kubuntu in the Konqueror user agen string with the changes in
    kio/kio/kprotocolmanager.cpp
  - Partially updated debian/patches/kubuntu_05_langpack_desktop_files.diff
    and left the balance in kdecore/localization/klocale.cpp.rej for later
    revision
  - Update debian/patches/kubuntu_06_user_disk_mounting.diff for changes in
    solid/solid/backends/hal/halstorageaccess.cpp
  - Remove debian/patches/kubuntu_71_backport_plasma_webview_changes.diff
    (backported from upstream, so already present now)
  - Add minimum version for libattica-dev of 0.1.90 to build-depends
  - Bump minimum version for libsoprano-dev build-depend to 2.5.60
  - Add minimum version for shared-desktop-ontologies of 0.5 in build-dep

[ Jonathan Riddell ]
* Add build-depends on grantlee, libudev-dev, hupnp (FIXME needs packaging fixes)
* Update kubuntu_04_add_langpack_path.diff 28_find_old_kde4_html_documentation.diff
  22_hack_in_etc_kde4_in_kstandarddirs.diff for QT_NO_CAST_FROM_ASCII
* Update kubuntu_05_langpack_desktop_files.diff for new upstream code
* Add kubuntu_78_solid_trunk.diff to fix solid linking
* Add libnepomukutils4 package for new library
* Don't install kcm_ssl for now, e-mailed upstream to suggest moving to kdebase
* Add kubuntu_79_knewstuff_fix.diff to fix compile broken by non-trunk commit
  http://websvn.kde.org/?view=revision&revision=1199825
* kdelibs5-data replaces old kdebase-runtime-data due to moved file
* Add kubuntu_80_find_hupnp.diff to find hupnp include files, committed upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright 2006 Kevin Ottens <ervin@kde.org>
 
3
 
 
4
    This library is free software; you can redistribute it and/or
 
5
    modify it under the terms of the GNU Lesser General Public
 
6
    License as published by the Free Software Foundation; either
 
7
    version 2.1 of the License, or (at your option) version 3, or any
 
8
    later version accepted by the membership of KDE e.V. (or its
 
9
    successor approved by the membership of KDE e.V.), which shall
 
10
    act as a proxy defined in Section 6 of version 3 of the license.
 
11
 
 
12
    This library is distributed in the hope that it will be useful,
 
13
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
    Lesser General Public License for more details.
 
16
 
 
17
    You should have received a copy of the GNU Lesser General Public
 
18
    License along with this library. If not, see <http://www.gnu.org/licenses/>.
 
19
*/
 
20
 
 
21
#include "halstorageaccess.h"
 
22
 
 
23
#include "halfstabhandling.h"
 
24
#include "../../genericinterface.h"
 
25
 
 
26
#include <QtCore/QLocale>
 
27
#include <QtCore/QDebug>
 
28
#include <QtCore/QTextStream>
 
29
#include <QtCore/QProcess>
 
30
#include <QtCore/QTimer>
 
31
#include <QtDBus/QDBusConnection>
 
32
#include <QtDBus/QDBusInterface>
 
33
#include <QtDBus/QDBusReply>
 
34
#include <QtDBus/QDBusVariant>
 
35
#include <QtGui/QApplication>
 
36
#include <QtGui/QWidget>
 
37
#include <localization/klocalizedstring.h>
 
38
 
 
39
#include <unistd.h>
 
40
#include <stdlib.h>
 
41
#include <locale.h>
 
42
 
 
43
#ifdef Q_OS_FREEBSD
 
44
#include <langinfo.h>
 
45
#endif
 
46
 
 
47
using namespace Solid::Backends::Hal;
 
48
 
 
49
StorageAccess::StorageAccess(HalDevice *device)
 
50
    : DeviceInterface(device), m_setupInProgress(false), m_teardownInProgress(false), m_ejectInProgress(false),
 
51
      m_passphraseRequested(false)
 
52
{
 
53
    connect(device, SIGNAL(propertyChanged(const QMap<QString,int> &)),
 
54
             this, SLOT(slotPropertyChanged(const QMap<QString,int> &)));
 
55
    // Delay connecting to DBus signals to avoid the related time penalty
 
56
    // in hot paths such as predicate matching
 
57
    QTimer::singleShot(0, this, SLOT(connectDBusSignals()));
 
58
}
 
59
 
 
60
StorageAccess::~StorageAccess()
 
61
{
 
62
 
 
63
}
 
64
 
 
65
void StorageAccess::connectDBusSignals()
 
66
{
 
67
    m_device->registerAction("setup", this,
 
68
                             SLOT(slotSetupRequested()),
 
69
                             SLOT(slotSetupDone(int, const QString&)));
 
70
 
 
71
    m_device->registerAction("teardown", this,
 
72
                             SLOT(slotTeardownRequested()),
 
73
                             SLOT(slotTeardownDone(int, const QString&)));
 
74
 
 
75
    m_device->registerAction("eject", this,
 
76
                             SLOT(slotEjectRequested()),
 
77
                             SLOT(slotEjectDone(int, const QString&)));
 
78
}
 
79
 
 
80
void StorageAccess::slotSetupDone(int error, const QString &errorString)
 
81
{
 
82
    m_setupInProgress = false;
 
83
    emit setupDone(static_cast<Solid::ErrorType>(error), errorString, m_device->udi());
 
84
}
 
85
 
 
86
void StorageAccess::slotTeardownDone(int error, const QString &errorString)
 
87
{
 
88
    m_teardownInProgress = false;
 
89
    emit teardownDone(static_cast<Solid::ErrorType>(error), errorString, m_device->udi());
 
90
}
 
91
 
 
92
void StorageAccess::slotEjectDone(int error, const QString &errorString)
 
93
{
 
94
    m_ejectInProgress = false;
 
95
    emit ejectDone(static_cast<Solid::ErrorType>(error), errorString, m_device->udi());
 
96
}
 
97
 
 
98
bool StorageAccess::isAccessible() const
 
99
{
 
100
    if (m_device->property("info.interfaces").toStringList().contains("org.freedesktop.Hal.Device.Volume.Crypto")) {
 
101
 
 
102
        // Might be a bit slow, but I see no cleaner way to do this with HAL...
 
103
        QDBusInterface manager("org.freedesktop.Hal",
 
104
                               "/org/freedesktop/Hal/Manager",
 
105
                               "org.freedesktop.Hal.Manager",
 
106
                               QDBusConnection::systemBus());
 
107
 
 
108
        QDBusReply<QStringList> reply = manager.call("FindDeviceStringMatch",
 
109
                                                     "volume.crypto_luks.clear.backing_volume",
 
110
                                                     m_device->udi());
 
111
 
 
112
        QStringList list = reply;
 
113
 
 
114
        return reply.isValid() && !list.isEmpty();
 
115
 
 
116
    } else {
 
117
        return m_device->property("volume.is_mounted").toBool();
 
118
    }
 
119
}
 
120
 
 
121
QString StorageAccess::filePath() const
 
122
{
 
123
    QString result = m_device->property("volume.mount_point").toString();
 
124
 
 
125
    if (result.isEmpty()) {
 
126
        QStringList mountpoints
 
127
            = FstabHandling::possibleMountPoints(m_device->property("block.device").toString());
 
128
        if (mountpoints.size()==1) {
 
129
            result = mountpoints.first();
 
130
        }
 
131
    }
 
132
 
 
133
    return result;
 
134
}
 
135
 
 
136
bool StorageAccess::isIgnored() const
 
137
{
 
138
    HalDevice lock("/org/freedesktop/Hal/devices/computer");
 
139
    bool isLocked = lock.property("info.named_locks.Global.org.freedesktop.Hal.Device.Storage.locked").toBool();
 
140
 
 
141
    if (m_device->property("volume.ignore").toBool() || isLocked ){
 
142
        return true;
 
143
    }
 
144
 
 
145
    const QString mount_point = StorageAccess(m_device).filePath();
 
146
    const bool mounted = m_device->property("volume.is_mounted").toBool();
 
147
    if (!mounted) {
 
148
        return false;
 
149
    } else if (mount_point.startsWith(QLatin1String("/media/")) || mount_point.startsWith(QLatin1String("/mnt/"))) {
 
150
        return false;
 
151
    }
 
152
 
 
153
    /* Now be a bit more aggressive on what we want to ignore,
 
154
     * the user generally need to check only what's removable or in /media
 
155
     * the volumes mounted to make the system (/, /boot, /var, etc.)
 
156
     * are useless to him.
 
157
     */
 
158
    Solid::Device drive(m_device->property("block.storage_device").toString());
 
159
 
 
160
    const bool removable = drive.as<Solid::GenericInterface>()->property("storage.removable").toBool();
 
161
    const bool hotpluggable = drive.as<Solid::GenericInterface>()->property("storage.hotpluggable").toBool();
 
162
 
 
163
    return !removable && !hotpluggable;
 
164
}
 
165
 
 
166
bool StorageAccess::setup()
 
167
{
 
168
    if (m_teardownInProgress || m_setupInProgress || isAccessible()) {
 
169
        return false;
 
170
    }
 
171
    m_setupInProgress = true;
 
172
    m_device->broadcastActionRequested("setup");
 
173
 
 
174
    if (m_device->property("info.interfaces").toStringList().contains("org.freedesktop.Hal.Device.Volume.Crypto")) {
 
175
        return requestPassphrase();
 
176
    } else if (FstabHandling::isInFstab(m_device->property("block.device").toString())) {
 
177
        return callSystemMount();
 
178
    } else {
 
179
        return callHalVolumeMount();
 
180
    }
 
181
}
 
182
 
 
183
bool StorageAccess::teardown()
 
184
{
 
185
    if (m_teardownInProgress || m_setupInProgress || !isAccessible()) {
 
186
        return false;
 
187
    }
 
188
    m_teardownInProgress = true;
 
189
    m_device->broadcastActionRequested("teardown");
 
190
 
 
191
    if (m_device->property("info.interfaces").toStringList().contains("org.freedesktop.Hal.Device.Volume.Crypto")) {
 
192
        return callCryptoTeardown();
 
193
    } else if (FstabHandling::isInFstab(m_device->property("block.device").toString())) {
 
194
        return callSystemUnmount();
 
195
    } else {
 
196
        return callHalVolumeUnmount();
 
197
    }
 
198
}
 
199
 
 
200
void StorageAccess::slotPropertyChanged(const QMap<QString,int> &changes)
 
201
{
 
202
    if (changes.contains("volume.is_mounted"))
 
203
    {
 
204
        emit accessibilityChanged(isAccessible(), m_device->udi());
 
205
    }
 
206
}
 
207
 
 
208
void StorageAccess::slotDBusReply(const QDBusMessage &/*reply*/)
 
209
{
 
210
    if (m_setupInProgress) {
 
211
        m_setupInProgress = false;
 
212
        m_device->broadcastActionDone("setup");
 
213
    } else if (m_teardownInProgress) {
 
214
        m_teardownInProgress = false;
 
215
        m_device->broadcastActionDone("teardown");
 
216
 
 
217
        HalDevice drive(m_device->property("block.storage_device").toString());
 
218
        if (drive.property("storage.drive_type").toString()!="cdrom"
 
219
         && drive.property("storage.requires_eject").toBool()) {
 
220
 
 
221
            QString devnode = m_device->property("block.device").toString();
 
222
 
 
223
#if defined(Q_OS_OPENBSD)
 
224
            QString program = "cdio";
 
225
            QStringList args;
 
226
            args << "-f" << devnode << "eject";
 
227
#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
 
228
            devnode.remove("/dev/").replace("([0-9]).", "\\1");
 
229
            QString program = "cdcontrol";
 
230
            QStringList args;
 
231
            args << "-f" << devnode << "eject";
 
232
#else
 
233
            QString program = "eject";
 
234
            QStringList args;
 
235
            args << devnode;
 
236
#endif
 
237
 
 
238
            m_ejectInProgress = true;
 
239
            m_device->broadcastActionRequested("eject");
 
240
            m_process = FstabHandling::callSystemCommand("eject", args,
 
241
                                                         this, SLOT(slotProcessFinished(int, QProcess::ExitStatus)));
 
242
        }
 
243
    } else if (m_ejectInProgress) {
 
244
        m_ejectInProgress = false;
 
245
        m_device->broadcastActionDone("eject");
 
246
    }
 
247
}
 
248
 
 
249
void StorageAccess::slotDBusError(const QDBusError &error)
 
250
{
 
251
    // TODO: Better error reporting here
 
252
    if (m_setupInProgress) {
 
253
       if (error.name() == "org.freedesktop.Hal.Device.Volume.PermissionDenied") {
 
254
          callHalPrivilegedVolumeMount();
 
255
          return;
 
256
        }
 
257
        m_setupInProgress = false;
 
258
        m_device->broadcastActionDone("setup", Solid::UnauthorizedOperation,
 
259
                                      QString(error.name()+": "+error.message()));
 
260
    } else if (m_teardownInProgress) {
 
261
        if (error.name() == "org.freedesktop.Hal.Device.PermissionDeniedByPolicy") {
 
262
            callHalPrivilegedVolumeUnmount();
 
263
            return;
 
264
        }
 
265
 
 
266
        m_teardownInProgress = false;
 
267
        m_device->broadcastActionDone("teardown", Solid::UnauthorizedOperation,
 
268
                                      QString(error.name()+": "+error.message()));
 
269
    } else if (m_ejectInProgress) {
 
270
        m_ejectInProgress = false;
 
271
        m_device->broadcastActionDone("eject", Solid::UnauthorizedOperation,
 
272
                                      QString(error.name()+": "+error.message()));
 
273
    }
 
274
}
 
275
 
 
276
void Solid::Backends::Hal::StorageAccess::slotProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
 
277
{
 
278
    Q_UNUSED(exitStatus);
 
279
    if (m_setupInProgress) {
 
280
        m_setupInProgress = false;
 
281
 
 
282
        if (exitCode==0) {
 
283
            m_device->broadcastActionDone("setup");
 
284
        } else {
 
285
            m_device->broadcastActionDone("setup", Solid::UnauthorizedOperation,
 
286
                                          m_process->readAllStandardError());
 
287
        }
 
288
    } else if (m_teardownInProgress) {
 
289
        m_teardownInProgress = false;
 
290
        if (exitCode==0) {
 
291
            m_device->broadcastActionDone("teardown");
 
292
        } else {
 
293
            m_device->broadcastActionDone("teardown", Solid::UnauthorizedOperation,
 
294
                                          m_process->readAllStandardError());
 
295
        }
 
296
    } else if (m_ejectInProgress) {
 
297
        if (exitCode==0)  {
 
298
            m_ejectInProgress = false;
 
299
            m_device->broadcastActionDone("eject");
 
300
        } else {
 
301
            callHalVolumeEject();
 
302
        }
 
303
    }
 
304
 
 
305
    delete m_process;
 
306
}
 
307
 
 
308
void StorageAccess::slotSetupRequested()
 
309
{
 
310
    m_setupInProgress = true;
 
311
    emit setupRequested(m_device->udi());
 
312
}
 
313
 
 
314
void StorageAccess::slotTeardownRequested()
 
315
{
 
316
    m_teardownInProgress = true;
 
317
    emit teardownRequested(m_device->udi());
 
318
}
 
319
 
 
320
void StorageAccess::slotEjectRequested()
 
321
{
 
322
    m_ejectInProgress = true;
 
323
}
 
324
 
 
325
QString generateReturnObjectPath()
 
326
{
 
327
    static int number = 1;
 
328
 
 
329
    return "/org/kde/solid/HalStorageAccess_"+QString::number(number++);
 
330
}
 
331
 
 
332
bool StorageAccess::requestPassphrase()
 
333
{
 
334
    QString udi = m_device->udi();
 
335
    QString returnService = QDBusConnection::sessionBus().baseService();
 
336
    m_lastReturnObject = generateReturnObjectPath();
 
337
 
 
338
    QDBusConnection::sessionBus().registerObject(m_lastReturnObject, this,
 
339
                                                 QDBusConnection::ExportScriptableSlots);
 
340
 
 
341
 
 
342
    QWidget *activeWindow = QApplication::activeWindow();
 
343
    uint wId = 0;
 
344
    if (activeWindow!=0) {
 
345
        wId = (uint)activeWindow->winId();
 
346
    }
 
347
 
 
348
    QString appId = QCoreApplication::applicationName();
 
349
 
 
350
    QDBusInterface soliduiserver("org.kde.kded", "/modules/soliduiserver", "org.kde.SolidUiServer");
 
351
    QDBusReply<void> reply = soliduiserver.call("showPassphraseDialog", udi,
 
352
                                                returnService, m_lastReturnObject,
 
353
                                                wId, appId);
 
354
    m_passphraseRequested = reply.isValid();
 
355
    if (!m_passphraseRequested) {
 
356
        qWarning() << "Failed to call the SolidUiServer, D-Bus said:" << reply.error();
 
357
    }
 
358
    return m_passphraseRequested;
 
359
}
 
360
 
 
361
void StorageAccess::passphraseReply(const QString &passphrase)
 
362
{
 
363
    if (m_passphraseRequested) {
 
364
        QDBusConnection::sessionBus().unregisterObject(m_lastReturnObject);
 
365
        m_passphraseRequested = false;
 
366
        if (!passphrase.isEmpty()) {
 
367
            callCryptoSetup(passphrase);
 
368
        } else {
 
369
            m_setupInProgress = false;
 
370
            m_device->broadcastActionDone("setup");
 
371
        }
 
372
    }
 
373
}
 
374
 
 
375
bool StorageAccess::callHalVolumeMount()
 
376
{
 
377
    QDBusConnection c = QDBusConnection::systemBus();
 
378
    QString udi = m_device->udi();
 
379
    QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.Hal", udi,
 
380
                                                      "org.freedesktop.Hal.Device.Volume",
 
381
                                                      "Mount");
 
382
 
 
383
    // HAL 0.5.12 supports using alternative drivers for the same filesystem.
 
384
    // This is mainly used to integrate the ntfs-3g driver.
 
385
    // Unfortunately, the primary driver gets used unless we
 
386
    // specify some other driver (fstype) to the Mount method.
 
387
    // TODO: Allow the user to choose the driver.
 
388
 
 
389
    QString fstype = m_device->property("volume.fstype").toString();
 
390
    QStringList halOptions = m_device->property("volume.mount.valid_options").toStringList();
 
391
 
 
392
    QString alternativePreferred = m_device->property("volume.fstype.alternative.preferred").toString();
 
393
    if (!alternativePreferred.isEmpty()) {
 
394
        QStringList alternativeFstypes = m_device->property("volume.fstype.alternative").toStringList();
 
395
        if (alternativeFstypes.contains(alternativePreferred)) {
 
396
            fstype = alternativePreferred;
 
397
            halOptions = m_device->property("volume.mount."+fstype+".valid_options").toStringList();
 
398
        }
 
399
    }
 
400
 
 
401
    QStringList options;
 
402
 
 
403
#ifdef Q_OS_FREEBSD
 
404
    QString uid="-u=";
 
405
#else
 
406
    QString uid="uid=";
 
407
#endif
 
408
    QString fsType = m_device->property("volume.fstype").toString();
 
409
 
 
410
    if (halOptions.contains("uid=") && !fsType.contains("ntfs")) {
 
411
        options << uid+QString::number(::getuid());
 
412
    }
 
413
 
 
414
    if (fsType.contains("ntfs")) {
 
415
        options << "locale=" + QString(setlocale(LC_ALL, ""));
 
416
    }
 
417
 
 
418
 
 
419
#ifdef Q_OS_FREEBSD
 
420
    char *cType;
 
421
    if ( fstype=="vfat" && halOptions.contains("-L=")) {
 
422
        if ( (cType = getenv("LC_ALL")) || (cType = getenv("LC_CTYPE")) || (cType = getenv("LANG")) )
 
423
              options << "-L="+QString(cType);
 
424
    }
 
425
    else if ( (fstype.startsWith(QLatin1String("ntfs")) || fstype=="iso9660" || fstype=="udf") && halOptions.contains("-C=") ) {
 
426
        if ((cType = getenv("LC_ALL")) || (cType = getenv("LC_CTYPE")) || (cType = getenv("LANG")) )
 
427
            options << "-C="+QString(nl_langinfo(CODESET));
 
428
    }
 
429
#else
 
430
    if (fstype=="vfat" || fstype=="ntfs" || fstype=="iso9660" || fstype=="udf" ) {
 
431
        if (halOptions.contains("utf8"))
 
432
            options<<"utf8";
 
433
        else if (halOptions.contains("iocharset="))
 
434
            options<<"iocharset=utf8";
 
435
        if (halOptions.contains("shortname="))
 
436
            options<<"shortname=mixed";
 
437
        if (halOptions.contains("flush"))
 
438
            options<<"flush";
 
439
    }
 
440
    // pass our locale to the ntfs-3g driver so it can translate local characters
 
441
    else if ( halOptions.contains("locale=") ) {
 
442
        // have to obtain LC_CTYPE as returned by the `locale` command
 
443
        // check in the same order as `locale` does
 
444
        char *cType;
 
445
        if ( (cType = getenv("LC_ALL")) || (cType = getenv("LC_CTYPE")) || (cType = getenv("LANG")) ) {
 
446
            options << "locale="+QString(cType);
 
447
        }
 
448
    }
 
449
#endif
 
450
 
 
451
    msg << "" << fstype << options;
 
452
 
 
453
    return c.callWithCallback(msg, this,
 
454
                              SLOT(slotDBusReply(const QDBusMessage &)),
 
455
                              SLOT(slotDBusError(const QDBusError &)));
 
456
}
 
457
 
 
458
bool StorageAccess::callHalVolumeUnmount()
 
459
{
 
460
    QDBusConnection c = QDBusConnection::systemBus();
 
461
    QString udi = m_device->udi();
 
462
    QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.Hal", udi,
 
463
                                                      "org.freedesktop.Hal.Device.Volume",
 
464
                                                      "Unmount");
 
465
 
 
466
    msg << QStringList();
 
467
 
 
468
    return c.callWithCallback(msg, this,
 
469
                              SLOT(slotDBusReply(const QDBusMessage &)),
 
470
                              SLOT(slotDBusError(const QDBusError &)));
 
471
}
 
472
 
 
473
bool StorageAccess::callHalVolumeEject()
 
474
{
 
475
    QString udi = m_device->udi();
 
476
    QString interface = "org.freedesktop.Hal.Device.Volume";
 
477
 
 
478
    QDBusConnection c = QDBusConnection::systemBus();
 
479
    QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.Hal", udi,
 
480
                                                      interface, "Eject");
 
481
 
 
482
    msg << QStringList();
 
483
 
 
484
    return c.callWithCallback(msg, this,
 
485
                              SLOT(slotDBusReply(const QDBusMessage &)),
 
486
                              SLOT(slotDBusError(const QDBusError &)));
 
487
}
 
488
 
 
489
bool Solid::Backends::Hal::StorageAccess::callSystemMount()
 
490
{
 
491
    const QString device = m_device->property("block.device").toString();
 
492
    m_process = FstabHandling::callSystemCommand("mount", device,
 
493
                                                 this, SLOT(slotProcessFinished(int, QProcess::ExitStatus)));
 
494
 
 
495
    return m_process!=0;
 
496
}
 
497
 
 
498
QString sudoCommandName()
 
499
{
 
500
    return "/usr/lib/kde4/libexec/kdesu";
 
501
}
 
502
 
 
503
QString dbusSendCommandName()
 
504
{
 
505
    return "dbus-send";
 
506
}
 
507
 
 
508
QProcess* callPrivilegedCommand(const QString& command,
 
509
                                QObject* obj, const char* slot,
 
510
                                const QString& comment)
 
511
{
 
512
    QProcess* process = new QProcess(obj);
 
513
 
 
514
    QObject::connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
 
515
                     obj, slot);
 
516
 
 
517
    QStringList commandArgs;
 
518
    commandArgs << "-d" << "--noignorebutton";
 
519
    if(!comment.isEmpty())
 
520
        commandArgs << "--comment" << comment;
 
521
    commandArgs << "-c" << command;
 
522
 
 
523
    process->start(sudoCommandName(), commandArgs);
 
524
 
 
525
    if (process->waitForStarted()) {
 
526
        return process;
 
527
    } else {
 
528
        delete process;
 
529
        return 0;
 
530
    }
 
531
}
 
532
 
 
533
bool Solid::Backends::Hal::StorageAccess::callHalPrivilegedVolumeMount()
 
534
{
 
535
    QStringList options;
 
536
    QStringList halOptions = m_device->property("volume.mount.valid_options").toStringList();
 
537
 
 
538
    QString fsType = m_device->property("volume.fstype").toString();
 
539
 
 
540
    if (halOptions.contains("uid=") && !fsType.contains("ntfs")) {
 
541
        options << "uid="+QString::number(::getuid());
 
542
    }
 
543
 
 
544
    if (fsType.contains("ntfs")) {
 
545
        options << "locale=" + QString(setlocale(LC_ALL, ""));
 
546
    }
 
547
 
 
548
    QString command;
 
549
    QTextStream(&command) << dbusSendCommandName()
 
550
            << " --system --print-reply --dest=org.freedesktop.Hal " << m_device->udi()
 
551
            << " org.freedesktop.Hal.Device.Volume.Mount string:" << filePath()
 
552
            << " string: array:string:" << options.join(",");
 
553
 
 
554
    m_process = callPrivilegedCommand(command,
 
555
                                      this,
 
556
                                      SLOT(slotProcessFinished(int, QProcess::ExitStatus)),
 
557
                                      QObject::tr("Please enter your password to use this device"));
 
558
 
 
559
    return (m_process != 0);
 
560
}
 
561
 
 
562
bool Solid::Backends::Hal::StorageAccess::callHalPrivilegedVolumeUnmount()
 
563
{
 
564
    QString command;
 
565
    QTextStream(&command) << dbusSendCommandName()
 
566
            << " --system --print-reply --dest=org.freedesktop.Hal " << m_device->udi()
 
567
            << " org.freedesktop.Hal.Device.Volume.Unmount array:string:force";
 
568
 
 
569
    m_process = callPrivilegedCommand(command,
 
570
                                      this,
 
571
                                      SLOT(slotProcessFinished(int, QProcess::ExitStatus)),
 
572
                                      QObject::tr("Please enter your password to safely remove this device"));
 
573
 
 
574
    return m_process != 0;
 
575
}
 
576
 
 
577
 
 
578
bool Solid::Backends::Hal::StorageAccess::callSystemUnmount()
 
579
{
 
580
    const QString device = m_device->property("block.device").toString();
 
581
    m_process = FstabHandling::callSystemCommand("umount", device,
 
582
                                                 this, SLOT(slotProcessFinished(int, QProcess::ExitStatus)));
 
583
 
 
584
    return m_process!=0;
 
585
}
 
586
 
 
587
void StorageAccess::callCryptoSetup(const QString &passphrase)
 
588
{
 
589
    QDBusConnection c = QDBusConnection::systemBus();
 
590
    QString udi = m_device->udi();
 
591
    QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.Hal", udi,
 
592
                                                      "org.freedesktop.Hal.Device.Volume.Crypto",
 
593
                                                      "Setup");
 
594
 
 
595
    msg << passphrase;
 
596
 
 
597
    c.callWithCallback(msg, this,
 
598
                       SLOT(slotDBusReply(const QDBusMessage &)),
 
599
                       SLOT(slotDBusError(const QDBusError &)));
 
600
}
 
601
 
 
602
bool StorageAccess::callCryptoTeardown()
 
603
{
 
604
    QDBusConnection c = QDBusConnection::systemBus();
 
605
    QString udi = m_device->udi();
 
606
    QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.Hal", udi,
 
607
                                                      "org.freedesktop.Hal.Device.Volume.Crypto",
 
608
                                                      "Teardown");
 
609
 
 
610
    return c.callWithCallback(msg, this,
 
611
                              SLOT(slotDBusReply(const QDBusMessage &)),
 
612
                              SLOT(slotDBusError(const QDBusError &)));
 
613
}
 
614
 
 
615
#include "backends/hal/halstorageaccess.moc"