From 16f263f531e537629ee6739e10ae05ffbb61fe2b Mon Sep 17 00:00:00 2001 From: Apple Date: Tue, 1 Feb 2005 00:20:44 +0000 Subject: [PATCH] hfs-154.tar.gz --- hfs_util/Info.plist | 115 ++++++++++++----- hfs_util/InfoPlist.strings | 7 +- hfs_util/hfs.util.8 | 4 +- hfs_util/hfsutil_jnl.c | 247 ++++++++++++++++++++++++++++++++++--- hfs_util/hfsutil_main.c | 18 +-- 5 files changed, 332 insertions(+), 59 deletions(-) diff --git a/hfs_util/Info.plist b/hfs_util/Info.plist index 5024f3d..cdbc0da 100644 --- a/hfs_util/Info.plist +++ b/hfs_util/Info.plist @@ -13,13 +13,29 @@ CFBundlePackageType fs CFBundleShortVersionString - 1.3.1 + 1.4 CFBundleSignature ???? CFBundleVersion - 1.3.1 + 1.4 FSMediaTypes + 48465300-0000-11AA-AA11-00306543ECAC + + FSMediaProperties + + Content Hint + 48465300-0000-11AA-AA11-00306543ECAC + Leaf + + + FSProbeArguments + -p + FSProbeExecutable + ../../hfs.util + FSProbeOrder + 1000 + Apple_HFS FSMediaProperties @@ -36,23 +52,23 @@ FSProbeOrder 1000 - Apple_HFSX - - FSMediaProperties - - Content Hint - Apple_HFSX - Leaf - - - FSProbeArguments - -p - FSProbeExecutable - ../../hfs.util - FSProbeOrder - 1000 - - CD + Apple_HFSX + + FSMediaProperties + + Content Hint + Apple_HFSX + Leaf + + + FSProbeArguments + -p + FSProbeExecutable + ../../hfs.util + FSProbeOrder + 1000 + + CD_ROM_Mode_1 FSMediaProperties @@ -68,7 +84,7 @@ FSProbeOrder 2000 - Partitionless + Whole FSMediaProperties @@ -105,6 +121,8 @@ ../../../../../../sbin/mount_hfs FSName Mac OS Standard + FSSubType + 128 FSRepairArguments -y FSRepairExecutable @@ -114,6 +132,35 @@ FSVerificationExecutable ../../../../../../sbin/fsck_hfs + HFS+ + + FSFormatArguments + + FSFormatContentMask + Apple_HFS + FSFormatExecutable + ../../../../../../sbin/newfs_hfs + FSFormatMinimumSize + 524288 + FSFormatMaximumSize + 9223372034707292160 + FSMountArguments + + FSMountExecutable + ../../../../../../sbin/mount_hfs + FSName + Mac OS Extended + FSSubType + 0 + FSRepairArguments + -y + FSRepairExecutable + ../../../../../../sbin/fsck_hfs + FSVerificationArguments + -fn + FSVerificationExecutable + ../../../../../../sbin/fsck_hfs + Journaled HFS+ FSFormatArguments @@ -125,13 +172,15 @@ FSFormatMinimumSize 4194304 FSFormatMaximumSize - 17592186040320 + 9223372034707292160 FSMountArguments FSMountExecutable ../../../../../../sbin/mount_hfs FSName Mac OS Extended (Journaled) + FSSubType + 1 FSRepairArguments -y FSRepairExecutable @@ -144,7 +193,7 @@ Case-sensitive HFS+ FSFormatArguments - -s -J + -s FSFormatContentMask Apple_HFSX FSFormatExecutable @@ -152,42 +201,44 @@ FSFormatMinimumSize 4194304 FSFormatMaximumSize - 17592186040320 + 9223372034707292160 FSMountArguments FSMountExecutable ../../../../../../sbin/mount_hfs FSName - Mac OS Extended (Case-sensitive/Journaled) + Mac OS Extended (Case-sensitive) + FSSubType + 2 FSRepairArguments -y FSRepairExecutable ../../../../../../sbin/fsck_hfs - FSServerOnly - FSVerificationArguments -fn FSVerificationExecutable ../../../../../../sbin/fsck_hfs - HFS+ + Case-sensitive Journaled HFS+ FSFormatArguments - + -s -J FSFormatContentMask - Apple_HFS + Apple_HFSX FSFormatExecutable ../../../../../../sbin/newfs_hfs FSFormatMinimumSize - 524288 + 4194304 FSFormatMaximumSize - 17592186040320 + 9223372034707292160 FSMountArguments FSMountExecutable ../../../../../../sbin/mount_hfs FSName - Mac OS Extended + Mac OS Extended (Case-sensitive, Journaled) + FSSubType + 3 FSRepairArguments -y FSRepairExecutable diff --git a/hfs_util/InfoPlist.strings b/hfs_util/InfoPlist.strings index ccbb86e..d96c886 100644 --- a/hfs_util/InfoPlist.strings +++ b/hfs_util/InfoPlist.strings @@ -24,7 +24,12 @@ Case-sensitive HFS+ FSName - Mac OS Extended (Case-sensitive/Journaled) + Mac OS Extended (Case-sensitive) + + Case-sensitive Journaled HFS+ + + FSName + Mac OS Extended (Case-sensitive, Journaled) diff --git a/hfs_util/hfs.util.8 b/hfs_util/hfs.util.8 index fa39fed..dd6ab4c 100644 --- a/hfs_util/hfs.util.8 +++ b/hfs_util/hfs.util.8 @@ -57,7 +57,7 @@ The command supports the mounting, probing, and unmounting of HFS file systems. .Pp Options: -.Bl -tag -width -indent "a" +.Bl -tag -compact -offset indent .It Fl a Adopt permissions for the HFS file system at .Ar device @@ -108,7 +108,7 @@ Disable journaling on the HFS file system mounted on The .Ar mountflags referenced above are either: -.Bl -bullet -indent +.Bl -bullet -compact -offset indent .It .Ar removable or diff --git a/hfs_util/hfsutil_jnl.c b/hfs_util/hfsutil_jnl.c index 931fb74..2a619e8 100644 --- a/hfs_util/hfsutil_jnl.c +++ b/hfs_util/hfsutil_jnl.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -120,28 +121,218 @@ int hide_file(const char * file) return (result == -1 ? errno : result); } -int -get_start_block(const char *file) +off_t +get_start_block(const char *file, uint32_t fs_block_size) { - struct attrlist alist = {0}; - ExtentsAttrBuf extentsbuf = {0}; + off_t cur_pos, phys_start, len; + int fd, err; + struct log2phys l2p; + struct stat st; - alist.bitmapcount = ATTR_BIT_MAP_COUNT; - alist.fileattr = ATTR_FILE_DATAEXTENTS; + fd = open(file, O_RDONLY); + if (fd < 0) { + return -1; + } - if (getattrlist(file, &alist, &extentsbuf, sizeof(extentsbuf), 0)) { - fprintf(stderr, "could not get attrlist for %s (%s)", file, strerror(errno)); + if (fstat(fd, &st) < 0) { + fprintf(stderr, "can't stat %s (%s)\n", file, strerror(errno)); + close(fd); return -1; } - if (extentsbuf.extents[1].startBlock != 0) { - fprintf(stderr, "Journal File not contiguous!\n"); + fs_block_size = st.st_blksize; // XXXdbg quick hack for now + + phys_start = len = 0; + for(cur_pos=0; cur_pos < st.st_size; cur_pos += fs_block_size) { + memset(&l2p, 0, sizeof(l2p)); + lseek(fd, cur_pos, SEEK_SET); + err = fcntl(fd, F_LOG2PHYS, &l2p); + + if (phys_start == 0) { + phys_start = l2p.l2p_devoffset; + len = fs_block_size; + } else if (l2p.l2p_devoffset != (phys_start + len)) { + // printf(" %lld : %lld - %lld\n", cur_pos, phys_start / fs_block_size, len / fs_block_size); + fprintf(stderr, "%s : is not contiguous!\n", file); + close(fd); + return -1; + // phys_start = l2p.l2p_devoffset; + // len = fs_block_size; + } else { + len += fs_block_size; + } + } + + close(fd); + + //printf("%s start offset %lld; byte len %lld (blksize %d)\n", + // file, phys_start, len, fs_block_size); + + if ((phys_start / (unsigned)fs_block_size) & 0xffffffff00000000LL) { + fprintf(stderr, "%s : starting block is > 32bits!\n", file); return -1; } + + return phys_start; +} + + +// +// Get the embedded offset (if any) for an hfs+ volume. +// This is pretty skanky that we have to do this but +// that's life... +// +#include +#include + +#include + +#define HFS_PRI_SECTOR(blksize) (1024 / (blksize)) +#define HFS_PRI_OFFSET(blksize) ((blksize) > 1024 ? 1024 : 0) + +#define SWAP_BE16(x) ntohs(x) +#define SWAP_BE32(x) ntohl(x) + + +off_t +get_embedded_offset(char *devname) +{ + int fd = -1; + off_t ret = 0; + char *buff = NULL, rawdev[256]; + u_int64_t blkcnt; + u_int32_t blksize; + HFSMasterDirectoryBlock *mdbp; + off_t embeddedOffset; + struct statfs sfs; + struct stat st; + + restart: + if (stat(devname, &st) != 0) { + fprintf(stderr, "Could not access %s (%s)\n", devname, strerror(errno)); + ret = -1; + goto out; + } + + if (S_ISCHR(st.st_mode) == 0) { + // hmmm, it's not the character special raw device so we + // should try to figure out the real device. + if (statfs(devname, &sfs) != 0) { + fprintf(stderr, "Can't find out any info about the fs for path %s (%s)\n", + devname, strerror(errno)); + ret = -1; + goto out; + } + + // copy the "/dev/" + strncpy(rawdev, sfs.f_mntfromname, 5); + rawdev[5] = 'r'; + strcpy(&rawdev[6], &sfs.f_mntfromname[5]); + devname = &rawdev[0]; + goto restart; + } + + fd = open(devname, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "can't open: %s (%s)\n", devname, strerror(errno)); + ret = -1; + goto out; + } + + /* Get the real physical block size. */ + if (ioctl(fd, DKIOCGETBLOCKSIZE, (caddr_t)&blksize) != 0) { + fprintf(stderr, "can't get the device block size (%s). assuming 512\n", strerror(errno)); + blksize = 512; + ret = -1; + goto out; + } + + /* Get the number of physical blocks. */ + if (ioctl(fd, DKIOCGETBLOCKCOUNT, (caddr_t)&blkcnt)) { + struct stat st; + fprintf(stderr, "failed to get block count. trying stat().\n"); + if (fstat(fd, &st) != 0) { + ret = -1; + goto out; + } + + blkcnt = st.st_size / blksize; + } + + /* + * There are only 31 bits worth of block count in + * the buffer cache. So for large volumes a 4K + * physical block size is needed. + */ + if (blksize == 512 && blkcnt > (u_int64_t)0x000000007fffffff) { + blksize = 4096; + } + + /* + * At this point: + * blksize has our prefered physical block size + * blkcnt has the total number of physical blocks + */ + + buff = (char *)malloc(blksize); + + if (pread(fd, buff, blksize, HFS_PRI_SECTOR(blksize)*blksize) != blksize) { + fprintf(stderr, "failed to read volume header @ offset %d (%s)\n", + HFS_PRI_SECTOR(blksize), strerror(errno)); + ret = -1; + goto out; + } + + mdbp = (HFSMasterDirectoryBlock *)buff; + if ( (SWAP_BE16(mdbp->drSigWord) != kHFSSigWord) + && (SWAP_BE16(mdbp->drSigWord) != kHFSPlusSigWord) + && (SWAP_BE16(mdbp->drSigWord) != kHFSXSigWord)) { + ret = -1; + goto out; + } + + if ((SWAP_BE16(mdbp->drSigWord) == kHFSSigWord) && (SWAP_BE16(mdbp->drEmbedSigWord) != kHFSPlusSigWord)) { + ret = -1; + goto out; + } else if (SWAP_BE16(mdbp->drEmbedSigWord) == kHFSPlusSigWord) { + /* Get the embedded Volume Header */ + embeddedOffset = SWAP_BE16(mdbp->drAlBlSt) * 512; + embeddedOffset += (u_int64_t)SWAP_BE16(mdbp->drEmbedExtent.startBlock) * + (u_int64_t)SWAP_BE32(mdbp->drAlBlkSiz); + + /* + * If the embedded volume doesn't start on a block + * boundary, then switch the device to a 512-byte + * block size so everything will line up on a block + * boundary. + */ + if ((embeddedOffset % blksize) != 0) { + fprintf(stderr, "HFS Mount: embedded volume offset not" + " a multiple of physical block size (%d);" + " switching to 512\n", blksize); + + blkcnt *= (blksize / 512); + blksize = 512; + } - return extentsbuf.extents[0].startBlock; + } else { /* pure HFS+ */ + embeddedOffset = 0; + } + + ret = embeddedOffset; + + out: + if (buff) { + free(buff); + } + if (fd >= 0) + close(fd); + + return ret; } + + static const char *journal_fname = ".journal"; static const char *jib_fname = ".journal_info_block"; @@ -152,10 +343,12 @@ DoMakeJournaled(char *volname, int jsize) char *buf; int ret; fstore_t fst; - int jstart_block, jinfo_block, sysctl_info[8]; + int32_t jstart_block, jinfo_block; + int sysctl_info[8]; JournalInfoBlock jib; struct statfs sfs; static char tmpname[MAXPATHLEN]; + off_t start_block, embedded_offset; if (statfs(volname, &sfs) != 0) { fprintf(stderr, "Can't stat volume %s (%s).\n", volname, strerror(errno)); @@ -202,6 +395,15 @@ DoMakeJournaled(char *volname, int jsize) return 10; } + + embedded_offset = get_embedded_offset(volname); + if (embedded_offset < 0) { + fprintf(stderr, "Can't calculate the embedded offset (if any) for %s.\n", volname); + fprintf(stderr, "Journal creation failure.\n"); + return 15; + } + // printf("Embedded offset == 0x%llx\n", embedded_offset); + fd = open(journal_fname, O_CREAT|O_TRUNC|O_RDWR, 000); if (fd < 0) { fprintf(stderr, "Can't create journal file on volume %s (%s)\n", @@ -270,9 +472,16 @@ DoMakeJournaled(char *volname, int jsize) close(fd); hide_file(journal_fname); - jstart_block = get_start_block(journal_fname); + start_block = get_start_block(journal_fname, block_size); + if (start_block == (off_t)-1) { + fprintf(stderr, "Failed to get start block for %s (%s)\n", + journal_fname, strerror(errno)); + unlink(journal_fname); + return 20; + } + jstart_block = (start_block / block_size) - (embedded_offset / block_size); - memset(&jib, 0, sizeof(jib)); + memset(&jib, 'Z', sizeof(jib)); jib.flags = kJIJournalInFSMask; jib.offset = (off_t)((unsigned)jstart_block) * (off_t)((unsigned)block_size); jib.size = (off_t)((unsigned)journal_size); @@ -308,7 +517,15 @@ DoMakeJournaled(char *volname, int jsize) close(fd); hide_file(jib_fname); - jinfo_block = get_start_block(jib_fname); + start_block = get_start_block(jib_fname, block_size); + if (start_block == (off_t)-1) { + fprintf(stderr, "Failed to get start block for %s (%s)\n", + jib_fname, strerror(errno)); + unlink(journal_fname); + unlink(jib_fname); + return 20; + } + jinfo_block = (start_block / block_size) - (embedded_offset / block_size); // diff --git a/hfs_util/hfsutil_main.c b/hfs_util/hfsutil_main.c index 0ee11c9..3d899f8 100644 --- a/hfs_util/hfsutil_main.c +++ b/hfs_util/hfsutil_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -1866,6 +1866,7 @@ GetCatalogOverflowExtents(int fd, off_t hfsPlusVolumeOffset, off_t offset; u_int32_t nodeSize; u_int32_t leafNode; + u_int32_t blockSize; BTNodeDescriptor * bTreeNodeDescriptorPtr; HFSPlusExtentDescriptor * extents; size_t listsize; @@ -1873,14 +1874,15 @@ GetCatalogOverflowExtents(int fd, off_t hfsPlusVolumeOffset, int i; int result; + blockSize = NXSwapBigLongToHost(volHdrPtr->blockSize); listsize = *catalogExtCount * sizeof(HFSPlusExtentDescriptor); extents = *catalogExtents; offset = (off_t)volHdrPtr->extentsFile.extents[0].startBlock * - (off_t)volHdrPtr->blockSize; + (off_t)blockSize; /* Read the header node of the extents B-Tree */ - result = GetBTreeNodeInfo(fd, hfsPlusVolumeOffset, volHdrPtr->blockSize, + result = GetBTreeNodeInfo(fd, hfsPlusVolumeOffset, blockSize, kHFSPlusExtentDensity, volHdrPtr->extentsFile.extents, &nodeSize, &leafNode); if (result != FSUR_IO_SUCCESS || leafNode == 0) @@ -1902,7 +1904,7 @@ GetCatalogOverflowExtents(int fd, off_t hfsPlusVolumeOffset, again: result = ReadFile(fd, bufPtr, offset, nodeSize, - hfsPlusVolumeOffset, volHdrPtr->blockSize, + hfsPlusVolumeOffset, blockSize, kHFSPlusExtentDensity, volHdrPtr->extentsFile.extents); if ( result == FSUR_IO_FAIL ) { #if TRACE_HFS_UTIL @@ -1939,7 +1941,7 @@ again: /* grow list and copy additional extents */ listsize += sizeof(HFSPlusExtentRecord); extents = (HFSPlusExtentDescriptor *) realloc(extents, listsize); - bcopy(p + k->keyLength + sizeof(u_int16_t), + bcopy(p + NXSwapBigShortToHost(k->keyLength) + sizeof(u_int16_t), &extents[*catalogExtCount], sizeof(HFSPlusExtentRecord)); *catalogExtCount += kHFSPlusExtentDensity; @@ -2326,7 +2328,7 @@ void GenerateVolumeUUID(VolumeUUID *newVolumeID) { int sysdata; char sysctlstring[128]; size_t datalen; - struct loadavg sysloadavg; + double sysloadavg[3]; struct vmtotal sysvmtotal; do { @@ -2375,10 +2377,8 @@ void GenerateVolumeUUID(VolumeUUID *newVolumeID) { SHA1_Update(&context, sysctlstring, datalen); /* The system's load average: */ - mib[0] = CTL_VM; - mib[1] = VM_LOADAVG; datalen = sizeof(sysloadavg); - sysctl(mib, 2, &sysloadavg, &datalen, NULL, 0); + getloadavg(sysloadavg, 3); SHA1_Update(&context, &sysloadavg, datalen); /* The system's VM statistics: */ -- 2.45.2