static int nullfs_getattr(struct vnop_getattr_args * args) { int error; struct null_mount * null_mp = MOUNTTONULLMOUNT(vnode_mount(args->a_vp)); NULLFSDEBUG("%s %p\n", __FUNCTION__, args->a_vp); lck_mtx_lock(&null_mp->nullm_lock); if (nullfs_isspecialvp(args->a_vp)) { error = nullfs_special_getattr(args); lck_mtx_unlock(&null_mp->nullm_lock); return error; } lck_mtx_unlock(&null_mp->nullm_lock); /* this will return a different inode for third than read dir will */ struct vnode * lowervp = NULLVPTOLOWERVP(args->a_vp); error = vnode_getwithref(lowervp); if (error == 0) { error = VNOP_GETATTR(lowervp, args->a_vap, args->a_context); vnode_put(lowervp); if (error == 0) { /* fix up fsid so it doesn't say the underlying fs*/ VATTR_RETURN(args->a_vap, va_fsid, vfs_statfs(vnode_mount(args->a_vp))->f_fsid.val[0]); } } return error; }
static int devfs_getattr(struct vnop_getattr_args *ap) /*struct vnop_getattr_args { struct vnode *a_vp; struct vnode_attr *a_vap; kauth_cred_t a_cred; struct proc *a_p; } */ { struct vnode *vp = ap->a_vp; struct vnode_attr *vap = ap->a_vap; devnode_t * file_node; struct timeval now; DEVFS_LOCK(); file_node = VTODN(vp); microtime(&now); dn_times(file_node, &now, &now, &now); VATTR_RETURN(vap, va_mode, file_node->dn_mode); /* * Note: for DEV_CDEV and DEV_BDEV, we return the device from * the vp, not the file_node; if we getting information on a * cloning device, we want the cloned information, not the template. */ switch (file_node->dn_type) { case DEV_DIR: VATTR_RETURN(vap, va_rdev, (dev_t)file_node->dn_dvm); vap->va_mode |= (S_IFDIR); break; case DEV_CDEV: VATTR_RETURN(vap, va_rdev, vp->v_rdev); vap->va_mode |= (S_IFCHR); break; case DEV_BDEV: VATTR_RETURN(vap, va_rdev, vp->v_rdev); vap->va_mode |= (S_IFBLK); break; case DEV_SLNK: VATTR_RETURN(vap, va_rdev, 0); vap->va_mode |= (S_IFLNK); break; default: VATTR_RETURN(vap, va_rdev, 0); /* default value only */ } VATTR_RETURN(vap, va_type, vp->v_type); VATTR_RETURN(vap, va_nlink, file_node->dn_links); VATTR_RETURN(vap, va_uid, file_node->dn_uid); VATTR_RETURN(vap, va_gid, file_node->dn_gid); VATTR_RETURN(vap, va_fsid, (uintptr_t)file_node->dn_dvm); VATTR_RETURN(vap, va_fileid, (uintptr_t)file_node); VATTR_RETURN(vap, va_data_size, file_node->dn_len); /* return an override block size (advisory) */ if (vp->v_type == VBLK) VATTR_RETURN(vap, va_iosize, BLKDEV_IOSIZE); else if (vp->v_type == VCHR) VATTR_RETURN(vap, va_iosize, MAXPHYSIO); else VATTR_RETURN(vap, va_iosize, vp->v_mount->mnt_vfsstat.f_iosize); /* if the time is bogus, set it to the boot time */ if (file_node->dn_ctime.tv_sec == 0) { file_node->dn_ctime.tv_sec = boottime_sec(); file_node->dn_ctime.tv_nsec = 0; } if (file_node->dn_mtime.tv_sec == 0) file_node->dn_mtime = file_node->dn_ctime; if (file_node->dn_atime.tv_sec == 0) file_node->dn_atime = file_node->dn_ctime; VATTR_RETURN(vap, va_change_time, file_node->dn_ctime); VATTR_RETURN(vap, va_modify_time, file_node->dn_mtime); VATTR_RETURN(vap, va_access_time, file_node->dn_atime); VATTR_RETURN(vap, va_gen, 0); VATTR_RETURN(vap, va_flags, 0); VATTR_RETURN(vap, va_filerev, 0); VATTR_RETURN(vap, va_acl, NULL); DEVFS_UNLOCK(); return 0; }
static int vboxvfs_vnode_getattr(struct vnop_getattr_args *args) { vboxvfs_mount_t *pMount; struct vnode_attr *vnode_args; vboxvfs_vnode_t *pVnodeData; struct timespec timespec; SHFLFSOBJINFO Info; mount_t mp; vnode_t vnode; int rc; PDEBUG("Getting vnode attribute..."); AssertReturn(args, EINVAL); vnode = args->a_vp; AssertReturn(vnode, EINVAL); vnode_args = args->a_vap; AssertReturn(vnode_args, EINVAL); mp = vnode_mount(vnode); AssertReturn(mp, EINVAL); pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp); AssertReturn(pMount, EINVAL); pVnodeData = (vboxvfs_vnode_t *)vnode_fsnode(vnode); AssertReturn(pVnodeData, EINVAL); lck_rw_lock_shared(pVnodeData->pLock); rc = vboxvfs_get_info_internal(mp, pVnodeData->pPath, &Info); if (rc == 0) { /* Set timestamps */ RTTimeSpecGetTimespec(&Info.BirthTime, ×pec); VATTR_RETURN(vnode_args, va_create_time, timespec); RTTimeSpecGetTimespec(&Info.AccessTime, ×pec); VATTR_RETURN(vnode_args, va_access_time, timespec); RTTimeSpecGetTimespec(&Info.ModificationTime, ×pec); VATTR_RETURN(vnode_args, va_modify_time, timespec); RTTimeSpecGetTimespec(&Info.ChangeTime, ×pec); VATTR_RETURN(vnode_args, va_change_time, timespec); VATTR_CLEAR_ACTIVE(vnode_args, va_backup_time); /* Set owner info. */ VATTR_RETURN(vnode_args, va_uid, pMount->owner); VATTR_CLEAR_ACTIVE(vnode_args, va_gid); /* Access mode and flags */ VATTR_RETURN(vnode_args, va_mode, vboxvfs_h2g_mode_inernal(Info.Attr.fMode)); VATTR_RETURN(vnode_args, va_flags, Info.Attr.u.Unix.fFlags); /* The current generation number (0 if this information is not available) */ VATTR_RETURN(vnode_args, va_gen, Info.Attr.u.Unix.GenerationId); VATTR_RETURN(vnode_args, va_rdev, 0); VATTR_RETURN(vnode_args, va_nlink, 2); VATTR_RETURN(vnode_args, va_data_size, sizeof(struct dirent)); /* Size of data returned per each readdir() request */ /* Hope, when it overflows nothing catastrophical will heppen! If we will not assign * a uniq va_fileid to each vnode, `ls`, 'find' (and simmilar tools that uses fts_read() calls) will think that * each sub-directory is self-cycled. */ VATTR_RETURN(vnode_args, va_fileid, (pMount->cFileIdCounter++)); /* Not supported */ VATTR_CLEAR_ACTIVE(vnode_args, va_linkid); VATTR_CLEAR_ACTIVE(vnode_args, va_parentid); VATTR_CLEAR_ACTIVE(vnode_args, va_fsid); VATTR_CLEAR_ACTIVE(vnode_args, va_filerev); /* Not present on 10.6 */ //VATTR_CLEAR_ACTIVE(vnode_args, va_addedtime); /* todo: take care about va_encoding (file name encoding) */ VATTR_CLEAR_ACTIVE(vnode_args, va_encoding); /* todo: take care about: va_acl */ VATTR_CLEAR_ACTIVE(vnode_args, va_acl); VATTR_CLEAR_ACTIVE(vnode_args, va_name); VATTR_CLEAR_ACTIVE(vnode_args, va_uuuid); VATTR_CLEAR_ACTIVE(vnode_args, va_guuid); VATTR_CLEAR_ACTIVE(vnode_args, va_total_size); VATTR_CLEAR_ACTIVE(vnode_args, va_total_alloc); VATTR_CLEAR_ACTIVE(vnode_args, va_data_alloc); VATTR_CLEAR_ACTIVE(vnode_args, va_iosize); VATTR_CLEAR_ACTIVE(vnode_args, va_nchildren); VATTR_CLEAR_ACTIVE(vnode_args, va_dirlinkcount); } else { PDEBUG("getattr: unable to get VBoxVFS object info"); } lck_rw_unlock_shared(pVnodeData->pLock); return rc; }
static int vnop_getattr_9p(struct vnop_getattr_args *ap) { struct vnode_attr *vap; struct timespec ts; node_9p *np; enum vtype type; dev_t rdev; int e, dotu; TRACE(); e = 0; np = NTO9P(ap->a_vp); /* exclusive, because we modify np->dir */ nlock_9p(np, NODE_LCK_EXCLUSIVE); if ((e=ngetdir_9p(np))) goto error; dotu = ISSET(np->nmp->flags, F_DOTU); ts.tv_nsec = 0; vap = ap->a_vap; VATTR_RETURN(vap, va_rdev, np->dir.dev); VATTR_RETURN(vap, va_nlink, 1); VATTR_RETURN(vap, va_data_size, np->dir.length); VATTR_RETURN(vap, va_iosize, np->iounit); if (dotu) { VATTR_RETURN(vap, va_uid, np->dir.uidnum); VATTR_RETURN(vap, va_gid, np->dir.gidnum); } else { VATTR_RETURN(vap, va_uid, np->nmp->uid); VATTR_RETURN(vap, va_gid, np->nmp->gid); } VATTR_RETURN(vap, va_mode, np->dir.mode & 0777); VATTR_RETURN(vap, va_flags, 0); ts.tv_sec = np->dir.atime; VATTR_RETURN(vap, va_access_time, ts); ts.tv_sec = np->dir.mtime; VATTR_RETURN(vap, va_modify_time, ts); VATTR_RETURN(vap, va_fileid, QTOI(np->dir.qid)); VATTR_RETURN(vap, va_linkid, QTOI(np->dir.qid)); VATTR_RETURN(vap, va_fsid, vfs_statfs(np->nmp->mp)->f_fsid.val[0]); VATTR_RETURN(vap, va_filerev, np->dir.qid.vers); VATTR_RETURN(vap, va_gen, 0); VATTR_RETURN(vap, va_encoding, 0x7E); /* utf-8 */ dirvtype_9p(&np->dir, dotu, &type, &rdev); VATTR_RETURN(vap, va_type, type); VATTR_RETURN(vap, va_rdev, rdev); /* if (VATTR_IS_ACTIVE(vap, va_name) && !vnode_isvroot(ap->a_vp)) { strlcpy(vap->va_name, dp->name, MAXPATHLEN); VATTR_SET_SUPPORTED(vap, va_name); } */ error: nunlock_9p(np); return e; }
/* copy out attributes from cache entry */ int afs_CopyOutAttrs(struct vcache *avc, struct vattr *attrs) { struct volume *tvp; struct cell *tcell; #if defined(AFS_FBSD_ENV) || defined(AFS_DFBSD_ENV) struct vnode *vp = AFSTOV(avc); #endif int fakedir = 0; AFS_STATCNT(afs_CopyOutAttrs); if (afs_fakestat_enable && avc->mvstat == AFS_MVSTAT_MTPT) fakedir = 1; attrs->va_type = fakedir ? VDIR : vType(avc); #if defined(AFS_SGI_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_DARWIN_ENV) attrs->va_mode = fakedir ? S_IFDIR | 0755 : (mode_t) (avc->f.m.Mode & 0xffff); #else attrs->va_mode = fakedir ? VDIR | 0755 : avc->f.m.Mode; #endif if (avc->f.m.Mode & (VSUID | VSGID)) { /* setuid or setgid, make sure we're allowed to run them from this cell */ tcell = afs_GetCell(avc->f.fid.Cell, 0); if (tcell && (tcell->states & CNoSUID)) attrs->va_mode &= ~(VSUID | VSGID); } #if defined(AFS_DARWIN_ENV) { if (!afs_darwin_realmodes) { /* Mac OS X uses the mode bits to determine whether a file or * directory is accessible, and believes them, even though under * AFS they're almost assuredly wrong, especially if the local uid * does not match the AFS ID. So we set the mode bits * conservatively. */ if (S_ISDIR(attrs->va_mode)) { /* all access bits need to be set for directories, since even * a mode 0 directory can still be used normally. */ attrs->va_mode |= ACCESSPERMS; } else { /* for other files, replicate the user bits to group and other */ mode_t ubits = (attrs->va_mode & S_IRWXU) >> 6; attrs->va_mode |= ubits | (ubits << 3); } } } #endif /* AFS_DARWIN_ENV */ attrs->va_uid = fakedir ? 0 : avc->f.m.Owner; attrs->va_gid = fakedir ? 0 : avc->f.m.Group; /* yeah! */ #if defined(AFS_SUN5_ENV) attrs->va_fsid = avc->v.v_vfsp->vfs_fsid.val[0]; #elif defined(AFS_DARWIN80_ENV) VATTR_RETURN(attrs, va_fsid, vfs_statfs(vnode_mount(AFSTOV(avc)))->f_fsid.val[0]); #elif defined(AFS_DARWIN_ENV) attrs->va_fsid = avc->v->v_mount->mnt_stat.f_fsid.val[0]; #else /* ! AFS_DARWIN_ENV */ attrs->va_fsid = 1; #endif if (avc->mvstat == AFS_MVSTAT_ROOT) { tvp = afs_GetVolume(&avc->f.fid, 0, READ_LOCK); /* The mount point's vnode. */ if (tvp) { attrs->va_nodeid = afs_calc_inum(tvp->mtpoint.Cell, tvp->mtpoint.Fid.Volume, tvp->mtpoint.Fid.Vnode); if (FidCmp(&afs_rootFid, &avc->f.fid) && !attrs->va_nodeid) attrs->va_nodeid = 2; afs_PutVolume(tvp, READ_LOCK); } else attrs->va_nodeid = 2; } else attrs->va_nodeid = afs_calc_inum(avc->f.fid.Cell, avc->f.fid.Fid.Volume, avc->f.fid.Fid.Vnode); attrs->va_nodeid &= 0x7fffffff; /* Saber C hates negative inode #s! */ attrs->va_nlink = fakedir ? 100 : avc->f.m.LinkCount; attrs->va_size = fakedir ? 4096 : avc->f.m.Length; #if defined(AFS_FBSD_ENV) || defined(AFS_DFBSD_ENV) vnode_pager_setsize(vp, (u_long) attrs->va_size); #endif attrs->va_atime.tv_sec = attrs->va_mtime.tv_sec = attrs->va_ctime.tv_sec = fakedir ? 0 : (int)avc->f.m.Date; /* set microseconds to be dataversion # so that we approximate NFS-style * use of mtime as a dataversion #. We take it mod 512K because * microseconds *must* be less than a million, and 512K is the biggest * power of 2 less than such. DataVersions are typically pretty small * anyway, so the difference between 512K and 1000000 shouldn't matter * much, and "&" is a lot faster than "%". */ #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV) /* nfs on these systems puts an 0 in nsec and stores the nfs usec (aka * dataversion) in va_gen */ attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec = attrs->va_ctime.tv_nsec = 0; attrs->va_gen = hgetlo(avc->f.m.DataVersion); #elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_OBSD_ENV) || defined(AFS_NBSD_ENV) attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec = attrs->va_ctime.tv_nsec = (hgetlo(avc->f.m.DataVersion) & 0x7ffff) * 1000; #else attrs->va_atime.tv_usec = attrs->va_mtime.tv_usec = attrs->va_ctime.tv_usec = (hgetlo(avc->f.m.DataVersion) & 0x7ffff); #endif #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) attrs->va_flags = 0; #endif #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) attrs->va_blksize = AFS_BLKSIZE; /* XXX Was 8192 XXX */ #else attrs->va_blocksize = AFS_BLKSIZE; /* XXX Was 8192 XXX */ #endif attrs->va_rdev = 1; #if defined(AFS_HPUX110_ENV) if (afs_globalVFS) attrs->va_fstype = afs_globalVFS->vfs_mtype; #endif /* * Below return 0 (and not 1) blocks if the file is zero length. This conforms * better with the other filesystems that do return 0. */ #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) attrs->va_bytes = (attrs->va_size ? (attrs->va_size + 1023) : 1024); #ifdef va_bytes_rsv attrs->va_bytes_rsv = -1; #endif #elif defined(AFS_HPUX_ENV) attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10) : 0); #elif defined(AFS_SGI_ENV) attrs->va_blocks = BTOBB(attrs->va_size); #elif defined(AFS_SUN5_ENV) attrs->va_nblocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0); #else /* everything else */ attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0); #endif return 0; }
/* For part 1 of zfs_getattr() */ int zfs_getattr_znode_locked(vattr_t *vap, znode_t *zp, cred_t *cr) { zfsvfs_t *zfsvfs = zp->z_zfsvfs; int error; uint64_t times[2]; uint64_t val; VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_MODE(zfsvfs), &val, sizeof (val)) == 0); vap->va_mode = val & MODEMASK; VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_UID(zfsvfs), &val, sizeof (val)) == 0); vap->va_uid = val; VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_GID(zfsvfs), &val, sizeof (val)) == 0); vap->va_gid = val; //vap->va_fsid = zp->z_zfsvfs->z_vfs->vfs_dev; /* On OS X, the root directory id is always 2 */ vap->va_fileid = (zp->z_id == zfsvfs->z_root) ? 2 : zp->z_id; VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_LINKS(zfsvfs), &val, sizeof (val)) == 0); vap->va_nlink = val; VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_SIZE(zfsvfs), &val, sizeof (val)) == 0); vap->va_data_size = val; vap->va_total_size = val; VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zfsvfs), &val, sizeof (val)) == 0); vap->va_rdev = val; VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), &val, sizeof (val)) == 0); vap->va_gen = val; (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(zfsvfs), times, sizeof (times)); ZFS_TIME_DECODE(&vap->va_create_time, times); (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_ATIME(zfsvfs), times, sizeof (times)); ZFS_TIME_DECODE(&vap->va_access_time, times); (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_MTIME(zfsvfs), times, sizeof (times)); ZFS_TIME_DECODE(&vap->va_modify_time, times); (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CTIME(zfsvfs), times, sizeof (times)); ZFS_TIME_DECODE(&vap->va_change_time, times); if (VATTR_IS_ACTIVE(vap, va_backup_time)) { vap->va_backup_time.tv_sec = 0; vap->va_backup_time.tv_nsec = 0; VATTR_SET_SUPPORTED(vap, va_backup_time); } vap->va_flags = zfs_getbsdflags(zp); /* On OS X, the root directory id is always 2 and its parent is 1 */ VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_PARENT(zfsvfs), &val, sizeof (val)) == 0); if (zp->z_id == zfsvfs->z_root) vap->va_parentid = 1; else if (val == zfsvfs->z_root) vap->va_parentid = 2; else vap->va_parentid = val; vap->va_iosize = zp->z_blksz ? zp->z_blksz : zfsvfs->z_max_blksz; VATTR_SET_SUPPORTED(vap, va_iosize); printf("stat blksize set to %d\n", vap->va_iosize); vap->va_supported |= ZFS_SUPPORTED_VATTRS; if (VATTR_IS_ACTIVE(vap, va_nchildren) && vnode_isdir(ZTOV(zp))) VATTR_RETURN(vap, va_nchildren, vap->va_nlink - 2); if (VATTR_IS_ACTIVE(vap, va_acl)) { if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zfsvfs), times, sizeof (times)))) { // if (zp->z_phys->zp_acl.z_acl_count == 0) { vap->va_acl = (kauth_acl_t) KAUTH_FILESEC_NONE; } else { error = zfs_getacl(zp, &vap->va_acl, B_TRUE, cr); if (error) return (error); VATTR_SET_SUPPORTED(vap, va_acl); /* * va_acl implies that va_uuuid and va_guuid are * also supported. */ VATTR_RETURN(vap, va_uuuid, kauth_null_guid); VATTR_RETURN(vap, va_guuid, kauth_null_guid); } } return (0); }
int zfs_getattr_znode_unlocked(struct vnode *vp, vattr_t *vap) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; int error = 0; uint64_t parent; //printf("getattr_osx\n"); ZFS_ENTER(zfsvfs); /* * On Mac OS X we always export the root directory id as 2 */ vap->va_fileid = (zp->z_id == zfsvfs->z_root) ? 2 : zp->z_id; //vap->va_fileid = (zp->z_id == zfsvfs->z_root) ? 2 : zp->z_vid; vap->va_nlink = zp->z_links; vap->va_data_size = zp->z_size; vap->va_total_size = zp->z_size; vap->va_gen = zp->z_gen; /* * For Carbon compatibility,pretend to support this legacy/unused attribute */ if (VATTR_IS_ACTIVE(vap, va_backup_time)) { vap->va_backup_time.tv_sec = 0; vap->va_backup_time.tv_nsec = 0; VATTR_SET_SUPPORTED(vap, va_backup_time); } vap->va_flags = zfs_getbsdflags(zp); /* * On Mac OS X we always export the root directory id as 2 * and its parent as 1 */ error = sa_lookup(zp->z_sa_hdl, SA_ZPL_PARENT(zfsvfs), &parent, sizeof (parent)); if (!error) { if (zp->z_id == zfsvfs->z_root) vap->va_parentid = 1; else if (parent == zfsvfs->z_root) vap->va_parentid = 2; else vap->va_parentid = parent; } vap->va_iosize = zp->z_blksz ? zp->z_blksz : zfsvfs->z_max_blksz; //vap->va_iosize = 512; VATTR_SET_SUPPORTED(vap, va_iosize); /* Don't include '.' and '..' in the number of entries */ if (VATTR_IS_ACTIVE(vap, va_nchildren) && vnode_isdir(vp)) { VATTR_RETURN(vap, va_nchildren, vap->va_nlink - 2); } /* * va_dirlinkcount is the count of directory hard links. When a file * system does not support ATTR_DIR_LINKCOUNT, xnu will default to 1. * Since we claim to support ATTR_DIR_LINKCOUNT both as valid and as * native, we'll just return 1. We set 1 for this value in dirattrpack * as well. If in the future ZFS actually supports directory hard links, * we can return a real value. */ if (VATTR_IS_ACTIVE(vap, va_dirlinkcount) && vnode_isdir(vp)) { VATTR_RETURN(vap, va_dirlinkcount, 1); } if (VATTR_IS_ACTIVE(vap, va_acl)) { //printf("want acl\n"); #if 0 zfs_acl_phys_t acl; if (sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zfsvfs), &acl, sizeof (zfs_acl_phys_t))) { //if (zp->z_acl.z_acl_count == 0) { vap->va_acl = (kauth_acl_t) KAUTH_FILESEC_NONE; } else { if ((error = zfs_getacl(zp, &vap->va_acl, B_TRUE, NULL))) { dprintf("zfs_getacl returned error %d\n", error); error = 0; //ZFS_EXIT(zfsvfs); //return (error); } } #endif //VATTR_SET_SUPPORTED(vap, va_acl); VATTR_RETURN(vap, va_uuuid, kauth_null_guid); VATTR_RETURN(vap, va_guuid, kauth_null_guid); dprintf("Calling getacl\n"); if ((error = zfs_getacl(zp, &vap->va_acl, B_FALSE, NULL))) { dprintf("zfs_getacl returned error %d\n", error); error = 0; } else { VATTR_SET_SUPPORTED(vap, va_acl); /* va_acl implies that va_uuuid and va_guuid are also supported. */ VATTR_RETURN(vap, va_uuuid, kauth_null_guid); VATTR_RETURN(vap, va_guuid, kauth_null_guid); } } if (VATTR_IS_ACTIVE(vap, va_data_alloc) || VATTR_IS_ACTIVE(vap, va_total_alloc)) { uint32_t blksize; u_longlong_t nblks; sa_object_size(zp->z_sa_hdl, &blksize, &nblks); vap->va_data_alloc = (uint64_t)512LL * (uint64_t)nblks; vap->va_total_alloc = vap->va_data_alloc; vap->va_supported |= VNODE_ATTR_va_data_alloc | VNODE_ATTR_va_total_alloc; } if (VATTR_IS_ACTIVE(vap, va_name)) { vap->va_name[0] = 0; if (!vnode_isvroot(vp)) { /* Lets not supply name as zap_cursor can cause panic */ #if 0 if (zap_value_search(zfsvfs->z_os, parent, zp->z_id, ZFS_DIRENT_OBJ(-1ULL), vap->va_name) == 0) VATTR_SET_SUPPORTED(vap, va_name); #endif } else { /* * The vroot objects must return a unique name for Finder to * be able to distringuish between mounts. For this reason * we simply return the fullname, from the statfs mountedfrom */ strlcpy(vap->va_name, vfs_statfs(vnode_mount(vp))->f_mntfromname, MAXPATHLEN); VATTR_SET_SUPPORTED(vap, va_name); } } if (VATTR_IS_ACTIVE(vap, va_filerev)) { VATTR_RETURN(vap, va_filerev, 0); } if (VATTR_IS_ACTIVE(vap, va_linkid)) { VATTR_RETURN(vap, va_linkid, vap->va_fileid); } if (VATTR_IS_ACTIVE(vap, va_fsid)) { VATTR_RETURN(vap, va_fsid, vfs_statfs(zfsvfs->z_vfs)->f_fsid.val[0]); } if (VATTR_IS_ACTIVE(vap, va_type)) { VATTR_RETURN(vap, va_type, vnode_vtype(ZTOV(zp))); } if (VATTR_IS_ACTIVE(vap, va_encoding)) { VATTR_RETURN(vap, va_encoding, kTextEncodingMacUnicode); } #ifdef VNODE_ATTR_va_addedtime if (VATTR_IS_ACTIVE(vap, va_addedtime)) { VATTR_RETURN(vap, va_addedtime, vap->va_ctime); } #endif if (VATTR_IS_ACTIVE(vap, va_uuuid)) { kauth_cred_uid2guid(zp->z_uid, &vap->va_uuuid); } if (VATTR_IS_ACTIVE(vap, va_guuid)) { kauth_cred_uid2guid(zp->z_gid, &vap->va_guuid); } vap->va_supported |= ZFS_SUPPORTED_VATTRS; ZFS_EXIT(zfsvfs); return (error); }
static int nullfs_special_getattr(struct vnop_getattr_args * args) { mount_t mp = vnode_mount(args->a_vp); struct null_mount * null_mp = MOUNTTONULLMOUNT(mp); ino_t ino = NULL_ROOT_INO; struct vnode_attr covered_rootattr; vnode_t checkvp = null_mp->nullm_lowerrootvp; VATTR_INIT(&covered_rootattr); VATTR_WANTED(&covered_rootattr, va_uid); VATTR_WANTED(&covered_rootattr, va_gid); VATTR_WANTED(&covered_rootattr, va_create_time); VATTR_WANTED(&covered_rootattr, va_modify_time); VATTR_WANTED(&covered_rootattr, va_access_time); /* prefer to get this from the lower root vp, but if not (i.e. forced unmount * of lower fs) try the mount point covered vnode */ if (vnode_getwithvid(checkvp, null_mp->nullm_lowerrootvid)) { checkvp = vfs_vnodecovered(mp); if (checkvp == NULL) { return EIO; } } int error = vnode_getattr(checkvp, &covered_rootattr, args->a_context); vnode_put(checkvp); if (error) { /* we should have been able to get attributes fore one of the two choices so * fail if we didn't */ return error; } /* we got the attributes of the vnode we cover so plow ahead */ if (args->a_vp == null_mp->nullm_secondvp) { ino = NULL_SECOND_INO; } VATTR_RETURN(args->a_vap, va_type, vnode_vtype(args->a_vp)); VATTR_RETURN(args->a_vap, va_rdev, 0); VATTR_RETURN(args->a_vap, va_nlink, 3); /* always just ., .., and the child */ VATTR_RETURN(args->a_vap, va_total_size, 0); // hoping this is ok VATTR_RETURN(args->a_vap, va_data_size, 0); // hoping this is ok VATTR_RETURN(args->a_vap, va_data_alloc, 0); VATTR_RETURN(args->a_vap, va_iosize, vfs_statfs(mp)->f_iosize); VATTR_RETURN(args->a_vap, va_fileid, ino); VATTR_RETURN(args->a_vap, va_linkid, ino); VATTR_RETURN(args->a_vap, va_fsid, vfs_statfs(mp)->f_fsid.val[0]); // return the fsid of the mount point VATTR_RETURN(args->a_vap, va_filerev, 0); VATTR_RETURN(args->a_vap, va_gen, 0); VATTR_RETURN(args->a_vap, va_flags, UF_HIDDEN); /* mark our fake directories as hidden. People shouldn't be enocouraged to poke around in them */ if (ino == NULL_SECOND_INO) { VATTR_RETURN(args->a_vap, va_parentid, NULL_ROOT_INO); /* no parent at the root, so the only other vnode that goes through this path is second and its parent is 1.*/ } if (VATTR_IS_ACTIVE(args->a_vap, va_mode)) { /* force dr_xr_xr_x */ VATTR_RETURN(args->a_vap, va_mode, S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); } if (VATTR_IS_ACTIVE(args->a_vap, va_uid)) { VATTR_RETURN(args->a_vap, va_uid, covered_rootattr.va_uid); } if (VATTR_IS_ACTIVE(args->a_vap, va_gid)) { VATTR_RETURN(args->a_vap, va_gid, covered_rootattr.va_gid); } if (VATTR_IS_ACTIVE(args->a_vap, va_create_time)) { VATTR_SET_SUPPORTED(args->a_vap, va_create_time); args->a_vap->va_create_time.tv_sec = covered_rootattr.va_create_time.tv_sec; args->a_vap->va_create_time.tv_nsec = covered_rootattr.va_create_time.tv_nsec; } if (VATTR_IS_ACTIVE(args->a_vap, va_modify_time)) { VATTR_SET_SUPPORTED(args->a_vap, va_modify_time); args->a_vap->va_modify_time.tv_sec = covered_rootattr.va_modify_time.tv_sec; args->a_vap->va_modify_time.tv_nsec = covered_rootattr.va_modify_time.tv_nsec; } if (VATTR_IS_ACTIVE(args->a_vap, va_access_time)) { VATTR_SET_SUPPORTED(args->a_vap, va_access_time); args->a_vap->va_modify_time.tv_sec = covered_rootattr.va_access_time.tv_sec; args->a_vap->va_modify_time.tv_nsec = covered_rootattr.va_access_time.tv_nsec; } return 0; }
/* getattr sidekicks */ __private_extern__ int fuse_internal_loadxtimes(vnode_t vp, struct vnode_attr *out_vap, vfs_context_t context) { struct vnode_attr *in_vap = VTOVA(vp); struct fuse_data *data = fuse_get_mpdata(vnode_mount(vp)); struct fuse_dispatcher fdi; struct fuse_getxtimes_out *fgxo = NULL; int isvroot = vnode_isvroot(vp); struct timespec t = { 0, 0 }; const struct timespec kZeroTime = { 0, 0 }; int err = 0; if (!(data->dataflags & FSESS_XTIMES)) { /* We don't return anything. */ goto out; } if (VTOFUD(vp)->c_flag & C_XTIMES_VALID) { VATTR_RETURN(out_vap, va_backup_time, in_vap->va_backup_time); VATTR_RETURN(out_vap, va_create_time, in_vap->va_create_time); goto out; } if (!fuse_implemented(data, FSESS_NOIMPLBIT(GETXTIMES))) { goto fake; } if (fuse_isdeadfs(vp) && isvroot) { goto fake; } if (!(data->dataflags & FSESS_INITED) && isvroot) { goto fake; } err = fdisp_simple_putget_vp(&fdi, FUSE_GETXTIMES, vp, context); if (err) { /* We don't ever treat this as a hard error. */ err = 0; goto fake; } fgxo = (struct fuse_getxtimes_out *)fdi.answ; t.tv_sec = (time_t)fgxo->bkuptime; /* XXX: truncation */ t.tv_nsec = fgxo->bkuptimensec; VATTR_RETURN(in_vap, va_backup_time, t); VATTR_RETURN(out_vap, va_backup_time, t); t.tv_sec = (time_t)fgxo->crtime; /* XXX: truncation */ t.tv_nsec = fgxo->crtimensec; VATTR_RETURN(in_vap, va_create_time, t); VATTR_RETURN(out_vap, va_create_time, t); fuse_ticket_drop(fdi.tick); VTOFUD(vp)->c_flag |= C_XTIMES_VALID; goto out; fake: VATTR_RETURN(out_vap, va_backup_time, kZeroTime); VATTR_RETURN(out_vap, va_create_time, kZeroTime); out: return err; }