1#include <fcntl.h>
2#include <util.h>
3#include <unistd.h>
4#include <string.h>
5#include <sys/mount.h>
6#include <uuid/uuid.h>
7#include <IOKit/IOBSD.h>
8#include <IOKit/IOKitLib.h>
9#include <IOKit/storage/IOMedia.h>
10
11extern char debug;
12extern void plog(const char *, ...);
13
14/*
15 * Given a uuid string, look up the BSD device and open it.
16 * This code comes from DanM.
17 *
18 * Essentially, it is given a UUID string (from the journal header),
19 * and then looks it up via IOKit.  From there, it then gets the
20 * BSD name (e.g., /dev/dsik3), and opens it read-only.
21 *
22 * It returns the file descriptor, or -1 on error.
23 */
24int
25OpenDeviceByUUID(void *uuidp, char **namep)
26{
27    char devname[ MAXPATHLEN ];
28    CFStringRef devname_string;
29    int fd = -1;
30    CFMutableDictionaryRef matching;
31    io_service_t media;
32    uuid_string_t uuid_cstring;
33    CFStringRef uuid_string;
34
35    memcpy(&uuid_cstring, uuidp, sizeof(uuid_cstring));
36
37    uuid_string = CFStringCreateWithCString( kCFAllocatorDefault, uuid_cstring, kCFStringEncodingUTF8 );
38    if ( uuid_string ) {
39        matching = IOServiceMatching( kIOMediaClass );
40        if ( matching ) {
41            CFDictionarySetValue( matching, CFSTR( kIOMediaUUIDKey ), uuid_string );
42            media = IOServiceGetMatchingService( kIOMasterPortDefault, matching );
43            if ( media ) {
44                devname_string = IORegistryEntryCreateCFProperty( media, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
45                if ( devname_string ) {
46                    if ( CFStringGetCString( devname_string, devname, sizeof( devname ), kCFStringEncodingUTF8 ) ) {
47			if (debug)
48				plog("external journal device name = `%s'\n", devname);
49
50                        fd = opendev( devname, O_RDONLY, 0, NULL );
51			if (fd != -1 && namep != NULL) {
52				*namep = strdup(devname);
53			}
54                    }
55                    CFRelease( devname_string );
56                }
57                IOObjectRelease( media );
58            }
59            /* do not CFRelease( matching ); */
60        }
61        CFRelease( uuid_string );
62    }
63
64    return fd;
65}
66