summaryrefslogtreecommitdiffstats
path: root/kdecore/kmountpoint.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdecore/kmountpoint.cpp')
-rw-r--r--kdecore/kmountpoint.cpp385
1 files changed, 385 insertions, 0 deletions
diff --git a/kdecore/kmountpoint.cpp b/kdecore/kmountpoint.cpp
new file mode 100644
index 000000000..a04780a37
--- /dev/null
+++ b/kdecore/kmountpoint.cpp
@@ -0,0 +1,385 @@
+/*
+ *
+ * This file is part of the KDE libraries
+ * Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
+ *
+ * $Id$
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ **/
+
+#include <config.h>
+#include <stdlib.h>
+
+#include <qfile.h>
+
+#include "kstandarddirs.h"
+
+#include "kmountpoint.h"
+
+#ifdef HAVE_VOLMGT
+#include <volmgt.h>
+#endif
+#ifdef HAVE_SYS_MNTTAB_H
+#include <sys/mnttab.h>
+#endif
+#ifdef HAVE_MNTENT_H
+#include <mntent.h>
+#elif defined(HAVE_SYS_MNTENT_H)
+#include <sys/mntent.h>
+#endif
+
+// This is the *BSD branch
+#ifdef HAVE_SYS_MOUNT_H
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/mount.h>
+#endif
+
+#ifdef HAVE_FSTAB_H
+#include <fstab.h>
+#endif
+#if defined(_AIX)
+#include <sys/mntctl.h>
+#include <sys/vmount.h>
+#include <sys/vfs.h>
+/* AIX does not prototype mntctl anywhere that I can find */
+#ifndef mntctl
+extern "C" {
+int mntctl(int command, int size, void* buffer);
+}
+#endif
+extern "C" struct vfs_ent *getvfsbytype(int vfsType);
+extern "C" void endvfsent( );
+#endif
+
+
+#ifndef HAVE_GETMNTINFO
+# ifdef _PATH_MOUNTED
+// On some Linux, MNTTAB points to /etc/fstab !
+# undef MNTTAB
+# define MNTTAB _PATH_MOUNTED
+# else
+# ifndef MNTTAB
+# ifdef MTAB_FILE
+# define MNTTAB MTAB_FILE
+# else
+# define MNTTAB "/etc/mnttab"
+# endif
+# endif
+# endif
+#endif
+
+
+
+#ifdef _OS_SOLARIS_
+#define FSTAB "/etc/vfstab"
+#else
+#define FSTAB "/etc/fstab"
+#endif
+
+
+
+KMountPoint::KMountPoint()
+{
+}
+
+KMountPoint::~KMountPoint()
+{
+}
+
+#ifdef HAVE_SETMNTENT
+#define SETMNTENT setmntent
+#define ENDMNTENT endmntent
+#define STRUCT_MNTENT struct mntent *
+#define STRUCT_SETMNTENT FILE *
+#define GETMNTENT(file, var) ((var = getmntent(file)) != 0)
+#define MOUNTPOINT(var) var->mnt_dir
+#define MOUNTTYPE(var) var->mnt_type
+#define MOUNTOPTIONS(var) var->mnt_opts
+#define FSNAME(var) var->mnt_fsname
+#else
+#define SETMNTENT fopen
+#define ENDMNTENT fclose
+#define STRUCT_MNTENT struct mnttab
+#define STRUCT_SETMNTENT FILE *
+#define GETMNTENT(file, var) (getmntent(file, &var) == 0)
+#define MOUNTPOINT(var) var.mnt_mountp
+#define MOUNTTYPE(var) var.mnt_fstype
+#define MOUNTOPTIONS(var) var.mnt_mntopts
+#define FSNAME(var) var.mnt_special
+#endif
+
+KMountPoint::List KMountPoint::possibleMountPoints(int infoNeeded)
+{
+ KMountPoint::List result;
+
+#ifdef HAVE_SETMNTENT
+ STRUCT_SETMNTENT fstab;
+ if ((fstab = SETMNTENT(FSTAB, "r")) == 0)
+ return result;
+
+ STRUCT_MNTENT fe;
+ while (GETMNTENT(fstab, fe))
+ {
+ KMountPoint *mp = new KMountPoint();
+ mp->m_mountedFrom = QFile::decodeName(FSNAME(fe));
+
+ mp->m_mountPoint = QFile::decodeName(MOUNTPOINT(fe));
+ mp->m_mountType = QFile::decodeName(MOUNTTYPE(fe));
+
+ //Devices using supermount have their device names in the mount options
+ //instead of the device field. That's why we need to read the mount options
+ if (infoNeeded & NeedMountOptions || (mp->m_mountType == "supermount"))
+ {
+ QString options = QFile::decodeName(MOUNTOPTIONS(fe));
+ mp->m_mountOptions = QStringList::split(',', options);
+ }
+
+ if(mp->m_mountType == "supermount")
+ mp->m_mountedFrom = devNameFromOptions(mp->m_mountOptions);
+
+ if (infoNeeded & NeedRealDeviceName)
+ {
+ if (mp->m_mountedFrom.startsWith("/"))
+ mp->m_device = KStandardDirs::realPath(mp->m_mountedFrom);
+ }
+ // TODO: Strip trailing '/' ?
+ result.append(mp);
+ }
+ ENDMNTENT(fstab);
+#else
+ QFile f(FSTAB);
+ if ( !f.open(IO_ReadOnly) )
+ return result;
+
+ QTextStream t (&f);
+ QString s;
+
+ while (! t.eof())
+ {
+ s=t.readLine().simplifyWhiteSpace();
+ if ( s.isEmpty() || (s[0] == '#'))
+ continue;
+
+ // not empty or commented out by '#'
+ QStringList item = QStringList::split(' ', s);
+
+#ifdef _OS_SOLARIS_
+ if (item.count() < 5)
+ continue;
+#else
+ if (item.count() < 4)
+ continue;
+#endif
+
+ KMountPoint *mp = new KMountPoint();
+
+ int i = 0;
+ mp->m_mountedFrom = item[i++];
+#ifdef _OS_SOLARIS_
+ //device to fsck
+ i++;
+#endif
+ mp->m_mountPoint = item[i++];
+ mp->m_mountType = item[i++];
+ QString options = item[i++];
+
+ if (infoNeeded & NeedMountOptions)
+ {
+ mp->m_mountOptions = QStringList::split(',', options);
+ }
+
+ if (infoNeeded & NeedRealDeviceName)
+ {
+ if (mp->m_mountedFrom.startsWith("/"))
+ mp->m_device = KStandardDirs::realPath(mp->m_mountedFrom);
+ }
+ // TODO: Strip trailing '/' ?
+ result.append(mp);
+ } //while
+
+ f.close();
+#endif
+ return result;
+}
+
+KMountPoint::List KMountPoint::currentMountPoints(int infoNeeded)
+{
+ KMountPoint::List result;
+
+#ifdef HAVE_GETMNTINFO
+
+#ifdef GETMNTINFO_USES_STATVFS
+ struct statvfs *mounted;
+#else
+ struct statfs *mounted;
+#endif
+
+ int num_fs = getmntinfo(&mounted, MNT_NOWAIT);
+
+ for (int i=0;i<num_fs;i++)
+ {
+ KMountPoint *mp = new KMountPoint();
+ mp->m_mountedFrom = QFile::decodeName(mounted[i].f_mntfromname);
+ mp->m_mountPoint = QFile::decodeName(mounted[i].f_mntonname);
+
+#ifdef __osf__
+ mp->m_mountType = QFile::decodeName(mnt_names[mounted[i].f_type]);
+#else
+ mp->m_mountType = QFile::decodeName(mounted[i].f_fstypename);
+#endif
+
+ if (infoNeeded & NeedMountOptions)
+ {
+ struct fstab *ft = getfsfile(mounted[i].f_mntonname);
+ QString options = QFile::decodeName(ft->fs_mntops);
+ mp->m_mountOptions = QStringList::split(',', options);
+ }
+
+ if (infoNeeded & NeedRealDeviceName)
+ {
+ if (mp->m_mountedFrom.startsWith("/"))
+ mp->m_device = KStandardDirs::realPath(mp->m_mountedFrom);
+ }
+ // TODO: Strip trailing '/' ?
+ result.append(mp);
+ }
+
+#elif defined(_AIX)
+
+ struct vmount *mntctl_buffer;
+ struct vmount *vm;
+ char *mountedfrom;
+ char *mountedto;
+ int fsname_len, num;
+ int buf_sz = 4096;
+
+ mntctl_buffer = (struct vmount*)malloc(buf_sz);
+ num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
+ if (num == 0)
+ {
+ buf_sz = *(int*)mntctl_buffer;
+ free(mntctl_buffer);
+ mntctl_buffer = (struct vmount*)malloc(buf_sz);
+ num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
+ }
+
+ if (num > 0)
+ {
+ /* iterate through items in the vmount structure: */
+ vm = (struct vmount *)mntctl_buffer;
+ for ( ; num > 0; num-- )
+ {
+ /* get the name of the mounted file systems: */
+ fsname_len = vmt2datasize(vm, VMT_STUB);
+ mountedto = (char*)malloc(fsname_len + 1);
+ mountedto[fsname_len] = '\0';
+ strncpy(mountedto, (char *)vmt2dataptr(vm, VMT_STUB), fsname_len);
+
+ fsname_len = vmt2datasize(vm, VMT_OBJECT);
+ mountedfrom = (char*)malloc(fsname_len + 1);
+ mountedfrom[fsname_len] = '\0';
+ strncpy(mountedfrom, (char *)vmt2dataptr(vm, VMT_OBJECT), fsname_len);
+
+ /* Look up the string for the file system type,
+ * as listed in /etc/vfs.
+ * ex.: nfs,jfs,afs,cdrfs,sfs,cachefs,nfs3,autofs
+ */
+ struct vfs_ent* ent = getvfsbytype(vm->vmt_gfstype);
+
+ KMountPoint *mp = new KMountPoint();
+ mp->m_mountedFrom = QFile::decodeName(mountedfrom);
+ mp->m_mountPoint = QFile::decodeName(mountedto);
+ mp->m_mountType = QFile::decodeName(ent->vfsent_name);
+
+ free(mountedfrom);
+ free(mountedto);
+
+ if (infoNeeded & NeedMountOptions)
+ {
+ // TODO
+ }
+
+ if (infoNeeded & NeedRealDeviceName)
+ {
+ if (mp->m_mountedFrom.startsWith("/"))
+ mp->m_device = KStandardDirs::realPath(mp->m_mountedFrom);
+ }
+
+ result.append(mp);
+
+ /* goto the next vmount structure: */
+ vm = (struct vmount *)((char *)vm + vm->vmt_length);
+ }
+
+ endvfsent( );
+ }
+
+ free( mntctl_buffer );
+#elif defined(Q_WS_WIN)
+ //TODO?
+#else
+ STRUCT_SETMNTENT mnttab;
+ if ((mnttab = SETMNTENT(MNTTAB, "r")) == 0)
+ return result;
+
+ STRUCT_MNTENT fe;
+ while (GETMNTENT(mnttab, fe))
+ {
+ KMountPoint *mp = new KMountPoint();
+ mp->m_mountedFrom = QFile::decodeName(FSNAME(fe));
+
+ mp->m_mountPoint = QFile::decodeName(MOUNTPOINT(fe));
+ mp->m_mountType = QFile::decodeName(MOUNTTYPE(fe));
+
+ //Devices using supermount have their device names in the mount options
+ //instead of the device field. That's why we need to read the mount options
+ if (infoNeeded & NeedMountOptions || (mp->m_mountType == "supermount"))
+ {
+ QString options = QFile::decodeName(MOUNTOPTIONS(fe));
+ mp->m_mountOptions = QStringList::split(',', options);
+ }
+
+ if (mp->m_mountType == "supermount")
+ mp->m_mountedFrom = devNameFromOptions(mp->m_mountOptions);
+
+ if (infoNeeded & NeedRealDeviceName)
+ {
+ if (mp->m_mountedFrom.startsWith("/"))
+ mp->m_device = KStandardDirs::realPath(mp->m_mountedFrom);
+ }
+ // TODO: Strip trailing '/' ?
+ result.append(mp);
+ }
+ ENDMNTENT(mnttab);
+#endif
+ return result;
+}
+
+QString KMountPoint::devNameFromOptions(const QStringList &options)
+{
+ // Search options to find the device name
+ for ( QStringList::ConstIterator it = options.begin(); it != options.end(); ++it)
+ {
+ if( (*it).startsWith("dev="))
+ return QString(*it).remove("dev=");
+ }
+ return QString("none");
+}