]> git.saurik.com Git - apple/libutil.git/commitdiff
libutil-47.20.1.tar.gz macos-10121 v47.20.1
authorApple <opensource@apple.com>
Mon, 8 Aug 2016 23:47:26 +0000 (23:47 +0000)
committerApple <opensource@apple.com>
Mon, 8 Aug 2016 23:47:26 +0000 (23:47 +0000)
libutil.xcodeproj/project.pbxproj
wipefs.cpp

index a8b631ac4663768e8d5f4aad7f4ea665df21eba0..c89e33f9688a2ca7c1968ed6662b2d21ffc39416 100644 (file)
@@ -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 */; };
                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 */,
                BA79F9E713BB77BB006A292D /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
-                       dstPath = "/usr/local/OpenSourceVersions";
+                       dstPath = /usr/local/OpenSourceVersions;
                        dstSubfolderSpec = 0;
                        files = (
                                BA79F9E913BB77FA006A292D /* libutil.plist in CopyFiles */,
                BA79F9E813BB77D6006A292D /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
-                       dstPath = "/usr/local/OpenSourceLicenses";
+                       dstPath = /usr/local/OpenSourceLicenses;
                        dstSubfolderSpec = 0;
                        files = (
                                BA79F9EA13BB77FF006A292D /* libutil.txt in CopyFiles */,
                FDBC26EE1741B13400CA4B2B /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 2147483647;
-                       dstPath = "/System/Library/LaunchDaemons";
+                       dstPath = /System/Library/LaunchDaemons;
                        dstSubfolderSpec = 0;
                        files = (
                                FDBC27051741B1C300CA4B2B /* com.apple.tzlinkd.plist in CopyFiles */,
 
 /* Begin PBXFileReference section */
                3F09C378186D1F73007AF93C /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = base.xcconfig; path = xcconfigs/base.xcconfig; sourceTree = "<group>"; };
+               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 = "<group>"; };
                BA79F9A413BB70FF006A292D /* ExtentManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtentManager.h; sourceTree = "<group>"; };
                BA79F9A513BB70FF006A292D /* getmntopts.3 */ = {isa = PBXFileReference; lastKnownFileType = text; path = getmntopts.3; sourceTree = "<group>"; };
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               7259A9751D51932B008F83F6 /* CoreFoundation.framework in Frameworks */,
+                               7259A9731D519322008F83F6 /* IOKit.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+               7259A9711D519321008F83F6 /* Frameworks */ = {
+                       isa = PBXGroup;
+                       children = (
+                               7259A9741D51932B008F83F6 /* CoreFoundation.framework */,
+                               7259A9721D519322008F83F6 /* IOKit.framework */,
+                       );
+                       name = Frameworks;
+                       sourceTree = "<group>";
+               };
                BA79F99513BB70D7006A292D = {
                        isa = PBXGroup;
                        children = (
                                BA79F9BE13BB70FF006A292D /* wipefs.h */,
                                FDBC270C1741B66500CA4B2B /* xcconfigs */,
                                BA79F9C613BB718B006A292D /* Products */,
+                               7259A9711D519321008F83F6 /* Frameworks */,
                        );
                        sourceTree = "<group>";
                };
index 3be8ae1e2419d9d8cca103f27b2c5916a8ab2217..b96e7b83a508016507ae890abbc5f939d9500265 100644 (file)
 #include <sys/ioctl.h>
 #include <sys/disk.h>
 #include <sys/stat.h>
+#include <sys/syslimits.h>
+#include <uuid/uuid.h>
+#include <paths.h>
+#include <string.h>
+#include <spawn.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/storage/IOMedia.h>
+#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
+#include <CoreFoundation/CFNumber.h>
+#include <os/log.h>
 
 #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