]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfs_catalog.c
xnu-792.13.8.tar.gz
[apple/xnu.git] / bsd / hfs / hfs_catalog.c
index fec7b0f145b8a2ef225eca45bc5269179169269a..038144ec85aa7ff62fc26c9776bff0a9eb4d1ea3 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
- * 
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
+ *
  * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
  * 
  * This file contains Original Code and/or Modifications of Original Code 
@@ -661,6 +661,9 @@ cat_lookupbykey(struct hfsmount *hfsmp, CatalogKey *keyp, u_long hint, int wantr
                        bcopy(&recp->hfsPlusFile.resourceFork.extents[0],
                              &forkp->cf_extents[0], sizeof(HFSPlusExtentRecord));
                } else {
+                       int i;
+                       u_int32_t validblks;
+
                        /* Convert the data fork. */
                        forkp->cf_size = recp->hfsPlusFile.dataFork.logicalSize;
                        forkp->cf_blocks = recp->hfsPlusFile.dataFork.totalBlocks;
@@ -675,6 +678,36 @@ cat_lookupbykey(struct hfsmount *hfsmp, CatalogKey *keyp, u_long hint, int wantr
                        forkp->cf_vblocks = 0;
                        bcopy(&recp->hfsPlusFile.dataFork.extents[0],
                              &forkp->cf_extents[0], sizeof(HFSPlusExtentRecord));
+
+                       /* Validate the fork's resident extents. */
+                       validblks = 0;
+                       for (i = 0; i < kHFSPlusExtentDensity; ++i) {
+                               if (forkp->cf_extents[i].startBlock + forkp->cf_extents[i].blockCount >= hfsmp->totalBlocks) {
+                                       /* Suppress any bad extents so a remove can succeed. */
+                                       forkp->cf_extents[i].startBlock = 0;
+                                       forkp->cf_extents[i].blockCount = 0;
+                                       /* Disable writes */
+                                       if (attrp != NULL) {
+                                               attrp->ca_mode &= S_IFMT | S_IRUSR | S_IRGRP | S_IROTH;
+                                       }
+                               } else {
+                                       validblks += forkp->cf_extents[i].blockCount;
+                               }
+                       }
+                       /* Adjust for any missing blocks. */
+                       if ((validblks < forkp->cf_blocks) && (forkp->cf_extents[7].blockCount == 0)) {
+                               u_int64_t psize;
+
+                               forkp->cf_blocks = validblks;
+                               if (attrp != NULL) {
+                                       attrp->ca_blocks = validblks + recp->hfsPlusFile.resourceFork.totalBlocks;
+                               }
+                               psize = (u_int64_t)validblks * (u_int64_t)hfsmp->blockSize;
+                               if (psize < forkp->cf_size) {
+                                       forkp->cf_size = psize;
+                               }
+
+                       }
                }
        }
        if (descp != NULL) {