File indexing completed on 2024-11-10 05:13:55
0001 /* 0002 SPDX-FileCopyrightText: 1998 Michael Kropfberger <michael.kropfberger@gmx.net> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "disks.h" 0007 0008 #include "kdfprivate_debug.h" 0009 0010 #include <KLocalizedString> 0011 #include <KProcess> 0012 0013 #include <QFileInfo> 0014 #include <QDir> 0015 0016 #include <unistd.h> 0017 #include <sys/types.h> 0018 0019 /****************************************************/ 0020 /********************* DiskEntry ********************/ 0021 /****************************************************/ 0022 0023 /** 0024 * Constructor 0025 **/ 0026 void DiskEntry::init(const QString &name) 0027 { 0028 setObjectName( name ); 0029 device.clear(); 0030 type.clear(); 0031 mountedOn.clear(); 0032 options.clear(); 0033 size=0; 0034 used=0; 0035 avail=0; 0036 isMounted=false; 0037 mntcmd.clear(); 0038 umntcmd.clear(); 0039 iconSetByUser=false; 0040 icoName.clear(); 0041 0042 0043 // BackgroundProcesses **************************************** 0044 0045 sysProc = new KProcess(); 0046 Q_CHECK_PTR(sysProc); 0047 sysProc->setOutputChannelMode( KProcess::MergedChannels ); 0048 connect( sysProc, &QProcess::readyReadStandardError, 0049 this, &DiskEntry::receivedSysStdErrOut ); 0050 connect( sysProc, &QProcess::readyReadStandardOutput, 0051 this, &DiskEntry::receivedSysStdErrOut ); 0052 readingSysStdErrOut=false; 0053 0054 0055 } 0056 0057 DiskEntry::DiskEntry(QObject *parent, const QString &name) 0058 : QObject (parent) 0059 { 0060 init(name); 0061 } 0062 0063 DiskEntry::DiskEntry(const QString & deviceName, QObject *parent, const QString &name) 0064 : QObject (parent) 0065 { 0066 init(name); 0067 0068 setDeviceName(deviceName); 0069 } 0070 DiskEntry::~DiskEntry() 0071 { 0072 disconnect(this); 0073 if ( sysProc->state() == QProcess::Running ) 0074 { 0075 sysProc->terminate(); 0076 sysProc->waitForFinished(-1); 0077 } 0078 delete sysProc; 0079 } 0080 0081 int DiskEntry::toggleMount() 0082 { 0083 if (!mounted()) 0084 return mount(); 0085 else 0086 return umount(); 0087 } 0088 0089 int DiskEntry::mount() 0090 { 0091 QString cmdS=mntcmd; 0092 if ( cmdS.isEmpty() ) 0093 { // generate default mount cmd 0094 if ( getuid()!=0 ) // user mountable 0095 { 0096 cmdS = QStringLiteral( "mount %d" ); 0097 } 0098 else // root mounts with all params/options 0099 { 0100 // FreeBSD's mount(8) is picky: -o _must_ go before 0101 // the device and mountpoint. 0102 cmdS = QStringLiteral( "mount -t%t -o%o %d %m" ); 0103 } 0104 } 0105 0106 cmdS.replace( QLatin1String( "%d" ), deviceName() ); 0107 cmdS.replace( QLatin1String( "%m" ), mountPoint() ); 0108 cmdS.replace( QLatin1String( "%t" ), fsType() ); 0109 cmdS.replace( QLatin1String( "%o" ), mountOptions() ); 0110 0111 qCDebug(KDF) << "mount-cmd: [" << cmdS << "]"; 0112 int e = sysCall( cmdS ); 0113 if (!e) 0114 setMounted( true ); 0115 qCDebug(KDF) << "mount-cmd: e=" << e; 0116 return e; 0117 } 0118 0119 int DiskEntry::umount() 0120 { 0121 qCDebug(KDF) << "umounting"; 0122 QString cmdS = umntcmd; 0123 if ( cmdS.isEmpty() ) // generate default umount cmd 0124 cmdS = QStringLiteral( "umount %d" ); 0125 0126 cmdS.replace( QLatin1String( "%d" ), deviceName() ); 0127 cmdS.replace( QLatin1String( "%m" ), mountPoint() ); 0128 0129 qCDebug(KDF) << "umount-cmd: [" << cmdS << "]"; 0130 int e = sysCall( cmdS ); 0131 if ( !e ) 0132 setMounted( false ); 0133 qCDebug(KDF) << "umount-cmd: e=" << e; 0134 0135 return e; 0136 } 0137 0138 int DiskEntry::remount() 0139 { 0140 if ( mntcmd.isEmpty() && umntcmd.isEmpty() // default mount/umount commands 0141 && ( getuid()==0) ) // you are root 0142 { 0143 QString oldOpt = options; 0144 if (options.isEmpty()) 0145 options = QStringLiteral( "remount" ); 0146 else 0147 options += QLatin1String( ",remount" ); 0148 0149 int e = mount(); 0150 options = oldOpt; 0151 return e; 0152 } else 0153 { 0154 if ( int e=umount() ) 0155 return mount(); 0156 else 0157 return e; 0158 } 0159 } 0160 0161 void DiskEntry::setMountCommand(const QString & mnt) 0162 { 0163 mntcmd=mnt; 0164 } 0165 0166 void DiskEntry::setUmountCommand(const QString & umnt) 0167 { 0168 umntcmd=umnt; 0169 } 0170 0171 void DiskEntry::setIconName(const QString & iconName) 0172 { 0173 iconSetByUser=true; 0174 icoName=iconName; 0175 if ( icoName.right(6) == QLatin1String( "_mount" ) ) 0176 icoName.chop(6); 0177 else if ( icoName.right(8) == QLatin1String( "_unmount" ) ) 0178 icoName.chop(8); 0179 0180 Q_EMIT iconNameChanged(); 0181 } 0182 0183 void DiskEntry::setIconToDefault() 0184 { 0185 iconSetByUser = false; 0186 icoName.clear(); 0187 0188 } 0189 0190 QString DiskEntry::iconName() 0191 { 0192 if (iconSetByUser) 0193 return icoName; 0194 else 0195 return guessIconName(); 0196 } 0197 0198 //TODO: Need porting to solid 0199 QString DiskEntry::guessIconName() 0200 { 0201 QString iconName; 0202 0203 /* 0204 //List Solid Devices 0205 foreach (const Solid::Device &device, Solid::Device::listFromType(Solid::DeviceInterface::StorageVolume)) 0206 { 0207 qCDebug(KDF) << device.udi().toLatin1().constData() << device.vendor() << device.product() << device.icon(); 0208 } 0209 Solid::Device * device = new Solid::Device(deviceName()); 0210 qCDebug(KDF) << "guess" << deviceName() << device->icon(); 0211 delete device; 0212 */ 0213 // try to be intelligent 0214 if (mountPoint().contains(QLatin1String( "cdrom" ),Qt::CaseInsensitive)) 0215 iconName+=QLatin1String( "media-optical" ); 0216 else if (deviceName().contains(QLatin1String( "cdrom" ),Qt::CaseInsensitive)) 0217 iconName+=QLatin1String( "media-optical" ); 0218 else if (mountPoint().contains(QLatin1String( "writer" ),Qt::CaseInsensitive)) 0219 iconName+=QLatin1String( "media-optical-recordable" ); 0220 else if (deviceName().contains(QLatin1String( "writer" ),Qt::CaseInsensitive)) 0221 iconName+=QLatin1String( "media-optical-recordable" ); 0222 else if (mountPoint().contains(QLatin1String( "mo" ),Qt::CaseInsensitive)) 0223 iconName+=QLatin1String( "mo" ); //TODO 0224 else if (deviceName().contains(QLatin1String( "mo" ),Qt::CaseInsensitive)) 0225 iconName+=QLatin1String( "mo" ); //TODO 0226 else if (deviceName().contains(QLatin1String( "fd" ),Qt::CaseInsensitive)) 0227 { 0228 if (deviceName().contains(QLatin1String( "360" ),Qt::CaseInsensitive)) 0229 iconName+=QLatin1String( "5floppy" ); //TODO 0230 if (deviceName().contains(QLatin1String( "1200" ),Qt::CaseInsensitive)) 0231 iconName+=QLatin1String( "5floppy" ); //TODO 0232 else 0233 iconName+=QLatin1String( "media-floppy" ); 0234 } 0235 else if (mountPoint().contains(QLatin1String( "floppy" ),Qt::CaseInsensitive)) 0236 iconName+=QLatin1String( "media-floppy" ); 0237 else if (mountPoint().contains(QLatin1String( "zip" ),Qt::CaseInsensitive)) 0238 iconName+=QLatin1String( "zip" ); //TODO 0239 else if (fsType().contains(QLatin1String( "nfs" ),Qt::CaseInsensitive)) 0240 iconName+=QLatin1String( "nfs" ); //TODO 0241 else 0242 iconName+=QLatin1String( "drive-harddisk" ); 0243 ///mounted() ? iconName+="_mount" : iconName+="_unmount"; 0244 // if ( !mountOptions().contains("user",Qt::CaseInsensitive) ) 0245 // iconName.prepend("root_"); // special root icon, normal user can't mount 0246 0247 //debug("device %s is %s",deviceName().latin1(),iconName.latin1()); 0248 0249 //Q_EMIT iconNameChanged(); 0250 return iconName; 0251 } 0252 0253 0254 /*************************************************************************** 0255 * starts a command on the underlying system via /bin/sh 0256 **/ 0257 int DiskEntry::sysCall(QString & completeCommand) 0258 { 0259 if (readingSysStdErrOut || sysProc->state() == QProcess::Running ) 0260 return -1; 0261 0262 sysStringErrOut=i18n("Called: %1\n\n", completeCommand); // put the called command on ErrOut 0263 sysProc->clearProgram(); 0264 0265 //Split command and arguments to use the new API, otherwise it doesn't work 0266 QTextStream tS(&completeCommand); 0267 0268 QString command; 0269 tS >> command; 0270 0271 QString tmp; 0272 QStringList args; 0273 while( !tS.atEnd() ) 0274 { 0275 tS >> tmp; 0276 args << tmp; 0277 } 0278 0279 sysProc->setProgram(command, args); 0280 sysProc->start(); 0281 0282 if ( !sysProc->waitForStarted(-1) ) 0283 qCCritical(KDF) << i18n("could not execute %1", command) ; 0284 0285 sysProc->waitForFinished(-1); 0286 0287 if (sysProc->exitCode()!=0) 0288 Q_EMIT sysCallError(this, sysProc->exitStatus()); 0289 0290 return (sysProc->exitCode()); 0291 } 0292 0293 0294 /*************************************************************************** 0295 * is called, when the Sys-command writes on StdOut or StdErr 0296 **/ 0297 void DiskEntry::receivedSysStdErrOut() 0298 { 0299 QString stdOut = QString::fromLocal8Bit( sysProc->readAllStandardOutput() ); 0300 QString stdErr = QString::fromLocal8Bit( sysProc->readAllStandardError() ); 0301 0302 sysStringErrOut.append( stdOut ); 0303 sysStringErrOut.append( stdErr ); 0304 } 0305 0306 int DiskEntry::percentFull() const 0307 { 0308 if (size != 0) 0309 { 0310 return 100 - qRound((qreal(avail) / qreal(size)) * 100); 0311 } 0312 else 0313 { 0314 return -1; 0315 } 0316 } 0317 0318 void DiskEntry::setDeviceName(const QString & deviceName) 0319 { 0320 device=deviceName; 0321 Q_EMIT deviceNameChanged(); 0322 } 0323 0324 QString DiskEntry::deviceRealName() const 0325 { 0326 QFileInfo inf( device ); 0327 QDir dir( inf.absolutePath() ); 0328 QString relPath = inf.fileName(); 0329 if ( inf.isSymLink() ) 0330 { 0331 QString link = inf.symLinkTarget(); 0332 if ( link.startsWith( QLatin1Char( '/' ) ) ) 0333 return link; 0334 relPath = link; 0335 } 0336 return dir.canonicalPath() + QLatin1Char( '/' ) + relPath; 0337 } 0338 0339 void DiskEntry::setMountPoint(const QString & mountPoint) 0340 { 0341 mountedOn=mountPoint; 0342 Q_EMIT mountPointChanged(); 0343 } 0344 0345 QString DiskEntry::realMountPoint() const 0346 { 0347 QDir dir( mountedOn ); 0348 return dir.canonicalPath(); 0349 } 0350 0351 void DiskEntry::setMountOptions(const QString & mountOptions) 0352 { 0353 options=mountOptions; 0354 Q_EMIT mountOptionsChanged(); 0355 } 0356 0357 void DiskEntry::setFsType(const QString & fsType) 0358 { 0359 type=fsType; 0360 Q_EMIT fsTypeChanged(); 0361 } 0362 0363 void DiskEntry::setMounted(bool nowMounted) 0364 { 0365 isMounted=nowMounted; 0366 Q_EMIT mountedChanged(); 0367 } 0368 0369 void DiskEntry::setKBSize(qulonglong kb_size) 0370 { 0371 size=kb_size; 0372 Q_EMIT kBSizeChanged(); 0373 } 0374 0375 void DiskEntry::setKBUsed(qulonglong kb_used) 0376 { 0377 used=kb_used; 0378 if ( size < (used+avail) ) 0379 { //adjust kBAvail 0380 qCWarning(KDF) << "device " << device << ": kBAvail(" << avail << ")+*kBUsed(" << used << ") exceeds kBSize(" << size << ")" ; 0381 setKBAvail(size-used); 0382 } 0383 Q_EMIT kBUsedChanged(); 0384 } 0385 0386 void DiskEntry::setKBAvail(qulonglong kb_avail) 0387 { 0388 avail=kb_avail; 0389 if ( size < (used+avail) ) 0390 { //adjust kBUsed 0391 qCWarning(KDF) << "device " << device << ": *kBAvail(" << avail << ")+kBUsed(" << used << ") exceeds kBSize(" << size << ")" ; 0392 setKBUsed(size-avail); 0393 } 0394 Q_EMIT kBAvailChanged(); 0395 } 0396 0397 0398 0399 #include "moc_disks.cpp"