]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfs_link.c
xnu-517.7.21.tar.gz
[apple/xnu.git] / bsd / hfs / hfs_link.c
index 97a36516cf4579d150d35c3b92326acfca74cede..97dfde7bbfd0328db1d8c0d05ed306a300e1720f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -113,6 +113,7 @@ hfs_makelink(struct hfsmount *hfsmp, struct cnode *cp, struct cnode *dcp,
        struct cat_desc to_desc;
        int newlink = 0;
        int retval;
+       cat_cookie_t cookie = {0};
 
 
        /* We don't allow link nodes in our Private Meta Data folder! */
@@ -122,10 +123,15 @@ hfs_makelink(struct hfsmount *hfsmp, struct cnode *cp, struct cnode *dcp,
        if (hfs_freeblks(hfsmp, 0) == 0)
                return (ENOSPC);
 
+       /* Reserve some space in the Catalog file. */
+       if ((retval = cat_preflight(hfsmp, (2 * CAT_CREATE)+ CAT_RENAME, &cookie, p))) {
+               return (retval);
+       }
+
        /* Lock catalog b-tree */
        retval = hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_EXCLUSIVE, p);
        if (retval) {
-           return retval;
+          goto out2;
        }
 
        /*
@@ -216,7 +222,8 @@ hfs_makelink(struct hfsmount *hfsmp, struct cnode *cp, struct cnode *dcp,
 out:
        /* Unlock catalog b-tree */
        (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_RELEASE, p);
-
+out2:
+       cat_postflight(hfsmp, &cookie, p);
        return (retval);
 }
 
@@ -232,6 +239,7 @@ out:
      IN struct componentname *cnp;
 
      */
+__private_extern__
 int
 hfs_link(ap)
        struct vop_link_args /* {
@@ -264,7 +272,7 @@ hfs_link(ap)
        if (VTOVCB(tdvp)->vcbSigWord != kHFSPlusSigWord)
                return err_link(ap);    /* hfs disks don't support hard links */
        
-       if (hfsmp->hfs_private_metadata_dir == 0)
+       if (hfsmp->hfs_privdir_desc.cd_cnid == 0)
                return err_link(ap);    /* no private metadata dir, no links possible */
 
        if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, p))) {
@@ -294,7 +302,9 @@ hfs_link(ap)
        if (hfsmp->jnl) {
            if (journal_start_transaction(hfsmp->jnl) != 0) {
                        hfs_global_shared_lock_release(hfsmp);
-                       return EINVAL;
+                       VOP_ABORTOP(tdvp, cnp);
+                       error = EINVAL;  /* cannot link to a special file */
+                       goto out1;
            }
        }
 
@@ -322,15 +332,25 @@ hfs_link(ap)
        }
 
        // XXXdbg - need to do this here as well because cp could have changed
-       error = VOP_UPDATE(vp, &tv, &tv, 1);
+       (void) VOP_UPDATE(vp, &tv, &tv, 1);
 
-       FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
 
        if (hfsmp->jnl) {
            journal_end_transaction(hfsmp->jnl);
        }
        hfs_global_shared_lock_release(hfsmp);
 
+       /* free the pathname buffer */
+       {
+               char *tmp = cnp->cn_pnbuf;
+               cnp->cn_pnbuf = NULL;
+               cnp->cn_flags &= ~HASBUF;
+               FREE_ZONE(tmp, cnp->cn_pnlen, M_NAMEI);
+       }
+       
+       HFS_KNOTE(vp, NOTE_LINK);
+       HFS_KNOTE(tdvp, NOTE_WRITE);
+
 out1:
        if (tdvp != vp)
                VOP_UNLOCK(vp, 0, p);