/*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
- * @APPLE_LICENSE_HEADER_START@
- *
- * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* Please see the License for the specific language governing rights and
* limitations under the License.
*
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
#include <sys/attr.h>
#include <sys/stat.h>
#include <sys/unistd.h>
+#include <sys/mount_internal.h>
+#include <sys/kauth.h>
+
+#include <kern/locks.h>
#include "hfs.h"
#include "hfs_cnode.h"
-extern uid_t console_user;
-
-
/* Routines that are shared by hfs_setattr: */
-extern int hfs_write_access(struct vnode *vp, struct ucred *cred,
+extern int hfs_write_access(struct vnode *vp, kauth_cred_t cred,
struct proc *p, Boolean considerFlags);
-extern int hfs_chflags(struct vnode *vp, u_long flags, struct ucred *cred,
+extern int hfs_chflags(struct vnode *vp, uint32_t flags, kauth_cred_t cred,
struct proc *p);
-extern int hfs_chmod(struct vnode *vp, int mode, struct ucred *cred,
+extern int hfs_chmod(struct vnode *vp, int mode, kauth_cred_t cred,
struct proc *p);
-extern int hfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred,
+extern int hfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred,
struct proc *p);
-extern char * hfs_getnamehint(struct cnode *dcp, int index);
+__private_extern__ int hfs_vnop_readdirattr(struct vnop_readdirattr_args *ap);
-extern void hfs_savenamehint(struct cnode *dcp, int index, const char * namehint);
+__private_extern__ int hfs_vnop_setattrlist(struct vnop_setattrlist_args *ap);
-extern void hfs_relnamehint(struct cnode *dcp, int index);
+__private_extern__ int hfs_vnop_getattrlist(struct vnop_getattrlist_args *ap);
/* Packing routines: */
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);
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 vnode *vp, struct cat_desc * descp,
struct cat_attr * cattrp);
-static void unpackattrblk(struct attrblock *abp, struct vnode *vp);
+
+#if 0
+static int unpackattrblk(struct attrblock *abp, struct vnode *vp);
static void unpackcommonattr(struct attrblock *abp, struct vnode *vp);
-static void unpackvolattr(struct attrblock *abp, struct hfsmount *hfsmp,
- struct vnode *rootvp);
+static int unpackvolattr(struct attrblock *abp, struct hfsmount *hfsmp,
+ struct vnode *root_vp);
/*
-
-#
-#% getattrlist vp = = =
-#
- vop_getattrlist {
- IN struct vnode *vp;
- IN struct attrlist *alist;
- INOUT struct uio *uio;
- IN struct ucred *cred;
- IN struct proc *p;
- };
-
+ * Get a list of attributes.
*/
__private_extern__
int
-hfs_getattrlist(ap)
- struct vop_getattrlist_args /* {
+hfs_vnop_getattrlist(ap)
+ struct vnop_getattrlist_args /* {
struct vnode *a_vp;
struct attrlist *a_alist
struct uio *a_uio;
- struct ucred *a_cred;
- struct proc *a_p;
+ int a_options;
+ vfs_context_t a_context;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
- struct cnode *cp = VTOC(vp);
- struct hfsmount *hfsmp = VTOHFS(vp);
+ struct cnode *cp;
+ struct hfsmount *hfsmp;
struct attrlist *alist = ap->a_alist;
- struct timeval tv;
+ proc_t p = vfs_context_proc(ap->a_context);
int fixedblocksize;
int attrblocksize;
int attrbufsize;
- void *attrbufptr;
+ void *attrbufptr = NULL;
void *attrptr;
void *varptr;
struct attrblock attrblk;
struct cat_fork *datafp = NULL;
struct cat_fork *rsrcfp = NULL;
- struct cat_fork rsrcfork = {0};
+ struct cat_fork rsrcfork;
+ int lockflags;
int error = 0;
if ((alist->bitmapcount != ATTR_BIT_MAP_COUNT) ||
return (EINVAL);
}
- /* Requesting volume information requires root vnode */
- if ((alist->volattr) && cp->c_fileid != kRootDirID)
- return (EINVAL);
+ if ((error = hfs_lock(VTOC(vp), HFS_EXCLUSIVE_LOCK)))
+ return (error);
+ cp = VTOC(vp);
+ hfsmp = VTOHFS(vp);
+ /* Requesting volume information requires root vnode */
+ if ((alist->volattr) && cp->c_fileid != kHFSRootFolderID) {
+ error = EINVAL;
+ goto exit;
+ }
/* Asking for data fork attributes from the rsrc fork is not supported */
- if (VNODE_IS_RSRC(vp) && (alist->fileattr & ATTR_DATAFORK_MASK))
- return (EINVAL);
-
+ if (VNODE_IS_RSRC(vp) && (alist->fileattr & ATTR_DATAFORK_MASK)) {
+ error = EINVAL;
+ goto exit;
+ }
/* This file no longer exists! */
- if (cp->c_flag & (C_NOEXISTS | C_DELETED))
- return (ENOENT);
-
+ if (cp->c_flag & (C_NOEXISTS | C_DELETED)) {
+ error = ENOENT;
+ goto exit;
+ }
/* This file doesn't have a name! */
- if ((cp->c_desc.cd_namelen == 0) && (alist->commonattr & ATTR_CMN_NAME))
- return (ENOENT);
+ if ((cp->c_desc.cd_namelen == 0) && (alist->commonattr & ATTR_CMN_NAME)) {
+ error = ENOENT;
+ goto exit;
+ }
/* Update cnode times if needed */
- tv = time;
- CTIMES(cp, &tv, &tv);
+ hfs_touchtimes(hfsmp, cp);
/*
* If a File ID (ATTR_CMN_OBJPERMANENTID) is requested on
* an HFS volume we must be sure to create the thread
* record before returning it. (yikes)
*/
- if ((vp->v_type == VREG) &&
+ if (vnode_isreg(vp) &&
(alist->commonattr & ATTR_CMN_OBJPERMANENTID) &&
(VTOVCB(vp)->vcbSigWord != kHFSPlusSigWord)) {
- if (VTOVFS(vp)->mnt_flag & MNT_RDONLY)
- 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;
- }
- }
+ cat_cookie_t cookie;
- /* Lock catalog b-tree */
- error = hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_SHARED, ap->a_p);
- if (error) {
- if (hfsmp->jnl) {
- journal_end_transaction(hfsmp->jnl);
- }
- hfs_global_shared_lock_release(hfsmp);
- return (error);
+ if (hfsmp->hfs_flags & HFS_READ_ONLY) {
+ error = EROFS;
+ goto exit;
}
+ if ((error = hfs_write_access(vp, vfs_context_ucred(ap->a_context),
+ p, false)) != 0) {
+ goto exit;
+ }
+ /*
+ * Reserve some space in the Catalog file.
+ */
+ bzero(&cookie, sizeof(cookie));
+ error = cat_preflight(hfsmp, CAT_CREATE, &cookie, p);
+ if (error) {
+ goto exit;
+ }
+
+ lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_EXCLUSIVE_LOCK);
error = cat_insertfilethread(hfsmp, &cp->c_desc);
- /* Unlock catalog b-tree */
- (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_RELEASE, ap->a_p);
+ hfs_systemfile_unlock(hfsmp, lockflags);
- if (hfsmp->jnl) {
- journal_end_transaction(hfsmp->jnl);
- }
- hfs_global_shared_lock_release(hfsmp);
+ cat_postflight(hfsmp, &cookie, p);
if (error)
- return (error);
+ goto exit;
}
-
+ bzero(&rsrcfork, sizeof(rsrcfork));
/* Establish known fork data */
if (cp->c_datafork != NULL) {
datafp = &cp->c_datafork->ff_data;
* fetched from the catalog.
*/
if ((alist->fileattr & ATTR_RSRCFORK_MASK) && (rsrcfp == NULL)) {
- /* Lock catalog b-tree */
- error = hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_SHARED, ap->a_p);
- if (error)
- return (error);
+
+ lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_SHARED_LOCK);
/* Get resource fork data */
error = cat_lookup(hfsmp, &cp->c_desc, 1,
- (struct cat_desc *)0, (struct cat_attr *)0, &rsrcfork);
+ (struct cat_desc *)0, (struct cat_attr *)0, &rsrcfork, NULL);
+
+ hfs_systemfile_unlock(hfsmp, lockflags);
- /* Unlock the Catalog */
- (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_RELEASE, ap->a_p);
if (error)
- return (error);
+ goto exit;
rsrcfp = &rsrcfork;
}
fixedblocksize = hfs_attrblksize(alist);
- attrblocksize = fixedblocksize + (sizeof(u_long)); /* u_long for length longword */
+ attrblocksize = fixedblocksize + (sizeof(uint32_t)); /* uint32_t for length word */
if (alist->commonattr & ATTR_CMN_NAME)
attrblocksize += kHFSPlusMaxFileNameBytes + 1;
if (alist->volattr & ATTR_VOL_MOUNTPOINT)
if (alist->fileattr & ATTR_FILE_FORKLIST)
attrblocksize += 0;
#endif
- attrbufsize = MIN(ap->a_uio->uio_resid, attrblocksize);
+ attrbufsize = MIN(uio_resid(ap->a_uio), attrblocksize);
MALLOC(attrbufptr, void *, attrblocksize, M_TEMP, M_WAITOK);
attrptr = attrbufptr;
- *((u_long *)attrptr) = 0; /* Set buffer length in case of errors */
- ++((u_long *)attrptr); /* Reserve space for length field */
+ *((uint32_t *)attrptr) = 0; /* Set buffer length in case of errors */
+ ++((uint32_t *)attrptr); /* Reserve space for length field */
varptr = ((char *)attrptr) + fixedblocksize;
attrblk.ab_attrlist = alist;
attrblk.ab_blocksize = attrblocksize;
hfs_packattrblk(&attrblk, hfsmp, vp, &cp->c_desc, &cp->c_attr,
- datafp, rsrcfp);
+ datafp, rsrcfp, p);
/* Don't copy out more data than was generated */
- attrbufsize = MIN(attrbufsize, (u_int)varptr - (u_int)attrbufptr);
+ attrbufsize = MIN((u_int)attrbufsize, (u_int)varptr - (u_int)attrbufptr);
/* Set actual buffer length for return to caller */
- *((u_long *)attrbufptr) = attrbufsize;
+ *((uint32_t *)attrbufptr) = attrbufsize;
error = uiomove((caddr_t)attrbufptr, attrbufsize, ap->a_uio);
-
- FREE(attrbufptr, M_TEMP);
+exit:
+ if (attrbufptr)
+ FREE(attrbufptr, M_TEMP);
+ hfs_unlock(cp);
return (error);
}
/*
-
-#
-#% setattrlist vp L L L
-#
- vop_setattrlist {
- IN struct vnode *vp;
- IN struct attrlist *alist;
- INOUT struct uio *uio;
- IN struct ucred *cred;
- IN struct proc *p;
- };
-
+ * Set a list of attributes.
*/
__private_extern__
int
-hfs_setattrlist(ap)
- struct vop_setattrlist_args /* {
+hfs_vnop_setattrlist(ap)
+ struct vnop_setattrlist_args /* {
struct vnode *a_vp;
struct attrlist *a_alist
struct uio *a_uio;
- struct ucred *a_cred;
- struct proc *a_p;
+ int a_options;
+ vfs_context_t a_context;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
- struct cnode *cp = VTOC(vp);
- struct hfsmount * hfsmp = VTOHFS(vp);
+ struct cnode *cp;
+ struct hfsmount * hfsmp;
struct attrlist *alist = ap->a_alist;
- struct ucred *cred = ap->a_cred;
- struct proc *p = ap->a_p;
+ kauth_cred_t cred = vfs_context_ucred(ap->a_context);
+ struct proc *p = vfs_context_proc(ap->a_context);
int attrblocksize;
void *attrbufptr = NULL;
void *attrptr;
uid_t saved_uid;
gid_t saved_gid;
mode_t saved_mode;
- u_long saved_flags;
+ uint32_t saved_flags;
int error = 0;
- if (VTOVFS(vp)->mnt_flag & MNT_RDONLY)
+ hfsmp = VTOHFS(vp);
+
+ if (hfsmp->hfs_flags & HFS_READ_ONLY)
return (EROFS);
if ((alist->bitmapcount != ATTR_BIT_MAP_COUNT) ||
((alist->commonattr & ~ATTR_CMN_SETMASK) != 0) ||
((alist->fileattr & ~ATTR_FILE_SETMASK) != 0)) {
return (EINVAL);
}
+ if ((error = hfs_lock(VTOC(vp), HFS_EXCLUSIVE_LOCK)))
+ return (error);
+ cp = VTOC(vp);
+
/*
* When setting volume attributes make sure
* that ATTR_VOL_INFO is set and that all
if ((alist->volattr != 0) &&
(((alist->volattr & ATTR_VOL_INFO) == 0) ||
(alist->commonattr & ~ATTR_CMN_VOLSETMASK) ||
- (cp->c_fileid != kRootDirID))) {
+ (cp->c_fileid != kHFSRootFolderID))) {
if ((alist->volattr & ATTR_VOL_INFO) == 0)
printf("hfs_setattrlist: you forgot to set ATTR_VOL_INFO bit!\n");
else
printf("hfs_setattrlist: you cannot set bits 0x%08X!\n",
alist->commonattr & ~ATTR_CMN_VOLSETMASK);
- return (EINVAL);
+ error = EINVAL;
+ goto ErrorExit;
+ }
+ if (cp->c_flag & (C_NOEXISTS | C_DELETED)) {
+ error = ENOENT;
+ goto ErrorExit;
}
- if (cp->c_flag & (C_NOEXISTS | C_DELETED))
- return (ENOENT);
-
// XXXdbg - don't allow modifying the journal or journal_info_block
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;
+ error = EPERM;
+ goto ErrorExit;
}
}
* change so this check is sufficient for now.
*/
if ((error = hfs_owner_rights(hfsmp, cp->c_uid, cred, p, true)) != 0)
- return (error);
+ goto ErrorExit;
}
/*
* For any other attributes, check to see if the user has
- * write access to the cnode in question [unlike VOP_ACCESS,
+ * write access to the cnode in question [unlike vn_access,
* ignore IMMUTABLE here]:
*/
if (((alist->commonattr & ~ATTR_OWNERSHIP_SETMASK) != 0) ||
(alist->volattr != 0) || (alist->dirattr != 0) ||
(alist->fileattr != 0)) {
if ((error = hfs_write_access(vp, cred, p, false)) != 0)
- return (error);
+ goto ErrorExit;
}
/*
* Allocate the buffer now to minimize the time we might
* be blocked holding the catalog lock.
*/
- attrblocksize = ap->a_uio->uio_resid;
- if (attrblocksize < hfs_attrblksize(alist))
- return (EINVAL);
+ // LP64todo - fix this
+ attrblocksize = uio_resid(ap->a_uio);
+ if (attrblocksize < hfs_attrblksize(alist)) {
+ error = EINVAL;
+ goto ErrorExit;
+ }
MALLOC(attrbufptr, void *, attrblocksize, M_TEMP, M_WAITOK);
attrblk.ab_varbufpp = &varptr;
attrblk.ab_flags = 0;
attrblk.ab_blocksize = attrblocksize;
- unpackattrblk(&attrblk, vp);
+ error = unpackattrblk(&attrblk, vp);
+ if (error)
+ goto ErrorExit;
/* If unpacking changed the owner/group then call hfs_chown() */
if ((saved_uid != cp->c_uid) || (saved_gid != cp->c_gid)) {
}
/* If unpacking changed the flags then call hfs_chflags() */
if (saved_flags !=cp->c_flags) {
- u_long flags;
+ uint32_t flags;
flags = cp->c_flags;
cp->c_flags = saved_flags;
* If any cnode attributes changed then do an update.
*/
if (alist->volattr == 0) {
- struct timeval tv;
-
cp->c_flag |= C_MODIFIED;
- tv = time;
- CTIMES(cp, &tv, &tv);
- if ((error = VOP_UPDATE(vp, &tv, &tv, 1)))
+ if ((error = hfs_update(vp, TRUE))) {
goto ErrorExit;
+ }
}
/* Volume Rename */
if (alist->volattr & ATTR_VOL_NAME) {
*/
copystr(cp->c_desc.cd_nameptr, vcb->vcbVN, sizeof(vcb->vcbVN), NULL);
} else {
- struct cat_desc to_desc = {0};
- struct cat_desc todir_desc = {0};
- struct cat_desc new_desc = {0};
-
- todir_desc.cd_parentcnid = kRootParID;
- todir_desc.cd_cnid = kRootParID;
+ struct cat_desc to_desc;
+ struct cat_desc todir_desc;
+ struct cat_desc new_desc;
+ cat_cookie_t cookie;
+ int catreserve = 0;
+ int catlocked = 0;
+ int started_tr = 0;
+ int lockflags;
+
+ bzero(&to_desc, sizeof(to_desc));
+ bzero(&todir_desc, sizeof(todir_desc));
+ bzero(&new_desc, sizeof(new_desc));
+ bzero(&cookie, sizeof(cookie));
+
+ todir_desc.cd_parentcnid = kHFSRootParentID;
+ todir_desc.cd_cnid = kHFSRootFolderID;
todir_desc.cd_flags = CD_ISDIR;
to_desc.cd_nameptr = vcb->vcbVN;
to_desc.cd_namelen = strlen(vcb->vcbVN);
- to_desc.cd_parentcnid = kRootParID;
+ to_desc.cd_parentcnid = kHFSRootParentID;
to_desc.cd_cnid = cp->c_cnid;
to_desc.cd_flags = CD_ISDIR;
- // 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 = hfs_start_transaction(hfsmp) != 0)) {
+ goto rename_out;
}
+ started_tr = 1;
-
- /* Lock catalog b-tree */
- error = hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_EXCLUSIVE, p);
+ /*
+ * Reserve some space in the Catalog file.
+ */
+ error = cat_preflight(hfsmp, CAT_RENAME, &cookie, 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;
}
+ catreserve = 1;
- error = cat_rename(hfsmp, &cp->c_desc, &todir_desc, &to_desc, &new_desc);
+ lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_EXCLUSIVE_LOCK);
+ catlocked = 1;
- /* Unlock the Catalog */
- (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_RELEASE, p);
-
- if (hfsmp->jnl) {
- journal_end_transaction(hfsmp->jnl);
+ error = cat_rename(hfsmp, &cp->c_desc, &todir_desc, &to_desc, &new_desc);
+rename_out:
+ if (catlocked) {
+ hfs_systemfile_unlock(hfsmp, lockflags);
+ }
+ if (catreserve) {
+ cat_postflight(hfsmp, &cookie, p);
+ }
+ (void) hfs_flushvolumeheader(hfsmp, MNT_WAIT, 0);
+ if (started_tr) {
+ hfs_end_transaction(hfsmp);
}
- hfs_global_shared_lock_release(hfsmp);
if (error) {
/* Restore the old name in the VCB */
cp->c_desc.cd_nameptr = 0;
cp->c_desc.cd_namelen = 0;
cp->c_desc.cd_flags &= ~CD_HASBUF;
- FREE(name, M_TEMP);
+ vfs_removename(name);
}
/* Update cnode's catalog descriptor */
replace_desc(cp, &new_desc);
vcb->volumeNameEncodingHint = new_desc.cd_encoding;
- cp->c_flag |= C_CHANGE;
+ cp->c_touch_chgtime = TRUE;
}
}
if (attrbufptr)
FREE(attrbufptr, M_TEMP);
+ hfs_unlock(cp);
return (error);
}
-
+#endif
/*
* readdirattr operation will return attributes for the items in the
#
#% readdirattr vp L L L
#
-vop_readdirattr {
+vnop_readdirattr {
IN struct vnode *vp;
IN struct attrlist *alist;
INOUT struct uio *uio;
OUT int *eofflag;
OUT u_long *actualCount;
OUT u_long **cookies;
- IN struct ucred *cred;
+ IN kauth_cred_t cred;
};
*/
__private_extern__
int
-hfs_readdirattr(ap)
- struct vop_readdirattr_args /* {
+hfs_vnop_readdirattr(ap)
+ struct vnop_readdirattr_args /* {
struct vnode *a_vp;
struct attrlist *a_alist;
struct uio *a_uio;
u_long *a_newstate;
int *a_eofflag;
u_long *a_actualcount;
- u_long **a_cookies;
- struct ucred *a_cred;
+ vfs_context_t a_context;
} */ *ap;
{
struct vnode *dvp = ap->a_vp;
- struct cnode *dcp = VTOC(dvp);
- struct hfsmount * hfsmp = VTOHFS(dvp);
+ struct cnode *dcp;
+ struct hfsmount * hfsmp;
struct attrlist *alist = ap->a_alist;
- struct uio *uio = ap->a_uio;
+ uio_t uio = ap->a_uio;
int maxcount = ap->a_maxcount;
- struct proc *p = current_proc();
- u_long fixedblocksize;
- u_long maxattrblocksize;
- u_long currattrbufsize;
+ struct proc *p = vfs_context_proc(ap->a_context);
+ uint32_t fixedblocksize;
+ uint32_t maxattrblocksize;
+ uint32_t currattrbufsize;
void *attrbufptr = NULL;
void *attrptr;
void *varptr;
struct attrblock attrblk;
int error = 0;
int depleted = 0;
- int index, startindex;
+ int index;
int i, dir_entries;
struct cat_desc *lastdescp = NULL;
- struct cat_desc prevdesc;
- char * prevnamebuf = NULL;
struct cat_entrylist *ce_list = NULL;
-
- dir_entries = dcp->c_entries;
- if (dcp->c_attr.ca_fileid == kHFSRootFolderID && hfsmp->jnl) {
- dir_entries -= 3;
- }
+ directoryhint_t *dirhint = NULL;
+ unsigned int tag;
+ int shared_cnode_lock = 0;
*(ap->a_actualcount) = 0;
*(ap->a_eofflag) = 0;
-
- if (ap->a_cookies != NULL) {
- printf("readdirattr: no cookies!\n");
- return (EINVAL);
- }
/* Check for invalid options and buffer space. */
if (((ap->a_options & ~(FSOPT_NOINMEMUPDATE | FSOPT_NOFOLLOW)) != 0)
- || (uio->uio_resid <= 0) || (uio->uio_iovcnt > 1) || (maxcount <= 0))
+ || (uio_resid(uio) <= 0) || (uio_iovcnt(uio) > 1) || (maxcount <= 0))
return (EINVAL);
/* This call doesn't take volume attributes. */
((alist->fileattr & ~ATTR_FILE_VALIDMASK) != 0))
return (EINVAL);
+ if ((error = hfs_lock(VTOC(dvp), HFS_EXCLUSIVE_LOCK)))
+ return (error);
+ dcp = VTOC(dvp);
+ hfsmp = VTOHFS(dvp);
+
/* Reject requests for unsupported options. */
if ((alist->commonattr & (ATTR_CMN_NAMEDATTRCOUNT | ATTR_CMN_NAMEDATTRLIST |
ATTR_CMN_OBJPERMANENTID)) ||
(alist->fileattr & (ATTR_FILE_FILETYPE | ATTR_FILE_FORKCOUNT |
ATTR_FILE_FORKLIST | ATTR_FILE_DATAEXTENTS | ATTR_FILE_RSRCEXTENTS))) {
printf("readdirattr: unsupported attributes! (%s)\n", dcp->c_desc.cd_nameptr);
- return (EINVAL);
+ error = EINVAL;
+ goto exit;
+ }
+
+ dir_entries = dcp->c_entries;
+ if (dcp->c_attr.ca_fileid == kHFSRootFolderID && (hfsmp->jnl || ((HFSTOVCB(hfsmp)->vcbAtrb & kHFSVolumeJournaledMask) && (hfsmp->hfs_flags & HFS_READ_ONLY)))) {
+ dir_entries -= 3;
}
/* Convert uio_offset into a directory index. */
- startindex = index = uio->uio_offset / sizeof(struct dirent);
+ index = uio_offset(uio) & HFS_INDEX_MASK;
+ tag = uio_offset(uio) & ~HFS_INDEX_MASK;
if ((index + 1) > dir_entries) {
*(ap->a_eofflag) = 1;
error = 0;
}
/* Get a buffer to hold packed attributes. */
- fixedblocksize = (sizeof(u_long) + hfs_attrblksize(alist)); /* u_long for length */
+ fixedblocksize = (sizeof(uint32_t) + hfs_attrblksize(alist)); /* 4 bytes for length */
maxattrblocksize = fixedblocksize;
if (alist->commonattr & ATTR_CMN_NAME)
maxattrblocksize += kHFSPlusMaxFileNameBytes + 1;
bzero(ce_list, sizeof(*ce_list));
ce_list->maxentries = MAXCATENTRIES;
- /* Initialize a starting descriptor. */
- bzero(&prevdesc, sizeof(prevdesc));
- prevdesc.cd_flags = CD_DECOMPOSED;
- prevdesc.cd_hint = dcp->c_childhint;
- prevdesc.cd_parentcnid = dcp->c_cnid;
- prevdesc.cd_nameptr = hfs_getnamehint(dcp, index);
- prevdesc.cd_namelen = prevdesc.cd_nameptr ? strlen(prevdesc.cd_nameptr) : 0;
-
+ /* Get a directory hint (cnode must be locked exclusive) */
+ dirhint = hfs_getdirhint(dcp, ((index - 1) & HFS_INDEX_MASK) | tag);
+
+ /* Hide tag from catalog layer. */
+ dirhint->dh_index &= HFS_INDEX_MASK;
+ if (dirhint->dh_index == HFS_INDEX_MASK) {
+ dirhint->dh_index = -1;
+ }
+
+ /*
+ * An ATTR_CMN_USERACCESS attribute request can result in a
+ * call to kauth_cred_ismember_gid(). So when requesting
+ * this attribute we downgrade our exclusive lock on dcp to
+ * a shared lock in case kauth_cred_ismember_gid generates
+ * an indirect call back into the file system.
+ */
+ if (alist->commonattr & ATTR_CMN_USERACCESS) {
+ lck_rw_lock_exclusive_to_shared(&dcp->c_rwlock);
+ dcp->c_lockowner = HFS_SHARED_OWNER;
+ shared_cnode_lock = 1;
+ }
/*
* Obtain a list of catalog entries and pack their attributes until
* the output buffer is full or maxcount entries have been packed.
*/
while (!depleted) {
int maxentries;
+ int lockflags;
/* Constrain our list size. */
- maxentries = uio->uio_resid / (fixedblocksize + HFS_AVERAGE_NAME_SIZE);
+ maxentries = uio_resid(uio) / (fixedblocksize + HFS_AVERAGE_NAME_SIZE);
maxentries = min(maxentries, dcp->c_entries - index);
maxentries = min(maxentries, maxcount);
ce_list->maxentries = min(maxentries, ce_list->maxentries);
lastdescp = NULL;
- /* Lock catalog b-tree. */
- error = hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_SHARED, p);
- if (error)
- goto exit;
+ lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_SHARED_LOCK);
- error = cat_getentriesattr(hfsmp, &prevdesc, index, ce_list);
+ error = cat_getentriesattr(hfsmp, dirhint, ce_list);
/* Don't forget to release the descriptors later! */
- /* Unlock catalog b-tree. */
- (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_RELEASE, p);
+ hfs_systemfile_unlock(hfsmp, lockflags);
if (error == ENOENT) {
*(ap->a_eofflag) = TRUE;
break;
/* Process the catalog entries. */
- for (i = 0; i < ce_list->realentries; ++i) {
+ for (i = 0; i < (int)ce_list->realentries; ++i) {
struct cnode *cp = NULL;
struct vnode *vp = NULL;
- struct vnode *rvp = NULL;
struct cat_desc * cdescp;
struct cat_attr * cattrp;
- struct cat_fork c_datafork = {0};
- struct cat_fork c_rsrcfork = {0};
+ struct cat_fork c_datafork;
+ struct cat_fork c_rsrcfork;
+ bzero(&c_datafork, sizeof(c_datafork));
+ bzero(&c_rsrcfork, sizeof(c_rsrcfork));
cdescp = &ce_list->entry[i].ce_desc;
cattrp = &ce_list->entry[i].ce_attr;
c_datafork.cf_size = ce_list->entry[i].ce_datasize;
* Get in memory cnode data (if any).
*/
if (!(ap->a_options & FSOPT_NOINMEMUPDATE)) {
- cp = hfs_chashget(dcp->c_dev, cattrp->ca_fileid, 0, &vp, &rvp);
- if (cp != NULL) {
+ vp = hfs_chash_getvnode(dcp->c_dev, cattrp->ca_fileid, 0, 0);
+
+ if (vp != NULL) {
+ cp = VTOC(vp);
/* Only use cnode's decriptor for non-hardlinks */
if (!(cp->c_flag & C_HARDLINK))
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;
}
}
}
- *((u_long *)attrptr)++ = 0; /* move it past length */
+ *((uint32_t *)attrptr)++ = 0; /* move it past length */
attrblk.ab_attrlist = alist;
attrblk.ab_attrbufpp = &attrptr;
attrblk.ab_varbufpp = &varptr;
/* 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. */
- if (vp) {
- vput(vp);
+ if (vp != NULL) {
+ hfs_unlock(VTOC(vp));
+ vnode_put(vp);
vp = NULL;
- } else if (rvp) {
- vput(rvp);
- rvp = NULL;
+ cp = NULL;
}
- cp = NULL;
/* Make sure there's enough buffer space remaining. */
- if (currattrbufsize > uio->uio_resid) {
+ // LP64todo - fix this!
+ if (uio_resid(uio) < 0 || currattrbufsize > (uint32_t)uio_resid(uio)) {
depleted = 1;
break;
} else {
- *((u_long *)attrbufptr) = currattrbufsize;
+ *((uint32_t *)attrbufptr) = currattrbufsize;
error = uiomove((caddr_t)attrbufptr, currattrbufsize, ap->a_uio);
if (error != E_NONE) {
depleted = 1;
/* Termination checks */
if ((--maxcount <= 0) ||
- (uio->uio_resid < (fixedblocksize + HFS_AVERAGE_NAME_SIZE)) ||
+ // LP64todo - fix this!
+ uio_resid(uio) < 0 ||
+ ((uint32_t)uio_resid(uio) < (fixedblocksize + HFS_AVERAGE_NAME_SIZE)) ||
(index >= dir_entries)) {
depleted = 1;
break;
if (index < dir_entries
&& !(*(ap->a_eofflag))
&& lastdescp != NULL) {
- if (prevnamebuf == NULL)
- MALLOC(prevnamebuf, char *, kHFSPlusMaxFileNameBytes + 1, M_TEMP, M_WAITOK);
- bcopy(lastdescp->cd_nameptr, prevnamebuf, lastdescp->cd_namelen + 1);
- if (!depleted) {
- prevdesc.cd_hint = lastdescp->cd_hint;
- prevdesc.cd_nameptr = prevnamebuf;
- prevdesc.cd_namelen = lastdescp->cd_namelen + 1;
+
+ /* Remember last entry */
+ if (dirhint->dh_desc.cd_nameptr != NULL) {
+ vfs_removename(dirhint->dh_desc.cd_nameptr);
}
+ dirhint->dh_desc.cd_namelen = lastdescp->cd_namelen;
+ dirhint->dh_desc.cd_nameptr =
+ vfs_addname(lastdescp->cd_nameptr, lastdescp->cd_namelen, 0, 0);
+ dirhint->dh_index = index - 1;
+ dirhint->dh_desc.cd_cnid = lastdescp->cd_cnid;
+ dirhint->dh_desc.cd_hint = lastdescp->cd_hint;
+ dirhint->dh_desc.cd_encoding = lastdescp->cd_encoding;
}
/* All done with the catalog descriptors. */
- for (i = 0; i < ce_list->realentries; ++i)
+ for (i = 0; i < (int)ce_list->realentries; ++i)
cat_releasedesc(&ce_list->entry[i].ce_desc);
ce_list->realentries = 0;
} /* while not depleted */
*ap->a_newstate = dcp->c_mtime;
-
- /* All done with last name hint */
- hfs_relnamehint(dcp, startindex);
- startindex = 0;
- /* Convert directory index into uio_offset. */
- uio->uio_offset = index * sizeof(struct dirent);
+ /* Make sure dcp is locked exclusive before changing c_dirhinttag. */
+ if (shared_cnode_lock) {
+ /*
+ * If the upgrade fails we loose the lock and
+ * have to take the exclusive lock on our own.
+ */
+ if (lck_rw_lock_shared_to_exclusive(&dcp->c_rwlock) != 0)
+ lck_rw_lock_exclusive(&dcp->c_rwlock);
+ dcp->c_lockowner = current_thread();
+ shared_cnode_lock = 0;
+ }
- /* Save a name hint if there are more entries */
- if ((error == 0) && prevnamebuf && (index + 1) < dcp->c_entries)
- hfs_savenamehint(dcp, index, prevnamebuf);
-exit:
- if (startindex > 0)
- hfs_relnamehint(dcp, startindex);
+ /* Convert directory index back into a uio_offset. */
+ while (tag == 0) tag = (++dcp->c_dirhinttag) << HFS_INDEX_BITS;
+ uio_setoffset(uio, index | tag);
+ dirhint->dh_index |= tag;
+exit:
+ /* Drop directory hint on error or if there are no more entries */
+ if (dirhint && (error || index >= dir_entries)) {
+ if (shared_cnode_lock) {
+ /*
+ * If the upgrade fails we loose the lock and
+ * have to take the exclusive lock on our own.
+ */
+ if (lck_rw_lock_shared_to_exclusive(&dcp->c_rwlock) != 0)
+ lck_rw_lock_exclusive(&dcp->c_rwlock);
+ dcp->c_lockowner = current_thread();
+ }
+ hfs_reldirhint(dcp, dirhint);
+ }
if (attrbufptr)
FREE(attrbufptr, M_TEMP);
if (ce_list)
FREE(ce_list, M_TEMP);
- if (prevnamebuf)
- FREE(prevnamebuf, M_TEMP);
+ hfs_unlock(dcp);
return (error);
}
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);
} 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);
static char*
mountpointname(struct mount *mp)
{
- size_t namelength = strlen(mp->mnt_stat.f_mntonname);
+ size_t namelength = strlen(mp->mnt_vfsstat.f_mntonname);
int foundchars = 0;
char *c;
* the first slash encountered (which must precede the
* last part of the pathname).
*/
- for (c = mp->mnt_stat.f_mntonname + namelength - 1;
+ for (c = mp->mnt_vfsstat.f_mntonname + namelength - 1;
namelength > 0; --c, --namelength) {
if (*c != '/') {
foundchars = 1;
}
}
- return (mp->mnt_stat.f_mntonname);
+ return (mp->mnt_vfsstat.f_mntonname);
}
struct attrreference * attr_refptr;
char *mpname;
size_t mpnamelen;
- u_long attrlength;
+ uint32_t attrlength;
char empty = 0;
/* A cnode's name may be incorrect for the root of a mounted
* root directory, it's best to return the last element of the
location where the volume's mounted:
*/
- if ((vp != NULL) && (vp->v_flag & VROOT) &&
- (mpname = mountpointname(vp->v_mount))) {
+ if ((vp != NULL) && vnode_isvroot(vp) &&
+ (mpname = mountpointname(vnode_mount(vp)))) {
mpnamelen = strlen(mpname);
/* Trim off any trailing slashes: */
* 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;
struct cnode *cp = VTOC(vp);
struct mount *mp = VTOVFS(vp);
ExtendedVCB *vcb = HFSTOVCB(hfsmp);
- u_long attrlength;
+ u_int32_t attrlength;
+ boolean_t is_64_bit = proc_is64bit(p);
attr = abp->ab_attrlist->commonattr;
*((dev_t *)attrbufptr)++ = hfsmp->hfs_raw_dev;
}
if (ATTR_CMN_FSID & attr) {
- *((fsid_t *)attrbufptr) = mp->mnt_stat.f_fsid;
+ fsid_t fsid;
+
+ fsid.val[0] = (long)hfsmp->hfs_raw_dev;
+ fsid.val[1] = (long)vfs_typenum(mp);
+ *((fsid_t *)attrbufptr) = fsid;
++((fsid_t *)attrbufptr);
}
if (ATTR_CMN_OBJTYPE & attr) {
++((fsobj_id_t *)attrbufptr);
}
if (ATTR_CMN_SCRIPT & attr) {
- u_long encoding;
+ uint32_t encoding;
if (vcb->vcbSigWord == kHFSPlusSigWord)
encoding = vcb->volumeNameEncodingHint;
*((text_encoding_t *)attrbufptr)++ = encoding;
}
if (ATTR_CMN_CRTIME & attr) {
- ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbCrDate;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
+ if (is_64_bit) {
+ ((struct user_timespec *)attrbufptr)->tv_sec = vcb->vcbCrDate;
+ ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct user_timespec *)attrbufptr);
+ }
+ else {
+ ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbCrDate;
+ ((struct timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct timespec *)attrbufptr);
+ }
}
if (ATTR_CMN_MODTIME & attr) {
- ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
+ if (is_64_bit) {
+ ((struct user_timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
+ ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct user_timespec *)attrbufptr);
+ }
+ else {
+ ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
+ ((struct timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct timespec *)attrbufptr);
+ }
}
if (ATTR_CMN_CHGTIME & attr) {
- ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
+ if (is_64_bit) {
+ ((struct user_timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
+ ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct user_timespec *)attrbufptr);
+ }
+ else {
+ ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
+ ((struct timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct timespec *)attrbufptr);
+ }
}
if (ATTR_CMN_ACCTIME & attr) {
- ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
+ if (is_64_bit) {
+ ((struct user_timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
+ ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct user_timespec *)attrbufptr);
+ }
+ else {
+ ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
+ ((struct timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct timespec *)attrbufptr);
+ }
}
if (ATTR_CMN_BKUPTIME & attr) {
- ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbVolBkUp;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
+ if (is_64_bit) {
+ ((struct user_timespec *)attrbufptr)->tv_sec = vcb->vcbVolBkUp;
+ ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct user_timespec *)attrbufptr);
+ }
+ else {
+ ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbVolBkUp;
+ ((struct timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct timespec *)attrbufptr);
+ }
}
if (ATTR_CMN_FNDRINFO & attr) {
bcopy (&vcb->vcbFndrInfo, attrbufptr, sizeof(vcb->vcbFndrInfo));
}
if (ATTR_CMN_OWNERID & attr) {
if (cp->c_uid == UNKNOWNUID)
- *((uid_t *)attrbufptr)++ = console_user;
+ *((uid_t *)attrbufptr)++ = kauth_cred_getuid(proc_ucred(p));
else
*((uid_t *)attrbufptr)++ = cp->c_uid;
}
if (ATTR_CMN_GRPID & attr) {
*((gid_t *)attrbufptr)++ = cp->c_gid;
}
+
if (ATTR_CMN_ACCESSMASK & attr) {
/*
* [2856576] Since we are dynamically changing the owner, also
* a security hole where set-user-id programs run as whoever is
* logged on (or root if nobody is logged in yet!)
*/
- *((u_long *)attrbufptr)++ =
+ *((uint32_t *)attrbufptr)++ =
(cp->c_uid == UNKNOWNUID) ? cp->c_mode & ~(S_ISUID | S_ISGID) : cp->c_mode;
}
if (ATTR_CMN_NAMEDATTRCOUNT & attr) {
- *((u_long *)attrbufptr)++ = 0; /* XXX PPD TBC */
+ *((uint32_t *)attrbufptr)++ = 0; /* XXX PPD TBC */
}
if (ATTR_CMN_NAMEDATTRLIST & attr) {
attrlength = 0;
++((struct attrreference *)attrbufptr);
}
if (ATTR_CMN_FLAGS & attr) {
- *((u_long *)attrbufptr)++ = cp->c_flags;
+ *((uint32_t *)attrbufptr)++ = cp->c_flags;
}
if (ATTR_CMN_USERACCESS & attr) {
- *((u_long *)attrbufptr)++ =
+ *((uint32_t *)attrbufptr)++ =
DerivePermissionSummary(cp->c_uid, cp->c_gid, cp->c_mode,
- VTOVFS(vp), current_proc()->p_ucred, current_proc());
+ VTOVFS(vp), kauth_cred_get(), proc_self());
}
*abp->ab_attrbufpp = attrbufptr;
struct cnode *cp = VTOC(vp);
struct mount *mp = VTOVFS(vp);
ExtendedVCB *vcb = HFSTOVCB(hfsmp);
- u_long attrlength;
+ uint32_t attrlength;
attr = abp->ab_attrlist->volattr;
if (ATTR_VOL_FSTYPE & attr) {
- *((u_long *)attrbufptr)++ = (u_long)mp->mnt_vfc->vfc_typenum;
+ *((uint32_t *)attrbufptr)++ = (uint32_t)vfs_typenum(mp);
}
if (ATTR_VOL_SIGNATURE & attr) {
- *((u_long *)attrbufptr)++ = (u_long)vcb->vcbSigWord;
+ *((uint32_t *)attrbufptr)++ = (uint32_t)vcb->vcbSigWord;
}
if (ATTR_VOL_SIZE & attr) {
*((off_t *)attrbufptr)++ =
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) *
*((off_t *)attrbufptr)++ = (off_t)(vcb->vcbClpSiz);
}
if (ATTR_VOL_IOBLOCKSIZE & attr) {
- *((u_long *)attrbufptr)++ = (u_long)hfsmp->hfs_logBlockSize;
+ *((uint32_t *)attrbufptr)++ = hfsmp->hfs_logBlockSize;
}
if (ATTR_VOL_OBJCOUNT & attr) {
- *((u_long *)attrbufptr)++ =
- (u_long)vcb->vcbFilCnt + (u_long)vcb->vcbDirCnt;
+ *((uint32_t *)attrbufptr)++ =
+ (uint32_t)vcb->vcbFilCnt + (uint32_t)vcb->vcbDirCnt;
}
if (ATTR_VOL_FILECOUNT & attr) {
- *((u_long *)attrbufptr)++ = (u_long)vcb->vcbFilCnt;
+ *((uint32_t *)attrbufptr)++ = (uint32_t)vcb->vcbFilCnt;
}
if (ATTR_VOL_DIRCOUNT & attr) {
- *((u_long *)attrbufptr)++ = (u_long)vcb->vcbDirCnt;
+ *((uint32_t *)attrbufptr)++ = (uint32_t)vcb->vcbDirCnt;
}
if (ATTR_VOL_MAXOBJCOUNT & attr) {
- *((u_long *)attrbufptr)++ = 0xFFFFFFFF;
+ *((uint32_t *)attrbufptr)++ = 0xFFFFFFFF;
}
if (ATTR_VOL_MOUNTPOINT & attr) {
((struct attrreference *)attrbufptr)->attr_dataoffset =
(char *)varbufptr - (char *)attrbufptr;
((struct attrreference *)attrbufptr)->attr_length =
- strlen(mp->mnt_stat.f_mntonname) + 1;
+ strlen(mp->mnt_vfsstat.f_mntonname) + 1;
attrlength = ((struct attrreference *)attrbufptr)->attr_length;
/* round up to the next 4-byte boundary: */
attrlength = attrlength + ((4 - (attrlength & 3)) & 3);
- (void) bcopy(mp->mnt_stat.f_mntonname, varbufptr, attrlength);
+ (void) bcopy(mp->mnt_vfsstat.f_mntonname, varbufptr, attrlength);
/* Advance beyond the space just allocated: */
(char *)varbufptr += attrlength;
(char *)varbufptr += attrlength;
++((struct attrreference *)attrbufptr);
}
- if (ATTR_VOL_MOUNTFLAGS & attr) {
- *((u_long *)attrbufptr)++ = (u_long)mp->mnt_flag;
- }
+ if (ATTR_VOL_MOUNTFLAGS & attr) {
+ *((uint32_t *)attrbufptr)++ = (uint32_t)vfs_flags(mp);
+ }
if (ATTR_VOL_MOUNTEDDEVICE & attr) {
((struct attrreference *)attrbufptr)->attr_dataoffset =
(char *)varbufptr - (char *)attrbufptr;
((struct attrreference *)attrbufptr)->attr_length =
- strlen(mp->mnt_stat.f_mntfromname) + 1;
+ strlen(mp->mnt_vfsstat.f_mntfromname) + 1;
attrlength = ((struct attrreference *)attrbufptr)->attr_length;
/* round up to the next 4-byte boundary: */
attrlength = attrlength + ((4 - (attrlength & 3)) & 3);
- (void) bcopy(mp->mnt_stat.f_mntfromname, varbufptr, attrlength);
+ (void) bcopy(mp->mnt_vfsstat.f_mntfromname, varbufptr, attrlength);
/* Advance beyond the space just allocated: */
(char *)varbufptr += attrlength;
vcapattrptr = (vol_capabilities_attr_t *)attrbufptr;
if (vcb->vcbSigWord == kHFSPlusSigWord) {
+ u_int32_t journal_active_cap;
+ u_int32_t case_sensitive;
+
+ if (hfsmp->jnl)
+ journal_active_cap = VOL_CAP_FMT_JOURNAL_ACTIVE;
+ else
+ journal_active_cap = 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_cap |
+ case_sensitive |
+ VOL_CAP_FMT_CASE_PRESERVING |
+ VOL_CAP_FMT_FAST_STATFS |
+ VOL_CAP_FMT_2TB_FILESIZE;
} 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 |
+ VOL_CAP_FMT_2TB_FILESIZE;
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);
void *attrbufptr = *abp->ab_attrbufpp;
void *varbufptr = *abp->ab_varbufpp;
- u_long attrlength = 0;
+ uint32_t attrlength = 0;
+ boolean_t is_64_bit = proc_is64bit(p);
if (ATTR_CMN_NAME & attr) {
packnameattr(abp, vp, cdp->cd_nameptr, cdp->cd_namelen);
*((dev_t *)attrbufptr)++ = hfsmp->hfs_raw_dev;
}
if (ATTR_CMN_FSID & attr) {
- *((fsid_t *)attrbufptr) = mp->mnt_stat.f_fsid;
+ fsid_t fsid;
+
+ fsid.val[0] = (long)hfsmp->hfs_raw_dev;
+ fsid.val[1] = (long)vfs_typenum(mp);
+ *((fsid_t *)attrbufptr) = fsid;
++((fsid_t *)attrbufptr);
}
if (ATTR_CMN_OBJTYPE & attr) {
* and Carbon APIs, which are hardlink-ignorant, will always
* receive the c_cnid (from getattrlist).
*/
- if (ATTR_CMN_OBJID & attr) {
+ if (ATTR_CMN_OBJID & attr) {
((fsobj_id_t *)attrbufptr)->fid_objno = cdp->cd_cnid;
((fsobj_id_t *)attrbufptr)->fid_generation = 0;
++((fsobj_id_t *)attrbufptr);
*((text_encoding_t *)attrbufptr)++ = cdp->cd_encoding;
}
if (ATTR_CMN_CRTIME & attr) {
- ((struct timespec *)attrbufptr)->tv_sec = cap->ca_itime;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
+ if (is_64_bit) {
+ ((struct user_timespec *)attrbufptr)->tv_sec = cap->ca_itime;
+ ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct user_timespec *)attrbufptr);
+ }
+ else {
+ ((struct timespec *)attrbufptr)->tv_sec = cap->ca_itime;
+ ((struct timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct timespec *)attrbufptr);
+ }
}
if (ATTR_CMN_MODTIME & attr) {
- ((struct timespec *)attrbufptr)->tv_sec = cap->ca_mtime;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
+ if (is_64_bit) {
+ ((struct user_timespec *)attrbufptr)->tv_sec = cap->ca_mtime;
+ ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct user_timespec *)attrbufptr);
+ }
+ else {
+ ((struct timespec *)attrbufptr)->tv_sec = cap->ca_mtime;
+ ((struct timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct timespec *)attrbufptr);
+ }
}
if (ATTR_CMN_CHGTIME & attr) {
- ((struct timespec *)attrbufptr)->tv_sec = cap->ca_ctime;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
+ if (is_64_bit) {
+ ((struct user_timespec *)attrbufptr)->tv_sec = cap->ca_ctime;
+ ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct user_timespec *)attrbufptr);
+ }
+ else {
+ ((struct timespec *)attrbufptr)->tv_sec = cap->ca_ctime;
+ ((struct timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct timespec *)attrbufptr);
+ }
}
if (ATTR_CMN_ACCTIME & attr) {
- ((struct timespec *)attrbufptr)->tv_sec = cap->ca_atime;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
+ if (is_64_bit) {
+ ((struct user_timespec *)attrbufptr)->tv_sec = cap->ca_atime;
+ ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct user_timespec *)attrbufptr);
+ }
+ else {
+ ((struct timespec *)attrbufptr)->tv_sec = cap->ca_atime;
+ ((struct timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct timespec *)attrbufptr);
+ }
}
if (ATTR_CMN_BKUPTIME & attr) {
- ((struct timespec *)attrbufptr)->tv_sec = cap->ca_btime;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
+ if (is_64_bit) {
+ ((struct user_timespec *)attrbufptr)->tv_sec = cap->ca_btime;
+ ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct user_timespec *)attrbufptr);
+ }
+ else {
+ ((struct timespec *)attrbufptr)->tv_sec = cap->ca_btime;
+ ((struct timespec *)attrbufptr)->tv_nsec = 0;
+ ++((struct timespec *)attrbufptr);
+ }
}
if (ATTR_CMN_FNDRINFO & attr) {
bcopy(&cap->ca_finderinfo, attrbufptr, sizeof(u_int8_t) * 32);
}
if (ATTR_CMN_OWNERID & attr) {
*((uid_t *)attrbufptr)++ =
- (cap->ca_uid == UNKNOWNUID) ? console_user : cap->ca_uid;
+ (cap->ca_uid == UNKNOWNUID) ? kauth_cred_getuid(proc_ucred(p)) : cap->ca_uid;
}
if (ATTR_CMN_GRPID & attr) {
*((gid_t *)attrbufptr)++ = cap->ca_gid;
* a security hole where set-user-id programs run as whoever is
* logged on (or root if nobody is logged in yet!)
*/
- *((u_long *)attrbufptr)++ =
+ *((uint32_t *)attrbufptr)++ =
(cap->ca_uid == UNKNOWNUID) ? cap->ca_mode & ~(S_ISUID | S_ISGID) : cap->ca_mode;
}
if (ATTR_CMN_NAMEDATTRCOUNT & attr) {
- *((u_long *)attrbufptr)++ = 0;
+ *((uint32_t *)attrbufptr)++ = 0;
}
if (ATTR_CMN_NAMEDATTRLIST & attr) {
attrlength = 0;
++((struct attrreference *)attrbufptr);
}
if (ATTR_CMN_FLAGS & attr) {
- *((u_long *)attrbufptr)++ = cap->ca_flags;
+ *((uint32_t *)attrbufptr)++ = cap->ca_flags;
}
if (ATTR_CMN_USERACCESS & attr) {
- *((u_long *)attrbufptr)++ =
+ *((uint32_t *)attrbufptr)++ =
DerivePermissionSummary(cap->ca_uid, cap->ca_gid,
- cap->ca_mode, mp, current_proc()->p_ucred,
+ cap->ca_mode, mp, proc_ucred(current_proc()),
current_proc());
}
void *attrbufptr = *abp->ab_attrbufpp;
if (ATTR_DIR_LINKCOUNT & attr)
- *((u_long *)attrbufptr)++ = cattrp->ca_nlink;
+ *((uint32_t *)attrbufptr)++ = cattrp->ca_nlink;
if (ATTR_DIR_ENTRYCOUNT & attr) {
- u_long entries = cattrp->ca_entries;
+ uint32_t entries = cattrp->ca_entries;
- if (descp->cd_parentcnid == kRootParID) {
- if (hfsmp->hfs_private_metadata_dir != 0)
+ if (descp->cd_parentcnid == kHFSRootParentID) {
+ if (hfsmp->hfs_privdir_desc.cd_cnid != 0)
--entries; /* hide private dir */
- if (hfsmp->jnl)
+ if (hfsmp->jnl || ((HFSTOVCB(hfsmp)->vcbAtrb & kHFSVolumeJournaledMask) && (hfsmp->hfs_flags & HFS_READ_ONLY)))
entries -= 2; /* hide the journal files */
}
- *((u_long *)attrbufptr)++ = entries;
+ *((uint32_t *)attrbufptr)++ = entries;
}
if (ATTR_DIR_MOUNTSTATUS & attr) {
- if (vp != NULL && vp->v_mountedhere != NULL)
- *((u_long *)attrbufptr)++ = DIR_MNTSTATUS_MNTPOINT;
+ if (vp != NULL && vnode_mountedhere(vp) != NULL)
+ *((uint32_t *)attrbufptr)++ = DIR_MNTSTATUS_MNTPOINT;
else
- *((u_long *)attrbufptr)++ = 0;
+ *((uint32_t *)attrbufptr)++ = 0;
}
*abp->ab_attrbufpp = attrbufptr;
}
attrgroup_t attr = abp->ab_attrlist->fileattr;
void *attrbufptr = *abp->ab_attrbufpp;
void *varbufptr = *abp->ab_varbufpp;
- u_long attrlength;
- u_long allocblksize;
+ uint32_t attrlength;
+ uint32_t allocblksize;
allocblksize = HFSTOVCB(hfsmp)->blockSize;
if (ATTR_FILE_LINKCOUNT & attr) {
- *((u_long *)attrbufptr)++ = cattrp->ca_nlink;
+ *((uint32_t *)attrbufptr)++ = cattrp->ca_nlink;
}
if (ATTR_FILE_TOTALSIZE & attr) {
*((off_t *)attrbufptr)++ = datafork->cf_size + rsrcfork->cf_size;
(off_t)cattrp->ca_blocks * (off_t)allocblksize;
}
if (ATTR_FILE_IOBLOCKSIZE & attr) {
- *((u_long *)attrbufptr)++ = hfsmp->hfs_logBlockSize;
+ *((uint32_t *)attrbufptr)++ = hfsmp->hfs_logBlockSize;
}
if (ATTR_FILE_CLUMPSIZE & attr) {
- *((u_long *)attrbufptr)++ = datafork->cf_clump; /* XXX ambiguity */
+ *((uint32_t *)attrbufptr)++ = HFSTOVCB(hfsmp)->vcbClpSiz;
}
if (ATTR_FILE_DEVTYPE & attr) {
if (S_ISBLK(cattrp->ca_mode) || S_ISCHR(cattrp->ca_mode))
- *((u_long *)attrbufptr)++ = (u_long)cattrp->ca_rdev;
+ *((uint32_t *)attrbufptr)++ = (uint32_t)cattrp->ca_rdev;
else
- *((u_long *)attrbufptr)++ = 0;
+ *((uint32_t *)attrbufptr)++ = 0;
}
if (ATTR_FILE_FILETYPE & attr) {
- *((u_long *)attrbufptr)++ = 0;
+ *((uint32_t *)attrbufptr)++ = 0;
}
if (ATTR_FILE_FORKCOUNT & attr) {
- *((u_long *)attrbufptr)++ = 2;
+ *((uint32_t *)attrbufptr)++ = 2;
}
if (ATTR_FILE_FORKLIST & attr) {
attrlength = 0;
*abp->ab_varbufpp = varbufptr;
}
-
-static void
+#if 0
+static int
unpackattrblk(struct attrblock *abp, struct vnode *vp)
{
struct attrlist *attrlistp = abp->ab_attrlist;
+ int error;
- if (attrlistp->volattr)
- unpackvolattr(abp, VTOHFS(vp), vp);
- else if (attrlistp->commonattr)
+ if (attrlistp->volattr) {
+ error = unpackvolattr(abp, VTOHFS(vp), vp);
+ if (error)
+ return (error);
+ } else if (attrlistp->commonattr) {
unpackcommonattr(abp, vp);
+ }
+ return (0);
}
attrgroup_t attr = abp->ab_attrlist->commonattr;
void *attrbufptr = *abp->ab_attrbufpp;
struct cnode *cp = VTOC(vp);
+ boolean_t is_64_bit = proc_is64bit(current_proc());
if (ATTR_CMN_SCRIPT & attr) {
cp->c_encoding = (u_int32_t)*((text_encoding_t *)attrbufptr)++;
hfs_setencodingbits(VTOHFS(vp), cp->c_encoding);
}
if (ATTR_CMN_CRTIME & attr) {
- cp->c_itime = ((struct timespec *)attrbufptr)->tv_sec;
- ++((struct timespec *)attrbufptr);
+ if (is_64_bit) {
+ cp->c_itime = ((struct user_timespec *)attrbufptr)->tv_sec;
+ ++((struct user_timespec *)attrbufptr);
+ }
+ else {
+ cp->c_itime = ((struct timespec *)attrbufptr)->tv_sec;
+ ++((struct timespec *)attrbufptr);
+ }
}
if (ATTR_CMN_MODTIME & attr) {
cp->c_mtime = ((struct timespec *)attrbufptr)->tv_sec;
- cp->c_mtime_nsec = ((struct timespec *)attrbufptr)->tv_nsec;
++((struct timespec *)attrbufptr);
- cp->c_flag &= ~C_UPDATE;
+ cp->c_touch_modtime = FALSE;
}
if (ATTR_CMN_CHGTIME & attr) {
cp->c_ctime = ((struct timespec *)attrbufptr)->tv_sec;
++((struct timespec *)attrbufptr);
- cp->c_flag &= ~C_CHANGE;
+ cp->c_touch_chgtime = FALSE;
}
if (ATTR_CMN_ACCTIME & attr) {
cp->c_atime = ((struct timespec *)attrbufptr)->tv_sec;
++((struct timespec *)attrbufptr);
- cp->c_flag &= ~C_ACCESS;
+ cp->c_touch_acctime = FALSE;
}
if (ATTR_CMN_BKUPTIME & attr) {
cp->c_btime = ((struct timespec *)attrbufptr)->tv_sec;
}
}
if (ATTR_CMN_ACCESSMASK & attr) {
- u_int16_t mode = (u_int16_t)*((u_long *)attrbufptr)++;
+ u_int16_t mode = (u_int16_t)*((uint32_t *)attrbufptr)++;
if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
if (mode != (mode_t)VNOVAL) {
cp->c_mode &= ~ALLPERMS;
}
}
if (ATTR_CMN_FLAGS & attr) {
- u_long flags = *((u_long *)attrbufptr)++;
+ uint32_t flags = *((uint32_t *)attrbufptr)++;
/*
* Flags are settable only on HFS+ volumes. A special
* exception is made for the IMMUTABLE flags
if ((VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) ||
((VTOVCB(vp)->vcbSigWord == kHFSSigWord) &&
((flags & ~IMMUTABLE) == 0))) {
- if (flags != (u_long)VNOVAL) {
+ if (flags != (uint32_t)VNOVAL) {
cp->c_flags = flags;
}
}
}
-static void
+static int
unpackvolattr(
struct attrblock *abp,
struct hfsmount *hfsmp,
- struct vnode *rootvp)
+ struct vnode *root_vp)
{
void *attrbufptr = *abp->ab_attrbufpp;
- ExtendedVCB *vcb = HFSTOVCB(hfsmp);
attrgroup_t attr;
+ int error = 0;
+ boolean_t is_64_bit = proc_is64bit(current_proc());
+
+ HFS_MOUNT_LOCK(hfsmp, TRUE);
attr = abp->ab_attrlist->commonattr;
if (attr == 0)
goto volattr;
if (ATTR_CMN_SCRIPT & attr) {
- vcb->volumeNameEncodingHint =
+ hfsmp->volumeNameEncodingHint =
(u_int32_t)*(((text_encoding_t *)attrbufptr)++);
}
if (ATTR_CMN_CRTIME & attr) {
- vcb->vcbCrDate = ((struct timespec *)attrbufptr)->tv_sec;
- ++((struct timespec *)attrbufptr);
+ if (is_64_bit) {
+ hfsmp->vcbCrDate = ((struct user_timespec *)attrbufptr)->tv_sec;
+ ++((struct user_timespec *)attrbufptr);
+ }
+ else {
+ hfsmp->vcbCrDate = ((struct timespec *)attrbufptr)->tv_sec;
+ ++((struct timespec *)attrbufptr);
+ }
/* The volume's create date comes from the root directory */
- VTOC(rootvp)->c_itime = vcb->vcbCrDate;
- VTOC(rootvp)->c_flag |= C_MODIFIED;
+ VTOC(root_vp)->c_itime = hfsmp->vcbCrDate;
+ VTOC(root_vp)->c_flag |= C_MODIFIED;
/*
* XXX Should we also do a relative change to the
* the volume header's create date in local time?
*/
}
if (ATTR_CMN_MODTIME & attr) {
- vcb->vcbLsMod = ((struct timespec *)attrbufptr)->tv_sec;
+ hfsmp->vcbLsMod = ((struct timespec *)attrbufptr)->tv_sec;
++((struct timespec *)attrbufptr);
}
if (ATTR_CMN_BKUPTIME & attr) {
- vcb->vcbVolBkUp = ((struct timespec *)attrbufptr)->tv_sec;
+ hfsmp->vcbVolBkUp = ((struct timespec *)attrbufptr)->tv_sec;
++((struct timespec *)attrbufptr);
}
if (ATTR_CMN_FNDRINFO & attr) {
- bcopy(attrbufptr, &vcb->vcbFndrInfo, sizeof(vcb->vcbFndrInfo));
- (char *)attrbufptr += sizeof(vcb->vcbFndrInfo);
+ bcopy(attrbufptr, &hfsmp->vcbFndrInfo, sizeof(hfsmp->vcbFndrInfo));
+ (char *)attrbufptr += sizeof(hfsmp->vcbFndrInfo);
}
volattr:
* It could be empty or garbage (bad UTF-8).
*/
if (ATTR_VOL_NAME & attr) {
- copystr(((char *)attrbufptr) + *((u_long *)attrbufptr),
- vcb->vcbVN, sizeof(vcb->vcbVN), NULL);
- (char *)attrbufptr += sizeof(struct attrreference);
+ attrreference_t * attr_refp = (attrreference_t *) attrbufptr;
+
+ error = copystr(((char *)attrbufptr) + attr_refp->attr_dataoffset,
+ hfsmp->vcbVN, MIN(attr_refp->attr_length, sizeof(hfsmp->vcbVN)),
+ NULL);
+ if (error == 0)
+ (char *)attrbufptr += sizeof(struct attrreference);
}
*abp->ab_attrbufpp = attrbufptr;
- vcb->vcbFlags |= 0xFF00;
+ hfsmp->vcbFlags |= 0xFF00;
+ HFS_MOUNT_UNLOCK(hfsmp, TRUE);
+
+ return (error);
}
+#endif
/*
* Calculate the total size of an attribute block.
{
int size;
attrgroup_t a;
+ int sizeof_timespec;
+ boolean_t is_64_bit = proc_is64bit(current_proc());
+ if (is_64_bit)
+ sizeof_timespec = sizeof(struct user_timespec);
+ else
+ sizeof_timespec = sizeof(struct timespec);
+
#if ((ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | ATTR_CMN_OBJTYPE | \
ATTR_CMN_OBJTAG | ATTR_CMN_OBJID | ATTR_CMN_OBJPERMANENTID | \
ATTR_CMN_PAROBJID | ATTR_CMN_SCRIPT | ATTR_CMN_CRTIME | \
if (a & ATTR_CMN_OBJPERMANENTID) size += sizeof(fsobj_id_t);
if (a & ATTR_CMN_PAROBJID) size += sizeof(fsobj_id_t);
if (a & ATTR_CMN_SCRIPT) size += sizeof(text_encoding_t);
- if (a & ATTR_CMN_CRTIME) size += sizeof(struct timespec);
- if (a & ATTR_CMN_MODTIME) size += sizeof(struct timespec);
- if (a & ATTR_CMN_CHGTIME) size += sizeof(struct timespec);
- if (a & ATTR_CMN_ACCTIME) size += sizeof(struct timespec);
- if (a & ATTR_CMN_BKUPTIME) size += sizeof(struct timespec);
+ if (a & ATTR_CMN_CRTIME) size += sizeof_timespec;
+ if (a & ATTR_CMN_MODTIME) size += sizeof_timespec;
+ if (a & ATTR_CMN_CHGTIME) size += sizeof_timespec;
+ if (a & ATTR_CMN_ACCTIME) size += sizeof_timespec;
+ if (a & ATTR_CMN_BKUPTIME) size += sizeof_timespec;
if (a & ATTR_CMN_FNDRINFO) size += 32 * sizeof(u_int8_t);
if (a & ATTR_CMN_OWNERID) size += sizeof(uid_t);
if (a & ATTR_CMN_GRPID) size += sizeof(gid_t);
- if (a & ATTR_CMN_ACCESSMASK) size += sizeof(u_long);
- if (a & ATTR_CMN_NAMEDATTRCOUNT) size += sizeof(u_long);
+ if (a & ATTR_CMN_ACCESSMASK) size += sizeof(uint32_t);
+ if (a & ATTR_CMN_NAMEDATTRCOUNT) size += sizeof(uint32_t);
if (a & ATTR_CMN_NAMEDATTRLIST) size += sizeof(struct attrreference);
- if (a & ATTR_CMN_FLAGS) size += sizeof(u_long);
- if (a & ATTR_CMN_USERACCESS) size += sizeof(u_long);
+ if (a & ATTR_CMN_FLAGS) size += sizeof(uint32_t);
+ if (a & ATTR_CMN_USERACCESS) size += sizeof(uint32_t);
};
if ((a = attrlist->volattr) != 0) {
- if (a & ATTR_VOL_FSTYPE) size += sizeof(u_long);
- if (a & ATTR_VOL_SIGNATURE) size += sizeof(u_long);
+ if (a & ATTR_VOL_FSTYPE) size += sizeof(uint32_t);
+ if (a & ATTR_VOL_SIGNATURE) size += sizeof(uint32_t);
if (a & ATTR_VOL_SIZE) size += sizeof(off_t);
if (a & ATTR_VOL_SPACEFREE) size += sizeof(off_t);
if (a & ATTR_VOL_SPACEAVAIL) size += sizeof(off_t);
if (a & ATTR_VOL_MINALLOCATION) size += sizeof(off_t);
if (a & ATTR_VOL_ALLOCATIONCLUMP) size += sizeof(off_t);
- if (a & ATTR_VOL_IOBLOCKSIZE) size += sizeof(u_long);
- if (a & ATTR_VOL_OBJCOUNT) size += sizeof(u_long);
- if (a & ATTR_VOL_FILECOUNT) size += sizeof(u_long);
- if (a & ATTR_VOL_DIRCOUNT) size += sizeof(u_long);
- if (a & ATTR_VOL_MAXOBJCOUNT) size += sizeof(u_long);
+ if (a & ATTR_VOL_IOBLOCKSIZE) size += sizeof(uint32_t);
+ if (a & ATTR_VOL_OBJCOUNT) size += sizeof(uint32_t);
+ if (a & ATTR_VOL_FILECOUNT) size += sizeof(uint32_t);
+ if (a & ATTR_VOL_DIRCOUNT) size += sizeof(uint32_t);
+ if (a & ATTR_VOL_MAXOBJCOUNT) size += sizeof(uint32_t);
if (a & ATTR_VOL_MOUNTPOINT) size += sizeof(struct attrreference);
if (a & ATTR_VOL_NAME) size += sizeof(struct attrreference);
- if (a & ATTR_VOL_MOUNTFLAGS) size += sizeof(u_long);
+ if (a & ATTR_VOL_MOUNTFLAGS) size += sizeof(uint32_t);
if (a & ATTR_VOL_MOUNTEDDEVICE) size += sizeof(struct attrreference);
if (a & ATTR_VOL_ENCODINGSUSED) size += sizeof(unsigned long long);
if (a & ATTR_VOL_CAPABILITIES) size += sizeof(vol_capabilities_attr_t);
if (a & ATTR_VOL_ATTRIBUTES) size += sizeof(vol_attributes_attr_t);
};
if ((a = attrlist->dirattr) != 0) {
- if (a & ATTR_DIR_LINKCOUNT) size += sizeof(u_long);
- if (a & ATTR_DIR_ENTRYCOUNT) size += sizeof(u_long);
- if (a & ATTR_DIR_MOUNTSTATUS) size += sizeof(u_long);
+ if (a & ATTR_DIR_LINKCOUNT) size += sizeof(uint32_t);
+ if (a & ATTR_DIR_ENTRYCOUNT) size += sizeof(uint32_t);
+ if (a & ATTR_DIR_MOUNTSTATUS) size += sizeof(uint32_t);
};
if ((a = attrlist->fileattr) != 0) {
- if (a & ATTR_FILE_LINKCOUNT) size += sizeof(u_long);
+ if (a & ATTR_FILE_LINKCOUNT) size += sizeof(uint32_t);
if (a & ATTR_FILE_TOTALSIZE) size += sizeof(off_t);
if (a & ATTR_FILE_ALLOCSIZE) size += sizeof(off_t);
- if (a & ATTR_FILE_IOBLOCKSIZE) size += sizeof(size_t);
- if (a & ATTR_FILE_CLUMPSIZE) size += sizeof(off_t);
- if (a & ATTR_FILE_DEVTYPE) size += sizeof(u_long);
- if (a & ATTR_FILE_FILETYPE) size += sizeof(u_long);
- if (a & ATTR_FILE_FORKCOUNT) size += sizeof(u_long);
+ if (a & ATTR_FILE_IOBLOCKSIZE) size += sizeof(uint32_t);
+ if (a & ATTR_FILE_CLUMPSIZE) size += sizeof(uint32_t);
+ if (a & ATTR_FILE_DEVTYPE) size += sizeof(uint32_t);
+ if (a & ATTR_FILE_FILETYPE) size += sizeof(uint32_t);
+ if (a & ATTR_FILE_FORKCOUNT) size += sizeof(uint32_t);
if (a & ATTR_FILE_FORKLIST) size += sizeof(struct attrreference);
if (a & ATTR_FILE_DATALENGTH) size += sizeof(off_t);
if (a & ATTR_FILE_DATAALLOCSIZE) size += sizeof(off_t);
__private_extern__
unsigned long
DerivePermissionSummary(uid_t obj_uid, gid_t obj_gid, mode_t obj_mode,
- struct mount *mp, struct ucred *cred, struct proc *p)
+ struct mount *mp, kauth_cred_t cred, struct proc *p)
{
- register gid_t *gp;
unsigned long permissions;
- int i;
if (obj_uid == UNKNOWNUID)
- obj_uid = console_user;
+ obj_uid = kauth_cred_getuid(proc_ucred(p));
/* User id 0 (root) always gets access. */
- if (cred->cr_uid == 0) {
+ if (!suser(cred, NULL)) {
permissions = R_OK | W_OK | X_OK;
goto Exit;
};
}
/* Otherwise, check the groups. */
- if (! (mp->mnt_flag & MNT_UNKNOWNPERMISSIONS)) {
- for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) {
- if (obj_gid == *gp) {
- permissions = ((unsigned long)obj_mode & S_IRWXG) >> 3;
- goto Exit;
- }
+ if (! (((unsigned int)vfs_flags(mp)) & MNT_UNKNOWNPERMISSIONS)) {
+ int is_member;
+
+ if (kauth_cred_ismember_gid(cred, obj_gid, &is_member) == 0 && is_member) {
+ permissions = ((unsigned long)obj_mode & S_IRWXG) >> 3;
+ goto Exit;
}
}