}
result = cat_lookupbykey(hfsmp, keyp, 0, 0, outdescp, attrp, forkp, NULL);
+ if (!result && outdescp) {
+ cnid_t dcnid = outdescp->cd_cnid;
+ /*
+ * Just for sanity's sake, let's make sure that
+ * the key in the thread matches the key in the record.
+ */
+ if (cnid != dcnid) {
+ printf("Requested cnid (%d / 0x%08lx) != dcnid (%d / 0x%08lx)\n", cnid, cnid, dcnid, dcnid);
+ result = ENOENT;
+ }
+ }
+
exit:
FREE(recp, M_TEMP);
FREE(iterator, M_TEMP);
return (ENOENT);
fileID = GetEmbeddedFileID(descp->cd_nameptr, descp->cd_namelen, &prefixlen);
- if (fileID < kHFSFirstUserCatalogNodeID)
+
+ if (fileID < (cnid_t)kHFSFirstUserCatalogNodeID)
return (ENOENT);
+ if(fileID == hfsmp->hfs_privdir_desc.cd_cnid ||
+ fileID == hfsmp->hfs_jnlfileid ||
+ fileID == hfsmp->hfs_jnlinfoblkid) {
+ return (ENOENT);
+ }
+
result = cat_idlookup(hfsmp, fileID, outdescp, attrp, forkp);
if (result)
return (ENOENT);
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;
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) {
result = BTIterateRecords(fcb, op, iterator,
(IterateCallBackProcPtr)cat_packdirentry, &state);
+ /* If readdir is called for NFS and BTIterateRecords reaches the end of the
+ * Catalog BTree, call cat_packdirentry() with dummy values to copy previous
+ * direntry stored in state to the user buffer.
+ */
+ if (state.cbs_extended && (result == fsBTRecordNotFoundErr)) {
+ CatalogKey ckp;
+ CatalogRecord crp;
+
+ bzero(&ckp, sizeof(ckp));
+ bzero(&crp, sizeof(crp));
+
+ result = cat_packdirentry(&ckp, &crp, &state);
+ }
+
/* Note that state.cbs_index is still valid on errors */
*items = state.cbs_index - index;
index = state.cbs_index;