4

I am developing an application that uses disk arbitration to find out which devices are connected to a machine and react to connect/disconnect events and that has been working well for years. Just recently I discovered that something does not work as expected when working with external thunderbolt drives and I debugged this to find that the volume's ejectable property (kDADiskDescriptionMediaEjectableKey in Disk Arbitration which maps to kIOMediaEjectableKey i IOKit) is set to false. However, the drive is displayed with an eject button.

What does finder use to decide if this volume is ejectable? Obviously not the obvious kDADiskDescriptionMediaEjectableKey.

Any hint appreciated.

user1573546
  • 523
  • 5
  • 13
  • I'm not 100% sure on this, but I suspect OS X shows the eject button for any external drives. (i.e. non-internal: `kDADiskDescriptionDeviceInternalKey` being false) Thunderbolt drives are really just external PCIe drive controllers, and don't have a bus concept of "ejecting;" clicking eject will usually just unmount the volume and send the drive into standby. You can re-mount it anytime if you don't actually unplug it. Contrast this with many USB drives, which actually seem to fall off the bus when you eject them. – pmdj Jul 21 '16 at 12:37
  • OK, thanks a lot! That is the only alternative I saw as well but the documentation of isInternal is sketchy at best but so far for all drives checked, this seems to be correct, so I'll probably do that. I'll wait a bit more for answers before closing this to allow for some more answers but then I'll probably accept this as the answer. – user1573546 Jul 22 '16 at 15:33
  • Having written storage device drivers myself, I can tell you the internal/external distinction is purely driver based - so it's entirely possible for a driver to claim that an external drive is internal and vice versa. To some extent you just have to trust the driver on this… In any case, I'll make my answer an answer not a comment. – pmdj Jul 23 '16 at 13:10
  • Are you sure you're looking at the proper level of the hierarchy? Are you working with the whole disk partition? If you use `DADiskCopyWholeDisk()` and copy its description, is it ejectable? – Ken Thomases Jul 23 '16 at 14:45
  • I am looking at the individual partition, i.e. if a drive is formatted with two partitions A and B, I look at A and B individually. Apart from the thunderbolt case this has worked but I'll check it out, next time I get my hands on a thunderbolt drive, which will be two days fro now, and report back. – user1573546 Jul 24 '16 at 19:29
  • OK, this is really weird. I tested with the internal SSD, an SD card in the MB macbookcard reader a USB SSD and a thunderbolt drive. The only DADisk that has mediaEjectable = true (and also mediaRemovable = true) is the SD card and its whole disk. All other disks I get have mediaEjectable = false and also mediaRemovable = false. The two DADisks for the SD card also have deviceInternal set to true. I noticed that we already have a work-around for that in the code testing for USB protocol. How the hell does Finder do it? This is a mess. – user1573546 Jul 26 '16 at 13:27
  • macOS seems to distinguish between removable drives and removable media. I don't know that the former is indicated. I think USB sticks and SD cards are considered removable media with the slots they plug into analogous to drives like floppy or optical drives. The fact that entire drives with fixed or removable media can be removed in their entirety from a USB or FireWire just blurs the distinction. But if you think of a DVD or floppy drive connected via USB it's clear that they still have removable media. – hippietrail Dec 14 '20 at 22:15

2 Answers2

2

I'm not 100% sure on this, but I suspect OS X shows the eject button for any external drives. (i.e. non-internal: kDADiskDescriptionDeviceInternalKey being false) Thunderbolt drives are really just external PCIe drive controllers (SATA or whatever), and don't have a bus concept of "ejecting;" clicking eject will usually just unmount the volume and send the drive into standby. You can re-mount it anytime if you don't actually unplug it. Contrast this with many USB drives, which actually seem to fall off the bus when you eject them. So if the driver supports an explicit "eject" action, that will be performed as well when you click eject, but it's not a requirement for showing the eject UI.

pmdj
  • 22,018
  • 3
  • 52
  • 103
  • Just as a counter-example, here I have a disk image I have mounted where kDADiskDescriptionDeviceInternalKey is true. – Hakanai Jul 11 '17 at 23:03
2

I did not find any other way but make heuristics based on trial and error with as many devices as I could find. Neither kDADiskDescriptionMediaEjectableKey nor kDADiskDescriptionMediaRemovableKey nor kDADiskDescriptionDeviceInternalKey properties can be relied on, e.g. an SD card inserted into the integrated card reader of a Macbook has kDADiskDescriptionDeviceInternalKey being true. Thus the condition I am using now is:

MediaEjectable == true || MediaRemovable == true || DeviceInternal == false) || DeviceProtocol == "USB" || DeviceProtocol == "FireWire"

Very ugly but haven't found a better way.

user1573546
  • 523
  • 5
  • 13