]> git.saurik.com Git - apple/hfs.git/blobdiff - hfs_util/hfsutil_main.c
hfs-366.1.1.tar.gz
[apple/hfs.git] / hfs_util / hfsutil_main.c
index 77add29875016d0506a19e130356715cf28a6d91..8d86934b6679f642870db9fa9a97a73488de96a2 100644 (file)
@@ -1,24 +1,21 @@
 /*
- * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.2 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
  * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
@@ -57,6 +54,7 @@
 #include <sys/attr.h>
 #include <hfs/hfs_format.h>
 #include <hfs/hfs_mount.h>
+#include <err.h>
 
 #include <ctype.h>
 #include <errno.h>
 #include <unistd.h>
 #include <syslog.h>
 
-#include <openssl/sha.h>
+/*
+ * CommonCrypto provides a more stable API than OpenSSL guarantees;
+ * the #define causes it to use the same API for MD5 and SHA1, so the rest of
+ * the code need not change.
+ */
+#define COMMON_DIGEST_FOR_OPENSSL
+#include  <CommonCrypto/CommonDigest.h>
 
-#include <architecture/byte_order.h>
+#include <libkern/OSByteOrder.h>
 
 #include <CoreFoundation/CFString.h>
 
+#include <uuid/uuid.h>
+#include <System/uuid/namespace.h>
+
 #define READ_DEFAULT_ENCODING 1
 
 #ifndef FSUC_ADOPT
 #define FSUC_UNJNL   'U'
 #endif
 
+#ifndef FSUC_UNJNL_RAW
+#define FSUC_UNJNL_RAW 'N'
+#endif
+
+#ifndef FSUC_JNLINFS_RAW
+#define FSUC_JNLINFS_RAW 'e'
+#endif
+
+#ifndef FSUC_EXTJNL_RAW
+#define FSUC_EXTJNL_RAW 'E'
+#endif
+
 #ifndef FSUC_JNLINFO
 #define FSUC_JNLINFO 'I'
 #endif
 
 /* **************************************** L O C A L S ******************************************* */
 
+#define kHFSPlusMaxFileNameBytes       (3 * 255 + 1)   /* 255 unicode characters, plus 1 NUL byte */
+
 #define        HFS_BLOCK_SIZE                  512
 
 char gHFS_FS_NAME[] = "hfs";
@@ -138,23 +159,31 @@ int gJournalSize = 0;
 #define AUTO_ENTER_FIXED 0
 
 
-struct FinderAttrBuf {
-       unsigned long info_length;
-       unsigned long finderinfo[8];
-};
+typedef struct FinderAttrBuf {
+       u_int32_t info_length;
+       u_int32_t finderinfo[8];
+} FinderAttrBuf_t;
+
+
+/* For requesting the UUID from the FS */
+typedef struct UUIDAttrBuf {
+       uint32_t info_length;
+       uuid_t uu;
+} UUIDAttrBuf_t;
 
+/* HFS+ internal representation of UUID */
+typedef struct hfs_UUID {
+       uint32_t high;
+       uint32_t low;
+} hfs_UUID_t;  
 
-#define VOLUMEUUIDVALUESIZE 2
-typedef union VolumeUUID {
-       unsigned long value[VOLUMEUUIDVALUESIZE];
-       struct {
-               unsigned long high;
-               unsigned long low;
-       } v;
-} VolumeUUID;
+/* an actual UUID */
+typedef struct volUUID {
+       uuid_t uuid;
+} volUUID_t;
 
-#define VOLUMEUUIDLENGTH 16
-typedef char VolumeUUIDString[VOLUMEUUIDLENGTH+1];
+
+#define HFSUUIDLENGTH 16
 
 #define VOLUME_RECORDED 0x80000000
 #define VOLUME_USEPERMISSIONS 0x00000001
@@ -162,41 +191,54 @@ typedef char VolumeUUIDString[VOLUMEUUIDLENGTH+1];
 
 typedef void *VolumeStatusDBHandle;
 
-void GenerateVolumeUUID(VolumeUUID *newVolumeID);
-void ConvertVolumeUUIDStringToUUID(const char *UUIDString, VolumeUUID *volumeID);
-void ConvertVolumeUUIDToString(VolumeUUID *volumeID, char *UUIDString);
+/* UUID generation and conversion functions */
+void GenerateHFSVolumeUUID(hfs_UUID_t *hfsuu);
+void ConvertHFSUUIDStringToUUID (const char* UUIDString, volUUID_t *volid);
+void ConvertHFSUUIDToUUID (hfs_UUID_t *hfsuuid, volUUID_t *uu);
+
+/* 
+ * Volume Database manipulation routines
+ * These functions MUST manipulate the VSDB in the same way that vsdbutil does
+ */
+int ConvertVolumeStatusDB(VolumeStatusDBHandle DBHandle);
 int OpenVolumeStatusDB(VolumeStatusDBHandle *DBHandlePtr);
-int GetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID, unsigned long *VolumeStatus);
-int SetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID, unsigned long VolumeStatus);
-int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID);
+int GetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, volUUID_t *volumeID, unsigned long *VolumeStatus);
+int SetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, volUUID_t *volumeID, unsigned long VolumeStatus);
+int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, volUUID_t *volumeID);
 int CloseVolumeStatusDB(VolumeStatusDBHandle DBHandle);
 
 /* ************************************ P R O T O T Y P E S *************************************** */
 static void    DoDisplayUsage( const char * argv[] );
-static int     DoMount( char * theDeviceNamePtr, const char * theMountPointPtr, boolean_t isLocked, boolean_t isSetuid, boolean_t isDev );
-static int     DoProbe( char * theDeviceNamePtr );
+static int     DoMount( char * theDeviceNamePtr, const char *rawName, const char * theMountPointPtr, 
+                                       boolean_t isLocked, boolean_t isSetuid, boolean_t isDev );
+static int     DoProbe( char * rawDeviceNamePtr, char * blockDeviceNamePtr );
 static int     DoUnmount( const char * theMountPointPtr );
-static int     DoGetUUIDKey( const char * theDeviceNamePtr );
+static int     DoGetUUIDKey( const char * theDeviceNamePtr, const char *rawName );
 static int     DoChangeUUIDKey( const char * theDeviceNamePtr );
-static int     DoAdopt( const char * theDeviceNamePtr );
-static int     DoDisown( const char * theDeviceNamePtr );
+static int     DoAdopt( const char * theDeviceNamePtr, const char *rawName);
+static int     DoDisown( const char * theDeviceNamePtr, const char *rawName);
 
 extern int  DoMakeJournaled( const char * volNamePtr, int journalSize );  // XXXdbg
 extern int  DoUnJournal( const char * volNamePtr );      // XXXdbg
 extern int  DoGetJournalInfo( const char * volNamePtr );
+extern int  RawDisableJournaling( const char *devname );
+extern int  SetJournalInFSState( const char *devname, int journal_in_fs);
 
 static int     ParseArgs( int argc, const char * argv[], const char ** actionPtr, const char ** mountPointPtr, boolean_t * isEjectablePtr, boolean_t * isLockedPtr, boolean_t * isSetuidPtr, boolean_t * isDevPtr );
-
 static int     GetHFSMountPoint(const char *deviceNamePtr, char **pathPtr);
-static int     ReadHeaderBlock(int fd, void *bufptr, off_t *startOffset, VolumeUUID **finderInfoUUIDPtr);
-static int     GetVolumeUUIDRaw(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr);
-static int     GetVolumeUUIDAttr(const char *path, VolumeUUID *volumeUUIDPtr);
-static int     GetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr, boolean_t generate);
-static int     SetVolumeUUIDRaw(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr);
-static int     SetVolumeUUIDAttr(const char *path, VolumeUUID *volumeUUIDPtr);
-static int     SetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr);
+
+/* Helper functions for manipulating HFS and full UUIDs */
+static int     ReadHeaderBlock(int fd, void *bufptr, off_t *startOffset, hfs_UUID_t **finderInfoUUIDPtr);
+static int     GetVolumeUUIDRaw(const char *deviceNamePtr, const char *rawName, volUUID_t *volumeUUIDPtr);
+static int     GetVolumeUUIDAttr(const char *path, volUUID_t *volumeUUIDPtr);
+static int     GetVolumeUUID(const char *deviceNamePtr, const char *rawName, volUUID_t *volumeUUIDPtr, boolean_t generate);
+static int     SetVolumeUUIDRaw(const char *deviceNamePtr, hfs_UUID_t *hfsuu);
+static int     SetVolumeUUIDAttr(const char *path, hfs_UUID_t *hfsuu);
+static int     SetVolumeUUID(const char *deviceNamePtr, hfs_UUID_t *hfsuu);
+
+
 static int     GetEmbeddedHFSPlusVol(HFSMasterDirectoryBlock * hfsMasterDirectoryBlockPtr, off_t * startOffsetPtr);
-static int     GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * name_o);
+static int     GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, unsigned char * name_o);
 static int     GetBTreeNodeInfo(int fd, off_t hfsPlusVolumeOffset, u_int32_t blockSize,
                                                        u_int32_t extentCount, const HFSPlusExtentDescriptor *extentList,
                                                        u_int32_t *nodeSize, u_int32_t *firstLeafNode);
@@ -216,6 +258,8 @@ static int  GetEncodingBias(void);
 
 CF_EXPORT Boolean _CFStringGetFileSystemRepresentation(CFStringRef string, UInt8 *buffer, CFIndex maxBufLen);
 
+static void     uuid_create_md5_from_name(uuid_t result_uuid, const uuid_t namespace, const void *name, int namelen);
+
 /*
  * The fuction CFStringGetSystemEncoding does not work correctly in
  * our context (autodiskmount deamon).  We include a local copy here
@@ -231,11 +275,11 @@ static unsigned int __CFStringGetDefaultEncodingForHFSUtil() {
         char buffer[MAXPATHLEN + 1];
         int fd;
 
-        strcpy(buffer, passwdp->pw_dir);
-        strcat(buffer, __kCFUserEncodingFileName);
+        strlcpy(buffer, passwdp->pw_dir, sizeof(buffer));
+        strlcat(buffer, __kCFUserEncodingFileName, sizeof(buffer));
 
         if ((fd = open(buffer, O_RDONLY, 0)) > 0) {
-            size_t readSize;
+            ssize_t readSize;
 
             readSize = read(fd, buffer, MAXPATHLEN);
             buffer[(readSize < 0 ? 0 : readSize)] = '\0';
@@ -297,7 +341,7 @@ static struct hfs_mnt_encoding hfs_mnt_encodinglist[] = {
 };
 
 #define KEXT_LOAD_COMMAND      "/sbin/kextload"
-#define ENCODING_MODULE_PATH   "/System/Library/Filesystems/hfs.fs/Encodings/"
+#define ENCODING_MODULE_PATH   "/System/Library/Filesystems/hfs.fs/Contents/Resources/Encodings/"
 
 static int load_encoding(CFStringEncoding encoding)
 {
@@ -328,7 +372,7 @@ static int load_encoding(CFStringEncoding encoding)
                return FSUR_LOADERR;
        }
        
-       sprintf(kmodfile, "%sHFS_Mac%s.kext", ENCODING_MODULE_PATH, encodingName);
+       snprintf(kmodfile, sizeof(kmodfile), "%sHFS_Mac%s.kext", ENCODING_MODULE_PATH, encodingName);
        if (stat(kmodfile, &sb) == -1)
        {
                /* We recognized the encoding, but couldn't find the KEXT */
@@ -394,37 +438,37 @@ int main (int argc, const char *argv[])
     --   "/dev/disk0s2"
     */
 
-    sprintf(rawDeviceName, "/dev/r%s", argv[2]);
-    sprintf(blockDeviceName, "/dev/%s", argv[2]);
+    snprintf(rawDeviceName, sizeof(rawDeviceName), "/dev/r%s", argv[2]);
+    snprintf(blockDeviceName, sizeof(blockDeviceName), "/dev/%s", argv[2]);
 
     /* call the appropriate routine to handle the given action argument after becoming root */
 
     switch( * actionPtr ) {
         case FSUC_PROBE:
-            result = DoProbe(rawDeviceName);
+            result = DoProbe(rawDeviceName, blockDeviceName);
             break;
 
         case FSUC_MOUNT:
         case FSUC_MOUNT_FORCE:
-            result = DoMount(blockDeviceName, mountPointPtr, isLocked, isSetuid, isDev);
+            result = DoMount(blockDeviceName, rawDeviceName, mountPointPtr, isLocked, isSetuid, isDev);
             break;
 
         case FSUC_UNMOUNT:
             result = DoUnmount( mountPointPtr );
             break;
                case FSUC_GETUUID:
-                       result = DoGetUUIDKey( blockDeviceName );
+                       result = DoGetUUIDKey( blockDeviceName, rawDeviceName);
                        break;
                
                case FSUC_SETUUID:
                        result = DoChangeUUIDKey( blockDeviceName );
                        break;
                case FSUC_ADOPT:
-                       result = DoAdopt( blockDeviceName );
+                       result = DoAdopt( blockDeviceName, rawDeviceName);
                        break;
                
                case FSUC_DISOWN:
-                       result = DoDisown( blockDeviceName );
+                       result = DoDisown( blockDeviceName, rawDeviceName );
                        break;
 
                case FSUC_MKJNL:
@@ -439,6 +483,23 @@ int main (int argc, const char *argv[])
                        result = DoUnJournal( argv[2] );
                        break;
                        
+               case FSUC_UNJNL_RAW:
+                       result = RawDisableJournaling( argv[2] );
+                       break;
+                       
+               case FSUC_JNLINFS_RAW:
+                       // argv[2] has the device for the external journal.  however
+                       // we don't need it so we ignore it and just pass argv[3]
+                       // which is the hfs volume whose state we're going to change
+                       //
+                       result = SetJournalInFSState( argv[3], 1 );
+                       break;
+                       
+               case FSUC_EXTJNL_RAW:
+                       // see the comment for FSUC_JNLINFS_RAW
+                       result = SetJournalInFSState( argv[3], 0 );
+                       break;
+                       
                case FSUC_JNLINFO:
                        result = DoGetJournalInfo( argv[2] );
                        break;
@@ -470,7 +531,8 @@ Output -
 returns FSUR_IO_SUCCESS everything is cool else one of several other FSUR_xyz error codes.
 *********************************************************************** */
 static int
-DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, boolean_t isSetuid, boolean_t isDev)
+DoMount(char *deviceNamePtr, const char *rawName, const char *mountPointPtr,
+               boolean_t isLocked, boolean_t isSetuid, boolean_t isDev)
 {
        int pid;
         char *isLockedstr;
@@ -481,7 +543,7 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, bool
        union wait status;
        char encodeopt[16] = "";
        CFStringEncoding encoding;
-       VolumeUUID targetVolumeUUID;
+       volUUID_t targetVolUUID;
        VolumeStatusDBHandle vsdbhandle = NULL;
        unsigned long targetVolumeStatus;
 
@@ -490,15 +552,14 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, bool
 
        /* get the volume UUID to check if permissions should be used: */
        targetVolumeStatus = 0;
-       if (((result = GetVolumeUUID(deviceNamePtr, &targetVolumeUUID, FALSE)) != FSUR_IO_SUCCESS) ||
-               (targetVolumeUUID.v.high ==0) ||
-               (targetVolumeUUID.v.low == 0)) {
+       if (((result = GetVolumeUUID(deviceNamePtr, rawName, &targetVolUUID, FALSE)) != FSUR_IO_SUCCESS) ||
+                       (uuid_is_null(targetVolUUID.uuid))) {
 #if TRACE_HFS_UTIL
                fprintf(stderr, "hfs.util: DoMount: GetVolumeUUID returned %d.\n", result);
 #endif
 #if AUTO_ADOPT_FIXED
                if (gIsEjectable == 0) {
-                       result = DoAdopt( deviceNamePtr );
+                       result = DoAdopt( deviceNamePtr, rawName);
 #if TRACE_HFS_UTIL
                        fprintf(stderr, "hfs.util: DoMount: Auto-adopting %s; result = %d.\n", deviceNamePtr, result);
 #endif
@@ -512,9 +573,6 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, bool
 #endif
        } else {
                /* We've got a real volume UUID! */
-#if TRACE_HFS_UTIL
-               fprintf(stderr, "hfs.util: DoMount: UUID = %08lX%08lX.\n", targetVolumeUUID.v.high, targetVolumeUUID.v.low);
-#endif
                if ((result = OpenVolumeStatusDB(&vsdbhandle)) != 0) {
                        /* Can't even get access to the volume info db; assume permissions are OK. */
 #if TRACE_HFS_UTIL
@@ -525,13 +583,13 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, bool
 #if TRACE_HFS_UTIL
                        fprintf(stderr, "hfs.util: DoMount: Looking up volume status...\n");
 #endif
-                       if ((result = GetVolumeStatusDBEntry(vsdbhandle, &targetVolumeUUID, &targetVolumeStatus)) != 0) {
+                       if ((result = GetVolumeStatusDBEntry(vsdbhandle, &targetVolUUID, &targetVolumeStatus)) != 0) {
 #if TRACE_HFS_UTIL
                                fprintf(stderr, "hfs.util: DoMount: GetVolumeStatusDBEntry returned %d.\n", result);
 #endif
 #if AUTO_ENTER_FIXED
                                if (gIsEjectable == 0) {
-                                       result = DoAdopt( deviceNamePtr );
+                                       result = DoAdopt( deviceNamePtr, rawName );
 #if TRACE_HFS_UTIL
                                        fprintf(stderr, "hfs.util: DoMount: Auto-adopting %s; result = %d.\n", deviceNamePtr, result);
 #endif
@@ -566,7 +624,7 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, bool
 #else
                encoding = CFStringGetSystemEncoding();
 #endif
-               sprintf(encodeopt, "-e=%d", (int)encoding);
+               snprintf(encodeopt, sizeof(encodeopt), "-e=%d", (int)encoding);
 #if TRACE_HFS_UTIL
                fprintf(stderr, "hfs.util: %s %s -o -x -o %s -o %s -o -u=unknown,-g=unknown,-m=0777 -t %s %s %s ...\n",
                                                        gMountCommand, isLockedstr, encodeopt, permissionsOption, gHFS_FS_NAME, deviceNamePtr, mountPointPtr);
@@ -577,7 +635,7 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, bool
                                         "-t", gHFS_FS_NAME, deviceNamePtr, mountPointPtr, NULL);
                 
 
-               /* IF WE ARE HERE, WE WERE UNSUCCESFULL */
+               /* IF WE ARE HERE, WE WERE UNSUCCESFUL */
                return (FSUR_IO_FAIL);
        }
 
@@ -636,25 +694,97 @@ DoUnmount(const char * theMountPointPtr)
 } /* DoUnmount */
 
 
+/*
+       PrintVolumeNameAttr
+       
+       Get the volume name of the volume mounted at "path".  Print that volume
+       name to standard out.
+
+       Returns: FSUR_RECOGNIZED, FSUR_IO_FAIL
+*/
+struct VolumeNameBuf {
+       u_int32_t       info_length;
+       attrreference_t name_ref;
+       char            buffer[1024];
+};
+
+static int
+PrintVolumeNameAttr(const char *path)
+{
+       struct attrlist alist;
+       struct VolumeNameBuf volNameInfo;
+       int result;
+
+       /* Set up the attrlist structure to get the volume's Finder Info */
+       memset (&alist, 0, sizeof(alist));
+       alist.bitmapcount = 5;
+       alist.reserved = 0;
+       alist.commonattr = 0;
+       alist.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME;
+       alist.dirattr = 0;
+       alist.fileattr = 0;
+       alist.forkattr = 0;
+       
+
+       /* Get the Finder Info */
+       result = getattrlist(path, &alist, &volNameInfo, sizeof(volNameInfo), 0);
+       if (result) {
+               result = FSUR_IO_FAIL;
+               goto Err_Exit;
+       }
+
+       /* Print the name to standard out */
+       printf("%.*s", (int) volNameInfo.name_ref.attr_length, ((char *) &volNameInfo.name_ref) + volNameInfo.name_ref.attr_dataoffset);
+       result = FSUR_RECOGNIZED;
+
+Err_Exit:
+       return result;
+}
+
+
 /* ******************************************* DoProbe **********************************************
 Purpose -
-    This routine will open the given raw device and check to make sure there is media that looks
-    like an HFS.
+    This routine will open the given device and check to make sure there is media that looks
+    like an HFS.  If it is HFS, then print the volume name to standard output.
 Input -
-    theDeviceNamePtr - pointer to the device name (full path, like /dev/disk0s2).
+    rawDeviceNamePtr - pointer to the full path of the raw device (like /dev/rdisk0s2).
+    blockDeviceNamePtr - pointer to the full path of the non-raw device (like /dev/disk0s2).
 Output -
     returns FSUR_RECOGNIZED if we can handle the media else one of the FSUR_xyz error codes.
 *************************************************************************************************** */
 static int
-DoProbe(char *deviceNamePtr)
+DoProbe(char *rawDeviceNamePtr, char *blockDeviceNamePtr)
 {
        int result = FSUR_UNRECOGNIZED;
        int fd = 0;
        char * bufPtr;
        HFSMasterDirectoryBlock * mdbPtr;
        HFSPlusVolumeHeader * volHdrPtr;
-       u_char volnameUTF8[NAME_MAX+1];
+       u_char volnameUTF8[kHFSPlusMaxFileNameBytes];
 
+       /*
+        * Determine if there is a volume already mounted from this device.  If
+        * there is, and it is HFS, then we need to get the volume name via
+        * getattrlist.
+        *
+        * NOTE: We're using bufPtr to hold a pointer to a path.
+        */
+       bufPtr = NULL;
+       result = GetHFSMountPoint(blockDeviceNamePtr, &bufPtr);
+       if (result != FSUR_IO_SUCCESS) {
+               goto Err_Exit;
+       }
+       if (bufPtr != NULL) {
+               /* There is an HFS volume mounted from the device. */
+               result = PrintVolumeNameAttr(bufPtr);
+               goto Err_Exit;
+       }
+       
+       /*
+        * If we get here, there is no volume mounted from this device, so
+        * go probe the raw device directly.
+        */
+       
        bufPtr = (char *)malloc(HFS_BLOCK_SIZE);
        if ( ! bufPtr ) {
                result = FSUR_UNRECOGNIZED;
@@ -664,7 +794,7 @@ DoProbe(char *deviceNamePtr)
        mdbPtr = (HFSMasterDirectoryBlock *) bufPtr;
        volHdrPtr = (HFSPlusVolumeHeader *) bufPtr;
 
-       fd = open( deviceNamePtr, O_RDONLY, 0 );
+       fd = open( rawDeviceNamePtr, O_RDONLY, 0 );
        if( fd <= 0 ) {
                result = FSUR_IO_FAIL;
                goto Return;
@@ -678,20 +808,20 @@ DoProbe(char *deviceNamePtr)
                goto Return;
 
        /* get classic HFS volume name (from MDB) */
-       if (NXSwapBigShortToHost(mdbPtr->drSigWord) == kHFSSigWord &&
-           NXSwapBigShortToHost(mdbPtr->drEmbedSigWord) != kHFSPlusSigWord) {
+       if (OSSwapBigToHostInt16(mdbPtr->drSigWord) == kHFSSigWord &&
+           OSSwapBigToHostInt16(mdbPtr->drEmbedSigWord) != kHFSPlusSigWord) {
                Boolean cfOK;
                CFStringRef cfstr;
                CFStringEncoding encoding;
 
                /* Some poorly mastered HFS CDs have an empty MDB name field! */
                if (mdbPtr->drVN[0] == '\0') {
-                       strcpy(&mdbPtr->drVN[1], gHFS_FS_NAME_NAME);
+                       strcpy((char *)&mdbPtr->drVN[1], gHFS_FS_NAME_NAME);
                        mdbPtr->drVN[0] = strlen(gHFS_FS_NAME_NAME);
                }
 
                /* Check for an encoding hint in the Finder Info (field 4). */
-               encoding = GET_HFS_TEXT_ENCODING(NXSwapBigLongToHost(mdbPtr->drFndrInfo[4]));
+               encoding = GET_HFS_TEXT_ENCODING(OSSwapBigToHostInt32(mdbPtr->drFndrInfo[4]));
                if (encoding == kCFStringEncodingInvalidId) {
                        /* Next try the encoding bias in the kernel. */
                        encoding = GetEncodingBias();
@@ -701,6 +831,10 @@ DoProbe(char *deviceNamePtr)
 
                cfstr = CFStringCreateWithPascalString(kCFAllocatorDefault,
                            mdbPtr->drVN, encoding);
+               if (cfstr == NULL) {
+                       result = FSUR_INVAL;
+                       goto Return;
+               }
                cfOK = _CFStringGetFileSystemRepresentation(cfstr, volnameUTF8, NAME_MAX);
                CFRelease(cfstr);
 
@@ -715,17 +849,23 @@ DoProbe(char *deviceNamePtr)
                }
  
                /* Preload the encoding converter so mount_hfs can run as an ordinary user. */
-               if (encoding != kCFStringEncodingMacRoman)
-                       result = load_encoding(encoding);
+               if (encoding != kCFStringEncodingMacRoman) {
+                       if (load_encoding(encoding) != FSUR_IO_SUCCESS) {
+                               encoding = kCFStringEncodingMacRoman;
+                               cfstr = CFStringCreateWithPascalString(kCFAllocatorDefault, mdbPtr->drVN, encoding);
+                               _CFStringGetFileSystemRepresentation(cfstr, volnameUTF8, NAME_MAX);
+                               CFRelease(cfstr);
+                       }
+               }
  
        /* get HFS Plus volume name (from Catalog) */
-       } else if ((NXSwapBigShortToHost(volHdrPtr->signature) == kHFSPlusSigWord)  ||
-                  (NXSwapBigShortToHost(volHdrPtr->signature) == kHFSXSigWord)  ||
-                  (NXSwapBigShortToHost(mdbPtr->drSigWord) == kHFSSigWord &&
-                   NXSwapBigShortToHost(mdbPtr->drEmbedSigWord) == kHFSPlusSigWord)) {
+       } else if ((OSSwapBigToHostInt16(volHdrPtr->signature) == kHFSPlusSigWord)  ||
+                  (OSSwapBigToHostInt16(volHdrPtr->signature) == kHFSXSigWord)  ||
+                  (OSSwapBigToHostInt16(mdbPtr->drSigWord) == kHFSSigWord &&
+                   OSSwapBigToHostInt16(mdbPtr->drEmbedSigWord) == kHFSPlusSigWord)) {
                off_t startOffset;
 
-               if (NXSwapBigShortToHost(volHdrPtr->signature) == kHFSSigWord) {
+               if (OSSwapBigToHostInt16(volHdrPtr->signature) == kHFSSigWord) {
                        /* embedded volume, first find offset */
                        result = GetEmbeddedHFSPlusVol(mdbPtr, &startOffset);
                        if ( result != FSUR_IO_SUCCESS )
@@ -741,16 +881,8 @@ DoProbe(char *deviceNamePtr)
        }
 
        if (FSUR_IO_SUCCESS == result) {
-               char *s;
-               
-               /* Change slashes to colons in the volume name */
-               for (s=volnameUTF8; *s; ++s) {
-                       if (*s == '/')
-                               *s = ':';
-               }
-
                /* Print the volume name to standard output */
-               write(1, volnameUTF8, strlen(volnameUTF8));
+               write(1, volnameUTF8, strlen((char *)volnameUTF8));
                result = FSUR_RECOGNIZED;
        }
 
@@ -761,36 +893,60 @@ Return:
 
        if (fd > 0)
                close(fd);
-
+Err_Exit:
        return result;
 
 } /* DoProbe */
 
+/*
+ * Create a version 3 UUID from a unique "name" in the given "name space".  
+ * Version 3 UUID are derived using "name" via MD5 checksum.
+ *
+ * Parameters:
+ *     result_uuid     - resulting UUID.
+ *     namespace       - namespace in which given name exists and UUID should be created.
+ *     name            - unique string used to create version 3 UUID.
+ *     namelen     - length of the name string.
+ */
+static void
+uuid_create_md5_from_name(uuid_t result_uuid, const uuid_t namespace, const void *name, int namelen)
+{
+    MD5_CTX c;
+
+    MD5_Init(&c);
+    MD5_Update(&c, namespace, sizeof(uuid_t));
+    MD5_Update(&c, name, namelen);
+    MD5_Final(result_uuid, &c);
+
+    result_uuid[6] = (result_uuid[6] & 0x0F) | 0x30;
+    result_uuid[8] = (result_uuid[8] & 0x3F) | 0x80;
+}
 
 
 /* **************************************** DoGetUUIDKey *******************************************
 Purpose -
-    This routine will open the given block device and return the volume UUID in text form written to stdout.
+    This routine will open the given block device and return the 128-bit volume UUID in text form written to stdout.
 Input -
     theDeviceNamePtr - pointer to the device name (full path, like /dev/disk0s2).
 Output -
     returns FSUR_IO_SUCCESS or else one of the FSUR_xyz error codes.
 *************************************************************************************************** */
 static int
-DoGetUUIDKey( const char * theDeviceNamePtr ) {
+DoGetUUIDKey( const char * theDeviceNamePtr, const char *rawName) {
        int result;
-       VolumeUUID targetVolumeUUID;
-       VolumeUUIDString UUIDString;
-       char uuidLine[VOLUMEUUIDLENGTH+2];
-       
-       if ((result = GetVolumeUUID(theDeviceNamePtr, &targetVolumeUUID, FALSE)) != FSUR_IO_SUCCESS) goto Err_Exit;
-       
-       ConvertVolumeUUIDToString( &targetVolumeUUID, UUIDString);
-       strncpy(uuidLine, UUIDString, VOLUMEUUIDLENGTH+1);
-       write(1, uuidLine, strlen(uuidLine));
-       result = FSUR_IO_SUCCESS;
-       
-Err_Exit:
+       volUUID_t targetVolumeUUID;
+       uuid_string_t uustr;
+
+       result = GetVolumeUUID(theDeviceNamePtr, rawName, &targetVolumeUUID, FALSE);
+       if (result == FSUR_IO_SUCCESS) {
+               uuid_unparse (targetVolumeUUID.uuid, uustr);
+               /* for compatibility, must write out the string to stdout, with NO newline */
+               write(STDOUT_FILENO, uustr, strlen(uustr));
+
+               /* for debugging */
+               // fprintf(stderr, "device %s UUID : %s\n", rawName, uustr);
+       }
+
        return result;
 }
 
@@ -807,11 +963,17 @@ Output -
 static int
 DoChangeUUIDKey( const char * theDeviceNamePtr ) {
        int result;
-       VolumeUUID newVolumeUUID;
+       hfs_UUID_t newVolumeUUID;
        
-       GenerateVolumeUUID(&newVolumeUUID);
+       GenerateHFSVolumeUUID(&newVolumeUUID);
+#if 0
+       // for testing purposes, may want to set a NULL UUID from command line.
+       memset (&newVolumeUUID, 0, sizeof(newVolumeUUID));
+#endif
        result = SetVolumeUUID(theDeviceNamePtr, &newVolumeUUID);
        
+       //fprintf(stderr, "device %s has new UUID \n", theDeviceNamePtr);
+
        return result;
 }
 
@@ -826,13 +988,13 @@ Output -
     returns FSUR_IO_SUCCESS or else one of the FSUR_xyz error codes.
 *************************************************************************************************** */
 static int
-DoAdopt( const char * theDeviceNamePtr ) {
+DoAdopt( const char * theDeviceNamePtr, const char *rawName) {
        int result, closeresult;
-       VolumeUUID targetVolumeUUID;
+       volUUID_t targetVolumeUUID;
        VolumeStatusDBHandle vsdbhandle = NULL;
        unsigned long targetVolumeStatus;
        
-       if ((result = GetVolumeUUID(theDeviceNamePtr, &targetVolumeUUID, TRUE)) != FSUR_IO_SUCCESS) goto Err_Return;
+       if ((result = GetVolumeUUID(theDeviceNamePtr, rawName, &targetVolumeUUID, TRUE)) != FSUR_IO_SUCCESS) goto Err_Return;
        
        if ((result = OpenVolumeStatusDB(&vsdbhandle)) != 0) goto Err_Exit;
        if ((result = GetVolumeStatusDBEntry(vsdbhandle, &targetVolumeUUID, &targetVolumeStatus)) != 0) {
@@ -870,13 +1032,13 @@ Output -
     returns FSUR_IO_SUCCESS or else one of the FSUR_xyz error codes.
 *************************************************************************************************** */
 static int
-DoDisown( const char * theDeviceNamePtr ) {
+DoDisown( const char * theDeviceNamePtr, const char *rawName) {
        int result, closeresult;
-       VolumeUUID targetVolumeUUID;
+       volUUID_t targetVolumeUUID;
        VolumeStatusDBHandle vsdbhandle = NULL;
        unsigned long targetVolumeStatus;
        
-       if ((result = GetVolumeUUID(theDeviceNamePtr, &targetVolumeUUID, TRUE)) != FSUR_IO_SUCCESS) goto Err_Return;
+       if ((result = GetVolumeUUID(theDeviceNamePtr, rawName, &targetVolumeUUID, TRUE)) != FSUR_IO_SUCCESS) goto Err_Return;
        
        if ((result = OpenVolumeStatusDB(&vsdbhandle)) != 0) goto Err_Exit;
        if ((result = GetVolumeStatusDBEntry(vsdbhandle, &targetVolumeUUID, &targetVolumeStatus)) != 0) {
@@ -1047,6 +1209,21 @@ ParseArgs(int argc, const char *argv[], const char ** actionPtr,
                        doLengthCheck = 0;
                        break;
 
+               case FSUC_UNJNL_RAW:
+                       index = 0;
+                       doLengthCheck = 0;
+                       break;
+
+               case FSUC_JNLINFS_RAW:
+                       index = 0;
+                       doLengthCheck = 0;
+                       break;
+
+               case FSUC_EXTJNL_RAW:
+                       index = 0;
+                       doLengthCheck = 0;
+                       break;
+
                case FSUC_JNLINFO:
                        index = 0;
                        doLengthCheck = 0;
@@ -1136,10 +1313,13 @@ DoDisplayUsage(const char *argv[])
 #ifdef HFS_UUID_SUPPORT
     printf("       -%c (Get UUID Key)\n", FSUC_GETUUID);
     printf("       -%c (Set UUID Key)\n", FSUC_SETUUID);
-#endif HFS_UUID_SUPPORT
+#endif //HFS_UUID_SUPPORT
     printf("       -%c (Adopt permissions)\n", FSUC_ADOPT);
        printf("       -%c (Make a file system journaled)\n", FSUC_MKJNL);
        printf("       -%c (Turn off journaling on a file system)\n", FSUC_UNJNL);
+       printf("       -%c (Turn off journaling on a raw device)\n", FSUC_UNJNL_RAW);
+       printf("       -%c (Disable use of an external journal on a raw device)\n", FSUC_JNLINFS_RAW);
+       printf("       -%c (Enable the use of an external journal on a raw device)\n", FSUC_EXTJNL_RAW);
        printf("       -%c (Get size & location of journaling on a file system)\n", FSUC_JNLINFO);
     printf("device_arg:\n");
     printf("       device we are acting upon (for example, 'disk0s2')\n");
@@ -1216,7 +1396,7 @@ GetHFSMountPoint(const char *deviceNamePtr, char **pathPtr)
        Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL, FSUR_UNRECOGNIZED
 */
 static int
-ReadHeaderBlock(int fd, void *bufPtr, off_t *startOffset, VolumeUUID **finderInfoUUIDPtr)
+ReadHeaderBlock(int fd, void *bufPtr, off_t *startOffset, hfs_UUID_t **finderInfoUUIDPtr)
 {
        int result;
        HFSMasterDirectoryBlock * mdbPtr;
@@ -1237,8 +1417,8 @@ ReadHeaderBlock(int fd, void *bufPtr, off_t *startOffset, VolumeUUID **finderInf
         * If this is a wrapped HFS Plus volume, read the Volume Header from
         * sector 2 of the embedded volume.
         */
-       if (NXSwapBigShortToHost(mdbPtr->drSigWord) == kHFSSigWord &&
-               NXSwapBigShortToHost(mdbPtr->drEmbedSigWord) == kHFSPlusSigWord) {
+       if (OSSwapBigToHostInt16(mdbPtr->drSigWord) == kHFSSigWord &&
+               OSSwapBigToHostInt16(mdbPtr->drEmbedSigWord) == kHFSPlusSigWord) {
                result = GetEmbeddedHFSPlusVol(mdbPtr, startOffset);
                if (result != FSUR_IO_SUCCESS)
                        goto Err_Exit;
@@ -1252,11 +1432,11 @@ ReadHeaderBlock(int fd, void *bufPtr, off_t *startOffset, VolumeUUID **finderInf
         * volumes (including wrapped HFS Plus).  Verify the signature and grab the
         * UUID from the Finder Info.
         */
-       if (NXSwapBigShortToHost(mdbPtr->drSigWord) == kHFSSigWord) {
-           *finderInfoUUIDPtr = (VolumeUUID *)(&mdbPtr->drFndrInfo[6]);
-       } else if (NXSwapBigShortToHost(volHdrPtr->signature) == kHFSPlusSigWord ||
-                               NXSwapBigShortToHost(volHdrPtr->signature) == kHFSXSigWord) {
-           *finderInfoUUIDPtr = (VolumeUUID *)&volHdrPtr->finderInfo[24];
+       if (OSSwapBigToHostInt16(mdbPtr->drSigWord) == kHFSSigWord) {
+           *finderInfoUUIDPtr = (hfs_UUID_t *)(&mdbPtr->drFndrInfo[6]);
+       } else if (OSSwapBigToHostInt16(volHdrPtr->signature) == kHFSPlusSigWord ||
+                               OSSwapBigToHostInt16(volHdrPtr->signature) == kHFSXSigWord) {
+           *finderInfoUUIDPtr = (hfs_UUID_t *)&volHdrPtr->finderInfo[24];
        } else {
                result = FSUR_UNRECOGNIZED;
        }
@@ -1271,18 +1451,22 @@ Err_Exit:
        
        Read the UUID from an unmounted volume, by doing direct access to the device.
        Assumes the caller has already determined that a volume is not mounted
-       on the device.
+       on the device.  Once we have the HFS UUID from the finderinfo, convert it to a
+       full UUID and then write it into the output argument provided (volUUIDPtr)
 
        Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL, FSUR_UNRECOGNIZED
 */
 static int
-GetVolumeUUIDRaw(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr)
+GetVolumeUUIDRaw(const char *deviceNamePtr, const char *rawName, volUUID_t *volUUIDPtr)
 {
        int fd = 0;
        char * bufPtr;
        off_t startOffset;
-       VolumeUUID *finderInfoUUIDPtr;
+       hfs_UUID_t *finderInfoUUIDPtr;
+       hfs_UUID_t hfs_uuid;
+       volUUID_t fullUUID;
        int result;
+       int error; 
 
        bufPtr = (char *)malloc(HFS_BLOCK_SIZE);
        if ( ! bufPtr ) {
@@ -1292,25 +1476,49 @@ GetVolumeUUIDRaw(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr)
 
        fd = open( deviceNamePtr, O_RDONLY, 0);
        if (fd <= 0) {
+               error = errno;
 #if TRACE_HFS_UTIL
-               fprintf(stderr, "hfs.util: GetVolumeUUIDRaw: device open failed (errno = %d).\n", errno);
+               fprintf(stderr, "hfs.util: GetVolumeUUIDRaw: device (%s)  open failed (errno = %d).\n", deviceNamePtr, errno);
 #endif
-               result = FSUR_IO_FAIL;
-               goto Err_Exit;
+               if (error == EBUSY) {
+                       /* If it was busy, then retry, this time using the raw device */
+                       fd = open (rawName, O_RDONLY, 0);
+                       if (fd <= 0) {
+#if TRACE_HFS_UTIL
+                               fprintf(stderr, "hfs.util: GetVolumeUUIDRaw: device (%s) open failed (errno = %d).\n", rawName, errno);
+#endif
+                               result = FSUR_IO_FAIL;
+                               goto Err_Exit;
+                       }
+               }
+               else {
+                       result = FSUR_IO_FAIL;
+                       goto Err_Exit;
+               }
        }
 
        /*
-        * Get the pointer to the volume UUID in the Finder Info
-        */
+        * Get the pointer to the volume UUID in the Finder Info*/
        result = ReadHeaderBlock(fd, bufPtr, &startOffset, &finderInfoUUIDPtr);
        if (result != FSUR_IO_SUCCESS)
                goto Err_Exit;
 
        /*
-        * Copy the volume UUID out of the Finder Info
+        * Copy the volume UUID out of the Finder Info. Note that the FinderInfo
+        * stores the UUID in big-endian so we have to convert to native
+        * endianness. 
+        */
+       hfs_uuid.high = OSSwapBigToHostInt32(finderInfoUUIDPtr->high);
+       hfs_uuid.low = OSSwapBigToHostInt32(finderInfoUUIDPtr->low);
+
+       /* 
+        * Now convert to a full UUID using the same algorithm as HFS+ 
+        * This makes sure to construct a full NULL-UUID if necessary.
         */
-       volumeUUIDPtr->v.high = NXSwapBigLongToHost(finderInfoUUIDPtr->v.high);
-       volumeUUIDPtr->v.low = NXSwapBigLongToHost(finderInfoUUIDPtr->v.low);
+       ConvertHFSUUIDToUUID (&hfs_uuid, &fullUUID);    
+
+       /* Copy it out into the caller's buffer */
+       uuid_copy(volUUIDPtr->uuid, fullUUID.uuid); 
 
 Err_Exit:
        if (fd > 0) close(fd);
@@ -1323,6 +1531,70 @@ Err_Exit:
 }
 
 
+
+void ConvertHFSUUIDStringToUUID(const char *UUIDString, volUUID_t *volumeID) {
+    int i;
+    char c;
+    u_int32_t nextdigit;
+    u_int32_t high = 0;
+    u_int32_t low = 0;
+    u_int32_t carry;
+       hfs_UUID_t hfsuu;
+
+    for (i = 0; (i < HFSUUIDLENGTH) && ((c = UUIDString[i]) != (char)0) ; ++i) {
+        if ((c >= '0') && (c <= '9')) {
+            nextdigit = c - '0';
+        } else if ((c >= 'A') && (c <= 'F')) {
+            nextdigit = c - 'A' + 10;
+        } else if ((c >= 'a') && (c <= 'f')) {
+            nextdigit = c - 'a' + 10;
+        } else {
+            nextdigit = 0;
+        }
+        carry = ((low & 0xF0000000) >> 28) & 0x0000000F;
+        high = (high << 4) | carry;
+        low = (low << 4) | nextdigit;
+    }
+
+    hfsuu.high = high;
+    hfsuu.low = low;
+
+       /* now convert to a full UUID */
+       ConvertHFSUUIDToUUID(&hfsuu, volumeID);
+
+       return;
+}
+
+
+
+/*
+ * Convert an HFS+ UUID in binary form to a full UUID 
+ * 
+ * Assumes that the HFS UUID argument is stored in native endianness
+ * If the input UUID is zeroes, then it will emit a NULL'd out UUID.
+ */
+void ConvertHFSUUIDToUUID (hfs_UUID_t *hfsuuid, volUUID_t *uu)
+{
+       uint8_t rawUUID[8];
+
+       /* if either high or low is 0, then return the NULL uuid */
+       if ((hfsuuid->high == 0) || (hfsuuid->low == 0)) {
+               uuid_clear (uu->uuid);
+               return;
+       }
+       /*
+        * If the input UUID was not zeroes, then run it through the normal md5
+        *
+        * NOTE: When using MD5 to compute the "full" UUID, we must pass in the
+        * big-endian values of the two 32-bit fields.  In the kernel, HFS uses the
+        * raw 4-byte fields of the finderinfo directly, without running them through
+        * an endian-swap.  As a result, we must endian-swap back to big endian here.
+        */
+       ((uint32_t*)rawUUID)[0] = OSSwapHostToBigInt32(hfsuuid->high);
+       ((uint32_t*)rawUUID)[1] = OSSwapHostToBigInt32(hfsuuid->low);   
+       uuid_create_md5_from_name(uu->uuid, kFSUUIDNamespaceSHA1, rawUUID, sizeof(rawUUID));    
+}
+
 /*
        SetVolumeUUIDRaw
        
@@ -1333,12 +1605,12 @@ Err_Exit:
        Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL, FSUR_UNRECOGNIZED
 */
 static int
-SetVolumeUUIDRaw(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr)
+SetVolumeUUIDRaw(const char *deviceNamePtr, hfs_UUID_t *volumeUUIDPtr)
 {
        int fd = 0;
        char * bufPtr;
        off_t startOffset;
-       VolumeUUID *finderInfoUUIDPtr;
+       hfs_UUID_t *finderInfoUUIDPtr;
        int result;
 
        bufPtr = (char *)malloc(HFS_BLOCK_SIZE);
@@ -1364,10 +1636,10 @@ SetVolumeUUIDRaw(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr)
                goto Err_Exit;
 
        /*
-        * Update the UUID in the Finder Info
+        * Update the UUID in the Finder Info. Make sure to write out big endian.
         */
-       finderInfoUUIDPtr->v.high = NXSwapHostLongToBig(volumeUUIDPtr->v.high);
-       finderInfoUUIDPtr->v.low = NXSwapHostLongToBig(volumeUUIDPtr->v.low);
+       finderInfoUUIDPtr->high = OSSwapHostToBigInt32(volumeUUIDPtr->high);
+       finderInfoUUIDPtr->low = OSSwapHostToBigInt32(volumeUUIDPtr->low);
 
        /*
         * Write the modified MDB or VHB back to disk
@@ -1389,20 +1661,42 @@ Err_Exit:
        GetVolumeUUIDAttr
        
        Read the UUID from a mounted volume, by calling getattrlist().
-       Assumes the path is the mount point of an HFS volume.
+       Assumes the path is the mount point of an HFS volume. Note that this will
+       return the full-length UUID to the caller, as emitted by the underlying
+       filesystem.  On HFS+ this means that we use the hfs_vfsops.c implementation
+       to construct the UUID
 
        Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL
 */
 static int
-GetVolumeUUIDAttr(const char *path, VolumeUUID *volumeUUIDPtr)
+GetVolumeUUIDAttr(const char *path, volUUID_t *volUUIDPtr) 
 {
        struct attrlist alist;
-       struct FinderAttrBuf volFinderInfo;
-       VolumeUUID *finderInfoUUIDPtr;
+       UUIDAttrBuf_t uuidattr;
+       FinderAttrBuf_t finderinfo;
        int result;
 
-       /* Set up the attrlist structure to get the volume's Finder Info */
-       alist.bitmapcount = 5;
+       /*
+        * This is a little bit dodgy.  In order to detect whether or not the
+        * volume has a valid UUID, we need to call getattrlist() and examine
+        * the FinderInfo, which is what this function has historically done, even if
+        * we ultimately want the full UUID, which is what is returned if one requests
+        * ATTR_VOL_UUID. 
+        * 
+        * The reason is that if the UUID does not exist, it will be stored
+        * as 8 bytes of zeroes in the UUID portion of the finder info. However, if 
+        * you request ATTR_VOL_UUID, it will run the 8 bytes of zeroes through 
+        * the MD5 function, where they will be manipulated into a full UUID. It 
+        * doesn't look like that guarantees the resulting UUID will also be a 
+        * NULL-uuid (i.e. all zeroes).
+        * 
+        * All of this to say we need to check the finder info first, then check 
+        * ATTR_VOL_UUID as needed afterwards. 
+        */
+
+       /* First set up for a call to getattrlist for the finderinfo */
+       memset (&alist, 0, sizeof(alist));
+       alist.bitmapcount = ATTR_BIT_MAP_COUNT;
        alist.reserved = 0;
        alist.commonattr = ATTR_CMN_FNDRINFO;
        alist.volattr = ATTR_VOL_INFO;
@@ -1410,20 +1704,45 @@ GetVolumeUUIDAttr(const char *path, VolumeUUID *volumeUUIDPtr)
        alist.fileattr = 0;
        alist.forkattr = 0;
 
-       /* Get the Finder Info */
-       result = getattrlist(path, &alist, &volFinderInfo, sizeof(volFinderInfo), 0);
+       /* Get the finderinfo */
+       result = getattrlist(path, &alist, &finderinfo, sizeof(finderinfo), 0);
        if (result) {
-               result = FSUR_IO_FAIL;
-               goto Err_Exit;
+               return FSUR_IO_FAIL;
        }
 
-       /* Copy the UUID from the Finder Into to caller's buffer */
-       finderInfoUUIDPtr = (VolumeUUID *)(&volFinderInfo.finderinfo[6]);
-       volumeUUIDPtr->v.high = NXSwapBigLongToHost(finderInfoUUIDPtr->v.high);
-       volumeUUIDPtr->v.low = NXSwapBigLongToHost(finderInfoUUIDPtr->v.low);
+       /* Now we need to check if the finderinfo UUID is NULL */
+       hfs_UUID_t* hfs_finderinfo = (hfs_UUID_t*)(&finderinfo.finderinfo[6]);
+       
+       /* 
+        * We should really endian-swap these, but if a uint32_t is 0, 
+        * the endianness doesn't matter 
+        */
+       if ((hfs_finderinfo->high == 0) || (hfs_finderinfo->low == 0)) {
+               /* Then it is an uninitialized/NULL UUID. Zap the caller buffer and bail out */
+               uuid_clear (volUUIDPtr->uuid);
+               return FSUR_IO_SUCCESS;
+       }       
+
+       /* OK, now set up the attrlist structure to get the volume's UUID */
+       memset (&alist, 0, sizeof(alist));
+       alist.bitmapcount = ATTR_BIT_MAP_COUNT;
+       alist.reserved = 0;
+       alist.commonattr = 0;
+       alist.volattr = (ATTR_VOL_INFO | ATTR_VOL_UUID);
+       alist.dirattr = 0;
+       alist.fileattr = 0;
+       alist.forkattr = 0;
+
+       /* Get the full UUID from the kernel */
+       result = getattrlist(path, &alist, &uuidattr, sizeof(uuidattr), 0);
+       if (result) {
+               return FSUR_IO_FAIL;
+       }
+
+       /* Copy the UUID from the buf to caller's buffer */
+       uuid_copy (volUUIDPtr->uuid, uuidattr.uu);
        result = FSUR_IO_SUCCESS;
 
-Err_Exit:
        return result;
 }
 
@@ -1437,15 +1756,16 @@ Err_Exit:
        Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL
 */
 static int
-SetVolumeUUIDAttr(const char *path, VolumeUUID *volumeUUIDPtr)
+SetVolumeUUIDAttr(const char *path, hfs_UUID_t *volumeUUIDPtr)
 {
        struct attrlist alist;
        struct FinderAttrBuf volFinderInfo;
-       VolumeUUID *finderInfoUUIDPtr;
+       hfs_UUID_t *finderInfoUUIDPtr;
        int result;
 
        /* Set up the attrlist structure to get the volume's Finder Info */
-       alist.bitmapcount = 5;
+       memset (&alist, 0, sizeof(alist));
+       alist.bitmapcount = ATTR_BIT_MAP_COUNT;
        alist.reserved = 0;
        alist.commonattr = ATTR_CMN_FNDRINFO;
        alist.volattr = ATTR_VOL_INFO;
@@ -1460,10 +1780,10 @@ SetVolumeUUIDAttr(const char *path, VolumeUUID *volumeUUIDPtr)
                goto Err_Exit;
        }
 
-       /* Update the UUID in the Finder Info */
-       finderInfoUUIDPtr = (VolumeUUID *)(&volFinderInfo.finderinfo[6]);
-       finderInfoUUIDPtr->v.high = NXSwapHostLongToBig(volumeUUIDPtr->v.high);
-       finderInfoUUIDPtr->v.low = NXSwapHostLongToBig(volumeUUIDPtr->v.low);
+       /* Update the UUID in the Finder Info. Make sure to swap back to big endian */
+       finderInfoUUIDPtr = (hfs_UUID_t *)(&volFinderInfo.finderinfo[6]);
+       finderInfoUUIDPtr->high = OSSwapHostToBigInt32(volumeUUIDPtr->high);
+       finderInfoUUIDPtr->low = OSSwapHostToBigInt32(volumeUUIDPtr->low);
 
        /* Write the Finder Info back to the volume */
        result = setattrlist(path, &alist, &volFinderInfo.finderinfo, sizeof(volFinderInfo.finderinfo), 0);
@@ -1495,7 +1815,7 @@ Err_Exit:
  */
 
 static int
-GetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr, boolean_t generate)
+GetVolumeUUID(const char *deviceNamePtr, const char *rawName, volUUID_t *voluu, boolean_t generate)
 {
        int result;
        char *path = NULL;
@@ -1506,33 +1826,39 @@ GetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr, boolean_t ge
         * with FSUR_UNRECOGNIZED.
         */
        result = GetHFSMountPoint(deviceNamePtr, &path);
-       if (result != FSUR_IO_SUCCESS)
-               goto Err_Exit;
+       if (result != FSUR_IO_SUCCESS) {
+               return result;
+       }
 
        /*
         * Get any existing UUID.
         */
-       if (path)
-               result = GetVolumeUUIDAttr(path, volumeUUIDPtr);
-       else
-               result = GetVolumeUUIDRaw(deviceNamePtr, volumeUUIDPtr);
-       if (result != FSUR_IO_SUCCESS)
-               goto Err_Exit;
+       if (path) {
+               result = GetVolumeUUIDAttr(path, voluu);
+       }
+       else {
+               result = GetVolumeUUIDRaw(deviceNamePtr, rawName, voluu);
+       }
+
+       if (result != FSUR_IO_SUCCESS) {
+               return result;
+       }
 
        /*
         * If there was no valid UUID, and we were asked to generate one, then
         * generate it and write it back to disk.
         */
-       if (generate && (volumeUUIDPtr->v.high == 0 || volumeUUIDPtr->v.low == 0)) {
-               GenerateVolumeUUID(volumeUUIDPtr);
-               if (path)
-                       result = SetVolumeUUIDAttr(path, volumeUUIDPtr);
-               else
-                       result = SetVolumeUUIDRaw(deviceNamePtr, volumeUUIDPtr);
-               /* Fall through to Err_Exit */
-       }
+       if (generate && (uuid_is_null(voluu->uuid))) {
+               hfs_UUID_t hfsuu;
 
-Err_Exit:
+               GenerateHFSVolumeUUID(&hfsuu);
+               if (path) {
+                       result = SetVolumeUUIDAttr(path, &hfsuu);
+               }
+               else {
+                       result = SetVolumeUUIDRaw(deviceNamePtr, &hfsuu);
+               }
+       }
        return result;
 }
 
@@ -1550,7 +1876,7 @@ Err_Exit:
        Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL, FSUR_UNRECOGNIZED
  */
 static int
-SetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr) {
+SetVolumeUUID(const char *deviceNamePtr, hfs_UUID_t *volumeUUIDPtr) {
        int result;
        char *path = NULL;
        
@@ -1592,21 +1918,21 @@ GetEmbeddedHFSPlusVol (HFSMasterDirectoryBlock * hfsMasterDirectoryBlockPtr, off
     int                result = FSUR_IO_SUCCESS;
     u_int32_t  allocationBlockSize, firstAllocationBlock, startBlock, blockCount;
 
-    if (NXSwapBigShortToHost(hfsMasterDirectoryBlockPtr->drSigWord) != kHFSSigWord) {
+    if (OSSwapBigToHostInt16(hfsMasterDirectoryBlockPtr->drSigWord) != kHFSSigWord) {
         result = FSUR_UNRECOGNIZED;
         goto Return;
     }
 
-    allocationBlockSize = NXSwapBigLongToHost(hfsMasterDirectoryBlockPtr->drAlBlkSiz);
-    firstAllocationBlock = NXSwapBigShortToHost(hfsMasterDirectoryBlockPtr->drAlBlSt);
+    allocationBlockSize = OSSwapBigToHostInt32(hfsMasterDirectoryBlockPtr->drAlBlkSiz);
+    firstAllocationBlock = OSSwapBigToHostInt16(hfsMasterDirectoryBlockPtr->drAlBlSt);
 
-    if (NXSwapBigShortToHost(hfsMasterDirectoryBlockPtr->drEmbedSigWord) != kHFSPlusSigWord) {
+    if (OSSwapBigToHostInt16(hfsMasterDirectoryBlockPtr->drEmbedSigWord) != kHFSPlusSigWord) {
         result = FSUR_UNRECOGNIZED;
         goto Return;
     }
 
-    startBlock = NXSwapBigShortToHost(hfsMasterDirectoryBlockPtr->drEmbedExtent.startBlock);
-    blockCount = NXSwapBigShortToHost(hfsMasterDirectoryBlockPtr->drEmbedExtent.blockCount);
+    startBlock = OSSwapBigToHostInt16(hfsMasterDirectoryBlockPtr->drEmbedExtent.startBlock);
+    blockCount = OSSwapBigToHostInt16(hfsMasterDirectoryBlockPtr->drEmbedExtent.blockCount);
 
     if ( startOffsetPtr )
         *startOffsetPtr = ((u_int64_t)startBlock * (u_int64_t)allocationBlockSize) +
@@ -1628,7 +1954,7 @@ Return:
  */
 
 static int
-GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * name_o)
+GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, unsigned char * name_o)
 {
     int                                        result = FSUR_IO_SUCCESS;
     u_int32_t                          blockSize;
@@ -1660,8 +1986,8 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
 
     /* Verify that it is an HFS+ volume. */
 
-    if (NXSwapBigShortToHost(volHdrPtr->signature) != kHFSPlusSigWord &&
-        NXSwapBigShortToHost(volHdrPtr->signature) != kHFSXSigWord) {
+    if (OSSwapBigToHostInt16(volHdrPtr->signature) != kHFSPlusSigWord &&
+        OSSwapBigToHostInt16(volHdrPtr->signature) != kHFSXSigWord) {
         result = FSUR_IO_FAIL;
 #if TRACE_HFS_UTIL
         fprintf(stderr, "hfs.util: GetNameFromHFSPlusVolumeStartingAt: volHdrPtr->signature != kHFSPlusSigWord\n");
@@ -1669,7 +1995,7 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
         goto Return;
     }
 
-    blockSize = NXSwapBigLongToHost(volHdrPtr->blockSize);
+    blockSize = OSSwapBigToHostInt32(volHdrPtr->blockSize);
     catalogExtents = (HFSPlusExtentDescriptor *) malloc(sizeof(HFSPlusExtentRecord));
     if ( ! catalogExtents ) {
         result = FSUR_IO_FAIL;
@@ -1679,7 +2005,7 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
        catalogExtCount = kHFSPlusExtentDensity;
 
        /* if there are overflow catalog extents, then go get them */
-       if (NXSwapBigLongToHost(catalogExtents[7].blockCount) != 0) {
+       if (OSSwapBigToHostInt32(catalogExtents[7].blockCount) != 0) {
                result = GetCatalogOverflowExtents(fd, hfsPlusVolumeOffset, volHdrPtr, &catalogExtents, &catalogExtCount);
                if (result != FSUR_IO_SUCCESS)
                        goto Return;
@@ -1719,7 +2045,7 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
         HFSPlusCatalogKey      *       k;
        CFStringRef cfstr;
 
-        if ( bTreeNodeDescriptorPtr->numRecords < 1) {
+        if ( OSSwapBigToHostInt16(bTreeNodeDescriptorPtr->numRecords) < 1) {
             result = FSUR_IO_FAIL;
 #if TRACE_HFS_UTIL
                        fprintf(stderr, "hfs.util: ERROR: bTreeNodeDescriptorPtr->numRecords < 1\n");
@@ -1734,12 +2060,12 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
 
        // Get a pointer to the first record.
 
-        p = bufPtr + NXSwapBigShortToHost(*v); // pointer arithmetic in bytes
+        p = bufPtr + OSSwapBigToHostInt16(*v); // pointer arithmetic in bytes
         k = (HFSPlusCatalogKey *)p;
 
        // There should be only one record whose parent is the root parent.  It should be the first record.
 
-        if (NXSwapBigLongToHost(k->parentID) != kHFSRootParentID) {
+        if (OSSwapBigToHostInt32(k->parentID) != kHFSRootParentID) {
             result = FSUR_IO_FAIL;
 #if TRACE_HFS_UTIL
             fprintf(stderr, "hfs.util: ERROR: k->parentID != kHFSRootParentID\n");
@@ -1747,6 +2073,16 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
             goto Return;
         }
 
+       if ((OSSwapBigToHostInt16(k->nodeName.length) >
+               (sizeof(k->nodeName.unicode) / sizeof(k->nodeName.unicode[0]))) ||
+               OSSwapBigToHostInt16(k->nodeName.length) > 255) {
+               result = FSUR_IO_FAIL;
+#if TRACE_HFS_UTIL
+               fprintf(stderr, "hfs.util: ERROR:  k->nodeName.length is a bad size (%d)\n", OSSwapBigToHostInt16(k->nodeName.length));
+#endif
+               goto Return;
+       }
+
        /* Extract the name of the root directory */
 
        {
@@ -1758,14 +2094,14 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
                result = FSUR_IO_FAIL;
                goto Return;
            }
-           swapped->length = NXSwapBigShortToHost(k->nodeName.length);
+           swapped->length = OSSwapBigToHostInt16(k->nodeName.length);
            
            for (i=0; i<swapped->length; i++) {
-               swapped->unicode[i] = NXSwapBigShortToHost(k->nodeName.unicode[i]);
+               swapped->unicode[i] = OSSwapBigToHostInt16(k->nodeName.unicode[i]);
            }
            swapped->unicode[i] = 0;
            cfstr = CFStringCreateWithCharacters(kCFAllocatorDefault, swapped->unicode, swapped->length);
-           (void) CFStringGetCString(cfstr, name_o, NAME_MAX, kCFStringEncodingUTF8);
+           (void) CFStringGetCString(cfstr, (char *)name_o, NAME_MAX * 3 + 1, kCFStringEncodingUTF8);
            CFRelease(cfstr);
            free(swapped);
        }
@@ -1788,12 +2124,10 @@ Return:
 } /* GetNameFromHFSPlusVolumeStartingAt */
 
 
-#pragma options align=mac68k
 typedef struct {
        BTNodeDescriptor        node;
        BTHeaderRec             header;
-} HeaderRec, *HeaderPtr;
-#pragma options align=reset
+} __attribute__((aligned(2), packed)) HeaderRec, *HeaderPtr;
 
 /*
  --    
@@ -1833,12 +2167,12 @@ GetBTreeNodeInfo(int fd, off_t hfsPlusVolumeOffset, u_int32_t blockSize,
                goto free;
        }
 
-       *nodeSize = NXSwapBigShortToHost(bTreeHeaderPtr->header.nodeSize);
+       *nodeSize = OSSwapBigToHostInt16(bTreeHeaderPtr->header.nodeSize);
 
-       if (NXSwapBigLongToHost(bTreeHeaderPtr->header.leafRecords) == 0)
+       if (OSSwapBigToHostInt32(bTreeHeaderPtr->header.leafRecords) == 0)
                *firstLeafNode = 0;
        else
-               *firstLeafNode = NXSwapBigLongToHost(bTreeHeaderPtr->header.firstLeafNode);
+               *firstLeafNode = OSSwapBigToHostInt32(bTreeHeaderPtr->header.firstLeafNode);
 
 free:;
        free((char*) bTreeHeaderPtr);
@@ -1861,23 +2195,26 @@ GetCatalogOverflowExtents(int fd, off_t hfsPlusVolumeOffset,
                u_int32_t *catalogExtCount)
 {
        off_t offset;
+       u_int32_t numRecords;
        u_int32_t nodeSize;
        u_int32_t leafNode;
+       u_int32_t blockSize;
     BTNodeDescriptor * bTreeNodeDescriptorPtr;
        HFSPlusExtentDescriptor * extents;
        size_t listsize;
     char *     bufPtr = NULL;
-       int i;
+       uint32_t i;
        int result;
 
+       blockSize = OSSwapBigToHostInt32(volHdrPtr->blockSize);
        listsize = *catalogExtCount * sizeof(HFSPlusExtentDescriptor);
        extents = *catalogExtents;
-       offset = (off_t)volHdrPtr->extentsFile.extents[0].startBlock *
-                   (off_t)volHdrPtr->blockSize;
+       offset = (off_t)OSSwapBigToHostInt32(volHdrPtr->extentsFile.extents[0].startBlock) *
+                   (off_t)blockSize;
 
        /* Read the header node of the extents B-Tree */
 
-       result = GetBTreeNodeInfo(fd, hfsPlusVolumeOffset, volHdrPtr->blockSize,
+       result = GetBTreeNodeInfo(fd, hfsPlusVolumeOffset, blockSize,
                        kHFSPlusExtentDensity, volHdrPtr->extentsFile.extents,
                    &nodeSize, &leafNode);
        if (result != FSUR_IO_SUCCESS || leafNode == 0)
@@ -1899,7 +2236,7 @@ GetCatalogOverflowExtents(int fd, off_t hfsPlusVolumeOffset,
 
 again:
        result = ReadFile(fd, bufPtr, offset, nodeSize,
-                                       hfsPlusVolumeOffset, volHdrPtr->blockSize,
+                                       hfsPlusVolumeOffset, blockSize,
                                        kHFSPlusExtentDensity, volHdrPtr->extentsFile.extents);
        if ( result == FSUR_IO_FAIL ) {
 #if TRACE_HFS_UTIL
@@ -1913,7 +2250,8 @@ again:
                goto Return;
        }
 
-       for (i = 1; i <= bTreeNodeDescriptorPtr->numRecords; ++i) {
+       numRecords = OSSwapBigToHostInt16(bTreeNodeDescriptorPtr->numRecords);
+       for (i = 1; i <= numRecords; ++i) {
                u_int16_t * v;
                char * p;
                HFSPlusExtentKey * k;
@@ -1927,23 +2265,23 @@ again:
 
                /* Get a pointer to the record */
 
-               p = bufPtr + NXSwapBigShortToHost(*v); /* pointer arithmetic in bytes */
+               p = bufPtr + OSSwapBigToHostInt16(*v); /* pointer arithmetic in bytes */
                k = (HFSPlusExtentKey *)p;
 
-               if (NXSwapBigLongToHost(k->fileID) != kHFSCatalogFileID)
+               if (OSSwapBigToHostInt32(k->fileID) != kHFSCatalogFileID)
                        goto Return;
 
                /* grow list and copy additional extents */
                listsize += sizeof(HFSPlusExtentRecord);
                extents = (HFSPlusExtentDescriptor *) realloc(extents, listsize);
-               bcopy(p + k->keyLength + sizeof(u_int16_t),
+               bcopy(p + OSSwapBigToHostInt16(k->keyLength) + sizeof(u_int16_t),
                        &extents[*catalogExtCount], sizeof(HFSPlusExtentRecord));
 
                *catalogExtCount += kHFSPlusExtentDensity;
                *catalogExtents = extents;
        }
        
-       if ((leafNode = bTreeNodeDescriptorPtr->fLink) != 0) {
+       if ((leafNode = OSSwapBigToHostInt32(bTreeNodeDescriptorPtr->fLink)) != 0) {
        
                offset = (off_t) leafNode * (off_t) nodeSize;
                
@@ -1992,7 +2330,7 @@ static int        LogicalToPhysical(off_t offset, ssize_t length, u_int32_t blockSize,
        /* Find the extent containing logicalBlock */
        for (extent = 0; extent < extentCount; ++extent)
        {
-               blockCount = NXSwapBigLongToHost(extentList[extent].blockCount);
+               blockCount = OSSwapBigToHostInt32(extentList[extent].blockCount);
                
                if (blockCount == 0)
                        return FSUR_IO_FAIL;    /* Tried to map past physical end of file */
@@ -2012,7 +2350,7 @@ static int        LogicalToPhysical(off_t offset, ssize_t length, u_int32_t blockSize,
         */
        
        /* Compute the physical starting position */
-       temp = NXSwapBigLongToHost(extentList[extent].startBlock) + logicalBlock;       /* First physical block */
+       temp = OSSwapBigToHostInt32(extentList[extent].startBlock) + logicalBlock;      /* First physical block */
        temp *= blockSize;      /* Byte offset of first physical block */
        *physicalOffset = temp + offset;
 
@@ -2255,21 +2593,35 @@ static char gVSDBPath[] = "/var/db/volinfo.database";
 
 /* Database layout: */
 
-struct VSDBKey {
+typedef struct VSDBKey {
        char uuid[16];
-};
+} VSDBKey_t;
+
+typedef struct VSDBKeyUUID {
+       uuid_string_t uuid_string;
+} VSDBKeyUUID_t;
 
 struct VSDBRecord {
        char statusFlags[8];
 };
 
-struct VSDBEntry {
-       struct VSDBKey key;
+/* A VSDB Entry using a uuid_str (36 byte) instead of HFS UUID string (8 byte) */
+typedef struct VSDBEntryUUID {
+       VSDBKeyUUID_t key;
        char keySeparator;
        char space;
        struct VSDBRecord record;
        char terminator;
-};
+} VSDBEntryUUID_t;
+
+/* a VSDB entry using the HFS UUID */
+typedef struct VSDBEntryHFS {
+       VSDBKey_t key;
+       char keySeparator;
+       char space;
+       struct VSDBRecord record;
+       char terminator;
+} VSDBEntryHFS_t;
 
 #define DBKEYSEPARATOR ':'
 #define DBBLANKSPACE ' '
@@ -2292,17 +2644,17 @@ typedef struct VSDBState *VSDBStatePtr;
 static int LockDB(VSDBStatePtr dbstateptr, int lockmode);
 static int UnlockDB(VSDBStatePtr dbstateptr);
 
-static int FindVolumeRecordByUUID(VSDBStatePtr dbstateptr, VolumeUUID *volumeID, struct VSDBEntry *dbentry, unsigned long options);
-static int AddVolumeRecord(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry);
-static int UpdateVolumeRecord(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry);
-static int GetVSDBEntry(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry);
-static int CompareVSDBKeys(struct VSDBKey *key1, struct VSDBKey *key2);
+static int FindVolumeRecordByUUID(VSDBStatePtr dbstateptr, volUUID_t *volumeID, VSDBEntryUUID_t *dbentry, unsigned long options);
+static int AddVolumeRecord(VSDBStatePtr dbstateptr, VSDBEntryUUID_t *dbentry);
+static int UpdateVolumeRecord(VSDBStatePtr dbstateptr, VSDBEntryUUID_t *dbentry);
+static int GetVSDBEntry(VSDBStatePtr dbstateptr, VSDBEntryUUID_t *dbentry);
+static int CompareVSDBKeys(VSDBKeyUUID_t *key1, VSDBKeyUUID_t *key2);
+
 
 static void FormatULong(unsigned long u, char *s);
-static void FormatUUID(VolumeUUID *volumeID, char *UUIDField);
-static void FormatDBKey(VolumeUUID *volumeID, struct VSDBKey *dbkey);
+static void FormatDBKey(volUUID_t *volumeID, VSDBKeyUUID_t *dbkey);
 static void FormatDBRecord(unsigned long volumeStatusFlags, struct VSDBRecord *dbrecord);
-static void FormatDBEntry(VolumeUUID *volumeID, unsigned long volumeStatusFlags, struct VSDBEntry *dbentry);
+static void FormatDBEntry(volUUID_t *volumeID, unsigned long volumeStatusFlags, VSDBEntryUUID_t *dbentry);
 static unsigned long ConvertHexStringToULong(const char *hs, long maxdigits);
 
 
@@ -2313,7 +2665,7 @@ static unsigned long ConvertHexStringToULong(const char *hs, long maxdigits);
  *
  *****************************************************************************/
 
-void GenerateVolumeUUID(VolumeUUID *newVolumeID) {
+void GenerateHFSVolumeUUID(hfs_UUID_t *newuuid) {
        SHA_CTX context;
        char randomInputBuffer[26];
        unsigned char digest[20];
@@ -2323,9 +2675,12 @@ void GenerateVolumeUUID(VolumeUUID *newVolumeID) {
        int sysdata;
        char sysctlstring[128];
        size_t datalen;
-       struct loadavg sysloadavg;
+       double sysloadavg[3];
        struct vmtotal sysvmtotal;
-       
+       hfs_UUID_t hfsuuid;
+
+       memset (&hfsuuid, 0, sizeof(hfsuuid));
+
        do {
                /* Initialize the SHA-1 context for processing: */
                SHA1_Init(&context);
@@ -2372,10 +2727,8 @@ void GenerateVolumeUUID(VolumeUUID *newVolumeID) {
                SHA1_Update(&context, sysctlstring, datalen);
 
                /* The system's load average: */
-               mib[0] = CTL_VM;
-               mib[1] = VM_LOADAVG;
                datalen = sizeof(sysloadavg);
-               sysctl(mib, 2, &sysloadavg, &datalen, NULL, 0);
+               getloadavg(sysloadavg, 3);
                SHA1_Update(&context, &sysloadavg, datalen);
 
                /* The system's VM statistics: */
@@ -2393,48 +2746,15 @@ void GenerateVolumeUUID(VolumeUUID *newVolumeID) {
                /* Pad the accumulated input and extract the final digest hash: */
                SHA1_Final(digest, &context);
        
-               memcpy(newVolumeID, digest, sizeof(*newVolumeID));
-       } while ((newVolumeID->v.high == 0) || (newVolumeID->v.low == 0));
-}
-
+               memcpy(&hfsuuid, digest, sizeof(hfsuuid));
+       } while ((hfsuuid.high == 0) || (hfsuuid.low == 0));
 
+       /* now copy out the hfs uuid */
+       memcpy (newuuid, &hfsuuid, sizeof (hfsuuid));
 
-void ConvertVolumeUUIDStringToUUID(const char *UUIDString, VolumeUUID *volumeID) {
-       int i;
-       char c;
-       unsigned long nextdigit;
-       unsigned long high = 0;
-       unsigned long low = 0;
-       unsigned long carry;
-       
-       for (i = 0; (i < VOLUMEUUIDLENGTH) && ((c = UUIDString[i]) != (char)0) ; ++i) {
-               if ((c >= '0') && (c <= '9')) {
-                       nextdigit = c - '0';
-               } else if ((c >= 'A') && (c <= 'F')) {
-                       nextdigit = c - 'A' + 10;
-               } else if ((c >= 'a') && (c <= 'f')) {
-                       nextdigit = c - 'a' + 10;
-               } else {
-                       nextdigit = 0;
-               }
-               carry = ((low & 0xF0000000) >> 28) & 0x0000000F;
-               high = (high << 4) | carry;
-               low = (low << 4) | nextdigit;
-       }
-       
-       volumeID->v.high = high;
-       volumeID->v.low = low;
+       return;
 }
 
-
-
-void ConvertVolumeUUIDToString(VolumeUUID *volumeID, char *UUIDString) {
-       FormatUUID(volumeID, UUIDString);
-       *(UUIDString+16) = (char)0;             /* Append a terminating null character */
-}
-
-
-
 int OpenVolumeStatusDB(VolumeStatusDBHandle *DBHandlePtr) {
        VSDBStatePtr dbstateptr;
        
@@ -2455,20 +2775,117 @@ int OpenVolumeStatusDB(VolumeStatusDBHandle *DBHandlePtr) {
                dbstateptr->dbmode = O_RDONLY;
                dbstateptr->dbfile = open(gVSDBPath, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
                if (dbstateptr->dbfile == -1) {
-                       return errno;
+                       errno_t local_errno = errno;
+                       free(dbstateptr);
+                       return local_errno;
                }
        }
        
        dbstateptr->signature = DBHANDLESIGNATURE;
        *DBHandlePtr = (VolumeStatusDBHandle)dbstateptr;
+       
+       /* VSDBUtil converts the status DB, so we do it here, too */
+       ConvertVolumeStatusDB(*DBHandlePtr);
+
        return 0;
 }
 
+/* Convert the volume status DB from 64-bit (HFS-style) entries into full UUIDs */
+int ConvertVolumeStatusDB(VolumeStatusDBHandle DBHandle) {
+    VSDBStatePtr dbstateptr = (VSDBStatePtr)DBHandle;
+    struct VSDBEntryHFS entry64;
+    struct stat dbinfo;
+    int result;
+    u_int32_t iobuffersize;
+    void *iobuffer = NULL;
+    int i;
+
+    if (dbstateptr->signature != DBHANDLESIGNATURE) return EINVAL;
+
+    if ((result = LockDB(dbstateptr, LOCK_EX)) != 0) return result;
+
+
+       /* 
+        * This function locks the database file then tries to read in
+        * the size of a old-style HFS UUID database entry.  If what it finds
+        * is a well-formatted HFS entry, then it will convert the entire database.
+        * If it finds that the file isn't long enough or isn't actually the
+        * format for the 64-bit UUID struct on-disk, then it will bail out and not 
+        * touch it. Otherwise it will read the whole file and convert it
+        *
+        * In practice this means that if the file is empty or if we have already
+        * converted it then do nothing.
+        */
+    lseek(dbstateptr->dbfile, 0, SEEK_SET);
+    result = read(dbstateptr->dbfile, &entry64, sizeof(entry64));
+    if ((result != sizeof(entry64)) ||
+        (entry64.keySeparator != DBKEYSEPARATOR) ||
+        (entry64.space != DBBLANKSPACE) ||
+        (entry64.terminator != DBRECORDTERMINATOR)) {
+        result = 0;
+        goto ErrExit;
+    } else {
+               /* Read in a giant buffer */
+        if ((result = stat(gVSDBPath, &dbinfo)) != 0) goto ErrExit;
+        iobuffersize = dbinfo.st_size;
+        iobuffer = malloc(iobuffersize);
+        if (iobuffer == NULL) {
+            result = ENOMEM;
+            goto ErrExit;
+        };
+
+        lseek(dbstateptr->dbfile, 0, SEEK_SET);
+        result = read(dbstateptr->dbfile, iobuffer, iobuffersize);
+        if (result != iobuffersize) {
+            result = errno;
+            goto ErrExit;
+        };
+        if ((result = ftruncate(dbstateptr->dbfile, 0)) != 0) {
+            goto ErrExit;
+        };
+        for (i = 0; i < iobuffersize / sizeof(entry64); i++) {
+            volUUID_t volumeID;
+            u_int32_t VolumeStatus;
+            struct VSDBEntryUUID dbentry;
+
+                       /* 
+                        * now iterate through the contents of the 64-bit entries in RAM
+                        * and write them on top of the existing database file
+                        */
+            entry64 = *(((struct VSDBEntryHFS *)iobuffer) + i);
+            if ((entry64.keySeparator != DBKEYSEPARATOR) ||
+                (entry64.space != DBBLANKSPACE) ||
+                (entry64.terminator != DBRECORDTERMINATOR)) {
+                continue;
+            }
+
+            ConvertHFSUUIDToUUID(entry64.key.uuid, &volumeID);
+            VolumeStatus = ConvertHexStringToULong(entry64.record.statusFlags, sizeof(entry64.record.statusFlags));
+
+            FormatDBEntry(&volumeID, VolumeStatus, &dbentry);
+            if ((result = AddVolumeRecord(dbstateptr, &dbentry)) != sizeof(dbentry)) {
+                warnx("couldn't convert volume status database: %s", strerror(result));
+                goto ErrExit;
+            };
+        };
+
+        fsync(dbstateptr->dbfile);
 
+        result = 0;
+    };
+
+ErrExit:
+    if (iobuffer) free(iobuffer);
+    UnlockDB(dbstateptr);
+    return result;
+}
 
-int GetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID, unsigned long *VolumeStatus) {
+
+
+
+int GetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, volUUID_t *volumeID, unsigned long *VolumeStatus) {
        VSDBStatePtr dbstateptr = (VSDBStatePtr)DBHandle;
-       struct VSDBEntry dbentry;
+       struct VSDBEntryUUID dbentry;
        int result;
 
        if (dbstateptr->signature != DBHANDLESIGNATURE) return EINVAL;
@@ -2489,9 +2906,9 @@ ErrExit:
 
 
 
-int SetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID, unsigned long VolumeStatus) {
+int SetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, volUUID_t *volumeID, unsigned long VolumeStatus) {
        VSDBStatePtr dbstateptr = (VSDBStatePtr)DBHandle;
-       struct VSDBEntry dbentry;
+       struct VSDBEntryUUID dbentry;
        int result;
        
        if (dbstateptr->signature != DBHANDLESIGNATURE) return EINVAL;
@@ -2525,7 +2942,7 @@ ErrExit:
 
 
 
-int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID) {
+int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, volUUID_t *volumeID) {
        VSDBStatePtr dbstateptr = (VSDBStatePtr)DBHandle;
        struct stat dbinfo;
        int result;
@@ -2550,8 +2967,8 @@ int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeI
                fprintf(stderr, "DeleteLocalVolumeUUID: Found record with matching volume UUID...\n");
 #endif
                if ((result = stat(gVSDBPath, &dbinfo)) != 0) goto ErrExit;
-               if ((dbinfo.st_size - dbstateptr->recordPosition - sizeof(struct VSDBEntry)) <= MAXIOMALLOC) {
-                       iobuffersize = dbinfo.st_size - dbstateptr->recordPosition - sizeof(struct VSDBEntry);
+               if ((dbinfo.st_size - dbstateptr->recordPosition - sizeof(struct VSDBEntryUUID)) <= MAXIOMALLOC) {
+                       iobuffersize = dbinfo.st_size - dbstateptr->recordPosition - sizeof(struct VSDBEntryUUID);
                } else {
                        iobuffersize = MAXIOMALLOC;
                }
@@ -2567,7 +2984,7 @@ int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeI
                                goto ErrExit;
                        }
                        
-                       dataoffset = dbstateptr->recordPosition + sizeof(struct VSDBEntry);
+                       dataoffset = dbstateptr->recordPosition + sizeof(struct VSDBEntryUUID);
                        do {
                                iotransfersize = dbinfo.st_size - dataoffset;
                                if (iotransfersize > 0) {
@@ -2584,9 +3001,9 @@ int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeI
                                        }
        
        #if DEBUG_TRACE
-                                       fprintf(stderr, "DeleteLocalVolumeUUID: writing 0x%08lx bytes starting at 0x%08lx ...\n", iotransfersize, (unsigned long)(dataoffset - (off_t)sizeof(struct VSDBEntry)));
+                                       fprintf(stderr, "DeleteLocalVolumeUUID: writing 0x%08lx bytes starting at 0x%08lx ...\n", iotransfersize, (unsigned long)(dataoffset - (off_t)sizeof(struct VSDBEntryUUID)));
        #endif
-                                       lseek(dbstateptr->dbfile, dataoffset - (off_t)sizeof(struct VSDBEntry), SEEK_SET);
+                                       lseek(dbstateptr->dbfile, dataoffset - (off_t)sizeof(struct VSDBEntryUUID), SEEK_SET);
                                        bytestransferred = write(dbstateptr->dbfile, iobuffer, iotransfersize);
                                        if (bytestransferred != iotransfersize) {
                                                result = errno;
@@ -2598,9 +3015,9 @@ int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeI
                        } while (iotransfersize > 0);
                }
 #if DEBUG_TRACE
-               fprintf(stderr, "DeleteLocalVolumeUUID: truncating database file to 0x%08lx bytes.\n", (unsigned long)(dbinfo.st_size - (off_t)(sizeof(struct VSDBEntry))));
+               fprintf(stderr, "DeleteLocalVolumeUUID: truncating database file to 0x%08lx bytes.\n", (unsigned long)(dbinfo.st_size - (off_t)(sizeof(struct VSDBEntryUUID))));
 #endif
-               if ((result = ftruncate(dbstateptr->dbfile, dbinfo.st_size - (off_t)(sizeof(struct VSDBEntry)))) != 0) {
+               if ((result = ftruncate(dbstateptr->dbfile, dbinfo.st_size - (off_t)(sizeof(struct VSDBEntryUUID)))) != 0) {
                        goto ErrExit;
                }
                
@@ -2660,9 +3077,10 @@ static int UnlockDB(VSDBStatePtr dbstateptr) {
 
 
 
-static int FindVolumeRecordByUUID(VSDBStatePtr dbstateptr, VolumeUUID *volumeID, struct VSDBEntry *targetEntry, unsigned long options) {
-       struct VSDBKey searchkey;
-       struct VSDBEntry dbentry;
+static int FindVolumeRecordByUUID(VSDBStatePtr dbstateptr, volUUID_t *volumeID, 
+               VSDBEntryUUID_t *targetEntry, unsigned long options) {
+       VSDBKeyUUID_t searchkey;
+       struct VSDBEntryUUID dbentry;
        int result;
        
        FormatDBKey(volumeID, &searchkey);
@@ -2686,53 +3104,22 @@ static int FindVolumeRecordByUUID(VSDBStatePtr dbstateptr, VolumeUUID *volumeID,
 
 
 
-static int AddVolumeRecord(VSDBStatePtr dbstateptr , struct VSDBEntry *dbentry) {
-#if DEBUG_TRACE
-       VolumeUUIDString id;
-#endif
-
-#if DEBUG_TRACE
-       strncpy(id, dbentry->key.uuid, sizeof(dbentry->key.uuid));
-       id[sizeof(dbentry->key.uuid)] = (char)0;
-       fprintf(stderr, "AddVolumeRecord: Adding record for UUID #%s...\n", id);
-#endif
+static int AddVolumeRecord(VSDBStatePtr dbstateptr, VSDBEntryUUID_t *dbentry) {
        lseek(dbstateptr->dbfile, 0, SEEK_END);
-       return write(dbstateptr->dbfile, dbentry, sizeof(struct VSDBEntry));
+       return write(dbstateptr->dbfile, dbentry, sizeof(struct VSDBEntryUUID));
 }
 
 
-
-
-static int UpdateVolumeRecord(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry) {
-#if DEBUG_TRACE
-       VolumeUUIDString id;
-#endif
-
-#if DEBUG_TRACE
-       strncpy(id, dbentry->key.uuid, sizeof(dbentry->key.uuid));
-       id[sizeof(dbentry->key.uuid)] = (char)0;
-       fprintf(stderr, "UpdateVolumeRecord: Updating record for UUID #%s at offset 0x%08lx in database...\n", id, (unsigned long)dbstateptr->recordPosition);
-#endif
+static int UpdateVolumeRecord(VSDBStatePtr dbstateptr, VSDBEntryUUID_t *dbentry) {
        lseek(dbstateptr->dbfile, dbstateptr->recordPosition, SEEK_SET);
-#if DEBUG_TRACE
-       fprintf(stderr, "UpdateVolumeRecord: Writing %d. bytes...\n", sizeof(*dbentry));
-#endif
        return write(dbstateptr->dbfile, dbentry, sizeof(*dbentry));
 }
 
-
-
-static int GetVSDBEntry(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry) {
-       struct VSDBEntry entry;
+static int GetVSDBEntry(VSDBStatePtr dbstateptr, VSDBEntryUUID_t *dbentry) {
+       struct VSDBEntryUUID entry;
        int result;
-#if DEBUG_TRACE
-       VolumeUUIDString id;
-#endif
        
        dbstateptr->recordPosition = lseek(dbstateptr->dbfile, 0, SEEK_CUR);
-#if 0 // DEBUG_TRACE
-       fprintf(stderr, "GetVSDBEntry: starting reading record at offset 0x%08lx...\n", (unsigned long)dbstateptr->recordPosition);
-#endif
        result = read(dbstateptr->dbfile, &entry, sizeof(entry));
        if ((result != sizeof(entry)) ||
                (entry.keySeparator != DBKEYSEPARATOR) ||
@@ -2741,30 +3128,15 @@ static int GetVSDBEntry(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry) {
                return -1;
        }
        
-#if DEBUG_TRACE
-       strncpy(id, entry.key.uuid, sizeof(entry.key.uuid));
-       id[sizeof(entry.key.uuid)] = (char)0;
-       fprintf(stderr, "GetVSDBEntry: returning entry for UUID #%s...\n", id);
-#endif
        memcpy(dbentry, &entry, sizeof(*dbentry));
        return 0;
 }
 
 
 
-static int CompareVSDBKeys(struct VSDBKey *key1, struct VSDBKey *key2) {
-#if 0 // DEBUG_TRACE
-       VolumeUUIDString id;
-
-       strncpy(id, key1->uuid, sizeof(key1->uuid));
-       id[sizeof(key1->uuid)] = (char)0;
-       fprintf(stderr, "CompareVSDBKeys: comparing #%s to ", id);
-       strncpy(id, key2->uuid, sizeof(key2->uuid));
-       id[sizeof(key2->uuid)] = (char)0;
-       fprintf(stderr, "%s (%d.)...\n", id, sizeof(key1->uuid));
-#endif
+static int CompareVSDBKeys(VSDBKeyUUID_t *key1, VSDBKeyUUID_t *key2) {
        
-       return memcmp(key1->uuid, key2->uuid, sizeof(key1->uuid));
+       return strcmp(key1->uuid_string, key2->uuid_string);
 }
 
 
@@ -2792,17 +3164,11 @@ static void FormatULong(unsigned long u, char *s) {
 }
 
 
+static void FormatDBKey(volUUID_t *volumeID, VSDBKeyUUID_t *dbkey) {
+       uuid_string_t uuid_str;
 
-static void FormatUUID(VolumeUUID *volumeID, char *UUIDField) {
-       FormatULong(volumeID->v.high, UUIDField);
-       FormatULong(volumeID->v.low, UUIDField+8);
-
-}
-
-
-
-static void FormatDBKey(VolumeUUID *volumeID, struct VSDBKey *dbkey) {
-       FormatUUID(volumeID, dbkey->uuid);
+       uuid_unparse (volumeID->uuid, uuid_str);
+       memcpy (dbkey->uuid_string, uuid_str, sizeof (uuid_str));
 }
 
 
@@ -2812,16 +3178,12 @@ static void FormatDBRecord(unsigned long volumeStatusFlags, struct VSDBRecord *d
 }
 
 
-
-static void FormatDBEntry(VolumeUUID *volumeID, unsigned long volumeStatusFlags, struct VSDBEntry *dbentry) {
+static void FormatDBEntry(volUUID_t *volumeID, unsigned long volumeStatusFlags, struct VSDBEntryUUID *dbentry) {
        FormatDBKey(volumeID, &dbentry->key);
        dbentry->keySeparator = DBKEYSEPARATOR;
        dbentry->space = DBBLANKSPACE;
        FormatDBRecord(volumeStatusFlags, &dbentry->record);
-#if 0 // DEBUG_TRACE
-       dbentry->terminator = (char)0;
-       fprintf(stderr, "FormatDBEntry: '%s' (%d.)\n", dbentry, sizeof(*dbentry));
-#endif
+
        dbentry->terminator = DBRECORDTERMINATOR;
 }