Changeset 85929 in vbox for trunk/src/VBox/Main/src-server/linux/HostHardwareLinux.cpp
- Timestamp:
- Aug 28, 2020 2:40:55 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/linux/HostHardwareLinux.cpp
r82968 r85929 1 1 /* $Id$ */ 2 2 /** @file 3 * Classes for handling hardware detection under Linux. Please feel free to 4 * expand these to work for other systems (Solaris!) or to add new ones for 5 * other systems. 3 * VirtualBox Main - Code for handling hardware detection under Linux, VBoxSVC. 6 4 */ 7 5 … … 18 16 */ 19 17 20 #define LOG_GROUP LOG_GROUP_MAIN21 22 18 23 19 /********************************************************************************************************************************* 24 20 * Header Files * 25 21 *********************************************************************************************************************************/ 26 27 #include <HostHardwareLinux.h> 28 #include <vector.h> 22 #define LOG_GROUP LOG_GROUP_MAIN 23 #include "HostHardwareLinux.h" 29 24 30 25 #include <VBox/err.h> … … 71 66 * Global Variables * 72 67 *********************************************************************************************************************************/ 73 74 68 #ifdef TESTCASE 75 69 static bool testing() { return true; } … … 87 81 * Typedefs and Defines * 88 82 *********************************************************************************************************************************/ 89 90 static int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList, 91 bool isDVD, bool *pfSuccess); 92 static int getDriveInfoFromSysfs(DriveInfoList *pList, bool isDVD, 93 bool *pfSuccess); 83 typedef enum SysfsWantDevice_T 84 { 85 DVD, 86 Floppy, 87 FixedDisk 88 } SysfsWantDevice_T; 89 90 91 /********************************************************************************************************************************* 92 * Internal Functions * 93 *********************************************************************************************************************************/ 94 static int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList, bool isDVD, bool *pfSuccess) RT_NOTHROW_PROTO; 95 static int getDriveInfoFromSysfs(DriveInfoList *pList, SysfsWantDevice_T wantDevice, bool *pfSuccess) RT_NOTHROW_PROTO; 96 94 97 95 98 /** Find the length of a string, ignoring trailing non-ascii or control 96 * characters */ 97 static size_t strLenStripped(const char *pcsz) 99 * characters 100 * @note Code duplicated in HostHardwareFreeBSD.cpp */ 101 static size_t strLenStripped(const char *pcsz) RT_NOTHROW_DEF 98 102 { 99 103 size_t cch = 0; 100 104 for (size_t i = 0; pcsz[i] != '\0'; ++i) 101 if (pcsz[i] > 32 && pcsz[i] < 127)105 if (pcsz[i] > 32 /*space*/ && pcsz[i] < 127 /*delete*/) 102 106 cch = i; 103 107 return cch + 1; … … 114 118 * @param pszName where to store the name retrieved 115 119 */ 116 static bool floppyGetName(const char *pcszNode, unsigned Number, 117 floppy_drive_name pszName) 120 static bool floppyGetName(const char *pcszNode, unsigned Number, floppy_drive_name pszName) RT_NOTHROW_DEF 118 121 { 119 122 AssertPtrReturn(pcszNode, false); … … 145 148 * FDC 1) 146 149 * @param pszDesc where to store the device description (optional) 147 * @param c chDescthe size of the buffer in @a pszDesc150 * @param cbDesc the size of the buffer in @a pszDesc 148 151 * @param pszUdi where to store the device UDI (optional) 149 * @param c chUdithe size of the buffer in @a pszUdi152 * @param cbUdi the size of the buffer in @a pszUdi 150 153 */ 151 static void floppyCreateDeviceStrings(const floppy_drive_name pcszName, 152 unsigned Number, char *pszDesc, 153 size_t cchDesc, char *pszUdi, 154 size_t cchUdi) 154 static void floppyCreateDeviceStrings(const floppy_drive_name pcszName, unsigned Number, 155 char *pszDesc, size_t cbDesc, char *pszUdi, size_t cbUdi) RT_NOTHROW_DEF 155 156 { 156 157 AssertPtrNullReturnVoid(pcszName); 157 158 AssertPtrNullReturnVoid(pszDesc); 158 AssertReturnVoid(!pszDesc || c chDesc > 0);159 AssertReturnVoid(!pszDesc || cbDesc > 0); 159 160 AssertPtrNullReturnVoid(pszUdi); 160 AssertReturnVoid(!pszUdi || c chUdi > 0);161 AssertReturnVoid(!pszUdi || cbUdi > 0); 161 162 AssertReturnVoid(Number <= 7); 162 163 if (pcszName) … … 175 176 } 176 177 if (pszDesc) 177 RTStrPrintf(pszDesc, c chDesc, "%s %s K%s", pcszSize, &pcszName[1],178 RTStrPrintf(pszDesc, cbDesc, "%s %s K%s", pcszSize, &pcszName[1], 178 179 Number > 3 ? ", FDC 2" : ""); 179 180 } … … 181 182 { 182 183 if (pszDesc) 183 RTStrPrintf(pszDesc, c chDesc, "FDD %d%s", (Number & 4) + 1,184 RTStrPrintf(pszDesc, cbDesc, "FDD %d%s", (Number & 4) + 1, 184 185 Number > 3 ? ", FDC 2" : ""); 185 186 } 186 187 if (pszUdi) 187 RTStrPrintf(pszUdi, c chUdi,188 RTStrPrintf(pszUdi, cbUdi, 188 189 "/org/freedesktop/Hal/devices/platform_floppy_%u_storage", 189 190 Number); … … 194 195 * Check whether a device number might correspond to a CD-ROM device according 195 196 * to Documentation/devices.txt in the Linux kernel source. 197 * 196 198 * @returns true if it might, false otherwise 197 199 * @param Number the device number (major and minor combination) 198 200 */ 199 static bool isCdromDevNum(dev_t Number) 201 static bool isCdromDevNum(dev_t Number) RT_NOTHROW_DEF 200 202 { 201 203 int major = major(Number); 202 204 int minor = minor(Number); 203 if ( (major == IDE0_MAJOR)&& !(minor & 0x3f))205 if (major == IDE0_MAJOR && !(minor & 0x3f)) 204 206 return true; 205 207 if (major == SCSI_CDROM_MAJOR) … … 215 217 if (major == MITSUMI_X_CDROM_MAJOR) 216 218 return true; 217 if ( (major == IDE1_MAJOR)&& !(minor & 0x3f))219 if (major == IDE1_MAJOR && !(minor & 0x3f)) 218 220 return true; 219 221 if (major == MITSUMI_CDROM_MAJOR) … … 235 237 if (major == CM206_CDROM_MAJOR) 236 238 return true; 237 if ( (major == IDE3_MAJOR)&& !(minor & 0x3f))239 if (major == IDE3_MAJOR && !(minor & 0x3f)) 238 240 return true; 239 241 if (major == 46 /* Parallel port ATAPI CD-ROM */) /* no #define */ 240 242 return true; 241 if ( (major == IDE4_MAJOR)&& !(minor & 0x3f))242 return true; 243 if ( (major == IDE5_MAJOR)&& !(minor & 0x3f))244 return true; 245 if ( (major == IDE6_MAJOR)&& !(minor & 0x3f))246 return true; 247 if ( (major == IDE7_MAJOR)&& !(minor & 0x3f))248 return true; 249 if ( (major == IDE8_MAJOR)&& !(minor & 0x3f))250 return true; 251 if ( (major == IDE9_MAJOR)&& !(minor & 0x3f))243 if (major == IDE4_MAJOR && !(minor & 0x3f)) 244 return true; 245 if (major == IDE5_MAJOR && !(minor & 0x3f)) 246 return true; 247 if (major == IDE6_MAJOR && !(minor & 0x3f)) 248 return true; 249 if (major == IDE7_MAJOR && !(minor & 0x3f)) 250 return true; 251 if (major == IDE8_MAJOR && !(minor & 0x3f)) 252 return true; 253 if (major == IDE9_MAJOR && !(minor & 0x3f)) 252 254 return true; 253 255 if (major == 113 /* VIOCD_MAJOR */) … … 259 261 /** 260 262 * Send an SCSI INQUIRY command to a device and return selected information. 263 * 261 264 * @returns iprt status code 262 * @ret urnsVERR_TRY_AGAIN if the query failed but might succeed next time265 * @retval VERR_TRY_AGAIN if the query failed but might succeed next time 263 266 * @param pcszNode the full path to the device node 264 * @param p u8Typewhere to store the SCSI device type on success (optional)265 * @param p chVendor where to store the vendor id string on success (optional)266 * @param c chVendor the size of the @a pchVendor buffer267 * @param p chModel where to store the product id string on success (optional)268 * @param cchModel the size of the @a p chModel buffer267 * @param pbType where to store the SCSI device type on success (optional) 268 * @param pszVendor where to store the vendor id string on success (optional) 269 * @param cbVendor the size of the @a pszVendor buffer 270 * @param pszModel where to store the product id string on success (optional) 271 * @param cchModel the size of the @a pszModel buffer 269 272 * @note check documentation on the SCSI INQUIRY command and the Linux kernel 270 273 * SCSI headers included above if you want to understand what is going 271 274 * on in this method. 272 275 */ 273 static int cdromDoInquiry(const char *pcszNode, uint8_t *pu8Type, 274 char *pchVendor, size_t cchVendor, char *pchModel, 275 size_t cchModel) 276 { 277 LogRelFlowFunc(("pcszNode=%s, pu8Type=%p, pchVendor=%p, cchVendor=%llu, pchModel=%p, cchModel=%llu\n", 278 pcszNode, pu8Type, pchVendor, cchVendor, pchModel, 279 cchModel)); 276 static int cdromDoInquiry(const char *pcszNode, uint8_t *pbType, char *pszVendor, size_t cbVendor, 277 char *pszModel, size_t cbModel) RT_NOTHROW_DEF 278 { 279 LogRelFlowFunc(("pcszNode=%s, pbType=%p, pszVendor=%p, cbVendor=%zu, pszModel=%p, cbModel=%zu\n", 280 pcszNode, pbType, pszVendor, cbVendor, pszModel, cbModel)); 280 281 AssertPtrReturn(pcszNode, VERR_INVALID_POINTER); 281 AssertPtrNullReturn(p u8Type, VERR_INVALID_POINTER);282 AssertPtrNullReturn(p chVendor, VERR_INVALID_POINTER);283 AssertPtrNullReturn(p chModel, VERR_INVALID_POINTER);284 285 RTFILE hFile ;282 AssertPtrNullReturn(pbType, VERR_INVALID_POINTER); 283 AssertPtrNullReturn(pszVendor, VERR_INVALID_POINTER); 284 AssertPtrNullReturn(pszModel, VERR_INVALID_POINTER); 285 286 RTFILE hFile = NIL_RTFILE; 286 287 int rc = RTFileOpen(&hFile, pcszNode, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_NON_BLOCK); 287 288 if (RT_SUCCESS(rc)) 288 289 { 289 int rcIoCtl = 0;290 unsigned char u8Response[96] = { 0 };290 int rcIoCtl = 0; 291 unsigned char auchResponse[96] = { 0 }; 291 292 struct cdrom_generic_command CdromCommandReq; 292 293 RT_ZERO(CdromCommandReq); 293 294 CdromCommandReq.cmd[0] = INQUIRY; 294 CdromCommandReq.cmd[4] = sizeof( u8Response);295 CdromCommandReq.buffer = u8Response;296 CdromCommandReq.buflen = sizeof( u8Response);295 CdromCommandReq.cmd[4] = sizeof(auchResponse); 296 CdromCommandReq.buffer = auchResponse; 297 CdromCommandReq.buflen = sizeof(auchResponse); 297 298 CdromCommandReq.data_direction = CGC_DATA_READ; 298 299 CdromCommandReq.timeout = 5000; /* ms */ … … 304 305 if (RT_SUCCESS(rc)) 305 306 { 306 if (pu8Type) 307 *pu8Type = u8Response[0] & 0x1f; 308 if (pchVendor) 309 RTStrPrintf(pchVendor, cchVendor, "%.8s", 310 &u8Response[8] /* vendor id string */); 311 if (pchModel) 312 RTStrPrintf(pchModel, cchModel, "%.16s", 313 &u8Response[16] /* product id string */); 307 if (pbType) 308 *pbType = auchResponse[0] & 0x1f; 309 if (pszVendor) 310 { 311 RTStrPrintf(pszVendor, cbVendor, "%.8s", &auchResponse[8] /* vendor id string */); 312 RTStrPurgeEncoding(pszVendor); 313 } 314 if (pszModel) 315 { 316 RTStrPrintf(pszModel, cbModel, "%.16s", &auchResponse[16] /* product id string */); 317 RTStrPurgeEncoding(pszModel); 318 } 314 319 LogRelFlowFunc(("returning success: type=%u, vendor=%.8s, product=%.16s\n", 315 u8Response[0] & 0x1f, &u8Response[8], &u8Response[16]));320 auchResponse[0] & 0x1f, &auchResponse[8], &auchResponse[16])); 316 321 return VINF_SUCCESS; 317 322 } … … 328 333 * @param pcszModel the product ID string 329 334 * @param pszDesc where to store the description string (optional) 330 * @param c chDescthe size of the buffer in @a pszDesc335 * @param cbDesc the size of the buffer in @a pszDesc 331 336 * @param pszUdi where to store the UDI string (optional) 332 * @param cchUdi the size of the buffer in @a pszUdi 337 * @param cbUdi the size of the buffer in @a pszUdi 338 * 339 * @note Used for more than DVDs these days. 333 340 */ 334 /* static */ 335 void dvdCreateDeviceStrings(const char *pcszVendor, const char *pcszModel, 336 char *pszDesc, size_t cchDesc, char *pszUdi, 337 size_t cchUdi) 341 static void dvdCreateDeviceStrings(const char *pcszVendor, const char *pcszModel, 342 char *pszDesc, size_t cbDesc, char *pszUdi, size_t cbUdi) RT_NOEXCEPT 338 343 { 339 344 AssertPtrReturnVoid(pcszVendor); 340 345 AssertPtrReturnVoid(pcszModel); 341 346 AssertPtrNullReturnVoid(pszDesc); 342 AssertReturnVoid(!pszDesc || c chDesc > 0);347 AssertReturnVoid(!pszDesc || cbDesc > 0); 343 348 AssertPtrNullReturnVoid(pszUdi); 344 AssertReturnVoid(!pszUdi || c chUdi > 0);345 char szCleaned[128]; 349 AssertReturnVoid(!pszUdi || cbUdi > 0); 350 346 351 size_t cchVendor = strLenStripped(pcszVendor); 347 352 size_t cchModel = strLenStripped(pcszModel); 348 353 349 354 /* Create a cleaned version of the model string for the UDI string. */ 355 char szCleaned[128]; 350 356 for (unsigned i = 0; i < sizeof(szCleaned) && pcszModel[i] != '\0'; ++i) 351 357 if ( (pcszModel[i] >= '0' && pcszModel[i] <= '9') … … 360 366 { 361 367 if (cchVendor > 0) 362 RTStrPrintf(pszDesc, cchDesc, "%.*s %s", cchVendor, pcszVendor, 363 cchModel > 0 ? pcszModel : "(unknown drive model)"); 368 { 369 RTStrPrintf(pszDesc, cbDesc, "%.*s %s", cchVendor, pcszVendor, cchModel > 0 ? pcszModel : "(unknown drive model)"); 370 RTStrPurgeEncoding(pszDesc); 371 } 364 372 else 365 RTStr Printf(pszDesc, cchDesc, "%s", pcszModel);373 RTStrCopy(pszDesc, cbDesc, pcszModel); 366 374 } 367 375 /* Construct the UDI string */ … … 369 377 { 370 378 if (cchModel > 0) 371 RTStrPrintf(pszUdi, cchUdi, 372 "/org/freedesktop/Hal/devices/storage_model_%s", 373 szCleaned); 379 RTStrPrintf(pszUdi, cbUdi, "/org/freedesktop/Hal/devices/storage_model_%s", szCleaned); 374 380 else 375 381 pszUdi[0] = '\0'; … … 381 387 * Check whether a device node points to a valid device and create a UDI and 382 388 * a description for it, and store the device number, if it does. 389 * 383 390 * @returns true if the device is valid, false otherwise 384 391 * @param pcszNode the path to the device node … … 386 393 * @param pDevice where to store the device node (optional) 387 394 * @param pszDesc where to store the device description (optional) 388 * @param c chDescthe size of the buffer in @a pszDesc395 * @param cbDesc the size of the buffer in @a pszDesc 389 396 * @param pszUdi where to store the device UDI (optional) 390 * @param c chUdithe size of the buffer in @a pszUdi397 * @param cbUdi the size of the buffer in @a pszUdi 391 398 */ 392 399 static bool devValidateDevice(const char *pcszNode, bool isDVD, dev_t *pDevice, 393 char *pszDesc, size_t cchDesc, char *pszUdi, 394 size_t cchUdi) 400 char *pszDesc, size_t cbDesc, char *pszUdi, size_t cbUdi) RT_NOTHROW_DEF 395 401 { 396 402 AssertPtrReturn(pcszNode, false); 397 403 AssertPtrNullReturn(pDevice, false); 398 404 AssertPtrNullReturn(pszDesc, false); 399 AssertReturn(!pszDesc || c chDesc > 0, false);405 AssertReturn(!pszDesc || cbDesc > 0, false); 400 406 AssertPtrNullReturn(pszUdi, false); 401 AssertReturn(!pszUdi || cchUdi > 0, false); 407 AssertReturn(!pszUdi || cbUdi > 0, false); 408 402 409 RTFSOBJINFO ObjInfo; 403 410 if (RT_FAILURE(RTPathQueryInfo(pcszNode, &ObjInfo, RTFSOBJATTRADD_UNIX))) … … 407 414 if (pDevice) 408 415 *pDevice = ObjInfo.Attr.u.Unix.Device; 416 409 417 if (isDVD) 410 418 { … … 419 427 if (u8Type != TYPE_ROM) 420 428 return false; 421 dvdCreateDeviceStrings(szVendor, szModel, pszDesc, cchDesc, 422 pszUdi, cchUdi); 429 dvdCreateDeviceStrings(szVendor, szModel, pszDesc, cbDesc, pszUdi, cbUdi); 423 430 } 424 431 else 425 432 { 426 /* Floppies on Linux are legacy devices with hardcoded majors and 427 * minors */ 428 unsigned Number; 429 floppy_drive_name szName; 433 /* Floppies on Linux are legacy devices with hardcoded majors and minors */ 430 434 if (major(ObjInfo.Attr.u.Unix.Device) != FLOPPY_MAJOR) 431 435 return false; 436 437 unsigned Number; 432 438 switch (minor(ObjInfo.Attr.u.Unix.Device)) 433 439 { … … 441 447 return false; 442 448 } 449 450 floppy_drive_name szName; 443 451 if (!floppyGetName(pcszNode, Number, szName)) 444 452 return false; 445 floppyCreateDeviceStrings(szName, Number, pszDesc, cchDesc, pszUdi, 446 cchUdi); 453 floppyCreateDeviceStrings(szName, Number, pszDesc, cbDesc, pszUdi, cbUdi); 447 454 } 448 455 return true; … … 450 457 451 458 452 int VBoxMainDriveInfo::updateDVDs ()459 int VBoxMainDriveInfo::updateDVDs() RT_NOEXCEPT 453 460 { 454 461 LogFlowThisFunc(("entered\n")); 455 int rc = VINF_SUCCESS; 456 bool success = false; /* Have we succeeded in finding anything yet? */ 462 int rc; 457 463 try 458 464 { 459 mDVDList.clear 465 mDVDList.clear(); 460 466 /* Always allow the user to override our auto-detection using an 461 467 * environment variable. */ 462 if (RT_SUCCESS(rc) && (!success || testing())) 463 rc = getDriveInfoFromEnv ("VBOX_CDROM", &mDVDList, true /* isDVD */, 464 &success); 468 bool fSuccess = false; /* Have we succeeded in finding anything yet? */ 469 rc = getDriveInfoFromEnv("VBOX_CDROM", &mDVDList, true /* isDVD */, &fSuccess); 465 470 setNoProbe(false); 466 if (RT_SUCCESS(rc) && (! success || testing()))467 rc = getDriveInfoFromSysfs(&mDVDList, true /* isDVD */, &success);471 if (RT_SUCCESS(rc) && (!fSuccess || testing())) 472 rc = getDriveInfoFromSysfs(&mDVDList, DVD, &fSuccess); 468 473 if (RT_SUCCESS(rc) && testing()) 469 474 { 470 475 setNoProbe(true); 471 rc = getDriveInfoFromSysfs(&mDVDList, true /* isDVD */, &success);472 } 473 } 474 catch (std::bad_alloc &e)476 rc = getDriveInfoFromSysfs(&mDVDList, DVD, &fSuccess); 477 } 478 } 479 catch (std::bad_alloc &e) 475 480 { 476 481 rc = VERR_NO_MEMORY; … … 480 485 } 481 486 482 int VBoxMainDriveInfo::updateFloppies ()487 int VBoxMainDriveInfo::updateFloppies() RT_NOEXCEPT 483 488 { 484 489 LogFlowThisFunc(("entered\n")); 485 int rc = VINF_SUCCESS; 486 bool success = false; /* Have we succeeded in finding anything yet? */ 490 int rc; 487 491 try 488 492 { 489 mFloppyList.clear (); 490 if (RT_SUCCESS(rc) && (!success || testing())) 491 rc = getDriveInfoFromEnv("VBOX_FLOPPY", &mFloppyList, 492 false /* isDVD */, &success); 493 mFloppyList.clear(); 494 bool fSuccess = false; /* Have we succeeded in finding anything yet? */ 495 rc = getDriveInfoFromEnv("VBOX_FLOPPY", &mFloppyList, false /* isDVD */, &fSuccess); 493 496 setNoProbe(false); 494 if ( RT_SUCCESS(rc) && (!success || testing())) 495 rc = getDriveInfoFromSysfs(&mFloppyList, false /* isDVD */, 496 &success); 497 if (RT_SUCCESS(rc) && (!fSuccess || testing())) 498 rc = getDriveInfoFromSysfs(&mFloppyList, Floppy, &fSuccess); 497 499 if (RT_SUCCESS(rc) && testing()) 498 500 { 499 501 setNoProbe(true); 500 rc = getDriveInfoFromSysfs(&mFloppyList, false /* isDVD */, &success);501 } 502 } 503 catch (std::bad_alloc &e)502 rc = getDriveInfoFromSysfs(&mFloppyList, Floppy, &fSuccess); 503 } 504 } 505 catch (std::bad_alloc &) 504 506 { 505 507 rc = VERR_NO_MEMORY; … … 507 509 LogFlowThisFunc(("rc=%Rrc\n", rc)); 508 510 return rc; 511 } 512 513 int VBoxMainDriveInfo::updateFixedDrives() RT_NOEXCEPT 514 { 515 LogFlowThisFunc(("entered\n")); 516 int vrc; 517 try 518 { 519 mFixedDriveList.clear(); 520 setNoProbe(false); 521 bool fSuccess = false; /* Have we succeeded in finding anything yet? */ 522 vrc = getDriveInfoFromSysfs(&mFixedDriveList, FixedDisk, &fSuccess); 523 if (RT_SUCCESS(vrc) && testing()) 524 { 525 setNoProbe(true); 526 vrc = getDriveInfoFromSysfs(&mFixedDriveList, FixedDisk, &fSuccess); 527 } 528 } 529 catch (std::bad_alloc &) 530 { 531 vrc = VERR_NO_MEMORY; 532 } 533 LogFlowThisFunc(("vrc=%Rrc\n", vrc)); 534 return vrc; 509 535 } 510 536 … … 513 539 * Extract the names of drives from an environment variable and add them to a 514 540 * list if they are valid. 541 * 515 542 * @returns iprt status code 516 543 * @param pcszVar the name of the environment variable. The variable … … 521 548 * @param pfSuccess this will be set to true if we found at least one drive 522 549 * and to false otherwise. Optional. 550 * 551 * @note This is duplicated in HostHardwareFreeBSD.cpp. 523 552 */ 524 /* static */ 525 int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList, 526 bool isDVD, bool *pfSuccess) 553 static int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList, bool isDVD, bool *pfSuccess) RT_NOTHROW_DEF 527 554 { 528 555 AssertPtrReturn(pcszVar, VERR_INVALID_POINTER); 529 556 AssertPtrReturn(pList, VERR_INVALID_POINTER); 530 557 AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER); 531 LogFlowFunc(("pcszVar=%s, pList=%p, isDVD=%d, pfSuccess=%p\n", pcszVar, 532 pList, isDVD, pfSuccess)); 558 LogFlowFunc(("pcszVar=%s, pList=%p, isDVD=%d, pfSuccess=%p\n", pcszVar, pList, isDVD, pfSuccess)); 533 559 int rc = VINF_SUCCESS; 534 560 bool success = false; … … 537 563 try 538 564 { 539 const char *pcszCurrent = pszFreeMe; 540 while (pcszCurrent && *pcszCurrent != '\0') 541 { 542 const char *pcszNext = strchr(pcszCurrent, ':'); 543 char szPath[RTPATH_MAX], szReal[RTPATH_MAX]; 565 char *pszCurrent = pszFreeMe; 566 while (pszCurrent && *pszCurrent != '\0') 567 { 568 char *pszNext = strchr(pszCurrent, ':'); 569 if (pszNext) 570 *pszNext++ = '\0'; 571 572 char szReal[RTPATH_MAX]; 544 573 char szDesc[256], szUdi[256]; 545 if (pcszNext) 546 RTStrPrintf(szPath, sizeof(szPath), "%.*s", 547 pcszNext - pcszCurrent - 1, pcszCurrent); 548 else 549 RTStrPrintf(szPath, sizeof(szPath), "%s", pcszCurrent); 550 if ( RT_SUCCESS(RTPathReal(szPath, szReal, sizeof(szReal))) 551 && devValidateDevice(szReal, isDVD, NULL, szDesc, 552 sizeof(szDesc), szUdi, sizeof(szUdi))) 574 if ( RT_SUCCESS(RTPathReal(pszCurrent, szReal, sizeof(szReal))) 575 && devValidateDevice(szReal, isDVD, NULL, szDesc, sizeof(szDesc), szUdi, sizeof(szUdi))) 553 576 { 554 577 pList->push_back(DriveInfo(szReal, szUdi, szDesc)); 555 578 success = true; 556 579 } 557 p cszCurrent = pcszNext ? pcszNext + 1 : NULL;580 pszCurrent = pszNext; 558 581 } 559 582 if (pfSuccess != NULL) 560 583 *pfSuccess = success; 561 584 } 562 catch (std::bad_alloc &e)585 catch (std::bad_alloc &) 563 586 { 564 587 rc = VERR_NO_MEMORY; … … 570 593 571 594 572 class sysfsBlockDev595 class SysfsBlockDev 573 596 { 574 597 public: 575 sysfsBlockDev(const char *pcszName, bool wantDVD) 576 : mpcszName(pcszName), mwantDVD(wantDVD), misConsistent(true), 577 misValid(false) 598 SysfsBlockDev(const char *pcszName, SysfsWantDevice_T wantDevice) RT_NOEXCEPT 599 : mpcszName(pcszName), mWantDevice(wantDevice), misConsistent(true), misValid(false) 578 600 { 579 601 if (findDeviceNode()) 580 602 { 581 if (mwantDVD) 582 validateAndInitForDVD(); 583 else 584 validateAndInitForFloppy(); 603 switch (mWantDevice) 604 { 605 case DVD: validateAndInitForDVD(); break; 606 case Floppy: validateAndInitForFloppy(); break; 607 default: validateAndInitForFixedDisk(); break; 608 } 585 609 } 586 610 } … … 588 612 /** The name of the subdirectory of /sys/block for this device */ 589 613 const char *mpcszName; 590 /** Are we looking for a floppy or a DVDdevice? */591 bool mwantDVD;614 /** Are we looking for a floppy, a DVD or a fixed disk device? */ 615 SysfsWantDevice_T mWantDevice; 592 616 /** The device node for the device */ 593 617 char mszNode[RTPATH_MAX]; … … 609 633 * @returns boolean success value 610 634 */ 611 bool findDeviceNode() 635 bool findDeviceNode() RT_NOEXCEPT 612 636 { 613 637 dev_t dev = 0; … … 618 642 return false; 619 643 } 620 rc = RTLinuxCheckDevicePath(dev, RTFS_TYPE_DEV_BLOCK, mszNode, 621 sizeof(mszNode), "%s", mpcszName); 622 if (RT_FAILURE(rc)) 623 return false; 624 return true; 644 rc = RTLinuxCheckDevicePath(dev, RTFS_TYPE_DEV_BLOCK, mszNode, sizeof(mszNode), "%s", mpcszName); 645 return RT_SUCCESS(rc); 625 646 } 626 647 … … 630 651 * poking the device, and if that fails we fall back to an SCSI INQUIRY 631 652 * command. */ 632 void validateAndInitForDVD() 633 { 634 char szVendor[128], szModel[128]; 653 void validateAndInitForDVD() RT_NOEXCEPT 654 { 635 655 int64_t type = 0; 636 656 int rc = RTLinuxSysFsReadIntFile(10, &type, "block/%s/device/type", mpcszName); … … 639 659 if (type == TYPE_ROM) 640 660 { 641 rc = RTLinuxSysFsReadStrFile(szVendor, sizeof(szVendor), NULL,642 661 char szVendor[128]; 662 rc = RTLinuxSysFsReadStrFile(szVendor, sizeof(szVendor), NULL, "block/%s/device/vendor", mpcszName); 643 663 if (RT_SUCCESS(rc)) 644 664 { 645 rc = RTLinuxSysFsReadStrFile(szModel, sizeof(szModel), NULL,646 665 char szModel[128]; 666 rc = RTLinuxSysFsReadStrFile(szModel, sizeof(szModel), NULL, "block/%s/device/model", mpcszName); 647 667 if (RT_SUCCESS(rc)) 648 668 { 649 669 misValid = true; 650 dvdCreateDeviceStrings(szVendor, szModel, 651 mszDesc, sizeof(mszDesc), 652 mszUdi, sizeof(mszUdi)); 670 dvdCreateDeviceStrings(szVendor, szModel, mszDesc, sizeof(mszDesc), mszUdi, sizeof(mszUdi)); 653 671 return; 654 672 } … … 663 681 * data members for the object based on the returned data. 664 682 */ 665 void probeAndInitForDVD() 683 void probeAndInitForDVD() RT_NOEXCEPT 666 684 { 667 685 AssertReturnVoid(mszNode[0] != '\0'); 668 uint8_t u8Type = 0;686 uint8_t bType = 0; 669 687 char szVendor[128] = ""; 670 688 char szModel[128] = ""; 671 int rc = cdromDoInquiry(mszNode, &u8Type, szVendor, 672 sizeof(szVendor), szModel, 673 sizeof(szModel)); 674 if (RT_SUCCESS(rc) && (u8Type == TYPE_ROM)) 689 int rc = cdromDoInquiry(mszNode, &bType, szVendor, sizeof(szVendor), szModel, sizeof(szModel)); 690 if (RT_SUCCESS(rc) && bType == TYPE_ROM) 675 691 { 676 692 misValid = true; 677 dvdCreateDeviceStrings(szVendor, szModel, mszDesc, sizeof(mszDesc), 678 mszUdi, sizeof(mszUdi)); 693 dvdCreateDeviceStrings(szVendor, szModel, mszDesc, sizeof(mszDesc), mszUdi, sizeof(mszUdi)); 679 694 } 680 695 } … … 684 699 * support floppies using the basic "floppy" driver, we check the driver 685 700 * using the entry name and a driver-specific ioctl. */ 686 void validateAndInitForFloppy() 687 { 688 bool haveName = false; 701 void validateAndInitForFloppy() RT_NOEXCEPT 702 { 689 703 floppy_drive_name szName; 690 704 char szDriver[8]; … … 695 709 || mpcszName[3] != '\0') 696 710 return; 711 bool fHaveName = false; 697 712 if (!noProbe()) 698 haveName = floppyGetName(mszNode, mpcszName[2] - '0', szName);713 fHaveName = floppyGetName(mszNode, mpcszName[2] - '0', szName); 699 714 int rc = RTLinuxSysFsGetLinkDest(szDriver, sizeof(szDriver), NULL, "block/%s/%s", 700 715 mpcszName, "device/driver"); … … 704 719 return; 705 720 } 706 else if (! haveName)721 else if (!fHaveName) 707 722 return; 708 floppyCreateDeviceStrings( haveName ? szName : NULL,723 floppyCreateDeviceStrings(fHaveName ? szName : NULL, 709 724 mpcszName[2] - '0', mszDesc, 710 725 sizeof(mszDesc), mszUdi, sizeof(mszUdi)); … … 712 727 } 713 728 729 void validateAndInitForFixedDisk() RT_NOEXCEPT 730 { 731 /* 732 * For current task only device path is needed. Therefore, device probing 733 * is skipped and other fields are empty if there aren't files in the 734 * device entry. 735 */ 736 int64_t type = 0; 737 int rc = RTLinuxSysFsReadIntFile(10, &type, "block/%s/device/type", mpcszName); 738 if (RT_SUCCESS(rc) && type != TYPE_DISK) 739 return; 740 char szVendor[128]; 741 rc = RTLinuxSysFsReadStrFile(szVendor, sizeof(szVendor), NULL, "block/%s/device/vendor", mpcszName); 742 if (RT_SUCCESS(rc)) 743 { 744 char szModel[128]; 745 rc = RTLinuxSysFsReadStrFile(szModel, sizeof(szModel), NULL, "block/%s/device/model", mpcszName); 746 if (RT_SUCCESS(rc)) 747 { 748 misValid = true; 749 dvdCreateDeviceStrings(szVendor, szModel, mszDesc, sizeof(mszDesc), mszUdi, sizeof(mszUdi)); 750 return; 751 } 752 } 753 } 754 714 755 public: 715 bool isConsistent() 756 bool isConsistent() const RT_NOEXCEPT 716 757 { 717 758 return misConsistent; 718 759 } 719 bool isValid() 760 bool isValid() const RT_NOEXCEPT 720 761 { 721 762 return misValid; 722 763 } 723 const char *getDesc() 764 const char *getDesc() const RT_NOEXCEPT 724 765 { 725 766 return mszDesc; 726 767 } 727 const char *getUdi() 768 const char *getUdi() const RT_NOEXCEPT 728 769 { 729 770 return mszUdi; 730 771 } 731 const char *getNode() 772 const char *getNode() const RT_NOEXCEPT 732 773 { 733 774 return mszNode; … … 739 780 * drives attached to the system. 740 781 * @returns iprt status code 741 * @param pList where to add information about the drives detected742 * @param isDVD are we looking for DVDs or floppies?743 * @param pfSuccess Did we find anything?782 * @param pList where to add information about the drives detected 783 * @param wantDevice The kind of devices we're looking for. 784 * @param pfSuccess Did we find anything? 744 785 * 745 786 * @returns IPRT status code 787 * @throws Nothing. 746 788 */ 747 /* static */ 748 int getDriveInfoFromSysfs(DriveInfoList *pList, bool isDVD, bool *pfSuccess) 789 static int getDriveInfoFromSysfs(DriveInfoList *pList, SysfsWantDevice_T wantDevice, bool *pfSuccess) RT_NOTHROW_DEF 749 790 { 750 791 AssertPtrReturn(pList, VERR_INVALID_POINTER); 751 792 AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER); /* Valid or Null */ 752 LogFlowFunc (("pList=%p, isDVD=%u, pfSuccess=%p\n", 753 pList, (unsigned) isDVD, pfSuccess)); 754 RTDIR hDir; 755 int rc; 756 bool fSuccess = false; 757 unsigned cFound = 0; 758 793 LogFlowFunc (("pList=%p, wantDevice=%u, pfSuccess=%p\n", 794 pList, (unsigned)wantDevice, pfSuccess)); 759 795 if (!RTPathExists("/sys")) 760 796 return VINF_SUCCESS; 761 rc = RTDirOpen(&hDir, "/sys/block"); 797 798 bool fSuccess = true; 799 unsigned cFound = 0; 800 RTDIR hDir = NIL_RTDIR; 801 int rc = RTDirOpen(&hDir, "/sys/block"); 762 802 /* This might mean that sysfs semantics have changed */ 763 803 AssertReturn(rc != VERR_FILE_NOT_FOUND, VINF_SUCCESS); 764 fSuccess = true;765 804 if (RT_SUCCESS(rc)) 766 805 { … … 774 813 if (entry.szName[0] == '.') 775 814 continue; 776 sysfsBlockDev dev(entry.szName, isDVD);815 SysfsBlockDev dev(entry.szName, wantDevice); 777 816 /* This might mean that sysfs semantics have changed */ 778 817 AssertBreakStmt(dev.isConsistent(), fSuccess = false); … … 783 822 pList->push_back(DriveInfo(dev.getNode(), dev.getUdi(), dev.getDesc())); 784 823 } 785 catch (std::bad_alloc &e)824 catch (std::bad_alloc &e) 786 825 { 787 826 rc = VERR_NO_MEMORY; … … 794 833 if (rc == VERR_NO_MORE_FILES) 795 834 rc = VINF_SUCCESS; 796 if (RT_FAILURE(rc))835 else if (RT_FAILURE(rc)) 797 836 /* Clean up again */ 798 for (unsigned i = 0; i < cFound; ++i)837 while (cFound-- > 0) 799 838 pList->pop_back(); 800 839 if (pfSuccess) 801 840 *pfSuccess = fSuccess; 802 LogFlow (("rc=%Rrc, fSuccess=%u\n", rc, (unsigned) 841 LogFlow (("rc=%Rrc, fSuccess=%u\n", rc, (unsigned)fSuccess)); 803 842 return rc; 804 843 } … … 807 846 /** Helper for readFilePathsFromDir(). Adds a path to the vector if it is not 808 847 * NULL and not a dotfile (".", "..", ".*"). */ 809 static int maybeAddPathToVector(const char *pcszPath, const char *pcszEntry, 810 VECTOR_PTR(char *) *pvecpchDevs) 811 { 812 char *pszPath; 813 848 static int maybeAddPathToVector(const char *pcszPath, const char *pcszEntry, VECTOR_PTR(char *) *pvecpchDevs) RT_NOTHROW_DEF 849 { 814 850 if (!pcszPath) 815 851 return 0; 816 852 if (pcszEntry[0] == '.') 817 853 return 0; 818 pszPath = RTStrDup(pcszPath); 819 if (!pszPath) 820 return ENOMEM; 821 if (RT_FAILURE(VEC_PUSH_BACK_PTR(pvecpchDevs, char *, pszPath))) 822 return ENOMEM; 823 return 0; 824 } 825 826 /** Helper for readFilePaths(). Adds the entries from the open directory 827 * @a pDir to the vector @a pvecpchDevs using either the full path or the 828 * realpath() and skipping hidden files and files on which realpath() fails. */ 829 static int readFilePathsFromDir(const char *pcszPath, DIR *pDir, 830 VECTOR_PTR(char *) *pvecpchDevs, int withRealPath) 854 char *pszPath = RTStrDup(pcszPath); 855 if (pszPath) 856 { 857 int vrc = VEC_PUSH_BACK_PTR(pvecpchDevs, char *, pszPath); 858 if (RT_SUCCESS(vrc)) 859 return 0; 860 } 861 return ENOMEM; 862 } 863 864 /** 865 * Helper for readFilePaths(). 866 * 867 * Adds the entries from the open directory @a pDir to the vector @a pvecpchDevs 868 * using either the full path or the realpath() and skipping hidden files 869 * and files on which realpath() fails. 870 */ 871 static int readFilePathsFromDir(const char *pcszPath, DIR *pDir, VECTOR_PTR(char *) *pvecpchDevs, int withRealPath) RT_NOTHROW_DEF 831 872 { 832 873 struct dirent entry, *pResult; … … 837 878 # pragma GCC diagnostic ignored "-Wdeprecated-declarations" 838 879 #endif 839 for (err = readdir_r(pDir, &entry, &pResult); pResult; 880 for (err = readdir_r(pDir, &entry, &pResult); 881 pResult /** @todo r=bird: && err == 0 ? */; 840 882 err = readdir_r(pDir, &entry, &pResult)) 841 883 #if RT_GNUC_PREREQ(4, 6) … … 869 911 * @param withRealPath whether to canonicalise the filename with realpath 870 912 */ 871 static int readFilePaths(const char *pcszPath, VECTOR_PTR(char *) *pvecpchDevs, 872 int withRealPath) 873 { 874 DIR *pDir; 875 int err; 876 913 static int readFilePaths(const char *pcszPath, VECTOR_PTR(char *) *pvecpchDevs, int withRealPath) RT_NOTHROW_DEF 914 { 877 915 AssertPtrReturn(pvecpchDevs, EINVAL); 878 916 AssertReturn(VEC_SIZE_PTR(pvecpchDevs) == 0, EINVAL); 879 917 AssertPtrReturn(pcszPath, EINVAL); 880 918 881 pDir = opendir(pcszPath);919 DIR *pDir = opendir(pcszPath); 882 920 if (!pDir) 883 921 return RTErrConvertFromErrno(errno); 884 err = readFilePathsFromDir(pcszPath, pDir, pvecpchDevs, withRealPath);922 int err = readFilePathsFromDir(pcszPath, pDir, pvecpchDevs, withRealPath); 885 923 if (closedir(pDir) < 0 && !err) 886 924 err = errno; … … 1262 1300 mImpl = new hotplugNullImpl(pcszDevicesRoot); 1263 1301 } 1264 catch (std::bad_alloc &e)1302 catch (std::bad_alloc &e) 1265 1303 { } 1266 1304 }
Note:
See TracChangeset
for help on using the changeset viewer.