Search code examples
objective-cmacosfilesystemsnsurldiskimage

Determine if a Volume is a Disk Image (DMG) from code


From Objective C (or Swift), I need to determine if a mounted volume is a Disk Image (mounted from a .dmg file).

Similar questions led me to NSURL Volume Property Keys, but none of them seem to give the type/protocol of the volume.

However, I can see this information with the terminal diskutil function under Protocol:

~/Temp$ diskutil info /dev/disk8
   Device Identifier:        disk8
   Device Node:              /dev/disk8
   Part of Whole:            disk8
   Device / Media Name:      Apple UDIF read-only Media

   Volume Name:              Not applicable (no file system)

   Mounted:                  Not applicable (no file system)

   File System:              None

   Content (IOContent):      GUID_partition_scheme
   OS Can Be Installed:      No
   Media Type:               Generic
   Protocol:                 Disk Image <=== THIS IS WHAT I WANT
   SMART Status:             Not Supported

   Total Size:               5.2 MB (5242880 Bytes) (exactly 10240 512-Byte-Units)
   Volume Free Space:        Not applicable (no file system)
   Device Block Size:        512 Bytes

   Read-Only Media:          Yes
   Read-Only Volume:         Not applicable (no file system)
   Ejectable:                Yes

   Whole:                    Yes
   Internal:                 No
   OS 9 Drivers:             No
   Low Level Format:         Not supported

EDIT: Found some code that at least used to do this, by means of this included category extension to NSWorkspace. However, it is pre-ARC and I'm not sure if it would still work.

Found it via this partial answer on other question..


Solution

  • You can obtain this information using the DiskArbitration framework. To use the example below, you must link against and #import it.

    #import <DiskArbitration/DiskArbitration.h>
    

    ...

    - (BOOL)isDMGVolumeAtURL:(NSURL *)url
    {
    
      BOOL isDMG = NO;
    
      if (url.isFileURL) {
    
        DASessionRef session = DASessionCreate(kCFAllocatorDefault);
        if (session != nil) {
    
          DADiskRef disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, (__bridge CFURLRef)url);
          if (disk != nil) {
    
            NSDictionary * desc = CFBridgingRelease(DADiskCopyDescription(disk));
            NSString * model = desc[(NSString *)kDADiskDescriptionDeviceModelKey];
            isDMG = ([model isEqualToString:@"Disk Image"]);
    
            CFRelease(disk);
    
          }
    
          CFRelease(session);
    
        }
    
      }
    
      return isDMG;
    
    }
    

    Usage:

    BOOL isDMG = [someObject isDMGVolumeAtURL:[NSURL fileURLWithPath:@"/Volumes/Some Volume"]];
    

    I hope this helps.