Created
April 22, 2015 11:21
-
-
Save core-code/79505e6782f0e3fda2ac to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*************************************************************************** | |
// PrintSMARTData - Prints S.M.A.R.T data // mostly from apple saple code | |
//*************************************************************************** | |
static IOReturn PrintSMARTData(io_service_t service, char *smart) | |
{ | |
IOCFPlugInInterface **cfPlugInInterface = NULL; | |
IOATASMARTInterface **smartInterface = NULL; | |
HRESULT herr = S_OK; | |
IOReturn err = kIOReturnSuccess; | |
SInt32 score = 0; | |
Boolean conditionExceeded = false; | |
err = IOCreatePlugInInterfaceForService(service, | |
kIOATASMARTUserClientTypeID, | |
kIOCFPlugInInterfaceID, | |
&cfPlugInInterface, | |
&score); | |
require ( (err == kIOReturnSuccess), ErrorExit); | |
herr = (*cfPlugInInterface)->QueryInterface( | |
cfPlugInInterface, | |
CFUUIDGetUUIDBytes(kIOATASMARTInterfaceID), | |
(LPVOID) &smartInterface); | |
require ( (herr == S_OK), ReleasePlugIn); | |
require ( (smartInterface != NULL), ReleasePlugIn); | |
err = (*smartInterface)->SMARTEnableDisableOperations(smartInterface, true); | |
require ( (err == kIOReturnSuccess), ReleaseInterface); | |
err = (*smartInterface)->SMARTEnableDisableAutosave(smartInterface, true); | |
require ( (err == kIOReturnSuccess), ReleaseInterface); | |
err = (*smartInterface)->SMARTReturnStatus(smartInterface, &conditionExceeded); | |
require ( (err == kIOReturnSuccess), ReleaseInterface); | |
if (conditionExceeded) | |
{ | |
*smart = kStatusError; // FAIL | |
} | |
else | |
{ | |
*smart = kStatusOK; // OK | |
} | |
ReleaseInterface: | |
(*smartInterface)->Release(smartInterface); | |
smartInterface = NULL; | |
ReleasePlugIn: | |
IODestroyPlugInInterface(cfPlugInInterface); | |
ErrorExit: | |
return err; | |
} | |
//*************************************************************************** | |
// PrintSMARTDataForBSDNode - Prints S.M.A.R.T data for a particular BSD Node // mostly from apple saple code | |
//*************************************************************************** | |
#pragma clang diagnostic push | |
#pragma clang diagnostic ignored "-Wshift-sign-overflow" | |
static IOReturn PrintSMARTDataForBSDNode(const char *bsdNode, char *smart) | |
{ | |
io_object_t object = MACH_PORT_NULL; | |
io_object_t parent = MACH_PORT_NULL; | |
bool found = false; | |
char *bsdName = NULL; | |
char deviceName[15]; | |
IOReturn err = kIOReturnError; | |
sprintf ( deviceName, "%s", bsdNode); | |
if (!strncmp(deviceName, "/dev/r", 6)) | |
{ | |
// Strip off the /dev/r from /dev/rdiskX | |
bsdName = &deviceName[6]; | |
} | |
else if (!strncmp(deviceName, "/dev/", 5)) | |
{ | |
// Strip off the /dev/r from /dev/rdiskX | |
bsdName = &deviceName[5]; | |
} | |
else | |
{ | |
bsdName = deviceName; | |
} | |
require ( (strncmp(bsdName, "disk", 4) == 0), ErrorExit); | |
object = IOServiceGetMatchingService(kIOMasterPortDefault, IOBSDNameMatching(kIOMasterPortDefault, 0, bsdName)); | |
require ( (object != MACH_PORT_NULL), ErrorExit); | |
parent = object; | |
while ((IOObjectConformsTo(object, kIOBlockStorageDeviceClass) == false)) | |
{ | |
err = IORegistryEntryGetParentEntry(object, kIOServicePlane, &parent); | |
require ( (err == kIOReturnSuccess), ReleaseObject); | |
require ( (parent != MACH_PORT_NULL), ReleaseObject); | |
IOObjectRelease(object); | |
object = parent; | |
} | |
if (IOObjectConformsTo(object, kIOBlockStorageDeviceClass)) | |
{ | |
Boolean hasSMART1 = FALSE, hasSMART2 = FALSE; | |
CFTypeRef data; | |
data = IORegistryEntryCreateCFProperty(object, CFSTR(kIOPropertySMARTCapableKey), kCFAllocatorDefault, 0); | |
if (data) | |
{ | |
hasSMART1 = CFBooleanGetValue((CFBooleanRef) data); | |
CFRelease(data); | |
} | |
data = IORegistryEntryCreateCFProperty(object, CFSTR(kIOUserClientClassKey), kCFAllocatorDefault, 0); // is this only on OLD OSes so? | |
if (data) | |
{ | |
hasSMART2 = [(NSString *) data isEqualToString:@"ATASMARTUserClient"]; | |
CFRelease(data); | |
} | |
if (hasSMART1 || hasSMART2) // support S.M.A.R.T. as it is advertised on old ppc and new intel macs - don't wanna check non capable disks | |
{ | |
err = PrintSMARTData(object, smart); | |
found = true; | |
} | |
} | |
ReleaseObject: | |
require ( (object != MACH_PORT_NULL), ErrorExit); | |
IOObjectRelease(object); | |
//object = MACH_PORT_NULL; | |
ErrorExit: | |
if (found == false) | |
{ | |
err = kIOReturnNoResources; | |
} | |
return err; | |
} | |
#pragma clang diagnostic pop |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment