<key>CFBundlePackageType</key>
<string>fs </string>
<key>CFBundleShortVersionString</key>
- <string>1.3.1</string>
+ <string>1.4</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.3.1</string>
+ <string>1.4</string>
<key>FSMediaTypes</key>
<dict>
+ <key>48465300-0000-11AA-AA11-00306543ECAC</key>
+ <dict>
+ <key>FSMediaProperties</key>
+ <dict>
+ <key>Content Hint</key>
+ <string>48465300-0000-11AA-AA11-00306543ECAC</string>
+ <key>Leaf</key>
+ <true/>
+ </dict>
+ <key>FSProbeArguments</key>
+ <string>-p</string>
+ <key>FSProbeExecutable</key>
+ <string>../../hfs.util</string>
+ <key>FSProbeOrder</key>
+ <integer>1000</integer>
+ </dict>
<key>Apple_HFS</key>
<dict>
<key>FSMediaProperties</key>
<key>FSProbeOrder</key>
<integer>1000</integer>
</dict>
- <key>Apple_HFSX</key>
- <dict>
- <key>FSMediaProperties</key>
- <dict>
- <key>Content Hint</key>
- <string>Apple_HFSX</string>
- <key>Leaf</key>
- <true/>
- </dict>
- <key>FSProbeArguments</key>
- <string>-p</string>
- <key>FSProbeExecutable</key>
- <string>../../hfs.util</string>
- <key>FSProbeOrder</key>
- <integer>1000</integer>
- </dict>
- <key>CD</key>
+ <key>Apple_HFSX</key>
+ <dict>
+ <key>FSMediaProperties</key>
+ <dict>
+ <key>Content Hint</key>
+ <string>Apple_HFSX</string>
+ <key>Leaf</key>
+ <true/>
+ </dict>
+ <key>FSProbeArguments</key>
+ <string>-p</string>
+ <key>FSProbeExecutable</key>
+ <string>../../hfs.util</string>
+ <key>FSProbeOrder</key>
+ <integer>1000</integer>
+ </dict>
+ <key>CD_ROM_Mode_1</key>
<dict>
<key>FSMediaProperties</key>
<dict>
<key>FSProbeOrder</key>
<integer>2000</integer>
</dict>
- <key>Partitionless</key>
+ <key>Whole</key>
<dict>
<key>FSMediaProperties</key>
<dict>
<string>../../../../../../sbin/mount_hfs</string>
<key>FSName</key>
<string>Mac OS Standard</string>
+ <key>FSSubType</key>
+ <integer>128</integer>
<key>FSRepairArguments</key>
<string>-y</string>
<key>FSRepairExecutable</key>
<key>FSVerificationExecutable</key>
<string>../../../../../../sbin/fsck_hfs</string>
</dict>
+ <key>HFS+</key>
+ <dict>
+ <key>FSFormatArguments</key>
+ <string></string>
+ <key>FSFormatContentMask</key>
+ <string>Apple_HFS</string>
+ <key>FSFormatExecutable</key>
+ <string>../../../../../../sbin/newfs_hfs</string>
+ <key>FSFormatMinimumSize</key>
+ <integer>524288</integer>
+ <key>FSFormatMaximumSize</key>
+ <integer>9223372034707292160</integer>
+ <key>FSMountArguments</key>
+ <string></string>
+ <key>FSMountExecutable</key>
+ <string>../../../../../../sbin/mount_hfs</string>
+ <key>FSName</key>
+ <string>Mac OS Extended</string>
+ <key>FSSubType</key>
+ <integer>0</integer>
+ <key>FSRepairArguments</key>
+ <string>-y</string>
+ <key>FSRepairExecutable</key>
+ <string>../../../../../../sbin/fsck_hfs</string>
+ <key>FSVerificationArguments</key>
+ <string>-fn</string>
+ <key>FSVerificationExecutable</key>
+ <string>../../../../../../sbin/fsck_hfs</string>
+ </dict>
<key>Journaled HFS+</key>
<dict>
<key>FSFormatArguments</key>
<key>FSFormatMinimumSize</key>
<integer>4194304</integer>
<key>FSFormatMaximumSize</key>
- <integer>17592186040320</integer>
+ <integer>9223372034707292160</integer>
<key>FSMountArguments</key>
<string></string>
<key>FSMountExecutable</key>
<string>../../../../../../sbin/mount_hfs</string>
<key>FSName</key>
<string>Mac OS Extended (Journaled)</string>
+ <key>FSSubType</key>
+ <integer>1</integer>
<key>FSRepairArguments</key>
<string>-y</string>
<key>FSRepairExecutable</key>
<key>Case-sensitive HFS+</key>
<dict>
<key>FSFormatArguments</key>
- <string>-s -J</string>
+ <string>-s</string>
<key>FSFormatContentMask</key>
<string>Apple_HFSX</string>
<key>FSFormatExecutable</key>
<key>FSFormatMinimumSize</key>
<integer>4194304</integer>
<key>FSFormatMaximumSize</key>
- <integer>17592186040320</integer>
+ <integer>9223372034707292160</integer>
<key>FSMountArguments</key>
<string></string>
<key>FSMountExecutable</key>
<string>../../../../../../sbin/mount_hfs</string>
<key>FSName</key>
- <string>Mac OS Extended (Case-sensitive/Journaled)</string>
+ <string>Mac OS Extended (Case-sensitive)</string>
+ <key>FSSubType</key>
+ <integer>2</integer>
<key>FSRepairArguments</key>
<string>-y</string>
<key>FSRepairExecutable</key>
<string>../../../../../../sbin/fsck_hfs</string>
- <key>FSServerOnly</key>
- <true/>
<key>FSVerificationArguments</key>
<string>-fn</string>
<key>FSVerificationExecutable</key>
<string>../../../../../../sbin/fsck_hfs</string>
</dict>
- <key>HFS+</key>
+ <key>Case-sensitive Journaled HFS+</key>
<dict>
<key>FSFormatArguments</key>
- <string></string>
+ <string>-s -J</string>
<key>FSFormatContentMask</key>
- <string>Apple_HFS</string>
+ <string>Apple_HFSX</string>
<key>FSFormatExecutable</key>
<string>../../../../../../sbin/newfs_hfs</string>
<key>FSFormatMinimumSize</key>
- <integer>524288</integer>
+ <integer>4194304</integer>
<key>FSFormatMaximumSize</key>
- <integer>17592186040320</integer>
+ <integer>9223372034707292160</integer>
<key>FSMountArguments</key>
<string></string>
<key>FSMountExecutable</key>
<string>../../../../../../sbin/mount_hfs</string>
<key>FSName</key>
- <string>Mac OS Extended</string>
+ <string>Mac OS Extended (Case-sensitive, Journaled)</string>
+ <key>FSSubType</key>
+ <integer>3</integer>
<key>FSRepairArguments</key>
<string>-y</string>
<key>FSRepairExecutable</key>
<key>Case-sensitive HFS+</key>
<dict>
<key>FSName</key>
- <string>Mac OS Extended (Case-sensitive/Journaled)</string>
+ <string>Mac OS Extended (Case-sensitive)</string>
+ </dict>
+ <key>Case-sensitive Journaled HFS+</key>
+ <dict>
+ <key>FSName</key>
+ <string>Mac OS Extended (Case-sensitive, Journaled)</string>
</dict>
</dict>
</dict>
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
The
.Ar mountflags
referenced above are either:
-.Bl -bullet -indent
+.Bl -bullet -compact -offset indent
.It
.Ar removable
or
#include <sys/vmmeter.h>
#include <sys/mount.h>
#include <sys/wait.h>
+#include <sys/ioctl.h>
#include <sys/disk.h>
#include <sys/loadable_fs.h>
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 <sys/disk.h>
+#include <hfs/hfs_format.h>
+
+#include <machine/endian.h>
+
+#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";
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));
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",
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);
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);
//
/*
- * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
off_t offset;
u_int32_t nodeSize;
u_int32_t leafNode;
+ u_int32_t blockSize;
BTNodeDescriptor * bTreeNodeDescriptorPtr;
HFSPlusExtentDescriptor * extents;
size_t listsize;
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)
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
/* 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;
int sysdata;
char sysctlstring[128];
size_t datalen;
- struct loadavg sysloadavg;
+ double sysloadavg[3];
struct vmtotal sysvmtotal;
do {
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: */