]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfs_vfsutils.c
xnu-792.6.70.tar.gz
[apple/xnu.git] / bsd / hfs / hfs_vfsutils.c
index 4eed699c9223f227dbd622a98f4b71a0cdc0c1c8..4336e873279ae5d00d92ad1e8c793d881483a57f 100644 (file)
@@ -562,7 +562,7 @@ OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp,
        //
        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) {
@@ -604,9 +604,13 @@ OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp,
                } 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);
@@ -615,6 +619,10 @@ OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp,
                        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;
+               }
        }
 
        /*
@@ -1728,6 +1736,28 @@ hfs_early_journal_init(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp,
        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);
@@ -1915,6 +1945,28 @@ hfs_late_journal_init(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp, void *_a
        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);