hfs-165.tar.gz
[apple/hfs.git] / hfs_util / hfsutil_main.c
index adb83c6ad27b173dd578be329ee6c29f08d6833e..15bb2d1ba87a56258749f90bd7953b210df4031e 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
+ * 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.
 #include <sys/vmmeter.h>
 #include <sys/mount.h>
 #include <sys/wait.h>
-
-#include <bsd/dev/disk.h>
+#include <sys/param.h>
+#include <sys/ucred.h>
+#include <sys/disk.h>
 #include <sys/loadable_fs.h>
+#include <sys/attr.h>
 #include <hfs/hfs_format.h>
+#include <hfs/hfs_mount.h>
 
+#include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <pwd.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <syslog.h>
 
-#include <CoreFoundation/CFString.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>
 
-#define READ_DEFAULT_ENCODING 1
+#include <libkern/OSByteOrder.h>
 
-#ifndef FSUR_MOUNT_HIDDEN
-#define FSUR_MOUNT_HIDDEN (-9)
-#endif
+#include <CoreFoundation/CFString.h>
 
-#ifndef FSUC_GETKEY
-#define FSUC_GETKEY 'k'
-#endif
+#include <System/uuid/uuid.h>
+#include <System/uuid/namespace.h>
+
+#define READ_DEFAULT_ENCODING 1
 
 #ifndef FSUC_ADOPT
 #define FSUC_ADOPT 'a'
 #define FSUC_DISOWN 'd'
 #endif
 
-#ifndef FSUC_NEWUUID
-#define FSUC_NEWUUID 'n'
+#ifndef FSUC_GETUUID
+#define FSUC_GETUUID 'k'
 #endif
 
+#ifndef FSUC_SETUUID
+#define FSUC_SETUUID 's'
+#endif
 
+#ifndef FSUC_MKJNL
+#define FSUC_MKJNL   'J'
+#endif
+
+#ifndef FSUC_UNJNL
+#define FSUC_UNJNL   'U'
+#endif
+
+#ifndef FSUC_UNJNL_RAW
+#define FSUC_UNJNL_RAW 'N'
+#endif
+
+#ifndef FSUC_JNLINFO
+#define FSUC_JNLINFO 'I'
+#endif
 
 /* **************************************** L O C A L S ******************************************* */
 
 char gHFS_FS_NAME[] = "hfs";
 char gHFS_FS_NAME_NAME[] = "HFS";
 
-char gFS_UUID_SUFFIX[] = ".uuid";
 char gNewlineString[] = "\n";
 
 char gMountCommand[] = "/sbin/mount";
@@ -103,15 +131,29 @@ char gUnmountCommand[] = "/sbin/umount";
 char gReadOnlyOption[] = "-r";
 char gReadWriteOption[] = "-w";
 
+char gSuidOption[] = "suid";
+char gNoSuidOption[] = "nosuid";
+
+char gDevOption[] = "dev";
+char gNoDevOption[] = "nodev";
+
 char gUsePermissionsOption[] = "perm";
 char gIgnorePermissionsOption[] = "noperm";
 
 boolean_t gIsEjectable = 0;
 
+int gJournalSize = 0;
+
 #define AUTO_ADOPT_FIXED 1
 #define AUTO_ENTER_FIXED 0
 
 
+struct FinderAttrBuf {
+       unsigned long info_length;
+       unsigned long finderinfo[8];
+};
+
+
 #define VOLUMEUUIDVALUESIZE 2
 typedef union VolumeUUID {
        unsigned long value[VOLUMEUUIDVALUESIZE];
@@ -133,7 +175,6 @@ typedef void *VolumeStatusDBHandle;
 void GenerateVolumeUUID(VolumeUUID *newVolumeID);
 void ConvertVolumeUUIDStringToUUID(const char *UUIDString, VolumeUUID *volumeID);
 void ConvertVolumeUUIDToString(VolumeUUID *volumeID, char *UUIDString);
-
 int OpenVolumeStatusDB(VolumeStatusDBHandle *DBHandlePtr);
 int GetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID, unsigned long *VolumeStatus);
 int SetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID, unsigned long VolumeStatus);
@@ -141,30 +182,52 @@ int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeI
 int CloseVolumeStatusDB(VolumeStatusDBHandle DBHandle);
 
 /* ************************************ P R O T O T Y P E S *************************************** */
-
 static void    DoDisplayUsage( const char * argv[] );
-static void    DoFileSystemFile( char * theFileNameSuffixPtr, char * theContentsPtr );
-static int     DoMount( char * theDeviceNamePtr, const char * theMountPointPtr, boolean_t isLocked );
+static int     DoMount( char * theDeviceNamePtr, const char * theMountPointPtr, boolean_t isLocked, boolean_t isSetuid, boolean_t isDev );
 static int     DoProbe( char * theDeviceNamePtr );
 static int     DoUnmount( const char * theMountPointPtr );
 static int     DoGetUUIDKey( const char * theDeviceNamePtr );
 static int     DoChangeUUIDKey( const char * theDeviceNamePtr );
 static int     DoAdopt( const char * theDeviceNamePtr );
 static int     DoDisown( const char * theDeviceNamePtr );
-static int     ParseArgs( int argc, const char * argv[], const char ** actionPtr, const char ** mountPointPtr, boolean_t * isEjectablePtr, boolean_t * isLockedPtr );
 
+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 );
+
+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);
 static int     GetEmbeddedHFSPlusVol(HFSMasterDirectoryBlock * hfsMasterDirectoryBlockPtr, off_t * startOffsetPtr);
-static int     GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * name_o);
-static int     GetBTreeNodeInfo(int fd, off_t btreeOffset, u_int32_t *nodeSize, u_int32_t *firstLeafNode);
-static off_t   CalcLeafNodeOffset(off_t fileOffset, u_int32_t blockSize, u_int32_t extentCount,
-                                                                        HFSPlusExtentDescriptor *extentList);
+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);
 static int     GetCatalogOverflowExtents(int fd, off_t hfsPlusVolumeOffset, HFSPlusVolumeHeader *volHdrPtr,
                                                                         HFSPlusExtentDescriptor **catalogExtents, u_int32_t *catalogExtCount);
+static int     LogicalToPhysical(off_t logicalOffset, ssize_t length, u_int32_t blockSize,
+                                                       u_int32_t extentCount, const HFSPlusExtentDescriptor *extentList,
+                                                       off_t *physicalOffset, ssize_t *availableBytes);
+static int     ReadFile(int fd, void *buffer, off_t offset, ssize_t length,
+                                       off_t volOffset, u_int32_t blockSize,
+                                       u_int32_t extentCount, const HFSPlusExtentDescriptor *extentList);
 static ssize_t readAt( int fd, void * buf, off_t offset, ssize_t length );
 static ssize_t writeAt( int fd, void * buf, off_t offset, ssize_t length );
 
+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
@@ -197,6 +260,119 @@ static unsigned int __CFStringGetDefaultEncodingForHFSUtil() {
 }
 #endif
 
+
+#define MXENCDNAMELEN  16      /* Maximun length of encoding name string */
+
+struct hfs_mnt_encoding {
+       char                            encoding_name[MXENCDNAMELEN];   /* encoding type name */
+       CFStringEncoding        encoding_id;                                    /* encoding type number */
+};
+
+static struct hfs_mnt_encoding hfs_mnt_encodinglist[] = {
+       { "Arabic",               4 },
+       { "Armenian",        24 },
+       { "Bengali",         13 },
+       { "Burmese",         19 },
+       { "Celtic",          39 },
+       { "CentralEurRoman", 29 },
+       { "ChineseSimp",     25 },
+       { "ChineseTrad",      2 },
+       { "Croatian",        36 },
+       { "Cyrillic",         7 },
+       { "Devanagari",       9 },
+       { "Ethiopic",        28 },
+       { "Farsi",          140 },
+       { "Gaelic",          40 },
+       { "Georgian",        23 },
+       { "Greek",                6 },
+       { "Gujarati",        11 },
+       { "Gurmukhi",        10 },
+       { "Hebrew",               5 },
+       { "Icelandic",       37 },
+       { "Japanese",         1 },
+       { "Kannada",         16 },
+       { "Khmer",           20 },
+       { "Korean",               3 },
+       { "Laotian",         22 },
+       { "Malayalam",       17 },
+       { "Mongolian",       27 },
+       { "Oriya",           12 },
+       { "Roman",                0 },  /* default */
+       { "Romanian",        38 },
+       { "Sinhalese",       18 },
+       { "Tamil",           14 },
+       { "Telugu",          15 },
+       { "Thai",                21 },
+       { "Tibetan",         26 },
+       { "Turkish",         35 },
+       { "Ukrainian",      152 },
+       { "Vietnamese",      30 },
+};
+
+#define KEXT_LOAD_COMMAND      "/sbin/kextload"
+#define ENCODING_MODULE_PATH   "/System/Library/Filesystems/hfs.fs/Encodings/"
+
+static int load_encoding(CFStringEncoding encoding)
+{
+       int i;
+       int numEncodings;
+       int pid;
+       char *encodingName;
+       struct stat sb;
+       union wait status;
+       char kmodfile[MAXPATHLEN];
+
+       /* Find the encoding that matches the one passed in */
+       numEncodings = sizeof(hfs_mnt_encodinglist) / sizeof(struct hfs_mnt_encoding);
+       encodingName = NULL;
+       for (i=0; i<numEncodings; ++i)
+       {
+               if (hfs_mnt_encodinglist[i].encoding_id == encoding)
+               {
+                       encodingName = hfs_mnt_encodinglist[i].encoding_name;
+                       break;
+               }
+       }
+       
+       if (encodingName == NULL)
+       {
+               /* Couldn't figure out which encoding KEXT to load */
+               syslog(LOG_ERR, "Couldn't find name for encoding #%d", encoding);
+               return FSUR_LOADERR;
+       }
+       
+       sprintf(kmodfile, "%sHFS_Mac%s.kext", ENCODING_MODULE_PATH, encodingName);
+       if (stat(kmodfile, &sb) == -1)
+       {
+               /* We recognized the encoding, but couldn't find the KEXT */
+               syslog(LOG_ERR, "Couldn't stat HFS_Mac%s.kext: %s", encodingName, strerror(errno));
+               return FSUR_LOADERR;
+       }
+       
+       pid = fork();
+       if (pid == 0)
+       {
+               (void) execl(KEXT_LOAD_COMMAND, KEXT_LOAD_COMMAND, "-q", kmodfile, NULL);
+
+               exit(1);        /* We can only get here if the exec failed */
+       }
+       else if (pid != -1)
+       {
+               if ((waitpid(pid, (int *)&status, 0) == pid) && WIFEXITED(status))
+               {
+                       if (WEXITSTATUS(status) != 0)
+                       {
+                               /* kextload returned an error.  Too bad its output doesn't get logged. */
+                               syslog(LOG_ERR, "Couldn't load HFS_Mac%s.kext", encodingName);
+                               return FSUR_LOADERR;
+                       }
+               }
+       }
+       
+       return FSUR_IO_SUCCESS;
+}
+
+
 /* ******************************************** main ************************************************
 Purpose -
 This our main entry point to this utility.  We get called by the WorkSpace.  See ParseArgs
@@ -216,9 +392,13 @@ int main (int argc, const char *argv[])
     const char                 *       mountPointPtr = NULL;
     int                                                result = FSUR_IO_SUCCESS;
     boolean_t                          isLocked = 0;   /* reasonable assumptions */
+    boolean_t                          isSetuid = 0;   /* reasonable assumptions */
+    boolean_t                          isDev = 0;      /* reasonable assumptions */
+
+       openlog("hfs.util", LOG_PID, LOG_DAEMON);
 
     /* Verify our arguments */
-    if ( (result = ParseArgs( argc, argv, & actionPtr, & mountPointPtr, & gIsEjectable, & isLocked )) != 0 ) {
+    if ( (result = ParseArgs( argc, argv, & actionPtr, & mountPointPtr, & gIsEjectable, & isLocked, &isSetuid, &isDev )) != 0 ) {
         goto AllDone;
     }
 
@@ -232,14 +412,6 @@ int main (int argc, const char *argv[])
 
     /* call the appropriate routine to handle the given action argument after becoming root */
 
-    result = seteuid( 0 );
-    if ( result ) {
-        result = FSUR_INVAL;
-        goto AllDone;
-    }
-
-    result = setegid( 0 );     // PPD - is this necessary?
-
     switch( * actionPtr ) {
         case FSUC_PROBE:
             result = DoProbe(rawDeviceName);
@@ -247,21 +419,19 @@ int main (int argc, const char *argv[])
 
         case FSUC_MOUNT:
         case FSUC_MOUNT_FORCE:
-            result = DoMount(blockDeviceName, mountPointPtr, isLocked);
+            result = DoMount(blockDeviceName, mountPointPtr, isLocked, isSetuid, isDev);
             break;
 
         case FSUC_UNMOUNT:
             result = DoUnmount( mountPointPtr );
             break;
-
-               case FSUC_GETKEY:
+               case FSUC_GETUUID:
                        result = DoGetUUIDKey( blockDeviceName );
                        break;
                
-               case FSUC_NEWUUID:
+               case FSUC_SETUUID:
                        result = DoChangeUUIDKey( blockDeviceName );
                        break;
-                       
                case FSUC_ADOPT:
                        result = DoAdopt( blockDeviceName );
                        break;
@@ -269,7 +439,27 @@ int main (int argc, const char *argv[])
                case FSUC_DISOWN:
                        result = DoDisown( blockDeviceName );
                        break;
+
+               case FSUC_MKJNL:
+                       if (gJournalSize) {
+                               result = DoMakeJournaled( argv[3], gJournalSize );
+                       } else {
+                               result = DoMakeJournaled( argv[2], gJournalSize );
+                       }
+                       break;
+
+               case FSUC_UNJNL:
+                       result = DoUnJournal( argv[2] );
+                       break;
                        
+               case FSUC_UNJNL_RAW:
+                       result = RawDisableJournaling( argv[2] );
+                       break;
+                       
+               case FSUC_JNLINFO:
+                       result = DoGetJournalInfo( argv[2] );
+                       break;
+
         default:
             /* should never get here since ParseArgs should handle this situation */
             DoDisplayUsage( argv );
@@ -297,10 +487,12 @@ 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)
+DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, boolean_t isSetuid, boolean_t isDev)
 {
        int pid;
-       char *isLockedstr;
+        char *isLockedstr;
+        char *isSetuidstr;
+        char *isDevstr;
        char *permissionsOption;
        int result = FSUR_IO_FAIL;
        union wait status;
@@ -333,7 +525,7 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked)
                        fprintf(stderr, "hfs.util: DoMount: Not adopting ejectable %s.\n", deviceNamePtr);
 #endif
                        targetVolumeStatus = 0;
-               };
+               }
 #endif
        } else {
                /* We've got a real volume UUID! */
@@ -366,19 +558,21 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked)
                                        fprintf(stderr, "hfs.util: DoMount: Not adopting ejectable %s.\n", deviceNamePtr);
 #endif
                                        targetVolumeStatus = 0;
-                               };
+                               }
 #else
                                targetVolumeStatus = 0;
 #endif
-                       };
+                       }
                        (void)CloseVolumeStatusDB(vsdbhandle);
                        vsdbhandle = NULL;
-               };
-       };
+               }
+       }
        
        pid = fork();
        if (pid == 0) {
-               isLockedstr = isLocked ? gReadOnlyOption : gReadWriteOption;
+                isLockedstr = isLocked ? gReadOnlyOption : gReadWriteOption;
+                isSetuidstr = isSetuid ? gSuidOption : gNoSuidOption;
+                isDevstr = isDev ? gDevOption : gNoDevOption;
                
                permissionsOption =
                        (targetVolumeStatus & VOLUME_USEPERMISSIONS) ? gUsePermissionsOption : gIgnorePermissionsOption;
@@ -394,10 +588,11 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked)
                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);
 #endif
-               (void) execl(gMountCommand, gMountCommand, isLockedstr,
-                           "-o", encodeopt, "-o", permissionsOption,
-                           "-o", "-u=unknown,-g=unknown,-m=0777",
-                           "-t", gHFS_FS_NAME, deviceNamePtr, mountPointPtr, NULL);
+                (void) execl(gMountCommand, gMountCommand, isLockedstr, "-o", isSetuidstr, "-o", isDevstr,
+                                        "-o", encodeopt, "-o", permissionsOption,
+                                        "-o", "-u=unknown,-g=unknown,-m=0777",
+                                        "-t", gHFS_FS_NAME, deviceNamePtr, mountPointPtr, NULL);
+                
 
                /* IF WE ARE HERE, WE WERE UNSUCCESFULL */
                return (FSUR_IO_FAIL);
@@ -465,7 +660,7 @@ Purpose -
 Input -
     theDeviceNamePtr - pointer to the device name (full path, like /dev/disk0s2).
 Output -
-    returns FSUR_MOUNT_HIDDEN (previously FSUR_RECOGNIZED) if we can handle the media else one of the FSUR_xyz error codes.
+    returns FSUR_RECOGNIZED if we can handle the media else one of the FSUR_xyz error codes.
 *************************************************************************************************** */
 static int
 DoProbe(char *deviceNamePtr)
@@ -500,17 +695,30 @@ DoProbe(char *deviceNamePtr)
                goto Return;
 
        /* get classic HFS volume name (from MDB) */
-       if (mdbPtr->drSigWord == kHFSSigWord &&
-           mdbPtr->drEmbedSigWord != kHFSPlusSigWord) {
+       if (OSSwapBigToHostInt16(mdbPtr->drSigWord) == kHFSSigWord &&
+           OSSwapBigToHostInt16(mdbPtr->drEmbedSigWord) != kHFSPlusSigWord) {
                Boolean cfOK;
                CFStringRef cfstr;
                CFStringEncoding encoding;
 
-               encoding = CFStringGetSystemEncoding();
+               /* Some poorly mastered HFS CDs have an empty MDB name field! */
+               if (mdbPtr->drVN[0] == '\0') {
+                       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(OSSwapBigToHostInt32(mdbPtr->drFndrInfo[4]));
+               if (encoding == kCFStringEncodingInvalidId) {
+                       /* Next try the encoding bias in the kernel. */
+                       encoding = GetEncodingBias();
+                       if (encoding == 0 || encoding == kCFStringEncodingInvalidId)
+                               encoding = __CFStringGetDefaultEncodingForHFSUtil();
+               }
+
                cfstr = CFStringCreateWithPascalString(kCFAllocatorDefault,
                            mdbPtr->drVN, encoding);
-               cfOK = CFStringGetCString(cfstr, volnameUTF8, NAME_MAX,
-                           kCFStringEncodingUTF8);
+               cfOK = _CFStringGetFileSystemRepresentation(cfstr, volnameUTF8, NAME_MAX);
                CFRelease(cfstr);
 
                if (!cfOK && encoding != kCFStringEncodingMacRoman) {
@@ -518,23 +726,35 @@ DoProbe(char *deviceNamePtr)
                        /* default to MacRoman on conversion errors */
                        cfstr = CFStringCreateWithPascalString(kCFAllocatorDefault,
                                    mdbPtr->drVN, kCFStringEncodingMacRoman);
-                       CFStringGetCString(cfstr, volnameUTF8, NAME_MAX,
-                           kCFStringEncodingUTF8);
+                       _CFStringGetFileSystemRepresentation(cfstr, volnameUTF8, NAME_MAX);
                        CFRelease(cfstr);
+                       encoding = kCFStringEncodingMacRoman;
                }
  
+               /* Preload the encoding converter so mount_hfs can run as an ordinary user. */
+               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 ((volHdrPtr->signature == kHFSPlusSigWord)  ||
-                  (mdbPtr->drSigWord == kHFSSigWord &&
-                   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 (volHdrPtr->signature == kHFSPlusSigWord) {
-                       startOffset = 0;
-               } else {/* embedded volume, first find offset */
+               if (OSSwapBigToHostInt16(volHdrPtr->signature) == kHFSSigWord) {
+                       /* embedded volume, first find offset */
                        result = GetEmbeddedHFSPlusVol(mdbPtr, &startOffset);
                        if ( result != FSUR_IO_SUCCESS )
                                goto Return;
+               } else {
+                       startOffset = 0;
                }
 
                result = GetNameFromHFSPlusVolumeStartingAt(fd, startOffset,
@@ -544,43 +764,17 @@ DoProbe(char *deviceNamePtr)
        }
 
        if (FSUR_IO_SUCCESS == result) {
-               CFStringRef slash;
-               CFStringRef colon;
-               CFMutableStringRef volumeName;
-               CFIndex volumeNameLength;
-               CFRange foundSubString;
-               
-               slash = CFStringCreateWithCString(kCFAllocatorDefault, "/", kCFStringEncodingUTF8);
-               if (slash == NULL) {
-                       result = FSUR_IO_FAIL;
-                       goto Return;
-               };
-               
-               colon = CFStringCreateWithCString(kCFAllocatorDefault, ":", kCFStringEncodingUTF8);
-               if (colon == NULL) {
-                       result = FSUR_IO_FAIL;
-                       goto Return;
-               };
+               unsigned char *s;
                
-               volumeName = CFStringCreateMutableCopy(
-                                                       kCFAllocatorDefault,
-                                                       0,                                                      /* maxLength */
-                                                       CFStringCreateWithCString(kCFAllocatorDefault, volnameUTF8, kCFStringEncodingUTF8));
-               if (volumeName == NULL) {
-                       result = FSUR_IO_FAIL;
-                       goto Return;
-               };
-               volumeNameLength = CFStringGetLength(volumeName);
-
-               while (CFStringFindWithOptions(volumeName, slash, CFRangeMake(0, volumeNameLength-1), 0, &foundSubString)) {
-                       CFStringReplace(volumeName, foundSubString, colon);
-               };
-
-               CFStringGetCString(volumeName, volnameUTF8, NAME_MAX, kCFStringEncodingUTF8);
+               /* Change slashes to colons in the volume name */
+               for (s=volnameUTF8; *s; ++s) {
+                       if (*s == '/')
+                               *s = ':';
+               }
 
-               DoFileSystemFile( FS_NAME_SUFFIX, gHFS_FS_NAME_NAME );
-               DoFileSystemFile( FS_LABEL_SUFFIX, volnameUTF8 );
-               result = FSUR_MOUNT_HIDDEN;
+               /* Print the volume name to standard output */
+               write(1, volnameUTF8, strlen((char *)volnameUTF8));
+               result = FSUR_RECOGNIZED;
        }
 
 Return:
@@ -595,11 +789,34 @@ Return:
 
 } /* 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.
+    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 -
@@ -609,15 +826,19 @@ static int
 DoGetUUIDKey( const char * theDeviceNamePtr ) {
        int result;
        VolumeUUID targetVolumeUUID;
-       VolumeUUIDString UUIDString;
-       char uuidLine[VOLUMEUUIDLENGTH+2];
-       
+       uuid_t uuid;
+       char uuidLine[40];
+
+       unsigned char rawUUID[8];
+
        if ((result = GetVolumeUUID(theDeviceNamePtr, &targetVolumeUUID, FALSE)) != FSUR_IO_SUCCESS) goto Err_Exit;
-       
-       ConvertVolumeUUIDToString( &targetVolumeUUID, UUIDString);
-       strncpy(uuidLine, UUIDString, VOLUMEUUIDLENGTH+1);
-       strcat(uuidLine, gNewlineString);
-       DoFileSystemFile( gFS_UUID_SUFFIX, uuidLine );
+
+       ((uint32_t *)rawUUID)[0] = OSSwapHostToBigInt32(targetVolumeUUID.v.high);
+       ((uint32_t *)rawUUID)[1] = OSSwapHostToBigInt32(targetVolumeUUID.v.low);
+
+       uuid_create_md5_from_name(uuid, kFSUUIDNamespaceSHA1, rawUUID, sizeof(rawUUID));
+       uuid_unparse(uuid, uuidLine);
+       write(1, uuidLine, strlen(uuidLine));
        result = FSUR_IO_SUCCESS;
        
 Err_Exit:
@@ -667,7 +888,7 @@ DoAdopt( const char * theDeviceNamePtr ) {
        if ((result = OpenVolumeStatusDB(&vsdbhandle)) != 0) goto Err_Exit;
        if ((result = GetVolumeStatusDBEntry(vsdbhandle, &targetVolumeUUID, &targetVolumeStatus)) != 0) {
                targetVolumeStatus = 0;
-       };
+       }
        targetVolumeStatus = (targetVolumeStatus & VOLUME_VALIDSTATUSBITS) | VOLUME_USEPERMISSIONS;
        if ((result = SetVolumeStatusDBEntry(vsdbhandle, &targetVolumeUUID, targetVolumeStatus)) != 0) goto Err_Exit;
 
@@ -678,7 +899,7 @@ Err_Exit:
                closeresult = CloseVolumeStatusDB(vsdbhandle);
                vsdbhandle = NULL;
                if (result == FSUR_IO_SUCCESS) result = closeresult;
-       };
+       }
        
        if ((result != 0) && (result != FSUR_IO_SUCCESS)) result = FSUR_IO_FAIL;
        
@@ -711,7 +932,7 @@ DoDisown( const char * theDeviceNamePtr ) {
        if ((result = OpenVolumeStatusDB(&vsdbhandle)) != 0) goto Err_Exit;
        if ((result = GetVolumeStatusDBEntry(vsdbhandle, &targetVolumeUUID, &targetVolumeStatus)) != 0) {
                targetVolumeStatus = 0;
-       };
+       }
        targetVolumeStatus = (targetVolumeStatus & VOLUME_VALIDSTATUSBITS) & ~VOLUME_USEPERMISSIONS;
        if ((result = SetVolumeStatusDBEntry(vsdbhandle, &targetVolumeUUID, targetVolumeStatus)) != 0) goto Err_Exit;
 
@@ -722,14 +943,14 @@ Err_Exit:
                closeresult = CloseVolumeStatusDB(vsdbhandle);
                vsdbhandle = NULL;
                if (result == FSUR_IO_SUCCESS) result = closeresult;
-       };
+       }
        
        if ((result != 0) && (result != FSUR_IO_SUCCESS)) {
 #if TRACE_HFS_UTIL
                if (result != 0) fprintf(stderr, "DoDisown: result = %d; changing to %d...\n", result, FSUR_IO_FAIL);
 #endif
                result = FSUR_IO_FAIL;
-       };
+       }
        
 Err_Return:
 #if TRACE_HFS_UTIL
@@ -739,6 +960,19 @@ Err_Return:
 }
 
 
+static int
+get_multiplier(char c)
+{
+       if (tolower(c) == 'k') {
+               return 1024;
+       } else if (tolower(c) == 'm') {
+               return 1024 * 1024;
+       } else if (tolower(c) == 'g') {
+               return 1024 * 1024 * 1024;
+       } 
+
+       return 1;
+}
 
 /* **************************************** ParseArgs ********************************************
 Purpose -
@@ -765,6 +999,8 @@ flagsArg:
         (these are ignored for CDROMs)
         either "readonly" OR "writable"
         either "removable" OR "fixed"
+        either "nosuid" or "suid"
+       either "nodev" or "dev"
 
 examples:
        hfs.util -p disk0s2 removable writable
@@ -780,11 +1016,12 @@ Output -
 static int
 ParseArgs(int argc, const char *argv[], const char ** actionPtr,
        const char ** mountPointPtr, boolean_t * isEjectablePtr,
-       boolean_t * isLockedPtr)
+          boolean_t * isLockedPtr, boolean_t * isSetuidPtr, boolean_t * isDevPtr)
 {
     int                        result = FSUR_INVAL;
-    int                        deviceLength;
+    int                        deviceLength, doLengthCheck = 1;
     int                        index;
+    int                mounting = 0;
 
     /* Must have at least 3 arguments and the action argument must start with a '-' */
     if ( (argc < 3) || (argv[1][0] != '-') ) {
@@ -815,21 +1052,22 @@ ParseArgs(int argc, const char *argv[], const char ** actionPtr,
             
         case FSUC_MOUNT:
         case FSUC_MOUNT_FORCE:
-            /* action Mount and ForceMount require 6 arguments (need the mountpoint and the flags) */
-            if ( argc < 6 ) {
+            /* action Mount and ForceMount require 8 arguments (need the mountpoint and the flags) */
+            if ( argc < 8 ) {
                 DoDisplayUsage( argv );
                 goto Return;
             } else {
                 * mountPointPtr = argv[3];
                 index = 4;
+                mounting = 1;
             }
             break;
         
-        case FSUC_GETKEY:
+        case FSUC_GETUUID:
                index = 0;
                        break;
                
-               case FSUC_NEWUUID:
+               case FSUC_SETUUID:
                        index = 0;
                        break;
                        
@@ -841,6 +1079,36 @@ ParseArgs(int argc, const char *argv[], const char ** actionPtr,
                        index = 0;
                        break;
                
+               // XXXdbg
+               case FSUC_MKJNL:
+                       index = 0;
+                       doLengthCheck = 0;
+                       if (isdigit(argv[2][0])) {
+                               char *ptr;
+                               gJournalSize = strtoul(argv[2], &ptr, 0);
+                               if (ptr) {
+                                       gJournalSize *= get_multiplier(*ptr);
+                               }
+                               return 0;
+                       }
+                       break;
+
+               case FSUC_UNJNL:
+                       index = 0;
+                       doLengthCheck = 0;
+                       break;
+
+               case FSUC_UNJNL_RAW:
+                       index = 0;
+                       doLengthCheck = 0;
+                       break;
+
+               case FSUC_JNLINFO:
+                       index = 0;
+                       doLengthCheck = 0;
+                       break;
+               // XXXdbg
+
         default:
             DoDisplayUsage( argv );
             goto Return;
@@ -849,7 +1117,7 @@ ParseArgs(int argc, const char *argv[], const char ** actionPtr,
 
     /* Make sure device (argv[2]) is something reasonable */
     deviceLength = strlen( argv[2] );
-    if ( deviceLength < 3 || deviceLength > 10 ) {
+    if ( doLengthCheck && (deviceLength < 3 || deviceLength > NAME_MAX) ) {
         DoDisplayUsage( argv );
         goto Return;
     }
@@ -872,6 +1140,28 @@ ParseArgs(int argc, const char *argv[], const char ** actionPtr,
         } else {
             printf("hfs.util: ERROR: unrecognized flag (readonly/writable) argv[%d]='%s'\n",index,argv[index+1]);
         }
+
+        if (mounting) {
+                    /* Flags: suid/nosuid. */
+                    if ( 0 == strcmp(argv[index+2],"suid") ) {
+                        * isSetuidPtr = 1;
+                    } else if ( 0 == strcmp(argv[index+2],"nosuid") ) {
+                        * isSetuidPtr = 0;
+                    } else {
+                        printf("hfs.util: ERROR: unrecognized flag (suid/nosuid) argv[%d]='%s'\n",index,argv[index+2]);
+                    }
+
+                    /* Flags: dev/nodev. */
+                    if ( 0 == strcmp(argv[index+3],"dev") ) {
+                        * isDevPtr = 1;
+                    } else if ( 0 == strcmp(argv[index+3],"nodev") ) {
+                        * isDevPtr = 0;
+                    } else {
+                        printf("hfs.util: ERROR: unrecognized flag (dev/nodev) argv[%d]='%s'\n",index,argv[index+3]);
+                    }
+        }
+
+
     }
 
     result = 0;
@@ -899,82 +1189,155 @@ DoDisplayUsage(const char *argv[])
     printf("       -%c (Mount)\n", FSUC_MOUNT);
     printf("       -%c (Unmount)\n", FSUC_UNMOUNT);
     printf("       -%c (Force Mount)\n", FSUC_MOUNT_FORCE);
-    printf("       -%c (Get UUID Key)\n", FSUC_GETKEY);
-    printf("       -%c (New UUID Key)\n", FSUC_NEWUUID);
+#ifdef HFS_UUID_SUPPORT
+    printf("       -%c (Get UUID Key)\n", FSUC_GETUUID);
+    printf("       -%c (Set UUID Key)\n", FSUC_SETUUID);
+#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 (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");
+    printf("       if '-%c' or '-%c' is specified, this should be the\n", FSUC_MKJNL, FSUC_UNJNL);
+       printf("       name of the file system we're to act on (for example, '/Volumes/foo' or '/')\n");
     printf("mount_point_arg:\n");
     printf("       required for Mount and Force Mount \n");
     printf("Flags:\n");
     printf("       required for Mount, Force Mount and Probe\n");
     printf("       indicates removable or fixed (for example 'fixed')\n");
     printf("       indicates readonly or writable (for example 'readonly')\n");
+    printf("       indicates suid or nosuid (for example 'suid')\n");
+    printf("       indicates dev or nodev (for example 'dev')\n");
     printf("Examples:\n");
     printf("       %s -p disk0s2 fixed writable\n", argv[0]);
-    printf("       %s -m disk0s2 /my/hfs removable readonly\n", argv[0]);
+    printf("       %s -m disk0s2 /my/hfs removable readonly nosuid nodev\n", argv[0]);
 
     return;
 
 } /* DoDisplayUsage */
 
 
-/* ************************************** DoFileSystemFile *******************************************
-Purpose -
-    This routine will create a file system info file that is used by WorkSpace.  After creating the
-    file it will write whatever theContentsPtr points to the new file.
-    We end up with a file something like:
-    /System/Library/Filesystems/hfs.fs/hfs.name
-    when our file system name is "hfs" and theFileNameSuffixPtr points to ".name"
-Input -
-    theFileNameSuffixPtr - pointer to a suffix we add to the file name we're creating.
-    theContentsPtr - pointer to C string to write into the file.
-Output -
-    NA.
-*************************************************************************************************** */
-static void
-DoFileSystemFile(char *fileNameSuffixPtr, char *contentsPtr)
+/*
+       GetHFSMountPoint
+       
+       Given a path to a device, determine if a volume is mounted on that
+       device.  If there is an HFS volume, return its path and FSUR_IO_SUCCESS.
+       If there is a non-HFS volume, return FSUR_UNRECOGNIZED.  If there is
+       no volume mounted on the device, set *pathPtr to NULL and return
+       FSUR_IO_SUCCESS.
+
+       Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL, FSUR_UNRECOGNIZED
+*/
+static int
+GetHFSMountPoint(const char *deviceNamePtr, char **pathPtr)
 {
-    int fd;
-    char fileName[MAXPATHLEN];
-
-    sprintf(fileName, "%s/%s%s/%s", FS_DIR_LOCATION, gHFS_FS_NAME,
-       FS_DIR_SUFFIX, gHFS_FS_NAME );
-    strcat(fileName, fileNameSuffixPtr );
-    unlink(fileName);          /* delete existing string */
-
-    if ( strlen( fileNameSuffixPtr ) ) {
-        int oldMask = umask(0);
-
-        fd = open( & fileName[0], O_CREAT | O_TRUNC | O_WRONLY, 0644 );
-        umask( oldMask );
-        if ( fd > 0 ) {
-            write( fd, contentsPtr, strlen( contentsPtr ) );
-            close( fd );
-        } else {
-            perror( fileName );
-        }
-    }
+       int result;
+       int i, numMounts;
+       struct statfs *buf;
+       
+       /* Assume no mounted volume found */    
+       *pathPtr = NULL;
+       result = FSUR_IO_SUCCESS;       
+       
+       numMounts = getmntinfo(&buf, MNT_NOWAIT);
+       if (numMounts == 0)
+               return FSUR_IO_FAIL;
+       
+       for (i=0; i<numMounts; ++i) {
+               if (!strcmp(deviceNamePtr, buf[i].f_mntfromname)) {
+                       /* Found a mounted volume; check the type */
+                       if (!strcmp(buf[i].f_fstypename, "hfs")) {
+                               *pathPtr = buf[i].f_mntonname;
+                               /* result = FSUR_IO_SUCCESS, above */
+                       } else {
+                               result = FSUR_UNRECOGNIZED;
+                       }
+                       break;
+               }
+       }
+       
+       return result;
+}
 
-    return;
 
-} /* DoFileSystemFile */
+/*
+       ReadHeaderBlock
+       
+       Read the Master Directory Block or Volume Header Block from an HFS,
+       HFS Plus, or HFSX volume into a caller-supplied buffer.  Return the
+       offset of an embedded HFS Plus volume (or 0 if not embedded HFS Plus).
+       Return a pointer to the volume UUID in the Finder Info.
 
+       Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL, FSUR_UNRECOGNIZED
+*/
+static int
+ReadHeaderBlock(int fd, void *bufPtr, off_t *startOffset, VolumeUUID **finderInfoUUIDPtr)
+{
+       int result;
+       HFSMasterDirectoryBlock * mdbPtr;
+       HFSPlusVolumeHeader * volHdrPtr;
 
+       mdbPtr = bufPtr;
+       volHdrPtr = bufPtr;
+
+       /*
+        * Read the HFS Master Directory Block or Volume Header from sector 2
+        */
+       *startOffset = 0;
+       result = readAt(fd, bufPtr, (off_t)(2 * HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
+       if (result != FSUR_IO_SUCCESS)
+               goto Err_Exit;
+
+       /*
+        * If this is a wrapped HFS Plus volume, read the Volume Header from
+        * sector 2 of the embedded volume.
+        */
+       if (OSSwapBigToHostInt16(mdbPtr->drSigWord) == kHFSSigWord &&
+               OSSwapBigToHostInt16(mdbPtr->drEmbedSigWord) == kHFSPlusSigWord) {
+               result = GetEmbeddedHFSPlusVol(mdbPtr, startOffset);
+               if (result != FSUR_IO_SUCCESS)
+                       goto Err_Exit;
+               result = readAt(fd, bufPtr, *startOffset + (off_t)(2*HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
+               if (result != FSUR_IO_SUCCESS)
+                       goto Err_Exit;
+       }
+       
+       /*
+        * At this point, we have the MDB for plain HFS, or VHB for HFS Plus and HFSX
+        * volumes (including wrapped HFS Plus).  Verify the signature and grab the
+        * UUID from the Finder Info.
+        */
+       if (OSSwapBigToHostInt16(mdbPtr->drSigWord) == kHFSSigWord) {
+           *finderInfoUUIDPtr = (VolumeUUID *)(&mdbPtr->drFndrInfo[6]);
+       } else if (OSSwapBigToHostInt16(volHdrPtr->signature) == kHFSPlusSigWord ||
+                               OSSwapBigToHostInt16(volHdrPtr->signature) == kHFSXSigWord) {
+           *finderInfoUUIDPtr = (VolumeUUID *)&volHdrPtr->finderInfo[24];
+       } else {
+               result = FSUR_UNRECOGNIZED;
+       }
+
+Err_Exit:
+       return result;
+}
 
 
 /*
- --    GetVolumeUUID
- --
- --    Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL
- */
+       GetVolumeUUIDRaw
+       
+       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.
 
+       Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL, FSUR_UNRECOGNIZED
+*/
 static int
-GetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr, boolean_t generate) {
+GetVolumeUUIDRaw(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr)
+{
        int fd = 0;
        char * bufPtr;
-       HFSMasterDirectoryBlock * mdbPtr;
-       HFSPlusVolumeHeader * volHdrPtr;
+       off_t startOffset;
        VolumeUUID *finderInfoUUIDPtr;
        int result;
 
@@ -984,185 +1347,290 @@ GetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr, boolean_t ge
                goto Err_Exit;
        }
 
-       mdbPtr = (HFSMasterDirectoryBlock *) bufPtr;
-       volHdrPtr = (HFSPlusVolumeHeader *) bufPtr;
-
-       fd = open( deviceNamePtr, O_RDWR, 0 );
-       if( fd <= 0 ) {
-               fd = open( deviceNamePtr, O_RDONLY, 0);
-               if (fd <= 0) {
+       fd = open( deviceNamePtr, O_RDONLY, 0);
+       if (fd <= 0) {
 #if TRACE_HFS_UTIL
-                       fprintf(stderr, "hfs.util: GetVolumeUUID: device open failed (errno = %d).\n", errno);
+               fprintf(stderr, "hfs.util: GetVolumeUUIDRaw: device open failed (errno = %d).\n", errno);
 #endif
-                       result = FSUR_IO_FAIL;
-                       goto Err_Exit;
-               };
-       };
+               result = FSUR_IO_FAIL;
+               goto Err_Exit;
+       }
 
        /*
-        * Read the HFS Master Directory Block from sector 2
+        * Get the pointer to the volume UUID in the Finder Info
         */
-       result = readAt(fd, volHdrPtr, (off_t)(2 * HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
-       if (result != FSUR_IO_SUCCESS) {
+       result = ReadHeaderBlock(fd, bufPtr, &startOffset, &finderInfoUUIDPtr);
+       if (result != FSUR_IO_SUCCESS)
                goto Err_Exit;
-       };
-
-       if (mdbPtr->drSigWord == kHFSSigWord &&
-           mdbPtr->drEmbedSigWord != kHFSPlusSigWord) {
-           finderInfoUUIDPtr = (VolumeUUID *)(&mdbPtr->drFndrInfo[6]);
-           if (generate && ((finderInfoUUIDPtr->v.high == 0) || (finderInfoUUIDPtr->v.low == 0))) {
-               GenerateVolumeUUID(volumeUUIDPtr);
-               bcopy(volumeUUIDPtr, finderInfoUUIDPtr, sizeof(*finderInfoUUIDPtr));
-                       result = writeAt(fd, volHdrPtr, (off_t)(2 * HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
-                       if (result != FSUR_IO_SUCCESS) goto Err_Exit;
-               };
-               bcopy(finderInfoUUIDPtr, volumeUUIDPtr, sizeof(*volumeUUIDPtr));
-               result = FSUR_IO_SUCCESS;
-       } else if ((volHdrPtr->signature == kHFSPlusSigWord)  ||
-                  ((mdbPtr->drSigWord == kHFSSigWord) &&
-                   (mdbPtr->drEmbedSigWord == kHFSPlusSigWord))) {
-               off_t startOffset;
 
-               if (volHdrPtr->signature == kHFSPlusSigWord) {
-                       startOffset = 0;
-               } else {/* embedded volume, first find offset */
-                       result = GetEmbeddedHFSPlusVol(mdbPtr, &startOffset);
-                       if ( result != FSUR_IO_SUCCESS ) {
-                               goto Err_Exit;
-                       };
-               }
-       
-           result = readAt( fd, volHdrPtr, startOffset + (off_t)(2*HFS_BLOCK_SIZE), HFS_BLOCK_SIZE );
-           if (result != FSUR_IO_SUCCESS) {
-               goto Err_Exit; // return FSUR_IO_FAIL
-           }
-       
-           /* Verify that it is an HFS+ volume. */
+       /*
+        * Copy the volume UUID out of the Finder Info
+        */
+       volumeUUIDPtr->v.high = OSSwapBigToHostInt32(finderInfoUUIDPtr->v.high);
+       volumeUUIDPtr->v.low = OSSwapBigToHostInt32(finderInfoUUIDPtr->v.low);
+
+Err_Exit:
+       if (fd > 0) close(fd);
+       if (bufPtr) free(bufPtr);
        
-           if (volHdrPtr->signature != kHFSPlusSigWord) {
-               result = FSUR_IO_FAIL;
-               goto Err_Exit;
-           }
+#if TRACE_HFS_UTIL
+       if (result != FSUR_IO_SUCCESS) fprintf(stderr, "hfs.util: GetVolumeUUIDRaw: result = %d...\n", result);
+#endif
+       return (result == FSUR_IO_SUCCESS) ? FSUR_IO_SUCCESS : FSUR_IO_FAIL;
+}
+
+
+/*
+       SetVolumeUUIDRaw
        
-           finderInfoUUIDPtr = (VolumeUUID *)&volHdrPtr->finderInfo[24];
-           if (generate && ((finderInfoUUIDPtr->v.high == 0) || (finderInfoUUIDPtr->v.low == 0))) {
-               GenerateVolumeUUID(volumeUUIDPtr);
-               bcopy(volumeUUIDPtr, finderInfoUUIDPtr, sizeof(*finderInfoUUIDPtr));
-                       result = writeAt( fd, volHdrPtr, startOffset + (off_t)(2*HFS_BLOCK_SIZE), HFS_BLOCK_SIZE );
-                       if (result != FSUR_IO_SUCCESS) {
-                               goto Err_Exit;
-                       };
-               };
-               bcopy(finderInfoUUIDPtr, volumeUUIDPtr, sizeof(*volumeUUIDPtr));
-               result = FSUR_IO_SUCCESS;
-       } else {
+       Write a previously generated UUID to 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.
+
+       Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL, FSUR_UNRECOGNIZED
+*/
+static int
+SetVolumeUUIDRaw(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr)
+{
+       int fd = 0;
+       char * bufPtr;
+       off_t startOffset;
+       VolumeUUID *finderInfoUUIDPtr;
+       int result;
+
+       bufPtr = (char *)malloc(HFS_BLOCK_SIZE);
+       if ( ! bufPtr ) {
                result = FSUR_UNRECOGNIZED;
-       };
+               goto Err_Exit;
+       }
+
+       fd = open( deviceNamePtr, O_RDWR, 0);
+       if (fd <= 0) {
+#if TRACE_HFS_UTIL
+               fprintf(stderr, "hfs.util: SetVolumeUUIDRaw: device open failed (errno = %d).\n", errno);
+#endif
+               result = FSUR_IO_FAIL;
+               goto Err_Exit;
+       }
+
+       /*
+        * 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;
+
+       /*
+        * Update the UUID in the Finder Info
+        */
+       finderInfoUUIDPtr->v.high = OSSwapHostToBigInt32(volumeUUIDPtr->v.high);
+       finderInfoUUIDPtr->v.low = OSSwapHostToBigInt32(volumeUUIDPtr->v.low);
+
+       /*
+        * Write the modified MDB or VHB back to disk
+        */
+       result = writeAt(fd, bufPtr, startOffset + (off_t)(2*HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
 
 Err_Exit:
        if (fd > 0) close(fd);
        if (bufPtr) free(bufPtr);
        
 #if TRACE_HFS_UTIL
-       if (result != FSUR_IO_SUCCESS) fprintf(stderr, "hfs.util: GetVolumeUUID: result = %d...\n", result);
+       if (result != FSUR_IO_SUCCESS) fprintf(stderr, "hfs.util: SetVolumeUUIDRaw: result = %d...\n", result);
 #endif
        return (result == FSUR_IO_SUCCESS) ? FSUR_IO_SUCCESS : FSUR_IO_FAIL;
-};
+}
 
 
+/*
+       GetVolumeUUIDAttr
+       
+       Read the UUID from a mounted volume, by calling getattrlist().
+       Assumes the path is the mount point of an HFS volume.
+
+       Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL
+*/
+static int
+GetVolumeUUIDAttr(const char *path, VolumeUUID *volumeUUIDPtr)
+{
+       struct attrlist alist;
+       struct FinderAttrBuf volFinderInfo;
+       VolumeUUID *finderInfoUUIDPtr;
+       int result;
+
+       /* Set up the attrlist structure to get the volume's Finder Info */
+       alist.bitmapcount = 5;
+       alist.reserved = 0;
+       alist.commonattr = ATTR_CMN_FNDRINFO;
+       alist.volattr = ATTR_VOL_INFO;
+       alist.dirattr = 0;
+       alist.fileattr = 0;
+       alist.forkattr = 0;
+
+       /* Get the Finder Info */
+       result = getattrlist(path, &alist, &volFinderInfo, sizeof(volFinderInfo), 0);
+       if (result) {
+               result = FSUR_IO_FAIL;
+               goto Err_Exit;
+       }
+
+       /* Copy the UUID from the Finder Into to caller's buffer */
+       finderInfoUUIDPtr = (VolumeUUID *)(&volFinderInfo.finderinfo[6]);
+       volumeUUIDPtr->v.high = OSSwapBigToHostInt32(finderInfoUUIDPtr->v.high);
+       volumeUUIDPtr->v.low = OSSwapBigToHostInt32(finderInfoUUIDPtr->v.low);
+       result = FSUR_IO_SUCCESS;
+
+Err_Exit:
+       return result;
+}
+
 
 /*
- --    SetVolumeUUID
- --
- --    Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL
- */
+       SetVolumeUUIDAttr
+       
+       Write a UUID to a mounted volume, by calling setattrlist().
+       Assumes the path is the mount point of an HFS volume.
 
+       Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL
+*/
 static int
-SetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr) {
-       int fd = 0;
-       char * bufPtr;
-       HFSMasterDirectoryBlock * mdbPtr;
-       HFSPlusVolumeHeader * volHdrPtr;
+SetVolumeUUIDAttr(const char *path, VolumeUUID *volumeUUIDPtr)
+{
+       struct attrlist alist;
+       struct FinderAttrBuf volFinderInfo;
        VolumeUUID *finderInfoUUIDPtr;
        int result;
 
-       bufPtr = (char *)malloc(HFS_BLOCK_SIZE);
-       if ( ! bufPtr ) {
-               result = FSUR_UNRECOGNIZED;
+       /* Set up the attrlist structure to get the volume's Finder Info */
+       alist.bitmapcount = 5;
+       alist.reserved = 0;
+       alist.commonattr = ATTR_CMN_FNDRINFO;
+       alist.volattr = ATTR_VOL_INFO;
+       alist.dirattr = 0;
+       alist.fileattr = 0;
+       alist.forkattr = 0;
+
+       /* Get the Finder Info */
+       result = getattrlist(path, &alist, &volFinderInfo, sizeof(volFinderInfo), 0);
+       if (result) {
+               result = FSUR_IO_FAIL;
                goto Err_Exit;
        }
 
-       mdbPtr = (HFSMasterDirectoryBlock *) bufPtr;
-       volHdrPtr = (HFSPlusVolumeHeader *) bufPtr;
+       /* Update the UUID in the Finder Info */
+       finderInfoUUIDPtr = (VolumeUUID *)(&volFinderInfo.finderinfo[6]);
+       finderInfoUUIDPtr->v.high = OSSwapHostToBigInt32(volumeUUIDPtr->v.high);
+       finderInfoUUIDPtr->v.low = OSSwapHostToBigInt32(volumeUUIDPtr->v.low);
 
-       fd = open( deviceNamePtr, O_RDWR, 0 );
-       if( fd <= 0 ) {
-#if TRACE_HFS_UTIL
-               fprintf(stderr, "hfs.util: SetVolumeUUID: device open failed (errno = %d).\n", errno);
-#endif
+       /* Write the Finder Info back to the volume */
+       result = setattrlist(path, &alist, &volFinderInfo.finderinfo, sizeof(volFinderInfo.finderinfo), 0);
+       if (result) {
                result = FSUR_IO_FAIL;
                goto Err_Exit;
-       };
+       }
+
+       result = FSUR_IO_SUCCESS;
+
+Err_Exit:
+       return result;
+}
+
+
+/*
+       GetVolumeUUID
+       
+       Return the UUID of an HFS, HFS Plus or HFSX volume.  If there is no UUID and
+       we were asked to generate one, then generate a new UUID and write it to the
+       volume.
+       
+       Determine whether an HFS volume is mounted on the given device.  If so, we
+       need to use GetVolumeUUIDAttr and SetVolumeUUIDAttr to access the UUID through
+       the filesystem.  If there is no mounted volume, then do direct device access
+       with GetVolumeUUIDRaw and SetVolumeUUIDRaw.
+       
+       Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL, FSUR_UNRECOGNIZED
+ */
+
+static int
+GetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr, boolean_t generate)
+{
+       int result;
+       char *path = NULL;
+       
+       /*
+        * Determine whether a volume is mounted on this device.  If it is HFS, then
+        * get the mount point's path.  If it is non-HFS, then we can exit immediately
+        * with FSUR_UNRECOGNIZED.
+        */
+       result = GetHFSMountPoint(deviceNamePtr, &path);
+       if (result != FSUR_IO_SUCCESS)
+               goto Err_Exit;
 
        /*
-        * Read the HFS Master Directory Block from sector 2
+        * Get any existing UUID.
         */
-       result = readAt(fd, volHdrPtr, (off_t)(2 * HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
-       if (result != FSUR_IO_SUCCESS) {
+       if (path)
+               result = GetVolumeUUIDAttr(path, volumeUUIDPtr);
+       else
+               result = GetVolumeUUIDRaw(deviceNamePtr, volumeUUIDPtr);
+       if (result != FSUR_IO_SUCCESS)
                goto Err_Exit;
-       };
-
-       if (mdbPtr->drSigWord == kHFSSigWord &&
-           mdbPtr->drEmbedSigWord != kHFSPlusSigWord) {
-           finderInfoUUIDPtr = (VolumeUUID *)(&mdbPtr->drFndrInfo[6]);
-           bcopy(volumeUUIDPtr, finderInfoUUIDPtr, sizeof(*finderInfoUUIDPtr));
-               result = writeAt(fd, volHdrPtr, (off_t)(2 * HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
-       } else if ((volHdrPtr->signature == kHFSPlusSigWord)  ||
-                  ((mdbPtr->drSigWord == kHFSSigWord) &&
-                   (mdbPtr->drEmbedSigWord == kHFSPlusSigWord))) {
-               off_t startOffset;
 
-               if (volHdrPtr->signature == kHFSPlusSigWord) {
-                       startOffset = 0;
-               } else {/* embedded volume, first find offset */
-                       result = GetEmbeddedHFSPlusVol(mdbPtr, &startOffset);
-                       if ( result != FSUR_IO_SUCCESS ) {
-                               goto Err_Exit;
-                       };
-               }
+       /*
+        * 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 */
+       }
+
+Err_Exit:
+       return result;
+}
+
+
+
+/*
+       SetVolumeUUID
        
-           result = readAt( fd, volHdrPtr, startOffset + (off_t)(2*HFS_BLOCK_SIZE), HFS_BLOCK_SIZE );
-           if (result != FSUR_IO_SUCCESS) {
-               goto Err_Exit; // return FSUR_IO_FAIL
-           }
+       Write a UUID to an HFS, HFS Plus or HFSX volume.
        
-           /* Verify that it is an HFS+ volume. */
+       Determine whether an HFS volume is mounted on the given device.  If so, we
+       need to use SetVolumeUUIDAttr to access the UUID through the filesystem.
+       If there is no mounted volume, then do direct device access SetVolumeUUIDRaw.
        
-           if (volHdrPtr->signature != kHFSPlusSigWord) {
-               result = FSUR_IO_FAIL;
-               goto Err_Exit;
-           }
+       Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL, FSUR_UNRECOGNIZED
+ */
+static int
+SetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr) {
+       int result;
+       char *path = NULL;
        
-           finderInfoUUIDPtr = (VolumeUUID *)&volHdrPtr->finderInfo[24];
-           bcopy(volumeUUIDPtr, finderInfoUUIDPtr, sizeof(*finderInfoUUIDPtr));
-               result = writeAt( fd, volHdrPtr, startOffset + (off_t)(2*HFS_BLOCK_SIZE), HFS_BLOCK_SIZE );
-               if (result != FSUR_IO_SUCCESS) {
-                       goto Err_Exit;
-               };
-               result = FSUR_IO_SUCCESS;
-       } else {
-               result = FSUR_UNRECOGNIZED;
-       };
+       /*
+        * Determine whether a volume is mounted on this device.  If it is HFS, then
+        * get the mount point's path.  If it is non-HFS, then we can exit immediately
+        * with FSUR_UNRECOGNIZED.
+        */
+       result = GetHFSMountPoint(deviceNamePtr, &path);
+       if (result != FSUR_IO_SUCCESS)
+               goto Err_Exit;
+
+       /*
+        * Update the UUID.
+        */
+       if (path)
+               result = SetVolumeUUIDAttr(path, volumeUUIDPtr);
+       else
+               result = SetVolumeUUIDRaw(deviceNamePtr, volumeUUIDPtr);
 
 Err_Exit:
-       if (fd > 0) close(fd);
-       if (bufPtr) free(bufPtr);
-       
-#if TRACE_HFS_UTIL
-       if (result != FSUR_IO_SUCCESS) fprintf(stderr, "hfs.util: SetVolumeUUID: result = %d...\n", result);
-#endif
-       return (result == FSUR_IO_SUCCESS) ? FSUR_IO_SUCCESS : FSUR_IO_FAIL;
-};
+       return result;
+}
 
 
 
@@ -1181,21 +1649,21 @@ GetEmbeddedHFSPlusVol (HFSMasterDirectoryBlock * hfsMasterDirectoryBlockPtr, off
     int                result = FSUR_IO_SUCCESS;
     u_int32_t  allocationBlockSize, firstAllocationBlock, startBlock, blockCount;
 
-    if (hfsMasterDirectoryBlockPtr->drSigWord != kHFSSigWord) {
+    if (OSSwapBigToHostInt16(hfsMasterDirectoryBlockPtr->drSigWord) != kHFSSigWord) {
         result = FSUR_UNRECOGNIZED;
         goto Return;
     }
 
-    allocationBlockSize = hfsMasterDirectoryBlockPtr->drAlBlkSiz;
-    firstAllocationBlock = hfsMasterDirectoryBlockPtr->drAlBlSt;
+    allocationBlockSize = OSSwapBigToHostInt32(hfsMasterDirectoryBlockPtr->drAlBlkSiz);
+    firstAllocationBlock = OSSwapBigToHostInt16(hfsMasterDirectoryBlockPtr->drAlBlSt);
 
-    if (hfsMasterDirectoryBlockPtr->drEmbedSigWord != kHFSPlusSigWord) {
+    if (OSSwapBigToHostInt16(hfsMasterDirectoryBlockPtr->drEmbedSigWord) != kHFSPlusSigWord) {
         result = FSUR_UNRECOGNIZED;
         goto Return;
     }
 
-    startBlock = hfsMasterDirectoryBlockPtr->drEmbedExtent.startBlock;
-    blockCount = hfsMasterDirectoryBlockPtr->drEmbedExtent.blockCount;
+    startBlock = OSSwapBigToHostInt16(hfsMasterDirectoryBlockPtr->drEmbedExtent.startBlock);
+    blockCount = OSSwapBigToHostInt16(hfsMasterDirectoryBlockPtr->drEmbedExtent.blockCount);
 
     if ( startOffsetPtr )
         *startOffsetPtr = ((u_int64_t)startBlock * (u_int64_t)allocationBlockSize) +
@@ -1217,13 +1685,12 @@ 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;
     char                       *       bufPtr = NULL;
     HFSPlusVolumeHeader                *       volHdrPtr;
-    off_t                              offset;
     BTNodeDescriptor           *       bTreeNodeDescriptorPtr;
     u_int32_t                          catalogNodeSize;
        u_int32_t leafNode;
@@ -1250,7 +1717,8 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
 
     /* Verify that it is an HFS+ volume. */
 
-    if (volHdrPtr->signature != kHFSPlusSigWord) {
+    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");
@@ -1258,7 +1726,7 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
         goto Return;
     }
 
-    blockSize = volHdrPtr->blockSize;
+    blockSize = OSSwapBigToHostInt32(volHdrPtr->blockSize);
     catalogExtents = (HFSPlusExtentDescriptor *) malloc(sizeof(HFSPlusExtentRecord));
     if ( ! catalogExtents ) {
         result = FSUR_IO_FAIL;
@@ -1268,32 +1736,20 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
        catalogExtCount = kHFSPlusExtentDensity;
 
        /* if there are overflow catalog extents, then go get them */
-       if (catalogExtents[7].blockCount != 0) {
+       if (OSSwapBigToHostInt32(catalogExtents[7].blockCount) != 0) {
                result = GetCatalogOverflowExtents(fd, hfsPlusVolumeOffset, volHdrPtr, &catalogExtents, &catalogExtCount);
                if (result != FSUR_IO_SUCCESS)
                        goto Return;
        }
 
-    offset = (off_t)catalogExtents[0].startBlock * (off_t)blockSize;
-    
        /* Read the header node of the catalog B-Tree */
 
-       result = GetBTreeNodeInfo(fd, hfsPlusVolumeOffset + offset, &catalogNodeSize, &leafNode);
+       result = GetBTreeNodeInfo(fd, hfsPlusVolumeOffset, blockSize,
+                                                       catalogExtCount, catalogExtents,
+                                                       &catalogNodeSize, &leafNode);
        if (result != FSUR_IO_SUCCESS)
         goto Return;
 
-       /* Calculate the starting block of the first leaf node */
-
-       offset = CalcLeafNodeOffset((leafNode * catalogNodeSize), blockSize, catalogExtCount, catalogExtents);
-
-    if ( offset == 0 ) {
-               result = FSUR_IO_FAIL;
-#if TRACE_HFS_UTIL
-        fprintf(stderr, "hfs.util: ERROR: can't find leaf block\n");
-#endif
-        goto Return;
-       }
-
        /* Read the first leaf node of the catalog b-tree */
 
     bufPtr = (char *)malloc(catalogNodeSize);
@@ -1304,10 +1760,12 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
 
     bTreeNodeDescriptorPtr = (BTNodeDescriptor *)bufPtr;
 
-    result = readAt( fd, bufPtr, hfsPlusVolumeOffset + offset, catalogNodeSize );
+       result = ReadFile(fd, bufPtr, (off_t) leafNode * (off_t) catalogNodeSize, catalogNodeSize,
+                                               hfsPlusVolumeOffset, blockSize,
+                                               catalogExtCount, catalogExtents);
     if (result == FSUR_IO_FAIL) {
 #if TRACE_HFS_UTIL
-        fprintf(stderr, "hfs.util: ERROR: readAt (first leaf) failed\n");
+        fprintf(stderr, "hfs.util: ERROR: reading first leaf failed\n");
 #endif
         goto Return; // return FSUR_IO_FAIL
     }
@@ -1318,7 +1776,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");
@@ -1333,12 +1791,12 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
 
        // Get a pointer to the first record.
 
-        p = bufPtr + *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 (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");
@@ -1348,9 +1806,26 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, char * nam
 
        /* Extract the name of the root directory */
 
-       cfstr = CFStringCreateWithCharacters(kCFAllocatorDefault, k->nodeName.unicode, k->nodeName.length);
-       (void) CFStringGetCString(cfstr, name_o, NAME_MAX, kCFStringEncodingUTF8);
-       CFRelease(cfstr);
+       {
+           HFSUniStr255 *swapped;
+           int i;
+    
+           swapped = (HFSUniStr255 *)malloc(sizeof(HFSUniStr255));
+           if (swapped == NULL) {
+               result = FSUR_IO_FAIL;
+               goto Return;
+           }
+           swapped->length = OSSwapBigToHostInt16(k->nodeName.length);
+           
+           for (i=0; i<swapped->length; i++) {
+               swapped->unicode[i] = OSSwapBigToHostInt16(k->nodeName.unicode[i]);
+           }
+           swapped->unicode[i] = 0;
+           cfstr = CFStringCreateWithCharacters(kCFAllocatorDefault, swapped->unicode, swapped->length);
+           (void) CFStringGetCString(cfstr, (char *)name_o, NAME_MAX, kCFStringEncodingUTF8);
+           CFRelease(cfstr);
+           free(swapped);
+       }
     }
 
     result = FSUR_IO_SUCCESS;
@@ -1384,7 +1859,9 @@ typedef struct {
  --
  */
 static int
-GetBTreeNodeInfo(int fd, off_t btreeOffset, u_int32_t *nodeSize, u_int32_t *firstLeafNode)
+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)
 {
        int result;
        HeaderRec * bTreeHeaderPtr = NULL;
@@ -1395,10 +1872,12 @@ GetBTreeNodeInfo(int fd, off_t btreeOffset, u_int32_t *nodeSize, u_int32_t *firs
     
        /* Read the b-tree header node */
 
-       result = readAt( fd, bTreeHeaderPtr, btreeOffset, HFS_BLOCK_SIZE );
+       result = ReadFile(fd, bTreeHeaderPtr, 0, HFS_BLOCK_SIZE,
+                                       hfsPlusVolumeOffset, blockSize,
+                                       extentCount, extentList);
        if ( result == FSUR_IO_FAIL ) {
 #if TRACE_HFS_UTIL
-               fprintf(stderr, "hfs.util: ERROR: readAt (header node) failed\n");
+               fprintf(stderr, "hfs.util: ERROR: reading header node failed\n");
 #endif
                goto free;
        }
@@ -1411,12 +1890,12 @@ GetBTreeNodeInfo(int fd, off_t btreeOffset, u_int32_t *nodeSize, u_int32_t *firs
                goto free;
        }
 
-       *nodeSize = bTreeHeaderPtr->header.nodeSize;
+       *nodeSize = OSSwapBigToHostInt16(bTreeHeaderPtr->header.nodeSize);
 
-       if (bTreeHeaderPtr->header.leafRecords == 0)
+       if (OSSwapBigToHostInt32(bTreeHeaderPtr->header.leafRecords) == 0)
                *firstLeafNode = 0;
        else
-               *firstLeafNode = bTreeHeaderPtr->header.firstLeafNode;
+               *firstLeafNode = OSSwapBigToHostInt32(bTreeHeaderPtr->header.firstLeafNode);
 
 free:;
        free((char*) bTreeHeaderPtr);
@@ -1426,44 +1905,6 @@ free:;
 } /* GetBTreeNodeInfo */
 
 
-/*
- --
- --
- --    Returns: byte offset to first leaf node 
- --
- */
-static off_t
-CalcLeafNodeOffset(off_t fileOffset, u_int32_t blockSize, u_int32_t extentCount,
-                       HFSPlusExtentDescriptor *extentList)
-{
-       off_t offset = 0;
-       int i;
-       u_long extblks;
-       u_long leafblk;
-
-       /* Find this block in the list of extents */
-       leafblk = fileOffset / blockSize;
-       extblks = 0;
-
-       for (i = 0; i < extentCount; ++i) {
-               if (extentList[i].startBlock == 0 || extentList[i].blockCount == 0)
-                       break; /* done when we reach empty extents */
-
-               extblks += extentList [i].blockCount;
-
-               if (extblks > leafblk) {
-                       offset = (off_t) extentList[i].startBlock * (off_t) blockSize;
-                       offset += fileOffset - (off_t) ((extblks - extentList[i].blockCount) * blockSize);
-                       break;
-               }
-       }
-
-       return offset;
-
-} /* CalcLeafNodeOffset */
-
-
 /*
  --
  --
@@ -1477,8 +1918,10 @@ 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;
@@ -1486,30 +1929,23 @@ GetCatalogOverflowExtents(int fd, off_t hfsPlusVolumeOffset,
        int 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 + offset,
+       result = GetBTreeNodeInfo(fd, hfsPlusVolumeOffset, blockSize,
+                       kHFSPlusExtentDensity, volHdrPtr->extentsFile.extents,
                    &nodeSize, &leafNode);
        if (result != FSUR_IO_SUCCESS || leafNode == 0)
                goto Return;
 
-       /* Calculate the starting block of the first leaf node */
-
-       offset = CalcLeafNodeOffset((leafNode * nodeSize), volHdrPtr->blockSize,
-                   kHFSPlusExtentDensity, &volHdrPtr->extentsFile.extents[0]);
+       /* Calculate the logical position of the first leaf node */
 
-       if (offset == 0) {
-               result = FSUR_IO_FAIL;
-#if TRACE_HFS_UTIL
-               fprintf(stderr, "hfs.util: ERROR: can't find extents b-tree leaf block\n");
-#endif
-               goto Return;
-       }
+       offset = (off_t) leafNode * (off_t) nodeSize;
 
        /* Read the first leaf node of the extents b-tree */
 
@@ -1522,20 +1958,23 @@ GetCatalogOverflowExtents(int fd, off_t hfsPlusVolumeOffset,
        bTreeNodeDescriptorPtr = (BTNodeDescriptor *)bufPtr;
 
 again:
-        result = readAt(fd, bufPtr, hfsPlusVolumeOffset + offset, nodeSize);
-        if ( result == FSUR_IO_FAIL ) {
+       result = ReadFile(fd, bufPtr, offset, nodeSize,
+                                       hfsPlusVolumeOffset, blockSize,
+                                       kHFSPlusExtentDensity, volHdrPtr->extentsFile.extents);
+       if ( result == FSUR_IO_FAIL ) {
 #if TRACE_HFS_UTIL
-            fprintf(stderr, "hfs.util: ERROR: readAt (first leaf) failed\n");
+               fprintf(stderr, "hfs.util: ERROR: reading first leaf failed\n");
 #endif
-            goto Return;
+               goto Return;
        }
 
-        if (bTreeNodeDescriptorPtr->kind != kBTLeafNode) {
+       if (bTreeNodeDescriptorPtr->kind != kBTLeafNode) {
                result = FSUR_IO_FAIL;
                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;
@@ -1549,35 +1988,26 @@ again:
 
                /* Get a pointer to the record */
 
-               p = bufPtr + *v; /* pointer arithmetic in bytes */
+               p = bufPtr + OSSwapBigToHostInt16(*v); /* pointer arithmetic in bytes */
                k = (HFSPlusExtentKey *)p;
 
-               if (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 = CalcLeafNodeOffset((leafNode * nodeSize),
-                           volHdrPtr->blockSize, kHFSPlusExtentDensity,
-               &volHdrPtr->extentsFile.extents[0]);
+               offset = (off_t) leafNode * (off_t) nodeSize;
                
-               if (offset == 0) {
-                       result = FSUR_IO_FAIL;
-#if TRACE_HFS_UTIL
-                       fprintf(stderr, "hfs.util: ERROR: can't find extents b-tree leaf block\n");
-#endif
-                       goto Return;
-               }
                goto again;
        }
 
@@ -1589,6 +2019,122 @@ Return:;
 }
 
 
+
+/*
+ *     LogicalToPhysical - Map a logical file position and size to volume-relative physical
+ *     position and number of contiguous bytes at that position.
+ *
+ *     Inputs:
+ *             logicalOffset   Logical offset in bytes from start of file
+ *             length                  Maximum number of bytes to map
+ *             blockSize               Number of bytes per allocation block
+ *             extentCount             Number of extents in file
+ *             extentList              The file's extents
+ *
+ *     Outputs:
+ *             physicalOffset  Physical offset in bytes from start of volume
+ *             availableBytes  Number of bytes physically contiguous (up to length)
+ *
+ *     Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL
+ */
+static int     LogicalToPhysical(off_t offset, ssize_t length, u_int32_t blockSize,
+                                                       u_int32_t extentCount, const HFSPlusExtentDescriptor *extentList,
+                                                       off_t *physicalOffset, ssize_t *availableBytes)
+{
+       off_t           temp;
+       u_int32_t       logicalBlock;
+       u_int32_t       extent;
+       u_int32_t       blockCount = 0;
+       
+       /* Determine allocation block containing logicalOffset */
+       logicalBlock = offset / blockSize;      /* This can't overflow for valid volumes */
+       offset %= blockSize;    /* Offset from start of allocation block */
+       
+       /* Find the extent containing logicalBlock */
+       for (extent = 0; extent < extentCount; ++extent)
+       {
+               blockCount = OSSwapBigToHostInt32(extentList[extent].blockCount);
+               
+               if (blockCount == 0)
+                       return FSUR_IO_FAIL;    /* Tried to map past physical end of file */
+               
+               if (logicalBlock < blockCount)
+                       break;                          /* Found it! */
+               
+               logicalBlock -= blockCount;
+       }
+
+       if (extent >= extentCount)
+               return FSUR_IO_FAIL;            /* Tried to map past physical end of file */
+
+       /*
+        *      When we get here, extentList[extent] is the extent containing logicalOffset.
+        *      The desired allocation block is logicalBlock blocks into the extent.
+        */
+       
+       /* Compute the physical starting position */
+       temp = OSSwapBigToHostInt32(extentList[extent].startBlock) + logicalBlock;      /* First physical block */
+       temp *= blockSize;      /* Byte offset of first physical block */
+       *physicalOffset = temp + offset;
+
+       /* Compute the available contiguous bytes. */
+       temp = blockCount - logicalBlock;       /* Number of blocks available in extent */
+       temp *= blockSize;
+       temp -= offset;                                         /* Number of bytes available */
+       
+       if (temp < length)
+               *availableBytes = temp;
+       else
+               *availableBytes = length;
+       
+       return FSUR_IO_SUCCESS;
+}
+
+
+
+/*
+ *     ReadFile - Read bytes from a file.  Handles cases where the starting and/or
+ *     ending position are not allocation or device block aligned.
+ *
+ *     Inputs:
+ *             fd                      Descriptor for reading the volume
+ *             buffer          The bytes are read into here
+ *             offset          Offset in file to start reading
+ *             length          Number of bytes to read
+ *             volOffset       Byte offset from start of device to start of volume
+ *             blockSize       Number of bytes per allocation block
+ *             extentCount     Number of extents in file
+ *             extentList      The file's exents
+ *
+ *     Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL
+ */
+static int     ReadFile(int fd, void *buffer, off_t offset, ssize_t length,
+                                       off_t volOffset, u_int32_t blockSize,
+                                       u_int32_t extentCount, const HFSPlusExtentDescriptor *extentList)
+{
+       int             result = FSUR_IO_SUCCESS;
+       off_t   physOffset;
+       ssize_t physLength;
+       
+       while (length > 0)
+       {
+               result = LogicalToPhysical(offset, length, blockSize, extentCount, extentList,
+                                                                       &physOffset, &physLength);
+               if (result != FSUR_IO_SUCCESS)
+                       break;
+               
+               result = readAt(fd, buffer, volOffset+physOffset, physLength);
+               if (result != FSUR_IO_SUCCESS)
+                       break;
+               
+               length -= physLength;
+               offset += physLength;
+               buffer = (char *) buffer + physLength;
+       }
+       
+       return result;
+}
+
 /*
  --    readAt = lseek() + read()
  --
@@ -1605,9 +2151,10 @@ readAt( int fd, void * bufPtr, off_t offset, ssize_t length )
     void *             rawData = NULL;
     off_t              rawOffset;
     ssize_t            rawLength;
+    ssize_t            dataOffset = 0;
     int                        result = FSUR_IO_SUCCESS;
 
-    if (ioctl(fd, DKIOCBLKSIZE, &blocksize) < 0) {
+    if (ioctl(fd, DKIOCGETBLOCKSIZE, &blocksize) < 0) {
 #if TRACE_HFS_UTIL
        fprintf(stderr, "hfs.util: readAt: couldn't determine block size of device.\n");
 #endif
@@ -1616,7 +2163,8 @@ readAt( int fd, void * bufPtr, off_t offset, ssize_t length )
     }
     /* put offset and length in terms of device blocksize */
     rawOffset = offset / blocksize * blocksize;
-    rawLength = ((length + blocksize - 1) / blocksize) * blocksize;
+    dataOffset = offset - rawOffset;
+    rawLength = ((length + dataOffset + blocksize - 1) / blocksize) * blocksize;
     rawData = malloc(rawLength);
     if (rawData == NULL) {
                result = FSUR_IO_FAIL;
@@ -1637,7 +2185,7 @@ readAt( int fd, void * bufPtr, off_t offset, ssize_t length )
         result = FSUR_IO_FAIL;
         goto Return;
     }
-    bcopy(rawData + (offset - rawOffset), bufPtr, length);
+    bcopy(rawData + dataOffset, bufPtr, length);
 
 Return:
     if (rawData) {
@@ -1663,9 +2211,10 @@ writeAt( int fd, void * bufPtr, off_t offset, ssize_t length )
     void *             rawData = NULL;
     off_t              rawOffset;
     ssize_t            rawLength;
+    ssize_t            dataOffset = 0;
     int                        result = FSUR_IO_SUCCESS;
 
-    if (ioctl(fd, DKIOCBLKSIZE, &blocksize) < 0) {
+    if (ioctl(fd, DKIOCGETBLOCKSIZE, &blocksize) < 0) {
 #if TRACE_HFS_UTIL
        fprintf(stderr, "hfs.util: couldn't determine block size of device.\n");
 #endif
@@ -1674,7 +2223,8 @@ writeAt( int fd, void * bufPtr, off_t offset, ssize_t length )
     }
     /* put offset and length in terms of device blocksize */
     rawOffset = offset / blocksize * blocksize;
-    rawLength = ((length + blocksize - 1) / blocksize) * blocksize;
+    dataOffset = offset - rawOffset;
+    rawLength = ((length + dataOffset + blocksize - 1) / blocksize) * blocksize;
     rawData = malloc(rawLength);
     if (rawData == NULL) {
                result = FSUR_IO_FAIL;
@@ -1697,9 +2247,9 @@ writeAt( int fd, void * bufPtr, off_t offset, ssize_t length )
                result = FSUR_IO_FAIL;
                goto Return;
            }
-       };
+       }
        
-    bcopy(bufPtr, rawData + (offset - rawOffset), length);     /* Copy in the new data */
+    bcopy(bufPtr, rawData + dataOffset, length);       /* Copy in the new data */
     
     deviceoffset = lseek( fd, rawOffset, SEEK_SET );
     if ( deviceoffset != rawOffset ) {
@@ -1724,6 +2274,31 @@ Return:
 } /* writeAt */
 
 
+/*
+ * Get kernel's encoding bias.
+ */
+static int
+GetEncodingBias()
+{
+        int mib[3];
+        size_t buflen = sizeof(int);
+        struct vfsconf vfc;
+        int hint = 0;
+
+        if (getvfsbyname("hfs", &vfc) < 0)
+               goto error;
+
+        mib[0] = CTL_VFS;
+        mib[1] = vfc.vfc_typenum;
+        mib[2] = HFS_ENCODINGBIAS;
+       if (sysctl(mib, 3, &hint, &buflen, NULL, 0) < 0)
+               goto error;
+       return (hint);
+error:
+       return (-1);
+}
+
 /******************************************************************************
  *
  *  V O L U M E   S T A T U S   D A T A B A S E   R O U T I N E S
@@ -1772,12 +2347,6 @@ struct VSDBState {
 
 typedef struct VSDBState *VSDBStatePtr;
 
-typedef struct {
-    unsigned long state[5];
-    unsigned long count[2];
-    unsigned char buffer[64];
-} SHA1_CTX;
-
 
 
 /* Internal function prototypes: */
@@ -1797,11 +2366,6 @@ static void FormatDBRecord(unsigned long volumeStatusFlags, struct VSDBRecord *d
 static void FormatDBEntry(VolumeUUID *volumeID, unsigned long volumeStatusFlags, struct VSDBEntry *dbentry);
 static unsigned long ConvertHexStringToULong(const char *hs, long maxdigits);
 
-static void SHA1Transform(unsigned long state[5], unsigned char buffer[64]);
-static void SHA1Init(SHA1_CTX* context);
-static void SHA1Update(SHA1_CTX* context, void* data, size_t len);
-static void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
-
 
 
 /******************************************************************************
@@ -1811,7 +2375,7 @@ static void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
  *****************************************************************************/
 
 void GenerateVolumeUUID(VolumeUUID *newVolumeID) {
-       SHA1_CTX context;
+       SHA_CTX context;
        char randomInputBuffer[26];
        unsigned char digest[20];
        time_t now;
@@ -1820,75 +2384,73 @@ void GenerateVolumeUUID(VolumeUUID *newVolumeID) {
        int sysdata;
        char sysctlstring[128];
        size_t datalen;
-       struct loadavg sysloadavg;
+       double sysloadavg[3];
        struct vmtotal sysvmtotal;
        
        do {
                /* Initialize the SHA-1 context for processing: */
-               SHA1Init(&context);
+               SHA1_Init(&context);
                
                /* Now process successive bits of "random" input to seed the process: */
                
                /* The current system's uptime: */
                uptime = clock();
-               SHA1Update(&context, &uptime, sizeof(uptime));
+               SHA1_Update(&context, &uptime, sizeof(uptime));
                
                /* The kernel's boot time: */
                mib[0] = CTL_KERN;
                mib[1] = KERN_BOOTTIME;
                datalen = sizeof(sysdata);
                sysctl(mib, 2, &sysdata, &datalen, NULL, 0);
-               SHA1Update(&context, &sysdata, datalen);
+               SHA1_Update(&context, &sysdata, datalen);
                
                /* The system's host id: */
                mib[0] = CTL_KERN;
                mib[1] = KERN_HOSTID;
                datalen = sizeof(sysdata);
                sysctl(mib, 2, &sysdata, &datalen, NULL, 0);
-               SHA1Update(&context, &sysdata, datalen);
+               SHA1_Update(&context, &sysdata, datalen);
 
                /* The system's host name: */
                mib[0] = CTL_KERN;
                mib[1] = KERN_HOSTNAME;
                datalen = sizeof(sysctlstring);
                sysctl(mib, 2, sysctlstring, &datalen, NULL, 0);
-               SHA1Update(&context, sysctlstring, datalen);
+               SHA1_Update(&context, sysctlstring, datalen);
 
                /* The running kernel's OS release string: */
                mib[0] = CTL_KERN;
                mib[1] = KERN_OSRELEASE;
                datalen = sizeof(sysctlstring);
                sysctl(mib, 2, sysctlstring, &datalen, NULL, 0);
-               SHA1Update(&context, sysctlstring, datalen);
+               SHA1_Update(&context, sysctlstring, datalen);
 
                /* The running kernel's version string: */
                mib[0] = CTL_KERN;
                mib[1] = KERN_VERSION;
                datalen = sizeof(sysctlstring);
                sysctl(mib, 2, sysctlstring, &datalen, NULL, 0);
-               SHA1Update(&context, sysctlstring, datalen);
+               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);
-               SHA1Update(&context, &sysloadavg, datalen);
+               getloadavg(sysloadavg, 3);
+               SHA1_Update(&context, &sysloadavg, datalen);
 
                /* The system's VM statistics: */
                mib[0] = CTL_VM;
                mib[1] = VM_METER;
                datalen = sizeof(sysvmtotal);
                sysctl(mib, 2, &sysvmtotal, &datalen, NULL, 0);
-               SHA1Update(&context, &sysvmtotal, datalen);
+               SHA1_Update(&context, &sysvmtotal, datalen);
 
                /* The current GMT (26 ASCII characters): */
                time(&now);
                strncpy(randomInputBuffer, asctime(gmtime(&now)), 26);  /* "Mon Mar 27 13:46:26 2000" */
-               SHA1Update(&context, randomInputBuffer, 26);
+               SHA1_Update(&context, randomInputBuffer, 26);
                
                /* Pad the accumulated input and extract the final digest hash: */
-               SHA1Final(digest, &context);
+               SHA1_Final(digest, &context);
        
                memcpy(newVolumeID, digest, sizeof(*newVolumeID));
        } while ((newVolumeID->v.high == 0) || (newVolumeID->v.low == 0));
@@ -1913,11 +2475,11 @@ void ConvertVolumeUUIDStringToUUID(const char *UUIDString, VolumeUUID *volumeID)
                        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;
@@ -1940,7 +2502,7 @@ int OpenVolumeStatusDB(VolumeStatusDBHandle *DBHandlePtr) {
        dbstateptr = (VSDBStatePtr)malloc(sizeof(*dbstateptr));
        if (dbstateptr == NULL) {
                return ENOMEM;
-       };
+       }
        
        dbstateptr->dbmode = O_RDWR;
        dbstateptr->dbfile = open(gVSDBPath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
@@ -1953,8 +2515,8 @@ int OpenVolumeStatusDB(VolumeStatusDBHandle *DBHandlePtr) {
                dbstateptr->dbfile = open(gVSDBPath, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
                if (dbstateptr->dbfile == -1) {
                        return errno;
-               };
-       };
+               }
+       }
        
        dbstateptr->signature = DBHANDLESIGNATURE;
        *DBHandlePtr = (VolumeStatusDBHandle)dbstateptr;
@@ -1974,7 +2536,7 @@ int GetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID,
        
        if ((result = FindVolumeRecordByUUID(dbstateptr, volumeID, &dbentry, 0)) != 0) {
                goto ErrExit;
-       };
+       }
        *VolumeStatus = VOLUME_RECORDED | ConvertHexStringToULong(dbentry.record.statusFlags, sizeof(dbentry.record.statusFlags));
        
        result = 0;
@@ -2009,7 +2571,7 @@ int SetVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeID,
                result = AddVolumeRecord(dbstateptr, &dbentry);
        } else {
                goto ErrExit;
-       };
+       }
        
        fsync(dbstateptr->dbfile);
        
@@ -2051,7 +2613,7 @@ int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeI
                        iobuffersize = dbinfo.st_size - dbstateptr->recordPosition - sizeof(struct VSDBEntry);
                } else {
                        iobuffersize = MAXIOMALLOC;
-               };
+               }
 #if DEBUG_TRACE
                fprintf(stderr, "DeleteLocalVolumeUUID: DB size = 0x%08lx; recordPosition = 0x%08lx;\n", 
                                                        (unsigned long)dbinfo.st_size, (unsigned long)dbstateptr->recordPosition);
@@ -2062,7 +2624,7 @@ int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeI
                        if (iobuffer == NULL) {
                                result = ENOMEM;
                                goto ErrExit;
-                       };
+                       }
                        
                        dataoffset = dbstateptr->recordPosition + sizeof(struct VSDBEntry);
                        do {
@@ -2078,7 +2640,7 @@ int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeI
                                        if (bytestransferred != iotransfersize) {
                                                result = errno;
                                                goto ErrExit;
-                                       };
+                                       }
        
        #if DEBUG_TRACE
                                        fprintf(stderr, "DeleteLocalVolumeUUID: writing 0x%08lx bytes starting at 0x%08lx ...\n", iotransfersize, (unsigned long)(dataoffset - (off_t)sizeof(struct VSDBEntry)));
@@ -2088,23 +2650,23 @@ int DeleteVolumeStatusDBEntry(VolumeStatusDBHandle DBHandle, VolumeUUID *volumeI
                                        if (bytestransferred != iotransfersize) {
                                                result = errno;
                                                goto ErrExit;
-                                       };
+                                       }
                                        
                                        dataoffset += (off_t)iotransfersize;
-                               };
+                               }
                        } 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))));
 #endif
                if ((result = ftruncate(dbstateptr->dbfile, dbinfo.st_size - (off_t)(sizeof(struct VSDBEntry)))) != 0) {
                        goto ErrExit;
-               };
+               }
                
                fsync(dbstateptr->dbfile);
                
                result = 0;
-       };
+       }
 
 ErrExit:
        if (iobuffer) free(iobuffer);
@@ -2173,9 +2735,9 @@ static int FindVolumeRecordByUUID(VSDBStatePtr dbstateptr, VolumeUUID *volumeID,
                                fprintf(stderr, "FindVolumeRecordByUUID: copying %d. bytes from %08xl to %08l...\n", sizeof(*targetEntry), &dbentry, targetEntry);
 #endif
                                memcpy(targetEntry, &dbentry, sizeof(*targetEntry));
-                       };
+                       }
                        return 0;
-               };
+               }
        } while (result == 0);
        
        return -1;
@@ -2236,7 +2798,7 @@ static int GetVSDBEntry(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry) {
                (entry.space != DBBLANKSPACE) ||
                (entry.terminator != DBRECORDTERMINATOR)) {
                return -1;
-       };
+       }
        
 #if DEBUG_TRACE
        strncpy(id, entry.key.uuid, sizeof(entry.key.uuid));
@@ -2245,7 +2807,7 @@ static int GetVSDBEntry(VSDBStatePtr dbstateptr, struct VSDBEntry *dbentry) {
 #endif
        memcpy(dbentry, &entry, sizeof(*dbentry));
        return 0;
-};
+}
 
 
 
@@ -2283,9 +2845,9 @@ static void FormatULong(unsigned long u, char *s) {
                        *digitptr++ = (char)(d + '0');
                } else {
                        *digitptr++ = (char)(d - 10 + 'A');
-               };
+               }
                u = u << 4;
-       };
+       }
 }
 
 
@@ -2294,7 +2856,7 @@ static void FormatUUID(VolumeUUID *volumeID, char *UUIDField) {
        FormatULong(volumeID->v.high, UUIDField);
        FormatULong(volumeID->v.low, UUIDField+8);
 
-};
+}
 
 
 
@@ -2340,191 +2902,9 @@ static unsigned long ConvertHexStringToULong(const char *hs, long maxdigits) {
                        nextdigit = c - 'a' + 10;
                } else {
                        nextdigit = 0;
-               };
+               }
                n = (n << 4) + nextdigit;
-       };
+       }
        
        return n;
 }
-
-
-
-/******************************************************************************
- *
- *  S H A - 1   I M P L E M E N T A T I O N   R O U T I N E S
- *
- *****************************************************************************/
-
-/*
-       Derived from SHA-1 in C
-       By Steve Reid <steve@edmweb.com>
-       100% Public Domain
-
-       Test Vectors (from FIPS PUB 180-1)
-               "abc"
-                       A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-               "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-                       84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-               A million repetitions of "a"
-                       34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-*/
-
-/* #define LITTLE_ENDIAN * This should be #define'd if true. */
-/* #define SHA1HANDSOFF * Copies data before messing with it. */
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from SSLeay */
-#ifdef LITTLE_ENDIAN
-#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
-    |(rol(block->l[i],8)&0x00FF00FF))
-#else
-#define blk0(i) block->l[i]
-#endif
-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
-    ^block->l[(i+2)&15]^block->l[i&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#if TRACE_HASH
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);printf("t = %2d: %08lX %08lX %08lX %08lX %08lX\n", i, a, b, c, d, e);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);printf("t = %2d: %08lX %08lX %08lX %08lX %08lX\n", i, a, b, c, d, e);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);printf("t = %2d: %08lX %08lX %08lX %08lX %08lX\n", i, a, b, c, d, e);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);printf("t = %2d: %08lX %08lX %08lX %08lX %08lX\n", i, a, b, c, d, e);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);printf("t = %2d: %08lX %08lX %08lX %08lX %08lX\n", i, a, b, c, d, e);
-#else
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-#endif
-
-
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-
-static void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
-{
-unsigned long a, b, c, d, e;
-typedef union {
-    unsigned char c[64];
-    unsigned long l[16];
-} CHAR64LONG16;
-CHAR64LONG16* block;
-#ifdef SHA1HANDSOFF
-static unsigned char workspace[64];
-    block = (CHAR64LONG16*)workspace;
-    memcpy(block, buffer, 64);
-#else
-    block = (CHAR64LONG16*)buffer;
-#endif
-    /* Copy context->state[] to working vars */
-    a = state[0];
-    b = state[1];
-    c = state[2];
-    d = state[3];
-    e = state[4];
-#if TRACE_HASH
-    printf("            A        B        C        D        E\n");
-    printf("        -------- -------- -------- -------- --------\n");
-    printf("        %08lX %08lX %08lX %08lX %08lX\n", a, b, c, d, e);
-#endif
-    /* 4 rounds of 20 operations each. Loop unrolled. */
-    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
-    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
-    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
-    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
-    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
-    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
-    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
-    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
-    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
-    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
-    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
-    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
-    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
-    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-    /* Add the working vars back into context.state[] */
-    state[0] += a;
-    state[1] += b;
-    state[2] += c;
-    state[3] += d;
-    state[4] += e;
-    /* Wipe variables */
-    a = b = c = d = e = 0;
-}
-
-
-/* SHA1Init - Initialize new context */
-
-static void SHA1Init(SHA1_CTX* context)
-{
-    /* SHA1 initialization constants */
-    context->state[0] = 0x67452301;
-    context->state[1] = 0xEFCDAB89;
-    context->state[2] = 0x98BADCFE;
-    context->state[3] = 0x10325476;
-    context->state[4] = 0xC3D2E1F0;
-    context->count[0] = context->count[1] = 0;
-}
-
-
-/* Run your data through this. */
-
-static void SHA1Update(SHA1_CTX* context, void* data, size_t len)
-{
-       unsigned char *dataptr = (char *)data;
-       unsigned int i, j;
-
-    j = (context->count[0] >> 3) & 63;
-    if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
-    context->count[1] += (len >> 29);
-    if ((j + len) > 63) {
-        memcpy(&context->buffer[j], dataptr, (i = 64-j));
-        SHA1Transform(context->state, context->buffer);
-        for ( ; i + 63 < len; i += 64) {
-            SHA1Transform(context->state, &dataptr[i]);
-        }
-        j = 0;
-    }
-    else i = 0;
-    memcpy(&context->buffer[j], &dataptr[i], len - i);
-}
-
-
-/* Add padding and return the message digest. */
-
-static void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
-{
-unsigned long i, j;
-unsigned char finalcount[8];
-
-    for (i = 0; i < 8; i++) {
-        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
-         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
-    }
-    SHA1Update(context, (unsigned char *)"\200", 1);
-    while ((context->count[0] & 504) != 448) {
-        SHA1Update(context, (unsigned char *)"\0", 1);
-    }
-    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
-    for (i = 0; i < 20; i++) {
-        digest[i] = (unsigned char)
-         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
-    }
-    /* Wipe variables */
-    i = j = 0;
-    memset(context->buffer, 0, 64);
-    memset(context->state, 0, 20);
-    memset(context->count, 0, 8);
-    memset(&finalcount, 0, 8);
-#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
-    SHA1Transform(context->state, context->buffer);
-#endif
-}