HostHardwareLinux.cpp revision bf94a12e434bda567d373eb5076cbf96aad6e987
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/* $Id$ */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/** @file
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Classes for handling hardware detection under Linux. Please feel free to
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * expand these to work for other systems (Solaris!) or to add new ones for
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * other systems.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync */
c58f1213e628a545081c70e26c6b67a841cff880vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/*
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Copyright (C) 2008-2010 Oracle Corporation
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync *
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * available from http://www.virtualbox.org. This file is free software;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * you can redistribute it and/or modify it under the terms of the GNU
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * General Public License (GPL) as published by the Free Software
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync */
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync#define LOG_GROUP LOG_GROUP_MAIN
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync/*******************************************************************************
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync* Header Files *
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync*******************************************************************************/
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <HostHardwareLinux.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <VBox/err.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <VBox/log.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
032a52c5b2984e26e84c2961f8f7f98a3954c8f2vboxsync#include <iprt/asm.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/dir.h>
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync#include <iprt/env.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/file.h>
45c3e41d012100c5f4a3f77e391e4c6da8f5b97avboxsync#include <iprt/mem.h>
45c3e41d012100c5f4a3f77e391e4c6da8f5b97avboxsync#include <iprt/param.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/path.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/string.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/thread.h> /* for RTThreadSleep() */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <linux/cdrom.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <linux/fd.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <linux/major.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <scsi/scsi.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/linux/sysfs.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#ifdef VBOX_USB_WITH_SYSFS
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync# ifdef VBOX_USB_WITH_INOTIFY
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync# include <dlfcn.h>
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync# include <fcntl.h>
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync# include <poll.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync# include <signal.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync# include <unistd.h>
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync# endif
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#endif
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync#include <vector>
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync#include <errno.h>
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/******************************************************************************
044af0d1e6474076366759db86f101778c5f20ccvboxsync* Global Variables *
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync******************************************************************************/
2d8870843ff566fee9bd3a6a5942414254106479vboxsync
2d8870843ff566fee9bd3a6a5942414254106479vboxsync#ifdef TESTCASE
2d8870843ff566fee9bd3a6a5942414254106479vboxsyncstatic bool testing() { return true; }
2d8870843ff566fee9bd3a6a5942414254106479vboxsyncstatic bool fNoProbe = false;
2d8870843ff566fee9bd3a6a5942414254106479vboxsyncstatic bool noProbe() { return fNoProbe; }
2d8870843ff566fee9bd3a6a5942414254106479vboxsyncstatic void setNoProbe(bool val) { fNoProbe = val; }
2d8870843ff566fee9bd3a6a5942414254106479vboxsync#else
2d8870843ff566fee9bd3a6a5942414254106479vboxsyncstatic bool testing() { return false; }
2d8870843ff566fee9bd3a6a5942414254106479vboxsyncstatic bool noProbe() { return false; }
2d8870843ff566fee9bd3a6a5942414254106479vboxsyncstatic void setNoProbe(bool val) { (void)val; }
2d8870843ff566fee9bd3a6a5942414254106479vboxsync#endif
2d8870843ff566fee9bd3a6a5942414254106479vboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync/******************************************************************************
044af0d1e6474076366759db86f101778c5f20ccvboxsync* Typedefs and Defines *
044af0d1e6474076366759db86f101778c5f20ccvboxsync******************************************************************************/
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsyncstatic int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList,
044af0d1e6474076366759db86f101778c5f20ccvboxsync bool isDVD, bool *pfSuccess);
044af0d1e6474076366759db86f101778c5f20ccvboxsyncstatic int getDriveInfoFromDev(DriveInfoList *pList, bool isDVD,
044af0d1e6474076366759db86f101778c5f20ccvboxsync bool *pfSuccess);
044af0d1e6474076366759db86f101778c5f20ccvboxsyncstatic int getDriveInfoFromSysfs(DriveInfoList *pList, bool isDVD,
044af0d1e6474076366759db86f101778c5f20ccvboxsync bool *pfSuccess);
044af0d1e6474076366759db86f101778c5f20ccvboxsync#ifdef VBOX_USB_WITH_SYSFS
044af0d1e6474076366759db86f101778c5f20ccvboxsync# ifdef VBOX_USB_WITH_INOTIFY
044af0d1e6474076366759db86f101778c5f20ccvboxsyncstatic int getUSBDeviceInfoFromSysfs(USBDeviceInfoList *pList, bool *pfSuccess);
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync/** Function object to be invoked on filenames from a directory. */
044af0d1e6474076366759db86f101778c5f20ccvboxsynctypedef struct pathHandler
044af0d1e6474076366759db86f101778c5f20ccvboxsync{
044af0d1e6474076366759db86f101778c5f20ccvboxsync /** Called on each element of the sysfs directory. Can e.g. store
044af0d1e6474076366759db86f101778c5f20ccvboxsync * interesting entries in a list. */
044af0d1e6474076366759db86f101778c5f20ccvboxsync bool (*handle)(pathHandler *pHandle, const char *pcszNode);
044af0d1e6474076366759db86f101778c5f20ccvboxsync} pathHandler;
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsyncstatic bool phDoHandle(pathHandler *pHandler, const char *pcszNode)
044af0d1e6474076366759db86f101778c5f20ccvboxsync{
044af0d1e6474076366759db86f101778c5f20ccvboxsync AssertPtr(pHandler);
044af0d1e6474076366759db86f101778c5f20ccvboxsync AssertPtr(pHandler->handle);
044af0d1e6474076366759db86f101778c5f20ccvboxsync AssertPtr(pcszNode);
044af0d1e6474076366759db86f101778c5f20ccvboxsync Assert(pcszNode[0] == '/');
044af0d1e6474076366759db86f101778c5f20ccvboxsync return pHandler->handle(pHandler, pcszNode);
044af0d1e6474076366759db86f101778c5f20ccvboxsync}
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsyncstatic int walkDirectory(const char *pcszPath, pathHandler *pHandler,
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync bool useRealPath);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncstatic int getDeviceInfoFromSysfs(const char *pcszPath, pathHandler *pHandler);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync# endif
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#endif /* VBOX_USB_WITH_SYSFS */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync/** Find the length of a string, ignoring trailing non-ascii or control
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * characters */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsyncstatic size_t strLenStripped(const char *pcsz)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync{
044af0d1e6474076366759db86f101778c5f20ccvboxsync size_t cch = 0;
044af0d1e6474076366759db86f101778c5f20ccvboxsync for (size_t i = 0; pcsz[i] != '\0'; ++i)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (pcsz[i] > 32 && pcsz[i] < 127)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync cch = i;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return cch + 1;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync}
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync/**
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Get the name of a floppy drive according to the Linux floppy driver.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @returns true on success, false if the name was not available (i.e. the
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * device was not readible, or the file name wasn't a PC floppy
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * device)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param pcszNode the path to the device node for the device
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param Number the Linux floppy driver number for the drive. Required.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param pszName where to store the name retreived
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncstatic bool floppyGetName(const char *pcszNode, unsigned Number,
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync floppy_drive_name pszName)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync{
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync AssertPtrReturn(pcszNode, false);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync AssertPtrReturn(pszName, false);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync AssertReturn(Number <= 7, false);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync RTFILE File;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync int rc = RTFileOpen(&File, pcszNode, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_NON_BLOCK);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (RT_SUCCESS(rc))
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync int rcIoCtl;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync rc = RTFileIoCtl(File, FDGETDRVTYP, pszName, 0, &rcIoCtl);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync RTFileClose(File);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (RT_SUCCESS(rc) && rcIoCtl >= 0)
a1df400bbe9d64aad400442e56eb637019300a5evboxsync return true;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
a1df400bbe9d64aad400442e56eb637019300a5evboxsync return false;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync}
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync/**
a1df400bbe9d64aad400442e56eb637019300a5evboxsync * Create a UDI and a description for a floppy drive based on a number and the
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * driver's name for it. We deliberately return an ugly sequence of
a1df400bbe9d64aad400442e56eb637019300a5evboxsync * characters as the description rather than an English language string to
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * avoid translation issues.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync *
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * @returns true if we know the device to be valid, false otherwise
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param pcszName the floppy driver name for the device (optional)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param Number the number of the floppy (0 to 3 on FDC 0, 4 to 7 on
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * FDC 1)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param pszDesc where to store the device description (optional)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param cchDesc the size of the buffer in @a pszDesc
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param pszUdi where to store the device UDI (optional)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param cchUdi the size of the buffer in @a pszUdi
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsyncstatic void floppyCreateDeviceStrings(const floppy_drive_name pcszName,
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync unsigned Number, char *pszDesc,
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync size_t cchDesc, char *pszUdi,
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync size_t cchUdi)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync{
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync AssertPtrNullReturnVoid(pcszName);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync AssertPtrNullReturnVoid(pszDesc);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync AssertReturnVoid(!pszDesc || cchDesc > 0);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync AssertPtrNullReturnVoid(pszUdi);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync AssertReturnVoid(!pszUdi || cchUdi > 0);
044af0d1e6474076366759db86f101778c5f20ccvboxsync AssertReturnVoid(Number <= 7);
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (pcszName)
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync const char *pcszSize;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync switch(pcszName[0])
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync case 'd': case 'q': case 'h':
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync pcszSize = "5.25\"";
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync break;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync case 'D': case 'H': case 'E': case 'u':
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync pcszSize = "3.5\"";
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync break;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync default:
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync pcszSize = "(unknown)";
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync }
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync if (pszDesc)
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync RTStrPrintf(pszDesc, cchDesc, "%s %s K%s", pcszSize, &pcszName[1],
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync Number > 3 ? ", FDC 2" : "");
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync }
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync else
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync {
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync if (pszDesc)
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync RTStrPrintf(pszDesc, cchDesc, "FDD %d%s", (Number & 4) + 1,
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync Number > 3 ? ", FDC 2" : "");
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync }
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync if (pszUdi)
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync RTStrPrintf(pszUdi, cchUdi,
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync "/org/freedesktop/Hal/devices/platform_floppy_%u_storage",
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync Number);
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync}
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync/**
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Check whether a device number might correspond to a CD-ROM device according
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * to Documentation/devices.txt in the Linux kernel source.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns true if it might, false otherwise
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param Number the device number (major and minor combination)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncstatic bool isCdromDevNum(dev_t Number)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync int major = major(Number);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync int minor = minor(Number);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if ((major == IDE0_MAJOR) && !(minor & 0x3f))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == SCSI_CDROM_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == CDU31A_CDROM_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == GOLDSTAR_CDROM_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == OPTICS_CDROM_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == SANYO_CDROM_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == MITSUMI_X_CDROM_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if ((major == IDE1_MAJOR) && !(minor & 0x3f))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == MITSUMI_CDROM_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == CDU535_CDROM_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == MATSUSHITA_CDROM_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == MATSUSHITA_CDROM2_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == MATSUSHITA_CDROM3_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == MATSUSHITA_CDROM4_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == AZTECH_CDROM_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == 30 /* CM205_CDROM_MAJOR */) /* no #define for some reason */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == CM206_CDROM_MAJOR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if ((major == IDE3_MAJOR) && !(minor & 0x3f))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == 46 /* Parallel port ATAPI CD-ROM */) /* no #define */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if ((major == IDE4_MAJOR) && !(minor & 0x3f))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if ((major == IDE5_MAJOR) && !(minor & 0x3f))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if ((major == IDE6_MAJOR) && !(minor & 0x3f))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if ((major == IDE7_MAJOR) && !(minor & 0x3f))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if ((major == IDE8_MAJOR) && !(minor & 0x3f))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if ((major == IDE9_MAJOR) && !(minor & 0x3f))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (major == 113 /* VIOCD_MAJOR */)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return true;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return false;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * Send an SCSI INQUIRY command to a device and return selected information.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns iprt status code
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns VERR_TRY_AGAIN if the query failed but might succeed next time
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pcszNode the full path to the device node
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pu8Type where to store the SCSI device type on success (optional)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pchVendor where to store the vendor id string on success (optional)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param cchVendor the size of the @a pchVendor buffer
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pchModel where to store the product id string on success (optional)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param cchModel the size of the @a pchModel buffer
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @note check documentation on the SCSI INQUIRY command and the Linux kernel
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * SCSI headers included above if you want to understand what is going
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * on in this method.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncstatic int cdromDoInquiry(const char *pcszNode, uint8_t *pu8Type,
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync char *pchVendor, size_t cchVendor, char *pchModel,
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync size_t cchModel)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync LogRelFlowFunc(("pcszNode=%s, pu8Type=%p, pchVendor=%p, cchVendor=%llu, pchModel=%p, cchModel=%llu\n",
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pcszNode, pu8Type, pchVendor, cchVendor, pchModel,
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync cchModel));
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync AssertPtrReturn(pcszNode, VERR_INVALID_POINTER);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync AssertPtrNullReturn(pu8Type, VERR_INVALID_POINTER);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync AssertPtrNullReturn(pchVendor, VERR_INVALID_POINTER);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync AssertPtrNullReturn(pchModel, VERR_INVALID_POINTER);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync RTFILE hFile;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync int rc = RTFileOpen(&hFile, pcszNode, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_NON_BLOCK);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (RT_SUCCESS(rc))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync {
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync int rcIoCtl = 0;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync unsigned char u8Response[96] = { 0 };
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync struct cdrom_generic_command CdromCommandReq;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync RT_ZERO(CdromCommandReq);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync CdromCommandReq.cmd[0] = INQUIRY;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync CdromCommandReq.cmd[4] = sizeof(u8Response);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync CdromCommandReq.buffer = u8Response;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync CdromCommandReq.buflen = sizeof(u8Response);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync CdromCommandReq.data_direction = CGC_DATA_READ;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync CdromCommandReq.timeout = 5000; /* ms */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync rc = RTFileIoCtl(hFile, CDROM_SEND_PACKET, &CdromCommandReq, 0, &rcIoCtl);
0109a2240391a89f6556b1545e6cc57f9efab060vboxsync if (RT_SUCCESS(rc) && rcIoCtl < 0)
0109a2240391a89f6556b1545e6cc57f9efab060vboxsync rc = RTErrConvertFromErrno(-CdromCommandReq.stat);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync RTFileClose(hFile);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (RT_SUCCESS(rc))
0109a2240391a89f6556b1545e6cc57f9efab060vboxsync {
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (pu8Type)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *pu8Type = u8Response[0] & 0x1f;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (pchVendor)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync RTStrPrintf(pchVendor, cchVendor, "%.8s",
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync &u8Response[8] /* vendor id string */);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (pchModel)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync RTStrPrintf(pchModel, cchModel, "%.16s",
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync &u8Response[16] /* product id string */);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync LogRelFlowFunc(("returning success: type=%u, vendor=%.8s, product=%.16s\n",
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync u8Response[0] & 0x1f, &u8Response[8], &u8Response[16]));
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return VINF_SUCCESS;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync }
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync }
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync LogRelFlowFunc(("returning %Rrc\n", rc));
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return rc;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * Initialise the device strings (description and UDI) for a DVD drive based on
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * vendor and model name strings.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pcszVendor the vendor ID string
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pcszModel the product ID string
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pszDesc where to store the description string (optional)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param cchDesc the size of the buffer in @pszDesc
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pszUdi where to store the UDI string (optional)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param cchUdi the size of the buffer in @pszUdi
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/* static */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncvoid dvdCreateDeviceStrings(const char *pcszVendor, const char *pcszModel,
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync char *pszDesc, size_t cchDesc, char *pszUdi,
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync size_t cchUdi)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync AssertPtrReturnVoid(pcszVendor);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync AssertPtrReturnVoid(pcszModel);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync AssertPtrNullReturnVoid(pszDesc);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync AssertReturnVoid(!pszDesc || cchDesc > 0);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync AssertPtrNullReturnVoid(pszUdi);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync AssertReturnVoid(!pszUdi || cchUdi > 0);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync char szCleaned[128];
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync size_t cchVendor = strLenStripped(pcszVendor);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync size_t cchModel = strLenStripped(pcszModel);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync /* Create a cleaned version of the model string for the UDI string. */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync for (unsigned i = 0; pcszModel[i] != '\0' && i < sizeof(szCleaned); ++i)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if ( (pcszModel[i] >= '0' && pcszModel[i] <= '9')
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync || (pcszModel[i] >= 'A' && pcszModel[i] <= 'z'))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync szCleaned[i] = pcszModel[i];
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync else
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync szCleaned[i] = '_';
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync szCleaned[RT_MIN(cchModel, sizeof(szCleaned) - 1)] = '\0';
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync /* Construct the description string as "Vendor Product" */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (pszDesc)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync {
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (cchVendor > 0)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync RTStrPrintf(pszDesc, cchDesc, "%.*s %s", cchVendor, pcszVendor,
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync cchModel > 0 ? pcszModel : "(unknown drive model)");
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync else
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync RTStrPrintf(pszDesc, cchDesc, "%s", pcszModel);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync }
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync /* Construct the UDI string */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (pszUdi)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync {
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (cchModel > 0)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync RTStrPrintf(pszUdi, cchUdi,
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync "/org/freedesktop/Hal/devices/storage_model_%s",
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync szCleaned);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync else
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pszUdi[0] = '\0';
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync }
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * Check whether a device node points to a valid device and create a UDI and
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * a description for it, and store the device number, if it does.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns true if the device is valid, false otherwise
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync * @param pcszNode the path to the device node
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync * @param isDVD are we looking for a DVD device (or a floppy device)?
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync * @param pDevice where to store the device node (optional)
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync * @param pszDesc where to store the device description (optional)
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync * @param cchDesc the size of the buffer in @a pszDesc
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync * @param pszUdi where to store the device UDI (optional)
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync * @param cchUdi the size of the buffer in @a pszUdi
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync */
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsyncstatic bool devValidateDevice(const char *pcszNode, bool isDVD, dev_t *pDevice,
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync char *pszDesc, size_t cchDesc, char *pszUdi,
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync size_t cchUdi)
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync{
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync AssertPtrReturn(pcszNode, false);
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync AssertPtrNullReturn(pDevice, false);
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync AssertPtrNullReturn(pszDesc, false);
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync AssertReturn(!pszDesc || cchDesc > 0, false);
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync AssertPtrNullReturn(pszUdi, false);
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync AssertReturn(!pszUdi || cchUdi > 0, false);
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync RTFSOBJINFO ObjInfo;
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync if (RT_FAILURE(RTPathQueryInfo(pcszNode, &ObjInfo, RTFSOBJATTRADD_UNIX)))
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync return false;
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync if (!RTFS_IS_DEV_BLOCK(ObjInfo.Attr.fMode))
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync return false;
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync if (pDevice)
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync *pDevice = ObjInfo.Attr.u.Unix.Device;
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync if (isDVD)
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync {
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync char szVendor[128], szModel[128];
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync uint8_t u8Type;
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync if (!isCdromDevNum(ObjInfo.Attr.u.Unix.Device))
9af7167fa39f1f139899c989da973e59b9cccc3fvboxsync return false;
9af7167fa39f1f139899c989da973e59b9cccc3fvboxsync if (RT_FAILURE(cdromDoInquiry(pcszNode, &u8Type,
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync szVendor, sizeof(szVendor),
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync szModel, sizeof(szModel))))
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync return false;
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync if (u8Type != TYPE_ROM)
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync return false;
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync dvdCreateDeviceStrings(szVendor, szModel, pszDesc, cchDesc,
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync pszUdi, cchUdi);
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync }
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync else
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync {
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync /* Floppies on Linux are legacy devices with hardcoded majors and
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync * minors */
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync unsigned Number;
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync floppy_drive_name szName;
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync if (major(ObjInfo.Attr.u.Unix.Device) != FLOPPY_MAJOR)
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync return false;
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync switch (minor(ObjInfo.Attr.u.Unix.Device))
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync {
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync case 0: case 1: case 2: case 3:
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync Number = minor(ObjInfo.Attr.u.Unix.Device);
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync break;
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync case 128: case 129: case 130: case 131:
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync Number = minor(ObjInfo.Attr.u.Unix.Device) - 128 + 4;
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync break;
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync default:
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync return false;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync }
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (!floppyGetName(pcszNode, Number, szName))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return false;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync floppyCreateDeviceStrings(szName, Number, pszDesc, cchDesc, pszUdi,
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync cchUdi);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return true;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync}
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncint VBoxMainDriveInfo::updateDVDs ()
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync{
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LogFlowThisFunc(("entered\n"));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync int rc = VINF_SUCCESS;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bool success = false; /* Have we succeeded in finding anything yet? */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync try
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync mDVDList.clear ();
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Always allow the user to override our auto-detection using an
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * environment variable. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RT_SUCCESS(rc) && (!success || testing()))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rc = getDriveInfoFromEnv ("VBOX_CDROM", &mDVDList, true /* isDVD */,
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync &success);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync setNoProbe(false);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RT_SUCCESS(rc) && (!success | testing()))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rc = getDriveInfoFromSysfs(&mDVDList, true /* isDVD */, &success);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RT_SUCCESS(rc) && testing())
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync setNoProbe(true);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rc = getDriveInfoFromSysfs(&mDVDList, true /* isDVD */, &success);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Walk through the /dev subtree if nothing else has helped. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RT_SUCCESS(rc) && (!success | testing()))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rc = getDriveInfoFromDev(&mDVDList, true /* isDVD */, &success);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync catch(std::bad_alloc &e)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rc = VERR_NO_MEMORY;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LogFlowThisFunc(("rc=%Rrc\n", rc));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return rc;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync}
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncint VBoxMainDriveInfo::updateFloppies ()
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync{
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LogFlowThisFunc(("entered\n"));
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync int rc = VINF_SUCCESS;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bool success = false; /* Have we succeeded in finding anything yet? */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync try
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync mFloppyList.clear ();
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync if (RT_SUCCESS(rc) && (!success || testing()))
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync rc = getDriveInfoFromEnv("VBOX_FLOPPY", &mFloppyList,
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync false /* isDVD */, &success);
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync setNoProbe(false);
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync if ( RT_SUCCESS(rc) && (!success || testing()))
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync rc = getDriveInfoFromSysfs(&mFloppyList, false /* isDVD */,
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync &success);
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync if (RT_SUCCESS(rc) && testing())
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync setNoProbe(true);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rc = getDriveInfoFromSysfs(&mFloppyList, false /* isDVD */, &success);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Walk through the /dev subtree if nothing else has helped. */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync if ( RT_SUCCESS(rc) && (!success || testing()))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rc = getDriveInfoFromDev(&mFloppyList, false /* isDVD */,
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync &success);
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync catch(std::bad_alloc &e)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rc = VERR_NO_MEMORY;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LogFlowThisFunc(("rc=%Rrc\n", rc));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return rc;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync}
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync/**
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * Extract the names of drives from an environment variable and add them to a
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * list if they are valid.
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync * @returns iprt status code
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync * @param pcszVar the name of the environment variable. The variable
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * value should be a list of device node names, separated
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * by ':' characters.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * @param pList the list to append the drives found to
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * @param isDVD are we looking for DVD drives or for floppies?
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * @param pfSuccess this will be set to true if we found at least one drive
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * and to false otherwise. Optional.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync/* static */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncint getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList,
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bool isDVD, bool *pfSuccess)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync{
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync AssertPtrReturn(pcszVar, VERR_INVALID_POINTER);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync AssertPtrReturn(pList, VERR_INVALID_POINTER);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync LogFlowFunc(("pcszVar=%s, pList=%p, isDVD=%d, pfSuccess=%p\n", pcszVar,
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pList, isDVD, pfSuccess));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync int rc = VINF_SUCCESS;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bool success = false;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync char *pszFreeMe = RTEnvDupEx(RTENV_DEFAULT, pcszVar);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync try
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync const char *pcszCurrent = pszFreeMe;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync while (pcszCurrent && *pcszCurrent != '\0')
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync const char *pcszNext = strchr(pcszCurrent, ':');
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync char szPath[RTPATH_MAX], szReal[RTPATH_MAX];
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync char szDesc[256], szUdi[256];
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (pcszNext)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync RTStrPrintf(szPath, sizeof(szPath), "%.*s",
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pcszNext - pcszCurrent - 1, pcszCurrent);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync else
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync RTStrPrintf(szPath, sizeof(szPath), "%s", pcszCurrent);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if ( RT_SUCCESS(RTPathReal(szPath, szReal, sizeof(szReal)))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync && devValidateDevice(szReal, isDVD, NULL, szDesc,
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync sizeof(szDesc), szUdi, sizeof(szUdi)))
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync pList->push_back(DriveInfo(szReal, szUdi, szDesc));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync success = true;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pcszCurrent = pcszNext ? pcszNext + 1 : NULL;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync if (pfSuccess != NULL)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync *pfSuccess = success;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync catch(std::bad_alloc &e)
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync rc = VERR_NO_MEMORY;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync RTStrFree(pszFreeMe);
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync LogFlowFunc(("rc=%Rrc, success=%d\n", rc, success));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return rc;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync}
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncclass sysfsBlockDev
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync{
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncpublic:
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync sysfsBlockDev(const char *pcszName, bool wantDVD)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync : mpcszName(pcszName), mwantDVD(wantDVD), misConsistent(true),
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync misValid(false)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (findDeviceNode())
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync if (mwantDVD)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync validateAndInitForDVD();
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync else
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync validateAndInitForFloppy();
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncprivate:
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** The name of the subdirectory of /sys/block for this device */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync const char *mpcszName;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** Are we looking for a floppy or a DVD device? */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bool mwantDVD;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** The device node for the device */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync char mszNode[RTPATH_MAX];
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** Does the sysfs entry look like we expect it too? This is a canary
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * for future sysfs ABI changes. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bool misConsistent;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** Is this entry a valid specimen of what we are looking for? */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bool misValid;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** Human readible drive description string */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync char mszDesc[256];
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** Unique identifier for the drive. Should be identical to hal's UDI for
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync * the device. May not be unique for two identical drives. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync char mszUdi[256];
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncprivate:
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Private methods */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /**
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * Fill in the device node member based on the /sys/block subdirectory.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * @returns boolean success value
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bool findDeviceNode()
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync dev_t dev = RTLinuxSysFsReadDevNumFile("block/%s/dev", mpcszName);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (dev == 0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync misConsistent = false;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return false;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RTLinuxFindDevicePath(dev, RTFS_TYPE_DEV_BLOCK, mszNode,
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync sizeof(mszNode), "%s", mpcszName) < 0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return false;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return true;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** Check whether the sysfs block entry is valid for a DVD device and
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * initialise the string data members for the object. We try to get all
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * the information we need from sysfs if possible, to avoid unnecessarily
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * poking the device, and if that fails we fall back to an SCSI INQUIRY
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * command. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync void validateAndInitForDVD()
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync char szVendor[128], szModel[128];
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync ssize_t cchVendor, cchModel;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync int64_t type = RTLinuxSysFsReadIntFile(10, "block/%s/device/type",
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync mpcszName);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (type >= 0 && type != TYPE_ROM)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (type == TYPE_ROM)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync cchVendor = RTLinuxSysFsReadStrFile(szVendor, sizeof(szVendor),
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync "block/%s/device/vendor",
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync mpcszName);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (cchVendor >= 0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync cchModel = RTLinuxSysFsReadStrFile(szModel, sizeof(szModel),
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync "block/%s/device/model",
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync mpcszName);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (cchModel >= 0)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync misValid = true;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync dvdCreateDeviceStrings(szVendor, szModel,
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync mszDesc, sizeof(mszDesc),
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync mszUdi, sizeof(mszUdi));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (!noProbe())
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync probeAndInitForDVD();
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** Try to find out whether a device is a DVD drive by sending it an
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * SCSI INQUIRY command. If it is, initialise the string and validity
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * data members for the object based on the returned data.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync void probeAndInitForDVD()
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync AssertReturnVoid(mszNode[0] != '\0');
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint8_t u8Type = 0;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync char szVendor[128] = "";
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync char szModel[128] = "";
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync int rc = cdromDoInquiry(mszNode, &u8Type, szVendor,
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync sizeof(szVendor), szModel,
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync sizeof(szModel));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RT_SUCCESS(rc) && (u8Type == TYPE_ROM))
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync {
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync misValid = true;
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync dvdCreateDeviceStrings(szVendor, szModel, mszDesc, sizeof(mszDesc),
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync mszUdi, sizeof(mszUdi));
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync }
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync }
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync /** Check whether the sysfs block entry is valid for a floppy device and
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * initialise the string data members for the object. Since we only
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * support floppies using the basic "floppy" driver, we check the driver
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync * using the entry name and a driver-specific ioctl. */
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync void validateAndInitForFloppy()
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync {
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync bool haveName = false;
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync floppy_drive_name szName;
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync char szDriver[8];
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync if ( mpcszName[0] != 'f'
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync || mpcszName[1] != 'd'
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync || mpcszName[2] < '0'
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync || mpcszName[2] > '7'
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync || mpcszName[3] != '\0')
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync return;
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync if (!noProbe())
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync haveName = floppyGetName(mszNode, mpcszName[2] - '0', szName);
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync if (RTLinuxSysFsGetLinkDest(szDriver, sizeof(szDriver), "block/%s/%s",
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync mpcszName, "device/driver") >= 0)
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync {
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync if (RTStrCmp(szDriver, "floppy"))
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync return;
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync }
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync else if (!haveName)
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync return;
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync floppyCreateDeviceStrings(haveName ? szName : NULL,
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync mpcszName[2] - '0', mszDesc,
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync sizeof(mszDesc), mszUdi, sizeof(mszUdi));
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync misValid = true;
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync }
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsyncpublic:
9b19ad593b379ebfcc8273f85b90763b14b1da63vboxsync bool isConsistent()
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return misConsistent;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bool isValid()
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return misValid;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync const char *getDesc()
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return mszDesc;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync const char *getUdi()
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return mszUdi;
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync const char *getNode()
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return mszNode;
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync};
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync/**
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * Helper function to query the sysfs subsystem for information about DVD
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * drives attached to the system.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * @returns iprt status code
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * @param pList where to add information about the drives detected
2d8870843ff566fee9bd3a6a5942414254106479vboxsync * @param isDVD are we looking for DVDs or floppies?
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * @param pfSuccess Did we find anything?
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync *
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * @returns IPRT status code
2d8870843ff566fee9bd3a6a5942414254106479vboxsync */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync/* static */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncint getDriveInfoFromSysfs(DriveInfoList *pList, bool isDVD, bool *pfSuccess)
88acfa6629a7976c0583c1712d2b5b22a87a5121vboxsync{
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync AssertPtrReturn(pList, VERR_INVALID_POINTER);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER); /* Valid or Null */
2d8870843ff566fee9bd3a6a5942414254106479vboxsync LogFlowFunc (("pList=%p, isDVD=%u, pfSuccess=%p\n",
2d8870843ff566fee9bd3a6a5942414254106479vboxsync pList, (unsigned) isDVD, pfSuccess));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync PRTDIR pDir = NULL;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync int rc;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync bool fSuccess = false;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync unsigned cFound = 0;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (!RTPathExists("/sys"))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return VINF_SUCCESS;
2d8870843ff566fee9bd3a6a5942414254106479vboxsync rc = RTDirOpen(&pDir, "/sys/block");
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* This might mean that sysfs semantics have changed */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync AssertReturn(rc != VERR_FILE_NOT_FOUND, VINF_SUCCESS);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync fSuccess = true;
2d8870843ff566fee9bd3a6a5942414254106479vboxsync if (RT_SUCCESS(rc))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (;;)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
a1df400bbe9d64aad400442e56eb637019300a5evboxsync RTDIRENTRY entry;
a1df400bbe9d64aad400442e56eb637019300a5evboxsync rc = RTDirRead(pDir, &entry, NULL);
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync Assert(rc != VERR_BUFFER_OVERFLOW); /* Should never happen... */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RT_FAILURE(rc)) /* Including overflow and no more files */
2d8870843ff566fee9bd3a6a5942414254106479vboxsync break;
2d8870843ff566fee9bd3a6a5942414254106479vboxsync if (entry.szName[0] == '.')
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync continue;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync sysfsBlockDev dev(entry.szName, isDVD);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* This might mean that sysfs semantics have changed */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync AssertBreakStmt(dev.isConsistent(), fSuccess = false);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (!dev.isValid())
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync continue;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync try
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync pList->push_back(DriveInfo(dev.getNode(), dev.getUdi(),
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync dev.getDesc()));
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync }
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync catch(std::bad_alloc &e)
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync {
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync rc = VERR_NO_MEMORY;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync break;
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync ++cFound;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync RTDirClose(pDir);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (rc == VERR_NO_MORE_FILES)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rc = VINF_SUCCESS;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RT_FAILURE(rc))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Clean up again */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync for (unsigned i = 0; i < cFound; ++i)
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync pList->pop_back();
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync if (pfSuccess)
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync *pfSuccess = fSuccess;
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync LogFlow (("rc=%Rrc, fSuccess=%u\n", rc, (unsigned) fSuccess));
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return rc;
9d020a0622f95aec3aabaff436a495e88dbbd71avboxsync}
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync/** Structure for holding information about a drive we have found */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncstruct deviceNodeInfo
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync{
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** The device number */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync dev_t Device;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** The device node path */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync char szPath[RTPATH_MAX];
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** The device description */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync char szDesc[256];
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** The device UDI */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync char szUdi[256];
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync};
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync/** The maximum number of devices we will search for. */
044af0d1e6474076366759db86f101778c5f20ccvboxsyncenum { MAX_DEVICE_NODES = 8 };
044af0d1e6474076366759db86f101778c5f20ccvboxsync/** An array of MAX_DEVICE_NODES devices */
044af0d1e6474076366759db86f101778c5f20ccvboxsynctypedef struct deviceNodeInfo deviceNodeArray[MAX_DEVICE_NODES];
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync/**
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Recursive worker function to walk the /dev tree looking for DVD or floppy
044af0d1e6474076366759db86f101778c5f20ccvboxsync * devices.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @returns true if we have already found MAX_DEVICE_NODES devices, false
044af0d1e6474076366759db86f101778c5f20ccvboxsync * otherwise
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param pszPath the path to start recursing. The function can modify
044af0d1e6474076366759db86f101778c5f20ccvboxsync * this string at and after the terminating zero
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param cchPath the size of the buffer (not the string!) in @a pszPath
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param aDevices where to fill in information about devices that we have
044af0d1e6474076366759db86f101778c5f20ccvboxsync * found
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param wantDVD are we looking for DVD devices (or floppies)?
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsyncstatic bool devFindDeviceRecursive(char *pszPath, size_t cchPath,
044af0d1e6474076366759db86f101778c5f20ccvboxsync deviceNodeArray aDevices, bool wantDVD)
044af0d1e6474076366759db86f101778c5f20ccvboxsync{
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync /*
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync * Check assumptions made by the code below.
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync */
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync size_t const cchBasePath = strlen(pszPath);
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync AssertReturn(cchBasePath < RTPATH_MAX - 10U, false);
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync AssertReturn(pszPath[cchBasePath - 1] != '/', false);
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync PRTDIR pDir;
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync if (RT_FAILURE(RTDirOpen(&pDir, pszPath)))
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync return false;
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync for (;;)
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync {
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync RTDIRENTRY Entry;
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync RTFSOBJINFO ObjInfo;
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync int rc = RTDirRead(pDir, &Entry, NULL);
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsync if (RT_FAILURE(rc))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync break;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (Entry.enmType == RTDIRENTRYTYPE_UNKNOWN)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RT_FAILURE(RTPathQueryInfo(pszPath, &ObjInfo,
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync RTFSOBJATTRADD_UNIX)))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync continue;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync continue;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (Entry.enmType == RTDIRENTRYTYPE_SYMLINK)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync continue;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pszPath[cchBasePath] = '\0';
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RT_FAILURE(RTPathAppend(pszPath, cchPath, Entry.szName)))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync break;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* Do the matching. */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync dev_t DevNode;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync char szDesc[256], szUdi[256];
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync if (!devValidateDevice(pszPath, wantDVD, &DevNode, szDesc,
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync sizeof(szDesc), szUdi, sizeof(szUdi)))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync continue;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync unsigned i;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync for (i = 0; i < MAX_DEVICE_NODES; ++i)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (!aDevices[i].Device || (aDevices[i].Device == DevNode))
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync break;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync AssertBreak(i < MAX_DEVICE_NODES);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (aDevices[i].Device)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync continue;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync aDevices[i].Device = DevNode;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync RTStrPrintf(aDevices[i].szPath, sizeof(aDevices[i].szPath),
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync "%s", pszPath);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync AssertCompile(sizeof(aDevices[i].szDesc) == sizeof(szDesc));
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync strcpy(aDevices[i].szDesc, szDesc);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync AssertCompile(sizeof(aDevices[i].szUdi) == sizeof(szUdi));
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync strcpy(aDevices[i].szUdi, szUdi);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (i == MAX_DEVICE_NODES - 1)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync break;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync continue;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /* Recurse into subdirectories. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if ( (Entry.enmType == RTDIRENTRYTYPE_UNKNOWN)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync && !RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync continue;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (Entry.enmType != RTDIRENTRYTYPE_DIRECTORY)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync continue;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (Entry.szName[0] == '.')
830a019ad79a45e6bf7a5419efd5a729a36e599evboxsync continue;
830a019ad79a45e6bf7a5419efd5a729a36e599evboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (devFindDeviceRecursive(pszPath, cchPath, aDevices, wantDVD))
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync break;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync }
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync RTDirClose(pDir);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return aDevices[MAX_DEVICE_NODES - 1].Device ? true : false;
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync/**
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * Recursively walk through the /dev tree and add any DVD or floppy drives we
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * find and can access to our list. (If we can't access them we can't check
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * whether or not they are really DVD or floppy drives).
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * @note this is rather slow (a couple of seconds) for DVD probing on
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * systems with a static /dev tree, as the current code tries to open
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * any device node with a major/minor combination that could belong to
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * a CD-ROM device, and opening a non-existent device can take a non.
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * negligeable time on Linux. If it is ever necessary to improve this
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * (static /dev trees are no longer very fashionable these days, and
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * sysfs looks like it will be with us for a while), we could further
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * reduce the number of device nodes we open by checking whether the
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * driver is actually loaded in /proc/devices, and by counting the
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * of currently attached SCSI CD-ROM devices in /proc/scsi/scsi (yes,
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * there is a race, but it is probably not important for us).
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * @returns iprt status code
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * @param pList the list to append the drives found to
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * @param isDVD are we looking for DVD drives or for floppies?
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * @param pfSuccess this will be set to true if we found at least one drive
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * and to false otherwise. Optional.
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync/* static */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncint getDriveInfoFromDev(DriveInfoList *pList, bool isDVD, bool *pfSuccess)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync{
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync AssertPtrReturn(pList, VERR_INVALID_POINTER);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync LogFlowFunc(("pList=%p, isDVD=%d, pfSuccess=%p\n", pList, isDVD,
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pfSuccess));
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync int rc = VINF_SUCCESS;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync bool success = false;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync char szPath[RTPATH_MAX] = "/dev";
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync deviceNodeArray aDevices;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync RT_ZERO(aDevices);
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync devFindDeviceRecursive(szPath, sizeof(szPath), aDevices, isDVD);
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync try
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync {
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync for (unsigned i = 0; i < MAX_DEVICE_NODES; ++i)
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync {
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync if (aDevices[i].Device)
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync {
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync pList->push_back(DriveInfo(aDevices[i].szPath,
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync aDevices[i].szUdi, aDevices[i].szDesc));
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync success = true;
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync }
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync }
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync if (pfSuccess != NULL)
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync *pfSuccess = success;
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync }
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync catch(std::bad_alloc &e)
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync {
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync rc = VERR_NO_MEMORY;
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync }
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync LogFlowFunc (("rc=%Rrc, success=%d\n", rc, success));
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync return rc;
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync}
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsyncint USBDevInfoUpdateDevices (VBoxMainUSBDeviceInfo *pSelf)
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync{
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync LogFlowFunc(("entered\n"));
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync int rc = VINF_SUCCESS;
e9525bea57dc13d82fd3392913aebb33d2cb79e3vboxsync bool success = false; /* Have we succeeded in finding anything yet? */
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync USBDeviceInfoList_clear(&pSelf->mDeviceList);
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync#ifdef VBOX_USB_WITH_SYSFS
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync# ifdef VBOX_USB_WITH_INOTIFY
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync if ( RT_SUCCESS(rc)
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync && (!success || testing()))
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync rc = getUSBDeviceInfoFromSysfs(&pSelf->mDeviceList, &success);
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync# endif
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync#else /* !VBOX_USB_WITH_SYSFS */
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync NOREF(success);
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync#endif /* !VBOX_USB_WITH_SYSFS */
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync LogFlowFunc(("rc=%Rrc\n", rc));
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync return rc;
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync}
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsyncclass hotplugNullImpl : public VBoxMainHotplugWaiterImpl
d90eec53c9dcaa0f3d1054e8734ed46875b9093avboxsync{
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncpublic:
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync hotplugNullImpl (void) {}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync virtual ~hotplugNullImpl (void) {}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /** @copydoc VBoxMainHotplugWaiter::Wait */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync virtual int Wait (RTMSINTERVAL)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return VERR_NOT_SUPPORTED;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /** @copydoc VBoxMainHotplugWaiter::Interrupt */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync virtual void Interrupt (void) {}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync virtual int getStatus(void)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return VERR_NOT_SUPPORTED;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync};
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync#ifdef VBOX_USB_WITH_SYSFS
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync# ifdef VBOX_USB_WITH_INOTIFY
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync/** Class wrapper around an inotify watch (or a group of them to be precise).
a1df400bbe9d64aad400442e56eb637019300a5evboxsync * Inherits from pathHandler so that it can be passed to walkDirectory() to
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * easily add all files from a directory. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsynctypedef struct inotifyWatch
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync{
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /** The pathHandler we inherit from - this must be the first structure
044af0d1e6474076366759db86f101778c5f20ccvboxsync * member */
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync pathHandler mParent;
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync /** Pointer to the inotify_add_watch() glibc function/Linux API */
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync int (*inotify_add_watch)(int, const char *, uint32_t);
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync /** The native handle of the inotify fd. */
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync int mhInotify;
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync} inotifyWatch;
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync/** The flags we pass to inotify - modify, create, delete, change permissions
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync */
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync#define IN_FLAGS 0x306
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsyncstatic bool iwHandle(pathHandler *pParent, const char *pcszPath)
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync{
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync AssertPtrReturn(pParent, false);
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync AssertReturn(pParent->handle == iwHandle, false);
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync inotifyWatch *pSelf = (inotifyWatch *)pParent;
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync errno = 0;
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync if ( pSelf->inotify_add_watch(pSelf->mhInotify, pcszPath, IN_FLAGS) >= 0
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync || (errno == EACCES))
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync return true;
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync /* Other errors listed in the manpage can be treated as fatal */
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync return false;
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync}
bbb4c0bfd5ea55e99591d8811771257a437053eevboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync/** Object initialisation */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncstatic int iwInit(inotifyWatch *pSelf)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync{
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync int (*inotify_init)(void);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync int fd, flags;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync int rc = VINF_SUCCESS;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync AssertPtr(pSelf);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pSelf->mParent.handle = iwHandle;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pSelf->mhInotify = -1;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync errno = 0;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync *(void **)(&inotify_init) = dlsym(RTLD_DEFAULT, "inotify_init");
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (!inotify_init)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return VERR_LDR_IMPORTED_SYMBOL_NOT_FOUND;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync *(void **)(&pSelf->inotify_add_watch)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync = dlsym(RTLD_DEFAULT, "inotify_add_watch");
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (!pSelf->inotify_add_watch)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return VERR_LDR_IMPORTED_SYMBOL_NOT_FOUND;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync fd = inotify_init();
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (fd < 0)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync Assert(errno > 0);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return RTErrConvertFromErrno(errno);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync Assert(errno == 0);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync flags = fcntl(fd, F_GETFL, NULL);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if ( flags < 0
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync Assert(errno > 0);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync rc = RTErrConvertFromErrno(errno);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (RT_FAILURE(rc))
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync close(fd);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync else
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync Assert(errno == 0);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pSelf->mhInotify = fd;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return rc;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncstatic void iwTerm(inotifyWatch *pSelf)
044af0d1e6474076366759db86f101778c5f20ccvboxsync{
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync AssertPtrReturnVoid(pSelf);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync if (pSelf->mhInotify != -1)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync close(pSelf->mhInotify);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync pSelf->mhInotify = -1;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync }
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncstatic int iwGetFD(inotifyWatch *pSelf)
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync{
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync AssertPtrReturn(pSelf, -1);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync return pSelf->mhInotify;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync}
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync# define SYSFS_USB_DEVICE_PATH "/dev/bus/usb"
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync# define SYSFS_WAKEUP_STRING "Wake up!"
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsyncclass hotplugInotifyImpl : public VBoxMainHotplugWaiterImpl
044af0d1e6474076366759db86f101778c5f20ccvboxsync{
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /** Pipe used to interrupt wait(), the read end. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync int mhWakeupPipeR;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /** Pipe used to interrupt wait(), the write end. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync int mhWakeupPipeW;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /** The inotify watch set */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync inotifyWatch mWatches;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /** Flag to mark that the Wait() method is currently being called, and to
a1df400bbe9d64aad400442e56eb637019300a5evboxsync * ensure that it isn't called multiple times in parallel. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync volatile uint32_t mfWaiting;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /** iprt result code from object initialisation. Should be AssertReturn-ed
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * on at the start of all methods. I went this way because I didn't want
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * to deal with exceptions. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync int mStatus;
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /** ID values associates with the wakeup pipe and the FAM socket for polling
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync enum
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync {
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync RPIPE_ID = 0,
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync INOTIFY_ID,
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync MAX_POLLID
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync };
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /** Clean up any resources in use, gracefully skipping over any which have
a1df400bbe9d64aad400442e56eb637019300a5evboxsync * not yet been allocated or already cleaned up. Intended to be called
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync * from the destructor or after a failed initialisation. */
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync void term(void);
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync int drainInotify();
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync
c0e27f622f9bd6d9e77d2d959aab71d69dabf0d3vboxsync /** Read the wakeup string from the wakeup pipe */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync int drainWakeupPipe(void);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncpublic:
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync hotplugInotifyImpl(void);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync virtual ~hotplugInotifyImpl(void)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync term();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#ifdef DEBUG
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /** The first call to term should mark all resources as freed, so this
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * should be a semantic no-op. */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync term();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /** Are sysfs and inotify available on this system? If so we expect that
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * this implementation will be usable. */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync static bool Available(void)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return ( RTDirExists(SYSFS_USB_DEVICE_PATH)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync && dlsym(RTLD_DEFAULT, "inotify_init") != NULL);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync virtual int getStatus(void)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return mStatus;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /** @copydoc VBoxMainHotplugWaiter::Wait */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync virtual int Wait(RTMSINTERVAL);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /** @copydoc VBoxMainHotplugWaiter::Interrupt */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync virtual void Interrupt(void);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync};
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync/** Simplified version of RTPipeCreate */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncstatic int pipeCreateSimple(int *phPipeRead, int *phPipeWrite)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertPtrReturn(phPipeRead, VERR_INVALID_POINTER);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertPtrReturn(phPipeWrite, VERR_INVALID_POINTER);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /*
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * Create the pipe and set the close-on-exec flag if requested.
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync int aFds[2] = {-1, -1};
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (pipe(aFds))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return RTErrConvertFromErrno(errno);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync *phPipeRead = aFds[0];
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync *phPipeWrite = aFds[1];
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /*
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * Before we leave, make sure to shut up SIGPIPE.
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync signal(SIGPIPE, SIG_IGN);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return VINF_SUCCESS;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsynchotplugInotifyImpl::hotplugInotifyImpl(void) :
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mhWakeupPipeR(-1), mhWakeupPipeW(-1), mfWaiting(0),
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mStatus(VERR_WRONG_ORDER)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync# ifdef DEBUG
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /* Excercise the code path (term() on a not-fully-initialised object) as
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * well as we can. On an uninitialised object this method is a sematic
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * no-op. */
a1df400bbe9d64aad400442e56eb637019300a5evboxsync term();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /* For now this probing method should only be used if nothing else is
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * available */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync# endif
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync int rc;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync do {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RT_FAILURE(rc = iwInit(&mWatches)))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync phDoHandle(&mWatches.mParent, SYSFS_USB_DEVICE_PATH);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RT_FAILURE(rc = pipeCreateSimple(&mhWakeupPipeR, &mhWakeupPipeW)))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync } while(0);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mStatus = rc;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RT_FAILURE(rc))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync term();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncvoid hotplugInotifyImpl::term(void)
a1df400bbe9d64aad400442e56eb637019300a5evboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /** This would probably be a pending segfault, so die cleanly */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertRelease(!mfWaiting);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (mhWakeupPipeR != -1)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync close(mhWakeupPipeR);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mhWakeupPipeR = -1;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (mhWakeupPipeW != -1)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync close(mhWakeupPipeW);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mhWakeupPipeW = -1;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync iwTerm(&mWatches);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncint hotplugInotifyImpl::drainInotify()
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
2d8870843ff566fee9bd3a6a5942414254106479vboxsync char chBuf[RTPATH_MAX + 256]; /* Should always be big enough */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync ssize_t cchRead;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertRCReturn(mStatus, VERR_WRONG_ORDER);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync errno = 0;
2d8870843ff566fee9bd3a6a5942414254106479vboxsync do {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync cchRead = read(iwGetFD(&mWatches), chBuf, sizeof(chBuf));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync } while (cchRead > 0);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (cchRead == 0)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return VINF_SUCCESS;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (cchRead < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
2d8870843ff566fee9bd3a6a5942414254106479vboxsync return VINF_SUCCESS;
2d8870843ff566fee9bd3a6a5942414254106479vboxsync Assert(errno > 0);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return RTErrConvertFromErrno(errno);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncint hotplugInotifyImpl::drainWakeupPipe(void)
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync char szBuf[sizeof(SYSFS_WAKEUP_STRING)];
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync ssize_t cbRead;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertRCReturn(mStatus, VERR_WRONG_ORDER);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync cbRead = read(mhWakeupPipeR, szBuf, sizeof(szBuf));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync Assert(cbRead > 0);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return VINF_SUCCESS;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncint hotplugInotifyImpl::Wait(RTMSINTERVAL aMillies)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync int rc;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
2d8870843ff566fee9bd3a6a5942414254106479vboxsync AssertRCReturn(mStatus, VERR_WRONG_ORDER);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync bool fEntered = ASMAtomicCmpXchgU32(&mfWaiting, 1, 0);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertReturn(fEntered, VERR_WRONG_ORDER);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync do {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync struct pollfd pollFD[MAX_POLLID];
2d8870843ff566fee9bd3a6a5942414254106479vboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RT_FAILURE(rc = walkDirectory(SYSFS_USB_DEVICE_PATH, &mWatches.mParent,
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync false)))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pollFD[RPIPE_ID].fd = mhWakeupPipeR;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pollFD[RPIPE_ID].events = POLLIN;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pollFD[INOTIFY_ID].fd = iwGetFD(&mWatches);
2d8870843ff566fee9bd3a6a5942414254106479vboxsync pollFD[INOTIFY_ID].events = POLLIN | POLLERR | POLLHUP;
2d8870843ff566fee9bd3a6a5942414254106479vboxsync errno = 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync int cPolled = poll(pollFD, RT_ELEMENTS(pollFD), aMillies);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (cPolled < 0)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync Assert(errno > 0);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync rc = RTErrConvertFromErrno(errno);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync else if (pollFD[RPIPE_ID].revents)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync rc = drainWakeupPipe();
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RT_SUCCESS(rc))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync rc = VERR_INTERRUPTED;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync else if (!(pollFD[INOTIFY_ID].revents))
a1df400bbe9d64aad400442e56eb637019300a5evboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertBreakStmt(cPolled == 0, rc = VERR_INTERNAL_ERROR);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync rc = VERR_TIMEOUT;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync Assert(errno == 0 || (RT_FAILURE(rc) && rc != VERR_TIMEOUT));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RT_FAILURE(rc))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertBreakStmt(cPolled == 1, rc = VERR_INTERNAL_ERROR);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RT_FAILURE(rc = drainInotify()))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync } while (false);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mfWaiting = 0;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return rc;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncvoid hotplugInotifyImpl::Interrupt(void)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertRCReturnVoid(mStatus);
a1df400bbe9d64aad400442e56eb637019300a5evboxsync ssize_t cbWritten = write(mhWakeupPipeW, SYSFS_WAKEUP_STRING,
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync sizeof(SYSFS_WAKEUP_STRING));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (cbWritten > 0)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync fsync(mhWakeupPipeW);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync# endif /* VBOX_USB_WITH_INOTIFY */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_USB_WTH_SYSFS */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncVBoxMainHotplugWaiter::VBoxMainHotplugWaiter(void)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync try
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#ifdef VBOX_USB_WITH_SYSFS
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync# ifdef VBOX_USB_WITH_INOTIFY
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (hotplugInotifyImpl::Available())
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mImpl = new hotplugInotifyImpl;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync# endif /* VBOX_USB_WITH_INOTIFY */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#endif /* VBOX_USB_WITH_SYSFS */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync mImpl = new hotplugNullImpl;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync catch(std::bad_alloc &e)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync { }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync#ifdef VBOX_USB_WITH_SYSFS
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync# ifdef VBOX_USB_WITH_INOTIFY
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync/**
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * Helper function to walk a directory, calling a function object on its files
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * @returns iprt status code
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * @param pcszPath Directory to walk.
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * @param pHandler Handler object which will be invoked on each file
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * @param useRealPath Whether to resolve the filename to its real path
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * before calling the handler. In this case the target
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * must exist.
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync *
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * @returns IPRT status code
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync/* static */
a1df400bbe9d64aad400442e56eb637019300a5evboxsyncint walkDirectory(const char *pcszPath, pathHandler *pHandler, bool useRealPath)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertPtrReturn(pcszPath, VERR_INVALID_POINTER);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertPtrReturn(pHandler, VERR_INVALID_POINTER);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync LogFlowFunc (("pcszPath=%s, pHandler=%p\n", pcszPath, pHandler));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync PRTDIR pDir = NULL;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync int rc;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync rc = RTDirOpen(&pDir, pcszPath);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RT_FAILURE(rc))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return rc;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync while (RT_SUCCESS(rc))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync RTDIRENTRY entry;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync char szPath[RTPATH_MAX], szAbsPath[RTPATH_MAX];
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync rc = RTDirRead(pDir, &entry, NULL);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync Assert(rc != VERR_BUFFER_OVERFLOW); /* Should never happen... */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /* We break on "no more files" as well as on "real" errors */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RT_FAILURE(rc))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (entry.szName[0] == '.')
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync continue;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RTStrPrintf(szPath, sizeof(szPath), "%s/%s", pcszPath,
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync entry.szName) >= sizeof(szPath))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync rc = VERR_BUFFER_OVERFLOW;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RT_FAILURE(rc))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (useRealPath)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync {
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync rc = RTPathReal(szPath, szAbsPath, sizeof(szAbsPath));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (RT_FAILURE(rc))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync break; /* The file can vanish if a device is unplugged. */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (!phDoHandle(pHandler, szAbsPath))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync else
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (!phDoHandle(pHandler, szPath))
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync break;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync }
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync RTDirClose(pDir);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync if (rc == VERR_NO_MORE_FILES)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync rc = VINF_SUCCESS;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync LogFlow (("rc=%Rrc\n", rc));
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return rc;
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync/**
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * Helper function to walk a sysfs directory for extracting information about
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * devices.
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * @returns iprt status code
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * @param pcszPath Sysfs directory to walk. Must exist.
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * @param pHandler Handler object which will be invoked on each directory
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * entry
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync *
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * @returns IPRT status code
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync/* static */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncint getDeviceInfoFromSysfs(const char *pcszPath, pathHandler *pHandler)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return walkDirectory(pcszPath, pHandler, true);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
88acfa6629a7976c0583c1712d2b5b22a87a5121vboxsync#define USBDEVICE_MAJOR 189
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync/** Deduce the bus that a USB device is plugged into from the device node
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * number. See drivers/usb/core/hub.c:usb_new_device as of Linux 2.6.20. */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncstatic unsigned usbBusFromDevNum(dev_t devNum)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertReturn(devNum, 0);
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync AssertReturn(major(devNum) == USBDEVICE_MAJOR, 0);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return (minor(devNum) >> 7) + 1;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync/** Deduce the device number of a USB device on the bus from the device node
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * number. See drivers/usb/core/hub.c:usb_new_device as of Linux 2.6.20. */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsyncstatic unsigned usbDeviceFromDevNum(dev_t devNum)
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertReturn(devNum, 0);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync AssertReturn(major(devNum) == USBDEVICE_MAJOR, 0);
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync return (minor(devNum) & 127) + 1;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync}
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync/**
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * Tell whether a file in /sys/bus/usb/devices is a device rather than an
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync * interface. To be used with getDeviceInfoFromSysfs().
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsynctypedef struct matchUSBDevice
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync{
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync /** The pathHandler object we inherit from - must come first */
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync pathHandler mParent;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync USBDeviceInfoList *mList;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync} matchUSBDevice;
df8e6a449f00e1884fbf4a1fc67143614d7d528dvboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncstatic bool mudHandle(pathHandler *pParent, const char *pcszNode)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync{
45c3e41d012100c5f4a3f77e391e4c6da8f5b97avboxsync AssertPtrReturn(pParent, false);
45c3e41d012100c5f4a3f77e391e4c6da8f5b97avboxsync AssertReturn(pParent->handle = mudHandle, false);
26645f447bb6a819f33492c84e03e364092ec600vboxsync matchUSBDevice *pSelf = (matchUSBDevice *)pParent;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync const char *pcszFile = strrchr(pcszNode, '/');
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (strchr(pcszFile, ':'))
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync return true;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync dev_t devnum = RTLinuxSysFsReadDevNumFile("%s/dev", pcszNode);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync /* Sanity test of our static helpers */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync Assert(usbBusFromDevNum(makedev(USBDEVICE_MAJOR, 517)) == 5);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync Assert(usbDeviceFromDevNum(makedev(USBDEVICE_MAJOR, 517)) == 6);
26645f447bb6a819f33492c84e03e364092ec600vboxsync AssertReturn (devnum, true);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync char szDevPath[RTPATH_MAX];
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync ssize_t cchDevPath;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync cchDevPath = RTLinuxFindDevicePath(devnum, RTFS_TYPE_DEV_CHAR,
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync szDevPath, sizeof(szDevPath),
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync "/dev/bus/usb/%.3d/%.3d",
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync usbBusFromDevNum(devnum),
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync usbDeviceFromDevNum(devnum));
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (cchDevPath < 0)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync return true;
4dcf37df51439573b55cc16f53590c7b68cb1051vboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync USBDeviceInfo info;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (USBDevInfoInit(&info, szDevPath, pcszNode))
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (USBDeviceInfoList_push_back(pSelf->mList, &info))
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync return true;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync USBDevInfoCleanup(&info);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync return false;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync}
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsyncstatic void mudInit(matchUSBDevice *pSelf, USBDeviceInfoList *pList)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync{
4dcf37df51439573b55cc16f53590c7b68cb1051vboxsync AssertPtrReturnVoid(pSelf);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync pSelf->mParent.handle = mudHandle;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync pSelf->mList = pList;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync}
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync/**
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * Tell whether a file in /sys/bus/usb/devices is an interface rather than a
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * device. To be used with getDeviceInfoFromSysfs().
4dcf37df51439573b55cc16f53590c7b68cb1051vboxsync */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsynctypedef struct matchUSBInterface
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync{
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync /** The pathHandler class we inherit from - must be the first member. */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync pathHandler mParent;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync USBDeviceInfo *mInfo;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync} matchUSBInterface;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync/** The logic for testing whether a sysfs address corresponds to an
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * interface of a device. Both must be referenced by their canonical
4dcf37df51439573b55cc16f53590c7b68cb1051vboxsync * sysfs paths. This is not tested, as the test requires file-system
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync * interaction. */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsyncstatic bool muiIsAnInterfaceOf(const char *pcszIface, const char *pcszDev)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync{
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync size_t cchDev = strlen(pcszDev);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync AssertPtr(pcszIface);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync AssertPtr(pcszDev);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync Assert(pcszIface[0] == '/');
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync Assert(pcszDev[0] == '/');
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync Assert(pcszDev[cchDev - 1] != '/');
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync /* If this passes, pcszIface is at least cchDev long */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (strncmp(pcszIface, pcszDev, cchDev))
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync return false;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync /* If this passes, pcszIface is longer than cchDev */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (pcszIface[cchDev] != '/')
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync return false;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync /* In sysfs an interface is an immediate subdirectory of the device */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (strchr(pcszIface + cchDev + 1, '/'))
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync return false;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync /* And it always has a colon in its name */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (!strchr(pcszIface + cchDev + 1, ':'))
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync return false;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync /* And hopefully we have now elimitated everything else */
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync return true;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync}
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsyncstatic bool muiHandle(pathHandler *pParent, const char *pcszNode)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync{
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync AssertPtrReturn(pParent, false);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync AssertReturn(pParent->handle == muiHandle, false);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync matchUSBInterface *pSelf = (matchUSBInterface *)pParent;
560a1042a968cf73161ac78555eddc8d16e8bebdvboxsync if (!muiIsAnInterfaceOf(pcszNode, pSelf->mInfo->mSysfsPath))
560a1042a968cf73161ac78555eddc8d16e8bebdvboxsync return true;
560a1042a968cf73161ac78555eddc8d16e8bebdvboxsync char *pcszDup = RTStrDup(pcszNode);
560a1042a968cf73161ac78555eddc8d16e8bebdvboxsync if (pcszDup)
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync if (USBInterfaceList_push_back(&pSelf->mInfo->mInterfaces, &pcszDup))
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync return true;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync RTStrFree(pcszDup);
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync return false;
feffb6492a600891a421e4c1bf0a2bcd2213568dvboxsync}
26645f447bb6a819f33492c84e03e364092ec600vboxsync
26645f447bb6a819f33492c84e03e364092ec600vboxsync/** This constructor is currently used to unit test the class logic in
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * debug builds. Since no access is made to anything outside the class,
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * this shouldn't cause any slowdown worth mentioning. */
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsyncstatic void muiInit(matchUSBInterface *pSelf, USBDeviceInfo *pInfo)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync{
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync Assert(muiIsAnInterfaceOf("/sys/devices/pci0000:00/0000:00:1a.0/usb3/3-0:1.0",
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync "/sys/devices/pci0000:00/0000:00:1a.0/usb3"));
Assert(!muiIsAnInterfaceOf("/sys/devices/pci0000:00/0000:00:1a.0/usb3/3-1",
"/sys/devices/pci0000:00/0000:00:1a.0/usb3"));
Assert(!muiIsAnInterfaceOf("/sys/devices/pci0000:00/0000:00:1a.0/usb3/3-0:1.0/driver",
"/sys/devices/pci0000:00/0000:00:1a.0/usb3"));
AssertPtrReturnVoid(pSelf);
pSelf->mInfo = pInfo;
pSelf->mParent.handle = muiHandle;
}
/**
* Helper function to query the sysfs subsystem for information about USB
* devices attached to the system.
* @returns iprt status code
* @param pList where to add information about the drives detected
* @param pfSuccess Did we find anything?
*
* @returns IPRT status code
*/
static int getUSBDeviceInfoFromSysfs(USBDeviceInfoList *pList,
bool *pfSuccess)
{
AssertPtrReturn(pList, VERR_INVALID_POINTER);
AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER); /* Valid or Null */
LogFlowFunc (("pList=%p, pfSuccess=%p\n",
pList, pfSuccess));
matchUSBDevice devHandler;
mudInit(&devHandler, pList);
int rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices", &devHandler.mParent);
do {
if (RT_FAILURE(rc))
break;
USBDeviceInfoList_iterator info;
USBDeviceInfoList_iter_init(&info,
USBDeviceInfoList_begin(pList));
while (!USBDeviceInfoList_iter_eq(&info,
USBDeviceInfoList_end(pList)))
{
matchUSBInterface ifaceHandler;
muiInit(&ifaceHandler, USBDeviceInfoList_iter_target(&info));
rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices",
&ifaceHandler.mParent);
if (RT_FAILURE(rc))
break;
USBDeviceInfoList_iter_incr(&info);
}
} while(0);
if (pfSuccess)
*pfSuccess = RT_SUCCESS(rc);
LogFlow (("rc=%Rrc\n", rc));
return rc;
}
# endif /* VBOX_USB_WITH_INOTIFY */
#endif /* VBOX_USB_WITH_SYSFS */