KIO
kmountpoint.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kmountpoint.h"
00022
00023 #include <config.h>
00024 #include <stdlib.h>
00025
00026 #include <QtCore/QFile>
00027 #include <QtCore/QTextIStream>
00028
00029 #include "kstandarddirs.h"
00030
00031 #include <solid/device.h>
00032 #include <solid/block.h>
00033
00034 #ifdef Q_WS_WIN
00035 #include <windows.h>
00036 #include <QDir>
00037 #endif
00038
00039 #ifdef HAVE_VOLMGT
00040 #include <volmgt.h>
00041 #endif
00042 #ifdef HAVE_SYS_MNTTAB_H
00043 #include <sys/mnttab.h>
00044 #endif
00045 #ifdef HAVE_MNTENT_H
00046 #include <mntent.h>
00047 #elif defined(HAVE_SYS_MNTENT_H)
00048 #include <sys/mntent.h>
00049 #endif
00050
00051
00052 #ifdef HAVE_SYS_MOUNT_H
00053 #ifdef HAVE_SYS_TYPES_H
00054 #include <sys/types.h>
00055 #endif
00056 #ifdef HAVE_SYS_PARAM_H
00057 #include <sys/param.h>
00058 #endif
00059 #include <sys/mount.h>
00060 #endif
00061
00062 #ifdef HAVE_FSTAB_H
00063 #include <fstab.h>
00064 #endif
00065 #if defined(_AIX)
00066 #include <sys/mntctl.h>
00067 #include <sys/vmount.h>
00068 #include <sys/vfs.h>
00069
00070 #ifndef mntctl
00071 extern "C" int mntctl(int command, int size, void* buffer);
00072 #endif
00073 extern "C" struct vfs_ent *getvfsbytype(int vfsType);
00074 extern "C" void endvfsent( );
00075 #endif
00076
00077
00078 #ifndef HAVE_GETMNTINFO
00079 # ifdef _PATH_MOUNTED
00080
00081 # undef MNTTAB
00082 # define MNTTAB _PATH_MOUNTED
00083 # else
00084 # ifndef MNTTAB
00085 # ifdef MTAB_FILE
00086 # define MNTTAB MTAB_FILE
00087 # else
00088 # define MNTTAB "/etc/mnttab"
00089 # endif
00090 # endif
00091 # endif
00092 #endif
00093
00094 #include "kdebug.h"
00095
00096
00097 #ifdef _OS_SOLARIS_
00098 #define FSTAB "/etc/vfstab"
00099 #else
00100 #define FSTAB "/etc/fstab"
00101 #endif
00102
00103 class KMountPoint::Private {
00104 public:
00105 void finalizePossibleMountPoint(DetailsNeededFlags infoNeeded);
00106 void finalizeCurrentMountPoint(DetailsNeededFlags infoNeeded);
00107
00108 QString mountedFrom;
00109 QString device;
00110 QString mountPoint;
00111 QString mountType;
00112 QStringList mountOptions;
00113 };
00114
00115 KMountPoint::KMountPoint()
00116 :d( new Private )
00117 {
00118 }
00119
00120 KMountPoint::~KMountPoint()
00121 {
00122 delete d;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132 #ifdef HAVE_SETMNTENT
00133 #define SETMNTENT setmntent
00134 #define ENDMNTENT endmntent
00135 #define STRUCT_MNTENT struct mntent *
00136 #define STRUCT_SETMNTENT FILE *
00137 #define GETMNTENT(file, var) ((var = getmntent(file)) != 0)
00138 #define MOUNTPOINT(var) var->mnt_dir
00139 #define MOUNTTYPE(var) var->mnt_type
00140 #define MOUNTOPTIONS(var) var->mnt_opts
00141 #define FSNAME(var) var->mnt_fsname
00142 #else
00143 #define SETMNTENT fopen
00144 #define ENDMNTENT fclose
00145 #define STRUCT_MNTENT struct mnttab
00146 #define STRUCT_SETMNTENT FILE *
00147 #define GETMNTENT(file, var) (getmntent(file, &var) == 0)
00148 #define MOUNTPOINT(var) var.mnt_mountp
00149 #define MOUNTTYPE(var) var.mnt_fstype
00150 #define MOUNTOPTIONS(var) var.mnt_mntopts
00151 #define FSNAME(var) var.mnt_special
00152 #endif
00153
00158 static QString devNameFromOptions(const QStringList &options)
00159 {
00160
00161 for ( QStringList::ConstIterator it = options.begin(); it != options.end(); ++it)
00162 {
00163 if( (*it).startsWith("dev="))
00164 return (*it).mid(4);
00165 }
00166 return QString("none");
00167 }
00168
00169 void KMountPoint::Private::finalizePossibleMountPoint(DetailsNeededFlags infoNeeded)
00170 {
00171 if (mountType == "supermount") {
00172 mountedFrom = devNameFromOptions(mountOptions);
00173 }
00174
00175 if (mountedFrom.startsWith("UUID=")) {
00176 const QString uuid = mountedFrom.mid(5);
00177 const QString query = "StorageVolume.uuid == '" + uuid + '\'';
00178 const QList<Solid::Device> lst = Solid::Device::listFromQuery(query);
00179 if (!lst.isEmpty()) {
00180 mountedFrom = lst.first().as<Solid::Block>()->device();
00181 }
00182 }
00183
00184 if (infoNeeded & NeedRealDeviceName) {
00185 if (mountedFrom.startsWith('/'))
00186 device = KStandardDirs::realFilePath(mountedFrom);
00187 }
00188
00189 }
00190
00191 void KMountPoint::Private::finalizeCurrentMountPoint(DetailsNeededFlags infoNeeded)
00192 {
00193 if (infoNeeded & NeedRealDeviceName) {
00194 if (mountedFrom.startsWith('/'))
00195 device = KStandardDirs::realFilePath(mountedFrom);
00196 }
00197 }
00198
00199 KMountPoint::List KMountPoint::possibleMountPoints(DetailsNeededFlags infoNeeded)
00200 {
00201 KMountPoint::List result;
00202
00203 #ifdef HAVE_SETMNTENT
00204 STRUCT_SETMNTENT fstab;
00205 if ((fstab = SETMNTENT(FSTAB, "r")) == 0)
00206 return result;
00207
00208 STRUCT_MNTENT fe;
00209 while (GETMNTENT(fstab, fe))
00210 {
00211 Ptr mp(new KMountPoint);
00212 mp->d->mountedFrom = QFile::decodeName(FSNAME(fe));
00213
00214 mp->d->mountPoint = QFile::decodeName(MOUNTPOINT(fe));
00215 mp->d->mountType = QFile::decodeName(MOUNTTYPE(fe));
00216
00217
00218
00219 if (infoNeeded & NeedMountOptions || (mp->d->mountType == "supermount"))
00220 {
00221 QString options = QFile::decodeName(MOUNTOPTIONS(fe));
00222 mp->d->mountOptions = options.split( ',' );
00223 }
00224
00225 mp->d->finalizePossibleMountPoint(infoNeeded);
00226
00227 result.append(mp);
00228 }
00229 ENDMNTENT(fstab);
00230 #else
00231 QFile f(FSTAB);
00232 if ( !f.open(QIODevice::ReadOnly) )
00233 return result;
00234
00235 QTextStream t (&f);
00236 QString s;
00237
00238 while (! t.atEnd())
00239 {
00240 s=t.readLine().simplified();
00241 if ( s.isEmpty() || (s[0] == '#'))
00242 continue;
00243
00244
00245 const QStringList item = s.split( ' ');
00246
00247 #ifdef _OS_SOLARIS_
00248 if (item.count() < 5)
00249 continue;
00250 #else
00251 if (item.count() < 4)
00252 continue;
00253 #endif
00254
00255 Ptr mp(new KMountPoint);
00256
00257 int i = 0;
00258 mp->d->mountedFrom = item[i++];
00259 #ifdef _OS_SOLARIS_
00260
00261 i++;
00262 #endif
00263 mp->d->mountPoint = item[i++];
00264 mp->d->mountType = item[i++];
00265 QString options = item[i++];
00266
00267 if (infoNeeded & NeedMountOptions)
00268 {
00269 mp->d->mountOptions = options.split( ',');
00270 }
00271
00272 mp->d->finalizePossibleMountPoint(infoNeeded);
00273
00274 result.append(mp);
00275 }
00276
00277 f.close();
00278 #endif
00279 return result;
00280 }
00281
00282 KMountPoint::List KMountPoint::currentMountPoints(DetailsNeededFlags infoNeeded)
00283 {
00284 KMountPoint::List result;
00285
00286 #ifdef HAVE_GETMNTINFO
00287
00288 #ifdef GETMNTINFO_USES_STATVFS
00289 struct statvfs *mounted;
00290 #else
00291 struct statfs *mounted;
00292 #endif
00293
00294 int num_fs = getmntinfo(&mounted, MNT_NOWAIT);
00295
00296 for (int i=0;i< num_fs;i++)
00297 {
00298 Ptr mp(new KMountPoint);
00299 mp->d->mountedFrom = QFile::decodeName(mounted[i].f_mntfromname);
00300 mp->d->mountPoint = QFile::decodeName(mounted[i].f_mntonname);
00301
00302 #ifdef __osf__
00303 mp->d->mountType = QFile::decodeName(mnt_names[mounted[i].f_type]);
00304 #else
00305 mp->d->mountType = QFile::decodeName(mounted[i].f_fstypename);
00306 #endif
00307
00308 if (infoNeeded & NeedMountOptions)
00309 {
00310 struct fstab *ft = getfsfile(mounted[i].f_mntonname);
00311 QString options = QFile::decodeName(ft->fs_mntops);
00312 mp->d->mountOptions = options.split( ',' );
00313 }
00314
00315 mp->d->finalizeCurrentMountPoint(infoNeeded);
00316
00317 result.append(mp);
00318 }
00319
00320 #elif defined(_AIX)
00321
00322 struct vmount *mntctl_buffer;
00323 struct vmount *vm;
00324 char *mountedfrom;
00325 char *mountedto;
00326 int fsname_len, num;
00327 int buf_sz = 4096;
00328
00329 mntctl_buffer = (struct vmount*)malloc(buf_sz);
00330 num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
00331 if (num == 0)
00332 {
00333 buf_sz = *(int*)mntctl_buffer;
00334 free(mntctl_buffer);
00335 mntctl_buffer = (struct vmount*)malloc(buf_sz);
00336 num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
00337 }
00338
00339 if (num > 0)
00340 {
00341
00342 vm = (struct vmount *)mntctl_buffer;
00343 for ( ; num > 0; num-- )
00344 {
00345
00346 fsname_len = vmt2datasize(vm, VMT_STUB);
00347 mountedto = (char*)malloc(fsname_len + 1);
00348 mountedto[fsname_len] = '\0';
00349 strncpy(mountedto, (char *)vmt2dataptr(vm, VMT_STUB), fsname_len);
00350
00351 fsname_len = vmt2datasize(vm, VMT_OBJECT);
00352 mountedfrom = (char*)malloc(fsname_len + 1);
00353 mountedfrom[fsname_len] = '\0';
00354 strncpy(mountedfrom, (char *)vmt2dataptr(vm, VMT_OBJECT), fsname_len);
00355
00356
00357
00358
00359
00360 struct vfs_ent* ent = getvfsbytype(vm->vmt_gfstype);
00361
00362 KMountPoint *mp = new KMountPoint;
00363 mp->d->mountedFrom = QFile::decodeName(mountedfrom);
00364 mp->d->mountPoint = QFile::decodeName(mountedto);
00365 mp->d->mountType = QFile::decodeName(ent->vfsent_name);
00366
00367 free(mountedfrom);
00368 free(mountedto);
00369
00370 if (infoNeeded & NeedMountOptions)
00371 {
00372
00373 }
00374
00375 mp->d->finalizeCurrentMountPoint(infoNeeded);
00376 result.append(mp);
00377
00378
00379 vm = (struct vmount *)((char *)vm + vm->vmt_length);
00380 }
00381
00382 endvfsent( );
00383 }
00384
00385 free( mntctl_buffer );
00386 #elif defined(Q_WS_WIN)
00387
00388 DWORD bits = GetLogicalDrives();
00389 if(!bits)
00390 return result;
00391
00392 for(int i = 0; i < 26; i++)
00393 {
00394 if(bits & (1 << i))
00395 {
00396 Ptr mp(new KMountPoint);
00397 mp->d->mountPoint = QString(QChar('A' + i) + QString(":/"));
00398 result.append(mp);
00399 }
00400 }
00401
00402 #else
00403 STRUCT_SETMNTENT mnttab;
00404 if ((mnttab = SETMNTENT(MNTTAB, "r")) == 0)
00405 return result;
00406
00407 STRUCT_MNTENT fe;
00408 while (GETMNTENT(mnttab, fe))
00409 {
00410 Ptr mp(new KMountPoint);
00411 mp->d->mountedFrom = QFile::decodeName(FSNAME(fe));
00412
00413 mp->d->mountPoint = QFile::decodeName(MOUNTPOINT(fe));
00414 mp->d->mountType = QFile::decodeName(MOUNTTYPE(fe));
00415
00416
00417
00418 if (infoNeeded & NeedMountOptions || (mp->d->mountType == "supermount"))
00419 {
00420 QString options = QFile::decodeName(MOUNTOPTIONS(fe));
00421 mp->d->mountOptions = options.split( ',' );
00422 }
00423 mp->d->finalizeCurrentMountPoint(infoNeeded);
00424
00425 result.append(mp);
00426 }
00427 ENDMNTENT(mnttab);
00428 #endif
00429 return result;
00430 }
00431
00432 QString KMountPoint::mountedFrom() const
00433 {
00434 return d->mountedFrom;
00435 }
00436
00437 QString KMountPoint::realDeviceName() const
00438 {
00439 return d->device;
00440 }
00441
00442 QString KMountPoint::mountPoint() const
00443 {
00444 return d->mountPoint;
00445 }
00446
00447 QString KMountPoint::mountType() const
00448 {
00449 return d->mountType;
00450 }
00451
00452 QStringList KMountPoint::mountOptions() const
00453 {
00454 return d->mountOptions;
00455 }
00456
00457 KMountPoint::List::List()
00458 : QList<Ptr>()
00459 {
00460 }
00461
00462 KMountPoint::Ptr KMountPoint::List::findByPath(const QString& path) const
00463 {
00464 #ifndef Q_WS_WIN
00465
00466 const QString realname = KStandardDirs::realFilePath(path);
00467 #else
00468 const QString realname = QDir::fromNativeSeparators(QDir(path).absolutePath());
00469 #endif
00470
00471 int max = 0;
00472 KMountPoint::Ptr result;
00473 for (const_iterator it = begin(); it != end(); ++it) {
00474 const QString mountpoint = (*it)->d->mountPoint;
00475 const int length = mountpoint.length();
00476 if (realname.startsWith(mountpoint) && length > max) {
00477 max = length;
00478 result = *it;
00479
00480 }
00481 }
00482 return result;
00483 }
00484
00485 KMountPoint::Ptr KMountPoint::List::findByDevice(const QString& device) const
00486 {
00487 const QString realDevice = KStandardDirs::realFilePath(device);
00488 if (realDevice.isEmpty())
00489 return Ptr();
00490 for (const_iterator it = begin(); it != end(); ++it) {
00491 if ((*it)->d->device == realDevice ||
00492 (*it)->d->mountedFrom == realDevice)
00493 return *it;
00494 }
00495 return Ptr();
00496 }
00497
00498 bool KMountPoint::probablySlow() const
00499 {
00500 bool nfs = d->mountType == "nfs";
00501 bool autofs = d->mountType == "autofs" || d->mountType == "subfs";
00502
00503
00504
00505
00506
00507 if (nfs || autofs) {
00508 return true;
00509 }
00510 return false;
00511 }
00512
00513 bool KMountPoint::testFileSystemFlag(FileSystemFlag flag) const
00514 {
00515 const bool isMsDos = ( d->mountType == "msdos" || d->mountType == "fat" || d->mountType == "vfat" );
00516 switch (flag) {
00517 case SupportsChmod:
00518 case SupportsChown:
00519 case SupportsUTime:
00520 case SupportsSymlinks:
00521 return !isMsDos;
00522 case CaseInsensitive:
00523 return isMsDos;
00524 }
00525 return false;
00526 }
00527