2

How is it possible for code to distinguish between external USB hard drives and solid-state drives on the one hand versus USB sticks on the other hand?

I'm not familiar with macOS APIs (or system calls, interrupts, messaging, and other things) but I'm guessing it would be in I/O Kit or Disk Arbitration?

On the Terminal command line you can use system_profiler SPUSBDataType and see this information listed under "Removable Media".

hippietrail
  • 15,848
  • 18
  • 99
  • 158
  • Any drive (pen/hard/ssd) connected via usb will be treated as removable drive only. One thing you can try is to check for their size and format type. But I dont think it will help much for what you are looking. – Ajay Kumar Dec 12 '20 at 15:22
  • @AjayKumar: There seems to be a concept of "removable media". When I hook up a USB hard drive, USB SSD, USB stick, and an SD card in a USB reader,`system_profiler SPUSBDataType` considers the USB stick and SD card to be "removable media" but not the hard drive or SSD, even though the whole drives can also be removed. I'm guessing this is an extension of when floppy, CD, and DVD drives needed to be distinguished from hard drives. I came across this using a cross-platform library that excludes USB sticks from the list of disks for Windows but not for Mac. – hippietrail Dec 12 '20 at 16:02
  • 1
    Hmm. Interesting stuff. I have bookmarked this thread. Keep digging. Good Luck. ! – Ajay Kumar Dec 12 '20 at 16:09
  • Relevant: [how can I know the relationship between usb device node and volume on mac](https://stackoverflow.com/questions/12951287/how-can-i-know-the-relationship-between-usb-device-node-and-volume-on-mac) – hippietrail Dec 14 '20 at 06:45
  • Typically there is no API at all but system calls, interrupts, messaging and other things involved when using C. You can programmatically look for devices through system calls. `system_profiler` sounds like a program, not a system interface. – Rob Dec 15 '20 at 02:31
  • system profiler is a program that obtains this information somehow, showing that it's possible to get it from the system. So I was looking for that method, or any other that works. – hippietrail Dec 15 '20 at 04:47

2 Answers2

2

You can get the removable/ejectable information directly from the URL, ejectable is sufficient for the differentiation

let mountedVolumeURLs = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: [.nameKey, .volumeIsEjectableKey])!
for volumeURL in mountedVolumeURLs where volumeURL.path == "/" || volumeURL.path.hasPrefix("/Volumes") {
    let resources = try! volumeURL.resourceValues(forKeys: [.nameKey, .volumeIsEjectableKey])
    
    let ejectable = resources.volumeIsEjectable!
    let name = resources.name!
    
    var type = name + " is "
    type += ejectable ? "USB stick, SD card, etc" : "hard drive, SSD, etc";
    type += " ("
    type += ejectable ? "" : "not "
    type += "ejectable)"
    print(" ", type)
}
vadian
  • 274,689
  • 30
  • 353
  • 361
  • Excellent! Is there an easy way to print out all the key/value pairs? I'd like to find criteria by which to filter out "home" and "net" which are not really drives. I'm too much of a newb to figure out how by browsing docs and Googling so far... – hippietrail Dec 15 '20 at 09:18
  • 1
    Please see the edit, the *good* volumes are the startup volume (`/`) and all volumes in `/Volumes` – vadian Dec 15 '20 at 10:10
  • It turns out that this just checking whether the path begins with `/Volumes` is not robust: https://apple.stackexchange.com/questions/409482/is-it-ever-possible-for-a-disk-volume-to-be-mounted-anywhere-other-than-in-volu – hippietrail Dec 22 '20 at 03:07
  • Of course it's basically possible to mount disks somewhere else but it's very unlikely and I don't know any case. Your accepted answer on Stackexchange is related to **shared** volumes, but this question is explicitly about **local** USB connected hard disks. – vadian Dec 22 '20 at 05:39
1

I've never written macOS or Swift code before. I learned just enough to get this proof of concept together. It only makes the two-way generalization as in my question: Removable and/or ejectable media vs non-removable non-ejectable media. DMGs are lumped with USB sticks and SD cards. Optical and floppy disks surely are too. I have no idea if there's such thing as a storage type where only one of "removable" and "ejectable" is true but not both...

import Cocoa
import DiskArbitration

if let session = DASessionCreate(kCFAllocatorDefault) {
    let mountedVolumeURLs = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: nil)!
    for volumeURL in mountedVolumeURLs {
        if let disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, volumeURL as CFURL),
            let bsdName = DADiskGetBSDName(disk) {
            let bsdString = String(cString : bsdName)
            print(volumeURL.path, bsdString)
            
            if let descDict = DADiskCopyDescription(disk) as? [String: CFTypeRef] {
                let removable : Bool, ejectable : Bool
                if let val = descDict["DAMediaRemovable"] as? Bool {
                    removable = val
                    if let val = descDict["DAMediaEjectable"] as? Bool {
                        ejectable = val

                        var type = ""
                        
                        type += removable || ejectable ? "USB stick, SD card, etc" : "hard drive, SSD, etc";
                        
                        type += " ("
                        
                        type += removable ? "" : "not "
                        type += "removable"
                        type += ", "
                        type += ejectable ? "" : "not "
                        type += "ejectable"
                        
                        type += ")"

                        print(" ", type)
                    }
                }
            }
            print("\n")
        }
    }
}
hippietrail
  • 15,848
  • 18
  • 99
  • 158
  • How can we get all volumes urls e.g "mountedVolumeURLs" in C++. – Ahad Khan May 03 '21 at 00:48
  • @AhadKhan: I don't know. I'd rather code in C/C++ but it's such a battle figuring out how to do anything in macOS. I've moved on to other things and forgotten everything about this stuff now. Good luck! – hippietrail May 03 '21 at 01:26