char iNodeName[32];
UInt32 hint;
UInt32 indlinkno;
+ UInt32 linkparid, linkcnid;
OSErr result;
fip = (struct FInfo *) &cndp->cnd_finderInfo;
/*
* Get nodeData from the data node file.
* Flag the node data to NOT copy the name (ie preserve the original)
+ * Also preserve the parent directory ID.
*/
+ linkparid = cndp->cnm_parID;
+ linkcnid = cndp->cnd_nodeID;
cndp->cnm_flags |= kCatNameNoCopyName;
result = GetCatalogNode(vcb, VCBTOHFS(vcb)->hfs_private_metadata_dir,
iNodeName, 0, 0, cndp, &hint);
/* Keep a copy of iNodeNum to put into h_indnodeno */
cndp->cnd_iNodeNumCopy = indlinkno;
+ cndp->cnm_parID = linkparid;
+ cndp->cnd_linkCNID = linkcnid;
}
}
}
*vpp = NULL;
return (EPERM);
}
- DBG_UTILS(("\thfs_vcreate: On '%s' with forktype of %d, nodeType of 0x%08lX\n", catInfo->nodeData.cnm_nameptr, forkType, (unsigned long)catInfo->nodeData.cnd_type));
-
+
+ /*
+ * If this is a hard link then check if the
+ * data node already exists in our hash.
+ */
+ if ((forkType == kDataFork)
+ && (catInfo->nodeData.cnd_type == kCatalogFileNode)
+ && ((catInfo->nodeData.cnd_mode & IFMT) == IFREG)
+ && (catInfo->nodeData.cnd_linkCount > 0)) {
+ vp = hfs_vhashget(dev, catInfo->nodeData.cnd_nodeID, kDataFork);
+ if (vp != NULL) {
+ /* Use the name of the link and it's parent ID. */
+ hp = VTOH(vp);
+ H_DIRID(hp) = catInfo->nodeData.cnm_parID;
+ hfs_set_metaname(catInfo->nodeData.cnm_nameptr, hp->h_meta, hfsmp);
+ *vpp = vp;
+ return (0);
+ }
+ }
+
/* Must malloc() here, since getnewvnode() can sleep */
MALLOC_ZONE(hp, struct hfsnode *, sizeof(struct hfsnode), M_HFSNODE, M_WAITOK);
bzero((caddr_t)hp, sizeof(struct hfsnode));
};
}
if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++ = root_vp->v_tag;
- if (a & ATTR_CMN_OBJID)
- {
- ((fsobj_id_t *)attrbufptr)->fid_objno = catalogInfo->nodeData.cnd_nodeID;
+ if (a & ATTR_CMN_OBJID) {
+ u_int32_t cnid;
+
+ /* For hard links use the link's cnid */
+ if (catalogInfo->nodeData.cnd_iNodeNumCopy != 0)
+ cnid = catalogInfo->nodeData.cnd_linkCNID;
+ else
+ cnid = catalogInfo->nodeData.cnd_nodeID;
+ ((fsobj_id_t *)attrbufptr)->fid_objno = cnid;
((fsobj_id_t *)attrbufptr)->fid_generation = 0;
++((fsobj_id_t *)attrbufptr);
};
- if (a & ATTR_CMN_OBJPERMANENTID)
- {
- ((fsobj_id_t *)attrbufptr)->fid_objno = catalogInfo->nodeData.cnd_nodeID;
+ if (a & ATTR_CMN_OBJPERMANENTID) {
+ u_int32_t cnid;
+
+ /* For hard links use the link's cnid */
+ if (catalogInfo->nodeData.cnd_iNodeNumCopy != 0)
+ cnid = catalogInfo->nodeData.cnd_linkCNID;
+ else
+ cnid = catalogInfo->nodeData.cnd_nodeID;
+ ((fsobj_id_t *)attrbufptr)->fid_objno = cnid;
((fsobj_id_t *)attrbufptr)->fid_generation = 0;
++((fsobj_id_t *)attrbufptr);
};
(char *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
++((struct attrreference *)attrbufptr);
};
- if (a & ATTR_CMN_FLAGS) {
- if (catalogInfo->nodeData.cnd_mode & IFMT) {
- if (catalogInfo->nodeData.cnd_flags & kHFSFileLockedMask) {
- *((u_long *)attrbufptr)++ =
- (u_long) (catalogInfo->nodeData.cnd_ownerFlags |
- (catalogInfo->nodeData.cnd_adminFlags << 16)) |
- UF_IMMUTABLE;
- } else {
- *((u_long *)attrbufptr)++ =
- (u_long) (catalogInfo->nodeData.cnd_ownerFlags |
- (catalogInfo->nodeData.cnd_adminFlags << 16)) & ~UF_IMMUTABLE;
- }
- } else {
- /* The information in the node flag fields is not valid: */
- *((u_long *)attrbufptr)++ =
- (catalogInfo->nodeData.cnd_flags & kHFSFileLockedMask) ? UF_IMMUTABLE : 0;
- };
- };
+ if (a & ATTR_CMN_FLAGS) {
+ u_long flags;
+
+ if (catalogInfo->nodeData.cnd_mode & IFMT)
+ flags = catalogInfo->nodeData.cnd_ownerFlags |
+ catalogInfo->nodeData.cnd_adminFlags << 16;
+ else
+ flags = 0;
+
+ if (catalogInfo->nodeData.cnd_type == kCatalogFileNode) {
+ if (catalogInfo->nodeData.cnd_flags & kHFSFileLockedMask)
+ flags |= UF_IMMUTABLE;
+ else
+ flags &= ~UF_IMMUTABLE;
+ };
+ *((u_long *)attrbufptr)++ = flags;
+ };
if (a & ATTR_CMN_USERACCESS) {
if ((VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) ||
((catalogInfo->nodeData.cnd_mode & IFMT) == 0)) {
if (a & ATTR_CMN_OBJTYPE) *((fsobj_type_t *)attrbufptr)++ = vp->v_type;
if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++ = vp->v_tag;
if (a & ATTR_CMN_OBJID) {
- ((fsobj_id_t *)attrbufptr)->fid_objno = H_FILEID(hp);
+ u_int32_t cnid;
+
+ /* For hard links use the link's cnid */
+ if (hp->h_meta->h_metaflags & IN_DATANODE)
+ cnid = catInfo->nodeData.cnd_linkCNID;
+ else
+ cnid = H_FILEID(hp);
+ ((fsobj_id_t *)attrbufptr)->fid_objno = cnid;
((fsobj_id_t *)attrbufptr)->fid_generation = 0;
++((fsobj_id_t *)attrbufptr);
};
if (a & ATTR_CMN_OBJPERMANENTID) {
- ((fsobj_id_t *)attrbufptr)->fid_objno = H_FILEID(hp);
+ u_int32_t cnid;
+
+ /* For hard links use the link's cnid */
+ if (hp->h_meta->h_metaflags & IN_DATANODE)
+ cnid = catInfo->nodeData.cnd_linkCNID;
+ else
+ cnid = H_FILEID(hp);
+ ((fsobj_id_t *)attrbufptr)->fid_objno = cnid;
((fsobj_id_t *)attrbufptr)->fid_generation = 0;
++((fsobj_id_t *)attrbufptr);
};