]> git.saurik.com Git - apple/hfs.git/blobdiff - hfs_util/hfsutil_main.c
hfs-195.tar.gz
[apple/hfs.git] / hfs_util / hfsutil_main.c
index b39cbc3a1e21698233819d739f23a95a808abb46..8bb4e84cf17cd5808c98e631c6279376b70d928d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #define FSUC_UNJNL_RAW 'N'
 #endif
 
+#ifndef FSUC_JNLINFS_RAW
+#define FSUC_JNLINFS_RAW 'e'
+#endif
+
+#ifndef FSUC_EXTJNL_RAW
+#define FSUC_EXTJNL_RAW 'E'
+#endif
+
 #ifndef FSUC_JNLINFO
 #define FSUC_JNLINFO 'I'
 #endif
@@ -149,17 +157,17 @@ int gJournalSize = 0;
 
 
 struct FinderAttrBuf {
-       unsigned long info_length;
-       unsigned long finderinfo[8];
+       u_int32_t info_length;
+       u_int32_t finderinfo[8];
 };
 
 
 #define VOLUMEUUIDVALUESIZE 2
 typedef union VolumeUUID {
-       unsigned long value[VOLUMEUUIDVALUESIZE];
+       u_int32_t value[VOLUMEUUIDVALUESIZE];
        struct {
-               unsigned long high;
-               unsigned long low;
+               u_int32_t high;
+               u_int32_t low;
        } v;
 } VolumeUUID;
 
@@ -183,26 +191,28 @@ int CloseVolumeStatusDB(VolumeStatusDBHandle DBHandle);
 
 /* ************************************ P R O T O T Y P E S *************************************** */
 static void    DoDisplayUsage( const char * argv[] );
-static int     DoMount( char * theDeviceNamePtr, const char * theMountPointPtr, boolean_t isLocked, boolean_t isSetuid, boolean_t isDev );
+static int     DoMount( char * theDeviceNamePtr, const char *rawName, const char * theMountPointPtr, 
+                                       boolean_t isLocked, boolean_t isSetuid, boolean_t isDev );
 static int     DoProbe( char * rawDeviceNamePtr, char * blockDeviceNamePtr );
 static int     DoUnmount( const char * theMountPointPtr );
-static int     DoGetUUIDKey( const char * theDeviceNamePtr );
+static int     DoGetUUIDKey( const char * theDeviceNamePtr, const char *rawName );
 static int     DoChangeUUIDKey( const char * theDeviceNamePtr );
-static int     DoAdopt( const char * theDeviceNamePtr );
-static int     DoDisown( const char * theDeviceNamePtr );
+static int     DoAdopt( const char * theDeviceNamePtr, const char *rawName);
+static int     DoDisown( const char * theDeviceNamePtr, const char *rawName);
 
 extern int  DoMakeJournaled( const char * volNamePtr, int journalSize );  // XXXdbg
 extern int  DoUnJournal( const char * volNamePtr );      // XXXdbg
 extern int  DoGetJournalInfo( const char * volNamePtr );
 extern int  RawDisableJournaling( const char *devname );
+extern int  SetJournalInFSState( const char *devname, int journal_in_fs);
 
 static int     ParseArgs( int argc, const char * argv[], const char ** actionPtr, const char ** mountPointPtr, boolean_t * isEjectablePtr, boolean_t * isLockedPtr, boolean_t * isSetuidPtr, boolean_t * isDevPtr );
 
 static int     GetHFSMountPoint(const char *deviceNamePtr, char **pathPtr);
 static int     ReadHeaderBlock(int fd, void *bufptr, off_t *startOffset, VolumeUUID **finderInfoUUIDPtr);
-static int     GetVolumeUUIDRaw(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr);
+static int     GetVolumeUUIDRaw(const char *deviceNamePtr, const char *rawName, VolumeUUID *volumeUUIDPtr);
 static int     GetVolumeUUIDAttr(const char *path, VolumeUUID *volumeUUIDPtr);
-static int     GetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr, boolean_t generate);
+static int     GetVolumeUUID(const char *deviceNamePtr, const char *rawName, 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);
@@ -244,8 +254,8 @@ static unsigned int __CFStringGetDefaultEncodingForHFSUtil() {
         char buffer[MAXPATHLEN + 1];
         int fd;
 
-        strcpy(buffer, passwdp->pw_dir);
-        strcat(buffer, __kCFUserEncodingFileName);
+        strlcpy(buffer, passwdp->pw_dir, sizeof(buffer));
+        strlcat(buffer, __kCFUserEncodingFileName, sizeof(buffer));
 
         if ((fd = open(buffer, O_RDONLY, 0)) > 0) {
             size_t readSize;
@@ -341,7 +351,7 @@ static int load_encoding(CFStringEncoding encoding)
                return FSUR_LOADERR;
        }
        
-       sprintf(kmodfile, "%sHFS_Mac%s.kext", ENCODING_MODULE_PATH, encodingName);
+       snprintf(kmodfile, sizeof(kmodfile), "%sHFS_Mac%s.kext", ENCODING_MODULE_PATH, encodingName);
        if (stat(kmodfile, &sb) == -1)
        {
                /* We recognized the encoding, but couldn't find the KEXT */
@@ -407,8 +417,8 @@ int main (int argc, const char *argv[])
     --   "/dev/disk0s2"
     */
 
-    sprintf(rawDeviceName, "/dev/r%s", argv[2]);
-    sprintf(blockDeviceName, "/dev/%s", argv[2]);
+    snprintf(rawDeviceName, sizeof(rawDeviceName), "/dev/r%s", argv[2]);
+    snprintf(blockDeviceName, sizeof(blockDeviceName), "/dev/%s", argv[2]);
 
     /* call the appropriate routine to handle the given action argument after becoming root */
 
@@ -419,25 +429,25 @@ int main (int argc, const char *argv[])
 
         case FSUC_MOUNT:
         case FSUC_MOUNT_FORCE:
-            result = DoMount(blockDeviceName, mountPointPtr, isLocked, isSetuid, isDev);
+            result = DoMount(blockDeviceName, rawDeviceName, mountPointPtr, isLocked, isSetuid, isDev);
             break;
 
         case FSUC_UNMOUNT:
             result = DoUnmount( mountPointPtr );
             break;
                case FSUC_GETUUID:
-                       result = DoGetUUIDKey( blockDeviceName );
+                       result = DoGetUUIDKey( blockDeviceName, rawDeviceName);
                        break;
                
                case FSUC_SETUUID:
                        result = DoChangeUUIDKey( blockDeviceName );
                        break;
                case FSUC_ADOPT:
-                       result = DoAdopt( blockDeviceName );
+                       result = DoAdopt( blockDeviceName, rawDeviceName);
                        break;
                
                case FSUC_DISOWN:
-                       result = DoDisown( blockDeviceName );
+                       result = DoDisown( blockDeviceName, rawDeviceName );
                        break;
 
                case FSUC_MKJNL:
@@ -456,6 +466,19 @@ int main (int argc, const char *argv[])
                        result = RawDisableJournaling( argv[2] );
                        break;
                        
+               case FSUC_JNLINFS_RAW:
+                       // argv[2] has the device for the external journal.  however
+                       // we don't need it so we ignore it and just pass argv[3]
+                       // which is the hfs volume whose state we're going to change
+                       //
+                       result = SetJournalInFSState( argv[3], 1 );
+                       break;
+                       
+               case FSUC_EXTJNL_RAW:
+                       // see the comment for FSUC_JNLINFS_RAW
+                       result = SetJournalInFSState( argv[3], 0 );
+                       break;
+                       
                case FSUC_JNLINFO:
                        result = DoGetJournalInfo( argv[2] );
                        break;
@@ -487,7 +510,8 @@ Output -
 returns FSUR_IO_SUCCESS everything is cool else one of several other FSUR_xyz error codes.
 *********************************************************************** */
 static int
-DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, boolean_t isSetuid, boolean_t isDev)
+DoMount(char *deviceNamePtr, const char *rawName, const char *mountPointPtr,
+               boolean_t isLocked, boolean_t isSetuid, boolean_t isDev)
 {
        int pid;
         char *isLockedstr;
@@ -507,7 +531,7 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, bool
 
        /* get the volume UUID to check if permissions should be used: */
        targetVolumeStatus = 0;
-       if (((result = GetVolumeUUID(deviceNamePtr, &targetVolumeUUID, FALSE)) != FSUR_IO_SUCCESS) ||
+       if (((result = GetVolumeUUID(deviceNamePtr, rawName, &targetVolumeUUID, FALSE)) != FSUR_IO_SUCCESS) ||
                (targetVolumeUUID.v.high ==0) ||
                (targetVolumeUUID.v.low == 0)) {
 #if TRACE_HFS_UTIL
@@ -515,7 +539,7 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, bool
 #endif
 #if AUTO_ADOPT_FIXED
                if (gIsEjectable == 0) {
-                       result = DoAdopt( deviceNamePtr );
+                       result = DoAdopt( deviceNamePtr, rawName);
 #if TRACE_HFS_UTIL
                        fprintf(stderr, "hfs.util: DoMount: Auto-adopting %s; result = %d.\n", deviceNamePtr, result);
 #endif
@@ -548,7 +572,7 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, bool
 #endif
 #if AUTO_ENTER_FIXED
                                if (gIsEjectable == 0) {
-                                       result = DoAdopt( deviceNamePtr );
+                                       result = DoAdopt( deviceNamePtr, rawName );
 #if TRACE_HFS_UTIL
                                        fprintf(stderr, "hfs.util: DoMount: Auto-adopting %s; result = %d.\n", deviceNamePtr, result);
 #endif
@@ -583,7 +607,7 @@ DoMount(char *deviceNamePtr, const char *mountPointPtr, boolean_t isLocked, bool
 #else
                encoding = CFStringGetSystemEncoding();
 #endif
-               sprintf(encodeopt, "-e=%d", (int)encoding);
+               snprintf(encodeopt, sizeof(encodeopt), "-e=%d", (int)encoding);
 #if TRACE_HFS_UTIL
                fprintf(stderr, "hfs.util: %s %s -o -x -o %s -o %s -o -u=unknown,-g=unknown,-m=0777 -t %s %s %s ...\n",
                                                        gMountCommand, isLockedstr, encodeopt, permissionsOption, gHFS_FS_NAME, deviceNamePtr, mountPointPtr);
@@ -788,6 +812,10 @@ DoProbe(char *rawDeviceNamePtr, char *blockDeviceNamePtr)
 
                cfstr = CFStringCreateWithPascalString(kCFAllocatorDefault,
                            mdbPtr->drVN, encoding);
+               if (cfstr == NULL) {
+                       result = FSUR_INVAL;
+                       goto Return;
+               }
                cfOK = _CFStringGetFileSystemRepresentation(cfstr, volnameUTF8, NAME_MAX);
                CFRelease(cfstr);
 
@@ -834,14 +862,6 @@ DoProbe(char *rawDeviceNamePtr, char *blockDeviceNamePtr)
        }
 
        if (FSUR_IO_SUCCESS == result) {
-               unsigned char *s;
-               
-               /* Change slashes to colons in the volume name */
-               for (s=volnameUTF8; *s; ++s) {
-                       if (*s == '/')
-                               *s = ':';
-               }
-
                /* Print the volume name to standard output */
                write(1, volnameUTF8, strlen((char *)volnameUTF8));
                result = FSUR_RECOGNIZED;
@@ -893,7 +913,7 @@ Output -
     returns FSUR_IO_SUCCESS or else one of the FSUR_xyz error codes.
 *************************************************************************************************** */
 static int
-DoGetUUIDKey( const char * theDeviceNamePtr ) {
+DoGetUUIDKey( const char * theDeviceNamePtr, const char *rawName) {
        int result;
        VolumeUUID targetVolumeUUID;
        uuid_t uuid;
@@ -901,7 +921,7 @@ DoGetUUIDKey( const char * theDeviceNamePtr ) {
 
        unsigned char rawUUID[8];
 
-       if ((result = GetVolumeUUID(theDeviceNamePtr, &targetVolumeUUID, FALSE)) != FSUR_IO_SUCCESS) goto Err_Exit;
+       if ((result = GetVolumeUUID(theDeviceNamePtr, rawName, &targetVolumeUUID, FALSE)) != FSUR_IO_SUCCESS) goto Err_Exit;
 
        ((uint32_t *)rawUUID)[0] = OSSwapHostToBigInt32(targetVolumeUUID.v.high);
        ((uint32_t *)rawUUID)[1] = OSSwapHostToBigInt32(targetVolumeUUID.v.low);
@@ -947,13 +967,13 @@ Output -
     returns FSUR_IO_SUCCESS or else one of the FSUR_xyz error codes.
 *************************************************************************************************** */
 static int
-DoAdopt( const char * theDeviceNamePtr ) {
+DoAdopt( const char * theDeviceNamePtr, const char *rawName) {
        int result, closeresult;
        VolumeUUID targetVolumeUUID;
        VolumeStatusDBHandle vsdbhandle = NULL;
        unsigned long targetVolumeStatus;
        
-       if ((result = GetVolumeUUID(theDeviceNamePtr, &targetVolumeUUID, TRUE)) != FSUR_IO_SUCCESS) goto Err_Return;
+       if ((result = GetVolumeUUID(theDeviceNamePtr, rawName, &targetVolumeUUID, TRUE)) != FSUR_IO_SUCCESS) goto Err_Return;
        
        if ((result = OpenVolumeStatusDB(&vsdbhandle)) != 0) goto Err_Exit;
        if ((result = GetVolumeStatusDBEntry(vsdbhandle, &targetVolumeUUID, &targetVolumeStatus)) != 0) {
@@ -991,13 +1011,13 @@ Output -
     returns FSUR_IO_SUCCESS or else one of the FSUR_xyz error codes.
 *************************************************************************************************** */
 static int
-DoDisown( const char * theDeviceNamePtr ) {
+DoDisown( const char * theDeviceNamePtr, const char *rawName) {
        int result, closeresult;
        VolumeUUID targetVolumeUUID;
        VolumeStatusDBHandle vsdbhandle = NULL;
        unsigned long targetVolumeStatus;
        
-       if ((result = GetVolumeUUID(theDeviceNamePtr, &targetVolumeUUID, TRUE)) != FSUR_IO_SUCCESS) goto Err_Return;
+       if ((result = GetVolumeUUID(theDeviceNamePtr, rawName, &targetVolumeUUID, TRUE)) != FSUR_IO_SUCCESS) goto Err_Return;
        
        if ((result = OpenVolumeStatusDB(&vsdbhandle)) != 0) goto Err_Exit;
        if ((result = GetVolumeStatusDBEntry(vsdbhandle, &targetVolumeUUID, &targetVolumeStatus)) != 0) {
@@ -1173,6 +1193,16 @@ ParseArgs(int argc, const char *argv[], const char ** actionPtr,
                        doLengthCheck = 0;
                        break;
 
+               case FSUC_JNLINFS_RAW:
+                       index = 0;
+                       doLengthCheck = 0;
+                       break;
+
+               case FSUC_EXTJNL_RAW:
+                       index = 0;
+                       doLengthCheck = 0;
+                       break;
+
                case FSUC_JNLINFO:
                        index = 0;
                        doLengthCheck = 0;
@@ -1267,6 +1297,8 @@ DoDisplayUsage(const char *argv[])
        printf("       -%c (Make a file system journaled)\n", FSUC_MKJNL);
        printf("       -%c (Turn off journaling on a file system)\n", FSUC_UNJNL);
        printf("       -%c (Turn off journaling on a raw device)\n", FSUC_UNJNL_RAW);
+       printf("       -%c (Disable use of an external journal on a raw device)\n", FSUC_JNLINFS_RAW);
+       printf("       -%c (Enable the use of an external journal on a raw device)\n", FSUC_EXTJNL_RAW);
        printf("       -%c (Get size & location of journaling on a file system)\n", FSUC_JNLINFO);
     printf("device_arg:\n");
     printf("       device we are acting upon (for example, 'disk0s2')\n");
@@ -1403,13 +1435,14 @@ Err_Exit:
        Returns: FSUR_IO_SUCCESS, FSUR_IO_FAIL, FSUR_UNRECOGNIZED
 */
 static int
-GetVolumeUUIDRaw(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr)
+GetVolumeUUIDRaw(const char *deviceNamePtr, const char *rawName, VolumeUUID *volumeUUIDPtr)
 {
        int fd = 0;
        char * bufPtr;
        off_t startOffset;
        VolumeUUID *finderInfoUUIDPtr;
        int result;
+       int error; 
 
        bufPtr = (char *)malloc(HFS_BLOCK_SIZE);
        if ( ! bufPtr ) {
@@ -1419,11 +1452,25 @@ GetVolumeUUIDRaw(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr)
 
        fd = open( deviceNamePtr, O_RDONLY, 0);
        if (fd <= 0) {
+               error = errno;
 #if TRACE_HFS_UTIL
-               fprintf(stderr, "hfs.util: GetVolumeUUIDRaw: device open failed (errno = %d).\n", errno);
+               fprintf(stderr, "hfs.util: GetVolumeUUIDRaw: device (%s)  open failed (errno = %d).\n", deviceNamePtr, errno);
 #endif
-               result = FSUR_IO_FAIL;
-               goto Err_Exit;
+               if (error == EBUSY) {
+                       /* If it was busy, then retry, this time using the raw device */
+                       fd = open (rawName, O_RDONLY, 0);
+                       if (fd <= 0) {
+#if TRACE_HFS_UTIL
+                               fprintf(stderr, "hfs.util: GetVolumeUUIDRaw: device (%s) open failed (errno = %d).\n", rawName, errno);
+#endif
+                               result = FSUR_IO_FAIL;
+                               goto Err_Exit;
+                       }
+               }
+               else {
+                       result = FSUR_IO_FAIL;
+                       goto Err_Exit;
+               }
        }
 
        /*
@@ -1622,7 +1669,7 @@ Err_Exit:
  */
 
 static int
-GetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr, boolean_t generate)
+GetVolumeUUID(const char *deviceNamePtr, const char *rawName, VolumeUUID *volumeUUIDPtr, boolean_t generate)
 {
        int result;
        char *path = NULL;
@@ -1642,7 +1689,7 @@ GetVolumeUUID(const char *deviceNamePtr, VolumeUUID *volumeUUIDPtr, boolean_t ge
        if (path)
                result = GetVolumeUUIDAttr(path, volumeUUIDPtr);
        else
-               result = GetVolumeUUIDRaw(deviceNamePtr, volumeUUIDPtr);
+               result = GetVolumeUUIDRaw(deviceNamePtr, rawName, volumeUUIDPtr);
        if (result != FSUR_IO_SUCCESS)
                goto Err_Exit;
 
@@ -1874,6 +1921,16 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, unsigned c
             goto Return;
         }
 
+       if ((OSSwapBigToHostInt16(k->nodeName.length) >
+               (sizeof(k->nodeName.unicode) / sizeof(k->nodeName.unicode[0]))) ||
+               OSSwapBigToHostInt16(k->nodeName.length) > 255) {
+               result = FSUR_IO_FAIL;
+#if TRACE_HFS_UTIL
+               fprintf(stderr, "hfs.util: ERROR:  k->nodeName.length is a bad size (%d)\n", OSSwapBigToHostInt16(k->nodeName.length));
+#endif
+               goto Return;
+       }
+
        /* Extract the name of the root directory */
 
        {
@@ -1915,12 +1972,10 @@ Return:
 } /* GetNameFromHFSPlusVolumeStartingAt */
 
 
-#pragma options align=mac68k
 typedef struct {
        BTNodeDescriptor        node;
        BTHeaderRec             header;
-} HeaderRec, *HeaderPtr;
-#pragma options align=reset
+} __attribute__((aligned(2), packed)) HeaderRec, *HeaderPtr;
 
 /*
  --    
@@ -2531,10 +2586,10 @@ void GenerateVolumeUUID(VolumeUUID *newVolumeID) {
 void ConvertVolumeUUIDStringToUUID(const char *UUIDString, VolumeUUID *volumeID) {
        int i;
        char c;
-       unsigned long nextdigit;
-       unsigned long high = 0;
-       unsigned long low = 0;
-       unsigned long carry;
+       u_int32_t nextdigit;
+       u_int32_t high = 0;
+       u_int32_t low = 0;
+       u_int32_t carry;
        
        for (i = 0; (i < VOLUMEUUIDLENGTH) && ((c = UUIDString[i]) != (char)0) ; ++i) {
                if ((c >= '0') && (c <= '9')) {