/*
* Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* Please see the License for the specific language governing rights and
* limitations under the License.
*
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/* @(#)hfs_vfsutils.c 4.0
*
hfs_unlock(VTOC(hfsmp->hfs_catalog_vp));
hfs_unlock(VTOC(hfsmp->hfs_extents_vp));
+ if (error == noErr)
+ {
+ error = cat_idlookup(hfsmp, kHFSRootFolderID, NULL, NULL, NULL);
+ }
+
if ( error == noErr )
{
if ( !(vcb->vcbAtrb & kHFSVolumeHardwareLockMask) ) // if the disk is not write protected
/* Pick up volume name and create date */
retval = cat_idlookup(hfsmp, kHFSRootFolderID, &cndesc, &cnattr, NULL);
if (retval) {
+ if (hfsmp->hfs_attribute_vp)
+ hfs_unlock(VTOC(hfsmp->hfs_attribute_vp));
hfs_unlock(VTOC(hfsmp->hfs_allocation_vp));
hfs_unlock(VTOC(hfsmp->hfs_catalog_vp));
hfs_unlock(VTOC(hfsmp->hfs_extents_vp));
//
if ( (vcb->vcbAtrb & kHFSVolumeJournaledMask)
&& (SWAP_BE32(vhp->lastMountedVersion) != kHFSJMountVersion)
- && (hfsmp->jnl == NULL)) {
+ && (hfsmp->jnl == NULL)) {
retval = hfs_late_journal_init(hfsmp, vhp, args);
if (retval != 0) {
} else if (hfsmp->jnl) {
vfs_setflags(hfsmp->hfs_mp, (uint64_t)((unsigned int)MNT_JOURNALED));
}
- } else if (hfsmp->jnl) {
+ } else if (hfsmp->jnl || ((vcb->vcbAtrb & kHFSVolumeJournaledMask) && (hfsmp->hfs_flags & HFS_READ_ONLY))) {
struct cat_attr jinfo_attr, jnl_attr;
+ if (hfsmp->hfs_flags & HFS_READ_ONLY) {
+ vcb->vcbAtrb &= ~kHFSVolumeJournaledMask;
+ }
+
// if we're here we need to fill in the fileid's for the
// journal and journal_info_block.
hfsmp->hfs_jnlinfoblkid = GetFileInfo(vcb, kRootDirID, ".journal_info_block", &jinfo_attr, NULL);
printf("hfs: danger! couldn't find the file-id's for the journal or journal_info_block\n");
printf("hfs: jnlfileid %d, jnlinfoblkid %d\n", hfsmp->hfs_jnlfileid, hfsmp->hfs_jnlinfoblkid);
}
+
+ if (hfsmp->hfs_flags & HFS_READ_ONLY) {
+ vcb->vcbAtrb |= kHFSVolumeJournaledMask;
+ }
}
/*
hfsmp->jnl_start = jibp->offset / SWAP_BE32(vhp->blockSize);
hfsmp->jnl_size = jibp->size;
+ if ((hfsmp->hfs_flags & HFS_READ_ONLY) && (vfs_flags(hfsmp->hfs_mp) & MNT_ROOTFS) == 0) {
+ // if the file system is read-only, check if the journal is empty.
+ // if it is, then we can allow the mount. otherwise we have to
+ // return failure.
+ retval = journal_is_clean(hfsmp->jvp,
+ jibp->offset + embeddedOffset,
+ jibp->size,
+ devvp,
+ hfsmp->hfs_phys_block_size);
+
+ hfsmp->jnl = NULL;
+
+ buf_brelse(jinfo_bp);
+
+ if (retval) {
+ printf("hfs: early journal init: volume on %s is read-only and journal is dirty. Can not mount volume.\n",
+ vnode_name(devvp));
+ }
+
+ return retval;
+ }
+
if (jibp->flags & kJIJournalNeedInitMask) {
printf("hfs: Initializing the journal (joffset 0x%llx sz 0x%llx)...\n",
jibp->offset + embeddedOffset, jibp->size);
hfsmp->jnl_start = jibp->offset / SWAP_BE32(vhp->blockSize);
hfsmp->jnl_size = jibp->size;
+ if ((hfsmp->hfs_flags & HFS_READ_ONLY) && (vfs_flags(hfsmp->hfs_mp) & MNT_ROOTFS) == 0) {
+ // if the file system is read-only, check if the journal is empty.
+ // if it is, then we can allow the mount. otherwise we have to
+ // return failure.
+ retval = journal_is_clean(hfsmp->jvp,
+ jibp->offset + (off_t)vcb->hfsPlusIOPosOffset,
+ jibp->size,
+ devvp,
+ hfsmp->hfs_phys_block_size);
+
+ hfsmp->jnl = NULL;
+
+ buf_brelse(jinfo_bp);
+
+ if (retval) {
+ printf("hfs: late journal init: volume on %s is read-only and journal is dirty. Can not mount volume.\n",
+ vnode_name(devvp));
+ }
+
+ return retval;
+ }
+
if (jibp->flags & kJIJournalNeedInitMask) {
printf("hfs: Initializing the journal (joffset 0x%llx sz 0x%llx)...\n",
jibp->offset + (off_t)vcb->hfsPlusIOPosOffset, jibp->size);