summaryrefslogtreecommitdiff
path: root/src/VBox/Main/linux/HostHardwareLinux.cpp
diff options
context:
space:
mode:
authorMichael Meskes <meskes@debian.org>2009-12-01 08:26:35 +0100
committerMichael Meskes <meskes@debian.org>2009-12-01 08:26:35 +0100
commit92d607e8349d0f1268b236b3bf4cb433179253f1 (patch)
tree6230e827557f7cd76ac792d43f4cc6a81be3b272 /src/VBox/Main/linux/HostHardwareLinux.cpp
parent541f51c4dab24f1decc1cb44888af9d45d619338 (diff)
downloadvirtualbox-92d607e8349d0f1268b236b3bf4cb433179253f1.tar.gz
Imported Upstream version 3.1.0-dfsgupstream/3.1.0-dfsg
Diffstat (limited to 'src/VBox/Main/linux/HostHardwareLinux.cpp')
-rw-r--r--src/VBox/Main/linux/HostHardwareLinux.cpp1708
1 files changed, 911 insertions, 797 deletions
diff --git a/src/VBox/Main/linux/HostHardwareLinux.cpp b/src/VBox/Main/linux/HostHardwareLinux.cpp
index d0dcdcd70..84ec5a428 100644
--- a/src/VBox/Main/linux/HostHardwareLinux.cpp
+++ b/src/VBox/Main/linux/HostHardwareLinux.cpp
@@ -1,4 +1,4 @@
-/* $Id: HostHardwareLinux.cpp $ */
+/* $Id: HostHardwareLinux.cpp 23973 2009-10-22 12:34:22Z vboxsync $ */
/** @file
* Classes for handling hardware detection under Linux. Please feel free to
* expand these to work for other systems (Solaris!) or to add new ones for
@@ -30,6 +30,9 @@
#include <HostHardwareLinux.h>
#include <VBox/log.h>
+# ifdef VBOX_WITH_DBUS
+# include <VBox/dbus.h>
+# endif
#include <iprt/dir.h>
#include <iprt/env.h>
@@ -44,51 +47,51 @@
# include <sys/types.h>
# include <sys/stat.h>
# include <unistd.h>
-# include <sys/ioctl.h>
# include <fcntl.h>
-# include <mntent.h>
/* bird: This is a hack to work around conflicts between these linux kernel headers
* and the GLIBC tcpip headers. They have different declarations of the 4
* standard byte order functions. */
// # define _LINUX_BYTEORDER_GENERIC_H
# define _LINUX_BYTEORDER_SWABB_H
# include <linux/cdrom.h>
-# ifdef VBOX_WITH_DBUS
-# include <vbox-dbus.h>
-# endif
+# include <linux/fd.h>
+# include <linux/major.h>
# include <errno.h>
# include <scsi/scsi.h>
-# include <scsi/sg.h>
# include <iprt/linux/sysfs.h>
#endif /* RT_OS_LINUX */
-#include <string>
#include <vector>
-/*******************************************************************************
-* Global Variables *
-*******************************************************************************/
-
-bool g_testHostHardwareLinux = false;
-static bool testing () { return g_testHostHardwareLinux; }
+/******************************************************************************
+* Global Variables *
+******************************************************************************/
+
+#ifdef TESTCASE
+static bool testing() { return true; }
+static bool fNoProbe = false;
+static bool noProbe() { return fNoProbe; }
+static void setNoProbe(bool val) { fNoProbe = val; }
+#else
+static bool testing() { return false; }
+static bool noProbe() { return false; }
+static void setNoProbe(bool val) { (void)val; }
+#endif
-/*******************************************************************************
-* Typedefs and Defines *
-*******************************************************************************/
+/******************************************************************************
+* Typedefs and Defines *
+******************************************************************************/
/** When waiting for hotplug events, we currently restart the wait after at
* most this many milliseconds. */
enum { DBUS_POLL_TIMEOUT = 2000 /* ms */ };
-
-static bool validateDevice(const char *deviceNode, bool isDVD);
-static int getDriveInfoFromEnv(const char *pszVar, DriveInfoList *pList,
+static int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList,
bool isDVD, bool *pfSuccess);
+static int getDriveInfoFromDev(DriveInfoList *pList, bool isDVD,
+ bool *pfSuccess);
static int getDriveInfoFromSysfs(DriveInfoList *pList, bool isDVD,
bool *pfSuccess);
-int scsiDoInquiry(const char *pszNode, uint8_t *pu8Type, char *pchVendor,
- size_t cchVendor, char *pchModel, size_t cchModel);
-static int getDVDInfoFromMTab(char *mountTable, DriveInfoList *pList);
#ifdef VBOX_WITH_DBUS
/* These must be extern to be usable in the RTMemAutoPtr template */
extern void VBoxHalShutdown (DBusConnection *pConnection);
@@ -106,7 +109,7 @@ static int halFindDeviceStringMatch (DBusConnection *pConnection,
static int halFindDeviceStringMatchVector (DBusConnection *pConnection,
const char *pszKey,
const char *pszValue,
- std::vector<std::string> *pMatches);
+ std::vector<iprt::MiniString> *pMatches);
*/
static int halGetPropertyStrings (DBusConnection *pConnection,
const char *pszUdi, size_t cKeys,
@@ -116,141 +119,902 @@ static int halGetPropertyStrings (DBusConnection *pConnection,
static int halGetPropertyStringsVector (DBusConnection *pConnection,
const char *pszUdi, size_t cProps,
const char **papszKeys,
- std::vector<std::string> *pMatches,
+ std::vector<iprt::MiniString> *pMatches,
bool *pfMatches, bool *pfSuccess);
*/
-static int getDriveInfoFromHal(DriveInfoList *pList, bool isDVD,
- bool *pfSuccess);
static int getUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess);
static int getOldUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess);
-static int getUSBInterfacesFromHal(std::vector <std::string> *pList,
+static int getUSBInterfacesFromHal(std::vector <iprt::MiniString> *pList,
const char *pcszUdi, bool *pfSuccess);
static DBusHandlerResult dbusFilterFunction (DBusConnection *pConnection,
DBusMessage *pMessage, void *pvUser);
#endif /* VBOX_WITH_DBUS */
+
/** Find the length of a string, ignoring trailing non-ascii or control
* characters */
-static size_t strLenStripped(const char *psz)
+static size_t strLenStripped(const char *pcsz)
{
size_t cch = 0;
- for (size_t i = 0; psz[i] != '\0'; ++i)
- if (psz[i] > 32 && psz[i] < 127)
+ for (size_t i = 0; pcsz[i] != '\0'; ++i)
+ if (pcsz[i] > 32 && pcsz[i] < 127)
cch = i;
return cch + 1;
}
+
+/**
+ * Get the name of a floppy drive according to the Linux floppy driver.
+ * @returns true on success, false if the name was not available (i.e. the
+ * device was not readible, or the file name wasn't a PC floppy
+ * device)
+ * @param pcszNode the path to the device node for the device
+ * @param Number the Linux floppy driver number for the drive. Required.
+ * @param pszName where to store the name retreived
+ */
+static bool floppyGetName(const char *pcszNode, unsigned Number,
+ floppy_drive_name pszName)
+{
+ AssertPtrReturn(pcszNode, false);
+ AssertPtrReturn(pszName, false);
+ AssertReturn(Number <= 7, false);
+ RTFILE File;
+ int rc = RTFileOpen(&File, pcszNode, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_NON_BLOCK);
+ if (RT_SUCCESS(rc))
+ {
+ int rcIoCtl;
+ /** @todo The next line can produce a warning, as the ioctl request
+ * field is defined as signed, but the Linux ioctl definition macros
+ * produce unsigned constants. */
+ rc = RTFileIoCtl(File, FDGETDRVTYP, pszName, 0, &rcIoCtl);
+ RTFileClose(File);
+ if (RT_SUCCESS(rc) && rcIoCtl >= 0)
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Create a UDI and a description for a floppy drive based on a number and the
+ * driver's name for it. We deliberately return an ugly sequence of
+ * characters as the description rather than an English language string to
+ * avoid translation issues.
+ *
+ * @returns true if we know the device to be valid, false otherwise
+ * @param pcszName the floppy driver name for the device (optional)
+ * @param Number the number of the floppy (0 to 3 on FDC 0, 4 to 7 on
+ * FDC 1)
+ * @param pszDesc where to store the device description (optional)
+ * @param cchDesc the size of the buffer in @a pszDesc
+ * @param pszUdi where to store the device UDI (optional)
+ * @param cchUdi the size of the buffer in @a pszUdi
+ */
+static void floppyCreateDeviceStrings(const floppy_drive_name pcszName,
+ unsigned Number, char *pszDesc,
+ size_t cchDesc, char *pszUdi,
+ size_t cchUdi)
+{
+ AssertPtrNullReturnVoid(pcszName);
+ AssertPtrNullReturnVoid(pszDesc);
+ AssertReturnVoid(!pszDesc || cchDesc > 0);
+ AssertPtrNullReturnVoid(pszUdi);
+ AssertReturnVoid(!pszUdi || cchUdi > 0);
+ AssertReturnVoid(Number <= 7);
+ if (pcszName)
+ {
+ const char *pcszSize;
+ switch(pcszName[0])
+ {
+ case 'd': case 'q': case 'h':
+ pcszSize = "5.25\"";
+ break;
+ case 'D': case 'H': case 'E': case 'u':
+ pcszSize = "3.5\"";
+ break;
+ default:
+ pcszSize = "(unknown)";
+ }
+ if (pszDesc)
+ RTStrPrintf(pszDesc, cchDesc, "%s %s K%s", pcszSize, &pcszName[1],
+ Number > 3 ? ", FDC 2" : "");
+ }
+ else
+ {
+ if (pszDesc)
+ RTStrPrintf(pszDesc, cchDesc, "FDD %d%s", (Number & 4) + 1,
+ Number > 3 ? ", FDC 2" : "");
+ }
+ if (pszUdi)
+ RTStrPrintf(pszUdi, cchUdi,
+ "/org/freedesktop/Hal/devices/platform_floppy_%u_storage",
+ Number);
+}
+
+
+/**
+ * Check whether a device number might correspond to a CD-ROM device according
+ * to Documentation/devices.txt in the Linux kernel source.
+ * @returns true if it might, false otherwise
+ * @param Number the device number (major and minor combination)
+ */
+static bool isCdromDevNum(dev_t Number)
+{
+ int major = major(Number);
+ int minor = minor(Number);
+ if ((major == IDE0_MAJOR) && !(minor & 0x3f))
+ return true;
+ if (major == SCSI_CDROM_MAJOR)
+ return true;
+ if (major == CDU31A_CDROM_MAJOR)
+ return true;
+ if (major == GOLDSTAR_CDROM_MAJOR)
+ return true;
+ if (major == OPTICS_CDROM_MAJOR)
+ return true;
+ if (major == SANYO_CDROM_MAJOR)
+ return true;
+ if (major == MITSUMI_X_CDROM_MAJOR)
+ return true;
+ if ((major == IDE1_MAJOR) && !(minor & 0x3f))
+ return true;
+ if (major == MITSUMI_CDROM_MAJOR)
+ return true;
+ if (major == CDU535_CDROM_MAJOR)
+ return true;
+ if (major == MATSUSHITA_CDROM_MAJOR)
+ return true;
+ if (major == MATSUSHITA_CDROM2_MAJOR)
+ return true;
+ if (major == MATSUSHITA_CDROM3_MAJOR)
+ return true;
+ if (major == MATSUSHITA_CDROM4_MAJOR)
+ return true;
+ if (major == AZTECH_CDROM_MAJOR)
+ return true;
+ if (major == 30 /* CM205_CDROM_MAJOR */) /* no #define for some reason */
+ return true;
+ if (major == CM206_CDROM_MAJOR)
+ return true;
+ if ((major == IDE3_MAJOR) && !(minor & 0x3f))
+ return true;
+ if (major == 46 /* Parallel port ATAPI CD-ROM */) /* no #define */
+ return true;
+ if ((major == IDE4_MAJOR) && !(minor & 0x3f))
+ return true;
+ if ((major == IDE5_MAJOR) && !(minor & 0x3f))
+ return true;
+ if ((major == IDE6_MAJOR) && !(minor & 0x3f))
+ return true;
+ if ((major == IDE7_MAJOR) && !(minor & 0x3f))
+ return true;
+ if ((major == IDE8_MAJOR) && !(minor & 0x3f))
+ return true;
+ if ((major == IDE9_MAJOR) && !(minor & 0x3f))
+ return true;
+ if (major == 113 /* VIOCD_MAJOR */)
+ return true;
+ return false;
+}
+
+
+/**
+ * Send an SCSI INQUIRY command to a device and return selected information.
+ * @returns iprt status code
+ * @returns VERR_TRY_AGAIN if the query failed but might succeed next time
+ * @param pcszNode the full path to the device node
+ * @param pu8Type where to store the SCSI device type on success (optional)
+ * @param pchVendor where to store the vendor id string on success (optional)
+ * @param cchVendor the size of the @a pchVendor buffer
+ * @param pchModel where to store the product id string on success (optional)
+ * @param cchModel the size of the @a pchModel buffer
+ * @note check documentation on the SCSI INQUIRY command and the Linux kernel
+ * SCSI headers included above if you want to understand what is going
+ * on in this method.
+ */
+static int cdromDoInquiry(const char *pcszNode, uint8_t *pu8Type,
+ char *pchVendor, size_t cchVendor, char *pchModel,
+ size_t cchModel)
+{
+ LogRelFlowFunc(("pcszNode=%s, pu8Type=%p, pchVendor=%p, cchVendor=%llu, pchModel=%p, cchModel=%llu\n",
+ pcszNode, pu8Type, pchVendor, cchVendor, pchModel,
+ cchModel));
+ AssertPtrReturn(pcszNode, VERR_INVALID_POINTER);
+ AssertPtrNullReturn(pu8Type, VERR_INVALID_POINTER);
+ AssertPtrNullReturn(pchVendor, VERR_INVALID_POINTER);
+ AssertPtrNullReturn(pchModel, VERR_INVALID_POINTER);
+
+ unsigned char u8Response[96] = { 0 };
+ struct cdrom_generic_command CdromCommandReq =
+ { { INQUIRY, 0, 0, 0, sizeof(u8Response), 0 } /* INQUIRY */ };
+ int rc, rcIoCtl = 0;
+ RTFILE file;
+ rc = RTFileOpen(&file, pcszNode, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_NON_BLOCK);
+ if (RT_SUCCESS(rc))
+ {
+ CdromCommandReq.buffer = u8Response;
+ CdromCommandReq.buflen = sizeof(u8Response);
+ CdromCommandReq.data_direction = CGC_DATA_READ;
+ CdromCommandReq.timeout = 5000; /* ms */
+ rc = RTFileIoCtl(file, CDROM_SEND_PACKET, &CdromCommandReq, 0,
+ &rcIoCtl);
+ if (RT_SUCCESS(rc) && rcIoCtl < 0)
+ rc = RTErrConvertFromErrno(-CdromCommandReq.stat);
+ RTFileClose(file);
+ }
+ if (RT_SUCCESS(rc))
+ {
+ if (pu8Type)
+ *pu8Type = u8Response[0] & 0x1f;
+ if (pchVendor)
+ RTStrPrintf(pchVendor, cchVendor, "%.8s",
+ (char *) &u8Response[8] /* vendor id string */);
+ if (pchModel)
+ RTStrPrintf(pchModel, cchModel, "%.16s",
+ (char *) &u8Response[16] /* product id string */);
+ }
+ LogRelFlowFunc(("returning %Rrc\n", rc));
+ if (RT_SUCCESS(rc))
+ LogRelFlowFunc((" type=%u, vendor=%.8s, product=%.16s\n",
+ u8Response[0] & 0x1f, (char *) &u8Response[8],
+ (char *) &u8Response[16]));
+ return rc;
+}
+
+
+/**
+ * Initialise the device strings (description and UDI) for a DVD drive based on
+ * vendor and model name strings.
+ * @param pcszVendor the vendor ID string
+ * @param pcszModel the product ID string
+ * @param pszDesc where to store the description string (optional)
+ * @param cchDesc the size of the buffer in @pszDesc
+ * @param pszUdi where to store the UDI string (optional)
+ * @param cchUdi the size of the buffer in @pszUdi
+ */
+/* static */
+void dvdCreateDeviceStrings(const char *pcszVendor, const char *pcszModel,
+ char *pszDesc, size_t cchDesc, char *pszUdi,
+ size_t cchUdi)
+{
+ AssertPtrReturnVoid(pcszVendor);
+ AssertPtrReturnVoid(pcszModel);
+ AssertPtrNullReturnVoid(pszDesc);
+ AssertReturnVoid(!pszDesc || cchDesc > 0);
+ AssertPtrNullReturnVoid(pszUdi);
+ AssertReturnVoid(!pszUdi || cchUdi > 0);
+ char szCleaned[128];
+ size_t cchVendor = strLenStripped(pcszVendor);
+ size_t cchModel = strLenStripped(pcszModel);
+
+ /* Create a cleaned version of the model string for the UDI string. */
+ for (unsigned i = 0; pcszModel[i] != '\0' && i < sizeof(szCleaned); ++i)
+ if ( (pcszModel[i] >= '0' && pcszModel[i] <= '9')
+ || (pcszModel[i] >= 'A' && pcszModel[i] <= 'z'))
+ szCleaned[i] = pcszModel[i];
+ else
+ szCleaned[i] = '_';
+ szCleaned[RT_MIN(cchModel, sizeof(szCleaned) - 1)] = '\0';
+
+ /* Construct the description string as "Vendor Product" */
+ if (pszDesc)
+ {
+ if (cchVendor > 0)
+ RTStrPrintf(pszDesc, cchDesc, "%.*s %s", cchVendor, pcszVendor,
+ cchModel > 0 ? pcszModel : "(unknown drive model)");
+ else
+ RTStrPrintf(pszDesc, cchDesc, "%s", pcszModel);
+ }
+ /* Construct the UDI string */
+ if (pszUdi)
+ {
+ if (cchModel > 0)
+ RTStrPrintf(pszUdi, cchUdi,
+ "/org/freedesktop/Hal/devices/storage_model_%s",
+ szCleaned);
+ else
+ pszUdi[0] = '\0';
+ }
+}
+
+
+/**
+ * Check whether a device node points to a valid device and create a UDI and
+ * a description for it, and store the device number, if it does.
+ * @returns true if the device is valid, false otherwise
+ * @param pcszNode the path to the device node
+ * @param isDVD are we looking for a DVD device (or a floppy device)?
+ * @param pDevice where to store the device node (optional)
+ * @param pszDesc where to store the device description (optional)
+ * @param cchDesc the size of the buffer in @a pszDesc
+ * @param pszUdi where to store the device UDI (optional)
+ * @param cchUdi the size of the buffer in @a pszUdi
+ */
+static bool devValidateDevice(const char *pcszNode, bool isDVD, dev_t *pDevice,
+ char *pszDesc, size_t cchDesc, char *pszUdi,
+ size_t cchUdi)
+{
+ AssertPtrReturn(pcszNode, false);
+ AssertPtrNullReturn(pDevice, false);
+ AssertPtrNullReturn(pszDesc, false);
+ AssertReturn(!pszDesc || cchDesc > 0, false);
+ AssertPtrNullReturn(pszUdi, false);
+ AssertReturn(!pszUdi || cchUdi > 0, false);
+ RTFSOBJINFO ObjInfo;
+ if (RT_FAILURE(RTPathQueryInfo(pcszNode, &ObjInfo, RTFSOBJATTRADD_UNIX)))
+ return false;
+ if (!RTFS_IS_DEV_BLOCK(ObjInfo.Attr.fMode))
+ return false;
+ if (pDevice)
+ *pDevice = ObjInfo.Attr.u.Unix.Device;
+ if (isDVD)
+ {
+ char szVendor[128], szModel[128];
+ uint8_t u8Type;
+ if (!isCdromDevNum(ObjInfo.Attr.u.Unix.Device))
+ return false;
+ if (RT_FAILURE(cdromDoInquiry(pcszNode, &u8Type,
+ szVendor, sizeof(szVendor),
+ szModel, sizeof(szModel))))
+ return false;
+ if (u8Type != TYPE_ROM)
+ return false;
+ dvdCreateDeviceStrings(szVendor, szModel, pszDesc, cchDesc,
+ pszUdi, cchUdi);
+ }
+ else
+ {
+ /* Floppies on Linux are legacy devices with hardcoded majors and
+ * minors */
+ unsigned Number;
+ floppy_drive_name szName;
+ if (major(ObjInfo.Attr.u.Unix.Device) != FLOPPY_MAJOR)
+ return false;
+ switch (minor(ObjInfo.Attr.u.Unix.Device))
+ {
+ case 0: case 1: case 2: case 3:
+ Number = minor(ObjInfo.Attr.u.Unix.Device);
+ break;
+ case 128: case 129: case 130: case 131:
+ Number = minor(ObjInfo.Attr.u.Unix.Device) - 128 + 4;
+ break;
+ default:
+ return false;
+ }
+ if (!floppyGetName(pcszNode, Number, szName))
+ return false;
+ floppyCreateDeviceStrings(szName, Number, pszDesc, cchDesc, pszUdi,
+ cchUdi);
+ }
+ return true;
+}
+
+
int VBoxMainDriveInfo::updateDVDs ()
{
- LogFlowThisFunc (("entered\n"));
+ LogFlowThisFunc(("entered\n"));
int rc = VINF_SUCCESS;
bool success = false; /* Have we succeeded in finding anything yet? */
try
{
mDVDList.clear ();
-#if defined(RT_OS_LINUX)
/* Always allow the user to override our auto-detection using an
* environment variable. */
- if (RT_SUCCESS (rc) && (!success || testing()))
+ if (RT_SUCCESS(rc) && (!success || testing()))
rc = getDriveInfoFromEnv ("VBOX_CDROM", &mDVDList, true /* isDVD */,
&success);
-#ifdef VBOX_WITH_DBUS
- if (RT_SUCCESS (rc) && RT_SUCCESS(VBoxLoadDBusLib()) && (!success || testing()))
- rc = getDriveInfoFromHal(&mDVDList, true /* isDVD */, &success);
-#endif /* VBOX_WITH_DBUS defined */
+ setNoProbe(false);
if (RT_SUCCESS(rc) && (!success | testing()))
rc = getDriveInfoFromSysfs(&mDVDList, true /* isDVD */, &success);
- /* On Linux without hal, the situation is much more complex. We will
- * take a heuristical approach. The general strategy is to try some
- * known device names and see of they exist. Failing that, we
- * enumerate the /etc/fstab file (luckily there's an API to parse it)
- * for CDROM devices. Ok, let's start! */
- if (RT_SUCCESS (rc) && (!success || testing()))
+ if (RT_SUCCESS(rc) && testing())
{
- // this is a good guess usually
- if (validateDevice("/dev/cdrom", true))
- try
- {
- mDVDList.push_back (DriveInfo ("/dev/cdrom"));
- }
- catch (std::bad_alloc)
- {
- rc = VERR_NO_MEMORY;
- }
-
- // check the mounted drives
- rc = getDVDInfoFromMTab((char*)"/etc/mtab", &mDVDList);
-
- // check the drives that can be mounted
- if (RT_SUCCESS (rc))
- rc = getDVDInfoFromMTab((char*)"/etc/fstab", &mDVDList);
+ setNoProbe(true);
+ rc = getDriveInfoFromSysfs(&mDVDList, true /* isDVD */, &success);
}
-#endif
+ /* Walk through the /dev subtree if nothing else has helped. */
+ if (RT_SUCCESS(rc) && (!success | testing()))
+ rc = getDriveInfoFromDev(&mDVDList, true /* isDVD */, &success);
}
- catch (std::bad_alloc)
+ catch(std::bad_alloc &e)
{
rc = VERR_NO_MEMORY;
}
- LogFlowThisFunc (("rc=%Rrc\n", rc));
+ LogFlowThisFunc(("rc=%Rrc\n", rc));
return rc;
}
int VBoxMainDriveInfo::updateFloppies ()
{
- LogFlowThisFunc (("entered\n"));
+ LogFlowThisFunc(("entered\n"));
int rc = VINF_SUCCESS;
bool success = false; /* Have we succeeded in finding anything yet? */
try
{
mFloppyList.clear ();
-#if defined(RT_OS_LINUX)
- if (RT_SUCCESS (rc) && (!success || testing()))
- rc = getDriveInfoFromEnv ("VBOX_FLOPPY", &mFloppyList, false /* isDVD */,
- &success);
-#ifdef VBOX_WITH_DBUS
- if ( RT_SUCCESS (rc)
- && RT_SUCCESS(VBoxLoadDBusLib())
- && (!success || testing()))
- rc = getDriveInfoFromHal(&mFloppyList, false /* isDVD */, &success);
-#endif /* VBOX_WITH_DBUS defined */
+ if (RT_SUCCESS(rc) && (!success || testing()))
+ rc = getDriveInfoFromEnv("VBOX_FLOPPY", &mFloppyList,
+ false /* isDVD */, &success);
+ setNoProbe(false);
if ( RT_SUCCESS(rc) && (!success || testing()))
+ rc = getDriveInfoFromSysfs(&mFloppyList, false /* isDVD */,
+ &success);
+ if (RT_SUCCESS(rc) && testing())
+ {
+ setNoProbe(true);
rc = getDriveInfoFromSysfs(&mFloppyList, false /* isDVD */, &success);
- /* As with the CDROMs, on Linux we have to take a multi-level approach
- * involving parsing the mount tables. As this is not bulletproof, we
- * give the user the chance to override the detection using an
- * environment variable, skiping the detection. */
+ }
+ /* Walk through the /dev subtree if nothing else has helped. */
+ if ( RT_SUCCESS(rc) && (!success || testing()))
+ rc = getDriveInfoFromDev(&mFloppyList, false /* isDVD */,
+ &success);
+ }
+ catch(std::bad_alloc &e)
+ {
+ rc = VERR_NO_MEMORY;
+ }
+ LogFlowThisFunc(("rc=%Rrc\n", rc));
+ return rc;
+}
+
- if (RT_SUCCESS (rc) && (!success || testing()))
+/**
+ * Extract the names of drives from an environment variable and add them to a
+ * list if they are valid.
+ * @returns iprt status code
+ * @param pcszVar the name of the environment variable. The variable
+ * value should be a list of device node names, separated
+ * by ':' characters.
+ * @param pList the list to append the drives found to
+ * @param isDVD are we looking for DVD drives or for floppies?
+ * @param pfSuccess this will be set to true if we found at least one drive
+ * and to false otherwise. Optional.
+ */
+/* static */
+int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList,
+ bool isDVD, bool *pfSuccess)
+{
+ AssertPtrReturn(pcszVar, VERR_INVALID_POINTER);
+ AssertPtrReturn(pList, VERR_INVALID_POINTER);
+ AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER);
+ LogFlowFunc(("pcszVar=%s, pList=%p, isDVD=%d, pfSuccess=%p\n", pcszVar,
+ pList, isDVD, pfSuccess));
+ int rc = VINF_SUCCESS;
+ bool success = false;
+
+ try
+ {
+ const char *pcszCurrent = RTEnvGet (pcszVar);
+ while (pcszCurrent && *pcszCurrent != '\0')
{
- // we assume that a floppy is always /dev/fd[x] with x from 0 to 7
- char devName[10];
- for (int i = 0; i <= 7; i++)
+ const char *pcszNext = strchr(pcszCurrent, ':');
+ char szPath[RTPATH_MAX], szReal[RTPATH_MAX];
+ char szDesc[256], szUdi[256];
+ if (pcszNext)
+ RTStrPrintf(szPath, sizeof(szPath), "%.*s",
+ pcszNext - pcszCurrent - 1, pcszCurrent);
+ else
+ RTStrPrintf(szPath, sizeof(szPath), "%s", pcszCurrent);
+ if ( RT_SUCCESS(RTPathReal(szPath, szReal, sizeof(szReal)))
+ && devValidateDevice(szReal, isDVD, NULL, szDesc,
+ sizeof(szDesc), szUdi, sizeof(szUdi)))
{
- RTStrPrintf(devName, sizeof(devName), "/dev/fd%d", i);
- if (validateDevice(devName, false))
- try
- {
- mFloppyList.push_back (DriveInfo (devName));
- }
- catch (std::bad_alloc)
- {
- rc = VERR_NO_MEMORY;
- }
+ pList->push_back(DriveInfo(szReal, szUdi, szDesc));
+ success = true;
}
+ pcszCurrent = pcszNext ? pcszNext + 1 : NULL;
}
-#endif
+ if (pfSuccess != NULL)
+ *pfSuccess = success;
+ }
+ catch(std::bad_alloc &e)
+ {
+ rc = VERR_NO_MEMORY;
+ }
+ LogFlowFunc (("rc=%Rrc, success=%d\n", rc, success));
+ return rc;
+}
+
+
+class sysfsBlockDev
+{
+public:
+ sysfsBlockDev(const char *pcszName, bool wantDVD)
+ : mpcszName(pcszName), mwantDVD(wantDVD), misConsistent(true),
+ misValid(false)
+ {
+ if (findDeviceNode())
+ {
+ if (mwantDVD)
+ validateAndInitForDVD();
+ else
+ validateAndInitForFloppy();
+ }
+ }
+private:
+ /** The name of the subdirectory of /sys/block for this device */
+ const char *mpcszName;
+ /** Are we looking for a floppy or a DVD device? */
+ bool mwantDVD;
+ /** The device node for the device */
+ char mszNode[RTPATH_MAX];
+ /** Does the sysfs entry look like we expect it too? This is a canary
+ * for future sysfs ABI changes. */
+ bool misConsistent;
+ /** Is this entry a valid specimen of what we are looking for? */
+ bool misValid;
+ /** Human readible drive description string */
+ char mszDesc[256];
+ /** Unique identifier for the drive. Should be identical to hal's UDI for
+ * the device. May not be unique for two identical drives. */
+ char mszUdi[256];
+private:
+ /* Private methods */
+
+ /**
+ * Fill in the device node member based on the /sys/block subdirectory.
+ * @returns boolean success value
+ */
+ bool findDeviceNode()
+ {
+ dev_t dev = RTLinuxSysFsReadDevNumFile("block/%s/dev", mpcszName);
+ if (dev == 0)
+ {
+ misConsistent = false;
+ return false;
+ }
+ if (RTLinuxFindDevicePath(dev, RTFS_TYPE_DEV_BLOCK, mszNode,
+ sizeof(mszNode), "%s", mpcszName) < 0)
+ return false;
+ return true;
+ }
+
+ /** Check whether the sysfs block entry is valid for a DVD device and
+ * initialise the string data members for the object. We try to get all
+ * the information we need from sysfs if possible, to avoid unnecessarily
+ * poking the device, and if that fails we fall back to an SCSI INQUIRY
+ * command. */
+ void validateAndInitForDVD()
+ {
+ char szVendor[128], szModel[128];
+ ssize_t cchVendor, cchModel;
+ int64_t type = RTLinuxSysFsReadIntFile(10, "block/%s/device/type",
+ mpcszName);
+ if (type >= 0 && type != TYPE_ROM)
+ return;
+ if (type == TYPE_ROM)
+ {
+ cchVendor = RTLinuxSysFsReadStrFile(szVendor, sizeof(szVendor),
+ "block/%s/device/vendor",
+ mpcszName);
+ if (cchVendor >= 0)
+ {
+ cchModel = RTLinuxSysFsReadStrFile(szModel, sizeof(szModel),
+ "block/%s/device/model",
+ mpcszName);
+ if (cchModel >= 0)
+ {
+ misValid = true;
+ dvdCreateDeviceStrings(szVendor, szModel,
+ mszDesc, sizeof(mszDesc),
+ mszUdi, sizeof(mszUdi));
+ return;
+ }
+ }
+ }
+ if (!noProbe())
+ probeAndInitForDVD();
+ }
+
+ /** Try to find out whether a device is a DVD drive by sending it an
+ * SCSI INQUIRY command. If it is, initialise the string and validity
+ * data members for the object based on the returned data.
+ */
+ void probeAndInitForDVD()
+ {
+ AssertReturnVoid(mszNode[0] != '\0');
+ uint8_t u8Type = 0;
+ char szVendor[128] = "";
+ char szModel[128] = "";
+ int rc = cdromDoInquiry(mszNode, &u8Type, szVendor,
+ sizeof(szVendor), szModel,
+ sizeof(szModel));
+ if (RT_SUCCESS(rc) && (u8Type == TYPE_ROM))
+ {
+ misValid = true;
+ dvdCreateDeviceStrings(szVendor, szModel, mszDesc, sizeof(mszDesc),
+ mszUdi, sizeof(mszUdi));
+ }
+ }
+
+ /** Check whether the sysfs block entry is valid for a floppy device and
+ * initialise the string data members for the object. Since we only
+ * support floppies using the basic "floppy" driver, we check the driver
+ * using the entry name and a driver-specific ioctl. */
+ void validateAndInitForFloppy()
+ {
+ bool haveName = false;
+ floppy_drive_name szName;
+ char szDriver[8];
+ if ( mpcszName[0] != 'f'
+ || mpcszName[1] != 'd'
+ || mpcszName[2] < '0'
+ || mpcszName[2] > '7'
+ || mpcszName[3] != '\0')
+ return;
+ if (!noProbe())
+ haveName = floppyGetName(mszNode, mpcszName[2] - '0', szName);
+ if (RTLinuxSysFsGetLinkDest(szDriver, sizeof(szDriver), "block/%s/%s",
+ mpcszName, "device/driver") >= 0)
+ {
+ if (RTStrCmp(szDriver, "floppy"))
+ return;
+ }
+ else if (!haveName)
+ return;
+ floppyCreateDeviceStrings(haveName ? szName : NULL,
+ mpcszName[2] - '0', mszDesc,
+ sizeof(mszDesc), mszUdi, sizeof(mszUdi));
+ misValid = true;
+ }
+
+public:
+ bool isConsistent()
+ {
+ return misConsistent;
+ }
+ bool isValid()
+ {
+ return misValid;
+ }
+ const char *getDesc()
+ {
+ return mszDesc;
+ }
+ const char *getUdi()
+ {
+ return mszUdi;
+ }
+ const char *getNode()
+ {
+ return mszNode;
+ }
+};
+
+/**
+ * Helper function to query the sysfs subsystem for information about DVD
+ * drives attached to the system.
+ * @returns iprt status code
+ * @param pList where to add information about the drives detected
+ * @param isDVD are we looking for DVDs or floppies?
+ * @param pfSuccess Did we find anything?
+ *
+ * @returns IPRT status code
+ */
+/* static */
+int getDriveInfoFromSysfs(DriveInfoList *pList, bool isDVD, bool *pfSuccess)
+{
+ AssertPtrReturn(pList, VERR_INVALID_POINTER);
+ AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER); /* Valid or Null */
+ LogFlowFunc (("pList=%p, isDVD=%u, pfSuccess=%p\n",
+ pList, (unsigned) isDVD, pfSuccess));
+ PRTDIR pDir = NULL;
+ RTDIRENTRY entry = {0};
+ int rc;
+ bool fSuccess = false;
+ unsigned cFound = 0;
+
+ if (!RTPathExists("/sys"))
+ return VINF_SUCCESS;
+ rc = RTDirOpen(&pDir, "/sys/block");
+ /* This might mean that sysfs semantics have changed */
+ AssertReturn(rc != VERR_FILE_NOT_FOUND, VINF_SUCCESS);
+ fSuccess = true;
+ if (RT_SUCCESS(rc))
+ while (true)
+ {
+ rc = RTDirRead(pDir, &entry, NULL);
+ Assert(rc != VERR_BUFFER_OVERFLOW); /* Should never happen... */
+ if (RT_FAILURE(rc)) /* Including overflow and no more files */
+ break;
+ if (entry.szName[0] == '.')
+ continue;
+ sysfsBlockDev dev(entry.szName, isDVD);
+ /* This might mean that sysfs semantics have changed */
+ AssertBreakStmt(dev.isConsistent(), fSuccess = false);
+ if (!dev.isValid())
+ continue;
+ try
+ {
+ pList->push_back(DriveInfo(dev.getNode(), dev.getUdi(),
+ dev.getDesc()));
+ }
+ catch(std::bad_alloc &e)
+ {
+ rc = VERR_NO_MEMORY;
+ break;
+ }
+ ++cFound;
+ }
+ RTDirClose(pDir);
+ if (rc == VERR_NO_MORE_FILES)
+ rc = VINF_SUCCESS;
+ if (RT_FAILURE(rc))
+ /* Clean up again */
+ for (unsigned i = 0; i < cFound; ++i)
+ pList->pop_back();
+ if (pfSuccess)
+ *pfSuccess = fSuccess;
+ LogFlow (("rc=%Rrc, fSuccess=%u\n", rc, (unsigned) fSuccess));
+ return rc;
+}
+
+
+/** Structure for holding information about a drive we have found */
+struct deviceNodeInfo
+{
+ /** The device number */
+ dev_t Device;
+ /** The device node path */
+ char szPath[RTPATH_MAX];
+ /** The device description */
+ char szDesc[256];
+ /** The device UDI */
+ char szUdi[256];
+};
+
+/** The maximum number of devices we will search for. */
+enum { MAX_DEVICE_NODES = 8 };
+/** An array of MAX_DEVICE_NODES devices */
+typedef struct deviceNodeInfo deviceNodeArray[MAX_DEVICE_NODES];
+
+/**
+ * Recursive worker function to walk the /dev tree looking for DVD or floppy
+ * devices.
+ * @returns true if we have already found MAX_DEVICE_NODES devices, false
+ * otherwise
+ * @param pszPath the path to start recursing. The function can modify
+ * this string at and after the terminating zero
+ * @param cchPath the size of the buffer (not the string!) in @a pszPath
+ * @param aDevices where to fill in information about devices that we have
+ * found
+ * @param wantDVD are we looking for DVD devices (or floppies)?
+ */
+static bool devFindDeviceRecursive(char *pszPath, size_t cchPath,
+ deviceNodeArray aDevices, bool wantDVD)
+{
+ /*
+ * Check assumptions made by the code below.
+ */
+ size_t const cchBasePath = strlen(pszPath);
+ AssertReturn(cchBasePath < RTPATH_MAX - 10U, false);
+ AssertReturn(pszPath[cchBasePath - 1] != '/', false);
+
+ PRTDIR pDir;
+ if (RT_FAILURE(RTDirOpen(&pDir, pszPath)))
+ return false;
+ for (;;)
+ {
+ RTDIRENTRY Entry;
+ RTFSOBJINFO ObjInfo;
+ int rc = RTDirRead(pDir, &Entry, NULL);
+ if (RT_FAILURE(rc))
+ break;
+ if (Entry.enmType == RTDIRENTRYTYPE_UNKNOWN)
+ {
+ if (RT_FAILURE(RTPathQueryInfo(pszPath, &ObjInfo,
+ RTFSOBJATTRADD_UNIX)))
+ continue;
+ if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
+ continue;
+ }
+
+ if (Entry.enmType == RTDIRENTRYTYPE_SYMLINK)
+ continue;
+ pszPath[cchBasePath] = '\0';
+ if (RT_FAILURE(RTPathAppend(pszPath, cchPath, Entry.szName)))
+ break;
+
+ /* Do the matching. */
+ dev_t DevNode;
+ char szDesc[256], szUdi[256];
+ if (!devValidateDevice(pszPath, wantDVD, &DevNode, szDesc,
+ sizeof(szDesc), szUdi, sizeof(szUdi)))
+ continue;
+ unsigned i;
+ for (i = 0; i < MAX_DEVICE_NODES; ++i)
+ if (!aDevices[i].Device || (aDevices[i].Device == DevNode))
+ break;
+ AssertBreak(i < MAX_DEVICE_NODES);
+ if (aDevices[i].Device)
+ continue;
+ aDevices[i].Device = DevNode;
+ RTStrPrintf(aDevices[i].szPath, sizeof(aDevices[i].szPath),
+ "%s", pszPath);
+ AssertCompile(sizeof(aDevices[i].szDesc) == sizeof(szDesc));
+ strcpy(aDevices[i].szDesc, szDesc);
+ AssertCompile(sizeof(aDevices[i].szUdi) == sizeof(szUdi));
+ strcpy(aDevices[i].szUdi, szUdi);
+ if (i == MAX_DEVICE_NODES - 1)
+ break;
+ continue;
+
+ /* Recurse into subdirectories. */
+ if ( (Entry.enmType == RTDIRENTRYTYPE_UNKNOWN)
+ && !RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
+ continue;
+ if (Entry.enmType != RTDIRENTRYTYPE_DIRECTORY)
+ continue;
+ if (Entry.szName[0] == '.')
+ continue;
+
+ if (devFindDeviceRecursive(pszPath, cchPath, aDevices, wantDVD))
+ break;
+ }
+ RTDirClose(pDir);
+ return aDevices[MAX_DEVICE_NODES - 1].Device ? true : false;
+}
+
+
+/**
+ * Recursively walk through the /dev tree and add any DVD or floppy drives we
+ * find and can access to our list. (If we can't access them we can't check
+ * whether or not they are really DVD or floppy drives).
+ * @note this is rather slow (a couple of seconds) for DVD probing on
+ * systems with a static /dev tree, as the current code tries to open
+ * any device node with a major/minor combination that could belong to
+ * a CD-ROM device, and opening a non-existent device can take a non.
+ * negligeable time on Linux. If it is ever necessary to improve this
+ * (static /dev trees are no longer very fashionable these days, and
+ * sysfs looks like it will be with us for a while), we could further
+ * reduce the number of device nodes we open by checking whether the
+ * driver is actually loaded in /proc/devices, and by counting the
+ * of currently attached SCSI CD-ROM devices in /proc/scsi/scsi (yes,
+ * there is a race, but it is probably not important for us).
+ * @returns iprt status code
+ * @param pList the list to append the drives found to
+ * @param isDVD are we looking for DVD drives or for floppies?
+ * @param pfSuccess this will be set to true if we found at least one drive
+ * and to false otherwise. Optional.
+ */
+/* static */
+int getDriveInfoFromDev(DriveInfoList *pList, bool isDVD, bool *pfSuccess)
+{
+ AssertPtrReturn(pList, VERR_INVALID_POINTER);
+ AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER);
+ LogFlowFunc(("pList=%p, isDVD=%d, pfSuccess=%p\n", pList, isDVD,
+ pfSuccess));
+ int rc = VINF_SUCCESS;
+ bool success = false;
+
+ deviceNodeArray aDevices = { { 0 } };
+ char szPath[RTPATH_MAX] = "/dev";
+ devFindDeviceRecursive(szPath, sizeof(szPath), aDevices, isDVD);
+ try
+ {
+ for (unsigned i = 0; i < MAX_DEVICE_NODES; ++i)
+ {
+ if (aDevices[i].Device)
+ {
+ pList->push_back(DriveInfo(aDevices[i].szPath,
+ aDevices[i].szUdi, aDevices[i].szDesc));
+ success = true;
+ }
+ }
+ if (pfSuccess != NULL)
+ *pfSuccess = success;
}
- catch (std::bad_alloc)
+ catch(std::bad_alloc &e)
{
rc = VERR_NO_MEMORY;
}
- LogFlowThisFunc (("rc=%Rrc\n", rc));
+ LogFlowFunc (("rc=%Rrc, success=%d\n", rc, success));
return rc;
}
+
int VBoxMainUSBDeviceInfo::UpdateDevices ()
{
- LogFlowThisFunc (("entered\n"));
+ LogFlowThisFunc(("entered\n"));
int rc = VINF_SUCCESS;
bool success = false; /* Have we succeeded in finding anything yet? */
try
@@ -259,24 +1023,24 @@ int VBoxMainUSBDeviceInfo::UpdateDevices ()
mDeviceList.clear();
#if defined(RT_OS_LINUX)
#ifdef VBOX_WITH_DBUS
- if ( RT_SUCCESS (rc)
- && RT_SUCCESS(VBoxLoadDBusLib())
+ if ( RT_SUCCESS(rc)
+ && RT_SUCCESS(RTDBusLoadLib())
&& (!success || testing()))
rc = getUSBDeviceInfoFromHal(&mDeviceList, &halSuccess);
/* Try the old API if the new one *succeeded* as only one of them will
* pick up devices anyway. */
- if (RT_SUCCESS (rc) && halSuccess && (!success || testing()))
+ if (RT_SUCCESS(rc) && halSuccess && (!success || testing()))
rc = getOldUSBDeviceInfoFromHal(&mDeviceList, &halSuccess);
if (!success)
success = halSuccess;
#endif /* VBOX_WITH_DBUS defined */
#endif /* RT_OS_LINUX */
}
- catch (std::bad_alloc)
+ catch(std::bad_alloc &e)
{
rc = VERR_NO_MEMORY;
}
- LogFlowThisFunc (("rc=%Rrc\n", rc));
+ LogFlowThisFunc(("rc=%Rrc\n", rc));
return rc;
}
@@ -305,7 +1069,7 @@ VBoxMainHotplugWaiter::VBoxMainHotplugWaiter ()
int rc = VINF_SUCCESS;
mContext = new Context;
- if (RT_SUCCESS(VBoxLoadDBusLib()))
+ if (RT_SUCCESS(RTDBusLoadLib()))
{
for (unsigned i = 0; RT_SUCCESS(rc) && i < 5 && !mContext->mConnection; ++i)
{
@@ -314,15 +1078,15 @@ VBoxMainHotplugWaiter::VBoxMainHotplugWaiter ()
if (!mContext->mConnection)
rc = VERR_NOT_SUPPORTED;
DBusMessage *pMessage;
- while ( RT_SUCCESS (rc)
+ while ( RT_SUCCESS(rc)
&& (pMessage = dbus_connection_pop_message (mContext->mConnection.get())) != NULL)
dbus_message_unref (pMessage); /* empty the message queue. */
- if ( RT_SUCCESS (rc)
+ if ( RT_SUCCESS(rc)
&& !dbus_connection_add_filter (mContext->mConnection.get(),
dbusFilterFunction,
(void *) &mContext->mTriggered, NULL))
rc = VERR_NO_MEMORY;
- if (RT_FAILURE (rc))
+ if (RT_FAILURE(rc))
mContext->mConnection.reset();
}
#endif /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */
@@ -356,7 +1120,7 @@ int VBoxMainHotplugWaiter::Wait(unsigned cMillies)
cRealMillies = cMillies;
else
cRealMillies = DBUS_POLL_TIMEOUT;
- while ( RT_SUCCESS (rc) && connected && !mContext->mTriggered
+ while ( RT_SUCCESS(rc) && connected && !mContext->mTriggered
&& !mContext->mInterrupt)
{
connected = dbus_connection_read_write_dispatch (mContext->mConnection.get(),
@@ -383,226 +1147,6 @@ void VBoxMainHotplugWaiter::Interrupt()
#endif /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */
}
-#ifdef RT_OS_LINUX
-/**
- * Helper function to check whether the given device node is a valid drive
- */
-/* static */
-bool validateDevice(const char *deviceNode, bool isDVD)
-{
- AssertReturn(VALID_PTR (deviceNode), VERR_INVALID_POINTER);
- LogFlowFunc (("deviceNode=%s, isDVD=%d\n", deviceNode, isDVD));
- struct stat statInfo;
- bool retValue = false;
-
- // sanity check
- if (!deviceNode)
- {
- return false;
- }
-
- // first a simple stat() call
- if (stat(deviceNode, &statInfo) < 0)
- {
- return false;
- } else
- {
- if (isDVD)
- {
- if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
- {
- int fileHandle;
- // now try to open the device
- fileHandle = open(deviceNode, O_RDONLY | O_NONBLOCK, 0);
- if (fileHandle >= 0)
- {
- cdrom_subchnl cdChannelInfo;
- cdChannelInfo.cdsc_format = CDROM_MSF;
- // this call will finally reveal the whole truth
-#ifdef RT_OS_LINUX
- if ((ioctl(fileHandle, CDROMSUBCHNL, &cdChannelInfo) == 0) ||
- (errno == EIO) || (errno == ENOENT) ||
- (errno == EINVAL) || (errno == ENOMEDIUM))
-#endif
- {
- retValue = true;
- }
- close(fileHandle);
- }
- }
- } else
- {
- // floppy case
- if (S_ISCHR(statInfo.st_mode) || S_ISBLK(statInfo.st_mode))
- {
- /// @todo do some more testing, maybe a nice IOCTL!
- retValue = true;
- }
- }
- }
- LogFlowFunc (("retValue=%d\n", retValue));
- return retValue;
-}
-#else /* !RT_OS_LINUX */
-# error Port me! Copying code over from HostImpl.cpp should be most of the job though.
-#endif /* !RT_OS_LINUX */
-
-/**
- * Extract the names of drives from an environment variable and add them to a
- * list if they are valid.
- * @returns iprt status code
- * @param pszVar the name of the environment variable. The variable
- * value should be a list of device node names, separated
- * by ':' characters.
- * @param pList the list to append the drives found to
- * @param isDVD are we looking for DVD drives or for floppies?
- * @param pfSuccess this will be set to true if we found at least one drive
- * and to false otherwise. Optional.
- */
-/* static */
-int getDriveInfoFromEnv(const char *pszVar, DriveInfoList *pList,
- bool isDVD, bool *pfSuccess)
-{
- AssertReturn( VALID_PTR (pszVar) && VALID_PTR (pList)
- && (pfSuccess == NULL || VALID_PTR (pfSuccess)),
- VERR_INVALID_POINTER);
- LogFlowFunc (("pszVar=%s, pList=%p, isDVD=%d, pfSuccess=%p\n", pszVar,
- pList, isDVD, pfSuccess));
- int rc = VINF_SUCCESS;
- bool success = false;
- RTMemAutoPtr<char, RTStrFree> drive;
- const char *pszValue = RTEnvGet (pszVar);
- if (pszValue != NULL)
- {
- drive = RTStrDup (pszValue);
- if (!drive)
- rc = VERR_NO_MEMORY;
- }
- if (pszValue != NULL && RT_SUCCESS (rc))
- {
- char *pDrive = drive.get();
- char *pDriveNext = strchr (pDrive, ':');
- while (pDrive != NULL && *pDrive != '\0')
- {
- if (pDriveNext != NULL)
- *pDriveNext = '\0';
- if (validateDevice(pDrive, isDVD))
- {
- try
- {
- pList->push_back (DriveInfo (pDrive));
- }
- catch (std::bad_alloc)
- {
- rc = VERR_NO_MEMORY;
- }
- success = true;
- }
- if (pDriveNext != NULL)
- {
- pDrive = pDriveNext + 1;
- pDriveNext = strchr (pDrive, ':');
- }
- else
- pDrive = NULL;
- }
- }
- if (pfSuccess != NULL)
- *pfSuccess = success;
- LogFlowFunc (("rc=%Rrc, success=%d\n", rc, success));
- return rc;
-}
-
-#ifdef RT_OS_LINUX
-/**
- * Helper function to parse the given mount file and add found entries
- */
-/* static */
-int getDVDInfoFromMTab(char *mountTable, DriveInfoList *pList)
-{
- AssertReturn(VALID_PTR (mountTable) && VALID_PTR (pList),
- VERR_INVALID_POINTER);
-#ifdef RT_OS_LINUX
- LogFlowFunc (("mountTable=%s, pList=%p\n", mountTable, pList));
- int rc = VINF_SUCCESS;
- FILE *mtab = setmntent(mountTable, "r");
- if (mtab)
- {
- struct mntent *mntent;
- RTMemAutoPtr <char, RTStrFree> mnt_type, mnt_dev;
- char *tmp;
- while (RT_SUCCESS (rc) && (mntent = getmntent(mtab)))
- {
- mnt_type = RTStrDup (mntent->mnt_type);
- mnt_dev = RTStrDup (mntent->mnt_fsname);
- if (!mnt_type || !mnt_dev)
- rc = VERR_NO_MEMORY;
- // supermount fs case
- if (RT_SUCCESS (rc) && strcmp(mnt_type.get(), "supermount") == 0)
- {
- tmp = strstr(mntent->mnt_opts, "fs=");
- if (tmp)
- {
- mnt_type = RTStrDup(tmp + strlen("fs="));
- if (!mnt_type)
- rc = VERR_NO_MEMORY;
- else
- {
- tmp = strchr(mnt_type.get(), ',');
- if (tmp)
- *tmp = '\0';
- }
- }
- tmp = strstr(mntent->mnt_opts, "dev=");
- if (tmp)
- {
- mnt_dev = RTStrDup(tmp + strlen("dev="));
- if (!mnt_dev)
- rc = VERR_NO_MEMORY;
- else
- {
- tmp = strchr(mnt_dev.get(), ',');
- if (tmp)
- *tmp = '\0';
- }
- }
- }
- // use strstr here to cover things fs types like "udf,iso9660"
- if (RT_SUCCESS (rc) && strstr(mnt_type.get(), "iso9660") == 0)
- {
- if (validateDevice(mnt_dev.get(), true))
- {
- bool insert = true;
- struct stat srcInfo;
- if (stat (mnt_dev.get(), &srcInfo) < 0)
- insert = false;
- for (DriveInfoList::const_iterator it = pList->begin();
- insert && it != pList->end(); ++it)
- {
- struct stat destInfo;
- if ( (stat (it->mDevice.c_str(), &destInfo) == 0)
- && (srcInfo.st_rdev == destInfo.st_rdev))
- insert = false;
- }
- if (insert)
- try
- {
- pList->push_back (DriveInfo (mnt_dev.get()));
- }
- catch (std::bad_alloc)
- {
- rc = VERR_NO_MEMORY;
- }
- }
- }
- }
- endmntent(mtab);
- }
- return rc;
-#endif
-}
-
-#endif /* RT_OS_LINUX */
#if defined(RT_OS_LINUX) && defined(VBOX_WITH_DBUS)
/** Wrapper class around DBusError for automatic cleanup */
@@ -622,10 +1166,10 @@ public:
Assert ((mError.name == NULL) == (mError.message == NULL));
return (mError.name != NULL);
}
- bool HasName (const char *pszName)
+ bool HasName (const char *pcszName)
{
Assert ((mError.name == NULL) == (mError.message == NULL));
- return (RTStrCmp (mError.name, pszName) == 0);
+ return (RTStrCmp (mError.name, pcszName) == 0);
}
void FlowLog ()
{
@@ -826,7 +1370,7 @@ int halFindDeviceStringMatch (DBusConnection *pConnection, const char *pszKey,
autoDBusError dbusError;
RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply;
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
{
message = dbus_message_new_method_call ("org.freedesktop.Hal",
"/org/freedesktop/Hal/Manager",
@@ -835,7 +1379,7 @@ int halFindDeviceStringMatch (DBusConnection *pConnection, const char *pszKey,
if (!message)
rc = VERR_NO_MEMORY;
}
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
{
DBusMessageIter iterAppend;
dbus_message_iter_init_append (message.get(), &iterAppend);
@@ -855,27 +1399,27 @@ int halFindDeviceStringMatch (DBusConnection *pConnection, const char *pszKey,
/**
* Find the UDIs of hal entries that contain Key=Value property and return the
- * result on the end of a vector of std::string.
+ * result on the end of a vector of iprt::MiniString.
* @returns iprt status code. If a non-fatal error occurs, we return success
* but set *pfSuccess to false.
* @param pConnection an initialised connection DBus
* @param pszKey the property key
* @param pszValue the property value
- * @param pMatches pointer to an array of std::string to append the
+ * @param pMatches pointer to an array of iprt::MiniString to append the
* results to. NOT optional.
* @param pfSuccess will be set to true if the operation succeeds
*/
/* static */
int halFindDeviceStringMatchVector (DBusConnection *pConnection,
const char *pszKey, const char *pszValue,
- std::vector<std::string> *pMatches,
+ std::vector<iprt::MiniString> *pMatches,
bool *pfSuccess)
{
AssertPtrReturn (pConnection, VERR_INVALID_POINTER);
AssertPtrReturn (pszKey, VERR_INVALID_POINTER);
AssertPtrReturn (pszValue, VERR_INVALID_POINTER);
AssertPtrReturn (pMatches, VERR_INVALID_POINTER);
- AssertReturn (pfSuccess == NULL || VALID_PTR (pfSuccess), VERR_INVALID_POINTER);
+ AssertReturn(pfSuccess == NULL || VALID_PTR (pfSuccess), VERR_INVALID_POINTER);
LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, pMatches=%p, pfSuccess=%p\n",
pConnection, pszKey, pszValue, pMatches, pfSuccess));
int rc = VINF_SUCCESS; /* We set this to failure on fatal errors. */
@@ -884,22 +1428,22 @@ int halFindDeviceStringMatchVector (DBusConnection *pConnection,
RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, replyFind;
DBusMessageIter iterFind, iterUdis;
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
{
rc = halFindDeviceStringMatch (pConnection, pszKey, pszValue,
&replyFind);
if (!replyFind)
halSuccess = false;
}
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
{
dbus_message_iter_init (replyFind.get(), &iterFind);
if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
halSuccess = false;
}
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
dbus_message_iter_recurse (&iterFind, &iterUdis);
- for (; halSuccess && RT_SUCCESS (rc)
+ for (; halSuccess && RT_SUCCESS(rc)
&& dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING;
dbus_message_iter_next(&iterUdis))
{
@@ -910,7 +1454,7 @@ int halFindDeviceStringMatchVector (DBusConnection *pConnection,
{
pMatches->push_back(pszUdi);
}
- catch (std::bad_alloc)
+ catch(std::bad_alloc &e)
{
rc = VERR_NO_MEMORY;
}
@@ -969,7 +1513,7 @@ int halGetPropertyStrings (DBusConnection *pConnection, const char *pszUdi,
"GetAllProperties");
if (!message)
rc = VERR_NO_MEMORY;
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
{
reply = dbus_connection_send_with_reply_and_block (pConnection,
message.get(), -1,
@@ -979,17 +1523,17 @@ int halGetPropertyStrings (DBusConnection *pConnection, const char *pszUdi,
}
/* Parse the reply */
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
{
dbus_message_iter_init (reply.get(), &iterGet);
if ( dbus_message_iter_get_arg_type (&iterGet) != DBUS_TYPE_ARRAY
&& dbus_message_iter_get_element_type (&iterGet) != DBUS_TYPE_DICT_ENTRY)
halSuccess = false;
}
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
dbus_message_iter_recurse (&iterGet, &iterProps);
/* Go through all entries in the reply and see if any match our keys. */
- while ( halSuccess && RT_SUCCESS (rc)
+ while ( halSuccess && RT_SUCCESS(rc)
&& dbus_message_iter_get_arg_type (&iterProps)
== DBUS_TYPE_DICT_ENTRY)
{
@@ -1008,7 +1552,7 @@ int halGetPropertyStrings (DBusConnection *pConnection, const char *pszUdi,
}
dbus_message_iter_next (&iterProps);
}
- if (RT_SUCCESS (rc) && halSuccess)
+ if (RT_SUCCESS(rc) && halSuccess)
*pMessage = reply.release();
if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
rc = VERR_NO_MEMORY;
@@ -1026,7 +1570,7 @@ int halGetPropertyStrings (DBusConnection *pConnection, const char *pszUdi,
* @param pszUdi the Udi of the device
* @param cProps the number of property values to look up
* @param papszKeys the keys of the properties to be looked up
- * @param pMatches pointer to an empty array of std::string to append the
+ * @param pMatches pointer to an empty array of iprt::MiniString to append the
* results to. NOT optional.
* @param pfMatches pointer to an array of boolean values indicating
* whether the respective property is a string. If this
@@ -1038,15 +1582,15 @@ int halGetPropertyStrings (DBusConnection *pConnection, const char *pszUdi,
int halGetPropertyStringsVector (DBusConnection *pConnection,
const char *pszUdi, size_t cProps,
const char **papszKeys,
- std::vector<std::string> *pMatches,
+ std::vector<iprt::MiniString> *pMatches,
bool *pfMatches, bool *pfSuccess)
{
AssertPtrReturn (pConnection, VERR_INVALID_POINTER);
AssertPtrReturn (pszUdi, VERR_INVALID_POINTER);
AssertPtrReturn (papszKeys, VERR_INVALID_POINTER);
AssertPtrReturn (pMatches, VERR_INVALID_POINTER);
- AssertReturn ((pfMatches == NULL) || VALID_PTR (pfMatches), VERR_INVALID_POINTER);
- AssertReturn ((pfSuccess == NULL) || VALID_PTR (pfSuccess), VERR_INVALID_POINTER);
+ AssertReturn((pfMatches == NULL) || VALID_PTR (pfMatches), VERR_INVALID_POINTER);
+ AssertReturn((pfSuccess == NULL) || VALID_PTR (pfSuccess), VERR_INVALID_POINTER);
AssertReturn(pMatches->empty(), VERR_INVALID_PARAMETER);
LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, pMatches=%p, pfMatches=%p, pfSuccess=%p\n",
pConnection, pszUdi, cProps, papszKeys, pMatches, pfMatches, pfSuccess));
@@ -1068,7 +1612,7 @@ int halGetPropertyStringsVector (DBusConnection *pConnection,
{
pMatches->push_back(fMatches ? values[i] : "");
}
- catch (std::bad_alloc)
+ catch(std::bad_alloc &e)
{
rc = VERR_NO_MEMORY;
}
@@ -1085,437 +1629,7 @@ int halGetPropertyStringsVector (DBusConnection *pConnection,
LogFlowFunc (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
return rc;
}
-#endif /* RT_OS_LINUX && VBOX_WITH_DBUS */
-
-/**
- * Send an SCSI INQUIRY command to a device and return selected information.
- * @returns iprt status code
- * @returns VERR_TRY_AGAIN if the query failed but might succeed next time
- * @param pszNode the full path to the device node
- * @param pu8Type where to store the SCSI device type on success (optional)
- * @param pchVendor where to store the vendor id string on success (optional)
- * @param cchVendor the size of the @a pchVendor buffer
- * @param pchModel where to store the product id string on success (optional)
- * @param cchModel the size of the @a pchModel buffer
- * @note check documentation on the SCSI INQUIRY command and the Linux kernel
- * SCSI headers included above if you want to understand what is going
- * on in this method.
- */
-/* static */
-int scsiDoInquiry(const char *pszNode, uint8_t *pu8Type, char *pchVendor,
- size_t cchVendor, char *pchModel, size_t cchModel)
-{
- LogRelFlowFunc(("pszNode=%s, pu8Type=%p, pchVendor=%p, cchVendor=%llu, pchModel=%p, cchModel=%llu\n",
- pszNode, pu8Type, pchVendor, cchVendor, pchModel,
- cchModel));
- AssertPtrReturn(pszNode, VERR_INVALID_POINTER);
- AssertPtrNullReturn(pu8Type, VERR_INVALID_POINTER);
- AssertPtrNullReturn(pchVendor, VERR_INVALID_POINTER);
- AssertPtrNullReturn(pchModel, VERR_INVALID_POINTER);
- sg_io_hdr_t ScsiIoReq = {0};
- unsigned char u8Response[96] = { 0 };
- unsigned char u8Command[6] =
- { INQUIRY, 0, 0, 0, sizeof(u8Response), 0 }; /* INQUIRY */
- int rc, rcIoCtl = 0;
- RTFILE file;
- rc = RTFileOpen(&file, pszNode, RTFILE_O_READ);
- if (RT_SUCCESS(rc))
- {
- ScsiIoReq.interface_id = 'S';
- ScsiIoReq.dxfer_direction = SG_DXFER_FROM_DEV;
- ScsiIoReq.cmd_len = sizeof(u8Command);
- ScsiIoReq.dxfer_len = sizeof(u8Response);
- ScsiIoReq.dxferp = u8Response;
- ScsiIoReq.cmdp = u8Command;
- ScsiIoReq.timeout = 5000 /* ms */;
- rc = RTFileIoCtl(file, SG_IO, &ScsiIoReq, 0, &rcIoCtl);
- if (RT_SUCCESS(rc) && rcIoCtl < 0)
- rc = VERR_NOT_SUPPORTED;
- RTFileClose(file);
- }
- if (RT_SUCCESS(rc))
- {
- if ( (ScsiIoReq.status >> 1 == GOOD)
- || (ScsiIoReq.status >> 1 == INTERMEDIATE_GOOD)
- || (ScsiIoReq.status >> 1 == INTERMEDIATE_C_GOOD)
- || (ScsiIoReq.status >> 1 == COMMAND_TERMINATED))
- {
- if (pu8Type)
- *pu8Type = u8Response[0] & 0x1f;
- if (pchVendor)
- RTStrPrintf(pchVendor, cchVendor, "%.8s",
- (char *) &u8Response[8] /* vendor id string */);
- if (pchModel)
- RTStrPrintf(pchModel, cchModel, "%.16s",
- (char *) &u8Response[16] /* product id string */);
- }
- else if ( ScsiIoReq.status >> 1 != BUSY
- && ScsiIoReq.status >> 1 != QUEUE_FULL
- && ScsiIoReq.status >> 1 != CHECK_CONDITION)
- rc = VERR_DEV_IO_ERROR; /* Actually, these should never happen */
- else
- rc = VERR_TRY_AGAIN;
- }
- LogRelFlowFunc(("returning %Rrc\n", rc));
- if (RT_SUCCESS(rc))
- LogRelFlowFunc((" type=%u, vendor=%.8s, product=%.16s\n",
- u8Response[0] & 0x1f, (char *) &u8Response[8],
- (char *) &u8Response[16]));
- return rc;
-}
-
-class sysfsBlockDev
-{
-public:
- sysfsBlockDev(const char *pcszName, bool wantDVD)
- : mpcszName(pcszName), mwantDVD(wantDVD), misValid(false)
- {
- if (findDeviceNode())
- {
- if (mwantDVD)
- validateAndInitForDVD();
- else
- validateAndInitForFloppy();
- }
- }
-private:
- /** The name of the subdirectory of /sys/block for this device */
- const char *mpcszName;
- /** Are we looking for a floppy or a DVD device? */
- bool mwantDVD;
- /** The device node for the device */
- char mszNode[RTPATH_MAX];
- /** Is this entry a valid specimen of what we are looking for? */
- bool misValid;
- /** Human readible drive description string */
- char mszDesc[256];
- /** Unique identifier for the drive. Should be identical to hal's UDI for
- * the device. May not be unique for two identical drives. */
- char mszUdi[256];
-private:
- /* Private methods */
-
- /**
- * Fill in the device node member based on the /sys/block subdirectory.
- * @returns boolean success value
- */
- bool findDeviceNode()
- {
- dev_t dev = RTLinuxSysFsReadDevNumFile("block/%s/dev", mpcszName);
- if (dev == 0)
- return false;
- if (RTLinuxFindDevicePath(dev, RTFS_TYPE_DEV_BLOCK, mszNode,
- sizeof(mszNode), "%s", mpcszName) < 0)
- return false;
- return true;
- }
-
- /** Check whether the sysfs block entry is valid for a DVD device and
- * initialise the string data members for the object. We try to get all
- * the information we need from sysfs if possible, to avoid unnecessarily
- * poking the device, and if that fails we fall back to an SCSI INQUIRY
- * command. */
- void validateAndInitForDVD()
- {
- char szVendor[128], szModel[128];
- ssize_t cchVendor, cchModel;
- int64_t type = RTLinuxSysFsReadIntFile(10, "block/%s/device/type",
- mpcszName);
- if (type >= 0 && type != TYPE_ROM)
- return;
- if (type == 5)
- {
- cchVendor = RTLinuxSysFsReadStrFile(szVendor, sizeof(szVendor),
- "block/%s/device/vendor",
- mpcszName);
- if (cchVendor >= 0)
- {
- cchModel = RTLinuxSysFsReadStrFile(szModel, sizeof(szModel),
- "block/%s/device/model",
- mpcszName);
- if (cchModel >= 0)
- {
- misValid = true;
- setDeviceStrings(szVendor, szModel);
- return;
- }
- }
- }
- probeAndInitForDVD();
- }
-
- /** Try to find out whether a device is a DVD drive by sending it an
- * SCSI INQUIRY command. If it is, initialise the string and validity
- * data members for the object based on the returned data.
- */
- void probeAndInitForDVD()
- {
- AssertReturnVoid(mszNode[0] != '\0');
- uint8_t u8Type = 0;
- char szVendor[128] = "";
- char szModel[128] = "";
- for (unsigned i = 0; i < 5; ++i) /* Give the device five chances */
- {
- int rc = scsiDoInquiry(mszNode, &u8Type, szVendor,
- sizeof(szVendor), szModel,
- sizeof(szModel));
- if (RT_SUCCESS(rc))
- {
- if (u8Type != TYPE_ROM)
- return;
- misValid = true;
- setDeviceStrings(szVendor, szModel);
- return;
- }
- if (rc != VERR_TRY_AGAIN)
- return;
- RTThreadSleep(100); /* wait a little before retrying */
- }
- }
-
- /**
- * Initialise the object device strings (description and UDI) based on
- * vendor and model name strings.
- * @param pszVendor the vendor ID string
- * @param pszModel the product ID string
- */
- void setDeviceStrings(const char *pszVendor, const char *pszModel)
- {
- char szCleaned[128];
- size_t cchVendor = strLenStripped(pszVendor);
- size_t cchModel = strLenStripped(pszModel);
-
- /* Create a cleaned version of the model string for the UDI string. */
- for (unsigned i = 0; pszModel[i] != '\0' && i < sizeof(szCleaned); ++i)
- if ( (pszModel[i] >= '0' && pszModel[i] <= '9')
- || (pszModel[i] >= 'A' && pszModel[i] <= 'z'))
- szCleaned[i] = pszModel[i];
- else
- szCleaned[i] = '_';
- szCleaned[RT_MIN(cchModel, sizeof(szCleaned) - 1)] = '\0';
-
- /* Construct the description string as "Vendor Product" */
- if (cchVendor > 0)
- RTStrPrintf(mszDesc, sizeof(mszDesc), "%.*s %s", cchVendor,
- pszVendor,
- cchModel > 0 ? pszModel : "(unknown drive model)");
- else
- RTStrPrintf(mszDesc, sizeof(mszDesc), "%s", pszModel);
- /* Construct the UDI string */
- if (cchModel)
- RTStrPrintf(mszUdi, sizeof(mszUdi),
- "/org/freedesktop/Hal/devices/storage_model_%s",
- szCleaned);
- else
- mszUdi[0] = '\0';
- }
-
- /** Check whether the sysfs block entry is valid for a floppy device and
- * initialise the string data members for the object. Since we only
- * support floppies using the basic "floppy" driver, we just check the
- * entry name and the bus type ("platform"). */
- void validateAndInitForFloppy()
- {
- char szBus[128];
- if ( mpcszName[0] != 'f'
- || mpcszName[1] != 'd'
- || mpcszName[2] < '0'
- || mpcszName[2] > '3'
- || mpcszName[3] != '\0')
- return;
- ssize_t cchBus = RTLinuxSysFsGetLinkDest(szBus, sizeof(szBus),
- "block/%s/device/bus",
- mpcszName);
- if (cchBus < 0)
- return;
- if (strcmp(szBus, "platform") != 0)
- return;
- misValid = true;
- strcpy(mszDesc, (mpcszName[2] == '0') ? "PC Floppy drive"
- : (mpcszName[2] == '1') ? "Second PC Floppy drive"
- : (mpcszName[2] == '2') ? "Third PC Floppy drive"
- : "Fourth PC Floppy drive");
- RTStrPrintf(mszUdi, sizeof(mszUdi),
- "/org/freedesktop/Hal/devices/platform_floppy_%u_storage",
- mpcszName[2]);
- }
-
-public:
- bool isValid()
- {
- return misValid;
- }
- const char *getDesc()
- {
- return mszDesc;
- }
- const char *getUdi()
- {
- return mszUdi;
- }
- const char *getNode()
- {
- return mszNode;
- }
-};
-
-/**
- * Helper function to query the sysfs subsystem for information about DVD
- * drives attached to the system.
- * @returns iprt status code
- * @param pList where to add information about the drives detected
- * @param isDVD are we looking for DVDs or floppies?
- * @param pfSuccess Did we find anything?
- *
- * @returns IPRT status code
- */
-/* static */
-int getDriveInfoFromSysfs(DriveInfoList *pList, bool isDVD, bool *pfSuccess)
-{
- AssertPtrReturn(pList, VERR_INVALID_POINTER);
- AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER); /* Valid or Null */
- LogFlowFunc (("pList=%p, isDVD=%u, pfSuccess=%p\n",
- pList, (unsigned) isDVD, pfSuccess));
- PRTDIR pDir = NULL;
- RTDIRENTRY entry = {0};
- int rc;
- bool fSuccess;
- unsigned cFound = 0;
-
- if (!RTPathExists("/sys"))
- return VINF_SUCCESS;
- rc = RTDirOpen(&pDir, "/sys/block");
- /* This might mean that sysfs semantics have changed */
- AssertReturn(rc != VERR_FILE_NOT_FOUND, VINF_SUCCESS);
- if (RT_SUCCESS(rc))
- while (true)
- {
- rc = RTDirRead(pDir, &entry, NULL);
- Assert(rc != VERR_BUFFER_OVERFLOW); /* Should never happen... */
- if (RT_FAILURE(rc)) /* Including overflow and no more files */
- break;
- if (entry.szName[0] == '.')
- continue;
- sysfsBlockDev dev(entry.szName, isDVD);
- if (!dev.isValid())
- continue;
- try
- {
- pList->push_back(DriveInfo(dev.getNode(), dev.getUdi(),
- dev.getDesc()));
- }
- catch(std::bad_alloc &e)
- {
- rc = VERR_NO_MEMORY;
- break;
- }
- ++cFound;
- }
- RTDirClose(pDir);
- if (rc == VERR_NO_MORE_FILES)
- rc = VINF_SUCCESS;
- fSuccess = (RT_SUCCESS(rc) && cFound > 0);
- if (!fSuccess)
- /* Clean up again */
- for (unsigned i = 0; i < cFound; ++i)
- pList->pop_back();
- if (pfSuccess)
- *pfSuccess = fSuccess;
- LogFlow (("rc=%Rrc, fSuccess=%u\n", rc, (unsigned) fSuccess));
- return rc;
-}
-
-#if defined(RT_OS_LINUX) && defined(VBOX_WITH_DBUS)
-
-/**
- * Helper function to query the hal subsystem for information about drives
- * attached to the system.
- * @returns iprt status code
- * @param pList where to add information about the drives detected
- * @param isDVD are we looking for DVDs or floppies?
- * @param pfSuccess will be set to true if all interactions with hal
- * succeeded and to false otherwise. Optional.
- *
- * @returns IPRT status code
- */
-/* static */
-int getDriveInfoFromHal(DriveInfoList *pList, bool isDVD, bool *pfSuccess)
-{
- AssertReturn(VALID_PTR (pList) && (pfSuccess == NULL || VALID_PTR (pfSuccess)),
- VERR_INVALID_POINTER);
- LogFlowFunc (("pList=%p, isDVD=%d, pfSuccess=%p\n", pList, isDVD, pfSuccess));
- int rc = VINF_SUCCESS; /* We set this to failure on fatal errors. */
- bool halSuccess = true; /* We set this to false to abort the operation. */
- autoDBusError dbusError;
-
- RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet;
- RTMemAutoPtr <DBusConnection, VBoxHalShutdown> dbusConnection;
- DBusMessageIter iterFind, iterUdis;
-
- rc = halInit (&dbusConnection);
- if (!dbusConnection)
- halSuccess = false;
- if (halSuccess && RT_SUCCESS (rc))
- {
- rc = halFindDeviceStringMatch (dbusConnection.get(), "storage.drive_type",
- isDVD ? "cdrom" : "floppy", &replyFind);
- if (!replyFind)
- halSuccess = false;
- }
- if (halSuccess && RT_SUCCESS (rc))
- {
- dbus_message_iter_init (replyFind.get(), &iterFind);
- if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
- halSuccess = false;
- }
- if (halSuccess && RT_SUCCESS (rc))
- dbus_message_iter_recurse (&iterFind, &iterUdis);
- for (; halSuccess && RT_SUCCESS (rc)
- && dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING;
- dbus_message_iter_next(&iterUdis))
- {
- /* Now get all properties from the iterator */
- const char *pszUdi;
- dbus_message_iter_get_basic (&iterUdis, &pszUdi);
- static const char *papszKeys[] =
- { "block.device", "info.product", "info.vendor" };
- char *papszValues[RT_ELEMENTS (papszKeys)];
- rc = halGetPropertyStrings (dbusConnection.get(), pszUdi, RT_ELEMENTS (papszKeys),
- papszKeys, papszValues, &replyGet);
- std::string description;
- const char *pszDevice = papszValues[0], *pszProduct = papszValues[1],
- *pszVendor = papszValues[2];
- if (!!replyGet && pszDevice == NULL)
- halSuccess = false;
- if (!!replyGet && pszDevice != NULL)
- {
- if ((pszVendor != NULL) && (pszVendor[0] != '\0'))
- (description += pszVendor) += " ";
- if ((pszProduct != NULL && pszProduct[0] != '\0'))
- description += pszProduct;
- try
- {
- pList->push_back (DriveInfo (pszDevice, pszUdi, description));
- }
- catch (std::bad_alloc)
- {
- rc = VERR_NO_MEMORY;
- }
- }
- }
- if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
- rc = VERR_NO_MEMORY;
- /* If we found nothing something may have gone wrong with hal, so
- * report failure to fall back to other methods. */
- if (pList->size() == 0)
- halSuccess = false;
- if (pfSuccess != NULL)
- *pfSuccess = halSuccess;
- LogFlow (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
- dbusError.FlowLog();
- return rc;
-}
/**
* Helper function to query the hal subsystem for information about USB devices
@@ -1546,14 +1660,14 @@ int getUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
if (!dbusConnection)
halSuccess = false;
/* Get an array of all devices in the usb_device subsystem */
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
{
rc = halFindDeviceStringMatch (dbusConnection.get(), "info.subsystem",
"usb_device", &replyFind);
if (!replyFind)
halSuccess = false;
}
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
{
dbus_message_iter_init (replyFind.get(), &iterFind);
if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
@@ -1561,9 +1675,9 @@ int getUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
}
/* Recurse down into the array and query interesting information about the
* entries. */
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
dbus_message_iter_recurse (&iterFind, &iterUdis);
- for (; halSuccess && RT_SUCCESS (rc)
+ for (; halSuccess && RT_SUCCESS(rc)
&& dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING;
dbus_message_iter_next(&iterUdis))
{
@@ -1587,7 +1701,7 @@ int getUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
{
pList->push_back (info);
}
- catch (std::bad_alloc)
+ catch(std::bad_alloc &e)
{
rc = VERR_NO_MEMORY;
}
@@ -1631,14 +1745,14 @@ int getOldUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
if (!dbusConnection)
halSuccess = false;
/* Get an array of all devices in the usb_device subsystem */
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
{
rc = halFindDeviceStringMatch (dbusConnection.get(), "info.category",
"usbraw", &replyFind);
if (!replyFind)
halSuccess = false;
}
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
{
dbus_message_iter_init (replyFind.get(), &iterFind);
if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
@@ -1646,9 +1760,9 @@ int getOldUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
}
/* Recurse down into the array and query interesting information about the
* entries. */
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
dbus_message_iter_recurse (&iterFind, &iterUdis);
- for (; halSuccess && RT_SUCCESS (rc)
+ for (; halSuccess && RT_SUCCESS(rc)
&& dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING;
dbus_message_iter_next(&iterUdis))
{
@@ -1673,7 +1787,7 @@ int getOldUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
{
pList->push_back (info);
}
- catch (std::bad_alloc)
+ catch(std::bad_alloc &e)
{
rc = VERR_NO_MEMORY;
}
@@ -1702,7 +1816,7 @@ int getOldUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
* @returns IPRT status code
*/
/* static */
-int getUSBInterfacesFromHal(std::vector <std::string> *pList,
+int getUSBInterfacesFromHal(std::vector<iprt::MiniString> *pList,
const char *pcszUdi, bool *pfSuccess)
{
AssertReturn(VALID_PTR (pList) && VALID_PTR (pcszUdi) &&
@@ -1721,7 +1835,7 @@ int getUSBInterfacesFromHal(std::vector <std::string> *pList,
rc = halInit (&dbusConnection);
if (!dbusConnection)
halSuccess = false;
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
{
/* Look for children of the current UDI. */
rc = halFindDeviceStringMatch (dbusConnection.get(), "info.parent",
@@ -1729,15 +1843,15 @@ int getUSBInterfacesFromHal(std::vector <std::string> *pList,
if (!replyFind)
halSuccess = false;
}
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
{
dbus_message_iter_init (replyFind.get(), &iterFind);
if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
halSuccess = false;
}
- if (halSuccess && RT_SUCCESS (rc))
+ if (halSuccess && RT_SUCCESS(rc))
dbus_message_iter_recurse (&iterFind, &iterUdis);
- for (; halSuccess && RT_SUCCESS (rc)
+ for (; halSuccess && RT_SUCCESS(rc)
&& dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING;
dbus_message_iter_next(&iterUdis))
{
@@ -1755,14 +1869,14 @@ int getUSBInterfacesFromHal(std::vector <std::string> *pList,
halSuccess = false;
if (!!replyGet && pszSysfsPath == NULL)
halSuccess = false;
- if ( halSuccess && RT_SUCCESS (rc)
+ if ( halSuccess && RT_SUCCESS(rc)
&& RTStrCmp (pszInfoSubsystem, "usb_device") != 0 /* Children of buses can also be devices. */
&& RTStrCmp (pszLinuxSubsystem, "usb_device") != 0)
try
{
pList->push_back (pszSysfsPath);
}
- catch (std::bad_alloc)
+ catch(std::bad_alloc &e)
{
rc = VERR_NO_MEMORY;
}