コード例 #1
0
/**
 * @brief Return true if create verifier matches
 *
 * This function returns true if the create verifier matches
 *
 * @param[in] entry   Entry to be managed.
 * @param[in] req_ctx Request context(user creds, client address etc)
 * @param[in] verf_hi High long of verifier
 * @param[in] verf_lo Low long of verifier
 *
 * @return Errors from cache_inode_lock_trust_attributes.
 *
 */
bool
cache_inode_create_verify(cache_entry_t *entry,
                          const struct req_op_context *req_ctx,
                          uint32_t verf_hi,
                          uint32_t verf_lo)
{
        /* True if the verifier matches */
        bool verified = false;

        /* Lock (and refresh if necessary) the attributes, copy them
           out, and unlock. */

        if (cache_inode_lock_trust_attrs(entry, req_ctx, false)
                == CACHE_INODE_SUCCESS) {
                if (FSAL_TEST_MASK(entry->obj_handle->attributes.mask,
                                   ATTR_ATIME) &&
                    FSAL_TEST_MASK(entry->obj_handle->attributes.mask,
                                   ATTR_MTIME) &&
                    entry->obj_handle->attributes.atime.tv_sec == verf_hi &&
                    entry->obj_handle->attributes.mtime.tv_sec == verf_lo) {
                        verified = true;
                }
                PTHREAD_RWLOCK_unlock(&entry->attr_lock);
        }

        return verified;
}
コード例 #2
0
void fsal_interval_proxy_fsalattr2bitmap4(fsal_attrib_list_t * pfsalattr,
                                          bitmap4 * pbitmap)
{
  uint32_t tmpattrlist[100];
  uint32_t attrlen = 0;

  if(FSAL_TEST_MASK(pfsalattr->asked_attributes, FSAL_ATTR_SIZE))
    tmpattrlist[attrlen++] = FATTR4_SIZE;
  if(FSAL_TEST_MASK(pfsalattr->asked_attributes, FSAL_ATTR_MODE))
    tmpattrlist[attrlen++] = FATTR4_MODE;
  if(FSAL_TEST_MASK(pfsalattr->asked_attributes, FSAL_ATTR_OWNER))
    tmpattrlist[attrlen++] = FATTR4_OWNER;
  if(FSAL_TEST_MASK(pfsalattr->asked_attributes, FSAL_ATTR_GROUP))
    tmpattrlist[attrlen++] = FATTR4_OWNER_GROUP;
  if(FSAL_TEST_MASK(pfsalattr->asked_attributes, FSAL_ATTR_ATIME))
    tmpattrlist[attrlen++] = FATTR4_TIME_ACCESS_SET;
  if(FSAL_TEST_MASK(pfsalattr->asked_attributes, FSAL_ATTR_ATIME_SERVER))
    tmpattrlist[attrlen++] = FATTR4_TIME_ACCESS_SET;
  if(FSAL_TEST_MASK(pfsalattr->asked_attributes, FSAL_ATTR_MTIME))
    tmpattrlist[attrlen++] = FATTR4_TIME_MODIFY_SET;
  if(FSAL_TEST_MASK(pfsalattr->asked_attributes, FSAL_ATTR_MTIME_SERVER))
    tmpattrlist[attrlen++] = FATTR4_TIME_MODIFY_SET;
  if(FSAL_TEST_MASK(pfsalattr->asked_attributes, FSAL_ATTR_CTIME))
    tmpattrlist[attrlen++] = FATTR4_TIME_METADATA;
 
  nfs4_list_to_bitmap4(pbitmap, attrlen, tmpattrlist);
}                               /* fsal_interval_proxy_fsalattr2bitmap4 */
コード例 #3
0
ファイル: fsal_convert.c プロジェクト: MeghanaM/nfs-ganesha
/**
 * hpssHandle2fsalAttributes:
 * Fills an FSAL attributes structure with the info
 * provided (only) by the hpss handle of an object.
 *
 * \param p_hpsshandle_in (input):
 *        Pointer to the HPSS NS object handle.
 * \param p_fsalattr_out (input/output):
 *        Pointer to the FSAL attributes.
 *        As input, it defines the attributes that the caller
 *        wants to retrieve (by positioning flags into this structure)
 *        and the output is built considering this input
 *        (it fills the structure according to the flags it contains).
 *
 * \return Major error codes:
 *      - ERR_FSAL_NO_ERROR: no error.
 *      - ERR_FSAL_FAULT: NULL pointer passed as input parameter.
 *      - ERR_FSAL_ATTRNOTSUPP: One of the asked attributes is not supported.
 *      - ERR_FSAL_SERVERFAULT: Unexpected error.
 */
fsal_status_t hpssHandle2fsalAttributes(ns_ObjHandle_t * p_hpsshandle_in,
                                        fsal_attrib_list_t * p_fsalattr_out)
{

  fsal_attrib_mask_t avail_attr, unavail_attr;

  /* sanity check */
  if(!p_hpsshandle_in || !p_fsalattr_out)
    ReturnCode(ERR_FSAL_FAULT, 0);

  /* check that asked attributes are available */
  avail_attr = (FSAL_ATTR_SUPPATTR | FSAL_ATTR_TYPE | FSAL_ATTR_FILEID);

  unavail_attr = (p_fsalattr_out->asked_attributes) & (~avail_attr);
  if(unavail_attr)
    {
      LogFullDebug(COMPONENT_FSAL,
                        "Attributes not available: %#llX", unavail_attr);
      ReturnCode(ERR_FSAL_ATTRNOTSUPP, 0);
    }

  /* Fills the output struct */
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_SUPPATTR))
    {
      p_fsalattr_out->supported_attributes = global_fs_info.supported_attrs;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_TYPE))
    {
      p_fsalattr_out->type = hpss2fsal_type(p_hpsshandle_in->Type);
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_FILEID))
    {
      p_fsalattr_out->fileid = (fsal_u64_t) hpss_GetObjId(p_hpsshandle_in);
    }

  /* everything has been copied ! */

  ReturnCode(ERR_FSAL_NO_ERROR, 0);

}
コード例 #4
0
ファイル: fsal_local_op.c プロジェクト: alangenfeld/cloud-nfs
fsal_status_t XFSFSAL_merge_attrs(fsal_attrib_list_t * pinit_attr,
                                  fsal_attrib_list_t * pnew_attr,
                                  fsal_attrib_list_t * presult_attr)
{
  if(pinit_attr == NULL || pnew_attr == NULL || presult_attr == NULL)
    Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_merge_attrs);

  /* The basis for the result attr is the fist argument */
  *presult_attr = *pinit_attr;

  /* Now deal with the attributes to be merged in this set of attributes */
  if(FSAL_TEST_MASK(pnew_attr->asked_attributes, FSAL_ATTR_MODE))
    presult_attr->mode = pnew_attr->mode;

  if(FSAL_TEST_MASK(pnew_attr->asked_attributes, FSAL_ATTR_OWNER))
    presult_attr->owner = pnew_attr->owner;

  if(FSAL_TEST_MASK(pnew_attr->asked_attributes, FSAL_ATTR_GROUP))
    presult_attr->group = pnew_attr->group;

  if(FSAL_TEST_MASK(pnew_attr->asked_attributes, FSAL_ATTR_SIZE))
    presult_attr->filesize = pnew_attr->filesize;

  if(FSAL_TEST_MASK(pnew_attr->asked_attributes, FSAL_ATTR_SPACEUSED))
    presult_attr->spaceused = pnew_attr->spaceused;

  if(FSAL_TEST_MASK(pnew_attr->asked_attributes, FSAL_ATTR_ATIME))
    {
      presult_attr->atime.seconds = pnew_attr->atime.seconds;
      presult_attr->atime.nseconds = pnew_attr->atime.nseconds;
    }

  if(FSAL_TEST_MASK(pnew_attr->asked_attributes, FSAL_ATTR_MTIME))
    {
      presult_attr->mtime.seconds = pnew_attr->mtime.seconds;
      presult_attr->mtime.nseconds = pnew_attr->mtime.nseconds;
    }

  /* Do not forget the ctime */
  FSAL_SET_MASK(presult_attr->asked_attributes, FSAL_ATTR_CTIME);
  presult_attr->ctime.seconds = pnew_attr->ctime.seconds;
  presult_attr->ctime.nseconds = pnew_attr->ctime.nseconds;

  /* Regular exit */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_merge_attrs);
}                               /* FSAL_merge_attrs */
コード例 #5
0
ファイル: fsal_convert.c プロジェクト: fmarsch/nfs-ganesha-1
/* Same function as posixstat64_2_fsal_attributes. When NFS4 ACL support
 * is enabled, this will replace posixstat64_2_fsal_attributes. */
fsal_status_t
ptfsal_xstat_2_fsal_attributes(ptfsal_xstat_t     * p_buffxstat,
				 fsal_attrib_list_t * p_fsalattr_out)
{

    fsal_attrib_mask_t supp_attr, unsupp_attr;
    struct stat64 *p_buffstat;

    /* sanity checks */
    if(!p_buffxstat || !p_fsalattr_out)
        ReturnCode(ERR_FSAL_FAULT, 0);

    /* check that asked attributes are supported */
    supp_attr = global_fs_info.supported_attrs;

    unsupp_attr = (p_fsalattr_out->asked_attributes) & (~supp_attr);
    if(unsupp_attr)
        {
            LogFullDebug(COMPONENT_FSAL, "Unsupported attributes: %#llX",
                         unsupp_attr);
            ReturnCode(ERR_FSAL_ATTRNOTSUPP, 0);
        }

    p_buffstat = &p_buffxstat->buffstat;

    /* Initialize ACL regardless of whether ACL was asked or not.
     * This is needed to make sure ACL attribute is initialized. */
    p_fsalattr_out->acl = NULL;

    /* Fills the output struct */
    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_SUPPATTR))
        {
            p_fsalattr_out->supported_attributes = supp_attr;
            LogFullDebug(COMPONENT_FSAL, "supported_attributes = %llu", 
                         p_fsalattr_out->supported_attributes);
        }
    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_TYPE))
        {
            p_fsalattr_out->type = posix2fsal_type(p_buffstat->st_mode);
            LogFullDebug(COMPONENT_FSAL, "type = 0x%x", p_fsalattr_out->type);
        }
    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_SIZE))
        {
            p_fsalattr_out->filesize = p_buffstat->st_size;
            LogFullDebug(COMPONENT_FSAL, "filesize = %lu", 
                         p_fsalattr_out->filesize);
        }
    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_FSID))
        {
            p_fsalattr_out->fsid = posix2fsal_fsid(p_buffstat->st_dev);
            LogFullDebug(COMPONENT_FSAL, "fsid major = %llu, minor = %llu", 
                         p_fsalattr_out->fsid.major, 
                         p_fsalattr_out->fsid.minor);
        }
    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_ACL))
        {
#ifndef _USE_NFS4_ACL
            p_fsalattr_out->acl = NULL;
#else
            if((p_buffxstat->attr_valid & XATTR_ACL) == 0)
              {
                /* ACL is invalid. */
                p_fsalattr_out->acl = NULL;
              }
            else
              {
                /* ACL is valid, so try to convert fsal acl. */
                if(ptfs_acl_2_fsal_acl(p_fsalattr_out,
                   (gpfs_acl_t *)p_buffxstat->buffacl) != ERR_FSAL_NO_ERROR)
                  p_fsalattr_out->acl = NULL;
              }
#endif                          /* _USE_NFS4_ACL */
            LogFullDebug(COMPONENT_FSAL, "acl = %p", p_fsalattr_out->acl);
        }
    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_FILEID))
        {
            p_fsalattr_out->fileid = (fsal_u64_t) (p_buffstat->st_ino);
            LogFullDebug(COMPONENT_FSAL, "fileid = %llu", 
                         p_fsalattr_out->fileid);
        }

    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_MODE))
        {
            p_fsalattr_out->mode = unix2fsal_mode(p_buffstat->st_mode);
            LogFullDebug(COMPONENT_FSAL, "mode = %llu", 
                         (long long unsigned int) p_fsalattr_out->mode);
        }
    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_NUMLINKS))
        {
            p_fsalattr_out->numlinks = p_buffstat->st_nlink;
            LogFullDebug(COMPONENT_FSAL, "numlinks = %lu", 
                         p_fsalattr_out->numlinks);
        }
    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_OWNER))
        {
            p_fsalattr_out->owner = p_buffstat->st_uid;
            LogFullDebug(COMPONENT_FSAL, "owner = %u", p_fsalattr_out->owner);
        }
    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_GROUP))
        {
            p_fsalattr_out->group = p_buffstat->st_gid;
            LogFullDebug(COMPONENT_FSAL, "group = %u", p_fsalattr_out->group);
        }
    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_ATIME))
        {
          p_fsalattr_out->atime = posix2fsal_time(p_buffstat->st_atime, 
                                                  p_buffstat->st_atim.tv_nsec);
            LogFullDebug(COMPONENT_FSAL, "atime = %u", 
                         p_fsalattr_out->atime.seconds);
        }

    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_CTIME))
        {
          p_fsalattr_out->ctime = posix2fsal_time(p_buffstat->st_ctime, 
                                                  p_buffstat->st_ctim.tv_nsec);
            LogFullDebug(COMPONENT_FSAL, "ctime = %u", 
                         p_fsalattr_out->ctime.seconds);
        }
    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_MTIME))
        {
          p_fsalattr_out->mtime = posix2fsal_time(p_buffstat->st_mtime, 
                                                  p_buffstat->st_mtim.tv_nsec);
            LogFullDebug(COMPONENT_FSAL, "mtime = %u", 
                         p_fsalattr_out->mtime.seconds);
        }

    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_CHGTIME))
        {
            p_fsalattr_out->chgtime
              = posix2fsal_time(MAX_2(p_buffstat->st_mtime, 
                                      p_buffstat->st_ctime), 0);
            p_fsalattr_out->change = 
              (uint64_t) p_fsalattr_out->chgtime.seconds ;
            LogFullDebug(COMPONENT_FSAL, "chgtime = %u", 
                         p_fsalattr_out->chgtime.seconds);
        }

    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_SPACEUSED))
        {
            p_fsalattr_out->spaceused = p_buffstat->st_blocks * S_BLKSIZE;
            LogFullDebug(COMPONENT_FSAL, "spaceused = %lu", 
                         p_fsalattr_out->spaceused);
        }

    if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_RAWDEV))
        {
            p_fsalattr_out->rawdev = posix2fsal_devt(p_buffstat->st_rdev);   
            LogFullDebug(COMPONENT_FSAL,
                         "rawdev major = %u, minor = %u",
                         (unsigned int) p_fsalattr_out->rawdev.major,
                         (unsigned int) p_fsalattr_out->rawdev.minor);
        }

    /* everything has been copied ! */

    ReturnCode(ERR_FSAL_NO_ERROR, 0);
}
コード例 #6
0
ファイル: fsal_convert.c プロジェクト: srimalik/nfs-ganesha
/**
 *  @brief convert GPFS xstat to FSAl attributes
 *
 *  @param gpfs_buf Reference to GPFS stat buffer
 *  @param fsal_attr Reference to attribute list
 *  @param use_acl Bool whether ACL are used
 *  @return FSAL status
 *
 *  Same function as posixstat64_2_fsal_attributes. When NFS4 ACL support
 *  is enabled, this will replace posixstat64_2_fsal_attributes.
 */
fsal_status_t
gpfsfsal_xstat_2_fsal_attributes(gpfsfsal_xstat_t *gpfs_buf,
				 struct attrlist *fsal_attr, bool use_acl)
{
	struct stat *p_buffstat;

	/* sanity checks */
	if (!gpfs_buf || !fsal_attr)
		return fsalstat(ERR_FSAL_FAULT, 0);

	p_buffstat = &gpfs_buf->buffstat;

	LogDebug(COMPONENT_FSAL, "inode %ld", p_buffstat->st_ino);

	/* Fills the output struct */
	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_TYPE)) {
		fsal_attr->type = posix2fsal_type(p_buffstat->st_mode);
		LogFullDebug(COMPONENT_FSAL, "type = 0x%x",
			     fsal_attr->type);
	}
	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_SIZE)) {
		fsal_attr->filesize = p_buffstat->st_size;
		LogFullDebug(COMPONENT_FSAL, "filesize = %llu",
			     (unsigned long long)fsal_attr->filesize);
	}
	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_FSID)) {
		fsal_attr->fsid = gpfs_buf->fsal_fsid;
		LogFullDebug(COMPONENT_FSAL,
			     "fsid=0x%016"PRIx64".0x%016"PRIx64,
			     fsal_attr->fsid.major,
			     fsal_attr->fsid.minor);
	}
	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_ACL)) {
		if (fsal_attr->acl != NULL) {
			/* We should never be passed attributes that have an
			 * ACL attached, but just in case some future code
			 * path changes that assumption, let's not release the
			 * old ACL properly.
			 */
			int acl_status;

			acl_status = nfs4_acl_release_entry(fsal_attr->acl);

			if (acl_status != NFS_V4_ACL_SUCCESS)
				LogCrit(COMPONENT_FSAL,
					"Failed to release old acl, status=%d",
					acl_status);

			fsal_attr->acl = NULL;
		}

		if (use_acl && gpfs_buf->attr_valid & XATTR_ACL) {
			/* ACL is valid, so try to convert fsal acl. */
			gpfs_acl_2_fsal_acl(fsal_attr,
					    (gpfs_acl_t *) gpfs_buf->buffacl);
		}
		LogFullDebug(COMPONENT_FSAL, "acl = %p", fsal_attr->acl);
	}
	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_FILEID)) {
		fsal_attr->fileid = (uint64_t) (p_buffstat->st_ino);
		LogFullDebug(COMPONENT_FSAL, "fileid = %" PRIu64,
			     fsal_attr->fileid);
	}

	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_MODE)) {
		fsal_attr->mode = unix2fsal_mode(p_buffstat->st_mode);
		LogFullDebug(COMPONENT_FSAL, "mode = %"PRIu32,
			     fsal_attr->mode);
	}
	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_NUMLINKS)) {
		fsal_attr->numlinks = p_buffstat->st_nlink;
		LogFullDebug(COMPONENT_FSAL, "numlinks = %u",
			     fsal_attr->numlinks);
	}
	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_OWNER)) {
		fsal_attr->owner = p_buffstat->st_uid;
		LogFullDebug(COMPONENT_FSAL, "owner = %" PRIu64,
			     fsal_attr->owner);
	}
	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_GROUP)) {
		fsal_attr->group = p_buffstat->st_gid;
		LogFullDebug(COMPONENT_FSAL, "group = %" PRIu64,
			     fsal_attr->group);
	}
	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_ATIME)) {
		fsal_attr->atime =
		    posix2fsal_time(p_buffstat->st_atime,
				    p_buffstat->st_atim.tv_nsec);
		LogFullDebug(COMPONENT_FSAL, "atime = %lu",
			     fsal_attr->atime.tv_sec);
	}

	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_CTIME)) {
		fsal_attr->ctime =
		    posix2fsal_time(p_buffstat->st_ctime,
				    p_buffstat->st_ctim.tv_nsec);
		LogFullDebug(COMPONENT_FSAL, "ctime = %lu",
			     fsal_attr->ctime.tv_sec);
	}
	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_MTIME)) {
		fsal_attr->mtime =
		    posix2fsal_time(p_buffstat->st_mtime,
				    p_buffstat->st_mtim.tv_nsec);
		LogFullDebug(COMPONENT_FSAL, "mtime = %lu",
			     fsal_attr->mtime.tv_sec);
	}

	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_CHGTIME)) {
		if (p_buffstat->st_mtime == p_buffstat->st_ctime) {
			if (p_buffstat->st_mtim.tv_nsec >
			    p_buffstat->st_ctim.tv_nsec)
				fsal_attr->chgtime =
				    posix2fsal_time(p_buffstat->st_mtime,
						    p_buffstat->st_mtim.
						    tv_nsec);
			else
				fsal_attr->chgtime =
				    posix2fsal_time(p_buffstat->st_ctime,
						    p_buffstat->st_ctim.
						    tv_nsec);
		} else if (p_buffstat->st_mtime > p_buffstat->st_ctime) {
			fsal_attr->chgtime =
			    posix2fsal_time(p_buffstat->st_mtime,
					    p_buffstat->st_mtim.tv_nsec);
		} else {
			fsal_attr->chgtime =
			    posix2fsal_time(p_buffstat->st_ctime,
					    p_buffstat->st_ctim.tv_nsec);
		}
		fsal_attr->change =
		    (uint64_t) fsal_attr->chgtime.tv_sec +
		    (uint64_t) fsal_attr->chgtime.tv_nsec;
		LogFullDebug(COMPONENT_FSAL, "chgtime = %lu",
			     fsal_attr->chgtime.tv_sec);

	}

	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_SPACEUSED)) {
		fsal_attr->spaceused = p_buffstat->st_blocks * S_BLKSIZE;
		LogFullDebug(COMPONENT_FSAL, "spaceused = %llu",
			     (unsigned long long)fsal_attr->spaceused);
	}

	if (FSAL_TEST_MASK(fsal_attr->mask, ATTR_RAWDEV)) {
		fsal_attr->rawdev = posix2fsal_devt(p_buffstat->st_rdev);
		LogFullDebug(COMPONENT_FSAL, "rawdev major = %u, minor = %u",
			     (unsigned int)fsal_attr->rawdev.major,
			     (unsigned int)fsal_attr->rawdev.minor);
	}

	/* everything has been copied ! */

	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
コード例 #7
0
/**
 * @brief Set the attributes for a file.
 *
 * This function sets the attributes of a file, both in the cache and
 * in the underlying filesystem.
 *
 * @param[in]     entry   Entry whose attributes are to be set
 * @param[in,out] attr    Attributes to set/result of set
 *
 * @retval CACHE_INODE_SUCCESS if operation is a success
 */
cache_inode_status_t
cache_inode_setattr(cache_entry_t *entry,
		    struct attrlist *attr,
		    bool is_open_write)
{
	struct fsal_obj_handle *obj_handle = entry->obj_handle;
	fsal_status_t fsal_status = { 0, 0 };
	fsal_acl_t *saved_acl = NULL;
	fsal_acl_status_t acl_status = 0;
	cache_inode_status_t status = CACHE_INODE_SUCCESS;
	uint64_t before;

	/* True if we have taken the content lock on 'entry' */
	bool content_locked = false;

	if ((attr->mask & (ATTR_SIZE | ATTR4_SPACE_RESERVED))
	     && (entry->type != REGULAR_FILE)) {
		LogWarn(COMPONENT_CACHE_INODE,
			"Attempt to truncate non-regular file: type=%d",
			entry->type);
		status = CACHE_INODE_BAD_TYPE;
	}

	/* Is it allowed to change times ? */
	if (!op_ctx->fsal_export->ops->fs_supports(op_ctx->fsal_export,
						    fso_cansettime)
	    &&
	    (FSAL_TEST_MASK
	     (attr->mask,
	      (ATTR_ATIME | ATTR_CREATION | ATTR_CTIME | ATTR_MTIME)))) {
		status = CACHE_INODE_INVALID_ARGUMENT;
		goto out;
	}

	/* Get wrlock on attr_lock and verify attrs */
	status = cache_inode_lock_trust_attrs(entry, true);
	if (status != CACHE_INODE_SUCCESS)
		return status;

	/* Do permission checks */
	status = cache_inode_check_setattr_perms(entry, attr, is_open_write);
	if (status != CACHE_INODE_SUCCESS)
		goto unlock;

	if (attr->mask & (ATTR_SIZE | ATTR4_SPACE_RESERVED)) {
		PTHREAD_RWLOCK_wrlock(&entry->content_lock);
		content_locked = true;
	}

	saved_acl = obj_handle->attributes.acl;
	before = obj_handle->attributes.change;
	fsal_status = obj_handle->ops->setattrs(obj_handle, attr);
	if (FSAL_IS_ERROR(fsal_status)) {
		status = cache_inode_error_convert(fsal_status);
		if (fsal_status.major == ERR_FSAL_STALE) {
			LogEvent(COMPONENT_CACHE_INODE,
				 "FSAL returned STALE from truncate");
			cache_inode_kill_entry(entry);
		}
		goto unlock;
	}
	fsal_status = obj_handle->ops->getattrs(obj_handle);
	*attr = obj_handle->attributes;
	if (FSAL_IS_ERROR(fsal_status)) {
		status = cache_inode_error_convert(fsal_status);
		if (fsal_status.major == ERR_FSAL_STALE) {
			LogEvent(COMPONENT_CACHE_INODE,
				 "FSAL returned STALE from setattrs");
			cache_inode_kill_entry(entry);
		}
		goto unlock;
	}
	if (before == obj_handle->attributes.change)
		obj_handle->attributes.change++;
	/* Decrement refcount on saved ACL */
	nfs4_acl_release_entry(saved_acl, &acl_status);
	if (acl_status != NFS_V4_ACL_SUCCESS)
		LogCrit(COMPONENT_CACHE_INODE,
			"Failed to release old acl, status=%d", acl_status);

	cache_inode_fixup_md(entry);

	/* Copy the complete set of new attributes out. */

	*attr = entry->obj_handle->attributes;

	status = CACHE_INODE_SUCCESS;

unlock:
	if (content_locked)
		PTHREAD_RWLOCK_unlock(&entry->content_lock);
	PTHREAD_RWLOCK_unlock(&entry->attr_lock);

out:
	return status;
}
コード例 #8
0
ファイル: fsal_convert.c プロジェクト: sbu-fsl/tc-server
/* Same function as posixstat64_2_fsal_attributes. When NFS4 ACL support
 * is enabled, this will replace posixstat64_2_fsal_attributes. */
fsal_status_t gpfsfsal_xstat_2_fsal_attributes(gpfsfsal_xstat_t *p_buffxstat,
					       struct attrlist *p_fsalattr_out,
					       bool use_acl)
{
	struct stat *p_buffstat;

	/* sanity checks */
	if (!p_buffxstat || !p_fsalattr_out)
		return fsalstat(ERR_FSAL_FAULT, 0);

	p_buffstat = &p_buffxstat->buffstat;

	LogDebug(COMPONENT_FSAL, "inode %ld", p_buffstat->st_ino);

	/* Fills the output struct */
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_TYPE)) {
		p_fsalattr_out->type = posix2fsal_type(p_buffstat->st_mode);
		LogFullDebug(COMPONENT_FSAL, "type = 0x%x",
			     p_fsalattr_out->type);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_SIZE)) {
		p_fsalattr_out->filesize = p_buffstat->st_size;
		LogFullDebug(COMPONENT_FSAL, "filesize = %llu",
			     (unsigned long long)p_fsalattr_out->filesize);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_FSID)) {
		p_fsalattr_out->fsid = p_buffxstat->fsal_fsid;
		LogFullDebug(COMPONENT_FSAL,
			     "fsid=0x%016"PRIx64".0x%016"PRIx64,
			     p_fsalattr_out->fsid.major,
			     p_fsalattr_out->fsid.minor);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_ACL)) {
		p_fsalattr_out->acl = NULL;
		if (use_acl && p_buffxstat->attr_valid & XATTR_ACL) {
			/* ACL is valid, so try to convert fsal acl. */
			gpfs_acl_2_fsal_acl(p_fsalattr_out,
					    (gpfs_acl_t *) p_buffxstat->
					    buffacl);
		}
		LogFullDebug(COMPONENT_FSAL, "acl = %p", p_fsalattr_out->acl);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_FILEID)) {
		p_fsalattr_out->fileid = (uint64_t) (p_buffstat->st_ino);
		LogFullDebug(COMPONENT_FSAL, "fileid = %lu",
			     p_fsalattr_out->fileid);
	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_MODE)) {
		p_fsalattr_out->mode = unix2fsal_mode(p_buffstat->st_mode);
		LogFullDebug(COMPONENT_FSAL, "mode = %"PRIu32,
			     p_fsalattr_out->mode);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_NUMLINKS)) {
		p_fsalattr_out->numlinks = p_buffstat->st_nlink;
		LogFullDebug(COMPONENT_FSAL, "numlinks = %u",
			     p_fsalattr_out->numlinks);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_OWNER)) {
		p_fsalattr_out->owner = p_buffstat->st_uid;
		LogFullDebug(COMPONENT_FSAL, "owner = %lu",
			     p_fsalattr_out->owner);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_GROUP)) {
		p_fsalattr_out->group = p_buffstat->st_gid;
		LogFullDebug(COMPONENT_FSAL, "group = %lu",
			     p_fsalattr_out->group);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_ATIME)) {
		p_fsalattr_out->atime =
		    posix2fsal_time(p_buffstat->st_atime,
				    p_buffstat->st_atim.tv_nsec);
		LogFullDebug(COMPONENT_FSAL, "atime = %lu",
			     p_fsalattr_out->atime.tv_sec);
	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_CTIME)) {
		p_fsalattr_out->ctime =
		    posix2fsal_time(p_buffstat->st_ctime,
				    p_buffstat->st_ctim.tv_nsec);
		LogFullDebug(COMPONENT_FSAL, "ctime = %lu",
			     p_fsalattr_out->ctime.tv_sec);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_MTIME)) {
		p_fsalattr_out->mtime =
		    posix2fsal_time(p_buffstat->st_mtime,
				    p_buffstat->st_mtim.tv_nsec);
		LogFullDebug(COMPONENT_FSAL, "mtime = %lu",
			     p_fsalattr_out->mtime.tv_sec);
	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_CHGTIME)) {
		if (p_buffstat->st_mtime == p_buffstat->st_ctime) {
			if (p_buffstat->st_mtim.tv_nsec >
			    p_buffstat->st_ctim.tv_nsec)
				p_fsalattr_out->chgtime =
				    posix2fsal_time(p_buffstat->st_mtime,
						    p_buffstat->st_mtim.
						    tv_nsec);
			else
				p_fsalattr_out->chgtime =
				    posix2fsal_time(p_buffstat->st_ctime,
						    p_buffstat->st_ctim.
						    tv_nsec);
		} else if (p_buffstat->st_mtime > p_buffstat->st_ctime) {
			p_fsalattr_out->chgtime =
			    posix2fsal_time(p_buffstat->st_mtime,
					    p_buffstat->st_mtim.tv_nsec);
		} else {
			p_fsalattr_out->chgtime =
			    posix2fsal_time(p_buffstat->st_ctime,
					    p_buffstat->st_ctim.tv_nsec);
		}
		p_fsalattr_out->change =
		    (uint64_t) p_fsalattr_out->chgtime.tv_sec +
		    (uint64_t) p_fsalattr_out->chgtime.tv_nsec;
		LogFullDebug(COMPONENT_FSAL, "chgtime = %lu",
			     p_fsalattr_out->chgtime.tv_sec);

	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_SPACEUSED)) {
		p_fsalattr_out->spaceused = p_buffstat->st_blocks * S_BLKSIZE;
		LogFullDebug(COMPONENT_FSAL, "spaceused = %llu",
			     (unsigned long long)p_fsalattr_out->spaceused);
	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_RAWDEV)) {
		p_fsalattr_out->rawdev = posix2fsal_devt(p_buffstat->st_rdev);
		LogFullDebug(COMPONENT_FSAL, "rawdev major = %u, minor = %u",
			     (unsigned int)p_fsalattr_out->rawdev.major,
			     (unsigned int)p_fsalattr_out->rawdev.minor);
	}

	/* everything has been copied ! */

	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
コード例 #9
0
ファイル: fsal_convert.c プロジェクト: MeghanaM/nfs-ganesha
fsal_status_t posix2fsal_attributes(struct stat * p_buffstat,
                                    fsal_attrib_list_t * p_fsalattr_out)
{

  fsal_attrib_mask_t supp_attr, unsupp_attr;

  /* sanity checks */
  if(!p_buffstat || !p_fsalattr_out)
    ReturnCode(ERR_FSAL_FAULT, 0);

  /* check that asked attributes are supported */
  supp_attr = global_fs_info.supported_attrs;

  unsupp_attr = (p_fsalattr_out->asked_attributes) & (~supp_attr);
  if(unsupp_attr)
    {
      LogFullDebug(COMPONENT_FSAL, "Unsupported attributes: %#llX",
                        unsupp_attr);
      ReturnCode(ERR_FSAL_ATTRNOTSUPP, 0);
    }

  /* Initialize ACL regardless of whether ACL was asked or not.
   * This is needed to make sure ACL attribute is initialized. */
  p_fsalattr_out->acl = NULL;

  /* Fills the output struct */
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_SUPPATTR))
    {
      p_fsalattr_out->supported_attributes = supp_attr;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_TYPE))
    {
      p_fsalattr_out->type = posix2fsal_type(p_buffstat->st_mode);
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_SIZE))
    {
      p_fsalattr_out->filesize = p_buffstat->st_size;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_FSID))
    {
      p_fsalattr_out->fsid = posix2fsal_fsid(p_buffstat->st_dev);
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_ACL))
    {
      p_fsalattr_out->acl = NULL;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_FILEID))
    {
      p_fsalattr_out->fileid = (fsal_u64_t) (p_buffstat->st_ino);
    }

  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_MODE))
    {
      p_fsalattr_out->mode = unix2fsal_mode(p_buffstat->st_mode);
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_NUMLINKS))
    {
      p_fsalattr_out->numlinks = p_buffstat->st_nlink;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_OWNER))
    {
      p_fsalattr_out->owner = p_buffstat->st_uid;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_GROUP))
    {
      p_fsalattr_out->group = p_buffstat->st_gid;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_ATIME))
    {
      p_fsalattr_out->atime = posix2fsal_time(p_buffstat->st_atime);

    }

  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_CTIME))
    {
      p_fsalattr_out->ctime = posix2fsal_time(p_buffstat->st_ctime);
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_MTIME))
    {
      p_fsalattr_out->mtime = posix2fsal_time(p_buffstat->st_mtime);
    }

  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_CHGTIME))
    {
      p_fsalattr_out->chgtime
          = posix2fsal_time(MAX_2(p_buffstat->st_mtime, p_buffstat->st_ctime));
      p_fsalattr_out->change = (uint64_t) p_fsalattr_out->chgtime.seconds ;
    }

  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_SPACEUSED))
    {
      p_fsalattr_out->spaceused = p_buffstat->st_blocks * S_BLKSIZE;
    }

  if(FSAL_TEST_MASK(p_fsalattr_out->asked_attributes, FSAL_ATTR_RAWDEV))
    {
      p_fsalattr_out->rawdev = posix2fsal_devt(p_buffstat->st_rdev);    /* XXX: convert ? */
    }
  /* mounted_on_fileid :
     if ( FSAL_TEST_MASK(p_fsalattr_out->asked_attributes,
     FSAL_ATTR_MOUNTFILEID )){
     p_fsalattr_out->mounted_on_fileid = 
     hpss2fsal_64( p_hpss_attr_in->FilesetRootId );
     }
   */

  /* everything has been copied ! */

  ReturnCode(ERR_FSAL_NO_ERROR, 0);
}
コード例 #10
0
ファイル: fsal_convertions.c プロジェクト: eitanb/nfs-ganesha
/* convert ghostfs attributes to FSAL attributes */
int ghost2fsal_attrs(fsal_attrib_list_t * p_fsal_attrs, GHOSTFS_Attrs_t * p_ghost_attrs)
{
  /* Fills the output struct */
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_SUPPATTR))
    {
      p_fsal_attrs->supported_attributes = GHOSTFS_SUPPORTED_ATTRIBUTES;
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_TYPE))
    {
      p_fsal_attrs->type = ghost2fsal_type(p_ghost_attrs->type);
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_SIZE))
    {
      p_fsal_attrs->filesize = p_ghost_attrs->size;
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_FSID))
    {
      /* constant FSID for ghostFS */
      p_fsal_attrs->fsid.major = 1;
      p_fsal_attrs->fsid.minor = 1;
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_FILEID))
    {
      p_fsal_attrs->fileid = (unsigned int)p_ghost_attrs->inode;
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_MODE))
    {
      p_fsal_attrs->mode = ghost2fsal_mode(p_ghost_attrs->mode);
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_NUMLINKS))
    {
      p_fsal_attrs->numlinks = p_ghost_attrs->linkcount;
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_OWNER))
    {
      p_fsal_attrs->owner = (fsal_uid_t) p_ghost_attrs->uid;
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_GROUP))
    {
      p_fsal_attrs->group = (fsal_gid_t) p_ghost_attrs->gid;
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_ATIME))
    {
      p_fsal_attrs->atime.seconds = p_ghost_attrs->atime;
      p_fsal_attrs->atime.nseconds = 0;
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_CTIME))
    {
      p_fsal_attrs->ctime.seconds = p_ghost_attrs->ctime;
      p_fsal_attrs->ctime.nseconds = 0;
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_MTIME))
    {
      p_fsal_attrs->mtime.seconds = p_ghost_attrs->mtime;
      p_fsal_attrs->mtime.nseconds = 0;
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_CREATION))
    {
      p_fsal_attrs->creation.seconds = p_ghost_attrs->creationTime;
      p_fsal_attrs->creation.nseconds = 0;
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_SPACEUSED))
    {
      p_fsal_attrs->spaceused = p_ghost_attrs->size;
    }
  if(FSAL_TEST_MASK(p_fsal_attrs->asked_attributes, FSAL_ATTR_CHGTIME))
    {
      p_fsal_attrs->chgtime.seconds = p_ghost_attrs->ctime;
      p_fsal_attrs->chgtime.nseconds = 0;
      p_fsal_attrs->change = (uint64_t) p_fsal_attrs->chgtime.seconds;
    }

  return 0;

}
コード例 #11
0
ファイル: fsal_attrs.c プロジェクト: chandra2/nfs-ganesha
/**
 * GPFSFSAL_setattrs:
 * Set attributes for the object specified by its filehandle.
 *
 * \param filehandle (input):
 *        The handle of the object to get parameters.
 * \param cred (input):
 *        Authentication context for the operation (user,...).
 * \param attrib_set (mandatory input):
 *        The attributes to be set for the object.
 *        It defines the attributes that the caller
 *        wants to set and their values.
 * \param object_attributes (optionnal input/output):
 *        The post operation attributes for the object.
 *        As input, it defines the attributes that the caller
 *        wants to retrieve (by positioning flags into this structure)
 *        and the output is built considering this input
 *        (it fills the structure according to the flags it contains).
 *        May be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - Another error code if an error occured.
 */
fsal_status_t GPFSFSAL_setattrs(fsal_handle_t * p_filehandle,       /* IN */
                            fsal_op_context_t * p_context,      /* IN */
                            fsal_attrib_list_t * p_attrib_set,  /* IN */
                            fsal_attrib_list_t * p_object_attributes    /* [ IN/OUT ] */
    )
{
  unsigned int i;
  fsal_status_t status;

  /* Buffer that will be passed to gpfs_ganesha API. */
  gpfsfsal_xstat_t buffxstat;

  /* Indicate if stat or acl or both should be changed. */
  int attr_valid = 0;

  /* Indiate which attribute in stat should be changed. */
  int attr_changed = 0;

  fsal_accessflags_t access_mask = 0;
  fsal_attrib_list_t wanted_attrs, current_attrs;

  /* sanity checks.
   * note : object_attributes is optional.
   */
  if(!p_filehandle || !p_context || !p_attrib_set)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs);

  /* local copy of attributes */
  wanted_attrs = *p_attrib_set;

  /* It does not make sense to setattr on a symlink */
  /* if(p_filehandle->type == DT_LNK)
     return fsal_internal_setattrs_symlink(p_filehandle, p_context, p_attrib_set,
     p_object_attributes);
   */
  /* First, check that FSAL attributes changes are allowed. */

  /* Is it allowed to change times ? */

  if(!global_fs_info.cansettime)
    {

      if(wanted_attrs.asked_attributes
         & (FSAL_ATTR_ATIME | FSAL_ATTR_CREATION | FSAL_ATTR_CTIME | FSAL_ATTR_MTIME))
        {
          /* handled as an unsettable attribute. */
          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_setattrs);
        }
    }

  /* apply umask, if mode attribute is to be changed */
  if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_MODE))
    {
      wanted_attrs.mode &= (~global_fs_info.umask);
    }

  /* get current attributes */
  current_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES;
  status = GPFSFSAL_getattrs(p_filehandle, p_context, &current_attrs);
  if(FSAL_IS_ERROR(status))
    {
      FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
      FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
      ReturnStatus(status, INDEX_FSAL_setattrs);
    }

  /***********
   *  CHMOD  *
   ***********/
  if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_MODE))
    {

      /* The POSIX chmod call don't affect the symlink object, but
       * the entry it points to. So we must ignore it.
       */
      if(current_attrs.type != FSAL_TYPE_LNK)
        {

#ifdef _USE_NFS4_ACL
          if(current_attrs.acl)
            {
              /* Check permission using ACL. */
              access_mask = FSAL_MODE_MASK_SET(0) |  /* Dummy. */
                            FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_ATTR);

              status = fsal_internal_testAccess(p_context, access_mask, NULL, &current_attrs);
              if(FSAL_IS_ERROR(status))
                ReturnStatus(status, INDEX_FSAL_setattrs);
            }
          else
            {
#endif
              /* For modifying mode, user must be root or the owner */
              if((p_context->credential.user != 0)
                 && (p_context->credential.user != current_attrs.owner))
                {
                  LogFullDebug(COMPONENT_FSAL,
                               "Permission denied for CHMOD opeartion: current owner=%d, credential=%d",
                               current_attrs.owner, p_context->credential.user);
                  Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
                }
#ifdef _USE_NFS4_ACL
             }
#endif
    
            attr_valid |= XATTR_STAT;
            attr_changed |= XATTR_MODE;
    
            /* Fill wanted mode. */
            buffxstat.buffstat.st_mode = fsal2unix_mode(wanted_attrs.mode);
            LogDebug(COMPONENT_FSAL,
                     "current mode = %o, new mode = %o",
                     fsal2unix_mode(current_attrs.mode), buffxstat.buffstat.st_mode);

        }

    }

  /***********
   *  CHOWN  *
   ***********/
  /* Only root can change uid and A normal user must be in the group he wants to set */
  if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_OWNER))
    {

#ifdef _USE_NFS4_ACL
      if(current_attrs.acl)
        {
          /* Check permission using ACL. */
          access_mask = FSAL_MODE_MASK_SET(0) |  /* Dummy. */
                        FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_OWNER);

          status = fsal_internal_testAccess(p_context, access_mask, NULL, &current_attrs);
          if(FSAL_IS_ERROR(status))
            ReturnStatus(status, INDEX_FSAL_setattrs);
        }
      else
        {
#endif
          /* For modifying owner, user must be root or current owner==wanted==client */
          if((p_context->credential.user != 0) &&
             ((p_context->credential.user != current_attrs.owner) ||
              (p_context->credential.user != wanted_attrs.owner)))
            {
              LogFullDebug(COMPONENT_FSAL,
                           "Permission denied for CHOWN opeartion: current owner=%d, credential=%d, new owner=%d",
                           current_attrs.owner, p_context->credential.user, wanted_attrs.owner);
              Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
            }
#ifdef _USE_NFS4_ACL
        }
#endif

    }

  if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_GROUP))
    {

#ifdef _USE_NFS4_ACL
      if(current_attrs.acl)
        {
          /* Check permission using ACL. */
          access_mask = FSAL_MODE_MASK_SET(0) |  /* Dummy. */
                        FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_OWNER);

          status = fsal_internal_testAccess(p_context, access_mask, NULL, &current_attrs);
          if(FSAL_IS_ERROR(status))
            ReturnStatus(status, INDEX_FSAL_setattrs);
        }
      else
        {
#endif
          /* For modifying group, user must be root or current owner */
          if((p_context->credential.user != 0)
             && (p_context->credential.user != current_attrs.owner))
            {
              Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
            }
    
          int in_grp = 0;
          /* set in_grp */
          if(p_context->credential.group == wanted_attrs.group)
            in_grp = 1;
          else
            for(i = 0; i < p_context->credential.nbgroups; i++)
              {
                if((in_grp = (wanted_attrs.group == p_context->credential.alt_groups[i])))
                  break;
              }
    
          /* it must also be in target group */
          if(p_context->credential.user != 0 && !in_grp)
            {
              LogFullDebug(COMPONENT_FSAL,
                           "Permission denied for CHOWN operation: current group=%d, credential=%d, new group=%d",
                           current_attrs.group, p_context->credential.group, wanted_attrs.group);
              Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
            }
#ifdef _USE_NFS4_ACL
        }
#endif
    }

  if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_OWNER | FSAL_ATTR_GROUP))
    {
      /*      LogFullDebug(COMPONENT_FSAL, "Performing chown(%s, %d,%d)",
                        fsalpath.path, FSAL_TEST_MASK(wanted_attrs.asked_attributes,
                                                      FSAL_ATTR_OWNER) ? (int)wanted_attrs.owner
                        : -1, FSAL_TEST_MASK(wanted_attrs.asked_attributes,
			FSAL_ATTR_GROUP) ? (int)wanted_attrs.group : -1);*/

      attr_valid |= XATTR_STAT;
      attr_changed |= FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_OWNER) ?
                      XATTR_UID : XATTR_GID;

      /* Fill wanted owner. */
      if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_OWNER))
        {
          buffxstat.buffstat.st_uid = (int)wanted_attrs.owner;
          LogDebug(COMPONENT_FSAL,
                   "current uid = %d, new uid = %d",
                   current_attrs.owner, buffxstat.buffstat.st_uid);
        }

      /* Fill wanted group. */
      if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_GROUP))
        {
          buffxstat.buffstat.st_gid = (int)wanted_attrs.group;
          LogDebug(COMPONENT_FSAL,
                   "current gid = %d, new gid = %d",
                   current_attrs.group, buffxstat.buffstat.st_gid);
        }

    }

  /***********
   *  UTIME  *
   ***********/

  /* user must be the owner or have read access to modify 'atime' */
  access_mask = FSAL_MODE_MASK_SET(FSAL_R_OK) |
                FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_ATTR);
  if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_ATIME)
     && (p_context->credential.user != 0)
     && (p_context->credential.user != current_attrs.owner)
     && ((status = fsal_internal_testAccess(p_context, access_mask, NULL, &current_attrs)).major
         != ERR_FSAL_NO_ERROR))
    {
      ReturnStatus(status, INDEX_FSAL_setattrs);
    }
  /* user must be the owner or have write access to modify 'mtime' */
  access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK) |
                FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_ATTR);
  if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_MTIME)
     && (p_context->credential.user != 0)
     && (p_context->credential.user != current_attrs.owner)
     && ((status = fsal_internal_testAccess(p_context, access_mask, NULL, &current_attrs)).major
         != ERR_FSAL_NO_ERROR))
    {
      ReturnStatus(status, INDEX_FSAL_setattrs);
    }

  if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_ATIME | FSAL_ATTR_MTIME))
    {
      attr_valid |= XATTR_STAT;

      /* Fill wanted atime. */
      if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_ATIME))
        {
          attr_changed |= XATTR_ATIME;
          buffxstat.buffstat.st_atime = (time_t) wanted_attrs.atime.seconds;
          LogDebug(COMPONENT_FSAL,
                   "current atime = %lu, new atime = %lu",
                   (unsigned long)current_attrs.atime.seconds, (unsigned long)buffxstat.buffstat.st_atime);
        }

      /* Fill wanted mtime. */
      if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_MTIME))
        {
          attr_changed |= XATTR_CTIME;
          buffxstat.buffstat.st_mtime = (time_t) wanted_attrs.mtime.seconds;
          LogDebug(COMPONENT_FSAL,
                   "current mtime = %lu, new mtime = %lu",
                   (unsigned long)current_attrs.mtime.seconds, (unsigned long)buffxstat.buffstat.st_mtime);
        }
    }

#ifdef _USE_NFS4_ACL
   /***********
   *  ACL  *
   ***********/

  if(FSAL_TEST_MASK(wanted_attrs.asked_attributes, FSAL_ATTR_ACL))
    {
      /* Check permission to set ACL. */
      access_mask = FSAL_MODE_MASK_SET(0) |  /* Dummy */
                    FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_ACL);

      status = fsal_internal_testAccess(p_context, access_mask, NULL, &current_attrs);
      if(FSAL_IS_ERROR(status))
        ReturnStatus(status, INDEX_FSAL_setattrs);

      if(wanted_attrs.acl)
        {
          attr_valid |= XATTR_ACL;
          LogDebug(COMPONENT_FSAL, "setattr acl = %p", wanted_attrs.acl);

          /* Convert FSAL ACL to GPFS NFS4 ACL and fill the buffer. */
          status = fsal_acl_2_gpfs_acl(wanted_attrs.acl, &buffxstat);

          if(FSAL_IS_ERROR(status))
            ReturnStatus(status, INDEX_FSAL_setattrs);
        }
      else
        {
          LogCrit(COMPONENT_FSAL, "setattr acl is NULL");
          Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs);
        }
    }
#endif                          /* _USE_NFS4_ACL */

  /* If there is any change in stat or acl or both, send it down to file system. */
  if((attr_valid == XATTR_STAT && attr_changed !=0) || attr_valid == XATTR_ACL)
    {
      status = fsal_set_xstat_by_handle(p_context,
                                        p_filehandle,
                                        attr_valid,
                                        attr_changed,
                                        &buffxstat);

      if(FSAL_IS_ERROR(status))
        ReturnStatus(status, INDEX_FSAL_setattrs);
    }

  /* Optionaly fills output attributes. */

  if(p_object_attributes)
    {
      status = GPFSFSAL_getattrs(p_filehandle, p_context, p_object_attributes);

      /* on error, we set a special bit in the mask. */
      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
          FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
        }

    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs);

}
コード例 #12
0
ファイル: fsal_convert.c プロジェクト: JasonZen/nfs-ganesha
fsal_status_t posixstat64_2_fsal_attributes(struct stat *p_buffstat,
					    struct attrlist *p_fsalattr_out)
{

	/* sanity checks */
	if (!p_buffstat || !p_fsalattr_out)
		return fsalstat(ERR_FSAL_FAULT, 0);

	/* Initialize ACL regardless of whether ACL was asked or not.
	 * This is needed to make sure ACL attribute is initialized. */
	p_fsalattr_out->acl = NULL;

	/* Fills the output struct */
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_TYPE))
		p_fsalattr_out->type = posix2fsal_type(p_buffstat->st_mode);
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_SIZE))
		p_fsalattr_out->filesize = p_buffstat->st_size;
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_FSID))
		p_fsalattr_out->fsid = posix2fsal_fsid(p_buffstat->st_dev);
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_ACL))
		p_fsalattr_out->acl = NULL;
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_FILEID))
		p_fsalattr_out->fileid = (uint64_t) (p_buffstat->st_ino);

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_MODE))
		p_fsalattr_out->mode = unix2fsal_mode(p_buffstat->st_mode);
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_NUMLINKS))
		p_fsalattr_out->numlinks = p_buffstat->st_nlink;
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_OWNER))
		p_fsalattr_out->owner = p_buffstat->st_uid;
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_GROUP))
		p_fsalattr_out->group = p_buffstat->st_gid;
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_ATIME)) {
		p_fsalattr_out->atime =
		    posix2fsal_time(p_buffstat->st_atime,
				    p_buffstat->st_atim.tv_nsec);

	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_CTIME)) {
		p_fsalattr_out->ctime =
		    posix2fsal_time(p_buffstat->st_ctime,
				    p_buffstat->st_ctim.tv_nsec);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_MTIME)) {
		p_fsalattr_out->mtime =
		    posix2fsal_time(p_buffstat->st_mtime,
				    p_buffstat->st_mtim.tv_nsec);
	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_CHGTIME)) {
		p_fsalattr_out->chgtime =
		    posix2fsal_time(MAX
				    (p_buffstat->st_mtime,
				     p_buffstat->st_ctime), 0);
		p_fsalattr_out->change =
		    (uint64_t) p_fsalattr_out->chgtime.tv_sec;
	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_SPACEUSED))
		p_fsalattr_out->spaceused = p_buffstat->st_blocks * S_BLKSIZE;

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_RAWDEV))
		p_fsalattr_out->rawdev = posix2fsal_devt(p_buffstat->st_rdev);

	/* everything has been copied ! */

	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
コード例 #13
0
/**
 *
 * @brief Checks permissions on an entry for setattrs
 *
 * This function acquires the attribute lock on the supplied cache
 * entry then checks if the supplied credentials are sufficient to
 * perform the required setattrs.
 *
 * @param[in] entry   The object to be checked
 * @param[in] attr    Attributes to set/result of set
 *
 * @return CACHE_INODE_SUCCESS if operation is a success
 */
cache_inode_status_t
cache_inode_check_setattr_perms(cache_entry_t *entry,
				struct attrlist *attr,
				bool is_open_write)
{
	cache_inode_status_t status = CACHE_INODE_SUCCESS;
	fsal_accessflags_t access_check = 0;
	bool not_owner;
	char *note = "";
	const struct user_cred *creds = op_ctx->creds;

	if (isDebug(COMPONENT_CACHE_INODE) || isDebug(COMPONENT_NFS_V4_ACL)) {
		char *setattr_size = "";
		char *setattr_owner = "";
		char *setattr_owner_group = "";
		char *setattr_mode = "";
		char *setattr_acl = "";
		char *setattr_mtime = "";
		char *setattr_atime = "";

		if (FSAL_TEST_MASK(attr->mask, ATTR_SIZE))
			setattr_size = " SIZE";

		if (FSAL_TEST_MASK(attr->mask, ATTR_OWNER))
			setattr_owner = " OWNER";

		if (FSAL_TEST_MASK(attr->mask, ATTR_GROUP))
			setattr_owner_group = " GROUP";

		if (FSAL_TEST_MASK(attr->mask, ATTR_MODE))
			setattr_mode = " MODE";

		if (FSAL_TEST_MASK(attr->mask, ATTR_ACL))
			setattr_acl = " ACL";

		if (FSAL_TEST_MASK(attr->mask, ATTR_ATIME))
			setattr_atime = " ATIME";
		else if (FSAL_TEST_MASK(attr->mask, ATTR_ATIME_SERVER))
			setattr_atime = " ATIME_SERVER";

		if (FSAL_TEST_MASK(attr->mask, ATTR_MTIME))
			setattr_mtime = " MTIME";
		else if (FSAL_TEST_MASK(attr->mask, ATTR_MTIME_SERVER))
			setattr_mtime = " MTIME_SERVER";

		LogDebugCIA(COMPONENT_CACHE_INODE, COMPONENT_NFS_V4_ACL,
			    "SETATTR %s%s%s%s%s%s%s", setattr_size,
			    setattr_owner, setattr_owner_group, setattr_mode,
			    setattr_acl, setattr_mtime, setattr_atime);
	}

	/* Shortcut, if current user is root, then we can just bail out with
	 * success. */
	if (creds->caller_uid == 0) {
		note = " (Ok for root user)";
		goto out;
	}

	not_owner = (creds->caller_uid != entry->obj_handle->attributes.owner);

	/* Only ownership change need to be checked for owner */
	if (FSAL_TEST_MASK(attr->mask, ATTR_OWNER)) {
		/* non-root is only allowed to "take ownership of file" */
		if (attr->owner != creds->caller_uid) {
			status = CACHE_INODE_FSAL_EPERM;
			note = " (new OWNER was not user)";
			goto out;
		}

		/* Owner of file will always be able to "change" the owner to
		 * himself. */
		if (not_owner) {
			access_check |=
			    FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_OWNER);
			LogDebugCIA(COMPONENT_CACHE_INODE, COMPONENT_NFS_V4_ACL,
				    "Change OWNER requires FSAL_ACE_PERM_WRITE_OWNER");
		}
	}
	if (FSAL_TEST_MASK(attr->mask, ATTR_GROUP)) {
		/* non-root is only allowed to change group_owner to a group
		 * user is a member of. */
		int not_in_group = not_in_group_list(attr->group);

		if (not_in_group) {
			status = CACHE_INODE_FSAL_EPERM;
			note = " (user is not member of new GROUP)";
			goto out;
		}
		/* Owner is always allowed to change the group_owner of a file
		 * to a group they are a member of.
		 */
		if (not_owner) {
			access_check |=
			    FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_OWNER);
			LogDebugCIA(COMPONENT_CACHE_INODE, COMPONENT_NFS_V4_ACL,
				    "Change GROUP requires FSAL_ACE_PERM_WRITE_OWNER");
		}
	}

	/* Any attribute after this is always changeable by the owner.
	 * And the above attributes have already been validated as a valid
	 * change for the file owner to make. Note that the owner may be
	 * setting ATTR_OWNER but at this point it MUST be to himself, and
	 * thus is no-op and does not need FSAL_ACE_PERM_WRITE_OWNER.
	 */
	if (!not_owner) {
		note = " (Ok for owner)";
		goto out;
	}

	if (FSAL_TEST_MASK(attr->mask, ATTR_MODE)
	    || FSAL_TEST_MASK(attr->mask, ATTR_ACL)) {
		/* Changing mode or ACL requires ACE4_WRITE_ACL */
		access_check |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_ACL);
		LogDebugCIA(COMPONENT_CACHE_INODE, COMPONENT_NFS_V4_ACL,
			    "Change MODE or ACL requires FSAL_ACE_PERM_WRITE_ACL");
	}

	if (FSAL_TEST_MASK(attr->mask, ATTR_SIZE) && !is_open_write) {
		/* Changing size requires owner or write permission */
	  /** @todo: does FSAL_ACE_PERM_APPEND_DATA allow enlarging the file? */
		access_check |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_DATA);
		LogDebugCIA(COMPONENT_CACHE_INODE, COMPONENT_NFS_V4_ACL,
			    "Change SIZE requires FSAL_ACE_PERM_WRITE_DATA");
	}

	/* Check if just setting atime and mtime to "now" */
	if ((FSAL_TEST_MASK(attr->mask, ATTR_MTIME_SERVER)
	     || FSAL_TEST_MASK(attr->mask, ATTR_ATIME_SERVER))
	    && !FSAL_TEST_MASK(attr->mask, ATTR_MTIME)
	    && !FSAL_TEST_MASK(attr->mask, ATTR_ATIME)) {
		/* If either atime and/or mtime are set to "now" then need only
		 * have write permission.
		 *
		 * Technically, client should not send atime updates, but if
		 * they really do, we'll let them to make the perm check a bit
		 * simpler. */
		access_check |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_DATA);
		LogDebugCIA(COMPONENT_CACHE_INODE, COMPONENT_NFS_V4_ACL,
			    "Change ATIME and MTIME to NOW requires FSAL_ACE_PERM_WRITE_DATA");
	} else if (FSAL_TEST_MASK(attr->mask, ATTR_MTIME_SERVER)
		   || FSAL_TEST_MASK(attr->mask, ATTR_ATIME_SERVER)
		   || FSAL_TEST_MASK(attr->mask, ATTR_MTIME)
		   || FSAL_TEST_MASK(attr->mask, ATTR_ATIME)) {
		/* Any other changes to atime or mtime require owner, root, or
		 * ACES4_WRITE_ATTRIBUTES.
		 *
		 * NOTE: we explicity do NOT check for update of atime only to
		 * "now". Section 10.6 of both RFC 3530 and RFC 5661 document
		 * the reasons clients should not do atime updates.
		 */
		access_check |= FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_ATTR);
		LogDebugCIA(COMPONENT_CACHE_INODE, COMPONENT_NFS_V4_ACL,
			    "Change ATIME and/or MTIME requires FSAL_ACE_PERM_WRITE_ATTR");
	}

	if (isDebug(COMPONENT_CACHE_INODE) || isDebug(COMPONENT_NFS_V4_ACL)) {
		char *need_write_owner = "";
		char *need_write_acl = "";
		char *need_write_data = "";
		char *need_write_attr = "";

		if (access_check & FSAL_ACE_PERM_WRITE_OWNER)
			need_write_owner = " WRITE_OWNER";

		if (access_check & FSAL_ACE_PERM_WRITE_ACL)
			need_write_acl = " WRITE_ACL";

		if (access_check & FSAL_ACE_PERM_WRITE_DATA)
			need_write_data = " WRITE_DATA";

		if (access_check & FSAL_ACE_PERM_WRITE_ATTR)
			need_write_attr = " WRITE_ATTR";

		LogDebugCIA(COMPONENT_CACHE_INODE, COMPONENT_NFS_V4_ACL,
			    "Requires %s%s%s%s", need_write_owner,
			    need_write_acl, need_write_data, need_write_attr);
	}

	if (entry->obj_handle->attributes.acl) {
		status =
		    cache_inode_access_no_mutex(entry, access_check);

		note = " (checked ACL)";
		goto out;
	}

	if (access_check != FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_DATA)) {
		/* Without an ACL, this user is not allowed some operation */
		status = CACHE_INODE_FSAL_EPERM;
		note = " (no ACL to check)";
		goto out;
	}

	status = cache_inode_access_no_mutex(entry, FSAL_W_OK);

	note = " (checked mode)";

 out:

	LogDebugCIA(COMPONENT_CACHE_INODE, COMPONENT_NFS_V4_ACL,
		    "Access check returned %s%s", cache_inode_err_str(status),
		    note);

	return status;
}
コード例 #14
0
/**
 * @brief Set the attributes for a file.
 *
 * This function sets the attributes of a file, both in the cache and
 * in the underlying filesystem.
 *
 * @param[in]     entry   Entry whose attributes are to be set
 * @param[in,out] attr    Attributes to set/result of set
 *
 * @retval CACHE_INODE_SUCCESS if operation is a success
 */
cache_inode_status_t
cache_inode_setattr(cache_entry_t *entry,
		    struct attrlist *attr,
		    bool is_open_write)
{
	struct fsal_obj_handle *obj_handle = entry->obj_handle;
	fsal_status_t fsal_status = { 0, 0 };
	fsal_acl_t *saved_acl = NULL;
	fsal_acl_status_t acl_status = 0;
	cache_inode_status_t status = CACHE_INODE_SUCCESS;
	uint64_t before;
	const struct user_cred *creds = op_ctx->creds;

	/* True if we have taken the content lock on 'entry' */
	bool content_locked = false;

	if ((attr->mask & (ATTR_SIZE | ATTR4_SPACE_RESERVED))
	     && (entry->type != REGULAR_FILE)) {
		LogWarn(COMPONENT_CACHE_INODE,
			"Attempt to truncate non-regular file: type=%d",
			entry->type);
		status = CACHE_INODE_BAD_TYPE;
		goto out;
	}

	/* Is it allowed to change times ? */
	if (!op_ctx->fsal_export->exp_ops.fs_supports(op_ctx->fsal_export,
						    fso_cansettime)
	    &&
	    (FSAL_TEST_MASK
	     (attr->mask,
	      (ATTR_ATIME | ATTR_CREATION | ATTR_CTIME | ATTR_MTIME)))) {
		status = CACHE_INODE_INVALID_ARGUMENT;
		goto out;
	}

	/* Get wrlock on attr_lock and verify attrs */
	status = cache_inode_lock_trust_attrs(entry, true);
	if (status != CACHE_INODE_SUCCESS)
		return status;

	/* Do permission checks */
	status = cache_inode_check_setattr_perms(entry, attr, is_open_write);
	if (status != CACHE_INODE_SUCCESS)
		goto unlock;

	if (attr->mask & (ATTR_SIZE | ATTR4_SPACE_RESERVED)) {
		PTHREAD_RWLOCK_wrlock(&entry->content_lock);
		content_locked = true;
	}

	/* Test for the following condition from chown(2):
	 *
	 *     When the owner or group of an executable file are changed by an
	 *     unprivileged user the S_ISUID and S_ISGID mode bits are cleared.
	 *     POSIX does not specify whether this also should happen when
	 *     root does the chown(); the Linux behavior depends on the kernel
	 *     version.  In case of a non-group-executable file (i.e., one for
	 *     which the S_IXGRP bit is not set) the S_ISGID bit indicates
	 *     mandatory locking, and is not cleared by a chown().
	 *
	 */
	if (creds->caller_uid != 0 &&
	    (FSAL_TEST_MASK(attr->mask, ATTR_OWNER) ||
	     FSAL_TEST_MASK(attr->mask, ATTR_GROUP)) &&
	    ((entry->obj_handle->attrs->mode &
	      (S_IXOTH | S_IXUSR | S_IXGRP)) != 0) &&
	    ((entry->obj_handle->attrs->mode &
	      (S_ISUID | S_ISGID)) != 0)) {
		/* Non-priviledged user changing ownership on an executable
		 * file with S_ISUID or S_ISGID bit set, need to be cleared.
		 */
		if (!FSAL_TEST_MASK(attr->mask, ATTR_MODE)) {
			/* Mode wasn't being set, so set it now, start with
			 * the current attributes.
			 */
			attr->mode = entry->obj_handle->attrs->mode;
			FSAL_SET_MASK(attr->mask, ATTR_MODE);
		}

		/* Don't clear S_ISGID if the file isn't group executable.
		 * In that case, S_ISGID indicates mandatory locking and
		 * is not cleared by chown.
		 */
		if ((entry->obj_handle->attrs->mode & S_IXGRP) != 0)
			attr->mode &= ~S_ISGID;

		/* Clear S_ISUID. */
		attr->mode &= ~S_ISUID;
	}

	/* Test for the following condition from chmod(2):
	 *
	 *     If the calling process is not privileged (Linux: does not have
	 *     the CAP_FSETID capability), and the group of the file does not
	 *     match the effective group ID of the process or one of its
	 *     supplementary group IDs, the S_ISGID bit will be turned off,
	 *     but this will not cause an error to be returned.
	 *
	 * We test the actual mode being set before testing for group
	 * membership since that is a bit more expensive.
	 */
	if (creds->caller_uid != 0 &&
	    FSAL_TEST_MASK(attr->mask, ATTR_MODE) &&
	    (attr->mode & S_ISGID) != 0 &&
	    not_in_group_list(entry->obj_handle->attrs->group)) {
		/* Clear S_ISGID */
		attr->mode &= ~S_ISGID;
	}

	saved_acl = entry->obj_handle->attrs->acl;
	before = entry->obj_handle->attrs->change;
	fsal_status = obj_handle->obj_ops.setattrs(obj_handle, attr);
	if (FSAL_IS_ERROR(fsal_status)) {
		status = cache_inode_error_convert(fsal_status);
		if (fsal_status.major == ERR_FSAL_STALE) {
			LogEvent(COMPONENT_CACHE_INODE,
				 "FSAL returned STALE from setattrs");
			cache_inode_kill_entry(entry);
		}
		goto unlock;
	}
	fsal_status = obj_handle->obj_ops.getattrs(obj_handle);
	*attr = *entry->obj_handle->attrs;
	if (FSAL_IS_ERROR(fsal_status)) {
		status = cache_inode_error_convert(fsal_status);
		if (fsal_status.major == ERR_FSAL_STALE) {
			LogEvent(COMPONENT_CACHE_INODE,
				 "FSAL returned STALE from getattrs");
			cache_inode_kill_entry(entry);
		}
		goto unlock;
	}
	if (before == entry->obj_handle->attrs->change)
		entry->obj_handle->attrs->change++;
	/* Decrement refcount on saved ACL */
	nfs4_acl_release_entry(saved_acl, &acl_status);
	if (acl_status != NFS_V4_ACL_SUCCESS)
		LogCrit(COMPONENT_CACHE_INODE,
			"Failed to release old acl, status=%d", acl_status);

	cache_inode_fixup_md(entry);

	/* Copy the complete set of new attributes out. */

	*attr = *entry->obj_handle->attrs;

	status = CACHE_INODE_SUCCESS;

unlock:
	if (content_locked)
		PTHREAD_RWLOCK_unlock(&entry->content_lock);
	PTHREAD_RWLOCK_unlock(&entry->attr_lock);

out:
	return status;
}
コード例 #15
0
/**
 *
 * cache_inode_get: Gets an entry by using its fsdata as a key and caches it if needed.
 * 
 * Gets an entry by using its fsdata as a key and caches it if needed.
 * ASSUMPTION: DIR_CONT entries are always garbabbaged before their related DIR_BEGINNG 
 *
 * @param fsdata [IN] file system data
 * @param pattr [OUT] pointer to the attributes for the result. 
 * @param ht [IN] hash table used for the cache, unused in this call.
 * @param pclient [INOUT] ressource allocated by the client for the nfs management.
 * @param pcontext [IN] FSAL credentials 
 * @param pstatus [OUT] returned status.
 * 
 * @return the pointer to the entry is successfull, NULL otherwise.
 *
 */
cache_entry_t *cache_inode_get(cache_inode_fsal_data_t * pfsdata,
                               fsal_attrib_list_t * pattr,
                               hash_table_t * ht,
                               cache_inode_client_t * pclient,
                               fsal_op_context_t * pcontext,
                               cache_inode_status_t * pstatus)
{
  hash_buffer_t key, value;
  cache_entry_t *pentry = NULL;
  fsal_status_t fsal_status;
  cache_inode_create_arg_t create_arg;
  cache_inode_file_type_t type;
  int hrc = 0;
  fsal_attrib_list_t fsal_attributes;
  cache_inode_fsal_data_t *ppoolfsdata = NULL;

  /* Set the return default to CACHE_INODE_SUCCESS */
  *pstatus = CACHE_INODE_SUCCESS;

  /* stats */
  pclient->stat.nb_call_total += 1;
  pclient->stat.func_stats.nb_call[CACHE_INODE_GET] += 1;

  /* Turn the input to a hash key */
  if(cache_inode_fsaldata_2_key(&key, pfsdata, pclient))
    {
      *pstatus = CACHE_INODE_UNAPPROPRIATED_KEY;

      /* stats */
      pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1;

      ppoolfsdata = (cache_inode_fsal_data_t *) key.pdata;
      RELEASE_PREALLOC(ppoolfsdata, pclient->pool_key, next_alloc);

      return NULL;
    }

  switch (hrc = HashTable_Get(ht, &key, &value))
    {
    case HASHTABLE_SUCCESS:
      /* Entry exists in the cache and was found */
      pentry = (cache_entry_t *) value.pdata;

      /* return attributes additionally */
      cache_inode_get_attributes(pentry, pattr);

      break;

    case HASHTABLE_ERROR_NO_SUCH_KEY:
      /* Cache miss, allocate a new entry */

      /* If we ask for a dir cont (in this case pfsdata.cookie != FSAL_DIR_BEGINNING, we have 
       * a client who performs a readdir in the middle of a directory, when the direcctories
       * have been garbbage. we must search for the DIR_BEGIN related to this DIR_CONT */
      if(pfsdata->cookie != DIR_START)
        {
          /* added for sanity check */
          LogDebug(COMPONENT_CACHE_INODE_GC,
              "=======> Pb cache_inode_get: line %u pfsdata->cookie != DIR_START (=%u) on object whose type is %u",
               __LINE__, pfsdata->cookie,
               cache_inode_fsal_type_convert(fsal_attributes.type));

          pfsdata->cookie = DIR_START;

          /* Free this key */
          cache_inode_release_fsaldata_key(&key, pclient);

          /* redo the call */
          return cache_inode_get(pfsdata, pattr, ht, pclient, pcontext, pstatus);
        }

      /* First, call FSAL to know what the object is */
      fsal_attributes.asked_attributes = pclient->attrmask;
      fsal_status = FSAL_getattrs(&pfsdata->handle, pcontext, &fsal_attributes);
      if(FSAL_IS_ERROR(fsal_status))
        {
          *pstatus = cache_inode_error_convert(fsal_status);

          LogDebug(COMPONENT_CACHE_INODE_GC, "cache_inode_get: line %u cache_inode_status=%u fsal_status=%u,%u ",
                     __LINE__, *pstatus, fsal_status.major, fsal_status.minor);

          if(fsal_status.major == ERR_FSAL_STALE)
            {
              char handle_str[256];

              snprintHandle(handle_str, 256, &pfsdata->handle);
              LogEvent(COMPONENT_CACHE_INODE_GC,"cache_inode_get: Stale FSAL File Handle %s", handle_str);

              *pstatus = CACHE_INODE_FSAL_ESTALE;
            }

          /* stats */
          pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1;

          /* Free this key */
          cache_inode_release_fsaldata_key(&key, pclient);

          return NULL;
        }

      /* The type has to be set in the attributes */
      if(!FSAL_TEST_MASK(fsal_attributes.supported_attributes, FSAL_ATTR_TYPE))
        {
          *pstatus = CACHE_INODE_FSAL_ERROR;

          /* stats */
          pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1;

          /* Free this key */
          cache_inode_release_fsaldata_key(&key, pclient);

          return NULL;
        }

      /* Get the cache_inode file type */
      type = cache_inode_fsal_type_convert(fsal_attributes.type);

      if(type == SYMBOLIC_LINK)
        {
          FSAL_CLEAR_MASK(fsal_attributes.asked_attributes);
          FSAL_SET_MASK(fsal_attributes.asked_attributes, pclient->attrmask);
          fsal_status =
              FSAL_readlink(&pfsdata->handle, pcontext, &create_arg.link_content,
                            &fsal_attributes);
          if(FSAL_IS_ERROR(fsal_status))
            {
              *pstatus = cache_inode_error_convert(fsal_status);

              /* stats */
              pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1;

              /* Free this key */
              cache_inode_release_fsaldata_key(&key, pclient);

              if(fsal_status.major == ERR_FSAL_STALE)
                {
                  cache_inode_status_t kill_status;

                  LogDebug(COMPONENT_CACHE_INODE_GC,
                      "cache_inode_get: Stale FSAL File Handle detected for pentry = %p",
                       pentry);

                  if(cache_inode_kill_entry(pentry, ht, pclient, &kill_status) !=
                     CACHE_INODE_SUCCESS)
                    LogCrit(COMPONENT_CACHE_INODE_GC,"cache_inode_get: Could not kill entry %p, status = %u",
                               pentry, kill_status);

                  *pstatus = CACHE_INODE_FSAL_ESTALE;

                }

              return NULL;
            }
        }

      /* Add the entry to the cache */
      if((pentry = cache_inode_new_entry(pfsdata, &fsal_attributes, type, &create_arg, NULL,    /* never used to add a new DIR_CONTINUE within the scope of this function */
                                         ht, pclient, pcontext, FALSE,  /* This is a population, not a creation */
                                         pstatus)) == NULL)
        {
          /* stats */
          pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1;

          /* Free this key */
          cache_inode_release_fsaldata_key(&key, pclient);

          return NULL;
        }

      /* Set the returned attributes */
      *pattr = fsal_attributes;

      /* Now, exit the switch/case and returns */
      break;

    default:
      /* This should not happened */
      *pstatus = CACHE_INODE_INVALID_ARGUMENT;

      /* stats */
      pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1;

      /* Free this key */
      cache_inode_release_fsaldata_key(&key, pclient);

      return NULL;
      break;
    }

  *pstatus = CACHE_INODE_SUCCESS;

  /* valid the found entry, if this is not feasable, returns nothing to the client */
  P_w(&pentry->lock);
  if((*pstatus =
      cache_inode_valid(pentry, CACHE_INODE_OP_GET, pclient)) != CACHE_INODE_SUCCESS)
    {
      V_w(&pentry->lock);
      pentry = NULL;
    }
  V_w(&pentry->lock);

  /* stats */
  pclient->stat.func_stats.nb_success[CACHE_INODE_GET] += 1;

  /* Free this key */
  cache_inode_release_fsaldata_key(&key, pclient);

  return pentry;
}                               /* cache_inode_get */
コード例 #16
0
/**
 *
 * cache_inode_getattr: Gets the attributes for a cached entry.
 *
 * Gets the attributes for a cached entry. The FSAL attributes are kept in a structure when the entry
 * is added to the cache.
 *
 * @param pentry [IN] entry to be managed.
 * @param pattr [OUT] pointer to the results
 * @param ht [IN] hash table used for the cache, unused in this call.
 * @param pclient [INOUT] ressource allocated by the client for the nfs management.
 * @param pcontext [IN] FSAL credentials
 * @param pstatus [OUT] returned status.
 *
 * @return CACHE_INODE_SUCCESS if operation is a success \n
 * @return CACHE_INODE_LRU_ERROR if allocation error occured when validating the entry
 *
 */
cache_inode_status_t
cache_inode_getattr(cache_entry_t * pentry,
                    fsal_attrib_list_t * pattr,
                    hash_table_t * ht, /* Unused, kept for protototype's homogeneity */
                    cache_inode_client_t * pclient,
                    fsal_op_context_t * pcontext,
                    cache_inode_status_t * pstatus)
{
    cache_inode_status_t status;
    fsal_handle_t *pfsal_handle = NULL;
    fsal_status_t fsal_status;

    /* sanity check */
    if(pentry == NULL || pattr == NULL ||
       ht == NULL || pclient == NULL || pcontext == NULL)
        {
            *pstatus = CACHE_INODE_INVALID_ARGUMENT;
            LogDebug(COMPONENT_CACHE_INODE,
                     "cache_inode_getattr: returning CACHE_INODE_INVALID_ARGUMENT because of bad arg");
            return *pstatus;
        }

    /* Set the return default to CACHE_INODE_SUCCESS */
    *pstatus = CACHE_INODE_SUCCESS;

    /* stats */
    pclient->stat.nb_call_total += 1;
    inc_func_call(pclient, CACHE_INODE_GETATTR);

    /* Lock the entry */
    P_w(&pentry->lock);
    status = cache_inode_renew_entry(pentry, pattr, ht,
                                     pclient, pcontext, pstatus);
    if(status != CACHE_INODE_SUCCESS)
        {
            V_w(&pentry->lock);
            inc_func_err_retryable(pclient, CACHE_INODE_GETATTR);
            LogFullDebug(COMPONENT_CACHE_INODE,
                         "cache_inode_getattr: returning %d(%s) from cache_inode_renew_entry",
                         *pstatus, cache_inode_err_str(*pstatus));
            return *pstatus;
        }

    /* RW Lock goes for writer to reader */
    rw_lock_downgrade(&pentry->lock);

    cache_inode_get_attributes(pentry, pattr);

    if(FSAL_TEST_MASK(pattr->asked_attributes,
                      FSAL_ATTR_RDATTR_ERR))
        {
            switch (pentry->internal_md.type)
                {
                case REGULAR_FILE:
                    pfsal_handle = &pentry->object.file.handle;
                    break;

                case SYMBOLIC_LINK:
                    assert(pentry->object.symlink);
                    pfsal_handle = &pentry->object.symlink->handle;
                    break;

                case DIRECTORY:
                    pfsal_handle = &pentry->object.dir.handle;
                    break;
                case SOCKET_FILE:
                case FIFO_FILE:
                case BLOCK_FILE:
                case CHARACTER_FILE:
                    pfsal_handle = &pentry->object.special_obj.handle;
                    break;
                case FS_JUNCTION:
                case UNASSIGNED:
                case RECYCLED:
                    *pstatus = CACHE_INODE_INVALID_ARGUMENT;
                    LogFullDebug(COMPONENT_CACHE_INODE,
                                 "cache_inode_getattr: returning %d(%s) from cache_inode_renew_entry - unexpected md_type",
                                 *pstatus, cache_inode_err_str(*pstatus));
                    return *pstatus;
                }

            /*
             * An error occured when trying to get
             * the attributes, they have to be renewed
             */
#ifdef _USE_MFSL
            fsal_status = FSAL_getattrs_descriptor(&(cache_inode_fd(pentry)->fsal_file), pfsal_handle, pcontext, pattr);
#else
            fsal_status = FSAL_getattrs_descriptor(cache_inode_fd(pentry), pfsal_handle, pcontext, pattr);
#endif
            if(FSAL_IS_ERROR(fsal_status))
                {
                    *pstatus = cache_inode_error_convert(fsal_status);
                    
                    V_r(&pentry->lock);

                    if(fsal_status.major == ERR_FSAL_STALE)
                        {
                            cache_inode_status_t kill_status;

                            LogEvent(COMPONENT_CACHE_INODE,
                                     "cache_inode_getattr: Stale FSAL File Handle detected for pentry = %p",
                                     pentry);

                            /* Locked flag is set to true to show entry has a read lock */
                            cache_inode_kill_entry( pentry, WT_LOCK, ht,
                                                    pclient, &kill_status);
                            if(kill_status != CACHE_INODE_SUCCESS)
                                LogCrit(COMPONENT_CACHE_INODE,
                                        "cache_inode_getattr: Could not kill entry %p, status = %u",
                                        pentry, kill_status);

                            *pstatus = CACHE_INODE_FSAL_ESTALE;
                        }

                    /* stat */
                    inc_func_err_unrecover(pclient, CACHE_INODE_GETATTR);
                    LogDebug(COMPONENT_CACHE_INODE,
                             "cache_inode_getattr: returning %d(%s) from FSAL_getattrs_descriptor",
                             *pstatus, cache_inode_err_str(*pstatus));
                    return *pstatus;
                }

            /* Set the new attributes */
            cache_inode_set_attributes(pentry, pattr);
        }
    *pstatus = cache_inode_valid(pentry, CACHE_INODE_OP_GET, pclient);

    V_r(&pentry->lock);

    /* stat */
    if(*pstatus != CACHE_INODE_SUCCESS)
        inc_func_err_retryable(pclient, CACHE_INODE_GETATTR);
    else
        inc_func_success(pclient, CACHE_INODE_GETATTR);

#ifdef _USE_NFS4_ACL
    if(isDebug(COMPONENT_NFS_V4_ACL))
      {
        LogDebug(COMPONENT_CACHE_INODE,
                 "cache_inode_getattr: pentry = %p, acl = %p",
                 pentry, pattr->acl);

        if(pattr->acl)
          {
            fsal_ace_t *pace;
            for(pace = pattr->acl->aces; pace < pattr->acl->aces + pattr->acl->naces; pace++)
              {
                LogDebug(COMPONENT_CACHE_INODE,
                         "cache_inode_getattr: ace type = 0x%x, flag = 0x%x, perm = 0x%x, special = %d, %s = 0x%x",
                         pace->type, pace->flag, pace->perm, IS_FSAL_ACE_SPECIAL_ID(*pace),
                         GET_FSAL_ACE_WHO_TYPE(*pace), GET_FSAL_ACE_WHO(*pace));
              }
          }
      }
#endif                          /* _USE_NFS4_ACL */

    LogFullDebug(COMPONENT_CACHE_INODE,
                 "cache_inode_getattr: returning %d(%s) from cache_inode_valid",
                 *pstatus, cache_inode_err_str(*pstatus));
    return *pstatus;
}
コード例 #17
0
ファイル: fsal_attrs.c プロジェクト: ShyamsundarR/nfs-ganesha
/**
 * VFSFSAL_setattrs:
 * Set attributes for the object specified by its filehandle.
 *
 * \param filehandle (input):
 *        The handle of the object to get parameters.
 * \param cred (input):
 *        Authentication context for the operation (user,...).
 * \param attrib_set (mandatory input):
 *        The attributes to be set for the object.
 *        It defines the attributes that the caller
 *        wants to set and their values.
 * \param object_attributes (optionnal input/output):
 *        The post operation attributes for the object.
 *        As input, it defines the attributes that the caller
 *        wants to retrieve (by positioning flags into this structure)
 *        and the output is built considering this input
 *        (it fills the structure according to the flags it contains).
 *        May be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - Another error code if an error occured.
 */
fsal_status_t VFSFSAL_setattrs(fsal_handle_t * p_filehandle,       /* IN */
                            fsal_op_context_t * p_context,      /* IN */
                            fsal_attrib_list_t * p_attrib_set,  /* IN */
                            fsal_attrib_list_t * p_object_attributes    /* [ IN/OUT ] */
    )
{
  vfsfsal_op_context_t * vfs_context = (vfsfsal_op_context_t *) p_context;
  int rc, errsv;
  unsigned int i;
  fsal_status_t status;
  fsal_attrib_list_t attrs;

  int fd;
  struct stat buffstat;

  /* sanity checks.
   * note : object_attributes is optional.
   */
  if(!p_filehandle || !p_context || !p_attrib_set)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs);

  /* local copy of attributes */
  attrs = *p_attrib_set;

  /* It does not make sense to setattr on a symlink */
  /* if(p_filehandle->type == DT_LNK)
     return fsal_internal_setattrs_symlink(p_filehandle, p_context, p_attrib_set,
     p_object_attributes);
   */
  /* First, check that FSAL attributes changes are allowed. */

  /* Is it allowed to change times ? */

  if(!global_fs_info.cansettime)
    {

      if(attrs.asked_attributes
         & (FSAL_ATTR_ATIME | FSAL_ATTR_CREATION | FSAL_ATTR_CTIME | FSAL_ATTR_MTIME))
        {
          /* handled as an unsettable attribute. */
          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_setattrs);
        }
    }

  /* apply umask, if mode attribute is to be changed */
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
    {
      attrs.mode &= (~global_fs_info.umask);
    }

  TakeTokenFSCall();
  status = fsal_internal_handle2fd(p_context, p_filehandle, &fd, O_RDONLY);
  ReleaseTokenFSCall();
  if(FSAL_IS_ERROR(status))
   {
     /* Symbolic link are handled here, they are to be opened as O_PATH */
     if( status.minor == ELOOP )
      {
           if(p_object_attributes)
             {
               status = VFSFSAL_getattrs(p_filehandle, p_context, p_object_attributes);

               /* on error, we set a special bit in the mask. */
               if(FSAL_IS_ERROR(status))
                 {
                   FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
                   FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
                 }
             }
           Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs);
      }

     ReturnStatus( status, INDEX_FSAL_setattrs);
   }

  /* get current attributes */
  TakeTokenFSCall();
  rc = fstat(fd, &buffstat);
  errsv = errno;
  ReleaseTokenFSCall();

  if(rc != 0)
    {
      close(fd);

      if(errsv == ENOENT)
        Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_setattrs);
      else
        Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_setattrs);
    }

  /***********
   *  CHMOD  *
   ***********/
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
    {

      /* The POSIX chmod call don't affect the symlink object, but
       * the entry it points to. So we must ignore it.
       */
      if(!S_ISLNK(buffstat.st_mode))
        {

          /* For modifying mode, user must be root or the owner */
          if((vfs_context->credential.user != 0)
             && (vfs_context->credential.user != buffstat.st_uid))
            {
              LogFullDebug(COMPONENT_FSAL,
                           "Permission denied for CHMOD opeartion: current owner=%d, credential=%d",
                           buffstat.st_uid, vfs_context->credential.user);
              close(fd);
              Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
            }

          TakeTokenFSCall();
          rc = fchmod(fd, fsal2unix_mode(attrs.mode));
          errsv = errno;
          ReleaseTokenFSCall();

          if(rc)
            {
              close(fd);
              Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_setattrs);
            }

        }

    }

  /***********
   *  CHOWN  *
   ***********/
  /* Only root can change uid and A normal user must be in the group he wants to set */
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER))
    {

      /* For modifying owner, user must be root or current owner==wanted==client */
      if((vfs_context->credential.user != 0) &&
         ((vfs_context->credential.user != buffstat.st_uid) ||
          (vfs_context->credential.user != attrs.owner)))
        {
          LogFullDebug(COMPONENT_FSAL,
                       "Permission denied for CHOWN opeartion: current owner=%d, credential=%d, new owner=%d",
                       buffstat.st_uid, vfs_context->credential.user, attrs.owner);
          close(fd);
          Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
        }
    }

  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_GROUP))
    {

      /* For modifying group, user must be root or current owner */
      if((vfs_context->credential.user != 0)
         && (vfs_context->credential.user != buffstat.st_uid))
        {
          close(fd);
          Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
        }

      int in_grp = 0;
      /* set in_grp */
      if(vfs_context->credential.group == attrs.group)
        in_grp = 1;
      else
        for(i = 0; i < vfs_context->credential.nbgroups; i++)
          {
            if((in_grp = (attrs.group == vfs_context->credential.alt_groups[i])))
              break;
          }

      /* it must also be in target group */
      if(vfs_context->credential.user != 0 && !in_grp)
        {
          LogFullDebug(COMPONENT_FSAL,
                       "Permission denied for CHOWN operation: current group=%d, credential=%d, new group=%d",
                       buffstat.st_gid, vfs_context->credential.group, attrs.group);
          close(fd);
          Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
        }
    }

  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER | FSAL_ATTR_GROUP))
    {
      /*      LogFullDebug(COMPONENT_FSAL, "Performing chown(%s, %d,%d)",
                        fsalpath.path, FSAL_TEST_MASK(attrs.asked_attributes,
                                                      FSAL_ATTR_OWNER) ? (int)attrs.owner
                        : -1, FSAL_TEST_MASK(attrs.asked_attributes,
			FSAL_ATTR_GROUP) ? (int)attrs.group : -1);*/

      TakeTokenFSCall();
      rc = fchown(fd,
                  FSAL_TEST_MASK(attrs.asked_attributes,
                                 FSAL_ATTR_OWNER) ? (int)attrs.owner : -1,
                  FSAL_TEST_MASK(attrs.asked_attributes,
                                 FSAL_ATTR_GROUP) ? (int)attrs.group : -1);
      ReleaseTokenFSCall();
      if(rc)
        {
          close(fd);
          Return(posix2fsal_error(errno), errno, INDEX_FSAL_setattrs);
        }
    }

  /***********
   *  UTIME  *
   ***********/

  /* user must be the owner or have read access to modify 'atime' */
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME)
     && (vfs_context->credential.user != 0)
     && (vfs_context->credential.user != buffstat.st_uid)
     && ((status = fsal_check_access(p_context, FSAL_R_OK, &buffstat, NULL)).major
         != ERR_FSAL_NO_ERROR))
    {
      close(fd);
      ReturnStatus(status, INDEX_FSAL_setattrs);
    }
  /* user must be the owner or have write access to modify 'mtime' */
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME)
     && (vfs_context->credential.user != 0)
     && (vfs_context->credential.user != buffstat.st_uid)
     && ((status = fsal_check_access(p_context, FSAL_W_OK, &buffstat, NULL)).major
         != ERR_FSAL_NO_ERROR))
    {
      close(fd);
      ReturnStatus(status, INDEX_FSAL_setattrs);
    }

  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME | FSAL_ATTR_MTIME))
    {

      struct timeval timebuf[2];

      /* Atime */
      timebuf[0].tv_sec =
          (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME) ? (time_t) attrs.
           atime.seconds : buffstat.st_atime);
      timebuf[0].tv_usec = 0;

      /* Mtime */
      timebuf[1].tv_sec =
          (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME) ? (time_t) attrs.
           mtime.seconds : buffstat.st_mtime);
      timebuf[1].tv_usec = 0;

      TakeTokenFSCall();
      rc = futimes(fd, timebuf);
      errsv = errno;
      ReleaseTokenFSCall();
      if(rc)
        {
          close(fd);
          Return(posix2fsal_error(errno), errno, INDEX_FSAL_setattrs);
        }
    }

  /* Optionaly fills output attributes. */

  if(p_object_attributes)
    {
      status = VFSFSAL_getattrs(p_filehandle, p_context, p_object_attributes);

      /* on error, we set a special bit in the mask. */
      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
          FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
        }

    }

  close(fd);
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs);

}
コード例 #18
0
ファイル: fsal_attrs.c プロジェクト: MeghanaM/nfs-ganesha
fsal_status_t CEPHFSAL_setattrs(fsal_handle_t * exthandle,
                                fsal_op_context_t * extcontext,
                                fsal_attrib_list_t * attrib_set,
                                fsal_attrib_list_t * object_attributes)
{
  cephfsal_handle_t* filehandle = (cephfsal_handle_t*) exthandle;
  cephfsal_op_context_t* context = (cephfsal_op_context_t*) extcontext;
  struct stat st;
  fsal_attrib_list_t attrs;
  int rc, mask=0;
  int uid = FSAL_OP_CONTEXT_TO_UID(context);
  int gid = FSAL_OP_CONTEXT_TO_GID(context);

  /* sanity checks.
   * note : object_attributes is optional.
   */
  if(!filehandle || !context || !attrib_set)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs);

  /* local copy of attributes */
  attrs = *attrib_set;

  /* First, check that FSAL attributes changes are allowed. */

  /* Is it allowed to change times ? */

  if(!global_fs_info.cansettime)
    {
      if(attrs.asked_attributes &
         (FSAL_ATTR_ATIME |
          FSAL_ATTR_CREATION |
          FSAL_ATTR_CTIME |
          FSAL_ATTR_MTIME))
        {

          /* handled as an unsettable attribute. */
          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_setattrs);
        }

    }

  /* apply umask, if mode attribute is to be changed */

  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
    {
      attrs.mode &= (~global_fs_info.umask);
    }

  /* Build flags and struct stat */

  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
    {
      mask |= CEPH_SETATTR_MODE;
      st.st_mode = fsal2unix_mode(attrs.mode);
    }
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER))
    {
      mask |= CEPH_SETATTR_UID;
      st.st_uid = attrs.owner;
    }
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_GROUP))
    {
      mask |= CEPH_SETATTR_UID;
      st.st_gid = attrs.group;
    }
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME))
    {
      mask |= CEPH_SETATTR_ATIME;
      st.st_atime = attrs.atime.seconds;
    }
  if (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME))
    {
      mask |= CEPH_SETATTR_MTIME;
      st.st_mtime = attrs.mtime.seconds;
    }
  if (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_CTIME))
    {
      mask |= CEPH_SETATTR_CTIME;
      st.st_ctime = attrs.ctime.seconds;
    }

  TakeTokenFSCall();

  rc = ceph_ll_setattr(context->export_context->cmount, VINODE(filehandle),
                       &st, mask, uid, gid);

  ReleaseTokenFSCall();

  if (rc < 0)
    Return(posix2fsal_error(rc), 0, INDEX_FSAL_getattrs);

  if(object_attributes)
    {
      fsal_status_t status;
      status = CEPHFSAL_getattrs(exthandle, extcontext, object_attributes);

      /* on error, we set a special bit in the mask. */
      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(object_attributes->asked_attributes);
          FSAL_SET_MASK(object_attributes->asked_attributes,
                        FSAL_ATTR_RDATTR_ERR);
        }

    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs);
}
コード例 #19
0
ファイル: test_fsal.c プロジェクト: MeghanaM/nfs-ganesha
void printmask(fsal_attrib_mask_t mask)
{

  if(FSAL_TEST_MASK(mask, FSAL_ATTR_SUPPATTR))
    LogTest("FSAL_ATTR_SUPPATTR");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_TYPE))
    LogTest("FSAL_ATTR_TYPE");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_SIZE))
    LogTest("FSAL_ATTR_SIZE");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_FSID))
    LogTest("FSAL_ATTR_FSID");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_ACL))
    LogTest("FSAL_ATTR_ACL ");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_FILEID))
    LogTest("FSAL_ATTR_FILEID");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_MODE))
    LogTest("FSAL_ATTR_MODE");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_NUMLINKS))
    LogTest("FSAL_ATTR_NUMLINKS");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_OWNER))
    LogTest("FSAL_ATTR_OWNER");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_GROUP))
    LogTest("FSAL_ATTR_GROUP");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_RAWDEV))
    LogTest("FSAL_ATTR_RAWDEV");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_ATIME))
    LogTest("FSAL_ATTR_ATIME");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_CREATION))
    LogTest("FSAL_ATTR_CREATION");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_CTIME))
    LogTest("FSAL_ATTR_CTIME");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_CHGTIME))
    LogTest("FSAL_ATTR_CHGTIME");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_MTIME))
    LogTest("FSAL_ATTR_MTIME");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_SPACEUSED))
    LogTest("FSAL_ATTR_SPACEUSED");
  if(FSAL_TEST_MASK(mask, FSAL_ATTR_MOUNTFILEID))
    LogTest("FSAL_ATTR_MOUNTFILEID");

}
コード例 #20
0
ファイル: fsal_access.c プロジェクト: jordan-dlh/nfs-ganesha
/**
 * FSAL_test_setattr_access_default :
 * test if a client identified by cred can access setattr on the object
 * knowing its attributes and parent's attributes.
 * The following fields of the object_attributes structures MUST be filled :
 * acls (if supported), mode, owner, group.
 * This doesn't make any call to the filesystem,
 * as a result, this doesn't ensure that the file exists, nor that
 * the permissions given as parameters are the actual file permissions :
 * this must be ensured by the cache_inode layer, using FSAL_getattrs,
 * for example.
 *
 * \param cred (in zfsfsal_cred_t *) user's identifier.
 * \param candidate_attributes the attributes we want to set on the object
 * \param object_attributes (in fsal_attrib_list_t *) the cached attributes
 *        for the object.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_ACCESS       (Permission denied)
 *        - ERR_FSAL_FAULT        (null pointer parameter)
 *        - ERR_FSAL_INVAL        (missing attributes : mode, group, user,...)
 *        - ERR_FSAL_SERVERFAULT  (unexpected error)
 */
fsal_status_t FSAL_setattr_access_default(fsal_op_context_t  * p_context,            /* IN */
                                          fsal_attrib_list_t * candidate_attributes, /* IN */
                                          fsal_attrib_list_t * object_attributes     /* IN */
    )
{
	fsal_status_t fsal_status;

	int in_grp;
	int i;
	fsal_count_t nb_alt_groups;
	gid_t * alt_groups;

	in_grp = 0;

	/*
	 * CHMOD
	 * */

	/* We just ignore symlinks. */
	if(FSAL_TEST_MASK(candidate_attributes->asked_attributes, FSAL_ATTR_MODE) 
	   && (object_attributes->type != FSAL_TYPE_LNK))
	{
		/* User must be root or owner of the file */
		if( (FSAL_OP_CONTEXT_TO_UID(p_context) != 0) 
		    && (FSAL_OP_CONTEXT_TO_UID(p_context) =! object_attributes->owner) )
			Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);
	}

	/*
	 * CHOWN
	 * */

	if(FSAL_TEST_MASK(candidate_attributes->asked_attributes, FSAL_ATTR_OWNER))
	{
		/* User must be root or (be the owner and the user he wants to set) */
		if( (FSAL_OP_CONTEXT_TO_UID(p_context) != 0) 
		    && ( ( FSAL_OP_CONTEXT_TO_UID(p_context) != object_attributes->owner ) 
		    	   || ( FSAL_OP_CONTEXT_TO_UID(p_context) != candidate_attributes->owner ) ) )
			Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);
	}

	if(FSAL_TEST_MASK(candidate_attributes->asked_attributes, FSAL_ATTR_GROUP))
	{
		/* User must ( be root or owner ) */
		if( (FSAL_OP_CONTEXT_TO_UID(p_context) != 0) && (FSAL_OP_CONTEXT_TO_UID(p_context) != object_attributes->owner) )
			Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);

		/* He must also be in the group he wants to set */
		in_grp = ( FSAL_OP_CONTEXT_TO_GID(p_context) == candidate_attributes->group );
		
		if(!in_grp && FSAL_OP_CONTEXT_TO_ALT_GROUPS(p_context) != NULL)
		{
			nb_alt_groups = FSAL_OP_CONTEXT_TO_NBGROUPS(p_context);
			alt_groups = FSAL_OP_CONTEXT_TO_ALT_GROUPS(p_context);

			/* Test user's alt groups */
			for(i = 0; i < nb_alt_groups; i++)
			{
				in_grp = (alt_groups[i] == object_attributes->group);
				if(in_grp)
					break;
			}
		}

		if(!in_grp)
			Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);

	}

	/* 
	 * UTIME 
	 * */

	/* Is it allowed to change time? */
	if(FSAL_TEST_MASK(candidate_attributes->asked_attributes, 
                          FSAL_ATTR_ATIME | FSAL_ATTR_CREATION | FSAL_ATTR_CTIME | FSAL_ATTR_MTIME)
	   && !global_fs_info.cansettime)
		Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);

	/* Atime: user must be owner or be root or have read access */
	if( FSAL_TEST_MASK(candidate_attributes->asked_attributes, FSAL_ATTR_ATIME)
	    && (FSAL_OP_CONTEXT_TO_UID(p_context) != 0)
	    && (FSAL_OP_CONTEXT_TO_UID(p_context) != object_attributes->owner))
	{
		fsal_status = FSAL_test_access_default(p_context, FSAL_R_OK, object_attributes);
		if(FSAL_IS_ERROR(fsal_status))
			Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);
	}

	/* Mtime: user must be owner or be root or have write access */
	if( FSAL_TEST_MASK(candidate_attributes->asked_attributes, FSAL_ATTR_MTIME)
	    && (FSAL_OP_CONTEXT_TO_UID(p_context) != 0)
	    && (FSAL_OP_CONTEXT_TO_UID(p_context) != object_attributes->owner))
	{
		fsal_status = FSAL_test_access_default(p_context, FSAL_W_OK, object_attributes);
		if(FSAL_IS_ERROR(fsal_status))
			Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);
	}

	/* If this point is reached, then access is granted. */
	Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattr_access);
}                               /* FSAL_test_setattr_access */
コード例 #21
0
ファイル: test_fsal.c プロジェクト: MeghanaM/nfs-ganesha
void printattributes(fsal_attrib_list_t attrs)
{

  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_RDATTR_ERR))
    LogTest("FSAL_ATTR_RDATTR_ERR");

  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_TYPE))
    LogTest("Type : %s", strtype(attrs.type));
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_SIZE))
    LogTest("Size : %llu", attrs.filesize);
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_FSID))
    LogTest("fsId : %llu.%llu", attrs.fsid.major, attrs.fsid.minor);
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ACL))
    LogTest("ACL List ...");
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_FILEID))
    LogTest("FileId : %llu", attrs.fileid);
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
    LogTest("Mode : %#o", attrs.mode);
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_NUMLINKS))
    LogTest("Numlinks : %u", (unsigned int)attrs.numlinks);
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER))
    LogTest("uid : %d", attrs.owner);
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_GROUP))
    LogTest("gid : %d", attrs.group);
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_RAWDEV))
    LogTest("Rawdev ...");
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME))
    LogTest("atime : %s", ctime((time_t *) & attrs.atime.seconds));
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_CREATION))
    LogTest("creation time : %s", ctime((time_t *) & attrs.creation.seconds));
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_CTIME))
    LogTest("ctime : %s", ctime((time_t *) & attrs.ctime.seconds));
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME))
    LogTest("mtime : %s", ctime((time_t *) & attrs.mtime.seconds));
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_CHGTIME))
    LogTest("chgtime : %s", ctime((time_t *) & attrs.chgtime.seconds));
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_SPACEUSED))
    LogTest("spaceused : %llu", attrs.spaceused);
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MOUNTFILEID))
    LogTest("mounted_on_fileid : %llu", attrs.mounted_on_fileid);

}
コード例 #22
0
fsal_status_t posix2fsal_attributes(struct stat * p_buffstat,
                                    struct attrlist * p_fsalattr_out)
{
  /* sanity checks */
  if(!p_buffstat || !p_fsalattr_out)
    return fsalstat(ERR_FSAL_FAULT, 0);

  /* Initialize ACL regardless of whether ACL was asked or not.
   * This is needed to make sure ACL attribute is initialized. */
  p_fsalattr_out->acl = NULL;

  /* Fills the output struct */
  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_TYPE))
    {
      p_fsalattr_out->type = posix2fsal_type(p_buffstat->st_mode);
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_SIZE))
    {
      p_fsalattr_out->filesize = p_buffstat->st_size;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_FSID))
    {
      p_fsalattr_out->fsid = posix2fsal_fsid(p_buffstat->st_dev);
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_ACL))
    {
      p_fsalattr_out->acl = NULL;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_FILEID))
    {
      p_fsalattr_out->fileid = (uint64_t) (p_buffstat->st_ino);
    }

  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_MODE))
    {
      p_fsalattr_out->mode = unix2fsal_mode(p_buffstat->st_mode);
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_NUMLINKS))
    {
      p_fsalattr_out->numlinks = p_buffstat->st_nlink;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_OWNER))
    {
      p_fsalattr_out->owner = p_buffstat->st_uid;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_GROUP))
    {
      p_fsalattr_out->group = p_buffstat->st_gid;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_ATIME))
    {
      p_fsalattr_out->atime = p_buffstat->st_atim;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_CTIME))
    {
      p_fsalattr_out->ctime = p_buffstat->st_ctim;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_MTIME))
    {
      p_fsalattr_out->mtime = p_buffstat->st_mtim;
    }
  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_CHGTIME))
    {
      p_fsalattr_out->chgtime =
          (gsh_time_cmp(&p_buffstat->st_mtim,
                        &p_buffstat->st_ctim) > 0) ?
          p_buffstat->st_mtim :
          p_buffstat->st_ctim;
      /* XXX */
      p_fsalattr_out->change = p_fsalattr_out->chgtime.tv_sec +
          p_fsalattr_out->chgtime.tv_nsec;
    }

  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_SPACEUSED))
    {
      p_fsalattr_out->spaceused = p_buffstat->st_blocks * S_BLKSIZE;
    }

  if(FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_RAWDEV))
    {
      p_fsalattr_out->rawdev = posix2fsal_devt(p_buffstat->st_rdev);    /* XXX: convert ? */
    }
  /* mounted_on_fileid :
     if ( FSAL_TEST_MASK(p_fsalattr_out->mask,
     ATTR_MOUNTFILEID )){
     p_fsalattr_out->mounted_on_fileid = 
     hpss2fsal_64( p_hpss_attr_in->FilesetRootId );
     }
   */

  /* everything has been copied ! */

  return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
コード例 #23
0
ファイル: file.c プロジェクト: srimalik/nfs-ganesha
/**
 * @brief Set attributes on an object
 *
 * This function sets attributes on an object.  Which attributes are
 * set is determined by attrib_set->mask. The FSAL must manage bypass
 * or not of share reservations, and a state may be passed.
 *
 * @param[in] obj_hdl    File on which to operate
 * @param[in] state      state_t to use for this operation
 * @param[in] attrib_set Attributes to set
 *
 * @return FSAL status.
 */
fsal_status_t vfs_setattr2(struct fsal_obj_handle *obj_hdl,
			   bool bypass,
			   struct state_t *state,
			   struct attrlist *attrib_set)
{
	struct vfs_fsal_obj_handle *myself;
	fsal_status_t status = {0, 0};
	int retval = 0;
	fsal_openflags_t openflags = FSAL_O_ANY;
	bool has_lock = false;
	bool need_fsync = false;
	bool closefd = false;
	int my_fd;
	const char *func;

	/* apply umask, if mode attribute is to be changed */
	if (FSAL_TEST_MASK(attrib_set->mask, ATTR_MODE))
		attrib_set->mode &=
		    ~op_ctx->fsal_export->exp_ops.fs_umask(op_ctx->fsal_export);

	myself = container_of(obj_hdl, struct vfs_fsal_obj_handle, obj_handle);

	if (obj_hdl->fsal != obj_hdl->fs->fsal) {
		LogDebug(COMPONENT_FSAL,
			 "FSAL %s operation for handle belonging to FSAL %s, return EXDEV",
			 obj_hdl->fsal->name,
			 obj_hdl->fs->fsal != NULL
				? obj_hdl->fs->fsal->name
				: "(none)");
		return fsalstat(posix2fsal_error(EXDEV), EXDEV);
	}

#ifdef ENABLE_VFS_DEBUG_ACL
#ifdef ENABLE_RFC_ACL
	if (FSAL_TEST_MASK(attrib_set->mask, ATTR_MODE) &&
	    !FSAL_TEST_MASK(attrib_set->mask, ATTR_ACL)) {
		/* Set ACL from MODE */
		struct attrlist attrs;

		fsal_prepare_attrs(&attrs, ATTR_ACL);

		status = obj_hdl->obj_ops.getattrs(obj_hdl, &attrs);

		if (FSAL_IS_ERROR(status))
			return status;

		status = fsal_mode_to_acl(attrib_set, attrs.acl);

		/* Done with the attrs */
		fsal_release_attrs(&attrs);
	} else {
		/* If ATTR_ACL is set, mode needs to be adjusted no matter what.
		 * See 7530 s 6.4.1.3 */
		if (!FSAL_TEST_MASK(attrib_set->mask, ATTR_MODE))
			attrib_set->mode = myself->mode;
		status = fsal_acl_to_mode(attrib_set);
	}

	if (FSAL_IS_ERROR(status))
		return status;
#endif /* ENABLE_RFC_ACL */
#endif

	/* This is yet another "you can't get there from here".  If this object
	 * is a socket (AF_UNIX), an fd on the socket s useless _period_.
	 * If it is for a symlink, without O_PATH, you will get an ELOOP error
	 * and (f)chmod doesn't work for a symlink anyway - not that it matters
	 * because access checking is not done on the symlink but the final
	 * target.
	 * AF_UNIX sockets are also ozone material.  If the socket is already
	 * active listeners et al, you can manipulate the mode etc.  If it is
	 * just sitting there as in you made it with a mknod.
	 * (one of those leaky abstractions...)
	 * or the listener forgot to unlink it, it is lame duck.
	 */

	/* Test if size is being set, make sure file is regular and if so,
	 * require a read/write file descriptor.
	 */
	if (FSAL_TEST_MASK(attrib_set->mask, ATTR_SIZE)) {
		if (obj_hdl->type != REGULAR_FILE) {
			LogFullDebug(COMPONENT_FSAL,
				     "Setting size on non-regular file");
			return fsalstat(ERR_FSAL_INVAL, EINVAL);
		}
		openflags = FSAL_O_RDWR;
	}

	/* Get a usable file descriptor. Share conflict is only possible if
	 * size is being set.
	 */
	status = find_fd(&my_fd, obj_hdl, bypass, state, openflags,
			 &has_lock, &need_fsync, &closefd, false);

	if (FSAL_IS_ERROR(status)) {
		if (obj_hdl->type == SYMBOLIC_LINK &&
		    status.major == ERR_FSAL_PERM) {
			/* You cannot open_by_handle (XFS) a symlink and it
			 * throws an EPERM error for it.  open_by_handle_at
			 * does not throw that error for symlinks so we play a
			 * game here.  Since there is not much we can do with
			 * symlinks anyway, say that we did it
			 * but don't actually do anything.
			 * If you *really* want to tweek things
			 * like owners, get a modern linux kernel...
			 */
			status = fsalstat(ERR_FSAL_NO_ERROR, 0);
		}
		LogFullDebug(COMPONENT_FSAL,
			     "find_fd status=%s",
			     fsal_err_txt(status));
		goto out;
	}

	/** TRUNCATE **/
	if (FSAL_TEST_MASK(attrib_set->mask, ATTR_SIZE)) {
		retval = ftruncate(my_fd, attrib_set->filesize);
		if (retval != 0) {
			/** @todo FSF: is this still necessary?
			 *
			 * XXX ESXi volume creation pattern reliably
			 * reached this point in the past, however now that we
			 * only use the already open file descriptor if it is
			 * open read/write, this may no longer fail.
			 * If there is some other error from ftruncate, then
			 * we will needlessly retry, but without more detail
			 * of the original failure, we can't be sure.
			 * Fortunately permission checking is done by
			 * Ganesha before calling here, so we won't get an
			 * EACCES since this call is done as root. We could
			 * get EFBIG, EPERM, or EINVAL.
			 */
			/** @todo FSF: re-open if we really still need this
			 */

			retval = ftruncate(my_fd, attrib_set->filesize);
			if (retval != 0) {
				func = "truncate";
				goto fileerr;
			}
		}
	}

	/** CHMOD **/
	if (FSAL_TEST_MASK(attrib_set->mask, ATTR_MODE)) {
		/* The POSIX chmod call doesn't affect the symlink object, but
		 * the entry it points to. So we must ignore it.
		 */
		if (obj_hdl->type != SYMBOLIC_LINK) {
			if (vfs_unopenable_type(obj_hdl->type))
				retval = fchmodat(
					my_fd,
					myself->u.unopenable.name,
					fsal2unix_mode(attrib_set->mode),
					0);
			else
				retval = fchmod(
					my_fd,
					fsal2unix_mode(attrib_set->mode));

			if (retval != 0) {
				func = "chmod";
				goto fileerr;
			}
		}
	}

	/**  CHOWN  **/
	if (FSAL_TEST_MASK(attrib_set->mask, ATTR_OWNER | ATTR_GROUP)) {
		uid_t user = FSAL_TEST_MASK(attrib_set->mask, ATTR_OWNER)
		    ? (int)attrib_set->owner : -1;
		gid_t group = FSAL_TEST_MASK(attrib_set->mask, ATTR_GROUP)
		    ? (int)attrib_set->group : -1;

		if (vfs_unopenable_type(obj_hdl->type))
			retval = fchownat(my_fd, myself->u.unopenable.name,
					  user, group, AT_SYMLINK_NOFOLLOW);
		else if (obj_hdl->type == SYMBOLIC_LINK)
			retval = fchownat(my_fd, "", user, group,
					  AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH);
		else
			retval = fchown(my_fd, user, group);

		if (retval) {
			func = "chown";
			goto fileerr;
		}
	}

	/**  UTIME  **/
	if (FSAL_TEST_MASK(attrib_set->mask, ATTRS_SET_TIME)) {
		struct timespec timebuf[2];

		if (obj_hdl->type == SYMBOLIC_LINK)
			goto out; /* Setting time on symlinks is illegal */
		/* Atime */
		if (FSAL_TEST_MASK(attrib_set->mask, ATTR_ATIME_SERVER)) {
			timebuf[0].tv_sec = 0;
			timebuf[0].tv_nsec = UTIME_NOW;
		} else if (FSAL_TEST_MASK(attrib_set->mask, ATTR_ATIME)) {
			timebuf[0] = attrib_set->atime;
		} else {
			timebuf[0].tv_sec = 0;
			timebuf[0].tv_nsec = UTIME_OMIT;
		}

		/* Mtime */
		if (FSAL_TEST_MASK(attrib_set->mask, ATTR_MTIME_SERVER)) {
			timebuf[1].tv_sec = 0;
			timebuf[1].tv_nsec = UTIME_NOW;
		} else if (FSAL_TEST_MASK(attrib_set->mask, ATTR_MTIME)) {
			timebuf[1] = attrib_set->mtime;
		} else {
			timebuf[1].tv_sec = 0;
			timebuf[1].tv_nsec = UTIME_OMIT;
		}
		if (vfs_unopenable_type(obj_hdl->type))
			retval = vfs_utimesat(my_fd, myself->u.unopenable.name,
					      timebuf, AT_SYMLINK_NOFOLLOW);
		else
			retval = vfs_utimes(my_fd, timebuf);
		if (retval != 0) {
			func = "utimes";
			goto fileerr;
		}
	}

	/** SUBFSAL **/
	if (myself->sub_ops && myself->sub_ops->setattrs) {
		status = myself->sub_ops->setattrs(
					myself,
					my_fd,
					attrib_set->mask, attrib_set);
		if (FSAL_IS_ERROR(status))
			goto out;
	}

	errno = 0;

 fileerr:

	retval = errno;

	if (retval != 0) {
		LogDebug(COMPONENT_FSAL,
			 "%s returned %s",
			 func, strerror(retval));
	}

	status = fsalstat(posix2fsal_error(retval), retval);

 out:

	if (closefd)
		close(my_fd);

	if (has_lock)
		PTHREAD_RWLOCK_unlock(&obj_hdl->lock);

	return status;
}
コード例 #24
0
/**
 *
 * @brief Gets an entry by using its fsdata as a key and caches it if needed.
 *
 * Gets an entry by using its fsdata as a key and caches it if needed.
 *
 * If a cache entry is returned, its refcount is incremented by one.
 *
 * It turns out we do need cache_inode_get_located functionality for
 * cases like lookupp on an entry returning itself when it isn't a
 * root.  Therefore, if the 'associated' parameter is equal to the got
 * cache entry, a reference count is incremented but the structure
 * pointed to by attr is NOT filled in.
 *
 * @param[in]     fsdata     File system data
 * @param[out]    attr       The attributes of the got entry
 * @param[in]     context    FSAL credentials
 * @param[in]     associated Entry that may be equal to the got entry
 * @param[out]    status     Returned status
 *
 * @return If successful, the pointer to the entry; NULL otherwise
 *
 */
cache_entry_t *
cache_inode_get(cache_inode_fsal_data_t *fsdata,
                fsal_attrib_list_t *attr,
                fsal_op_context_t *context,
                cache_entry_t *associated,
                cache_inode_status_t *status)
{
    hash_buffer_t key, value;
    cache_entry_t *entry = NULL;
    fsal_status_t fsal_status = {0, 0};
    cache_inode_create_arg_t create_arg = {
        .newly_created_dir = FALSE
    };
    cache_inode_file_type_t type = UNASSIGNED;
    hash_error_t hrc = 0;
    fsal_attrib_list_t fsal_attributes;
    fsal_handle_t *file_handle;
    struct hash_latch latch;

    /* Set the return default to CACHE_INODE_SUCCESS */
    *status = CACHE_INODE_SUCCESS;

    /* Turn the input to a hash key on our own.
     */
    key.pdata = fsdata->fh_desc.start;
    key.len = fsdata->fh_desc.len;

    hrc = HashTable_GetLatch(fh_to_cache_entry_ht, &key, &value,
                             FALSE,
                             &latch);

    if ((hrc != HASHTABLE_SUCCESS) &&
            (hrc != HASHTABLE_ERROR_NO_SUCH_KEY)) {
        /* This should not happened */
        *status = CACHE_INODE_HASH_TABLE_ERROR;
        LogCrit(COMPONENT_CACHE_INODE,
                "Hash access failed with code %d"
                " - this should not have happened",
                hrc);
        return NULL;
    }

    if (hrc == HASHTABLE_SUCCESS) {
        /* Entry exists in the cache and was found */
        entry = value.pdata;
        /* take an extra reference within the critical section */
        if (cache_inode_lru_ref(entry, LRU_REQ_INITIAL) !=
                CACHE_INODE_SUCCESS) {
            /* Dead entry.  Treat like a lookup failure. */
            entry = NULL;
        } else {
            if (entry == associated) {
                /* Take a quick exit so we don't invert lock
                   ordering. */
                HashTable_ReleaseLatched(fh_to_cache_entry_ht, &latch);
                return entry;
            }
        }
    }
    HashTable_ReleaseLatched(fh_to_cache_entry_ht, &latch);

    if (!context) {
        /* Upcalls have no access to fsal_op_context_t,
           so just return the entry without revalidating it or
           creating a new one. */
        if (entry == NULL) {
            *status = CACHE_INODE_NOT_FOUND;
        }
        return entry;
    }

    if (!entry) {
        /* Cache miss, allocate a new entry */
        file_handle = (fsal_handle_t *) fsdata->fh_desc.start;
        /* First, call FSAL to know what the object is */
        fsal_attributes.asked_attributes = cache_inode_params.attrmask;
        fsal_status
            = FSAL_getattrs(file_handle, context, &fsal_attributes);
        if (FSAL_IS_ERROR(fsal_status)) {
            *status = cache_inode_error_convert(fsal_status);
            LogDebug(COMPONENT_CACHE_INODE,
                     "cache_inode_get: cache_inode_status=%u "
                     "fsal_status=%u,%u ", *status,
                     fsal_status.major,
                     fsal_status.minor);
            return NULL;
        }

        /* The type has to be set in the attributes */
        if (!FSAL_TEST_MASK(fsal_attributes.supported_attributes,
                            FSAL_ATTR_TYPE)) {
            *status = CACHE_INODE_FSAL_ERROR;
            return NULL;
        }

        /* Get the cache_inode file type */
        type = cache_inode_fsal_type_convert(fsal_attributes.type);
        if (type == SYMBOLIC_LINK) {
            fsal_attributes.asked_attributes = cache_inode_params.attrmask;
            fsal_status =
                FSAL_readlink(file_handle, context,
                              &create_arg.link_content,
                              &fsal_attributes);

            if (FSAL_IS_ERROR(fsal_status)) {
                *status = cache_inode_error_convert(fsal_status);
                return NULL;
            }
        }
        if ((entry
                = cache_inode_new_entry(fsdata,
                                        &fsal_attributes,
                                        type,
                                        &create_arg,
                                        status)) == NULL) {
            return NULL;
        }

    }

    *status = CACHE_INODE_SUCCESS;

    /* This is the replacement for cache_inode_renew_entry.  Rather
       than calling that function at the start of every cache_inode
       call with the inode locked, we call cache_inode_check trust to
       perform 'heavyweight' (timed expiration of cached attributes,
       getattr-based directory trust) checks the first time after
       getting an inode.  It does all of the checks read-locked and
       only acquires a write lock if there's something requiring a
       change.

       There is a second light-weight check done before use of cached
       data that checks whether the bits saying that inode attributes
       or inode content are trustworthy have been cleared by, for
       example, FSAL_CB.

       To summarize, the current implementation is that policy-based
       trust of validity is checked once per logical series of
       operations at cache_inode_get, and asynchronous trust is
       checked with use (when the attributes are locked for reading,
       for example.) */

    if ((*status = cache_inode_check_trust(entry,
                                           context))
            != CACHE_INODE_SUCCESS) {
        goto out_put;
    }

    /* Set the returned attributes */
    *status = cache_inode_lock_trust_attrs(entry, context);

    /* cache_inode_lock_trust_attrs may fail, in that case, the
       attributes are wrong and pthread_rwlock_unlock can't be called
       again */
    if(*status != CACHE_INODE_SUCCESS)
    {
        goto out_put;
    }
    *attr = entry->attributes;
    pthread_rwlock_unlock(&entry->attr_lock);

    return entry;

out_put:
    cache_inode_put(entry);
    entry = NULL;
    return entry;
} /* cache_inode_get */
コード例 #25
0
ファイル: nfs_creds.c プロジェクト: srimalik/nfs-ganesha
fsal_errors_t nfs_access_op(struct fsal_obj_handle *obj,
				   uint32_t requested_access,
				   uint32_t *granted_access,
				   uint32_t *supported_access)
{
	fsal_status_t fsal_status;
	fsal_accessflags_t access_mask;
	fsal_accessflags_t access_allowed;
	fsal_accessflags_t access_denied;
	uint32_t granted_mask = requested_access;

	access_mask = 0;
	*granted_access = 0;

	LogDebugAlt(COMPONENT_NFSPROTO, COMPONENT_NFS_V4_ACL,
		    "Requested ACCESS=%s,%s,%s,%s,%s,%s",
		    FSAL_TEST_MASK(requested_access,
				   ACCESS3_READ) ? "READ" : "-",
		    FSAL_TEST_MASK(requested_access,
				   ACCESS3_LOOKUP) ? "LOOKUP" : "-",
		    FSAL_TEST_MASK(requested_access,
				   ACCESS3_MODIFY) ? "MODIFY" : "-",
		    FSAL_TEST_MASK(requested_access,
				   ACCESS3_EXTEND) ? "EXTEND" : "-",
		    FSAL_TEST_MASK(requested_access,
				   ACCESS3_DELETE) ? "DELETE" : "-",
		    FSAL_TEST_MASK(requested_access,
				   ACCESS3_EXECUTE) ? "EXECUTE" : "-");

	/* Set mode for read.
	 * NOTE: FSAL_ACE_PERM_LIST_DIR and FSAL_ACE_PERM_READ_DATA have
	 *       the same bit value so we don't bother looking at file type.
	 */
	if (requested_access & ACCESS3_READ)
		access_mask |= FSAL_R_OK | FSAL_ACE_PERM_READ_DATA;

	if (requested_access & ACCESS3_LOOKUP) {
		if (obj->type == DIRECTORY)
			access_mask |= FSAL_X_OK | FSAL_ACE_PERM_EXECUTE;
		else
			granted_mask &= ~ACCESS3_LOOKUP;
	}

	if (requested_access & ACCESS3_MODIFY) {
		if (obj->type == DIRECTORY)
			access_mask |= FSAL_W_OK | FSAL_ACE_PERM_DELETE_CHILD;
		else
			access_mask |= FSAL_W_OK | FSAL_ACE_PERM_WRITE_DATA;
	}

	if (requested_access & ACCESS3_EXTEND) {
		if (obj->type == DIRECTORY)
			access_mask |=
			    FSAL_W_OK | FSAL_ACE_PERM_ADD_FILE |
			    FSAL_ACE_PERM_ADD_SUBDIRECTORY;
		else
			access_mask |= FSAL_W_OK | FSAL_ACE_PERM_APPEND_DATA;
	}

	if (requested_access & ACCESS3_DELETE) {
		if (obj->type == DIRECTORY)
			access_mask |= FSAL_W_OK | FSAL_ACE_PERM_DELETE_CHILD;
		else
			granted_mask &= ~ACCESS3_DELETE;
	}

	if (requested_access & ACCESS3_EXECUTE) {
		if (obj->type != DIRECTORY)
			access_mask |= FSAL_X_OK | FSAL_ACE_PERM_EXECUTE;
		else
			granted_mask &= ~ACCESS3_EXECUTE;
	}

	if (access_mask != 0)
		access_mask |=
		    FSAL_MODE_MASK_FLAG | FSAL_ACE4_MASK_FLAG |
		    FSAL_ACE4_PERM_CONTINUE;

	LogDebugAlt(COMPONENT_NFSPROTO, COMPONENT_NFS_V4_ACL,
		    "access_mask = mode(%c%c%c) ACL(%s,%s,%s,%s,%s)",
		    FSAL_TEST_MASK(access_mask, FSAL_R_OK) ? 'r' : '-',
		    FSAL_TEST_MASK(access_mask, FSAL_W_OK) ? 'w' : '-',
		    FSAL_TEST_MASK(access_mask, FSAL_X_OK) ? 'x' : '-',
		    FSAL_TEST_MASK(access_mask, FSAL_ACE_PERM_READ_DATA) ?
			obj->type == DIRECTORY ?
			"list_dir" : "read_data" : "-",
		    FSAL_TEST_MASK(access_mask,
				   FSAL_ACE_PERM_WRITE_DATA) ?
			obj->type == DIRECTORY ?
			"add_file" : "write_data" : "-",
		    FSAL_TEST_MASK(access_mask, FSAL_ACE_PERM_EXECUTE) ?
			"execute" : "-",
		    FSAL_TEST_MASK(access_mask,
				   FSAL_ACE_PERM_ADD_SUBDIRECTORY) ?
			"add_subdirectory" : "-",
		    FSAL_TEST_MASK(access_mask, FSAL_ACE_PERM_DELETE_CHILD) ?
			"delete_child" : "-");

	fsal_status = obj->obj_ops.test_access(obj, access_mask,
					       &access_allowed,
					       &access_denied, false);
	if (fsal_status.major == ERR_FSAL_NO_ERROR ||
	    fsal_status.major == ERR_FSAL_ACCESS) {
		/* Define granted access based on granted mode bits. */
		if (access_allowed & FSAL_R_OK)
			*granted_access |= ACCESS3_READ;

		if (access_allowed & FSAL_W_OK)
			*granted_access |=
			    ACCESS3_MODIFY | ACCESS3_EXTEND | ACCESS3_DELETE;

		if (access_allowed & FSAL_X_OK)
			*granted_access |= ACCESS3_LOOKUP | ACCESS3_EXECUTE;

		/* Define granted access based on granted ACL bits. */
		if (access_allowed & FSAL_ACE_PERM_READ_DATA)
			*granted_access |= ACCESS3_READ;

		if (obj->type == DIRECTORY) {
			if (access_allowed & FSAL_ACE_PERM_DELETE_CHILD)
				*granted_access |=
				    ACCESS3_MODIFY | ACCESS3_DELETE;

			if (access_allowed & FSAL_ACE_PERM_ADD_FILE)
				*granted_access |= ACCESS3_EXTEND;

			if (access_allowed & FSAL_ACE_PERM_ADD_SUBDIRECTORY)
				*granted_access |= ACCESS3_EXTEND;
		} else {
			if (access_allowed & FSAL_ACE_PERM_WRITE_DATA)
				*granted_access |= ACCESS3_MODIFY;

			if (access_allowed & FSAL_ACE_PERM_APPEND_DATA)
				*granted_access |= ACCESS3_EXTEND;
		}

		if (access_allowed & FSAL_ACE_PERM_EXECUTE)
			*granted_access |= ACCESS3_LOOKUP | ACCESS3_EXECUTE;

		/* Don't allow any bits that weren't set on request or
		 * allowed by the file type.
		 */
		*granted_access &= granted_mask;

		if (supported_access != NULL)
			*supported_access = granted_mask;

		LogDebugAlt(COMPONENT_NFSPROTO, COMPONENT_NFS_V4_ACL,
			    "Supported ACCESS=%s,%s,%s,%s,%s,%s",
			    FSAL_TEST_MASK(granted_mask,
					   ACCESS3_READ) ? "READ" : "-",
			    FSAL_TEST_MASK(granted_mask,
					   ACCESS3_LOOKUP) ? "LOOKUP" : "-",
			    FSAL_TEST_MASK(granted_mask,
					   ACCESS3_MODIFY) ? "MODIFY" : "-",
			    FSAL_TEST_MASK(granted_mask,
					   ACCESS3_EXTEND) ? "EXTEND" : "-",
			    FSAL_TEST_MASK(granted_mask,
					   ACCESS3_DELETE) ? "DELETE" : "-",
			    FSAL_TEST_MASK(granted_mask,
					   ACCESS3_EXECUTE) ? "EXECUTE" : "-");

		LogDebugAlt(COMPONENT_NFSPROTO, COMPONENT_NFS_V4_ACL,
			    "Granted ACCESS=%s,%s,%s,%s,%s,%s",
			    FSAL_TEST_MASK(*granted_access,
					   ACCESS3_READ) ? "READ" : "-",
			    FSAL_TEST_MASK(*granted_access,
					   ACCESS3_LOOKUP) ? "LOOKUP" : "-",
			    FSAL_TEST_MASK(*granted_access,
					   ACCESS3_MODIFY) ? "MODIFY" : "-",
			    FSAL_TEST_MASK(*granted_access,
					   ACCESS3_EXTEND) ? "EXTEND" : "-",
			    FSAL_TEST_MASK(*granted_access,
					   ACCESS3_DELETE) ? "DELETE" : "-",
			    FSAL_TEST_MASK(*granted_access,
					   ACCESS3_EXECUTE) ? "EXECUTE" : "-");
	}

	return fsal_status.major;
}
コード例 #26
0
ファイル: nfs4_op_open.c プロジェクト: dotbugfix/nfs-ganesha
static void open4_ex(OPEN4args *arg,
		     compound_data_t *data,
		     OPEN4res *res_OPEN4,
		     nfs_client_id_t *clientid,
		     state_owner_t *owner,
		     state_t **file_state,
		     bool *new_state)
{
	/* Parent directory in which to open the file. */
	struct fsal_obj_handle *parent = NULL;
	/* The entry we associated with the desired file before open. */
	struct fsal_obj_handle *file_obj = NULL;
	/* Indicator that file_obj came from lookup. */
	bool looked_up_file_obj = false;
	/* The in_obj to pass to fsal_open2. */
	struct fsal_obj_handle *in_obj = NULL;
	/* The entry open associated with the file. */
	struct fsal_obj_handle *out_obj = NULL;
	fsal_openflags_t openflags = 0;
	fsal_openflags_t old_openflags = 0;
	enum fsal_create_mode createmode = FSAL_NO_CREATE;
	/* The filename to create */
	char *filename = NULL;
	/* The supplied calim type */
	open_claim_type4 claim = arg->claim.claim;
	fsal_verifier_t verifier;
	struct attrlist sattr;
	/* Status for fsal calls */
	fsal_status_t status = {0, 0};
	/* The open state for the file */
	bool state_lock_held = false;

	/* Make sure the attributes are initialized */
	memset(&sattr, 0, sizeof(sattr));

	/* Make sure... */
	*file_state = NULL;
	*new_state = false;

	/* Pre-process the claim type */
	switch (claim) {
	case CLAIM_NULL:
		/* Check parent */
		parent = data->current_obj;
		in_obj = parent;

		/* Parent must be a directory */
		if (parent->type != DIRECTORY) {
			if (parent->type == SYMBOLIC_LINK) {
				res_OPEN4->status = NFS4ERR_SYMLINK;
				goto out;
			} else {
				res_OPEN4->status = NFS4ERR_NOTDIR;
				goto out;
			}
		}

		/* Validate and convert the utf8 filename */
		res_OPEN4->status =
		    nfs4_utf8string2dynamic(&arg->claim.open_claim4_u.file,
					    UTF8_SCAN_ALL, &filename);

		if (res_OPEN4->status != NFS4_OK)
			goto out;

		/* Set the createmode if appropriate) */
		if (arg->openhow.opentype == OPEN4_CREATE) {
			open4_ex_create_args(arg, data, res_OPEN4, verifier,
					     &createmode, &sattr);

			if (res_OPEN4->status != NFS4_OK)
				goto out;
		}

		status = fsal_lookup(parent, filename, &file_obj, NULL);

		if (!FSAL_IS_ERROR(status)) {
			/* Check create situations. */
			if (arg->openhow.opentype == OPEN4_CREATE) {
				if (createmode >= FSAL_EXCLUSIVE) {
					/* Could be a replay, need to continue.
					 */
					LogFullDebug(COMPONENT_STATE,
						     "EXCLUSIVE open with existing file %s",
						     filename);
				} else if (createmode == FSAL_GUARDED) {
					/* This will be a failure no matter'
					 * what.
					 */
					looked_up_file_obj = true;
					res_OPEN4->status = NFS4ERR_EXIST;
					goto out;
				} else {
					/* FSAL_UNCHECKED, may be a truncate
					 * and we need to pass in the case
					 * of fsal_reopen2 case.
					 */
					if (FSAL_TEST_MASK(sattr.valid_mask,
							   ATTR_SIZE) &&
					    sattr.filesize == 0) {
						LogFullDebug(COMPONENT_STATE,
							     "Truncate");
						openflags |= FSAL_O_TRUNC;
					}
				}
			}

			/* We found the file by lookup, discard the filename
			 * and remember that we found the entry by lookup.
			 */
			looked_up_file_obj = true;
			gsh_free(filename);
			filename = NULL;
		} else if (status.major != ERR_FSAL_NOENT ||
			   arg->openhow.opentype != OPEN4_CREATE) {
			/* A real error occurred */
			res_OPEN4->status = nfs4_Errno_status(status);
			goto out;
		}

		break;

		/* Both of these just use the current filehandle. */
	case CLAIM_PREVIOUS:
		owner->so_owner.so_nfs4_owner.so_confirmed = true;
		if (!nfs4_check_deleg_reclaim(clientid, &data->currentFH)) {
			/* It must have been revoked. Can't reclaim.*/
			LogInfo(COMPONENT_NFS_V4, "Can't reclaim delegation");
			res_OPEN4->status = NFS4ERR_RECLAIM_BAD;
			goto out;
		}
		openflags |= FSAL_O_RECLAIM;
		file_obj = data->current_obj;
		break;

	case CLAIM_FH:
		file_obj = data->current_obj;
		break;

	case CLAIM_DELEGATE_PREV:
		/* FIXME: Remove this when we have full support
		 * for CLAIM_DELEGATE_PREV and delegpurge operations
		 */
		res_OPEN4->status = NFS4ERR_NOTSUPP;
		goto out;

	case CLAIM_DELEGATE_CUR:
		res_OPEN4->status = open4_claim_deleg(arg, data);
		if (res_OPEN4->status != NFS4_OK)
			goto out;
		openflags |= FSAL_O_RECLAIM;
		file_obj = data->current_obj;
		break;

	default:
		LogFatal(COMPONENT_STATE,
			 "Programming error.  Invalid claim after check.");
	}

	if ((arg->share_access & OPEN4_SHARE_ACCESS_READ) != 0)
		openflags |= FSAL_O_READ;

	if ((arg->share_access & OPEN4_SHARE_ACCESS_WRITE) != 0)
		openflags |= FSAL_O_WRITE;

	if ((arg->share_deny & OPEN4_SHARE_DENY_READ) != 0)
		openflags |= FSAL_O_DENY_READ;

	if ((arg->share_deny & OPEN4_SHARE_DENY_WRITE) != 0)
		openflags |= FSAL_O_DENY_WRITE_MAND;

	/* Check if file_obj a REGULAR_FILE */
	if (file_obj != NULL && file_obj->type != REGULAR_FILE) {
		LogDebug(COMPONENT_NFS_V4,
			 "Wrong file type expected REGULAR_FILE actual %s",
			 object_file_type_to_str(file_obj->type));

		if (file_obj->type == DIRECTORY) {
			res_OPEN4->status = NFS4ERR_ISDIR;
		} else {
			/* All special nodes must return NFS4ERR_SYMLINK for
			 * proper client behavior per this linux-nfs post:
			 * http://marc.info/?l=linux-nfs&m=131342421825436&w=2
			 */
			res_OPEN4->status = NFS4ERR_SYMLINK;
		}

		goto out;
	}

	if (file_obj != NULL) {
		/* Go ahead and take the state lock now. */
		PTHREAD_RWLOCK_wrlock(&file_obj->state_hdl->state_lock);
		state_lock_held = true;
		in_obj = file_obj;

		/* Check if any existing delegations conflict with this open.
		 * Delegation recalls will be scheduled if there is a conflict.
		 */
		if (state_deleg_conflict(file_obj,
					  (arg->share_access &
					   OPEN4_SHARE_ACCESS_WRITE) != 0)) {
			res_OPEN4->status = NFS4ERR_DELAY;
			goto out;
		}

		/* Check if there is already a state for this entry and owner.
		 */
		*file_state = nfs4_State_Get_Obj(file_obj, owner);

		if (isFullDebug(COMPONENT_STATE) && *file_state != NULL) {
			char str[LOG_BUFF_LEN] = "\0";
			struct display_buffer dspbuf = {sizeof(str), str, str};

			display_stateid(&dspbuf, *file_state);

			LogFullDebug(COMPONENT_STATE,
				     "Found existing state %s",
				     str);
		}

		/* Check if open from another export */
		if (*file_state != NULL &&
		    !state_same_export(*file_state, op_ctx->ctx_export)) {
			LogEvent(COMPONENT_STATE,
				 "Lock Owner Export Conflict, Lock held for export %"
				 PRIu16" request for export %"PRIu16,
				 state_export_id(*file_state),
				 op_ctx->ctx_export->export_id);
			res_OPEN4->status = NFS4ERR_INVAL;
			goto out;
		}
	}

	/* If that did not succeed, allocate a state from the FSAL. */
	if (*file_state == NULL) {
		*file_state = op_ctx->fsal_export->exp_ops.alloc_state(
							op_ctx->fsal_export,
							STATE_TYPE_SHARE,
							NULL);

		/* Remember we allocated a new state */
		*new_state = true;

		/* We are ready to perform the open (with possible create).
		 * in_obj has been set to the file itself or the parent.
		 * filename is NULL if in_obj is the file itself.
		 *
		 * Permission check has been done on directory if appropriate,
		 * otherwise fsal_open2 will do a directory permission
		 * check.
		 *
		 * fsal_open2 handles the permission check on the file
		 * itself and also handles all the share reservation stuff.
		 *
		 * fsal_open2 returns with a ref on out_obj, which should be
		 * passed to the state.
		 */
		LogFullDebug(COMPONENT_STATE,
			     "Calling open2 for %s", filename);

		status = fsal_open2(in_obj,
				    *file_state,
				    openflags,
				    createmode,
				    filename,
				    &sattr,
				    verifier,
				    &out_obj,
				    NULL);

		if (FSAL_IS_ERROR(status)) {
			res_OPEN4->status = nfs4_Errno_status(status);
			goto out;
		}
	} else if (createmode >= FSAL_EXCLUSIVE) {
		/* We have an EXCLUSIVE create with an existing
		 * state. We still need to verify it, but no need
		 * to call reopen2.
		 */
		LogFullDebug(COMPONENT_STATE, "Calling verify2 ");

		status = fsal_verify2(file_obj, verifier);

		if (FSAL_IS_ERROR(status)) {
			res_OPEN4->status = nfs4_Errno_status(status);
			goto out;
		}

		/* We need an extra reference below. */
		file_obj->obj_ops->get_ref(file_obj);
	} else {
		old_openflags =
			file_obj->obj_ops->status2(file_obj, *file_state);

		/* Open upgrade */
		LogFullDebug(COMPONENT_STATE, "Calling reopen2");

		status = fsal_reopen2(file_obj, *file_state,
				      openflags | old_openflags,
				      false);

		if (FSAL_IS_ERROR(status)) {
			res_OPEN4->status = nfs4_Errno_status(status);
			goto out;
		}

		/* We need an extra reference below. */
		file_obj->obj_ops->get_ref(file_obj);
	}

	if (file_obj == NULL) {
		/* We have a new cache inode entry, take the state lock. */
		file_obj = out_obj;
		PTHREAD_RWLOCK_wrlock(&file_obj->state_hdl->state_lock);
		state_lock_held = true;
	}

	/* Now the state_lock is held for sure and we have an extra LRU
	 * reference to file_obj, which is the opened file.
	 */

	if (*new_state) {
		/* The state data to be added */
		union state_data candidate_data;
		/* Tracking data for the open state */
		struct state_refer refer, *p_refer = NULL;
		state_status_t state_status;

		candidate_data.share.share_access =
		    arg->share_access & OPEN4_SHARE_ACCESS_BOTH;
		candidate_data.share.share_deny = arg->share_deny;
		candidate_data.share.share_access_prev =
			(1 << candidate_data.share.share_access);
		candidate_data.share.share_deny_prev =
			(1 << candidate_data.share.share_deny);

		LogFullDebug(COMPONENT_STATE,
			     "Creating new state access=%x deny=%x access_prev=%x deny_prev=%x",
			     candidate_data.share.share_access,
			     candidate_data.share.share_deny,
			     candidate_data.share.share_access_prev,
			     candidate_data.share.share_deny_prev);

		/* Record the sequence info */
		if (data->minorversion > 0) {
			memcpy(refer.session,
			       data->session->session_id,
			       sizeof(sessionid4));
			refer.sequence = data->sequence;
			refer.slot = data->slot;
			p_refer = &refer;
		}

		/* We need to register this state now. */
		state_status = state_add_impl(file_obj,
					      STATE_TYPE_SHARE,
					      &candidate_data,
					      owner,
					      file_state,
					      p_refer);

		if (state_status != STATE_SUCCESS) {
			/* state_add_impl failure closed and freed state.
			 * file_state will also be NULL at this point. Also
			 * release the ref on file_obj, since the state add
			 * failed.
			 */
			file_obj->obj_ops->put_ref(file_obj);
			res_OPEN4->status = nfs4_Errno_state(state_status);
			*new_state = false;
			goto out;
		}

		glist_init(&(*file_state)->state_data.share.share_lockstates);
	}

	res_OPEN4->status = open4_create_fh(data, file_obj, true);

	if (res_OPEN4->status != NFS4_OK) {
		if (*new_state) {
			/* state_del_locked will close the file. */
			state_del_locked(*file_state);
			*file_state = NULL;
			*new_state = false;
		} else {
			/*Do an open downgrade to the old open flags */
			status = file_obj->obj_ops->reopen2(file_obj,
							   *file_state,
							   old_openflags);
			if (FSAL_IS_ERROR(status)) {
				LogCrit(COMPONENT_NFS_V4,
					"Failed to allocate handle, reopen2 failed with %s",
					fsal_err_txt(status));
			}

			/* Need to release the state_lock before the put_ref
			 * call.
			 */
			PTHREAD_RWLOCK_unlock(&file_obj->state_hdl->state_lock);
			state_lock_held = false;

			/* Release the extra LRU reference on file_obj. */
			file_obj->obj_ops->put_ref(file_obj);
			goto out;
		}
	}

	/* Since open4_create_fh succeeded the LRU reference to file_obj was
	 * consumed by data->current_obj.
	 */

	if (!(*new_state)) {
		LogFullDebug(COMPONENT_STATE,
			     "Open upgrade old access=%x deny=%x access_prev=%x deny_prev=%x",
			     (*file_state)->state_data.share.share_access,
			     (*file_state)->state_data.share.share_deny,
			     (*file_state)->state_data.share.share_access_prev,
			     (*file_state)->state_data.share.share_deny_prev);

		LogFullDebug(COMPONENT_STATE,
			     "Open upgrade to access=%x deny=%x",
			     arg->share_access,
			     arg->share_deny);

		/* Update share_access and share_deny */
		(*file_state)->state_data.share.share_access |=
			arg->share_access & OPEN4_SHARE_ACCESS_BOTH;

		(*file_state)->state_data.share.share_deny |=
			arg->share_deny;

		/* Update share_access_prev and share_deny_prev */
		(*file_state)->state_data.share.share_access_prev |=
			(1 << (arg->share_access & OPEN4_SHARE_ACCESS_BOTH));

		(*file_state)->state_data.share.share_deny_prev |=
			(1 << arg->share_deny);

		LogFullDebug(COMPONENT_STATE,
			     "Open upgrade new access=%x deny=%x access_prev=%x deny_prev=%x",
			     (*file_state)->state_data.share.share_access,
			     (*file_state)->state_data.share.share_deny,
			     (*file_state)->state_data.share.share_access_prev,
			     (*file_state)->state_data.share.share_deny_prev);
	}

	do_delegation(arg, res_OPEN4, data, owner, *file_state, clientid);
 out:

	/* Release the attributes (may release an inherited ACL) */
	fsal_release_attrs(&sattr);

	if (state_lock_held)
		PTHREAD_RWLOCK_unlock(&file_obj->state_hdl->state_lock);

	if (filename)
		gsh_free(filename);

	if (res_OPEN4->status != NFS4_OK) {
		/* Cleanup state on error */
		if (*new_state)
			(*file_state)
				->state_exp->exp_ops.free_state(
					(*file_state)->state_exp, *file_state);
		else if (*file_state != NULL)
			dec_state_t_ref(*file_state);
		*file_state = NULL;
	}

	if (looked_up_file_obj) {
		/* We got file_obj via lookup, we need to unref it. */
		file_obj->obj_ops->put_ref(file_obj);
	}
}
コード例 #27
0
ファイル: nfs4_op_setattr.c プロジェクト: JevonQ/nfs-ganesha
int nfs4_op_setattr(struct nfs_argop4 *op, compound_data_t *data,
		    struct nfs_resop4 *resp)
{
	SETATTR4args * const arg_SETATTR4 = &op->nfs_argop4_u.opsetattr;
	SETATTR4res * const res_SETATTR4 = &resp->nfs_resop4_u.opsetattr;
	struct attrlist sattr;
	cache_inode_status_t cache_status = CACHE_INODE_SUCCESS;
	const char *tag = "SETATTR";
	state_t *state_found = NULL;
	state_t *state_open = NULL;
	cache_entry_t *entry = NULL;
	bool anonymous_started = false;

	resp->resop = NFS4_OP_SETATTR;
	res_SETATTR4->status = NFS4_OK;

	/* Do basic checks on a filehandle */
	res_SETATTR4->status = nfs4_sanity_check_FH(data, NO_FILE_TYPE, false);

	if (res_SETATTR4->status != NFS4_OK)
		return res_SETATTR4->status;

	/* Don't allow attribute change while we are in grace period.
	 * Required for delegation reclaims and may be needed for other
	 * reclaimable states as well.
	 */
	if (nfs_in_grace()) {
		res_SETATTR4->status = NFS4ERR_GRACE;
		return res_SETATTR4->status;
	}

	/* Get only attributes that are allowed to be read */
	if (!nfs4_Fattr_Check_Access
	    (&arg_SETATTR4->obj_attributes, FATTR4_ATTR_WRITE)) {
		res_SETATTR4->status = NFS4ERR_INVAL;
		return res_SETATTR4->status;
	}

	/* Ask only for supported attributes */
	if (!nfs4_Fattr_Supported(&arg_SETATTR4->obj_attributes)) {
		res_SETATTR4->status = NFS4ERR_ATTRNOTSUPP;
		return res_SETATTR4->status;
	}

	/* Convert the fattr4 in the request to a fsal sattr structure */
	res_SETATTR4->status =
		nfs4_Fattr_To_FSAL_attr(&sattr,
					&arg_SETATTR4->obj_attributes,
					data);

	if (res_SETATTR4->status != NFS4_OK)
		return res_SETATTR4->status;

	/* Trunc may change Xtime so we have to start with trunc and
	 * finish by the mtime and atime
	 */
	if ((FSAL_TEST_MASK(sattr.mask, ATTR_SIZE))
	     || (FSAL_TEST_MASK(sattr.mask, ATTR4_SPACE_RESERVED))) {
		/* Setting the size of a directory is prohibited */
		if (data->current_filetype == DIRECTORY) {
			res_SETATTR4->status = NFS4ERR_ISDIR;
			return res_SETATTR4->status;
		}

		/* Object should be a file */
		if (data->current_entry->type != REGULAR_FILE) {
			res_SETATTR4->status = NFS4ERR_INVAL;
			return res_SETATTR4->status;
		}

		entry = data->current_entry;

		/* Check stateid correctness and get pointer to state */
		res_SETATTR4->status =
		    nfs4_Check_Stateid(&arg_SETATTR4->stateid,
				       data->current_entry,
				       &state_found,
				       data,
				       STATEID_SPECIAL_ANY,
				       0,
				       false,
				       tag);

		if (res_SETATTR4->status != NFS4_OK)
			return res_SETATTR4->status;

		/* NB: After this point, if state_found == NULL, then
		 * the stateid is all-0 or all-1
		 */
		if (state_found != NULL) {
			switch (state_found->state_type) {
			case STATE_TYPE_SHARE:
				state_open = state_found;
				/* Note this causes an extra refcount, but it
				 * simplifies logic below.
				 */
				inc_state_t_ref(state_open);
				break;

			case STATE_TYPE_LOCK:
				state_open =
				    state_found->state_data.lock.openstate;
				inc_state_t_ref(state_open);
				break;

			case STATE_TYPE_DELEG:
				state_open = NULL;
				break;

			default:
				res_SETATTR4->status = NFS4ERR_BAD_STATEID;
				return res_SETATTR4->status;
			}

			/* This is a size operation, this means that
			 * the file MUST have been opened for writing
			 */
			if (state_open != NULL &&
			    (state_open->state_data.share.share_access &
			     OPEN4_SHARE_ACCESS_WRITE) == 0) {
				/* Bad open mode, return NFS4ERR_OPENMODE */
				res_SETATTR4->status = NFS4ERR_OPENMODE;
				return res_SETATTR4->status;
			}
		} else {
			/* Special stateid, no open state, check to
			 * see if any share conflicts
			 */
			state_open = NULL;

			/* Special stateid, no open state, check to see if
			 * any share conflicts The stateid is all-0 or all-1
			 */
			res_SETATTR4->status = nfs4_Errno_state(
				state_share_anonymous_io_start(
					entry,
					OPEN4_SHARE_ACCESS_WRITE,
					SHARE_BYPASS_NONE));

			if (res_SETATTR4->status != NFS4_OK)
				return res_SETATTR4->status;

			anonymous_started = true;
		}
	}

	const time_t S_NSECS = 1000000000UL;
	/* Set the atime and mtime (ctime is not setable) */

	/* A carry into seconds considered invalid */
	if (sattr.atime.tv_nsec >= S_NSECS) {
		res_SETATTR4->status = NFS4ERR_INVAL;
		goto done;
	}

	if (sattr.mtime.tv_nsec >= S_NSECS) {
		res_SETATTR4->status = NFS4ERR_INVAL;
		goto done;
	}

	/* If owner or owner_group are set, and the credential was
	 * squashed, then we must squash the set owner and owner_group.
	 */
	squash_setattr(&sattr);

	/* If a SETATTR comes with an open stateid, and size is being
	 * set, then the open MUST be for write (checked above), so
	 * is_open_write is simple at this stage, it's just a check that
	 * we have an open owner.
	 */
	cache_status = cache_inode_setattr(data->current_entry,
					   &sattr,
					   state_open != NULL);

	if (cache_status != CACHE_INODE_SUCCESS) {
		res_SETATTR4->status = nfs4_Errno(cache_status);
		goto done;
	}

	/* Set the replyed structure */
	res_SETATTR4->attrsset = arg_SETATTR4->obj_attributes.attrmask;

	/* Exit with no error */
	res_SETATTR4->status = NFS4_OK;

 done:

	if (anonymous_started)
		state_share_anonymous_io_done(entry, OPEN4_SHARE_ACCESS_WRITE);

	if (state_found != NULL)
		dec_state_t_ref(state_found);

	if (state_open != NULL)
		dec_state_t_ref(state_open);

	return res_SETATTR4->status;
}				/* nfs4_op_setattr */
コード例 #28
0
ファイル: handle.c プロジェクト: asias/nfs-ganesha
static fsal_status_t setattrs(struct fsal_obj_handle *obj_hdl,
			      const struct req_op_context *opctx,
			      struct attrlist *attrs)
{
	int rc = 0;
	fsal_status_t status = { ERR_FSAL_NO_ERROR, 0 };
	struct stat sb;
	int mask = 0;
	struct glusterfs_export *glfs_export =
	    container_of(obj_hdl->export, struct glusterfs_export, export);
	struct glusterfs_handle *objhandle =
	    container_of(obj_hdl, struct glusterfs_handle, handle);
#ifdef GLTIMING
	struct timespec s_time, e_time;

	now(&s_time);
#endif

	memset(&sb, 0, sizeof(struct stat));

	if (FSAL_TEST_MASK(attrs->mask, ATTR_SIZE)) {
		rc = glfs_h_truncate(glfs_export->gl_fs, objhandle->glhandle,
				     attrs->filesize);
		if (rc != 0) {
			status = gluster2fsal_error(errno);
			goto out;
		}
	}

	if (FSAL_TEST_MASK(attrs->mask, ATTR_MODE)) {
		mask |= GLAPI_SET_ATTR_MODE;
		sb.st_mode = fsal2unix_mode(attrs->mode);
	}

	if (FSAL_TEST_MASK(attrs->mask, ATTR_OWNER)) {
		mask |= GLAPI_SET_ATTR_UID;
		sb.st_uid = attrs->owner;
	}

	if (FSAL_TEST_MASK(attrs->mask, ATTR_GROUP)) {
		mask |= GLAPI_SET_ATTR_GID;
		sb.st_gid = attrs->group;
	}

	if (FSAL_TEST_MASK(attrs->mask, ATTR_ATIME)) {
		mask |= GLAPI_SET_ATTR_ATIME;
		sb.st_atim = attrs->atime;
	}

	if (FSAL_TEST_MASK(attrs->mask, ATTR_ATIME_SERVER)) {
		mask |= GLAPI_SET_ATTR_ATIME;
		struct timespec timestamp;

		rc = clock_gettime(CLOCK_REALTIME, &timestamp);
		if (rc != 0) {
			status = gluster2fsal_error(errno);
			goto out;
		}
		sb.st_atim = timestamp;
	}

	if (FSAL_TEST_MASK(attrs->mask, ATTR_MTIME)) {
		mask |= GLAPI_SET_ATTR_MTIME;
		sb.st_mtim = attrs->mtime;
	}
	if (FSAL_TEST_MASK(attrs->mask, ATTR_MTIME_SERVER)) {
		mask |= GLAPI_SET_ATTR_MTIME;
		struct timespec timestamp;

		rc = clock_gettime(CLOCK_REALTIME, &timestamp);
		if (rc != 0) {
			status = gluster2fsal_error(rc);
			goto out;
		}
		sb.st_mtim = timestamp;
	}

	rc = glfs_h_setattrs(glfs_export->gl_fs, objhandle->glhandle, &sb,
			     mask);
	if (rc != 0) {
		status = gluster2fsal_error(errno);
		goto out;
	}

 out:
#ifdef GLTIMING
	now(&e_time);
	latency_update(&s_time, &e_time, lat_setattrs);
#endif
	return status;
}
コード例 #29
0
ファイル: nfs4_op_open.c プロジェクト: dotbugfix/nfs-ganesha
static void open4_ex_create_args(OPEN4args *arg,
				 compound_data_t *data,
				 OPEN4res *res_OPEN4,
				 void *verifier,
				 enum fsal_create_mode *createmode,
				 struct attrlist *sattr)
{
	createhow4 *createhow = &arg->openhow.openflag4_u.how;
	fattr4 *arg_attrs = NULL;

	*createmode = nfs4_createmode_to_fsal(createhow->mode);

	if (createhow->mode == EXCLUSIVE4_1) {
		memcpy(verifier,
		       createhow->createhow4_u.ch_createboth.cva_verf,
		       sizeof(fsal_verifier_t));
	} else if (createhow->mode == EXCLUSIVE4) {
		memcpy(verifier,
		       createhow->createhow4_u.createverf,
		       sizeof(fsal_verifier_t));
	}

	/* Select the correct attributes */
	if (createhow->mode == GUARDED4 || createhow->mode == UNCHECKED4)
		arg_attrs = &createhow->createhow4_u.createattrs;
	else if (createhow->mode == EXCLUSIVE4_1)
		arg_attrs = &createhow->createhow4_u.ch_createboth.cva_attrs;

	if (arg_attrs != NULL) {
		/* Check if asked attributes are correct */
		if (!nfs4_Fattr_Supported(arg_attrs)) {
			res_OPEN4->status = NFS4ERR_ATTRNOTSUPP;
			return;
		}

		if (!nfs4_Fattr_Check_Access(arg_attrs, FATTR4_ATTR_WRITE)) {
			res_OPEN4->status = NFS4ERR_INVAL;
			return;
		}

		/* Convert the attributes */
		if (arg_attrs->attrmask.bitmap4_len != 0) {
			/* Convert fattr4 so nfs4_sattr */
			res_OPEN4->status =
			    nfs4_Fattr_To_FSAL_attr(sattr, arg_attrs, data);

			if (res_OPEN4->status != NFS4_OK)
				return;
		}

		if (createhow->mode == EXCLUSIVE4_1) {
			/** @todo FSF: this needs to be corrected in case FSAL
			 *             uses different attributes for the
			 *             verifier.
			 */
			/* Check that we aren't trying to set the verifier
			 * attributes.
			 */
			if (FSAL_TEST_MASK(sattr->valid_mask, ATTR_ATIME) ||
			    FSAL_TEST_MASK(sattr->valid_mask, ATTR_MTIME)) {
				res_OPEN4->status = NFS4ERR_INVAL;
				return;
			}
		}

		/* If owner or owner_group are set, and the credential was
		 * squashed, then we must squash the set owner and owner_group.
		 */
		squash_setattr(sattr);
	}

	if (!(sattr->valid_mask & ATTR_MODE)) {
		/* Make sure mode is set, even for exclusive create. */
		sattr->mode = 0600;
		sattr->valid_mask |= ATTR_MODE;
	}
}
コード例 #30
0
ファイル: fsal_attrs.c プロジェクト: alangenfeld/cloud-nfs
fsal_status_t FSAL_setattrs(fsal_handle_t * filehandle, /* IN */
                            fsal_op_context_t * p_context,      /* IN */
                            fsal_attrib_list_t * attrib_set,    /* IN */
                            fsal_attrib_list_t * object_attributes      /* [ IN/OUT ] */
    )
{
  GHOSTFS_setattr_mask_t set_mask = 0;
  GHOSTFS_Attrs_t ghost_attrs;
  int rc;

  memset(&ghost_attrs, 0, sizeof(GHOSTFS_Attrs_t));

  /* For logging */
  SetFuncID(INDEX_FSAL_setattrs);

#define SETTABLE_ATTRIBUTES ( FSAL_ATTR_SIZE |\
                              FSAL_ATTR_MODE |\
                              FSAL_ATTR_OWNER |\
                              FSAL_ATTR_GROUP |\
                              FSAL_ATTR_ATIME |\
                              FSAL_ATTR_MTIME )
  /* sanity checks.
   * note : object_attributes is optional.
   */
  if(!filehandle || !p_context || !attrib_set)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs);

  /* first convert attributes and mask */

  if(FSAL_TEST_MASK(attrib_set->asked_attributes, FSAL_ATTR_SIZE))
    {
      set_mask |= SETATTR_SIZE;
      ghost_attrs.size = attrib_set->filesize;
    }
  if(FSAL_TEST_MASK(attrib_set->asked_attributes, FSAL_ATTR_MODE))
    {
      set_mask |= SETATTR_MODE;
      ghost_attrs.mode = fsal2ghost_mode(attrib_set->mode);
    }

  /* ghostfs does not check chown restrictions,
   * so we check this for it. */

  if(FSAL_TEST_MASK(attrib_set->asked_attributes, FSAL_ATTR_OWNER))
    {

      if(p_context->credential.user != 0)
        Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);

      set_mask |= SETATTR_UID;
      ghost_attrs.uid = attrib_set->owner;
    }

  if(FSAL_TEST_MASK(attrib_set->asked_attributes, FSAL_ATTR_GROUP))
    {
      if(p_context->credential.user != 0)
        Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);

      set_mask |= SETATTR_GID;
      ghost_attrs.gid = attrib_set->group;
    }

  if(FSAL_TEST_MASK(attrib_set->asked_attributes, FSAL_ATTR_ATIME))
    {
      set_mask |= SETATTR_ATIME;
      ghost_attrs.atime = attrib_set->atime.seconds;
    }
  if(FSAL_TEST_MASK(attrib_set->asked_attributes, FSAL_ATTR_MTIME))
    {
      set_mask |= SETATTR_MTIME;
      ghost_attrs.mtime = attrib_set->mtime.seconds;
    }

  if(attrib_set->asked_attributes & ~SETTABLE_ATTRIBUTES)
    {
      LogFullDebug(COMPONENT_FSAL, "FSAL: To be set %llX, Settable %llX",
             (unsigned long long)object_attributes->asked_attributes,
             (unsigned long long)SETTABLE_ATTRIBUTES);

      Return(ERR_FSAL_ATTRNOTSUPP, 0, INDEX_FSAL_setattrs);
    }

  /* appel a setattr */
  rc = GHOSTFS_SetAttrs((GHOSTFS_handle_t) (*filehandle), set_mask, ghost_attrs);

  if(rc)
    Return(ghost2fsal_error(rc), rc, INDEX_FSAL_setattrs);

  if(object_attributes)
    {
      fsal_status_t status = FSAL_getattrs(filehandle, p_context, object_attributes);

      /* on error, we set a special bit in the mask. */
      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(object_attributes->asked_attributes);
          FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
        }

    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs);

}