- if (ap->a_options & FSOPT_NOINMEMUPDATE) {
- /* vp okay to use instead of root vp */
- PackCatalogInfoAttributeBlock(alist, vp, &catInfo, &attrptr, &varptr);
- } else {
- /* Check to see if there's a vnode for this item in the cache: */
- entryvnode = hfs_vhashget(H_DEV(VTOH(vp)), catInfo.nodeData.cnd_nodeID, kDefault);
- if (entryvnode != NULL) {
- PackAttributeBlock(alist, entryvnode, &catInfo, &attrptr, &varptr);
- vput(entryvnode);
- } else {
- /* vp okay to use instead of root vp */
- PackCatalogInfoAttributeBlock(alist, vp, &catInfo, &attrptr, &varptr);
- };
- };
- currattrbufsize = *((u_long *)attrbufptr) = ((char *)varptr - (char *)attrbufptr);
+ /*
+ * Don't use data from cached vnodes when FSOPT_NOINMEMUPDATE
+ * option is active or if this entry is a hard link.
+ */
+ if ((ap->a_options & FSOPT_NOINMEMUPDATE)
+ || (catInfo.nodeData.cnd_iNodeNumCopy != 0)) {
+ /* vp okay to use instead of root vp */
+ PackCatalogInfoAttributeBlock(alist, vp, &catInfo, &attrptr, &varptr);
+ } else {
+ struct vnode *entry_vp = NULL;
+ struct vnode *rsrc_vp = NULL;
+ int nodetype;
+ UInt32 nodeid;
+
+ /*
+ * Flush out any in-memory state to the catalog record.
+ *
+ * In the HFS locking hierarchy, the data fork vnode must
+ * be acquired before the resource fork vnode.
+ */
+ nodeid = catInfo.nodeData.cnd_nodeID;
+ if (catInfo.nodeData.cnd_type == kCatalogFolderNode)
+ nodetype = kDirectory;
+ else
+ nodetype = kDataFork;
+
+ /* Check for this entry's cached vnode: */
+ entry_vp = hfs_vhashget(H_DEV(VTOH(vp)), nodeid, nodetype);
+
+ /* Also check for a cached resource fork vnode: */
+ if (nodetype == kDataFork) {
+ rsrc_vp = hfs_vhashget(H_DEV(VTOH(vp)), nodeid, kRsrcFork);
+ if ((rsrc_vp != NULL)
+ && (VTOH(rsrc_vp)->h_nodeflags & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE))) {
+ /* Pick up resource fork info */
+ CopyVNodeToCatalogNode(rsrc_vp, &catInfo.nodeData);
+ }
+ }
+
+ if (entry_vp != NULL)
+ PackAttributeBlock(alist, entry_vp, &catInfo, &attrptr, &varptr);
+ else if (rsrc_vp != NULL)
+ PackAttributeBlock(alist, rsrc_vp, &catInfo, &attrptr, &varptr);
+ else
+ PackCatalogInfoAttributeBlock(alist, vp, &catInfo, &attrptr, &varptr);
+
+ if (rsrc_vp)
+ vput(rsrc_vp);
+ if (entry_vp)
+ vput(entry_vp);
+ }
+ currattrbufsize = *((u_long *)attrbufptr) = ((char *)varptr - (char *)attrbufptr);