#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"
class ExtentManager extMan;
// xartutil information
- bool have_xartutil_info;
- uuid_string_t uuid_str;
- bool is_internal;
+ char *diskname;
};
static void
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;
+static char *
+query_disk_info(int fd) {
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;
+ return (NULL);
}
- // 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;
+ // Find the last pathname component.
+ disk_name = strrchr(disk_path, '/');
+ if (disk_name == NULL) {
+ // Not that we expect this to happen...
+ disk_name = disk_path;
} 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;
+ // Skip over the '/'.
+ disk_name++;
}
- 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;
+ if (*disk_name == 'r') {
+ // Raw device; skip over leading 'r'.
+ disk_name++;
}
- // 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);
+ // ...and make sure it's really a disk.
+ if (strncmp(disk_name, "disk", strlen("disk")) != 0) {
+ return (NULL);
}
- return (result);
+ return (strdup(disk_name));
}
static
-int run_xartutil(uuid_string_t uuid_str, bool is_internal)
+int run_xartutil(char *const diskname)
{
- char external[2];
pid_t child_pid, wait_pid;
posix_spawn_file_actions_t fileActions;
bool haveFileActions = false;
int result = 0;
char arg1[] = "xartutil";
- char arg2[] = "--erase";
- char arg4[] = "--is-external";
-
- external[0] = (is_internal == false) ? '1' : '0';
- external[1] = 0;
+ char arg2[] = "--erase-disk";
- char *xartutil_argv[] = {arg1, arg2, uuid_str, arg4, external, NULL};
+ char *const xartutil_argv[] = {arg1, arg2, diskname, NULL};
result = posix_spawn_file_actions_init(&fileActions);
if (result) {
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;
+ char *diskname = NULL;
*handle = NULL;
- uuid_str[0] = 0;
(void)fstat(fd, &sbuf);
switch (sbuf.st_mode & S_IFMT) {
case S_IFCHR:
}
totalSizeInBytes = numBlocks * nativeBlockSize;
- uuid_err = query_disk_info(fd, uuid_str, sizeof(uuid_str), &is_internal);
- if (uuid_err == 0) {
- have_xartutil_info = true;
- }
+ diskname = query_disk_info(fd);
break;
case S_IFREG:
nativeBlockSize = sbuf.st_blksize;
}
(*handle)->fd = fd;
+ (*handle)->diskname = NULL;
extMan = &(*handle)->extMan;
extMan->Init(block_size, nativeBlockSize, totalSizeInBytes);
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));
- }
+ (*handle)->diskname = diskname;
}
catch (bad_alloc &e) {
err = ENOMEM;
labelExit:
if (err != 0) {
+ if (diskname != NULL)
+ free(diskname);
wipefs_free(handle);
}
return err;
size_t bufSize;
dk_extent_t extent;
dk_unmap_t unmap;
- bool did_write = false;
+
+ if (handle->diskname != NULL) {
+ // Remove this disk's entry from the xART.
+ run_xartutil(handle->diskname);
+ }
memset(&extent, 0, sizeof(dk_extent_t));
extent.length = handle->extMan.totalBytes;
// informational for the lower-level drivers.
//
ioctl(handle->fd, DKIOCUNMAP, (caddr_t)&unmap);
-
bufSize = 128 * 1024; // issue large I/O to get better performance
if (handle->extMan.nativeBlockSize > bufSize) {
}
numBytes -= numBytesToWrite;
byteOffset += numBytesToWrite;
-
- if (did_write == false) {
- did_write = true;
- }
}
}
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
wipefs_free(wipefs_ctx *handle)
{
if (*handle != NULL) {
+ char *diskname;
+
+ if ((diskname = (*handle)->diskname) != NULL)
+ free(diskname);
delete *handle;
*handle = NULL;
}