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 if (ft != 0) {
00312 QString options = QFile::decodeName(ft->fs_mntops);
00313 mp->d->mountOptions = options.split( ',' );
00314 } else {
00315
00316 }
00317 }
00318
00319 mp->d->finalizeCurrentMountPoint(infoNeeded);
00320
00321 result.append(mp);
00322 }
00323
00324 #elif defined(_AIX)
00325
00326 struct vmount *mntctl_buffer;
00327 struct vmount *vm;
00328 char *mountedfrom;
00329 char *mountedto;
00330 int fsname_len, num;
00331 int buf_sz = 4096;
00332
00333 mntctl_buffer = (struct vmount*)malloc(buf_sz);
00334 num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
00335 if (num == 0)
00336 {
00337 buf_sz = *(int*)mntctl_buffer;
00338 free(mntctl_buffer);
00339 mntctl_buffer = (struct vmount*)malloc(buf_sz);
00340 num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
00341 }
00342
00343 if (num > 0)
00344 {
00345
00346 vm = (struct vmount *)mntctl_buffer;
00347 for ( ; num > 0; --num )
00348 {
00349
00350 fsname_len = vmt2datasize(vm, VMT_STUB);
00351 mountedto = (char*)malloc(fsname_len + 1);
00352 mountedto[fsname_len] = '\0';
00353 strncpy(mountedto, (char *)vmt2dataptr(vm, VMT_STUB), fsname_len);
00354
00355 fsname_len = vmt2datasize(vm, VMT_OBJECT);
00356 mountedfrom = (char*)malloc(fsname_len + 1);
00357 mountedfrom[fsname_len] = '\0';
00358 strncpy(mountedfrom, (char *)vmt2dataptr(vm, VMT_OBJECT), fsname_len);
00359
00360
00361
00362
00363
00364 struct vfs_ent* ent = getvfsbytype(vm->vmt_gfstype);
00365
00366 KMountPoint *mp = new KMountPoint;
00367 mp->d->mountedFrom = QFile::decodeName(mountedfrom);
00368 mp->d->mountPoint = QFile::decodeName(mountedto);
00369 mp->d->mountType = QFile::decodeName(ent->vfsent_name);
00370
00371 free(mountedfrom);
00372 free(mountedto);
00373
00374 if (infoNeeded & NeedMountOptions)
00375 {
00376
00377 }
00378
00379 mp->d->finalizeCurrentMountPoint(infoNeeded);
00380 result.append(mp);
00381
00382
00383 vm = (struct vmount *)((char *)vm + vm->vmt_length);
00384 }
00385
00386 endvfsent( );
00387 }
00388
00389 free( mntctl_buffer );
00390 #elif defined(Q_WS_WIN)
00391
00392 DWORD bits = GetLogicalDrives();
00393 if(!bits)
00394 return result;
00395
00396 for(int i = 0; i < 26; i++)
00397 {
00398 if(bits & (1 << i))
00399 {
00400 Ptr mp(new KMountPoint);
00401 mp->d->mountPoint = QString(QChar('A' + i) + QString(":/"));
00402 result.append(mp);
00403 }
00404 }
00405
00406 #else
00407 STRUCT_SETMNTENT mnttab;
00408 if ((mnttab = SETMNTENT(MNTTAB, "r")) == 0)
00409 return result;
00410
00411 STRUCT_MNTENT fe;
00412 while (GETMNTENT(mnttab, fe))
00413 {
00414 Ptr mp(new KMountPoint);
00415 mp->d->mountedFrom = QFile::decodeName(FSNAME(fe));
00416
00417 mp->d->mountPoint = QFile::decodeName(MOUNTPOINT(fe));
00418 mp->d->mountType = QFile::decodeName(MOUNTTYPE(fe));
00419
00420
00421
00422 if (infoNeeded & NeedMountOptions || (mp->d->mountType == "supermount"))
00423 {
00424 QString options = QFile::decodeName(MOUNTOPTIONS(fe));
00425 mp->d->mountOptions = options.split( ',' );
00426 }
00427 mp->d->finalizeCurrentMountPoint(infoNeeded);
00428
00429 result.append(mp);
00430 }
00431 ENDMNTENT(mnttab);
00432 #endif
00433 return result;
00434 }
00435
00436 QString KMountPoint::mountedFrom() const
00437 {
00438 return d->mountedFrom;
00439 }
00440
00441 QString KMountPoint::realDeviceName() const
00442 {
00443 return d->device;
00444 }
00445
00446 QString KMountPoint::mountPoint() const
00447 {
00448 return d->mountPoint;
00449 }
00450
00451 QString KMountPoint::mountType() const
00452 {
00453 return d->mountType;
00454 }
00455
00456 QStringList KMountPoint::mountOptions() const
00457 {
00458 return d->mountOptions;
00459 }
00460
00461 KMountPoint::List::List()
00462 : QList<Ptr>()
00463 {
00464 }
00465
00466 KMountPoint::Ptr KMountPoint::List::findByPath(const QString& path) const
00467 {
00468 #ifndef Q_WS_WIN
00469
00470 const QString realname = KStandardDirs::realFilePath(path);
00471 #else
00472 const QString realname = QDir::fromNativeSeparators(QDir(path).absolutePath());
00473 #endif
00474
00475 int max = 0;
00476 KMountPoint::Ptr result;
00477 for (const_iterator it = begin(); it != end(); ++it) {
00478 const QString mountpoint = (*it)->d->mountPoint;
00479 const int length = mountpoint.length();
00480 if (realname.startsWith(mountpoint) && length > max) {
00481 max = length;
00482 result = *it;
00483
00484 }
00485 }
00486 return result;
00487 }
00488
00489 KMountPoint::Ptr KMountPoint::List::findByDevice(const QString& device) const
00490 {
00491 const QString realDevice = KStandardDirs::realFilePath(device);
00492 if (realDevice.isEmpty())
00493 return Ptr();
00494 for (const_iterator it = begin(); it != end(); ++it) {
00495 if ((*it)->d->device == realDevice ||
00496 (*it)->d->mountedFrom == realDevice)
00497 return *it;
00498 }
00499 return Ptr();
00500 }
00501
00502 bool KMountPoint::probablySlow() const
00503 {
00504 bool nfs = d->mountType == "nfs";
00505 bool autofs = d->mountType == "autofs" || d->mountType == "subfs";
00506
00507
00508
00509
00510
00511 if (nfs || autofs) {
00512 return true;
00513 }
00514 return false;
00515 }
00516
00517 bool KMountPoint::testFileSystemFlag(FileSystemFlag flag) const
00518 {
00519 const bool isMsDos = ( d->mountType == "msdos" || d->mountType == "fat" || d->mountType == "vfat" );
00520 switch (flag) {
00521 case SupportsChmod:
00522 case SupportsChown:
00523 case SupportsUTime:
00524 case SupportsSymlinks:
00525 return !isMsDos;
00526 case CaseInsensitive:
00527 return isMsDos;
00528 }
00529 return false;
00530 }
00531