Использование IOKit для возврата серийного номера Mac возвращает 4 лишних символа - PullRequest
1 голос
/ 06 января 2012

Я играю с IOKit и у меня есть следующий код, общая идея - передать ключ platformExpert в это небольшое базовое приложение командной строки и распечатать декодированную строку. Контрольный пример - «серийный номер». Код ниже при запуске, как:

. / Скомпилированный серийный номер

Почти работает, но возвращает последние 4 символа серийного номера в начале строки, то есть для примера серийного номера, такого как C12D2JMPDDQX, он вернет

DDQXC12D2JMPDDQX

Есть идеи?

#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>

int main (int argc, const char * argv[]) {
    CFStringRef parameter = CFSTR("serial-number");
    if (argv[1]) {
       parameter = CFStringCreateWithCString(
                                 NULL,
                                 argv[1],
                                 kCFStringEncodingUTF8);
    }

    CFDataRef data;

    io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
    if (platformExpert)
    {
        data = IORegistryEntryCreateCFProperty(platformExpert,
                                               parameter,
                                               kCFAllocatorDefault, 0);
    }

    IOObjectRelease(platformExpert);
    CFIndex bufferLength = CFDataGetLength(data);  
    UInt8 *buffer = malloc(bufferLength);
    CFDataGetBytes(data, CFRangeMake(0,bufferLength), (UInt8*) buffer);
    CFStringRef string = CFStringCreateWithBytes(kCFAllocatorDefault,
                                                 buffer,
                                                 bufferLength,
                                                 kCFStringEncodingUTF8,
                                                 TRUE);
    CFShow(string);
    return 0;
}

Ответы [ 2 ]

6 голосов
/ 29 мая 2012

Более упрощенное решение:

#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>

int main()
{
    CFMutableDictionaryRef matching = IOServiceMatching("IOPlatformExpertDevice");
    io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, matching);
    CFStringRef serialNumber = IORegistryEntryCreateCFProperty(service,
        CFSTR("IOPlatformSerialNumber"), kCFAllocatorDefault, 0);
    const char* str = CFStringGetCStringPtr(serialNumber,kCFStringEncodingMacRoman);
    printf("%s\n", str); //->stdout
    //CFShow(serialNumber); //->stderr
    IOObjectRelease(service);
    return 0;
}

скомпилировать с:

clang -framework IOKit -framework ApplicationServices cpuid.c -o cpuid

Вилка из github, если хотите;)

https://github.com/0infinity/IOPlatformSerialNumber

3 голосов
/ 06 января 2012

Возможно, вы неверно истолковываете значение параметра серийного номера. Если я использую ioreg -f -k serial-number, я получаю это:

    |   "serial-number" = 
    |     00000000: 55 51 32 00 00 00 00 00 00 00 00 00 00 XX XX XX XX UQ2..........XXXX
    |     00000011: XX XX XX XX 55 51 32 00 00 00 00 00 00 00 00 00 00 XXXXUQ2..........
    |     00000022: 00 00 00 00 00 00 00 00 00                         .........

(У меня есть серийный номер моего Mac за исключением повторной части.)

Вы не видите нулевые символы, когда вы показываете строку, потому что, ну, они нулевые символы. Я не знаю, почему он имеет то, что выглядит как несколько полей, разделенных нулевыми символами, но это то, что кажется.

Я рекомендую провести дальнейшее расследование, чтобы убедиться, что нет спецификации для того, как эти данные должны интерпретироваться; если вы ничего не найдете, я пропустил бы первый прогон нулей и получил бы все после этого до следующего прогона нулей.

...