stat() before open() makes it possible to introduce a file race.
From: Erik Hovland <erik@hovland.org>
---
mythplugins/mythvideo/mtd/dvdprobe.cpp | 55 ++++++++++++++++----------------
1 files changed, 27 insertions(+), 28 deletions(-)
diff --git a/mythplugins/mythvideo/mtd/dvdprobe.cpp b/mythplugins/mythvideo/mtd/dvdprobe.cpp
index 0e9cb5a..21b1949 100644
a
|
b
|
|
19 | 19 | #include <cmath> |
20 | 20 | #include <climits> // for CDSL_CURRENT which is currently INT_MAX |
21 | 21 | |
| 22 | // Qt |
| 23 | #include <QFile> |
| 24 | |
22 | 25 | #include "dvdprobe.h" |
23 | 26 | |
24 | 27 | #include <mythtv/mythcontext.h> |
… |
… |
void DVDProbe::Reset(void) |
425 | 428 | |
426 | 429 | bool DVDProbe::Probe(void) |
427 | 430 | { |
428 | | // |
429 | 431 | // Before touching libdvdread stuff |
430 | 432 | // (below), see if there's actually |
431 | 433 | // a drive with media in it |
432 | | // |
433 | | |
434 | | struct stat fileinfo; |
435 | | |
436 | | QByteArray dev = device.toLocal8Bit(); |
437 | | int ret = stat(dev.constData(), &fileinfo); |
438 | | if (ret < 0) |
| 434 | QFile dvdDevice(device); |
| 435 | if (!dvdDevice.exists()) |
439 | 436 | { |
440 | | // |
441 | | // Can't even stat the device, it probably |
442 | | // doesn't exist. Silly user |
443 | | // |
| 437 | // Device doesn't exist. Silly user |
444 | 438 | Reset(); |
445 | 439 | return false; |
446 | 440 | } |
447 | 441 | |
448 | | #if defined(__linux__) || defined(__FreeBSD__) |
449 | | // |
450 | | // I have no idea if the following code block |
451 | | // is anywhere close to the "right way" of doing |
452 | | // this, but it seems to work. |
453 | | // |
| 442 | if (!dvdDevice.open(QIODevice::ReadOnly)) |
| 443 | { |
| 444 | // Can't open device. |
| 445 | Reset(); |
| 446 | return false; |
| 447 | } |
454 | 448 | |
455 | | int drive_handle = open(dev.constData(), O_RDONLY | O_NONBLOCK); |
| 449 | int drive_handle = dvdDevice.handle(); |
456 | 450 | |
457 | 451 | if (drive_handle == -1) |
458 | 452 | { |
459 | 453 | Reset(); |
460 | 454 | return false; |
461 | 455 | } |
| 456 | #if defined(__linux__) || defined(__FreeBSD__) |
| 457 | // I have no idea if the following code block |
| 458 | // is anywhere close to the "right way" of doing |
| 459 | // this, but it seems to work. |
462 | 460 | |
463 | 461 | // Sometimes the first result following an open is a lie. Often the |
464 | 462 | // first call will return 4, however an immediate second call will |
… |
… |
bool DVDProbe::Probe(void) |
467 | 465 | // (in an admittedly small test number) seems to make it much more |
468 | 466 | // accurate (with only a 1 in 6 chance that the first result was more |
469 | 467 | // accurate than the second). |
470 | | ioctl(drive_handle, CDROM_DRIVE_STATUS, CDSL_CURRENT); |
471 | 468 | int status = ioctl(drive_handle, CDROM_DRIVE_STATUS, CDSL_CURRENT); |
| 469 | if (status < 0) |
| 470 | { |
| 471 | Reset(); |
| 472 | return false; |
| 473 | } |
| 474 | |
| 475 | status = ioctl(drive_handle, CDROM_DRIVE_STATUS, CDSL_CURRENT); |
472 | 476 | if (status < 4) |
473 | 477 | { |
474 | 478 | // |
… |
… |
bool DVDProbe::Probe(void) |
478 | 482 | // 3 = not ready |
479 | 483 | // |
480 | 484 | Reset(); |
481 | | close(drive_handle); |
482 | 485 | return false; |
483 | | |
484 | 486 | } |
485 | 487 | |
486 | 488 | status = ioctl(drive_handle, CDROM_MEDIA_CHANGED, NULL); |
487 | | close(drive_handle); |
488 | 489 | |
489 | 490 | if (!status) |
490 | 491 | { |
491 | | // |
492 | 492 | // the disc has not changed. but if this is our |
493 | 493 | // first time running, we still need to check it |
494 | | // |
495 | | |
496 | 494 | if (!first_time) |
497 | 495 | { |
498 | | // |
499 | 496 | // Return whatever we returned before |
500 | 497 | // |
501 | 498 | |
… |
… |
bool DVDProbe::Probe(void) |
503 | 500 | } |
504 | 501 | } |
505 | 502 | #endif |
| 503 | dvdDevice.close(); |
506 | 504 | |
507 | 505 | // |
508 | 506 | // Try to open the disc |
509 | | // (as far libdvdread is concerned, the argument |
| 507 | // (as far as libdvdread is concerned, the argument |
510 | 508 | // could be a path, file, whatever). |
511 | 509 | // |
512 | 510 | |
513 | 511 | Reset(); |
514 | 512 | first_time = false; |
| 513 | QByteArray dev = device.toAscii(); |
515 | 514 | dvd = DVDOpen(dev.constData()); |
516 | 515 | if (!dvd) |
517 | 516 | return false; |