How to get serial number from Mac hard disks?
Asked Answered
J

8

14

Is there an easy way to get the serial number of all the hard disks in a Mac using an API?

Basically, I'm looking for a unique identifier for the hard disk with which I can figure out whether the hard disk has been used (or referred to) by my application or not.

Please let me know if there is any other solution.

Note: I need this solution for 10.4 and above.

Jermaine answered 7/1, 2010 at 9:15 Comment(0)
B
13

I'm not sure if "AppleUSBEHCI" is the proper thing to look for but you can retrieve this sort of data using the IOKit framework:

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

kern_return_t   kr;
io_iterator_t   io_objects;
io_service_t    io_service;

kr = IOServiceGetMatchingServices(kIOMasterPortDefault,
            IOServiceNameMatching("AppleUSBEHCI"), &io_objects);

if(kr != KERN_SUCCESS)
    exit(1);

while((io_service= IOIteratorNext(io_objects)))
{
    kr = IORegistryEntryCreateCFProperties(io_service, &service_properties, kCFAllocatorDefault, kNilOptions);
    if(kr == KERN_SUCCESS)
    {
        NSDictionary * m = (NSDictionary *)service_properties;
        NSLog(@"%@", m);
        CFRelease(service_properties);
    }

    io_iterator_t   iter;
    //handle kr error
    kr = IORegistryEntryGetChildIterator(io_service, kIOServicePlane, &iter);

    io_registry_entry_t     child;
    while( (child = IOIteratorNext( iter )))
    {
        kr = IORegistryEntryCreateCFProperties(child, &child_props,  kCFAllocatorDefault, kNilOptions );
        NSLog(@"Child props: %@", child_props);
        //release child_props
    }

    IOObjectRelease(io_service);
}

IOObjectRelease(io_objects);
Boone answered 7/1, 2010 at 9:25 Comment(8)
AppleAHCIDiskDriver - not resulting hard disk which are connected are USB. By looking in system profiler USB HD was using "Host Controller Driver: AppleUSBEHCI" so I tried using AppleUSBEHCI instead AppleAHCIDiskDriver but did not resulted any result. not sure I am missing some thing.Jermaine
You might want to try mouviciel's answer before you continue on the IOKit path. For devices connected to USB, do IOServiceNameMatching("AppleUSBEHCI") and then iterate through all its children using IORegistryEntryGetChildIterator(io_service, kIOServicePlane, &iter).Boone
I appreciate your help. I tied mouviciel solution but did not work. when I tried using IORegistryEntryGetChildIterator - it return error(268435459), I just called this after IOServiceGetMatchingServices, not sure what am I missing.Jermaine
You probably called IORegistryEntryGetChildIterator on the iterator which doesn't make sense. I've edited my answer to illustrate iterating through children of a ioregistryentry. Note that I've tested with a USB stick - a HDD may or may not appear in the same way. You need to do some reading on IOKit before writing production code.Boone
it worked, you are right I was called IORegistryEntryGetChildIterator on the iterato. I will consider your suggestion to read IOKit before going to production. thanks for your help.Jermaine
is there any way to get 'BSD Name:' in this process. I could see BSD Name in System profiler but I could not see this in the 'child_props' can I get some help on this. Basically I am trying to map serial number with drive (BSD name - since it is unique).Jermaine
you're a geniusBarren
developer.apple.com/documentation/iokit/… tells that return value of IOIteratorNext must be released as well.Tristatristam
A
9

From the command line:

ioreg -rd1 -w0 -c AppleAHCIDiskDriver | grep Serial

This gives you the serial number of the built-in hard disk.

Ambulate answered 28/5, 2014 at 15:57 Comment(1)
update: AppleAHCIDiskDriver is no longer used in newer machines, so this will be empty. Maybe look for AppleANS2Controller instead.Reentry
A
6

I think it's better to get the Volume UUID (which appears in the Disk Utility, for example.) UUID can be obtained using the Disk Arbitration framework, which is slightly higher-level than IOKit and easier to use. Create DADiskRef using DADiskCreateFromBSDName, and use DADiskCopyDescription to get the info dictionary, and look up the key kDADiskDescriptionMediaUUIDKey. Info on the mount point etc. can be obtained by statfs.

That said, it might be easier just to invoke the command-line utility diskutil with the option -plist to get the info in the plist format.

The sample code FSMegaInfo might also be instructive how to get much more info about a disk.

Allisonallissa answered 7/1, 2010 at 16:22 Comment(4)
thanks for valuable information. As per my understanding UUID is generated in system not sure it can be considered as unique. In my system I am not able to see UUID for the device.Jermaine
UUID is an acronym for Universally Unique ID, and it's unique. It's used for example to control what to mount in /etc/fstab. It's also weird that you don't see the UUID. What does diskutil info /dev/disk0s2 return on your machine? Don't you see the entry Volume UUID in the list? You might need to change /disk0s2 above to what you actually have. Check first with diskutil list.Allisonallissa
a volume ID is conceptually different from a drive ID for a number of reasons, a drive can have multiple volumes, a drive's volumes do not necessary have to be mounted, volumes can be added and removed hence changing their ID even if the drive remains the sameFanfare
One can get a volume UUID using -[NSURL getResourceValue:forKey:error:] with the key NSURLVolumeUUIDStringKey. Docs say it could return nil "if a persistent UUID is not available" but don't say when that could happen.Burdened
S
3

The following will list the serial numbers on the SATA-bus. You don't get to know which device it is as is but you can do it with some scripting/parsing. I've used "sed" to remove all the spaces and "awk" to isolate just the serial in case you are not familiar:

$ system_profiler SPSerialATADataType -detailLevel medium | grep Serial | sed -e 's/[\<\>\"\ ]//g' | -F':' '{print $2}'
Sienese answered 14/12, 2015 at 17:43 Comment(2)
I guess you can also find this useful: -> $ system_profiler SPSerialATADataType -detailLevel medium | grep -e "Serial" -e "Model" | awk -F': ' '{print $2}'Sienese
update: SPSerialATADataType not present on newer machines with NVME drives.Reentry
M
2

Have a look at IOKit.

There are two handy tools on your Mac to find out about the possibilities of it:

  • ioreg, a command line tool
  • IORegistryExplorer, the same with a GUI.
Medrano answered 7/1, 2010 at 9:27 Comment(0)
F
1

The drive ID's can be retrieved from the IORegistry as follows:

  • Internal drives: IOAHCIBlockStorageDevice string property "Serial Number" inside "Device Characteristics" e.g.: (WD-WCAV5D1345345)

  • USB drives : IOUSBDevice string property "USB Serial Number" e.g.: (5743415654564561373734)

  • FireWire drives : IOReducedBlockServices number property "GUID" inside "Protocol Characteristics" e.g.: (407345709348650)

  • Thunderbolt drives: ??

These ID's are persistent meaning the same external drives connected to different machines will show the same ID.

Fanfare answered 1/3, 2012 at 19:47 Comment(1)
How are they retrieved? What is the complete command?Mentally
M
1

This is a very old thread and also the first search result so I will add another useful method that relies on installing homebrew and smartmontools

Install homebrew, then...

brew install smartmontools

You can then run

smartctl -x disk0s1 | grep "Serial Number"

You will need to use the diskutil list command to find the disk ID. I used "disk0s1" above but you will enter your own.

Mentally answered 26/8, 2023 at 21:21 Comment(0)
S
-1

maybe you can just place a hidden file on a hard disk that your app has used? That's e.g. how apple's Time Machine does it.

Septicemia answered 7/1, 2010 at 9:26 Comment(1)
good suggestion, I can consider this solution only if get some information from Hard disk. If file is get deleted, I can not recognize it any more in my app.Jermaine

© 2022 - 2024 — McMap. All rights reserved.