]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfs_attrlist.c
xnu-517.tar.gz
[apple/xnu.git] / bsd / hfs / hfs_attrlist.c
index b52bed88f931cd5260d0555629a35d3f3697c463..c73610c72e55d36d15b2ed781104b9091f4d0c76 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -45,9 +45,6 @@
 
 
 
-extern uid_t console_user;
-
-
 /* Routines that are shared by hfs_setattr: */
 extern int hfs_write_access(struct vnode *vp, struct ucred *cred,
                        struct proc *p, Boolean considerFlags);
@@ -71,22 +68,22 @@ extern void   hfs_relnamehint(struct cnode *dcp, int index);
 
 
 static void packvolcommonattr(struct attrblock *abp, struct hfsmount *hfsmp,
-                       struct vnode *vp);
+                       struct vnode *vp, struct proc *p);
 
 static void packvolattr(struct attrblock *abp, struct hfsmount *hfsmp,
-                       struct vnode *vp);
+                       struct vnode *vp, struct proc *p);
 
 static void packcommonattr(struct attrblock *abp, struct hfsmount *hfsmp,
                        struct vnode *vp, struct cat_desc * cdp,
-                       struct cat_attr * cap);
+                       struct cat_attr * cap, struct proc *p);
 
 static void packfileattr(struct attrblock *abp, struct hfsmount *hfsmp,
                        struct cat_attr *cattrp, struct cat_fork *datafork,
-                       struct cat_fork *rsrcfork);
+                       struct cat_fork *rsrcfork, struct proc *p);
 
 static void packdirattr(struct attrblock *abp, struct hfsmount *hfsmp,
                        struct vnode *vp, struct cat_desc * descp,
-                       struct cat_attr * cattrp);
+                       struct cat_attr * cattrp, struct proc *p);
 
 static void unpackattrblk(struct attrblock *abp, struct vnode *vp);
 
@@ -192,39 +189,34 @@ hfs_getattrlist(ap)
            (alist->commonattr & ATTR_CMN_OBJPERMANENTID) &&
            (VTOVCB(vp)->vcbSigWord != kHFSPlusSigWord)) {
 
-               if (VTOVFS(vp)->mnt_flag & MNT_RDONLY)
+               cat_cookie_t cookie = {0};
+
+               if (hfsmp->hfs_flags & HFS_READ_ONLY)
                        return (EROFS);
                if ((error = hfs_write_access(vp, ap->a_cred, ap->a_p, false)) != 0)
                        return (error);
 
-               // XXXdbg
-               hfs_global_shared_lock_acquire(hfsmp);
-               if (hfsmp->jnl) {
-                   if ((error = journal_start_transaction(hfsmp->jnl)) != 0) {
-                               hfs_global_shared_lock_release(hfsmp);
-                               return error;
-                   }
-               }
+               /*
+                * Reserve some space in the Catalog file.
+                */
+               error = cat_preflight(hfsmp, CAT_CREATE, &cookie, ap->a_p);
+               if (error)
+                       return (error);
 
                /* Lock catalog b-tree */
-               error = hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_SHARED, ap->a_p);
+               error = hfs_metafilelocking(hfsmp, kHFSCatalogFileID,
+                                           LK_EXCLUSIVE, ap->a_p);
                if (error) {
-                   if (hfsmp->jnl) {
-                               journal_end_transaction(hfsmp->jnl);
-                       }
-                       hfs_global_shared_lock_release(hfsmp);
-                   return (error);
+                       cat_postflight(hfsmp, &cookie, ap->a_p);
+                               return (error);
                }
 
                error = cat_insertfilethread(hfsmp, &cp->c_desc);
 
-               /* Unlock catalog b-tree */
-               (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_RELEASE, ap->a_p);
+               (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_RELEASE,
+                                          ap->a_p);
 
-               if (hfsmp->jnl) {
-                   journal_end_transaction(hfsmp->jnl);
-               }
-               hfs_global_shared_lock_release(hfsmp);
+               cat_postflight(hfsmp, &cookie, ap->a_p);
 
                if (error)
                        return (error);
@@ -291,7 +283,7 @@ hfs_getattrlist(ap)
        attrblk.ab_blocksize = attrblocksize;
 
        hfs_packattrblk(&attrblk, hfsmp, vp, &cp->c_desc, &cp->c_attr,
-                       datafp, rsrcfp);
+                       datafp, rsrcfp, ap->a_p);
 
        /* Don't copy out more data than was generated */
        attrbufsize = MIN(attrbufsize, (u_int)varptr - (u_int)attrbufptr);
@@ -346,7 +338,7 @@ hfs_setattrlist(ap)
        u_long saved_flags;
        int error = 0;
 
-       if (VTOVFS(vp)->mnt_flag & MNT_RDONLY)
+       if (hfsmp->hfs_flags & HFS_READ_ONLY)
                return (EROFS);
        if ((alist->bitmapcount != ATTR_BIT_MAP_COUNT)     ||
            ((alist->commonattr & ~ATTR_CMN_SETMASK) != 0) ||
@@ -378,7 +370,7 @@ hfs_setattrlist(ap)
        if (hfsmp->jnl && cp->c_datafork) {
                struct HFSPlusExtentDescriptor *extd;
                
-               extd = &cp->c_datafork->ff_data.cf_extents[0];
+               extd = &cp->c_datafork->ff_extents[0];
                if (extd->startBlock == HFSTOVCB(hfsmp)->vcbJinfoBlock || extd->startBlock == hfsmp->jnl_start) {
                        return EPERM;
                }
@@ -503,6 +495,10 @@ hfs_setattrlist(ap)
                        struct cat_desc to_desc = {0};
                        struct cat_desc todir_desc = {0};
                        struct cat_desc new_desc = {0};
+                       cat_cookie_t cookie = {0};
+                       int catreserve = 0;
+                       int catlocked = 0;
+                       int started_tr = 0;
 
                        todir_desc.cd_parentcnid = kRootParID;
                        todir_desc.cd_cnid = kRootParID;
@@ -517,38 +513,38 @@ hfs_setattrlist(ap)
                        // XXXdbg
                        hfs_global_shared_lock_acquire(hfsmp);
                        if (hfsmp->jnl) {
-                           if (journal_start_transaction(hfsmp->jnl) != 0) {
-                                       hfs_global_shared_lock_release(hfsmp);
-                                       error = EINVAL;
-                                       /* Restore the old name in the VCB */
-                                       copystr(cp->c_desc.cd_nameptr, vcb->vcbVN, sizeof(vcb->vcbVN), NULL);
-                                       vcb->vcbFlags |= 0xFF00;
-                                       goto ErrorExit;
-                           }
+                               if ((error = journal_start_transaction(hfsmp->jnl) != 0)) {
+                                       goto rename_out;
+                               }
+                               started_tr = 1;
                        }
 
+                       /*
+                        * Reserve some space in the Catalog file.
+                        */
+                       error = cat_preflight(hfsmp, CAT_RENAME, &cookie, p);
+                       if (error) {
+                               goto rename_out;
+                       }
+                       catreserve = 1;
 
                        /* Lock catalog b-tree */
                        error = hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_EXCLUSIVE, p);
                        if (error) {
-                               if (hfsmp->jnl) {
-                                   journal_end_transaction(hfsmp->jnl);
-                               }
-                               hfs_global_shared_lock_release(hfsmp);
-
-                               /* Restore the old name in the VCB */
-                               copystr(cp->c_desc.cd_nameptr, vcb->vcbVN, sizeof(vcb->vcbVN), NULL);
-                               vcb->vcbFlags |= 0xFF00;
-                               goto ErrorExit;
+                               goto rename_out;
                        }
+                       catlocked = 1;
 
                        error = cat_rename(hfsmp, &cp->c_desc, &todir_desc, &to_desc, &new_desc);
-
-                       /* Unlock the Catalog */
-                       (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_RELEASE, p);
-                       
-                       if (hfsmp->jnl) {
-                           journal_end_transaction(hfsmp->jnl);
+rename_out:                    
+                       if (catlocked) {
+                               (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_RELEASE, p);
+                       }
+                       if (catreserve) {
+                               cat_postflight(hfsmp, &cookie, p);
+                       }
+                       if (started_tr) {
+                               journal_end_transaction(hfsmp->jnl);
                        }
                        hfs_global_shared_lock_release(hfsmp);
                        
@@ -565,7 +561,7 @@ hfs_setattrlist(ap)
                                cp->c_desc.cd_nameptr = 0;
                                cp->c_desc.cd_namelen = 0;
                                cp->c_desc.cd_flags &= ~CD_HASBUF;
-                               FREE(name, M_TEMP);
+                               remove_name(name);
                        }                       
                        /* Update cnode's catalog descriptor */
                        replace_desc(cp, &new_desc);
@@ -788,14 +784,12 @@ hfs_readdirattr(ap)
                                                cdescp = &cp->c_desc;
                                        cattrp = &cp->c_attr;
                                        if (cp->c_datafork) {
-                                               c_datafork.cf_size   = cp->c_datafork->ff_data.cf_size;
-                                               c_datafork.cf_clump  = cp->c_datafork->ff_data.cf_clump;
-                                               c_datafork.cf_blocks = cp->c_datafork->ff_data.cf_blocks;
+                                               c_datafork.cf_size   = cp->c_datafork->ff_size;
+                                               c_datafork.cf_blocks = cp->c_datafork->ff_blocks;
                                        }
                                        if (cp->c_rsrcfork) {
-                                               c_rsrcfork.cf_size   = cp->c_rsrcfork->ff_data.cf_size;
-                                               c_rsrcfork.cf_clump  = cp->c_rsrcfork->ff_data.cf_clump;
-                                               c_rsrcfork.cf_blocks = cp->c_rsrcfork->ff_data.cf_blocks;
+                                               c_rsrcfork.cf_size   = cp->c_rsrcfork->ff_size;
+                                               c_rsrcfork.cf_blocks = cp->c_rsrcfork->ff_blocks;
                                        }
                                }
                        }
@@ -808,7 +802,7 @@ hfs_readdirattr(ap)
 
                        /* Pack catalog entries into attribute buffer. */
                        hfs_packattrblk(&attrblk, hfsmp, vp, cdescp, cattrp,
-                                       &c_datafork, &c_rsrcfork);
+                                       &c_datafork, &c_rsrcfork, p);
                        currattrbufsize = ((char *)varptr - (char *)attrbufptr);
                
                        /* All done with cnode. */
@@ -910,25 +904,26 @@ hfs_packattrblk(struct attrblock *abp,
                struct cat_desc *descp,
                struct cat_attr *attrp,
                struct cat_fork *datafork,
-               struct cat_fork *rsrcfork)
+               struct cat_fork *rsrcfork,
+               struct proc *p)
 {
        struct attrlist *attrlistp = abp->ab_attrlist;
 
        if (attrlistp->volattr) {
                if (attrlistp->commonattr)
-                       packvolcommonattr(abp, hfsmp, vp);
+                       packvolcommonattr(abp, hfsmp, vp, p);
 
                if (attrlistp->volattr & ~ATTR_VOL_INFO)
-                       packvolattr(abp, hfsmp, vp);
+                       packvolattr(abp, hfsmp, vp, p);
        } else {
                if (attrlistp->commonattr)
-                       packcommonattr(abp, hfsmp, vp, descp, attrp);
+                       packcommonattr(abp, hfsmp, vp, descp, attrp, p);
        
                if (attrlistp->dirattr && S_ISDIR(attrp->ca_mode))
-                       packdirattr(abp, hfsmp, vp, descp,attrp);
+                       packdirattr(abp, hfsmp, vp, descp,attrp, p);
        
                if (attrlistp->fileattr && !S_ISDIR(attrp->ca_mode))
-                       packfileattr(abp, hfsmp, attrp, datafork, rsrcfork);
+                       packfileattr(abp, hfsmp, attrp, datafork, rsrcfork, p);
        }
 }
 
@@ -966,7 +961,8 @@ packnameattr(
        struct attrblock *abp,
        struct vnode *vp,
        char *name,
-       int namelen)
+       int namelen,
+       struct proc *p)
 {
        void *varbufptr;
        struct attrreference * attr_refptr;
@@ -1022,7 +1018,7 @@ packnameattr(
  * Pack common volume attributes.
  */
 static void
-packvolcommonattr(struct attrblock *abp, struct hfsmount *hfsmp, struct vnode *vp)
+packvolcommonattr(struct attrblock *abp, struct hfsmount *hfsmp, struct vnode *vp, struct proc *p)
 {
        attrgroup_t attr;
        void *attrbufptr = *abp->ab_attrbufpp;
@@ -1035,7 +1031,7 @@ packvolcommonattr(struct attrblock *abp, struct hfsmount *hfsmp, struct vnode *v
        attr = abp->ab_attrlist->commonattr;
 
        if (ATTR_CMN_NAME & attr) {
-               packnameattr(abp, vp, cp->c_desc.cd_nameptr, cp->c_desc.cd_namelen);
+               packnameattr(abp, vp, cp->c_desc.cd_nameptr, cp->c_desc.cd_namelen, p);
                attrbufptr = *abp->ab_attrbufpp;
                varbufptr = *abp->ab_varbufpp;
        }
@@ -1107,7 +1103,7 @@ packvolcommonattr(struct attrblock *abp, struct hfsmount *hfsmp, struct vnode *v
        }
        if (ATTR_CMN_OWNERID & attr) {
                if (cp->c_uid == UNKNOWNUID)
-                       *((uid_t *)attrbufptr)++ = console_user;
+                       *((uid_t *)attrbufptr)++ = p->p_ucred->cr_uid;
                else
                        *((uid_t *)attrbufptr)++ = cp->c_uid;
        }
@@ -1154,7 +1150,7 @@ packvolcommonattr(struct attrblock *abp, struct hfsmount *hfsmp, struct vnode *v
 
 
 static void
-packvolattr(struct attrblock *abp, struct hfsmount *hfsmp, struct vnode *vp)
+packvolattr(struct attrblock *abp, struct hfsmount *hfsmp, struct vnode *vp, struct proc *p)
 {
        attrgroup_t attr;
        void *attrbufptr = *abp->ab_attrbufpp;
@@ -1179,7 +1175,6 @@ packvolattr(struct attrblock *abp, struct hfsmount *hfsmp, struct vnode *vp)
        if (ATTR_VOL_SPACEFREE & attr) {
                *((off_t *)attrbufptr)++ = (off_t)hfs_freeblks(hfsmp, 0) *
                                           (off_t)vcb->blockSize;
-               
        }
        if (ATTR_VOL_SPACEAVAIL & attr) {
                *((off_t *)attrbufptr)++ = (off_t)hfs_freeblks(hfsmp, 1) *
@@ -1263,31 +1258,70 @@ packvolattr(struct attrblock *abp, struct hfsmount *hfsmp, struct vnode *vp)
                vcapattrptr = (vol_capabilities_attr_t *)attrbufptr;
 
                if (vcb->vcbSigWord == kHFSPlusSigWord) {
+                       u_int32_t journal_active;
+                       u_int32_t case_sensitive;
+                       
+                       if (hfsmp->jnl)
+                               journal_active = VOL_CAP_FMT_JOURNAL_ACTIVE;
+                       else
+                               journal_active = 0;
+
+                       if (hfsmp->hfs_flags & HFS_CASE_SENSITIVE)
+                               case_sensitive = VOL_CAP_FMT_CASE_SENSITIVE;
+                       else
+                               case_sensitive = 0;
+                       
                        vcapattrptr->capabilities[VOL_CAPABILITIES_FORMAT] =
                                        VOL_CAP_FMT_PERSISTENTOBJECTIDS |
                                        VOL_CAP_FMT_SYMBOLICLINKS |
-                                       VOL_CAP_FMT_HARDLINKS;
+                                       VOL_CAP_FMT_HARDLINKS |
+                                       VOL_CAP_FMT_JOURNAL |
+                                       journal_active |
+                                       case_sensitive |
+                                       VOL_CAP_FMT_CASE_PRESERVING |
+                                       VOL_CAP_FMT_FAST_STATFS ;
                } else { /* Plain HFS */
                        vcapattrptr->capabilities[VOL_CAPABILITIES_FORMAT] =
-                                       VOL_CAP_FMT_PERSISTENTOBJECTIDS;
+                                       VOL_CAP_FMT_PERSISTENTOBJECTIDS |
+                                       VOL_CAP_FMT_CASE_PRESERVING |
+                                       VOL_CAP_FMT_FAST_STATFS ;
                }
                vcapattrptr->capabilities[VOL_CAPABILITIES_INTERFACES] =
                                        VOL_CAP_INT_SEARCHFS |
                                        VOL_CAP_INT_ATTRLIST |
                                        VOL_CAP_INT_NFSEXPORT |
-                                       VOL_CAP_INT_READDIRATTR ;
+                                       VOL_CAP_INT_READDIRATTR |
+                                       VOL_CAP_INT_EXCHANGEDATA |
+                                       VOL_CAP_INT_ALLOCATE |
+                                       VOL_CAP_INT_VOL_RENAME |
+                                       VOL_CAP_INT_ADVLOCK |
+                                       VOL_CAP_INT_FLOCK ;
                vcapattrptr->capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
                vcapattrptr->capabilities[VOL_CAPABILITIES_RESERVED2] = 0;
 
                vcapattrptr->valid[VOL_CAPABILITIES_FORMAT] =
                                        VOL_CAP_FMT_PERSISTENTOBJECTIDS |
                                        VOL_CAP_FMT_SYMBOLICLINKS |
-                                       VOL_CAP_FMT_HARDLINKS;
+                                       VOL_CAP_FMT_HARDLINKS |
+                                       VOL_CAP_FMT_JOURNAL |
+                                       VOL_CAP_FMT_JOURNAL_ACTIVE |
+                                       VOL_CAP_FMT_NO_ROOT_TIMES |
+                                       VOL_CAP_FMT_SPARSE_FILES |
+                                       VOL_CAP_FMT_ZERO_RUNS |
+                                       VOL_CAP_FMT_CASE_SENSITIVE |
+                                       VOL_CAP_FMT_CASE_PRESERVING |
+                                       VOL_CAP_FMT_FAST_STATFS ;
                vcapattrptr->valid[VOL_CAPABILITIES_INTERFACES] =
                                        VOL_CAP_INT_SEARCHFS |
                                        VOL_CAP_INT_ATTRLIST |
                                        VOL_CAP_INT_NFSEXPORT |
-                                       VOL_CAP_INT_READDIRATTR ;
+                                       VOL_CAP_INT_READDIRATTR |
+                                       VOL_CAP_INT_EXCHANGEDATA |
+                                       VOL_CAP_INT_COPYFILE |
+                                       VOL_CAP_INT_ALLOCATE |
+                                       VOL_CAP_INT_VOL_RENAME |
+                                       VOL_CAP_INT_ADVLOCK |
+                                       VOL_CAP_INT_FLOCK ;
                vcapattrptr->valid[VOL_CAPABILITIES_RESERVED1] = 0;
                vcapattrptr->valid[VOL_CAPABILITIES_RESERVED2] = 0;
 
@@ -1322,7 +1356,8 @@ packcommonattr(
        struct hfsmount *hfsmp,
        struct vnode *vp,
        struct cat_desc * cdp,
-       struct cat_attr * cap)
+       struct cat_attr * cap,
+       struct proc *p)
 {
        attrgroup_t attr = abp->ab_attrlist->commonattr;
        struct mount *mp = HFSTOVFS(hfsmp);
@@ -1331,7 +1366,7 @@ packcommonattr(
        u_long attrlength = 0;
        
        if (ATTR_CMN_NAME & attr) {
-               packnameattr(abp, vp, cdp->cd_nameptr, cdp->cd_namelen);
+               packnameattr(abp, vp, cdp->cd_nameptr, cdp->cd_namelen, p);
                attrbufptr = *abp->ab_attrbufpp;
                varbufptr = *abp->ab_varbufpp;
        }
@@ -1409,7 +1444,7 @@ packcommonattr(
        }
        if (ATTR_CMN_OWNERID & attr) {
                *((uid_t *)attrbufptr)++ =
-                       (cap->ca_uid == UNKNOWNUID) ? console_user : cap->ca_uid;
+                       (cap->ca_uid == UNKNOWNUID) ? p->p_ucred->cr_uid : cap->ca_uid;
        }
        if (ATTR_CMN_GRPID & attr) {
                *((gid_t *)attrbufptr)++ = cap->ca_gid;
@@ -1459,7 +1494,8 @@ packdirattr(
        struct hfsmount *hfsmp,
        struct vnode *vp,
        struct cat_desc * descp,
-       struct cat_attr * cattrp)
+       struct cat_attr * cattrp,
+       struct proc *p)
 {
        attrgroup_t attr = abp->ab_attrlist->dirattr;
        void *attrbufptr = *abp->ab_attrbufpp;
@@ -1470,7 +1506,7 @@ packdirattr(
                u_long entries = cattrp->ca_entries;
 
                if (descp->cd_parentcnid == kRootParID) {
-                       if (hfsmp->hfs_private_metadata_dir != 0)
+                       if (hfsmp->hfs_privdir_desc.cd_cnid != 0)
                                --entries;          /* hide private dir */
                        if (hfsmp->jnl)
                                entries -= 2;   /* hide the journal files */
@@ -1493,7 +1529,8 @@ packfileattr(
        struct hfsmount *hfsmp,
        struct cat_attr *cattrp,
        struct cat_fork *datafork,
-       struct cat_fork *rsrcfork)
+       struct cat_fork *rsrcfork,
+       struct proc *p)
 {
        attrgroup_t attr = abp->ab_attrlist->fileattr;
        void *attrbufptr = *abp->ab_attrbufpp;
@@ -1517,7 +1554,7 @@ packfileattr(
                *((u_long *)attrbufptr)++ = hfsmp->hfs_logBlockSize;
        }
        if (ATTR_FILE_CLUMPSIZE & attr) {
-               *((u_long *)attrbufptr)++ = datafork->cf_clump;  /* XXX ambiguity */
+               *((u_long *)attrbufptr)++ = HFSTOVCB(hfsmp)->vcbClpSiz;
        }
        if (ATTR_FILE_DEVTYPE & attr) {
                if (S_ISBLK(cattrp->ca_mode) || S_ISCHR(cattrp->ca_mode))
@@ -1870,7 +1907,7 @@ DerivePermissionSummary(uid_t obj_uid, gid_t obj_gid, mode_t obj_mode,
        int i;
 
        if (obj_uid == UNKNOWNUID)
-               obj_uid = console_user;
+               obj_uid = p->p_ucred->cr_uid;
 
        /* User id 0 (root) always gets access. */
        if (cred->cr_uid == 0) {