kextfind_commands.c [plain text]
#include <CoreFoundation/CFBundlePriv.h>
#include <IOKit/kext/KXKextManager.h>
#include <IOKit/kext/fat_util.h>
#include <IOKit/kext/macho_util.h>
#include "kextfind_commands.h"
#include "kextfind.h"
#include "kextfind_query.h"
char * getKextPath(
KXKextRef theKext,
PathSpec pathSpec)
{
char * result = NULL;
CFStringRef copiedPath = NULL; CFStringRef kextPath = NULL;
if (pathSpec == kPathsNone) {
kextPath = KXKextGetBundleDirectoryName(theKext);
if (!kextPath) {
goto finish;
}
result = cStringForCFString(kextPath);
} else if (pathSpec == kPathsRelative) {
kextPath = KXKextGetBundlePathInRepository(theKext);
if (!kextPath) {
goto finish;
}
result = cStringForCFString(kextPath);
} else {
copiedPath = KXKextCopyAbsolutePath(theKext);
if (!copiedPath) {
goto finish;
}
result = cStringForCFString(copiedPath);
}
finish:
if (copiedPath) CFRelease(copiedPath);
return result;
}
void printKext(
KXKextRef theKext,
PathSpec pathSpec,
Boolean extra_info,
char lineEnd)
{
CFBundleRef bundle = NULL; CFStringRef bundleID = NULL; CFStringRef bundleVersion = NULL;
char * kext_path = NULL; char * bundle_id = NULL; char * bundle_version = NULL;
kext_path = getKextPath(theKext, pathSpec);
if (!kext_path) {
goto finish;
}
if (extra_info) {
bundle = KXKextGetBundle(theKext);
bundleID = KXKextGetBundleIdentifier(theKext);
bundleVersion = CFBundleGetValueForInfoDictionaryKey(bundle,
kCFBundleVersionKey);
bundle_id = cStringForCFString(bundleID);
bundle_version = cStringForCFString(bundleVersion);
if (!bundle_id || !bundle_version) {
goto finish;
}
fprintf(stdout, "%s\t%s\t%s%c", kext_path, bundle_id,
bundle_version, lineEnd);
} else {
fprintf(stdout, "%s%c", kext_path, lineEnd);
}
finish:
if (kext_path) free(kext_path);
if (bundle_id) free(bundle_id);
if (bundle_version) free(bundle_version);
return;
}
#define kMaxPrintableCFDataLength (36)
#define kByteGroupSize (4)
char * stringForData(const UInt8 * data, int numBytes)
{
char * result = NULL;
char * scan = NULL;
int numByteGroups;
int i;
char digits[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
numByteGroups = numBytes / kByteGroupSize;
result = malloc(((numBytes * 2) + numByteGroups + 1) * sizeof(char));
if (!result) {
goto finish;
}
scan = result;
for (i = 0; i < numBytes; i++) {
int binaryDigit1 = (data[i] & 0xF0) >> 4;
int binaryDigit2 = data[i] & 0xF;
if (i > 0 && i % kByteGroupSize == 0) {
*scan++ = ' ';
}
*scan++ = digits[binaryDigit1];
*scan++ = digits[binaryDigit2];
}
*scan++ = '\0';
finish:
return result;
}
void printProperty(
CFStringRef label,
CFStringRef propKey,
CFTypeRef value,
char lineEnd)
{
CFTypeID type = CFGetTypeID(value);
CFStringRef propString = NULL; CFStringRef labeledString = NULL; CFStringRef outputString = NULL; char * allocString = NULL; char * dataString = NULL;
if (type == CFStringGetTypeID()) {
propString = CFStringCreateWithFormat(
kCFAllocatorDefault, NULL, CFSTR("%@ = \"%@\"%c"),
propKey, value, lineEnd);
} else if (type == CFNumberGetTypeID()) {
propString = CFStringCreateWithFormat(
kCFAllocatorDefault, NULL, CFSTR("%@ = %@%c"),
propKey, value, lineEnd);
} else if (type == CFBooleanGetTypeID()) {
propString = CFStringCreateWithFormat(
kCFAllocatorDefault, NULL, CFSTR("%@ = %@%c"),
propKey, value, lineEnd);
} else if (type == CFDataGetTypeID()) {
propString = CFStringCreateWithFormat(
kCFAllocatorDefault, NULL, CFSTR("%@ = %@%c"),
propKey, value, lineEnd);
CFIndex length = 0;
length = CFDataGetLength(value);
const UInt8 * data = CFDataGetBytePtr(value);
if (!data) {
propString = CFStringCreateWithFormat(
kCFAllocatorDefault, NULL, CFSTR("%@ = <null data pointer>%c"),
propKey, length, lineEnd);
} else {
int numBytes = MIN(length, kMaxPrintableCFDataLength);
dataString = stringForData(data, MIN(numBytes, kMaxPrintableCFDataLength));
if (length > kMaxPrintableCFDataLength) {
propString = CFStringCreateWithFormat(
kCFAllocatorDefault, NULL,
CFSTR("%@ = <data (%d bytes): %s...>%c"),
propKey, length, dataString, lineEnd);
} else {
propString = CFStringCreateWithFormat(
kCFAllocatorDefault, NULL,
CFSTR("%@ = <data (%d bytes): %s>%c"),
propKey, length, dataString, lineEnd);
}
}
} else if (type == CFDictionaryGetTypeID()) {
propString = CFStringCreateWithFormat(
kCFAllocatorDefault, NULL, CFSTR("%@ = <dictionary of %d items>%c"),
propKey, CFDictionaryGetCount(value), lineEnd);
} else if (type == CFArrayGetTypeID()) {
propString = CFStringCreateWithFormat(
kCFAllocatorDefault, NULL, CFSTR("%@ = <array of %d items>%c"),
propKey, CFArrayGetCount(value), lineEnd);
} else {
propString = CFStringCreateWithFormat(
kCFAllocatorDefault, NULL, CFSTR("%@ = <value of unknown type>%c"),
propKey, value, lineEnd);
}
if (!propString) {
goto finish;
}
if (label) {
labeledString = CFStringCreateWithFormat(
kCFAllocatorDefault, NULL, CFSTR("%@: %@"), label, propString);
outputString = labeledString;
} else {
labeledString = CFStringCreateWithFormat(
kCFAllocatorDefault, NULL, CFSTR("%@"), propString);
outputString = labeledString;
}
if (!outputString) {
goto finish;
}
allocString = cStringForCFString(outputString);
if (!allocString) {
goto finish;
}
fprintf(stdout, "%s", allocString);
finish:
if (propString) CFRelease(propString);
if (labeledString) CFRelease(labeledString);
if (allocString) free(allocString);
if (dataString) free(dataString);
return;
}
void printKextProperty(
KXKextRef theKext,
CFStringRef propKey,
char lineEnd)
{
CFDictionaryRef infoDict = KXKextGetInfoDictionary(theKext);
CFTypeRef value = NULL;
if (!infoDict) {
goto finish;
}
value = CFDictionaryGetValue(infoDict, propKey);
if (value) {
printProperty(NULL, propKey, value, lineEnd);
}
finish:
return;
}
void printKextMatchProperty(
KXKextRef theKext,
CFStringRef propKey,
char lineEnd)
{
CFDictionaryRef personalitiesDict = NULL;
CFStringRef * names = NULL;
CFDictionaryRef * personalities = NULL;
CFIndex numPersonalities;
CFIndex i;
personalitiesDict = KXKextCopyPersonalities(theKext);
if (!personalitiesDict) {
goto finish;
}
numPersonalities = CFDictionaryGetCount(personalitiesDict);
if (!numPersonalities) {
goto finish;
}
names = malloc(numPersonalities * sizeof(CFStringRef));
personalities = malloc(numPersonalities * sizeof(CFDictionaryRef));
if (!names || !personalities) {
goto finish;
}
CFDictionaryGetKeysAndValues(personalitiesDict, (const void **)names,
(const void **)personalities);
for (i = 0; i < numPersonalities; i++) {
CFTypeRef value = CFDictionaryGetValue(personalities[i], propKey);
if (value) {
printProperty(names[i], propKey, value, lineEnd);
}
}
finish:
if (personalitiesDict) CFRelease(personalitiesDict);
if (names) free(names);
if (personalities) free(personalities);
return;
}
extern fat_iterator _KXKextCopyFatIterator(KXKextRef aKext);
void printKextArches(
KXKextRef theKext,
char lineEnd,
Boolean printLineEnd)
{
fat_iterator fiter = NULL;
struct mach_header * farch = NULL;
const NXArchInfo * archinfo = NULL;
Boolean printedOne = false;
fiter = _KXKextCopyFatIterator(theKext);
if (!fiter) {
goto finish;
}
while ((farch = fat_iterator_next_arch(fiter, NULL))) {
int swap = ISSWAPPEDMACHO(farch->magic);
archinfo = NXGetArchInfoFromCpuType(CondSwapInt32(swap, farch->cputype),
CondSwapInt32(swap, farch->cpusubtype));
if (archinfo) {
fprintf(stdout, "%s%s", printedOne ? "," : "", archinfo->name);
printedOne = true;
}
}
finish:
if (printLineEnd && printedOne) {
fprintf(stdout, "%c", lineEnd);
}
if (fiter) fat_iterator_close(fiter);
return;
}
void printKextDependencies(
KXKextRef theKext,
PathSpec pathSpec,
Boolean extra_info,
char lineEnd)
{
CFArrayRef kextDependencies = KXKextCopyAllDependencies(theKext);
CFIndex count, i;
if (!kextDependencies) {
goto finish;
}
count = CFArrayGetCount(kextDependencies);
for (i = 0; i < count; i++) {
KXKextRef thisKext = (KXKextRef)CFArrayGetValueAtIndex(kextDependencies, i);
printKext(thisKext, pathSpec, extra_info, lineEnd);
}
finish:
if (kextDependencies) CFRelease(kextDependencies);
return;
}
void printKextDependents(
KXKextRef theKext,
PathSpec pathSpec,
Boolean extra_info,
char lineEnd)
{
CFArrayRef kextDependents = KXKextCopyAllDependents(theKext);
CFIndex count, i;
if (!kextDependents) {
goto finish;
}
count = CFArrayGetCount(kextDependents);
for (i = 0; i < count; i++) {
KXKextRef thisKext = (KXKextRef)CFArrayGetValueAtIndex(kextDependents, i);
printKext(thisKext, pathSpec, extra_info, lineEnd);
}
finish:
if (kextDependents) CFRelease(kextDependents);
return;
}
void printKextPlugins(
KXKextRef theKext,
PathSpec pathSpec,
Boolean extra_info,
char lineEnd)
{
CFArrayRef plugins = KXKextGetPlugins(theKext); CFIndex count, i;
if (!plugins) {
goto finish;
}
count = CFArrayGetCount(plugins);
for (i = 0; i < count; i++) {
KXKextRef thisKext = (KXKextRef)CFArrayGetValueAtIndex(plugins, i);
printKext(thisKext, pathSpec, extra_info, lineEnd);
}
finish:
return;
}
const char * nameForIntegrityState(KXKextIntegrityState state)
{
if (kKXKextIntegrityCorrect == state) {
return kIntegrityCorrect;
} else if (kKXKextIntegrityKextIsModified == state) {
return kIntegrityModified;
} else if (kKXKextIntegrityNoReceipt == state) {
return kIntegrityNoReceipt;
} else if (kKXKextIntegrityNotApple == state) {
return kIntegrityNotApple;
} else if (kKXKextIntegrityUnknown == state) {
return kIntegrityUnknown;
}
return NULL;
}
char * getAdjustedPath(
KXKextRef theKext,
CFURLRef pathToAdjust,
PathSpec pathSpec)
{
char * result = NULL;
KXKextRepositoryRef repository = NULL; CFURLRef repositoryURL = NULL; CFURLRef kextAbsURL = NULL; char infoDictPath[PATH_MAX];
char containingPath[PATH_MAX];
if (!CFURLGetFileSystemRepresentation(pathToAdjust, true,
(UInt8 *)infoDictPath, PATH_MAX)) {
goto finish;
}
if (pathSpec == kPathsFull) {
result = strdup(infoDictPath);
goto finish;
}
if (pathSpec == kPathsRelative) {
repository = KXKextGetRepository(theKext);
repositoryURL = KXKextRepositoryCopyURL(repository);
if (!repositoryURL) {
goto finish;
}
if (!CFURLGetFileSystemRepresentation(repositoryURL, true,
(UInt8 *)containingPath, PATH_MAX)) {
goto finish;
}
result = strdup(infoDictPath + strlen(containingPath) + 1);
}
if (pathSpec == kPathsNone) {
kextAbsURL = KXKextGetAbsoluteURL(theKext);
if (!kextAbsURL) {
goto finish;
}
if (!CFURLGetFileSystemRepresentation(kextAbsURL, true,
(UInt8 *)containingPath, PATH_MAX)) {
goto finish;
}
result = strdup(infoDictPath + strlen(containingPath) + 1);
}
finish:
if (repositoryURL) CFRelease(repositoryURL);
return result;
}
char * getKextInfoDictionaryPath(
KXKextRef theKext,
PathSpec pathSpec)
{
char * result = NULL;
CFURLRef infoDictURL = NULL;
infoDictURL = _CFBundleCopyInfoPlistURL(KXKextGetBundle(theKext));
if (!infoDictURL) {
goto finish;
}
result = getAdjustedPath(theKext, infoDictURL, pathSpec);
finish:
if (infoDictURL) CFRelease(infoDictURL);
return result;
}
void printKextInfoDictionary(
KXKextRef theKext,
PathSpec pathSpec,
char lineEnd)
{
char * infoDictPath = NULL;
infoDictPath = getKextInfoDictionaryPath(theKext, pathSpec);
if (infoDictPath) {
printf("%s%c", infoDictPath, lineEnd);
free(infoDictPath);
}
return;
}
char * getKextExecutablePath(
KXKextRef theKext,
PathSpec pathSpec)
{
char * result = NULL;
CFURLRef executableURL = NULL;
executableURL = CFBundleCopyExecutableURL(KXKextGetBundle(theKext));
if (!executableURL) {
goto finish;
}
result = getAdjustedPath(theKext, executableURL, pathSpec);
finish:
if (executableURL) CFRelease(executableURL);
return result;
}
void printKextExecutable(
KXKextRef theKext,
PathSpec pathSpec,
char lineEnd)
{
char * executablePath = getKextExecutablePath(theKext, pathSpec);
if (executablePath) {
printf("%s%c", executablePath, lineEnd);
free(executablePath);
}
return;
}