-/*
- * To make the HFS Plus filesystem follow UFS unlink semantics, a remove
- * of an active vnode is translated to a move/rename so the file appears
- * deleted. The destination folder for these move/renames is setup here
- * and a reference to it is place in hfsmp->hfs_privdir_desc.
- */
-__private_extern__
-u_long
-FindMetaDataDirectory(ExtendedVCB *vcb)
-{
- struct hfsmount * hfsmp;
- struct vnode * dvp = NULL;
- struct cnode * dcp = NULL;
- struct FndrDirInfo * fndrinfo;
- struct cat_desc out_desc = {0};
- struct proc *p = current_proc();
- struct timeval tv;
- cat_cookie_t cookie;
- int lockflags;
- int error;
-
- if (vcb->vcbSigWord != kHFSPlusSigWord)
- return (0);
-
- hfsmp = VCBTOHFS(vcb);
-
- if (hfsmp->hfs_privdir_desc.cd_parentcnid == 0) {
- hfsmp->hfs_privdir_desc.cd_parentcnid = kRootDirID;
- hfsmp->hfs_privdir_desc.cd_nameptr = hfs_privdirname;
- hfsmp->hfs_privdir_desc.cd_namelen = strlen(hfs_privdirname);
- hfsmp->hfs_privdir_desc.cd_flags = CD_ISDIR;
- }
-
- lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_SHARED_LOCK);
-
- error = cat_lookup(hfsmp, &hfsmp->hfs_privdir_desc, 0, NULL,
- &hfsmp->hfs_privdir_attr, NULL, NULL);
-
- hfs_systemfile_unlock(hfsmp, lockflags);
-
- if (error == 0) {
- hfsmp->hfs_metadata_createdate = hfsmp->hfs_privdir_attr.ca_itime;
- hfsmp->hfs_privdir_desc.cd_cnid = hfsmp->hfs_privdir_attr.ca_fileid;
- /*
- * Clear the system immutable flag if set...
- */
- if ((hfsmp->hfs_privdir_attr.ca_flags & SF_IMMUTABLE) &&
- (hfsmp->hfs_flags & HFS_READ_ONLY) == 0) {
- hfsmp->hfs_privdir_attr.ca_flags &= ~SF_IMMUTABLE;
-
- if ((error = hfs_start_transaction(hfsmp)) != 0) {
- return (hfsmp->hfs_privdir_attr.ca_fileid);
- }
-
- lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_SHARED_LOCK);
- (void) cat_update(hfsmp, &hfsmp->hfs_privdir_desc,
- &hfsmp->hfs_privdir_attr, NULL, NULL);
- hfs_systemfile_unlock(hfsmp, lockflags);
-
- hfs_end_transaction(hfsmp);
- }
- return (hfsmp->hfs_privdir_attr.ca_fileid);
-
- } else if (hfsmp->hfs_flags & HFS_READ_ONLY) {
-
- return (0);
- }
-
- /* Setup the default attributes */
- bzero(&hfsmp->hfs_privdir_attr, sizeof(struct cat_attr));
- hfsmp->hfs_privdir_attr.ca_mode = S_IFDIR;
- hfsmp->hfs_privdir_attr.ca_nlink = 2;
- hfsmp->hfs_privdir_attr.ca_itime = vcb->vcbCrDate;
- microtime(&tv);
- hfsmp->hfs_privdir_attr.ca_mtime = tv.tv_sec;
-
- /* hidden and off the desktop view */
- fndrinfo = (struct FndrDirInfo *)&hfsmp->hfs_privdir_attr.ca_finderinfo;
- fndrinfo->frLocation.v = SWAP_BE16 (22460);
- fndrinfo->frLocation.h = SWAP_BE16 (22460);
- fndrinfo->frFlags |= SWAP_BE16 (kIsInvisible + kNameLocked);
-
- if ((error = hfs_start_transaction(hfsmp)) != 0) {
- return (0);
- }
- /* Reserve some space in the Catalog file. */
- if (cat_preflight(hfsmp, CAT_CREATE, &cookie, p) != 0) {
- hfs_end_transaction(hfsmp);
-
- return (0);
- }
-
- lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_EXCLUSIVE_LOCK);
-
- error = cat_create(hfsmp, &hfsmp->hfs_privdir_desc,
- &hfsmp->hfs_privdir_attr, &out_desc);
-
- hfs_systemfile_unlock(hfsmp, lockflags);
-
- cat_postflight(hfsmp, &cookie, p);
-
- if (error) {
- hfs_volupdate(hfsmp, VOL_UPDATE, 0);
-
- hfs_end_transaction(hfsmp);
-
- return (0);
- }
-
- hfsmp->hfs_privdir_desc.cd_hint = out_desc.cd_hint;
- hfsmp->hfs_privdir_desc.cd_cnid = out_desc.cd_cnid;
- hfsmp->hfs_privdir_attr.ca_fileid = out_desc.cd_cnid;
- hfsmp->hfs_metadata_createdate = vcb->vcbCrDate;
-
- if (hfs_vget(hfsmp, kRootDirID, &dvp, 0) == 0) {
- dcp = VTOC(dvp);
- dcp->c_childhint = out_desc.cd_hint;
- dcp->c_nlink++;
- dcp->c_entries++;
- dcp->c_touch_chgtime = TRUE;
- dcp->c_touch_modtime = TRUE;
- (void) hfs_update(dvp, 0);
- hfs_unlock(dcp);
- vnode_put(dvp);
- }
- hfs_volupdate(hfsmp, VOL_MKDIR, 1);
- hfs_end_transaction(hfsmp);
-
- cat_releasedesc(&out_desc);
-
- return (out_desc.cd_cnid);
-}
-