+long GetFSUUID(char *spec, char *uuidStr)
+{
+ BVRef bvr;
+ long rval = -1;
+ const char *devSpec;
+
+ if ((bvr = getBootVolumeRef(spec, &devSpec)) == NULL)
+ return -1;
+
+ if(bvr->fs_getuuid)
+ rval = bvr->fs_getuuid(bvr, uuidStr);
+
+ return rval;
+}
+
+
+// filesystem-specific getUUID functions call this shared string generator
+long CreateUUIDString(uint8_t uubytes[], int nbytes, char *uuidStr)
+{
+ unsigned fmtbase, fmtidx, i;
+ uint8_t uuidfmt[] = { 4, 2, 2, 2, 6 };
+ char *p = uuidStr;
+ MD5_CTX md5c;
+ uint8_t mdresult[16];
+
+ bzero(mdresult, sizeof(mdresult));
+
+ // just like AppleFileSystemDriver
+ MD5Init(&md5c);
+ MD5Update(&md5c, kFSUUIDNamespaceSHA1, sizeof(kFSUUIDNamespaceSHA1));
+ MD5Update(&md5c, uubytes, nbytes);
+ MD5Final(mdresult, &md5c);
+
+ // this UUID has been made version 3 style (i.e. via namespace)
+ // see "-uuid-urn-" IETF draft (which otherwise copies byte for byte)
+ mdresult[6] = 0x30 | ( mdresult[6] & 0x0F );
+ mdresult[8] = 0x80 | ( mdresult[8] & 0x3F );
+
+
+ // generate the text: e.g. 5EB1869F-C4FA-3502-BDEB-3B8ED5D87292
+ i = 0; fmtbase = 0;
+ for(fmtidx = 0; fmtidx < sizeof(uuidfmt); fmtidx++) {
+ for(i=0; i < uuidfmt[fmtidx]; i++) {
+ uint8_t byte = mdresult[fmtbase+i];
+ char nib;
+
+ nib = byte >> 4;
+ *p = nib + '0'; // 0x4 -> '4'
+ if(*p > '9') *p = (nib - 9 + ('A'-1)); // 0xB -> 'B'
+ p++;
+
+ nib = byte & 0xf;
+ *p = nib + '0'; // 0x4 -> '4'
+ if(*p > '9') *p = (nib - 9 + ('A'-1)); // 0xB -> 'B'
+ p++;
+
+ }
+ fmtbase += i;
+ if(fmtidx < sizeof(uuidfmt)-1)
+ *(p++) = '-';
+ else
+ *p = '\0';
+ }
+
+ return 0;
+}
+