From 150da4be71d4f6ea47b77d792befe57c76d3a76b Mon Sep 17 00:00:00 2001 From: Nasado Date: Mon, 3 Feb 2025 17:41:54 -0600 Subject: [PATCH] Use volume UUIDs on macOS --- Makefile.am | 10 ++++++-- cmdline/mac.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++ cmdline/mac.h | 28 ++++++++++++++++++++++ cmdline/portable.h | 2 ++ cmdline/state.c | 13 ++++++++++- configure.ac | 1 + 6 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 cmdline/mac.c create mode 100644 cmdline/mac.h diff --git a/Makefile.am b/Makefile.am index 9064b9f2..3d806b56 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,6 +3,10 @@ check_PROGRAMS = mktest mkstream AM_CPPFLAGS = -DSYSCONFDIR="\"${sysconfdir}\"" +if HAVE_DISK_ARBITRATION +snapraid_LDFLAGS = -framework CoreFoundation -framework DiskArbitration +endif + snapraid_SOURCES = \ raid/raid.c \ raid/check.c \ @@ -44,7 +48,8 @@ snapraid_SOURCES = \ cmdline/import.c \ cmdline/search.c \ cmdline/mingw.c \ - cmdline/unix.c + cmdline/unix.c \ + cmdline/mac.c noinst_HEADERS = \ raid/raid.h \ @@ -88,7 +93,8 @@ noinst_HEADERS = \ cmdline/import.h \ cmdline/search.h \ cmdline/mingw.h \ - cmdline/unix.h + cmdline/unix.h \ + cmdline/mac.h mktest_SOURCES = \ cmdline/mktest.c \ diff --git a/cmdline/mac.c b/cmdline/mac.c new file mode 100644 index 00000000..ead4488c --- /dev/null +++ b/cmdline/mac.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef __APPLE__ + +#include "mac.h" +#include +#include + +int devuuid_macos(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 diff --git a/cmdline/mac.h b/cmdline/mac.h new file mode 100644 index 00000000..8b66365b --- /dev/null +++ b/cmdline/mac.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __MAC_H +#define __MAC_H +#ifdef __APPLE__ + +#include +#include + +int devuuid_macos(char *path, char* uuid, size_t uuid_size); + +#endif +#endif diff --git a/cmdline/portable.h b/cmdline/portable.h index 3227a7b2..69d5b7b9 100644 --- a/cmdline/portable.h +++ b/cmdline/portable.h @@ -334,11 +334,13 @@ static inline int hardlink(const char* a, const char* b) return link(a, b); } +#ifndef __APPLE__ // Use devuuid_macos instead (different API). /** * Get the device UUID. * Return 0 on success. */ int devuuid(uint64_t device, char* uuid, size_t size); +#endif /** * Physical offset not yet read. diff --git a/cmdline/state.c b/cmdline/state.c index 0c5bf28a..91ed27bc 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -28,6 +28,7 @@ #include "io.h" #include "raid/raid.h" #include "raid/cpu.h" +#include "mac.h" /** * Configure the multithread support. @@ -948,7 +949,13 @@ 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 ( +#ifdef __APPLE__ + devuuid_macos(dir, uuid, sizeof(uuid)) +#else + devuuid(dev, uuid, sizeof(uuid)) +#endif + != 0) { *uuid = 0; } @@ -1450,7 +1457,11 @@ static void state_map(struct snapraid_state* state) char uuid[UUID_MAX]; int ret; +#ifdef __APPLE__ + ret = devuuid_macos(state->parity[l].split_map[s].path, uuid, sizeof(uuid)); +#else ret = devuuid(state->parity[l].split_map[s].device, uuid, sizeof(uuid)); +#endif if (ret != 0) { /* uuid not available, just ignore */ continue; 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])],