Пример #1
0
static errno_t
fuse_vfsop_setattr(mount_t mp, struct vfs_attr *fsap, vfs_context_t context)
{
    int error = 0;

    fuse_trace_printf_vfsop();

    kauth_cred_t cred = vfs_context_ucred(context);

    if (!fuse_vfs_context_issuser(context) &&
            (kauth_cred_getuid(cred) != vfs_statfs(mp)->f_owner)) {
        return EACCES;
    }

    struct fuse_data *data = fuse_get_mpdata(mp);

    if (VFSATTR_IS_ACTIVE(fsap, f_vol_name)) {

        if (!fuse_implemented(data, FSESS_NOIMPLBIT(SETVOLNAME))) {
            error = ENOTSUP;
            goto out;
        }

        if (fsap->f_vol_name[0] == 0) {
            error = EINVAL;
            goto out;
        }

        size_t namelen = strlen(fsap->f_vol_name);
        if (namelen >= MAXPATHLEN) {
            error = ENAMETOOLONG;
            goto out;
        }

        vnode_t root_vp;

        error = fuse_vfsop_root(mp, &root_vp, context);
        if (error) {
            goto out;
        }

        struct fuse_dispatcher fdi;
        fdisp_init(&fdi, namelen + 1);
        fdisp_make_vp(&fdi, FUSE_SETVOLNAME, root_vp, context);
        memcpy((char *)fdi.indata, fsap->f_vol_name, namelen);
        ((char *)fdi.indata)[namelen] = '\0';

        if (!(error = fdisp_wait_answ(&fdi))) {
            fuse_ticket_drop(fdi.tick);
        }

        (void)vnode_put(root_vp);

        if (error) {
            if (error == ENOSYS) {
                error = ENOTSUP;
                fuse_clear_implemented(data, FSESS_NOIMPLBIT(SETVOLNAME));
            }
            goto out;
        }

        copystr(fsap->f_vol_name, data->volname, MAXPATHLEN - 1, &namelen);
        bzero(data->volname + namelen, MAXPATHLEN - namelen);

        VFSATTR_SET_SUPPORTED(fsap, f_vol_name);
    }

out:
    return error;
}
Пример #2
0
static errno_t
fuse_vfsop_getattr(mount_t mp, struct vfs_attr *attr, vfs_context_t context)
{
    int err     = 0;
    bool deading = false, faking = false;

    struct fuse_dispatcher  fdi;
    struct fuse_statfs_out *fsfo;
    struct fuse_statfs_out  faked;
    struct fuse_data       *data;

    fuse_trace_printf_vfsop();

    data = fuse_get_mpdata(mp);
    if (!data) {
        panic("fuse4x: no private data for mount point?");
    }

    if (!(data->dataflags & FSESS_INITED)) {
        // coreservices process requests ATTR_VOL_CAPABILITIES on the mountpoint right before
        // returning from mount() syscall. We need to fake the output because daemon might
        // not be ready to response yet (and deadlock will happen).
        faking = true;
        goto dostatfs;
    }

    fdisp_init(&fdi, 0);
    fdisp_make(&fdi, FUSE_STATFS, mp, FUSE_ROOT_ID, context);
    if ((err = fdisp_wait_answ(&fdi))) {
        // If we cannot communicate with the daemon (most likely because
        // it's dead), we still want to portray that we are a bonafide
        // file system so that we can be gracefully unmounted.

        if (err == ENOTCONN) {
            deading = faking = true;
            goto dostatfs;
        }

        return err;
    }

dostatfs:
    if (faking) {
        bzero(&faked, sizeof(faked));
        fsfo = &faked;
    } else {
        fsfo = fdi.answ;
    }

    if (fsfo->st.bsize == 0) {
        fsfo->st.bsize = FUSE_DEFAULT_IOSIZE;
    }

    if (fsfo->st.frsize == 0) {
        fsfo->st.frsize = FUSE_DEFAULT_BLOCKSIZE;
    }

    /* optimal transfer block size; will go into f_iosize in the kernel */
    fsfo->st.bsize = fuse_round_size(fsfo->st.bsize,
                                     FUSE_MIN_IOSIZE, FUSE_MAX_IOSIZE);

    /* file system fragment size; will go into f_bsize in the kernel */
    fsfo->st.frsize  = fuse_round_size(fsfo->st.frsize,
                                       FUSE_MIN_BLOCKSIZE, FUSE_MAX_BLOCKSIZE);

    /* We must have: f_iosize >= f_bsize (fsfo->st.bsize >= fsfo->st_frsize) */
    if (fsfo->st.bsize < fsfo->st.frsize) {
        fsfo->st.bsize = fsfo->st.frsize;
    }

    /*
     * TBD: Possibility:
     *
     * For actual I/O to fuse4x's "virtual" storage device, we use
     * data->blocksize and data->iosize. These are really meant to be
     * constant across the lifetime of a single mount. If necessary, we
     * can experiment by updating the mount point's stat with the frsize
     * and bsize values we come across here.
     */

    /*
     * FUSE user daemon will (might) give us this:
     *
     * __u64   blocks;  // total data blocks in the file system
     * __u64   bfree;   // free blocks in the file system
     * __u64   bavail;  // free blocks available to non-superuser
     * __u64   files;   // total file nodes in the file system
     * __u64   ffree;   // free file nodes in the file system
     * __u32   bsize;   // preferred/optimal file system block size
     * __u32   namelen; // maximum length of filenames
     * __u32   frsize;  // fundamental file system block size
     *
     * On Mac OS X, we will map this data to struct vfs_attr as follows:
     *
     *  Mac OS X                     FUSE
     *  --------                     ----
     *  uint64_t f_supported   <-    // handled here
     *  uint64_t f_active      <-    // handled here
     *  uint64_t f_objcount    <-    -
     *  uint64_t f_filecount   <-    files
     *  uint64_t f_dircount    <-    -
     *  uint32_t f_bsize       <-    frsize
     *  size_t   f_iosize      <-    bsize
     *  uint64_t f_blocks      <-    blocks
     *  uint64_t f_bfree       <-    bfree
     *  uint64_t f_bavail      <-    bavail
     *  uint64_t f_bused       <-    blocks - bfree
     *  uint64_t f_files       <-    files
     *  uint64_t f_ffree       <-    ffree
     *  fsid_t   f_fsid        <-    // handled elsewhere
     *  uid_t    f_owner       <-    // handled elsewhere
     *  ... capabilities       <-    // handled here
     *  ... attributes         <-    // handled here
     *  f_create_time          <-    -
     *  f_modify_time          <-    -
     *  f_access_time          <-    -
     *  f_backup_time          <-    -
     *  uint32_t f_fssubtype   <-    // daemon provides
     *  char *f_vol_name       <-    // handled here
     *  uint16_t f_signature   <-    // handled here
     *  uint16_t f_carbon_fsid <-    // handled here
     */

    VFSATTR_RETURN(attr, f_filecount, fsfo->st.files);
    VFSATTR_RETURN(attr, f_bsize, fsfo->st.frsize);
    VFSATTR_RETURN(attr, f_iosize, fsfo->st.bsize);
    VFSATTR_RETURN(attr, f_blocks, fsfo->st.blocks);
    VFSATTR_RETURN(attr, f_bfree, fsfo->st.bfree);
    VFSATTR_RETURN(attr, f_bavail, fsfo->st.bavail);
    VFSATTR_RETURN(attr, f_bused, (fsfo->st.blocks - fsfo->st.bfree));
    VFSATTR_RETURN(attr, f_files, fsfo->st.files);
    VFSATTR_RETURN(attr, f_ffree, fsfo->st.ffree);

    /* f_fsid and f_owner handled elsewhere. */

    /* Handle capabilities and attributes. */
    handle_capabilities_and_attributes(mp, attr);

    VFSATTR_RETURN(attr, f_create_time, kZeroTime);
    VFSATTR_RETURN(attr, f_modify_time, kZeroTime);
    VFSATTR_RETURN(attr, f_access_time, kZeroTime);
    VFSATTR_RETURN(attr, f_backup_time, kZeroTime);

    if (deading) {
        VFSATTR_RETURN(attr, f_fssubtype, (uint32_t)FUSE_FSSUBTYPE_INVALID);
    } else {
        VFSATTR_RETURN(attr, f_fssubtype, data->fssubtype);
    }

    /* Daemon needs to pass this. */
    if (VFSATTR_IS_ACTIVE(attr, f_vol_name)) {
        if (data->volname[0] != 0) {
            strncpy(attr->f_vol_name, data->volname, MAXPATHLEN);
            attr->f_vol_name[MAXPATHLEN - 1] = 0;
            VFSATTR_SET_SUPPORTED(attr, f_vol_name);
        }
    }

    VFSATTR_RETURN(attr, f_signature, OSSwapBigToHostInt16(FUSEFS_SIGNATURE));
    VFSATTR_RETURN(attr, f_carbon_fsid, 0);

    if (!faking)
        fuse_ticket_drop(fdi.tick);

    return 0;
}
Пример #3
0
static int
zfs_vfs_getattr(struct mount *mp, struct vfs_attr *fsap, __unused vfs_context_t context)
{
	zfsvfs_t *zfsvfs = vfs_fsprivate(mp);
	uint64_t refdbytes, availbytes, usedobjs, availobjs;

	ZFS_ENTER(zfsvfs);

	dmu_objset_space(zfsvfs->z_os,
	    &refdbytes, &availbytes, &usedobjs, &availobjs);

	VFSATTR_RETURN(fsap, f_objcount, usedobjs);
	VFSATTR_RETURN(fsap, f_maxobjcount, 0x7fffffffffffffff);
	/*
	 * Carbon depends on f_filecount and f_dircount so
	 * make up some values based on total objects.
	 */
	VFSATTR_RETURN(fsap, f_filecount, usedobjs - (usedobjs / 4));
	VFSATTR_RETURN(fsap, f_dircount, usedobjs / 4);

	/*
	 * The underlying storage pool actually uses multiple block sizes.
	 * We report the fragsize as the smallest block size we support,
	 * and we report our blocksize as the filesystem's maximum blocksize.
	 */
	VFSATTR_RETURN(fsap, f_bsize, 1UL << SPA_MINBLOCKSHIFT);
	VFSATTR_RETURN(fsap, f_iosize, zfsvfs->z_max_blksz);

	/*
	 * The following report "total" blocks of various kinds in the
	 * file system, but reported in terms of f_frsize - the
	 * "fragment" size.
	 */
	VFSATTR_RETURN(fsap, f_blocks,
	               (u_int64_t)((refdbytes + availbytes) >> SPA_MINBLOCKSHIFT));
	VFSATTR_RETURN(fsap, f_bfree, (u_int64_t)(availbytes >> SPA_MINBLOCKSHIFT));
	VFSATTR_RETURN(fsap, f_bavail, fsap->f_bfree);  /* no root reservation */
	VFSATTR_RETURN(fsap, f_bused, fsap->f_blocks - fsap->f_bfree);

	/*
	 * statvfs() should really be called statufs(), because it assumes
	 * static metadata.  ZFS doesn't preallocate files, so the best
	 * we can do is report the max that could possibly fit in f_files,
	 * and that minus the number actually used in f_ffree.
	 * For f_ffree, report the smaller of the number of object available
	 * and the number of blocks (each object will take at least a block).
	 */
	VFSATTR_RETURN(fsap, f_ffree, (u_int64_t)MIN(availobjs, fsap->f_bfree));
	VFSATTR_RETURN(fsap, f_files,  fsap->f_ffree + usedobjs);

#if 0
	statp->f_flag = vf_to_stf(vfsp->vfs_flag);
#endif

	if (VFSATTR_IS_ACTIVE(fsap, f_fsid)) {
		VFSATTR_RETURN(fsap, f_fsid, vfs_statfs(mp)->f_fsid);
	}
	if (VFSATTR_IS_ACTIVE(fsap, f_capabilities)) {
		bcopy(&zfs_capabilities, &fsap->f_capabilities, sizeof (zfs_capabilities));
		VFSATTR_SET_SUPPORTED(fsap, f_capabilities);
	}
	if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) {
		bcopy(&zfs_attributes, &fsap->f_attributes.validattr, sizeof (zfs_attributes));
		bcopy(&zfs_attributes, &fsap->f_attributes.nativeattr, sizeof (zfs_attributes));
		VFSATTR_SET_SUPPORTED(fsap, f_attributes);
	}
	if (VFSATTR_IS_ACTIVE(fsap, f_create_time)) {
		dmu_objset_stats_t dmu_stat;

		dmu_objset_fast_stat(zfsvfs->z_os, &dmu_stat);
		fsap->f_create_time.tv_sec = dmu_stat.dds_creation_time;
		fsap->f_create_time.tv_nsec = 0;
		VFSATTR_SET_SUPPORTED(fsap, f_create_time);
	}
	if (VFSATTR_IS_ACTIVE(fsap, f_modify_time)) {
		if (zfsvfs->z_mtime_vp != NULL) {
			znode_t *mzp;

			mzp = VTOZ(zfsvfs->z_mtime_vp);
			ZFS_TIME_DECODE(&fsap->f_modify_time, mzp->z_phys->zp_mtime);
		} else {
			fsap->f_modify_time.tv_sec = 0;
			fsap->f_modify_time.tv_nsec = 0;
		}
		VFSATTR_SET_SUPPORTED(fsap, f_modify_time);
	}
	/*
	 * For Carbon compatibility, pretend to support this legacy/unused 
	 * attribute
	 */
	if (VFSATTR_IS_ACTIVE(fsap, f_backup_time)) {
		fsap->f_backup_time.tv_sec = 0;
		fsap->f_backup_time.tv_nsec = 0;
		VFSATTR_SET_SUPPORTED(fsap, f_backup_time);
	}
	if (VFSATTR_IS_ACTIVE(fsap, f_vol_name)) {
		spa_t *spa = dmu_objset_spa(zfsvfs->z_os);
		spa_config_enter(spa, RW_READER, FTAG);
		strlcpy(fsap->f_vol_name, spa_name(spa), MAXPATHLEN);
		spa_config_exit(spa, FTAG);
		VFSATTR_SET_SUPPORTED(fsap, f_vol_name);
	}
	VFSATTR_RETURN(fsap, f_fssubtype, 0);
	VFSATTR_RETURN(fsap, f_signature, 0x5a21);  /* 'Z!' */
	VFSATTR_RETURN(fsap, f_carbon_fsid, 0);

	ZFS_EXIT(zfsvfs);
	return (0);
}
Пример #4
0
static int
devfs_vfs_getattr(__unused mount_t mp, struct vfs_attr *fsap, __unused vfs_context_t ctx)
{
	VFSATTR_RETURN(fsap, f_objcount, devfs_stats.nodes);
	VFSATTR_RETURN(fsap, f_maxobjcount, devfs_stats.nodes);
	VFSATTR_RETURN(fsap, f_bsize, 512);
	VFSATTR_RETURN(fsap, f_iosize, 512);
	if (VFSATTR_IS_ACTIVE(fsap, f_blocks) || VFSATTR_IS_ACTIVE(fsap, f_bused)) {
		fsap->f_blocks = (devfs_stats.mounts * sizeof(struct devfsmount)
			 + devfs_stats.nodes * sizeof(devnode_t)
			 + devfs_stats.entries * sizeof(devdirent_t)
			 + devfs_stats.stringspace
			 ) / fsap->f_bsize;
		fsap->f_bused = fsap->f_blocks;
		VFSATTR_SET_SUPPORTED(fsap, f_blocks);
		VFSATTR_SET_SUPPORTED(fsap, f_bused);
	}
	VFSATTR_RETURN(fsap, f_bfree, 0);
	VFSATTR_RETURN(fsap, f_bavail, 0);
	VFSATTR_RETURN(fsap, f_files, devfs_stats.nodes);
	VFSATTR_RETURN(fsap, f_ffree, 0);
	VFSATTR_RETURN(fsap, f_fssubtype, 0);
	
	if (VFSATTR_IS_ACTIVE(fsap, f_capabilities)) {
		fsap->f_capabilities.capabilities[VOL_CAPABILITIES_FORMAT] =
			VOL_CAP_FMT_SYMBOLICLINKS |
			VOL_CAP_FMT_HARDLINKS |
			VOL_CAP_FMT_NO_ROOT_TIMES |
			VOL_CAP_FMT_CASE_SENSITIVE |
			VOL_CAP_FMT_CASE_PRESERVING |
			VOL_CAP_FMT_FAST_STATFS |
			VOL_CAP_FMT_2TB_FILESIZE |
			VOL_CAP_FMT_HIDDEN_FILES;
		fsap->f_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] =
			VOL_CAP_INT_ATTRLIST ;
		fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
		fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED2] = 0;
		
		fsap->f_capabilities.valid[VOL_CAPABILITIES_FORMAT] =
			VOL_CAP_FMT_PERSISTENTOBJECTIDS |
			VOL_CAP_FMT_SYMBOLICLINKS |
			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 |
			VOL_CAP_FMT_OPENDENYMODES |
			VOL_CAP_FMT_HIDDEN_FILES |
			VOL_CAP_FMT_PATH_FROM_ID |
			VOL_CAP_FMT_NO_VOLUME_SIZES;
		fsap->f_capabilities.valid[VOL_CAPABILITIES_INTERFACES] =
			VOL_CAP_INT_SEARCHFS |
			VOL_CAP_INT_ATTRLIST |
			VOL_CAP_INT_NFSEXPORT |
			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 |
			VOL_CAP_INT_EXTENDED_SECURITY |
			VOL_CAP_INT_USERACCESS |
			VOL_CAP_INT_MANLOCK |
			VOL_CAP_INT_EXTENDED_ATTR |
			VOL_CAP_INT_NAMEDSTREAMS;
		fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED1] = 0;
		fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED2] = 0;
		
		VFSATTR_SET_SUPPORTED(fsap, f_capabilities);
	}
	
	if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) {
		fsap->f_attributes.validattr.commonattr =
			ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID |
			ATTR_CMN_OBJTYPE | ATTR_CMN_OBJTAG | ATTR_CMN_OBJID |
			ATTR_CMN_PAROBJID |
			ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | ATTR_CMN_ACCTIME |
			ATTR_CMN_OWNERID | ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK |
			ATTR_CMN_FLAGS | ATTR_CMN_USERACCESS | ATTR_CMN_FILEID;
		fsap->f_attributes.validattr.volattr =
			ATTR_VOL_FSTYPE | ATTR_VOL_SIZE | ATTR_VOL_SPACEFREE |
			ATTR_VOL_SPACEAVAIL | ATTR_VOL_MINALLOCATION |
			ATTR_VOL_OBJCOUNT | ATTR_VOL_MAXOBJCOUNT |
			ATTR_VOL_MOUNTPOINT | ATTR_VOL_MOUNTFLAGS |
			ATTR_VOL_MOUNTEDDEVICE | ATTR_VOL_CAPABILITIES |
			ATTR_VOL_ATTRIBUTES;
		fsap->f_attributes.validattr.dirattr =
			ATTR_DIR_LINKCOUNT | ATTR_DIR_MOUNTSTATUS;
		fsap->f_attributes.validattr.fileattr =
			ATTR_FILE_LINKCOUNT | ATTR_FILE_TOTALSIZE |
			ATTR_FILE_IOBLOCKSIZE | ATTR_FILE_DEVTYPE |
			ATTR_FILE_DATALENGTH;
		fsap->f_attributes.validattr.forkattr = 0;
		
		fsap->f_attributes.nativeattr.commonattr =
			ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID |
			ATTR_CMN_OBJTYPE | ATTR_CMN_OBJTAG | ATTR_CMN_OBJID |
			ATTR_CMN_PAROBJID |
			ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | ATTR_CMN_ACCTIME |
			ATTR_CMN_OWNERID | ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK |
			ATTR_CMN_FLAGS | ATTR_CMN_USERACCESS | ATTR_CMN_FILEID;
		fsap->f_attributes.nativeattr.volattr =
			ATTR_VOL_FSTYPE | ATTR_VOL_SIZE | ATTR_VOL_SPACEFREE |
			ATTR_VOL_SPACEAVAIL | ATTR_VOL_MINALLOCATION |
			ATTR_VOL_OBJCOUNT | ATTR_VOL_MAXOBJCOUNT |
			ATTR_VOL_MOUNTPOINT | ATTR_VOL_MOUNTFLAGS |
			ATTR_VOL_MOUNTEDDEVICE | ATTR_VOL_CAPABILITIES |
			ATTR_VOL_ATTRIBUTES;
		fsap->f_attributes.nativeattr.dirattr =
			ATTR_DIR_MOUNTSTATUS;
		fsap->f_attributes.nativeattr.fileattr =
			ATTR_FILE_LINKCOUNT | ATTR_FILE_TOTALSIZE |
			ATTR_FILE_IOBLOCKSIZE | ATTR_FILE_DEVTYPE |
			ATTR_FILE_DATALENGTH;
		fsap->f_attributes.nativeattr.forkattr = 0;

		VFSATTR_SET_SUPPORTED(fsap, f_attributes);
	}
	
	return 0;
}
Пример #5
0
static int
nullfs_vfs_getattr(struct mount * mp, struct vfs_attr * vfap, vfs_context_t ctx)
{
	struct vnode * coveredvp = NULL;
	struct vfs_attr vfa;
	struct null_mount * null_mp = MOUNTTONULLMOUNT(mp);
	vol_capabilities_attr_t capabilities;
	struct vfsstatfs * sp = vfs_statfs(mp);

	struct timespec tzero = {0, 0};

	NULLFSDEBUG("%s\n", __FUNCTION__);

	/* Set default capabilities in case the lower file system is gone */
	memset(&capabilities, 0, sizeof(capabilities));
	capabilities.capabilities[VOL_CAPABILITIES_FORMAT] = VOL_CAP_FMT_FAST_STATFS | VOL_CAP_FMT_HIDDEN_FILES;
	capabilities.valid[VOL_CAPABILITIES_FORMAT]        = VOL_CAP_FMT_FAST_STATFS | VOL_CAP_FMT_HIDDEN_FILES;

	if (nullfs_vfs_getlowerattr(vnode_mount(null_mp->nullm_lowerrootvp), &vfa, ctx) == 0) {
		if (VFSATTR_IS_SUPPORTED(&vfa, f_capabilities)) {
			memcpy(&capabilities, &vfa.f_capabilities, sizeof(capabilities));
			/* don't support vget */
			capabilities.capabilities[VOL_CAPABILITIES_FORMAT] &= ~(VOL_CAP_FMT_PERSISTENTOBJECTIDS | VOL_CAP_FMT_PATH_FROM_ID);

			capabilities.capabilities[VOL_CAPABILITIES_FORMAT] |= VOL_CAP_FMT_HIDDEN_FILES; /* Always support UF_HIDDEN */

			capabilities.valid[VOL_CAPABILITIES_FORMAT] &= ~(VOL_CAP_FMT_PERSISTENTOBJECTIDS | VOL_CAP_FMT_PATH_FROM_ID);

			capabilities.valid[VOL_CAPABILITIES_FORMAT] |= VOL_CAP_FMT_HIDDEN_FILES; /* Always support UF_HIDDEN */

			/* dont' support interfaces that only make sense on a writable file system
			 * or one with specific vnops implemented */
			capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] = 0;

			capabilities.valid[VOL_CAPABILITIES_INTERFACES] &=
			    ~(VOL_CAP_INT_SEARCHFS | VOL_CAP_INT_ATTRLIST | 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);
		}
	}

	if (VFSATTR_IS_ACTIVE(vfap, f_create_time))
		VFSATTR_RETURN(vfap, f_create_time, tzero);

	if (VFSATTR_IS_ACTIVE(vfap, f_modify_time))
		VFSATTR_RETURN(vfap, f_modify_time, tzero);

	if (VFSATTR_IS_ACTIVE(vfap, f_access_time))
		VFSATTR_RETURN(vfap, f_access_time, tzero);

	if (VFSATTR_IS_ACTIVE(vfap, f_bsize))
		VFSATTR_RETURN(vfap, f_bsize, sp->f_bsize);

	if (VFSATTR_IS_ACTIVE(vfap, f_iosize))
		VFSATTR_RETURN(vfap, f_iosize, sp->f_iosize);

	if (VFSATTR_IS_ACTIVE(vfap, f_owner))
		VFSATTR_RETURN(vfap, f_owner, 0);

	if (VFSATTR_IS_ACTIVE(vfap, f_blocks))
		VFSATTR_RETURN(vfap, f_blocks, sp->f_blocks);

	if (VFSATTR_IS_ACTIVE(vfap, f_bfree))
		VFSATTR_RETURN(vfap, f_bfree, sp->f_bfree);

	if (VFSATTR_IS_ACTIVE(vfap, f_bavail))
		VFSATTR_RETURN(vfap, f_bavail, sp->f_bavail);

	if (VFSATTR_IS_ACTIVE(vfap, f_bused))
		VFSATTR_RETURN(vfap, f_bused, sp->f_bused);

	if (VFSATTR_IS_ACTIVE(vfap, f_files))
		VFSATTR_RETURN(vfap, f_files, sp->f_files);

	if (VFSATTR_IS_ACTIVE(vfap, f_ffree))
		VFSATTR_RETURN(vfap, f_ffree, sp->f_ffree);

	if (VFSATTR_IS_ACTIVE(vfap, f_fssubtype))
		VFSATTR_RETURN(vfap, f_fssubtype, 0);

	if (VFSATTR_IS_ACTIVE(vfap, f_capabilities)) {
		memcpy(&vfap->f_capabilities, &capabilities, sizeof(vol_capabilities_attr_t));

		VFSATTR_SET_SUPPORTED(vfap, f_capabilities);
	}

	if (VFSATTR_IS_ACTIVE(vfap, f_attributes)) {
		vol_attributes_attr_t * volattr = &vfap->f_attributes;

		volattr->validattr.commonattr = 0;
		volattr->validattr.volattr    = ATTR_VOL_NAME | ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES;
		volattr->validattr.dirattr    = 0;
		volattr->validattr.fileattr   = 0;
		volattr->validattr.forkattr   = 0;

		volattr->nativeattr.commonattr = 0;
		volattr->nativeattr.volattr    = ATTR_VOL_NAME | ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES;
		volattr->nativeattr.dirattr    = 0;
		volattr->nativeattr.fileattr   = 0;
		volattr->nativeattr.forkattr   = 0;

		VFSATTR_SET_SUPPORTED(vfap, f_attributes);
	}

	if (VFSATTR_IS_ACTIVE(vfap, f_vol_name)) {
		/* The name of the volume is the same as the directory we mounted on */
		coveredvp = vfs_vnodecovered(mp);
		if (coveredvp) {
			const char * name = vnode_getname_printable(coveredvp);
			strlcpy(vfap->f_vol_name, name, MAXPATHLEN);
			vnode_putname_printable(name);

			VFSATTR_SET_SUPPORTED(vfap, f_vol_name);
			vnode_put(coveredvp);
		}
	}

	return 0;
}
Пример #6
0
static int
vfs_getattr_9p(mount_t mp, struct vfs_attr *ap, vfs_context_t ctx)
{
#pragma unused(ctx)
	struct vfsstatfs *sp;
	mount_9p *nmp;

	TRACE();
	nmp = MTO9P(mp);
	sp = vfs_statfs(mp);
	VFSATTR_RETURN(ap, f_bsize, sp->f_bsize);
	VFSATTR_RETURN(ap, f_iosize, sp->f_iosize);
//	VFSATTR_RETURN(ap, f_blocks, sp->f_blocks);
//	VFSATTR_RETURN(ap, f_bfree, sp->f_bfree);
//	VFSATTR_RETURN(ap, f_bavail, sp->f_bavail);
//	VFSATTR_RETURN(ap, f_bused, sp->f_bused);
	VFSATTR_RETURN(ap, f_files, sp->f_files);
	VFSATTR_RETURN(ap, f_ffree, sp->f_ffree);
	if (VFSATTR_IS_ACTIVE(ap, f_capabilities)) {
		ap->f_capabilities.valid[VOL_CAPABILITIES_FORMAT] = 0
			| VOL_CAP_FMT_PERSISTENTOBJECTIDS
			| VOL_CAP_FMT_SYMBOLICLINKS
			| 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
			| VOL_CAP_FMT_OPENDENYMODES
			| VOL_CAP_FMT_HIDDEN_FILES
			| VOL_CAP_FMT_PATH_FROM_ID
			| VOL_CAP_FMT_NO_VOLUME_SIZES
			| VOL_CAP_FMT_DECMPFS_COMPRESSION
			;
		ap->f_capabilities.capabilities[VOL_CAPABILITIES_FORMAT] = 0
			| VOL_CAP_FMT_NO_ROOT_TIMES
			| VOL_CAP_FMT_CASE_SENSITIVE
			| VOL_CAP_FMT_CASE_PRESERVING
			| VOL_CAP_FMT_FAST_STATFS
			| VOL_CAP_FMT_2TB_FILESIZE
			| VOL_CAP_FMT_NO_VOLUME_SIZES
			;

		ap->f_capabilities.valid[VOL_CAPABILITIES_INTERFACES] = 0
			| VOL_CAP_INT_SEARCHFS
			| VOL_CAP_INT_ATTRLIST
			| VOL_CAP_INT_NFSEXPORT
			| 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
			| VOL_CAP_INT_EXTENDED_SECURITY
			| VOL_CAP_INT_USERACCESS
			| VOL_CAP_INT_MANLOCK
			| VOL_CAP_INT_NAMEDSTREAMS
			| VOL_CAP_INT_EXTENDED_ATTR
			;
		ap->f_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] = 0
			| VOL_CAP_INT_ADVLOCK
			| VOL_CAP_INT_FLOCK
			;

		ap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED1] = 0;
		ap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED2] = 0;
		ap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
		ap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED2] = 0;

		VFSATTR_SET_SUPPORTED(ap, f_capabilities);

	}

	if (VFSATTR_IS_ACTIVE(ap, f_attributes)) {
		ap->f_attributes.nativeattr.commonattr = ap->f_attributes.validattr.commonattr = 0;
		ap->f_attributes.nativeattr.volattr = ap->f_attributes.validattr.volattr = 0
			| ATTR_VOL_IOBLOCKSIZE
			| ATTR_VOL_MOUNTFLAGS
			| ATTR_VOL_NAME
			| ATTR_VOL_MOUNTFLAGS
			| ATTR_VOL_MOUNTEDDEVICE
			| ATTR_VOL_CAPABILITIES
			| ATTR_VOL_ATTRIBUTES
			;
		ap->f_attributes.nativeattr.dirattr = ap->f_attributes.validattr.dirattr = 0;
		ap->f_attributes.nativeattr.fileattr = ap->f_attributes.validattr.fileattr = 0;
		ap->f_attributes.nativeattr.forkattr = ap->f_attributes.validattr.forkattr = 0;

		VFSATTR_SET_SUPPORTED(ap, f_attributes);
	}	

	if (VFSATTR_IS_ACTIVE(ap, f_vol_name)) {
		strlcpy(ap->f_vol_name, nmp->volume, MAXPATHLEN);
		VFSATTR_SET_SUPPORTED(ap, f_vol_name);
	}

	return 0;
}
Пример #7
0
/**
 * VBoxVFS get VFS layer object attribute callback.
 *
 * @param mp        Mount data provided by VFS layer.
 * @param pAttr     Output buffer to return attributes.
 * @param pContext  kAuth context needed in order to authentificate mount operation.
 *
 * @returns     0 for success, else an error code.
 */
static int
vboxvfs_getattr(struct mount *mp, struct vfs_attr *pAttr, vfs_context_t pContext)
{
    NOREF(pContext);

    vboxvfs_mount_t     *pMount;
    SHFLVOLINFO          SHFLVolumeInfo;

    int      rc;
    uint32_t cbBuffer = sizeof(SHFLVolumeInfo);

    uint32_t u32bsize;
    uint64_t u64blocks;
    uint64_t u64bfree;

    PDEBUG("Getting attribute...\n");

    AssertReturn(mp, EINVAL);

    pMount = (vboxvfs_mount_t *)vfs_fsprivate(mp);
    AssertReturn(pMount, EINVAL);
    AssertReturn(pMount->pShareName, EINVAL);

    rc = VbglR0SfFsInfo(&g_vboxSFClient, &pMount->pMap, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME,
                        &cbBuffer, (PSHFLDIRINFO)&SHFLVolumeInfo);
    AssertReturn(rc == 0, EPROTO);

    u32bsize  = (uint32_t)SHFLVolumeInfo.ulBytesPerAllocationUnit;
    AssertReturn(u32bsize > 0, ENOTSUP);

    u64blocks = (uint64_t)SHFLVolumeInfo.ullTotalAllocationBytes / (uint64_t)u32bsize;
    u64bfree  = (uint64_t)SHFLVolumeInfo.ullAvailableAllocationBytes / (uint64_t)u32bsize;

    VFSATTR_RETURN(pAttr, f_bsize,  u32bsize);
    VFSATTR_RETURN(pAttr, f_blocks, u64blocks);
    VFSATTR_RETURN(pAttr, f_bfree,  u64bfree);
    VFSATTR_RETURN(pAttr, f_bavail, u64bfree);
    VFSATTR_RETURN(pAttr, f_bused,  u64blocks - u64bfree);

    VFSATTR_RETURN(pAttr, f_owner,  pMount->owner);

    VFSATTR_CLEAR_ACTIVE(pAttr, f_iosize);
    VFSATTR_CLEAR_ACTIVE(pAttr, f_files);
    VFSATTR_CLEAR_ACTIVE(pAttr, f_ffree);
    VFSATTR_CLEAR_ACTIVE(pAttr, f_fssubtype);

    /* todo: take care about f_capabilities and f_attributes, f_fsid */
    VFSATTR_CLEAR_ACTIVE(pAttr, f_capabilities);
    VFSATTR_CLEAR_ACTIVE(pAttr, f_attributes);
    VFSATTR_CLEAR_ACTIVE(pAttr, f_fsid);

    /* todo: take care about f_create_time, f_modify_time, f_access_time, f_backup_time */
    VFSATTR_CLEAR_ACTIVE(pAttr, f_create_time);
    VFSATTR_CLEAR_ACTIVE(pAttr, f_modify_time);
    VFSATTR_CLEAR_ACTIVE(pAttr, f_access_time);
    VFSATTR_CLEAR_ACTIVE(pAttr, f_backup_time);

    VFSATTR_CLEAR_ACTIVE(pAttr, f_signature);
    VFSATTR_CLEAR_ACTIVE(pAttr, f_carbon_fsid);
    VFSATTR_CLEAR_ACTIVE(pAttr, f_uuid);

    if (VFSATTR_IS_ACTIVE(pAttr, f_vol_name))
    {
        strlcpy(pAttr->f_vol_name, (char*)pMount->pShareName->String.utf8, MAXPATHLEN);
        VFSATTR_SET_SUPPORTED(pAttr, f_vol_name);
    }

    VFSATTR_ALL_SUPPORTED(pAttr);

    return 0;
}