Skip to main content
Added suggestion about device name.
Source Link
user1118321
  • 11.8k
  • 1
  • 19
  • 46

There are 2 things missing from your code. As @Hanzaplastique mentioned, you need to wait for the callback to be executed. Secondly, you need to pass a valid queue to DASessionSetDispatchQueue(). If you pass NULL as in your code, you're telling it to unschedule the session.

You can use a dispatch_semaphore_t to wait between threads. Putting it all together, I get this:

#include <stdio.h>
#import <CoreFoundation/CoreFoundation.h>
#import <DiskArbitration/DiskArbitration.h>

static dispatch_semaphore_t semaphore;

void MountCallback(DADiskRef disk, DADissenterRef dissenter, void *context);

int main(int argc, const char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <disk>\n", argv[0]);
        return EXIT_FAILURE;
    }
    
    const char *deviceName = argv[1];
    
    // Create the semaphore we'll wait on.
    semaphore = dispatch_semaphore_create(0);
    
    DASessionRef session = DASessionCreate(kCFAllocatorDefault);
    DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, deviceName);
    
    // Pass NULL for a "standard" mount path.
    DADiskMount(disk, NULL, kDADiskMountOptionWhole, MountCallback, (void *)deviceName);
    
    // We'll pass the global concurrent queue here so it gets executed in the background
    DASessionSetDispatchQueue(session, dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0));
    CFRelease(session);
    session = NULL;
    
    // Wait for the callback to signal that it's done
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    // Clean up
    dispatch_release(semaphore);
    
    return EXIT_SUCCESS;
}

void MountCallback(DADiskRef disk, DADissenterRef dissenter, void *context) {
    const char *mountedDisk = context;
    fprintf(stderr, "Device mounted: %s\n", mountedDisk);
    fflush(stderr);

    // Tell the main thread that we've finished up.
    dispatch_semaphore_signal(semaphore);
    return;
}

One other suggestion - I would change the usage to say <device> instead of <disk>. It wasn't immediately clear to me wether I was supposed to have something like "Macintosh HD" (the disk name) in there or "disk5s1" (the device name). It looks to me like it's supposed to be the device name, correct?

There are 2 things missing from your code. As @Hanzaplastique mentioned, you need to wait for the callback to be executed. Secondly, you need to pass a valid queue to DASessionSetDispatchQueue(). If you pass NULL as in your code, you're telling it to unschedule the session.

You can use a dispatch_semaphore_t to wait between threads. Putting it all together, I get this:

#include <stdio.h>
#import <CoreFoundation/CoreFoundation.h>
#import <DiskArbitration/DiskArbitration.h>

static dispatch_semaphore_t semaphore;

void MountCallback(DADiskRef disk, DADissenterRef dissenter, void *context);

int main(int argc, const char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <disk>\n", argv[0]);
        return EXIT_FAILURE;
    }
    
    const char *deviceName = argv[1];
    
    // Create the semaphore we'll wait on.
    semaphore = dispatch_semaphore_create(0);
    
    DASessionRef session = DASessionCreate(kCFAllocatorDefault);
    DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, deviceName);
    
    // Pass NULL for a "standard" mount path.
    DADiskMount(disk, NULL, kDADiskMountOptionWhole, MountCallback, (void *)deviceName);
    
    // We'll pass the global concurrent queue here so it gets executed in the background
    DASessionSetDispatchQueue(session, dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0));
    CFRelease(session);
    session = NULL;
    
    // Wait for the callback to signal that it's done
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    // Clean up
    dispatch_release(semaphore);
    
    return EXIT_SUCCESS;
}

void MountCallback(DADiskRef disk, DADissenterRef dissenter, void *context) {
    const char *mountedDisk = context;
    fprintf(stderr, "Device mounted: %s\n", mountedDisk);
    fflush(stderr);

    // Tell the main thread that we've finished up.
    dispatch_semaphore_signal(semaphore);
    return;
}

There are 2 things missing from your code. As @Hanzaplastique mentioned, you need to wait for the callback to be executed. Secondly, you need to pass a valid queue to DASessionSetDispatchQueue(). If you pass NULL as in your code, you're telling it to unschedule the session.

You can use a dispatch_semaphore_t to wait between threads. Putting it all together, I get this:

#include <stdio.h>
#import <CoreFoundation/CoreFoundation.h>
#import <DiskArbitration/DiskArbitration.h>

static dispatch_semaphore_t semaphore;

void MountCallback(DADiskRef disk, DADissenterRef dissenter, void *context);

int main(int argc, const char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <disk>\n", argv[0]);
        return EXIT_FAILURE;
    }
    
    const char *deviceName = argv[1];
    
    // Create the semaphore we'll wait on.
    semaphore = dispatch_semaphore_create(0);
    
    DASessionRef session = DASessionCreate(kCFAllocatorDefault);
    DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, deviceName);
    
    // Pass NULL for a "standard" mount path.
    DADiskMount(disk, NULL, kDADiskMountOptionWhole, MountCallback, (void *)deviceName);
    
    // We'll pass the global concurrent queue here so it gets executed in the background
    DASessionSetDispatchQueue(session, dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0));
    CFRelease(session);
    session = NULL;
    
    // Wait for the callback to signal that it's done
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    // Clean up
    dispatch_release(semaphore);
    
    return EXIT_SUCCESS;
}

void MountCallback(DADiskRef disk, DADissenterRef dissenter, void *context) {
    const char *mountedDisk = context;
    fprintf(stderr, "Device mounted: %s\n", mountedDisk);
    fflush(stderr);

    // Tell the main thread that we've finished up.
    dispatch_semaphore_signal(semaphore);
    return;
}

One other suggestion - I would change the usage to say <device> instead of <disk>. It wasn't immediately clear to me wether I was supposed to have something like "Macintosh HD" (the disk name) in there or "disk5s1" (the device name). It looks to me like it's supposed to be the device name, correct?

Source Link
user1118321
  • 11.8k
  • 1
  • 19
  • 46

There are 2 things missing from your code. As @Hanzaplastique mentioned, you need to wait for the callback to be executed. Secondly, you need to pass a valid queue to DASessionSetDispatchQueue(). If you pass NULL as in your code, you're telling it to unschedule the session.

You can use a dispatch_semaphore_t to wait between threads. Putting it all together, I get this:

#include <stdio.h>
#import <CoreFoundation/CoreFoundation.h>
#import <DiskArbitration/DiskArbitration.h>

static dispatch_semaphore_t semaphore;

void MountCallback(DADiskRef disk, DADissenterRef dissenter, void *context);

int main(int argc, const char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <disk>\n", argv[0]);
        return EXIT_FAILURE;
    }
    
    const char *deviceName = argv[1];
    
    // Create the semaphore we'll wait on.
    semaphore = dispatch_semaphore_create(0);
    
    DASessionRef session = DASessionCreate(kCFAllocatorDefault);
    DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, deviceName);
    
    // Pass NULL for a "standard" mount path.
    DADiskMount(disk, NULL, kDADiskMountOptionWhole, MountCallback, (void *)deviceName);
    
    // We'll pass the global concurrent queue here so it gets executed in the background
    DASessionSetDispatchQueue(session, dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0));
    CFRelease(session);
    session = NULL;
    
    // Wait for the callback to signal that it's done
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    // Clean up
    dispatch_release(semaphore);
    
    return EXIT_SUCCESS;
}

void MountCallback(DADiskRef disk, DADissenterRef dissenter, void *context) {
    const char *mountedDisk = context;
    fprintf(stderr, "Device mounted: %s\n", mountedDisk);
    fflush(stderr);

    // Tell the main thread that we've finished up.
    dispatch_semaphore_signal(semaphore);
    return;
}