disks.cpp 10.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * disks.cpp
 *
 * Copyright (c) 1998 Michael Kropfberger <michael.kropfberger@gmx.net>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
Script Kiddy's avatar
Script Kiddy committed
18
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 20
 */

21
#include "disks.h"
22

23 24
#include "kdf_debug.h"

25 26
#include <kprocess.h>
#include <klocale.h>
27 28 29 30 31 32

#include <QFileInfo>
#include <QDir>

#include <unistd.h>
#include <sys/types.h>
33

34 35 36 37 38 39 40
/****************************************************/
/********************* DiskEntry ********************/
/****************************************************/

/**
  * Constructor
**/
Rolf Eike Beer's avatar
Rolf Eike Beer committed
41
void DiskEntry::init(const char *name)
42
{
43
    setObjectName( QLatin1String( name ) );
44 45 46 47
    device.clear();
    type.clear();
    mountedOn.clear();
    options.clear();
48 49 50 51
    size=0;
    used=0;
    avail=0;
    isMounted=false;
52 53
    mntcmd.clear();
    umntcmd.clear();
54
    iconSetByUser=false;
55
    icoName.clear();
56 57 58 59 60 61 62


    // BackgroundProcesses ****************************************

    sysProc = new KProcess();
    Q_CHECK_PTR(sysProc);
    sysProc->setOutputChannelMode( KProcess::MergedChannels );
Laurent Montel's avatar
Laurent Montel committed
63 64 65 66
    connect( sysProc, SIGNAL(readyReadStandardError()),
             this, SLOT (receivedSysStdErrOut()) );
    connect( sysProc, SIGNAL(readyReadStandardOutput()),
             this, SLOT (receivedSysStdErrOut()) );
67
    readingSysStdErrOut=false;
68 69 70 71 72


}

DiskEntry::DiskEntry(QObject *parent, const char *name)
73
        : QObject (parent)
74
{
75
    init(name);
76 77
}

78
DiskEntry::DiskEntry(const QString & deviceName, QObject *parent, const char *name)
79
        : QObject (parent)
80
{
81
    init(name);
Dirk Mueller's avatar
Dirk Mueller committed
82

83
    setDeviceName(deviceName);
84 85 86
}
DiskEntry::~DiskEntry()
{
87 88 89 90 91 92 93
    disconnect(this);
    if ( sysProc->state() == QProcess::Running )
    {
        sysProc->terminate();
        sysProc->waitForFinished(-1);
    }
    delete sysProc;
Dirk Mueller's avatar
Dirk Mueller committed
94
}
95 96

int DiskEntry::toggleMount()
Dirk Mueller's avatar
Dirk Mueller committed
97
{
98 99 100 101
    if (!mounted())
        return mount();
    else
        return umount();
Dirk Mueller's avatar
Dirk Mueller committed
102
}
103 104

int DiskEntry::mount()
Dirk Mueller's avatar
Dirk Mueller committed
105
{
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
    QString cmdS=mntcmd;
    if ( cmdS.isEmpty() )
    { // generate default mount cmd
        if ( getuid()!=0 ) // user mountable
        {
            cmdS = QLatin1String( "mount %d" );
        }
        else  // root mounts with all params/options
        {
            // FreeBSD's mount(8) is picky: -o _must_ go before
            // the device and mountpoint.
            cmdS = QLatin1String( "mount -t%t -o%o %d %m" );
        }
    }

    cmdS.replace( QLatin1String( "%d" ), deviceName() );
    cmdS.replace( QLatin1String( "%m" ), mountPoint() );
    cmdS.replace( QLatin1String( "%t" ), fsType() );
    cmdS.replace( QLatin1String( "%o" ), mountOptions() );

126
    qCDebug(KDF) << "mount-cmd: [" << cmdS << "]";
127 128 129
    int e = sysCall( cmdS );
    if (!e)
        setMounted( true );
130
    qCDebug(KDF) << "mount-cmd: e=" << e;
131
    return e;
Dirk Mueller's avatar
Dirk Mueller committed
132
}
133 134 135

int DiskEntry::umount()
{
136
    qCDebug(KDF) << "umounting";
137 138 139
    QString cmdS = umntcmd;
    if ( cmdS.isEmpty() ) // generate default umount cmd
        cmdS = QLatin1String( "umount %d" );
140

141 142
    cmdS.replace( QLatin1String( "%d" ), deviceName() );
    cmdS.replace( QLatin1String( "%m" ), mountPoint() );
143

144
    qCDebug(KDF) << "umount-cmd: [" << cmdS << "]";
145 146 147
    int e = sysCall( cmdS );
    if ( !e )
        setMounted( false );
148
    qCDebug(KDF) << "umount-cmd: e=" << e;
149

150
    return e;
Dirk Mueller's avatar
Dirk Mueller committed
151
}
152 153 154

int DiskEntry::remount()
{
155 156
    if ( mntcmd.isEmpty() && umntcmd.isEmpty() // default mount/umount commands
            && ( getuid()==0) ) // you are root
157
    {
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
        QString oldOpt = options;
        if (options.isEmpty())
            options = QLatin1String( "remount" );
        else
            options += QLatin1String( ",remount" );

        int e = mount();
        options = oldOpt;
        return e;
    } else
    {
        if ( int e=umount() )
            return mount();
        else
            return e;
    }
Dirk Mueller's avatar
Dirk Mueller committed
174
}
175

Dirk Mueller's avatar
Dirk Mueller committed
176
void DiskEntry::setMountCommand(const QString & mnt)
177
{
178
    mntcmd=mnt;
Dirk Mueller's avatar
Dirk Mueller committed
179
}
180

Dirk Mueller's avatar
Dirk Mueller committed
181
void DiskEntry::setUmountCommand(const QString & umnt)
182
{
183
    umntcmd=umnt;
Dirk Mueller's avatar
Dirk Mueller committed
184
}
185

Dirk Mueller's avatar
Dirk Mueller committed
186
void DiskEntry::setIconName(const QString & iconName)
187
{
188 189 190 191 192 193 194 195 196 197 198 199 200 201
    iconSetByUser=true;
    icoName=iconName;
    if ( icoName.right(6) == QLatin1String( "_mount" ) )
        icoName.truncate(icoName.length()-6);
    else if ( icoName.right(8) == QLatin1String( "_unmount" ) )
        icoName.truncate(icoName.length()-8);

    emit iconNameChanged();
}

void DiskEntry::setIconToDefault()
{
    iconSetByUser = false;
    icoName.clear();
202

Dirk Mueller's avatar
Dirk Mueller committed
203
}
204

Dirk Mueller's avatar
Dirk Mueller committed
205
QString DiskEntry::iconName()
206
{
207
    if (iconSetByUser)
208
        return icoName;
209 210
    else
        return guessIconName();
Dirk Mueller's avatar
Dirk Mueller committed
211
}
212

Davide Bettio's avatar
Davide Bettio committed
213
//TODO: Need porting to solid
214 215
QString DiskEntry::guessIconName()
{
216 217 218
    QString iconName;

    /*
219
    //List Solid Devices
220 221
    foreach (const Solid::Device &device, Solid::Device::listFromType(Solid::DeviceInterface::StorageVolume))
      {
222
          qCDebug(KDF) << device.udi().toLatin1().constData() << device.vendor() << device.product() << device.icon();
223 224
      }
    Solid::Device * device = new Solid::Device(deviceName());
225
    qCDebug(KDF) << "guess" << deviceName() << device->icon();
226 227
    delete device;
    */
228
    // try to be intelligent
229 230 231 232 233 234 235 236 237 238 239 240 241
    if (mountPoint().contains(QLatin1String( "cdrom" ),Qt::CaseInsensitive))
        iconName+=QLatin1String( "media-optical" );
    else if (deviceName().contains(QLatin1String( "cdrom" ),Qt::CaseInsensitive))
        iconName+=QLatin1String( "media-optical" );
    else if (mountPoint().contains(QLatin1String( "writer" ),Qt::CaseInsensitive))
        iconName+=QLatin1String( "media-optical-recordable" );
    else if (deviceName().contains(QLatin1String( "writer" ),Qt::CaseInsensitive))
        iconName+=QLatin1String( "media-optical-recordable" );
    else if (mountPoint().contains(QLatin1String( "mo" ),Qt::CaseInsensitive))
        iconName+=QLatin1String( "mo" ); //TODO
    else if (deviceName().contains(QLatin1String( "mo" ),Qt::CaseInsensitive))
        iconName+=QLatin1String( "mo" ); //TODO
    else if (deviceName().contains(QLatin1String( "fd" ),Qt::CaseInsensitive))
242
    {
243 244 245 246
        if (deviceName().contains(QLatin1String( "360" ),Qt::CaseInsensitive))
            iconName+=QLatin1String( "5floppy" ); //TODO
        if (deviceName().contains(QLatin1String( "1200" ),Qt::CaseInsensitive))
            iconName+=QLatin1String( "5floppy" ); //TODO
247
        else
248
            iconName+=QLatin1String( "media-floppy" );
249
    }
250 251 252 253 254 255
    else if (mountPoint().contains(QLatin1String( "floppy" ),Qt::CaseInsensitive))
        iconName+=QLatin1String( "media-floppy" );
    else if (mountPoint().contains(QLatin1String( "zip" ),Qt::CaseInsensitive))
        iconName+=QLatin1String( "zip" ); //TODO
    else if (fsType().contains(QLatin1String( "nfs" ),Qt::CaseInsensitive))
        iconName+=QLatin1String( "nfs" ); //TODO
256
    else
257
        iconName+=QLatin1String( "drive-harddisk" );
Davide Bettio's avatar
Davide Bettio committed
258
    ///mounted() ? iconName+="_mount" : iconName+="_unmount";
259 260
    //    if ( !mountOptions().contains("user",Qt::CaseInsensitive) )
    //      iconName.prepend("root_"); // special root icon, normal user can't mount
261

262
    //debug("device %s is %s",deviceName().latin1(),iconName.latin1());
Dirk Mueller's avatar
Dirk Mueller committed
263

264
    //emit iconNameChanged();
265
    return iconName;
Dirk Mueller's avatar
Dirk Mueller committed
266
}
267 268 269 270 271


/***************************************************************************
  * starts a command on the underlying system via /bin/sh
**/
272
int DiskEntry::sysCall(QString & completeCommand)
273
{
274 275 276 277 278 279 280 281 282 283 284
    if (readingSysStdErrOut || sysProc->state() == QProcess::Running )
        return -1;

    sysStringErrOut=i18n("Called: %1\n\n", completeCommand); // put the called command on ErrOut
    sysProc->clearProgram();

    //Split command and arguments to use the new API, otherwise it doesn't work
    QTextStream tS(&completeCommand);

    QString command;
    tS >> command;
285

286 287 288 289 290 291 292 293 294 295 296 297
    QString tmp;
    QStringList args;
    while( !tS.atEnd() )
    {
        tS >> tmp;
        args << tmp;
    }

    sysProc->setProgram(command, args);
    sysProc->start();

    if ( !sysProc->waitForStarted(-1) )
298
        qCCritical(KDF) << i18n("could not execute %1", command) ;
299

300
    sysProc->waitForFinished(-1);
301

302 303 304 305
    if (sysProc->exitCode()!=0)
        emit sysCallError(this, sysProc->exitStatus());

    return (sysProc->exitCode());
Dirk Mueller's avatar
Dirk Mueller committed
306
}
307 308 309 310 311


/***************************************************************************
  * is called, when the Sys-command writes on StdOut or StdErr
**/
312
void DiskEntry::receivedSysStdErrOut()
313
{
314 315 316 317 318
    QString stdOut = QString::fromLocal8Bit( sysProc->readAllStandardOutput() );
    QString stdErr = QString::fromLocal8Bit( sysProc->readAllStandardError() );

    sysStringErrOut.append( stdOut );
    sysStringErrOut.append( stdErr );
Dirk Mueller's avatar
Dirk Mueller committed
319
}
320 321 322

float DiskEntry::percentFull() const
{
323 324 325 326 327 328 329 330
    if (size != 0)
    {
        return 100 - ( ((float)avail / (float)size) * 100 );
    }
    else
    {
        return -1;
    }
331 332
}

333
void DiskEntry::setDeviceName(const QString & deviceName)
334
{
335 336
    device=deviceName;
    emit deviceNameChanged();
Dirk Mueller's avatar
Dirk Mueller committed
337
}
338

339 340
QString DiskEntry::deviceRealName() const
{
341 342 343 344 345 346
    QFileInfo inf( device );
    QDir dir( inf.absolutePath() );
    QString relPath = inf.fileName();
    if ( inf.isSymLink() )
    {
        QString link = inf.readLink();
347
        if ( link.startsWith( QLatin1Char( '/' ) ) )
348 349 350
            return link;
        relPath = link;
    }
351
    return dir.canonicalPath() + QLatin1Char( '/' ) + relPath;
352 353
}

354
void DiskEntry::setMountPoint(const QString & mountPoint)
355
{
356 357
    mountedOn=mountPoint;
    emit mountPointChanged();
Dirk Mueller's avatar
Dirk Mueller committed
358
}
359

360 361
QString DiskEntry::realMountPoint() const
{
362 363
    QDir dir( mountedOn );
    return dir.canonicalPath();
364 365
}

366
void DiskEntry::setMountOptions(const QString & mountOptions)
367
{
368 369
    options=mountOptions;
    emit mountOptionsChanged();
Dirk Mueller's avatar
Dirk Mueller committed
370
}
371

372
void DiskEntry::setFsType(const QString & fsType)
373
{
374 375
    type=fsType;
    emit fsTypeChanged();
Dirk Mueller's avatar
Dirk Mueller committed
376
}
377

Dirk Mueller's avatar
Dirk Mueller committed
378 379
void DiskEntry::setMounted(bool nowMounted)
{
380 381
    isMounted=nowMounted;
    emit mountedChanged();
Dirk Mueller's avatar
Dirk Mueller committed
382
}
Dirk Mueller's avatar
Dirk Mueller committed
383

384
void DiskEntry::setKBSize(qulonglong kb_size)
385
{
386 387
    size=kb_size;
    emit kBSizeChanged();
Dirk Mueller's avatar
Dirk Mueller committed
388
}
389

390
void DiskEntry::setKBUsed(qulonglong kb_used)
391
{
392 393 394
    used=kb_used;
    if ( size < (used+avail) )
    {  //adjust kBAvail
395
        qCWarning(KDF) << "device " << device << ": kBAvail(" << avail << ")+*kBUsed(" << used << ") exceeds kBSize(" << size << ")" ;
396 397 398
        setKBAvail(size-used);
    }
    emit kBUsedChanged();
Dirk Mueller's avatar
Dirk Mueller committed
399
}
400

401
void DiskEntry::setKBAvail(qulonglong kb_avail)
402
{
403 404 405
    avail=kb_avail;
    if ( size < (used+avail) )
    {  //adjust kBUsed
406
        qCWarning(KDF) << "device " << device << ": *kBAvail(" << avail << ")+kBUsed(" << used << ") exceeds kBSize(" << size << ")" ;
407 408 409
        setKBUsed(size-avail);
    }
    emit kBAvailChanged();
Dirk Mueller's avatar
Dirk Mueller committed
410
}
411

412
#include "disks.moc"
413