diff --git a/Makefile.am b/Makefile.am index 9064b9f2..5d835336 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,6 +3,12 @@ check_PROGRAMS = mktest mkstream AM_CPPFLAGS = -DSYSCONFDIR="\"${sysconfdir}\"" +if HAVE_DISK_ARBITRATION +snapraid_LDFLAGS = -framework CoreFoundation -framework DiskArbitration +mktest_LDFLAGS = -framework CoreFoundation -framework DiskArbitration +mkstream_LDFLAGS = -framework CoreFoundation -framework DiskArbitration +endif + snapraid_SOURCES = \ raid/raid.c \ raid/check.c \ diff --git a/cmdline/mingw.c b/cmdline/mingw.c index 2a0069f9..3d23d1ee 100644 --- a/cmdline/mingw.c +++ b/cmdline/mingw.c @@ -1693,8 +1693,10 @@ int windows_readlink(const char* file, char* buffer, size_t size) return len; } -int devuuid(uint64_t device, char* uuid, size_t uuid_size) +int devuuid(uint64_t device, const char* path, char* uuid, size_t uuid_size) { + (void)path; + /* just use the volume serial number returned in the device parameter */ snprintf(uuid, uuid_size, "%08x", (unsigned)device); diff --git a/cmdline/portable.h b/cmdline/portable.h index 3227a7b2..e0131408 100644 --- a/cmdline/portable.h +++ b/cmdline/portable.h @@ -238,6 +238,11 @@ #include #endif +#ifdef __APPLE__ +#include +#include +#endif + /** * Enable thread use. */ @@ -338,7 +343,7 @@ static inline int hardlink(const char* a, const char* b) * Get the device UUID. * Return 0 on success. */ -int devuuid(uint64_t device, char* uuid, size_t size); +int devuuid(uint64_t device, const char* path, char* uuid, size_t size); /** * Physical offset not yet read. diff --git a/cmdline/state.c b/cmdline/state.c index 0c5bf28a..65d09e3b 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -948,7 +948,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co dev = st.st_dev; /* read the uuid, if unsupported use an empty one */ - if (devuuid(dev, uuid, sizeof(uuid)) != 0) { + if (devuuid(dev, dir, uuid, sizeof(uuid)) != 0) { *uuid = 0; } @@ -1450,7 +1450,8 @@ static void state_map(struct snapraid_state* state) char uuid[UUID_MAX]; int ret; - ret = devuuid(state->parity[l].split_map[s].device, uuid, sizeof(uuid)); + ret = devuuid(state->parity[l].split_map[s].device, state->parity[l].split_map[s].path, uuid, sizeof(uuid)); + if (ret != 0) { /* uuid not available, just ignore */ continue; diff --git a/cmdline/unix.c b/cmdline/unix.c index ce17cf23..2dbd4e5a 100644 --- a/cmdline/unix.c +++ b/cmdline/unix.c @@ -512,8 +512,54 @@ static int devuuid_blkid(uint64_t device, char* uuid, size_t uuid_size) } #endif -int devuuid(uint64_t device, char* uuid, size_t uuid_size) +#ifdef __APPLE__ +static int devuuid_darwin(const char* path, char* uuid, size_t uuid_size) { + CFStringRef path_apple = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8); + DASessionRef session = DASessionCreate(kCFAllocatorDefault); + + CFURLRef path_appler = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_apple, kCFURLPOSIXPathStyle, false); + DADiskRef disk; + do { + disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, path_appler); + if (disk) { + CFRelease(path_appler); + break; + } else { + CFURLRef parent_path_appler = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, path_appler); + CFRelease(path_appler); + path_appler = parent_path_appler; + } + } while (true); // This is guaranteed to succeed eventually because it'll hit `/`. + + CFDictionaryRef description = DADiskCopyDescription(disk); + CFUUIDRef uuid_apple = CFDictionaryGetValue(description, kDADiskDescriptionVolumeUUIDKey); + CFStringRef uuid_string = CFUUIDCreateString(kCFAllocatorDefault, uuid_apple); + bool success = CFStringGetCString(uuid_string, uuid, uuid_size, kCFStringEncodingUTF8); + CFRelease(uuid_string); + CFRelease(description); + CFRelease(disk); + CFRelease(session); + CFRelease(path_apple); + + if (success) { + return 0; + } else { + return 1; + } +} +#endif + +int devuuid(uint64_t device, const char* path, char* uuid, size_t uuid_size) +{ + (void)path; + (void)device; + +#ifdef __APPLE__ + if (devuuid_darwin(path, uuid, uuid_size) == 0) + return 0; +#endif + #if HAVE_LINUX_DEVICE /* if the major is the null device */ if (major(device) == 0) { diff --git a/configure.ac b/configure.ac index eae1c310..d93233c0 100644 --- a/configure.ac +++ b/configure.ac @@ -241,6 +241,7 @@ AS_CASE([$host], [POSIX=1] ) AM_CONDITIONAL(HAVE_POSIX, [test x"$POSIX" != x]) +AM_CONDITIONAL(HAVE_DISK_ARBITRATION, [test "$(uname)" == Darwin]) AC_ARG_ENABLE([profiler], [AS_HELP_STRING([--enable-profiler],[enable the use of gprof for code coverage])],