/*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
-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);
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);
(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);
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);
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) ||
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;
}
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;
// 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);
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);
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;
}
}
}
/* 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. */
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);
}
}
struct attrblock *abp,
struct vnode *vp,
char *name,
- int namelen)
+ int namelen,
+ struct proc *p)
{
void *varbufptr;
struct attrreference * attr_refptr;
* 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;
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;
}
}
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;
}
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;
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) *
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;
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);
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;
}
}
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;
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;
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 */
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;
*((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))
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) {