Skip to content

Instantly share code, notes, and snippets.

@core-code
Created April 22, 2015 11:21
Show Gist options
  • Save core-code/79505e6782f0e3fda2ac to your computer and use it in GitHub Desktop.
Save core-code/79505e6782f0e3fda2ac to your computer and use it in GitHub Desktop.
/***************************************************************************
// 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