From a71d6fbf6c8461f3f3893e46266ae316f13b39ca Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 8 Aug 2016 23:47:26 +0000 Subject: [PATCH] libutil-47.20.1.tar.gz --- libutil.xcodeproj/project.pbxproj | 24 ++- wipefs.cpp | 288 +++++++++++++++++++++++++++++- 2 files changed, 305 insertions(+), 7 deletions(-) diff --git a/libutil.xcodeproj/project.pbxproj b/libutil.xcodeproj/project.pbxproj index a8b631a..c89e33f 100644 --- a/libutil.xcodeproj/project.pbxproj +++ b/libutil.xcodeproj/project.pbxproj @@ -46,6 +46,8 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 7259A9731D519322008F83F6 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7259A9721D519322008F83F6 /* IOKit.framework */; }; + 7259A9751D51932B008F83F6 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7259A9741D51932B008F83F6 /* CoreFoundation.framework */; }; BA79F9CB13BB7207006A292D /* ExtentManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BA79F9A313BB70FF006A292D /* ExtentManager.cpp */; }; BA79F9CC13BB7207006A292D /* getmntopts.c in Sources */ = {isa = PBXBuildFile; fileRef = BA79F9A613BB70FF006A292D /* getmntopts.c */; }; BA79F9CD13BB7207006A292D /* humanize_number.c in Sources */ = {isa = PBXBuildFile; fileRef = BA79F9A813BB70FF006A292D /* humanize_number.c */; }; @@ -125,7 +127,7 @@ BA79F9DB13BB7698006A292D /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; - dstPath = "/usr/local/share/man/man3"; + dstPath = /usr/local/share/man/man3; dstSubfolderSpec = 0; files = ( BA79F9DD13BB76B0006A292D /* getmntopts.3 in CopyFiles */, @@ -142,7 +144,7 @@ BA79F9E713BB77BB006A292D /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; - dstPath = "/usr/local/OpenSourceVersions"; + dstPath = /usr/local/OpenSourceVersions; dstSubfolderSpec = 0; files = ( BA79F9E913BB77FA006A292D /* libutil.plist in CopyFiles */, @@ -152,7 +154,7 @@ BA79F9E813BB77D6006A292D /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; - dstPath = "/usr/local/OpenSourceLicenses"; + dstPath = /usr/local/OpenSourceLicenses; dstSubfolderSpec = 0; files = ( BA79F9EA13BB77FF006A292D /* libutil.txt in CopyFiles */, @@ -162,7 +164,7 @@ FDBC26EE1741B13400CA4B2B /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; - dstPath = "/System/Library/LaunchDaemons"; + dstPath = /System/Library/LaunchDaemons; dstSubfolderSpec = 0; files = ( FDBC27051741B1C300CA4B2B /* com.apple.tzlinkd.plist in CopyFiles */, @@ -173,6 +175,8 @@ /* Begin PBXFileReference section */ 3F09C378186D1F73007AF93C /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = base.xcconfig; path = xcconfigs/base.xcconfig; sourceTree = ""; }; + 7259A9721D519322008F83F6 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; + 7259A9741D51932B008F83F6 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; BA79F9A313BB70FF006A292D /* ExtentManager.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ExtentManager.cpp; sourceTree = ""; }; BA79F9A413BB70FF006A292D /* ExtentManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtentManager.h; sourceTree = ""; }; BA79F9A513BB70FF006A292D /* getmntopts.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = getmntopts.3; sourceTree = ""; }; @@ -215,6 +219,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 7259A9751D51932B008F83F6 /* CoreFoundation.framework in Frameworks */, + 7259A9731D519322008F83F6 /* IOKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -236,6 +242,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 7259A9711D519321008F83F6 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 7259A9741D51932B008F83F6 /* CoreFoundation.framework */, + 7259A9721D519322008F83F6 /* IOKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; BA79F99513BB70D7006A292D = { isa = PBXGroup; children = ( @@ -270,6 +285,7 @@ BA79F9BE13BB70FF006A292D /* wipefs.h */, FDBC270C1741B66500CA4B2B /* xcconfigs */, BA79F9C613BB718B006A292D /* Products */, + 7259A9711D519321008F83F6 /* Frameworks */, ); sourceTree = ""; }; diff --git a/wipefs.cpp b/wipefs.cpp index 3be8ae1..b96e7b8 100644 --- a/wipefs.cpp +++ b/wipefs.cpp @@ -30,15 +30,30 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "ExtentManager.h" #include "wipefs.h" -#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#define wipefs_roundup(x, y) ((((x)+((y)-1))/(y))*(y)) struct __wipefs_ctx { int fd; class ExtentManager extMan; + + // xartutil information + bool have_xartutil_info; + uuid_string_t uuid_str; + bool is_internal; }; static void @@ -135,6 +150,244 @@ AddExtentsForCoreStorage(class ExtentManager *extMan) extMan->AddByteRangeExtent(extMan->totalBytes - 512, 512); } +static bool +is_disk_device(const char *pathname) { + bool is_disk_dev = false; + + if (strncmp(pathname, "/dev/disk", strlen("/dev/disk")) == 0) { + is_disk_dev = true; + } else if (strncmp(pathname, "/dev/rdisk", strlen("/dev/rdisk")) == 0) { + is_disk_dev = true; + } + + return (is_disk_dev); +} + +static int +query_disk_info(int fd, char *uuid_str, int uuid_len, bool *is_internal) { + io_service_t obj; + io_iterator_t iter; + kern_return_t error; + CFBooleanRef removableRef; + CFStringRef uuidRef; + CFStringRef locationRef; + CFDictionaryRef protocolCharacteristics; + bool deviceInternal, mediaRemovable; + int result; + char disk_path[PATH_MAX]; + char *disk_name; + + result = EINVAL; + deviceInternal = false; + mediaRemovable = false; + removableRef = NULL; + protocolCharacteristics = NULL; + uuidRef = NULL; + obj = IO_OBJECT_NULL; + iter = IO_OBJECT_NULL; + + // Fetch the path + if (fcntl(fd, F_GETPATH, disk_path) == -1) { + goto out; + } + + // Make sure path begins with /dev/disk or /dev/rdisk + if (is_disk_device(disk_path) == false) { + goto out; + } + + // Derive device name + disk_name = disk_path; + if(strncmp(disk_path, _PATH_DEV, strlen(_PATH_DEV)) == 0) { + // Skip over leading "/dev/" + disk_name += strlen(_PATH_DEV); + } + if (strncmp(disk_name, "r", strlen("r")) == 0) { + // Raw device, skip over leading "r" + disk_name += strlen("r"); + } + + // Get an iterator object + error = IOServiceGetMatchingServices(kIOMasterPortDefault, + IOBSDNameMatching(kIOMasterPortDefault, 0, disk_name), &iter); + if (error) { + os_log_error(OS_LOG_DEFAULT, "Warning, unable to obtain UUID info (iterator), device %s", disk_name); + goto out; + } + + // Get the matching device object + obj = IOIteratorNext(iter); + if (!obj) { + os_log_error(OS_LOG_DEFAULT, "Warning, unable to obtain UUID info (dev obj), device %s", disk_name); + goto out; + } + + // Get a protocol characteristics dictionary + protocolCharacteristics = (CFDictionaryRef) IORegistryEntrySearchCFProperty(obj, + kIOServicePlane, + CFSTR(kIOPropertyProtocolCharacteristicsKey), + kCFAllocatorDefault, + kIORegistryIterateRecursively|kIORegistryIterateParents); + + if ((protocolCharacteristics == NULL) || (CFDictionaryGetTypeID() != CFGetTypeID(protocolCharacteristics))) + { + os_log_error(OS_LOG_DEFAULT, "Warning, failed to obtain UUID info (protocol characteristics), device %s\n", disk_name); + goto out; + } + + // Check for kIOPropertyInternalKey + locationRef = (CFStringRef) CFDictionaryGetValue(protocolCharacteristics, CFSTR(kIOPropertyPhysicalInterconnectLocationKey)); + + if ((locationRef == NULL) || (CFStringGetTypeID() != CFGetTypeID(locationRef))) { + os_log_error(OS_LOG_DEFAULT, "Warning, failed to obtain UUID info (location), device %s\n", disk_name); + goto out; + } + + if (CFEqual(locationRef, CFSTR(kIOPropertyInternalKey))) { + deviceInternal = true; + } + + // Check for kIOMediaRemovableKey + removableRef = (CFBooleanRef)IORegistryEntrySearchCFProperty(obj, + kIOServicePlane, + CFSTR(kIOMediaRemovableKey), + kCFAllocatorDefault, + 0); + + if ((removableRef == NULL) || (CFBooleanGetTypeID() != CFGetTypeID(removableRef))) { + os_log_error(OS_LOG_DEFAULT, "Warning, unable to obtain UUID info (MediaRemovable key), device %s", disk_name); + goto out; + } + + if (CFBooleanGetValue(removableRef)) { + mediaRemovable = true; + } + + // is_internal ==> DeviceInternal && !MediaRemovable + if ((deviceInternal == true) && (mediaRemovable == false)) { + *is_internal = true; + } else { + *is_internal = false; + } + + // Get the UUID + uuidRef = (CFStringRef)IORegistryEntrySearchCFProperty(obj, + kIOServicePlane, + CFSTR(kIOMediaUUIDKey), + kCFAllocatorDefault, + 0); + if ((uuidRef == NULL) || (CFStringGetTypeID() != CFGetTypeID(uuidRef))) + { + os_log_error(OS_LOG_DEFAULT, "Warning, unable to obtain UUID info (MediaUUID key), device %s", disk_name); + goto out; + } + + if (!CFStringGetCString(uuidRef, uuid_str, uuid_len, kCFStringEncodingASCII)) { + os_log_error(OS_LOG_DEFAULT, "Warning, unable to obtain UUID info (convert UUID), device %s", disk_name); + goto out; + } + + // Success + result = 0; + +out: + if (obj != IO_OBJECT_NULL) { + IOObjectRelease(obj); + } + if (iter != IO_OBJECT_NULL) { + IOObjectRelease(iter); + } + if (removableRef != NULL) { + CFRelease(removableRef); + } + if (protocolCharacteristics != NULL) { + CFRelease(protocolCharacteristics); + } + if (uuidRef != NULL) { + CFRelease(uuidRef); + } + + return (result); +} + +static +int run_xartutil(uuid_string_t uuid_str, bool is_internal) +{ + char external[2]; + pid_t child_pid, wait_pid; + posix_spawn_file_actions_t fileActions; + bool haveFileActions = false; + int child_status = 0; + int result = 0; + + char arg1[] = "xartutil"; + char arg2[] = "--erase"; + char arg4[] = "--is-external"; + + external[0] = (is_internal == false) ? '1' : '0'; + external[1] = 0; + + char *xartutil_argv[] = {arg1, arg2, uuid_str, arg4, external, NULL}; + + result = posix_spawn_file_actions_init(&fileActions); + if (result) { + os_log_error(OS_LOG_DEFAULT, "Warning, init xartutil file actions error: %d", result); + result = -1; + goto out; + } + + haveFileActions = true; + + // Redirect stdout & stderr (results not critical, so we ignore return values). + posix_spawn_file_actions_addopen(&fileActions, STDOUT_FILENO, "/dev/null", O_WRONLY, 0); + posix_spawn_file_actions_addopen(&fileActions, STDERR_FILENO, "/dev/null", O_WRONLY, 0); + + result = posix_spawn(&child_pid, "/usr/sbin/xartutil", &fileActions, NULL, xartutil_argv, NULL); + + if (result) { + os_log_error(OS_LOG_DEFAULT, "Warning, unable to start xartutil, spawn error: %d", result); + result = -1; + goto out; + } + + do { + wait_pid = waitpid(child_pid, &child_status, 0); + } while (wait_pid == -1 && errno == EINTR); + + if (wait_pid == -1) { + os_log_error(OS_LOG_DEFAULT, "Warning, unable to start xartutil, waitpid error: %d", errno); + result = -1; + goto out; + } + + if (WIFEXITED(child_status)) { + // xartutil terminated normally, get exit status + result = WEXITSTATUS(child_status); + + if (result) { + os_log_error(OS_LOG_DEFAULT, "Warning, xartutil returned status %d", result); + } + } else { + result = -1; + + if (WIFSIGNALED(child_status)) { + os_log_error(OS_LOG_DEFAULT, "Warning, xartutil terminated by signal: %u", WTERMSIG(child_status)); + } else if (WIFSTOPPED(child_status)) { + os_log_error(OS_LOG_DEFAULT, "Warning, xartutil stopped by signal: %u", WSTOPSIG(child_status)); + } else { + os_log_error(OS_LOG_DEFAULT, "Warning, xartutil terminated abnormally, status 0x%x", child_status); + } + } + +out: + + if (haveFileActions) { + posix_spawn_file_actions_destroy(&fileActions); + } + + return (result); +} + extern "C" int wipefs_alloc(int fd, size_t block_size, wipefs_ctx *handle) { @@ -144,8 +397,13 @@ wipefs_alloc(int fd, size_t block_size, wipefs_ctx *handle) off_t totalSizeInBytes = 0; class ExtentManager *extMan = NULL; struct stat sbuf = { 0 }; + bool have_xartutil_info = false; + uuid_string_t uuid_str; + bool is_internal; + int uuid_err = 0; *handle = NULL; + uuid_str[0] = 0; (void)fstat(fd, &sbuf); switch (sbuf.st_mode & S_IFMT) { case S_IFCHR: @@ -159,6 +417,11 @@ wipefs_alloc(int fd, size_t block_size, wipefs_ctx *handle) goto labelExit; } totalSizeInBytes = numBlocks * nativeBlockSize; + + uuid_err = query_disk_info(fd, uuid_str, sizeof(uuid_str), &is_internal); + if (uuid_err == 0) { + have_xartutil_info = true; + } break; case S_IFREG: nativeBlockSize = sbuf.st_blksize; @@ -197,6 +460,14 @@ wipefs_alloc(int fd, size_t block_size, wipefs_ctx *handle) AddExtentsForZFS(extMan); AddExtentsForPartitions(extMan); AddExtentsForCoreStorage(extMan); + + (*handle)->have_xartutil_info = false; + + if (have_xartutil_info == true) { + (*handle)->have_xartutil_info = true; + (*handle)->is_internal = is_internal; + memcpy((*handle)->uuid_str, uuid_str, sizeof(uuid_str)); + } } catch (bad_alloc &e) { err = ENOMEM; @@ -253,6 +524,7 @@ wipefs_wipe(wipefs_ctx handle) size_t bufSize; dk_extent_t extent; dk_unmap_t unmap; + bool did_write = false; memset(&extent, 0, sizeof(dk_extent_t)); extent.length = handle->extMan.totalBytes; @@ -290,7 +562,7 @@ wipefs_wipe(wipefs_ctx handle) size_t nativeBlockSize = handle->extMan.nativeBlockSize; off_t newOffset, newEndOffset; newOffset = byteOffset / nativeBlockSize * nativeBlockSize; - newEndOffset = roundup(byteOffset + numBytes, nativeBlockSize); + newEndOffset = wipefs_roundup(byteOffset + numBytes, nativeBlockSize); byteOffset = newOffset; numBytes = newEndOffset - newOffset; } @@ -305,14 +577,24 @@ wipefs_wipe(wipefs_ctx handle) } numBytes -= numBytesToWrite; byteOffset += numBytesToWrite; + + if (did_write == false) { + did_write = true; + } } - } + } labelExit: (void)ioctl(handle->fd, DKIOCSYNCHRONIZECACHE); if (bufZero != NULL) delete[] bufZero; + + if ((did_write == true) && (handle->have_xartutil_info == true)) { + // We wrote some zero bytes and have UUID info, notify xART now. + run_xartutil(handle->uuid_str, handle->is_internal); + } + return err; } // wipefs_wipe -- 2.45.2