Beispiel #1
0
fsal_status_t FSAL_proxy_truncate_stateless(proxyfsal_handle_t * filehandle,    /* IN */
                                            proxyfsal_op_context_t * p_context, /* IN */
                                            fsal_size_t length, /* IN */
                                            fsal_attrib_list_t * object_attributes      /* [ IN/OUT ] */
    )
{
  int rc;

  COMPOUND4args argnfs4;
  COMPOUND4res resnfs4;
  nfs_fh4 nfs4fh;
  fsal_status_t fsal_status;
  fsal_attrib_list_t open_attrs;
  bitmap4 inbitmap;
  bitmap4 convert_bitmap;
  uint32_t inbitmap_val[2];
  uint32_t bitmap_res[2];
  uint32_t bitmap_set[2];
  uint32_t bitmap_conv_val[2];

#define FSAL_TRUNCATE_STATELESS_NB_OP_ALLOC 3
  nfs_argop4 argoparray[FSAL_TRUNCATE_STATELESS_NB_OP_ALLOC];
  nfs_resop4 resoparray[FSAL_TRUNCATE_STATELESS_NB_OP_ALLOC];

  fsal_attrib_list_t fsal_attr_set;
  fattr4 fattr_set;
  fsal_proxy_internal_fattr_t fattr_internal;
  struct timeval timeout = { 25, 0 };

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

  if(filehandle->data.object_type_reminder != FSAL_TYPE_FILE)
    {
      Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_truncate);
    }

  /* Setup results structures */
  argnfs4.argarray.argarray_val = argoparray;
  resnfs4.resarray.resarray_val = resoparray;
  fsal_internal_proxy_setup_fattr(&fattr_internal);
  argnfs4.minorversion = 0;
  /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Truncate" ; */
  argnfs4.tag.utf8string_val = NULL;
  argnfs4.tag.utf8string_len = 0;
  argnfs4.argarray.argarray_len = 0;

  /* Get NFSv4 File handle */
  if(fsal_internal_proxy_extract_fh(&nfs4fh, filehandle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_truncate);

  /* Get prepared for truncate */
  fsal_attr_set.asked_attributes = FSAL_ATTR_SIZE;
  fsal_attr_set.filesize = length;

  convert_bitmap.bitmap4_val = bitmap_conv_val;
  convert_bitmap.bitmap4_len = 2;

  fsal_interval_proxy_fsalattr2bitmap4(&fsal_attr_set, &convert_bitmap);

  if(nfs4_FSALattr_To_Fattr(NULL,       /* no exportlist required here */
                            &fsal_attr_set, &fattr_set, NULL,   /* no compound data required here */
                            NULL,       /* No fh here, filehandle is not a settable attribute */
                            &convert_bitmap) == -1)
    Return(ERR_FSAL_INVAL, -1, INDEX_FSAL_truncate);

  inbitmap.bitmap4_val = inbitmap_val;
  inbitmap.bitmap4_len = 2;
  fsal_internal_proxy_create_fattr_bitmap(&inbitmap);

#define FSAL_TRUNCATE_STATELESS_IDX_OP_PUTFH     0
#define FSAL_TRUNCATE_STATELESS_IDX_OP_SETATTR   1
#define FSAL_TRUNCATE_STATELESS_IDX_OP_GETATTR   2
  COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
  COMPOUNDV4_ARG_ADD_OP_SETATTR(argnfs4, fattr_set);
  COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, inbitmap);

  /* For ATTR_SIZE, stateid is needed, we use the stateless "all-0's" stateid here */
  argnfs4.argarray.argarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_SETATTR].nfs_argop4_u.
      opsetattr.stateid.seqid = 0;
  memset(argnfs4.argarray.argarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_SETATTR].
         nfs_argop4_u.opsetattr.stateid.other, 0, 12);

  resnfs4.resarray.resarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_GETATTR].nfs_resop4_u.
      opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res;
  resnfs4.resarray.resarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_GETATTR].nfs_resop4_u.
      opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_GETATTR].nfs_resop4_u.
      opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
      (char *)&fattr_internal;
  resnfs4.resarray.resarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_GETATTR].nfs_resop4_u.
      opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
      sizeof(fattr_internal);

  resnfs4.resarray.resarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_SETATTR].nfs_resop4_u.
      opsetattr.attrsset.bitmap4_val = bitmap_set;
  resnfs4.resarray.resarray_val[FSAL_TRUNCATE_STATELESS_IDX_OP_SETATTR].nfs_resop4_u.
      opsetattr.attrsset.bitmap4_len = 2;

  TakeTokenFSCall();

  COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
  if(rc != RPC_SUCCESS)
    {
      ReleaseTokenFSCall();

      Return(ERR_FSAL_IO, 0, INDEX_FSAL_truncate);
    }

  ReleaseTokenFSCall();

  if(resnfs4.status != NFS4_OK)
    return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_truncate);

  /* >> interpret error code << */

  /* >> Optionnaly retrieve post op attributes
   * If your filesystem truncate call can't return them,
   * you can proceed like this : <<
   */
  if(object_attributes)
    {
      if(nfs4_Fattr_To_FSAL_attr(object_attributes,
                                 &resnfs4.resarray.resarray_val
                                 [FSAL_TRUNCATE_STATELESS_IDX_OP_GETATTR].
                                 nfs_resop4_u.opgetattr.GETATTR4res_u.resok4.
                                 obj_attributes) != 1)
        {
          FSAL_CLEAR_MASK(object_attributes->asked_attributes);
          FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);

          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_truncate);
        }

    }

  /* No error occured */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_truncate);
}                               /* FSAL_proxy_truncate_stateless */
Beispiel #2
0
fsal_status_t PROXYFSAL_rename(fsal_handle_t * old_parent,       /* IN */
                               fsal_name_t * p_old_name,        /* IN */
                               fsal_handle_t * new_parent,       /* IN */
                               fsal_name_t * p_new_name,        /* IN */
                               fsal_op_context_t *context,      /* IN */
                               fsal_attrib_list_t * src_dir_attributes, /* [ IN/OUT ] */
                               fsal_attrib_list_t * tgt_dir_attributes  /* [ IN/OUT ] */
    )
{

  int rc;

  COMPOUND4args argnfs4;
  COMPOUND4res resnfs4;
  nfs_fh4 nfs4fh_old;
  nfs_fh4 nfs4fh_new;
  bitmap4 bitmap_old;
  uint32_t bitmap_val_old[2];
  bitmap4 bitmap_new;
  uint32_t bitmap_val_new[2];
  component4 oldname;
  char oldnameval[MAXNAMLEN];
  component4 newname;
  char newnameval[MAXNAMLEN];
  proxyfsal_handle_t * old_parentdir_handle = (proxyfsal_handle_t *)old_parent;
  proxyfsal_handle_t * new_parentdir_handle = (proxyfsal_handle_t *)new_parent;
  proxyfsal_op_context_t * p_context = (proxyfsal_op_context_t *)context;

#define FSAL_RENAME_NB_OP_ALLOC 7
  nfs_argop4 argoparray[FSAL_RENAME_NB_OP_ALLOC];
  nfs_resop4 resoparray[FSAL_RENAME_NB_OP_ALLOC];
  uint32_t bitmap_res_old[2];
  uint32_t bitmap_res_new[2];

  fsal_proxy_internal_fattr_t fattr_internal_new;
  fsal_proxy_internal_fattr_t fattr_internal_old;
  struct timeval timeout = TIMEOUTRPC;

  /* sanity checks.
   * note : src/tgt_dir_attributes are optional.
   */
  if(!old_parentdir_handle ||
     !new_parentdir_handle || !p_old_name || !p_new_name || !p_context)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename);

  /* Setup results structures */
  argnfs4.argarray.argarray_val = argoparray;
  resnfs4.resarray.resarray_val = resoparray;
  fsal_internal_proxy_setup_fattr(&fattr_internal_new);
  fsal_internal_proxy_setup_fattr(&fattr_internal_old);
  argnfs4.minorversion = 0;
  /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Rename" ; */
  argnfs4.tag.utf8string_val = NULL;
  argnfs4.tag.utf8string_len = 0;
  argnfs4.argarray.argarray_len = 0;

  /* Prepare the structures */
  bitmap_old.bitmap4_val = bitmap_val_old;
  bitmap_old.bitmap4_len = 2;

  fsal_internal_proxy_create_fattr_bitmap(&bitmap_old);

  if(fsal_internal_proxy_extract_fh(&nfs4fh_old, old_parent) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename);

  memset((char *)&oldname, 0, sizeof(component4));
  oldname.utf8string_val = oldnameval;
  if(fsal_internal_proxy_fsal_name_2_utf8(p_old_name, &oldname) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename);

  bitmap_new.bitmap4_val = bitmap_val_new;
  bitmap_new.bitmap4_len = 2;
  fsal_internal_proxy_create_fattr_bitmap(&bitmap_new);

  if(fsal_internal_proxy_extract_fh(&nfs4fh_new, new_parent) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename);

  memset((char *)&newname, 0, sizeof(component4));
  newname.utf8string_val = newnameval;
  if(fsal_internal_proxy_fsal_name_2_utf8(p_new_name, &newname) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename);

#define FSAL_RENAME_IDX_OP_PUTFH_OLD      0
#define FSAL_RENAME_IDX_OP_SAVEFH         1
#define FSAL_RENAME_IDX_OP_PUTFH_NEW      2
#define FSAL_RENAME_IDX_OP_RENAME         3
#define FSAL_RENAME_IDX_OP_GETATTR_NEW    4
#define FSAL_RENAME_IDX_OP_RESTOREFH      5
#define FSAL_RENAME_IDX_OP_GETATTR_OLD    6

  COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh_old);
  COMPOUNDV4_ARG_ADD_OP_SAVEFH(argnfs4);
  COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh_new);
  COMPOUNDV4_ARG_ADD_OP_RENAME(argnfs4, oldname, newname);
  COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap_new);
  COMPOUNDV4_ARG_ADD_OP_RESTOREFH(argnfs4);
  COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap_old);

  resnfs4.resarray.resarray_val[FSAL_RENAME_IDX_OP_GETATTR_NEW].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res_new;
  resnfs4.resarray.resarray_val[FSAL_RENAME_IDX_OP_GETATTR_NEW].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_RENAME_IDX_OP_GETATTR_NEW].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
      (char *)&fattr_internal_new;
  resnfs4.resarray.resarray_val[FSAL_RENAME_IDX_OP_GETATTR_NEW].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
      sizeof(fattr_internal_new);

  resnfs4.resarray.resarray_val[FSAL_RENAME_IDX_OP_GETATTR_OLD].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res_old;
  resnfs4.resarray.resarray_val[FSAL_RENAME_IDX_OP_GETATTR_OLD].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_RENAME_IDX_OP_GETATTR_OLD].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
      (char *)&fattr_internal_old;
  resnfs4.resarray.resarray_val[FSAL_RENAME_IDX_OP_GETATTR_OLD].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
      sizeof(fattr_internal_old);

  TakeTokenFSCall();

  /* Call the NFSv4 function */
  COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
  if(rc != RPC_SUCCESS)
    {
      ReleaseTokenFSCall();

      Return(ERR_FSAL_IO, rc, INDEX_FSAL_rename);
    }

  ReleaseTokenFSCall();

  if(resnfs4.status != NFS4_OK)
    return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_rename);

  /* >> get last parent post op attributes if asked
   * For example : << */

  if(src_dir_attributes)
    {
      if(nfs4_Fattr_To_FSAL_attr(src_dir_attributes,
                                 &resnfs4.resarray.resarray_val
                                 [FSAL_RENAME_IDX_OP_GETATTR_OLD].nfs_resop4_u.
                                 opgetattr.GETATTR4res_u.resok4.obj_attributes) != NFS4_OK)
        {
          FSAL_CLEAR_MASK(src_dir_attributes->asked_attributes);
          FSAL_SET_MASK(src_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);

          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rename);
        }

    }

  /* >> get new parent post op attributes if asked
   * For example : << */

  if(tgt_dir_attributes)
    {
      if(nfs4_Fattr_To_FSAL_attr(tgt_dir_attributes,
                                 &resnfs4.resarray.resarray_val
                                 [FSAL_RENAME_IDX_OP_GETATTR_NEW].nfs_resop4_u.
                                 opgetattr.GETATTR4res_u.resok4.obj_attributes) != NFS4_OK)
        {
          FSAL_CLEAR_MASK(tgt_dir_attributes->asked_attributes);
          FSAL_SET_MASK(tgt_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);

          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_rename);
        }

    }

  /* OK */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_rename);

}
Beispiel #3
0
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 */
Beispiel #4
0
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;
	}
}
Beispiel #5
0
fsal_status_t PROXYFSAL_lookup(proxyfsal_handle_t * parent_directory_handle,    /* IN */
                               fsal_name_t * p_filename,        /* IN */
                               proxyfsal_op_context_t * p_context,      /* IN */
                               proxyfsal_handle_t * object_handle,      /* OUT */
                               fsal_attrib_list_t * object_attributes   /* [ IN/OUT ] */
    )
{

  int rc;
  COMPOUND4args argnfs4;
  COMPOUND4res resnfs4;
  nfs_fh4 nfs4fh;
  bitmap4 bitmap;
  uint32_t bitmap_val[2];
  component4 name;
  char nameval[MAXNAMLEN];
  fsal_attrib_list_t attributes;
  unsigned int index_getfh = 0;
  unsigned int index_getattr = 0;

#define FSAL_LOOKUP_NB_OP_ALLOC 4
  nfs_argop4 argoparray[FSAL_LOOKUP_NB_OP_ALLOC];
  nfs_resop4 resoparray[FSAL_LOOKUP_NB_OP_ALLOC];
  uint32_t bitmap_res[2];

  fsal_proxy_internal_fattr_t fattr_internal;
  char padfilehandle[FSAL_PROXY_FILEHANDLE_MAX_LEN];

  struct timeval timeout = TIMEOUTRPC;
  /* sanity checks
   * note : object_attributes is optionnal
   *        parent_directory_handle may be null for getting FS root.
   */
  if(!object_handle || !p_context)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);

  /* Setup results structures */
  argnfs4.argarray.argarray_val = argoparray;
  resnfs4.resarray.resarray_val = resoparray;
  fsal_internal_proxy_setup_fattr(&fattr_internal);
  argnfs4.minorversion = 0;
  argnfs4.argarray.argarray_len = 0;

  /* >> retrieve root handle filehandle here << */
  bitmap.bitmap4_val = bitmap_val;
  bitmap.bitmap4_len = 2;
  fsal_internal_proxy_create_fattr_bitmap(&bitmap);

  if(!parent_directory_handle)
    {

      /* check that p_filename is NULL,
       * else, parent_directory_handle should not
       * be NULL.
       */
      if(p_filename != NULL)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);

      /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Lookup Root" ; */
      argnfs4.tag.utf8string_val = NULL;
      argnfs4.tag.utf8string_len = 0;

#define FSAL_LOOKUP_IDX_OP_PUTROOTFH      0
#define FSAL_LOOKUP_IDX_OP_GETATTR_ROOT   1
#define FSAL_LOOKUP_IDX_OP_GETFH_ROOT     2
      COMPOUNDV4_ARG_ADD_OP_PUTROOTFH(argnfs4);
      COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);
      COMPOUNDV4_ARG_ADD_OP_GETFH(argnfs4);

      index_getattr = FSAL_LOOKUP_IDX_OP_GETATTR_ROOT;
      index_getfh = FSAL_LOOKUP_IDX_OP_GETFH_ROOT;

      resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR_ROOT].nfs_resop4_u.
          opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res;
      resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR_ROOT].nfs_resop4_u.
          opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

      resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR_ROOT].nfs_resop4_u.
          opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
          (char *)&fattr_internal;
      resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR_ROOT].nfs_resop4_u.
          opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
          sizeof(fattr_internal);

      resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETFH_ROOT].nfs_resop4_u.opgetfh.
          GETFH4res_u.resok4.object.nfs_fh4_val = (char *)padfilehandle;
      resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETFH_ROOT].nfs_resop4_u.opgetfh.
          GETFH4res_u.resok4.object.nfs_fh4_len = FSAL_PROXY_FILEHANDLE_MAX_LEN;
    }
  else                          /* this is a real lookup(parent, name)  */
    {
      PRINT_HANDLE("PROXYFSAL_lookup parent", parent_directory_handle);

      /* the filename should not be null */
      if(p_filename == NULL)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);

      /* >> Be careful about junction crossing, symlinks, hardlinks,...
       * You may check the parent type if it's sored into the handle <<
       */

      switch (parent_directory_handle->data.object_type_reminder)
        {
        case FSAL_TYPE_DIR:
          /* OK */
          break;

        case FSAL_TYPE_JUNCTION:
          /* This is a junction */
          Return(ERR_FSAL_XDEV, 0, INDEX_FSAL_lookup);

        case FSAL_TYPE_FILE:
        case FSAL_TYPE_LNK:
        case FSAL_TYPE_XATTR:
          /* not a directory */
          Return(ERR_FSAL_NOTDIR, 0, INDEX_FSAL_lookup);

        default:
          Return(ERR_FSAL_SERVERFAULT, 0, INDEX_FSAL_lookup);
        }

      /* >> Call your filesystem lookup function here << */
      if(fsal_internal_proxy_extract_fh(&nfs4fh, parent_directory_handle) == FALSE)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);

      memset((char *)&name, 0, sizeof(component4));
      name.utf8string_val = nameval;
      if(fsal_internal_proxy_fsal_name_2_utf8(p_filename, &name) == FALSE)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);

      if(!FSAL_namecmp(p_filename, (fsal_name_t *) & FSAL_DOT))
        {
          /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Lookup current" ; */
          argnfs4.tag.utf8string_val = NULL;
          argnfs4.tag.utf8string_len = 0;

#define FSAL_LOOKUP_IDX_OP_DOT_PUTFH     0
#define FSAL_LOOKUP_IDX_OP_DOT_GETATTR   1
#define FSAL_LOOKUP_IDX_OP_DOT_GETFH     2
          COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
          COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);
          COMPOUNDV4_ARG_ADD_OP_GETFH(argnfs4);

          index_getattr = FSAL_LOOKUP_IDX_OP_DOT_GETATTR;
          index_getfh = FSAL_LOOKUP_IDX_OP_DOT_GETFH;

          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_GETATTR].nfs_resop4_u.
              opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val =
              bitmap_res;
          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_GETATTR].nfs_resop4_u.
              opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_GETATTR].nfs_resop4_u.
              opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
              (char *)&fattr_internal;
          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_GETATTR].nfs_resop4_u.
              opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
              sizeof(fattr_internal);

          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_GETFH].nfs_resop4_u.
              opgetfh.GETFH4res_u.resok4.object.nfs_fh4_val = (char *)padfilehandle;
          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_GETFH].nfs_resop4_u.
              opgetfh.GETFH4res_u.resok4.object.nfs_fh4_len =
              FSAL_PROXY_FILEHANDLE_MAX_LEN;
        }
      else if(!FSAL_namecmp(p_filename, (fsal_name_t *) & FSAL_DOT_DOT))
        {
          /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Lookup parent" ; */
          argnfs4.tag.utf8string_val = NULL;
          argnfs4.tag.utf8string_len = 0;

#define FSAL_LOOKUP_IDX_OP_DOT_DOT_PUTFH     0
#define FSAL_LOOKUP_IDX_OP_DOT_DOT_LOOKUPP   1
#define FSAL_LOOKUP_IDX_OP_DOT_DOT_GETATTR   2
#define FSAL_LOOKUP_IDX_OP_DOT_DOT_GETFH     3
          COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
          COMPOUNDV4_ARG_ADD_OP_LOOKUPP(argnfs4);
          COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);
          COMPOUNDV4_ARG_ADD_OP_GETFH(argnfs4);

          index_getattr = FSAL_LOOKUP_IDX_OP_DOT_DOT_GETATTR;
          index_getfh = FSAL_LOOKUP_IDX_OP_DOT_DOT_GETFH;

          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_DOT_GETATTR].nfs_resop4_u.
              opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val =
              bitmap_res;
          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_DOT_GETATTR].nfs_resop4_u.
              opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_DOT_GETATTR].nfs_resop4_u.
              opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
              (char *)&fattr_internal;
          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_DOT_GETATTR].nfs_resop4_u.
              opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
              sizeof(fattr_internal);

          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_DOT_GETFH].nfs_resop4_u.
              opgetfh.GETFH4res_u.resok4.object.nfs_fh4_val = (char *)padfilehandle;
          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_DOT_DOT_GETFH].nfs_resop4_u.
              opgetfh.GETFH4res_u.resok4.object.nfs_fh4_len =
              FSAL_PROXY_FILEHANDLE_MAX_LEN;
        }
      else
        {
          /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Lookup name" ; */
          argnfs4.tag.utf8string_val = NULL;
          argnfs4.tag.utf8string_len = 0;

#define FSAL_LOOKUP_IDX_OP_PUTFH     0
#define FSAL_LOOKUP_IDX_OP_LOOKUP    1
#define FSAL_LOOKUP_IDX_OP_GETATTR   2
#define FSAL_LOOKUP_IDX_OP_GETFH     3
          COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
          COMPOUNDV4_ARG_ADD_OP_LOOKUP(argnfs4, name);
          COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);
          COMPOUNDV4_ARG_ADD_OP_GETFH(argnfs4);

          index_getattr = FSAL_LOOKUP_IDX_OP_GETATTR;
          index_getfh = FSAL_LOOKUP_IDX_OP_GETFH;

          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR].nfs_resop4_u.
              opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val =
              bitmap_res;
          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR].nfs_resop4_u.
              opgetattr.GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR].nfs_resop4_u.
              opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
              (char *)&fattr_internal;
          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETATTR].nfs_resop4_u.
              opgetattr.GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
              sizeof(fattr_internal);

          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
              GETFH4res_u.resok4.object.nfs_fh4_val = (char *)padfilehandle;
          resnfs4.resarray.resarray_val[FSAL_LOOKUP_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
              GETFH4res_u.resok4.object.nfs_fh4_len = FSAL_PROXY_FILEHANDLE_MAX_LEN;
        }
    }

  TakeTokenFSCall();

  /* Call the NFSv4 function */
  COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
  if(rc != RPC_SUCCESS)
    {
      ReleaseTokenFSCall();

      Return(ERR_FSAL_IO, rc, INDEX_FSAL_lookup);
    }
  ReleaseTokenFSCall();

  if(resnfs4.status != NFS4_OK)
    return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_lookup);

  /* Use NFSv4 service function to build the FSAL_attr */
  if(nfs4_Fattr_To_FSAL_attr(&attributes,
                             &resnfs4.resarray.resarray_val[index_getattr].nfs_resop4_u.
                             opgetattr.GETATTR4res_u.resok4.obj_attributes) != NFS4_OK)
    {
      FSAL_CLEAR_MASK(object_attributes->asked_attributes);
      FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);

      Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_lookup);
    }

  if(object_attributes)
    {
      memcpy(object_attributes, &attributes, sizeof(attributes));
    }

  /* Build the handle */
  if(fsal_internal_proxy_create_fh
     (&resnfs4.resarray.resarray_val[index_getfh].nfs_resop4_u.opgetfh.GETFH4res_u.
      resok4.object, attributes.type, attributes.fileid, object_handle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);

  PRINT_HANDLE("PROXYFSAL_lookup object found", object_handle);

  /* Return attributes if asked */
  if(object_attributes)
    {
      memcpy(object_attributes, &attributes, sizeof(attributes));
    }

  /* lookup complete ! */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookup);

}
Beispiel #6
0
fsal_status_t PROXYFSAL_readlink(proxyfsal_handle_t * linkhandle,       /* IN */
                                 proxyfsal_op_context_t * p_context,    /* IN */
                                 fsal_path_t * p_link_content,  /* OUT */
                                 fsal_attrib_list_t * link_attributes   /* [ IN/OUT ] */
    )
{

  int rc;

  COMPOUND4args argnfs4;
  COMPOUND4res resnfs4;
  nfs_fh4 nfs4fh;
  bitmap4 bitmap;
  uint32_t bitmap_val[2];
  fsal_attrib_list_t attributes;

#define FSAL_READLINK_NB_OP_ALLOC 4
  nfs_argop4 argoparray[FSAL_READLINK_NB_OP_ALLOC];
  nfs_resop4 resoparray[FSAL_READLINK_NB_OP_ALLOC];
  uint32_t bitmap_res[2];

  fsal_proxy_internal_fattr_t fattr_internal;
  char padpath[FSAL_MAX_PATH_LEN];

  struct timeval timeout = TIMEOUTRPC;

  /* sanity checks.
   * note : link_attributes is optional.
   */
  if(!linkhandle || !p_context || !p_link_content)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readlink);

  /* Setup results structures */
  argnfs4.argarray.argarray_val = argoparray;
  resnfs4.resarray.resarray_val = resoparray;
  fsal_internal_proxy_setup_fattr(&fattr_internal);
  argnfs4.minorversion = 0;
  /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Readlink" ; */
  argnfs4.tag.utf8string_val = NULL;
  argnfs4.tag.utf8string_len = 0;
  argnfs4.argarray.argarray_len = 0;

  /* >> retrieve root handle filehandle here << */
  bitmap.bitmap4_val = bitmap_val;
  bitmap.bitmap4_len = 2;
  fsal_internal_proxy_create_fattr_bitmap(&bitmap);

  if(fsal_internal_proxy_extract_fh(&nfs4fh, linkhandle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readlink);

#define FSAL_READLINK_IDX_OP_PUTFH     0
#define FSAL_READLINK_IDX_OP_READLINK  1
#define FSAL_READLINK_IDX_OP_GETATTR   2

  COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
  COMPOUNDV4_ARG_ADD_OP_READLINK(argnfs4);
  COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);

  resnfs4.resarray.resarray_val[FSAL_READLINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res;
  resnfs4.resarray.resarray_val[FSAL_READLINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_READLINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
      (char *)&fattr_internal;
  resnfs4.resarray.resarray_val[FSAL_READLINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
      sizeof(fattr_internal);

  resnfs4.resarray.resarray_val[FSAL_READLINK_IDX_OP_READLINK].nfs_resop4_u.opreadlink.
      READLINK4res_u.resok4.link.utf8string_val = (char *)padpath;
  resnfs4.resarray.resarray_val[FSAL_READLINK_IDX_OP_READLINK].nfs_resop4_u.opreadlink.
      READLINK4res_u.resok4.link.utf8string_len = FSAL_MAX_PATH_LEN;

  TakeTokenFSCall();

  /* Call the NFSv4 function */
  COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
  if(rc != RPC_SUCCESS)
    {
      ReleaseTokenFSCall();

      Return(ERR_FSAL_IO, rc, INDEX_FSAL_readlink);
    }

  ReleaseTokenFSCall();

  /* >> convert error code and return on error << */
  if(resnfs4.status != NFS4_OK)
    return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_readlink);

  /* >> convert fs output to fsal_path_t
   * for example, if this is a char * (link_content_out) :
   */

  if(fsal_internal_proxy_fsal_utf8_2_path(p_link_content,
                                          &(resnfs4.resarray.resarray_val
                                            [FSAL_READLINK_IDX_OP_READLINK].
                                            nfs_resop4_u.opreadlink.READLINK4res_u.resok4.
                                            link)) == FALSE)

    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readlink);

  /* retrieves object attributes, if asked */
  if(link_attributes)
    {
      /* Use NFSv4 service function to build the FSAL_attr */
      if(nfs4_Fattr_To_FSAL_attr(&attributes,
                                 &resnfs4.resarray.
                                 resarray_val[FSAL_READLINK_IDX_OP_GETATTR].nfs_resop4_u.
                                 opgetattr.GETATTR4res_u.resok4.obj_attributes) != NFS4_OK)
        {
          FSAL_CLEAR_MASK(link_attributes->asked_attributes);
          FSAL_SET_MASK(link_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);

          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_readlink);
        }

      memcpy(link_attributes, &attributes, sizeof(attributes));

    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readlink);

}
Beispiel #7
0
int nfs4_op_create(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
{
  cache_entry_t *pentry_parent = NULL;
  cache_entry_t *pentry_new = NULL;

  fsal_attrib_list_t attr_parent;
  fsal_attrib_list_t attr_new;
  fsal_attrib_list_t sattr;

  fsal_handle_t *pnewfsal_handle = NULL;

  nfs_fh4 newfh4;
  cache_inode_status_t cache_status;
  int convrc = 0;

  fsal_accessmode_t mode = 0600;
  fsal_name_t name;

  cache_inode_create_arg_t create_arg;

  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_create";
  unsigned int i = 0;

  resp->resop = NFS4_OP_CREATE;
  res_CREATE4.status = NFS4_OK;

  /* If the filehandle is Empty */
  if(nfs4_Is_Fh_Empty(&(data->currentFH)))
    {
      res_CREATE4.status = NFS4ERR_NOFILEHANDLE;
      return res_CREATE4.status;
    }

  /* If the filehandle is invalid */
  if(nfs4_Is_Fh_Invalid(&(data->currentFH)))
    {
      res_CREATE4.status = NFS4ERR_BADHANDLE;
      return res_CREATE4.status;
    }

  /* Tests if the Filehandle is expired (for volatile filehandle) */
  if(nfs4_Is_Fh_Expired(&(data->currentFH)))
    {
      res_CREATE4.status = NFS4ERR_FHEXPIRED;
      return res_CREATE4.status;
    }

  /* Pseudo Fs is explictely a Read-Only File system */
  if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
    {
      res_CREATE4.status = NFS4ERR_ROFS;
      return res_CREATE4.status;
    }

  /* Ask only for supported attributes */
  if(!nfs4_Fattr_Supported(&arg_CREATE4.createattrs))
    {
      res_CREATE4.status = NFS4ERR_ATTRNOTSUPP;
      return res_CREATE4.status;
    }

  /* Do not use READ attr, use WRITE attr */
  if(!nfs4_Fattr_Check_Access(&arg_CREATE4.createattrs, FATTR4_ATTR_WRITE))
    {
      res_CREATE4.status = NFS4ERR_INVAL;
      return res_CREATE4.status;
    }

  /* Check for name to long */
  if(arg_CREATE4.objname.utf8string_len > FSAL_MAX_NAME_LEN)
    {
      res_CREATE4.status = NFS4ERR_NAMETOOLONG;
      return res_CREATE4.status;
    }

  /* 
   * This operation is used to create a non-regular file, 
   * this means: - a symbolic link
   *             - a block device file
   *             - a character device file
   *             - a socket file
   *             - a fifo
   *             - a directory 
   *
   * You can't use this operation to create a regular file, you have to use NFS4_OP_OPEN for this
   */

  /* Convert the UFT8 objname to a regular string */
  if(arg_CREATE4.objname.utf8string_len == 0)
    {
      res_CREATE4.status = NFS4ERR_INVAL;
      return res_CREATE4.status;
    }

  if(utf82str(name.name, &arg_CREATE4.objname) == -1)
    {
      res_CREATE4.status = NFS4ERR_INVAL;
      return res_CREATE4.status;
    }
  name.len = strlen(name.name);

  /* Sanuty check: never create a directory named '.' or '..' */
  if(arg_CREATE4.objtype.type == NF4DIR)
    {
      if(!FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT)
         || !FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT_DOT))
        {
          res_CREATE4.status = NFS4ERR_BADNAME;
          return res_CREATE4.status;
        }

    }

  /* Filename should contain not slash */
  for(i = 0; i < name.len; i++)
    {
      if(name.name[i] == '/')
        {
          res_CREATE4.status = NFS4ERR_BADCHAR;
          return res_CREATE4.status;
        }
    }
  /* Convert current FH into a cached entry, the current_pentry (assocated with the current FH will be used for this */
  pentry_parent = data->current_entry;

  /* The currentFH must point to a directory (objects are always created within a directory) */
  if(data->current_filetype != DIR_BEGINNING && data->current_filetype != DIR_CONTINUE)
    {
      res_CREATE4.status = NFS4ERR_NOTDIR;
      return res_CREATE4.status;
    }

  /* get attributes of parent directory, for 'change4' info replyed */
  if((cache_status = cache_inode_getattr(pentry_parent,
                                         &attr_parent,
                                         data->ht,
                                         data->pclient,
                                         data->pcontext,
                                         &cache_status)) != CACHE_INODE_SUCCESS)
    {
      res_CREATE4.status = nfs4_Errno(cache_status);
      return res_CREATE4.status;
    }
  /* Change info for client cache coherency, pentry internal_md is used for that */
  memset(&(res_CREATE4.CREATE4res_u.resok4.cinfo.before), 0, sizeof(changeid4));
  res_CREATE4.CREATE4res_u.resok4.cinfo.before =
      (changeid4) pentry_parent->internal_md.mod_time;

  /* Convert the incoming fattr4 to a vattr structure, if such arguments are supplied */
  if(arg_CREATE4.createattrs.attrmask.bitmap4_len != 0)
    {
      /* Arguments were supplied, extract them */
      convrc = nfs4_Fattr_To_FSAL_attr(&sattr, &(arg_CREATE4.createattrs));

      if(convrc == 0)
        {
          res_CREATE4.status = NFS4ERR_ATTRNOTSUPP;
          return res_CREATE4.status;
        }

      if(convrc == -1)
        {
          res_CREATE4.status = NFS4ERR_BADXDR;
          return res_CREATE4.status;
        }
    }

  /* Create either a symbolic link or a directory */
  switch (arg_CREATE4.objtype.type)
    {
    case NF4LNK:
      /* Convert the name to link from into a regular string */
      if(arg_CREATE4.objtype.createtype4_u.linkdata.utf8string_len == 0)
        {
          res_CREATE4.status = NFS4ERR_INVAL;
          return res_CREATE4.status;
        }
      else
        {
          if(utf82str
             (create_arg.link_content.path,
              &arg_CREATE4.objtype.createtype4_u.linkdata) == -1)
            {
              res_CREATE4.status = NFS4ERR_INVAL;
              return res_CREATE4.status;
            }
          create_arg.link_content.len = strlen(create_arg.link_content.path);
        }

      /* do the symlink operation */
      if((pentry_new = cache_inode_create(pentry_parent,
                                          &name,
                                          SYMBOLIC_LINK,
                                          mode,
                                          &create_arg,
                                          &attr_new,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* If entry exists pentry_new is not null but cache_status was set */
      if(cache_status == CACHE_INODE_ENTRY_EXISTS)
        {
          res_CREATE4.status = NFS4ERR_EXIST;
          return res_CREATE4.status;
        }

      break;
    case NF4DIR:
      /* Create a new directory */
      /* do the symlink operation */
      if((pentry_new = cache_inode_create(pentry_parent,
                                          &name,
                                          DIR_BEGINNING,
                                          mode,
                                          &create_arg,
                                          &attr_new,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* If entry exists pentry_new is not null but cache_status was set */
      if(cache_status == CACHE_INODE_ENTRY_EXISTS)
        {
          res_CREATE4.status = NFS4ERR_EXIST;
          return res_CREATE4.status;
        }
      break;

    case NF4SOCK:

      /* Create a new socket file */
      if((pentry_new = cache_inode_create(pentry_parent,
                                          &name,
                                          SOCKET_FILE,
                                          mode,
                                          NULL,
                                          &attr_new,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* If entry exists pentry_new is not null but cache_status was set */
      if(cache_status == CACHE_INODE_ENTRY_EXISTS)
        {
          res_CREATE4.status = NFS4ERR_EXIST;
          return res_CREATE4.status;
        }
      break;

    case NF4FIFO:

      /* Create a new socket file */
      if((pentry_new = cache_inode_create(pentry_parent,
                                          &name,
                                          FIFO_FILE,
                                          mode,
                                          NULL,
                                          &attr_new,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* If entry exists pentry_new is not null but cache_status was set */
      if(cache_status == CACHE_INODE_ENTRY_EXISTS)
        {
          res_CREATE4.status = NFS4ERR_EXIST;
          return res_CREATE4.status;
        }
      break;

    case NF4CHR:

      create_arg.dev_spec.major = arg_CREATE4.objtype.createtype4_u.devdata.specdata1;
      create_arg.dev_spec.minor = arg_CREATE4.objtype.createtype4_u.devdata.specdata2;

      /* Create a new socket file */
      if((pentry_new = cache_inode_create(pentry_parent,
                                          &name,
                                          CHARACTER_FILE,
                                          mode,
                                          &create_arg,
                                          &attr_new,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* If entry exists pentry_new is not null but cache_status was set */
      if(cache_status == CACHE_INODE_ENTRY_EXISTS)
        {
          res_CREATE4.status = NFS4ERR_EXIST;
          return res_CREATE4.status;
        }
      break;

    case NF4BLK:

      create_arg.dev_spec.major = arg_CREATE4.objtype.createtype4_u.devdata.specdata1;
      create_arg.dev_spec.minor = arg_CREATE4.objtype.createtype4_u.devdata.specdata2;

      /* Create a new socket file */
      if((pentry_new = cache_inode_create(pentry_parent,
                                          &name,
                                          BLOCK_FILE,
                                          mode,
                                          &create_arg,
                                          &attr_new,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* If entry exists pentry_new is not null but cache_status was set */
      if(cache_status == CACHE_INODE_ENTRY_EXISTS)
        {
          res_CREATE4.status = NFS4ERR_EXIST;
          return res_CREATE4.status;
        }
      break;

    default:
      /* Should never happen, but return NFS4ERR_BADTYPE in this case */
      res_CREATE4.status = NFS4ERR_BADTYPE;
      return res_CREATE4.status;
      break;
    }                           /* switch( arg_CREATE4.objtype.type ) */

  /* Now produce the filehandle to this file */
  if((pnewfsal_handle = cache_inode_get_fsal_handle(pentry_new, &cache_status)) == NULL)
    {
      res_CREATE4.status = nfs4_Errno(cache_status);
      return res_CREATE4.status;
    }

  /* Allocation of a new file handle */
  if(nfs4_AllocateFH(&newfh4) != NFS4_OK)
    {
      res_CREATE4.status = NFS4ERR_SERVERFAULT;
      return res_CREATE4.status;
    }

  /* Building the new file handle */
  if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data))
    {
      res_CREATE4.status = NFS4ERR_SERVERFAULT;
      return res_CREATE4.status;
    }

  /* This new fh replaces the current FH */
  data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len;
  memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val, newfh4.nfs_fh4_len);

  /* No do not need newfh any more */
  Mem_Free((char *)newfh4.nfs_fh4_val);

  /* Set the mode if requested */
  /* Use the same fattr mask for reply, if one attribute was not settable, NFS4ERR_ATTRNOTSUPP was replyied */
  res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_len =
      arg_CREATE4.createattrs.attrmask.bitmap4_len;

  if(arg_CREATE4.createattrs.attrmask.bitmap4_len != 0)
    {
      if((cache_status = cache_inode_setattr(pentry_new,
                                             &sattr,
                                             data->ht,
                                             data->pclient,
                                             data->pcontext,
                                             &cache_status)) != CACHE_INODE_SUCCESS)

        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* Allocate a new bitmap */
      res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_val =
          (unsigned int *)Mem_Alloc(res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_len *
                                    sizeof(u_int));

      if(res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_val == NULL)
        {
          res_CREATE4.status = NFS4ERR_SERVERFAULT;
          return res_CREATE4.status;
        }
      memset(res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_val, 0,
             res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_len);

      memcpy(res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_val,
             arg_CREATE4.createattrs.attrmask.bitmap4_val,
             res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_len * sizeof(u_int));
    }

  /* Get the change info on parent directory after the operation was successfull */
  if((cache_status = cache_inode_getattr(pentry_parent,
                                         &attr_parent,
                                         data->ht,
                                         data->pclient,
                                         data->pcontext,
                                         &cache_status)) != CACHE_INODE_SUCCESS)
    {
      res_CREATE4.status = nfs4_Errno(cache_status);
      return res_CREATE4.status;
    }
  memset(&(res_CREATE4.CREATE4res_u.resok4.cinfo.after), 0, sizeof(changeid4));
  res_CREATE4.CREATE4res_u.resok4.cinfo.after =
      (changeid4) pentry_parent->internal_md.mod_time;

  /* Operation is supposed to be atomic .... */
  res_CREATE4.CREATE4res_u.resok4.cinfo.atomic = TRUE;

  LogFullDebug(COMPONENT_NFS_V4, "           CREATE CINFO before = %llu  after = %llu  atomic = %d\n",
         res_CREATE4.CREATE4res_u.resok4.cinfo.before,
         res_CREATE4.CREATE4res_u.resok4.cinfo.after,
         res_CREATE4.CREATE4res_u.resok4.cinfo.atomic);

  /* @todo : BUGAZOMEU: fair ele free dans cette fonction */

  /* Keep the vnode entry for the file in the compound data */
  data->current_entry = pentry_new;
  data->current_filetype = pentry_new->internal_md.type;

  /* If you reach this point, then no error occured */
  res_CREATE4.status = NFS4_OK;

  return res_CREATE4.status;
}                               /* nfs4_op_create */
Beispiel #8
0
int nfs41_op_open(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
{
    cache_entry_t *pentry_parent = NULL;
    cache_entry_t *pentry_lookup = NULL;
    cache_entry_t *pentry_newfile = NULL;
    fsal_handle_t *pnewfsal_handle = NULL;
    fsal_attrib_list_t attr_parent;
    fsal_attrib_list_t attr;
    fsal_attrib_list_t attr_newfile;
    fsal_attrib_list_t sattr;
    fsal_openflags_t openflags = 0;
    cache_inode_status_t cache_status;
    nfsstat4 rc;
    int retval;
    fsal_name_t filename;
    bool_t AttrProvided = FALSE;
    fsal_accessmode_t mode = 0600;
    nfs_fh4 newfh4;
    nfs_client_id_t nfs_clientid;
    nfs_worker_data_t *pworker = NULL;
    int convrc = 0;
    char __attribute__ ((__unused__)) funcname[] = "nfs4_op_open";

    cache_inode_state_data_t candidate_data;
    cache_inode_state_type_t candidate_type;
    cache_inode_state_t *pfile_state = NULL;
    cache_inode_state_t *pstate_found_iterate = NULL;
    cache_inode_state_t *pstate_previous_iterate = NULL;
    cache_inode_state_t *pstate_found_same_owner = NULL;

    cache_inode_open_owner_name_t owner_name;
    cache_inode_open_owner_name_t *powner_name = NULL;
    cache_inode_open_owner_t *powner = NULL;
    bool_t open_owner_known = FALSE;

    resp->resop = NFS4_OP_OPEN;
    res_OPEN4.status = NFS4_OK;

    uint32_t tmp_attr[2];
    uint_t tmp_int = 2;

    int pnfs_status;
    cache_inode_create_arg_t create_arg;

    pworker = (nfs_worker_data_t *) data->pclient->pworker;

    /* If there is no FH */
    if(nfs4_Is_Fh_Empty(&(data->currentFH)))
    {
        res_OPEN4.status = NFS4ERR_NOFILEHANDLE;
        return res_OPEN4.status;
    }

    /* If the filehandle is invalid */
    if(nfs4_Is_Fh_Invalid(&(data->currentFH)))
    {
        res_OPEN4.status = NFS4ERR_BADHANDLE;
        return res_OPEN4.status;
    }

    /* Tests if the Filehandle is expired (for volatile filehandle) */
    if(nfs4_Is_Fh_Expired(&(data->currentFH)))
    {
        res_OPEN4.status = NFS4ERR_FHEXPIRED;
        return res_OPEN4.status;
    }

    /* This can't be done on the pseudofs */
    if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
    {
        res_OPEN4.status = NFS4ERR_ROFS;
        return res_OPEN4.status;
    }

    /* If Filehandle points to a xattr object, manage it via the xattrs specific functions */
    if(nfs4_Is_Fh_Xattr(&(data->currentFH)))
        return nfs4_op_open_xattr(op, data, resp);

    /* If data->current_entry is empty, repopulate it */
    if(data->current_entry == NULL)
    {
        if((data->current_entry = nfs_FhandleToCache(NFS_V4,
                                  NULL,
                                  NULL,
                                  &(data->currentFH),
                                  NULL,
                                  NULL,
                                  &(res_OPEN4.status),
                                  &attr,
                                  data->pcontext,
                                  data->pclient,
                                  data->ht, &retval)) == NULL)
        {
            res_OPEN4.status = NFS4ERR_SERVERFAULT;
            return res_OPEN4.status;
        }
    }

    /* Set parent */
    pentry_parent = data->current_entry;

    /* First switch is based upon claim type */
    switch (arg_OPEN4.claim.claim)
    {
    case CLAIM_DELEGATE_CUR:
    case CLAIM_DELEGATE_PREV:
        /* Check for name length */
        if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len > FSAL_MAX_NAME_LEN)
        {
            res_OPEN4.status = NFS4ERR_NAMETOOLONG;
            return res_OPEN4.status;
        }

        /* get the filename from the argument, it should not be empty */
        if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len == 0)
        {
            res_OPEN4.status = NFS4ERR_INVAL;
            return res_OPEN4.status;
        }

        res_OPEN4.status = NFS4ERR_NOTSUPP;
        return res_OPEN4.status;
        break;

    case CLAIM_NULL:
        /* Check for name length */
        if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len > FSAL_MAX_NAME_LEN)
        {
            res_OPEN4.status = NFS4ERR_NAMETOOLONG;
            return res_OPEN4.status;
        }

        /* get the filename from the argument, it should not be empty */
        if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len == 0)
        {
            res_OPEN4.status = NFS4ERR_INVAL;
            return res_OPEN4.status;
        }

        /* Check if asked attributes are correct */
        if(arg_OPEN4.openhow.openflag4_u.how.mode == GUARDED4 ||
                arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4)
        {
            if(!nfs4_Fattr_Supported
                    (&arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs))
            {
                res_OPEN4.status = NFS4ERR_ATTRNOTSUPP;
                return res_OPEN4.status;
            }

            /* Do not use READ attr, use WRITE attr */
            if(!nfs4_Fattr_Check_Access
                    (&arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs,
                     FATTR4_ATTR_WRITE))
            {
                res_OPEN4.status = NFS4ERR_INVAL;
                return res_OPEN4.status;
            }
        }

        /* Check if filename is correct */
        if((cache_status =
                    cache_inode_error_convert(FSAL_buffdesc2name
                                              ((fsal_buffdesc_t *) & arg_OPEN4.claim.open_claim4_u.
                                               file, &filename))) != CACHE_INODE_SUCCESS)
        {
            res_OPEN4.status = nfs4_Errno(cache_status);
            return res_OPEN4.status;
        }

        /* Check parent */
        pentry_parent = data->current_entry;

        /* Parent must be a directory */
        if((pentry_parent->internal_md.type != DIR_BEGINNING) &&
                (pentry_parent->internal_md.type != DIR_CONTINUE))
        {
            /* Parent object is not a directory... */
            if(pentry_parent->internal_md.type == SYMBOLIC_LINK)
                res_OPEN4.status = NFS4ERR_SYMLINK;
            else
                res_OPEN4.status = NFS4ERR_NOTDIR;

            return res_OPEN4.status;
        }

        /* What kind of open is it ? */

        LogFullDebug(COMPONENT_NFS_V4,
                     "     OPEN: Claim type = %d   Open Type = %d  Share Deny = %d   Share Access = %d \n",
                     arg_OPEN4.claim.claim, arg_OPEN4.openhow.opentype, arg_OPEN4.share_deny,
                     arg_OPEN4.share_access);


        /* It this a known client id ? */
        LogDebug(COMPONENT_NFS_V4, "OPEN Client id = %llx", arg_OPEN4.owner.clientid);

        /* Is this open_owner known ? */
        if(!nfs_convert_open_owner(&arg_OPEN4.owner, &owner_name))
        {
            res_OPEN4.status = NFS4ERR_SERVERFAULT;
            return res_OPEN4.status;
        }

        if(!nfs_open_owner_Get_Pointer(&owner_name, &powner))
        {
            /* This open owner is not known yet, allocated and set up a new one */
            GET_PREALLOC(powner,
                         data->pclient->pool_open_owner,
                         data->pclient->nb_pre_state_v4, cache_inode_open_owner_t, next);

            GET_PREALLOC(powner_name,
                         data->pclient->pool_open_owner_name,
                         data->pclient->nb_pre_state_v4,
                         cache_inode_open_owner_name_t, next);

            if(powner == NULL || powner_name == NULL)
            {
                res_OPEN4.status = NFS4ERR_SERVERFAULT;
                return res_OPEN4.status;
            }

            memcpy((char *)powner_name, (char *)&owner_name,
                   sizeof(cache_inode_open_owner_name_t));

            /* set up the content of the open_owner */
            powner->confirmed = FALSE;
            powner->seqid = 1;    /* NFSv4.1 specific, initial seqid is 1 */
            powner->related_owner = NULL;
            powner->next = NULL;
            powner->clientid = arg_OPEN4.owner.clientid;
            powner->owner_len = arg_OPEN4.owner.owner.owner_len;
            memcpy((char *)powner->owner_val, (char *)arg_OPEN4.owner.owner.owner_val,
                   arg_OPEN4.owner.owner.owner_len);
            powner->owner_val[powner->owner_len] = '\0';

            pthread_mutex_init(&powner->lock, NULL);

            if(!nfs_open_owner_Set(powner_name, powner))
            {
                res_OPEN4.status = NFS4ERR_SERVERFAULT;
                return res_OPEN4.status;
            }

        }

        /* Status of parent directory before the operation */
        if((cache_status = cache_inode_getattr(pentry_parent,
                                               &attr_parent,
                                               data->ht,
                                               data->pclient,
                                               data->pcontext,
                                               &cache_status)) != CACHE_INODE_SUCCESS)
        {
            res_OPEN4.status = nfs4_Errno(cache_status);
            return res_OPEN4.status;
        }
        memset(&(res_OPEN4.OPEN4res_u.resok4.cinfo.before), 0, sizeof(changeid4));
        res_OPEN4.OPEN4res_u.resok4.cinfo.before =
            (changeid4) pentry_parent->internal_md.mod_time;

        /* CLient may have provided fattr4 to set attributes at creation time */
        if(arg_OPEN4.openhow.openflag4_u.how.mode == GUARDED4 ||
                arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4)
        {
            if(arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs.attrmask.
                    bitmap4_len != 0)
            {
                /* Convert fattr4 so nfs4_sattr */
                convrc =
                    nfs4_Fattr_To_FSAL_attr(&sattr,
                                            &(arg_OPEN4.openhow.openflag4_u.how.
                                              createhow4_u.createattrs));

                if(convrc == 0)
                {
                    res_OPEN4.status = NFS4ERR_ATTRNOTSUPP;
                    return res_OPEN4.status;
                }

                if(convrc == -1)
                {
                    res_OPEN4.status = NFS4ERR_BADXDR;
                    return res_OPEN4.status;
                }

                AttrProvided = TRUE;
            }

        }

        /* Second switch is based upon "openhow" */
        switch (arg_OPEN4.openhow.opentype)
        {
        case OPEN4_CREATE:
            /* a new file is to be created */

            /* Does a file with this name already exist ? */
            pentry_lookup = cache_inode_lookup(pentry_parent,
                                               &filename,
                                               &attr_newfile,
                                               data->ht,
                                               data->pclient,
                                               data->pcontext, &cache_status);

            if(cache_status != CACHE_INODE_NOT_FOUND)
            {
                /* if open is UNCHECKED, return NFS4_OK (RFC3530 page 172) */
                if(arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4
                        && (cache_status == CACHE_INODE_SUCCESS))
                {
                    /* If the file is opened for write, OPEN4 while deny share write access,
                     * in this case, check caller has write access to the file */
                    if(arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE)
                    {
                        if(cache_inode_access(pentry_lookup,
                                              FSAL_W_OK,
                                              data->ht,
                                              data->pclient,
                                              data->pcontext,
                                              &cache_status) != CACHE_INODE_SUCCESS)
                        {
                            res_OPEN4.status = NFS4ERR_ACCESS;
                            return res_OPEN4.status;
                        }
                        openflags = FSAL_O_WRONLY;
                    }

                    /* Same check on read: check for readability of a file before opening it for read */
                    if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_READ)
                    {
                        if(cache_inode_access(pentry_lookup,
                                              FSAL_R_OK,
                                              data->ht,
                                              data->pclient,
                                              data->pcontext,
                                              &cache_status) != CACHE_INODE_SUCCESS)
                        {
                            res_OPEN4.status = NFS4ERR_ACCESS;
                            return res_OPEN4.status;
                        }
                        openflags = FSAL_O_RDONLY;
                    }

                    if(AttrProvided == TRUE)      /* Set the attribute if provided */
                    {
                        if((cache_status = cache_inode_setattr(pentry_lookup,
                                                               &sattr,
                                                               data->ht,
                                                               data->pclient,
                                                               data->pcontext,
                                                               &cache_status)) !=
                                CACHE_INODE_SUCCESS)
                        {
                            res_OPEN4.status = nfs4_Errno(cache_status);
                            return res_OPEN4.status;
                        }

                        res_OPEN4.OPEN4res_u.resok4.attrset =
                            arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs.
                            attrmask;
                    }
                    else
                        res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 0;

                    /* Same check on write */
                    if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE)
                    {
                        if(cache_inode_access(pentry_lookup,
                                              FSAL_W_OK,
                                              data->ht,
                                              data->pclient,
                                              data->pcontext,
                                              &cache_status) != CACHE_INODE_SUCCESS)
                        {
                            res_OPEN4.status = NFS4ERR_ACCESS;
                            return res_OPEN4.status;
                        }
                        openflags = FSAL_O_RDWR;
                    }

                    /* Set the state for the related file */

                    /* Prepare state management structure */
                    candidate_type = CACHE_INODE_STATE_SHARE;
                    candidate_data.share.share_deny = arg_OPEN4.share_deny;
                    candidate_data.share.share_access = arg_OPEN4.share_access;

                    if(cache_inode_add_state(pentry_lookup,
                                             candidate_type,
                                             &candidate_data,
                                             powner,
                                             data->pclient,
                                             data->pcontext,
                                             &pfile_state,
                                             &cache_status) != CACHE_INODE_SUCCESS)
                    {
                        /* Seqid has to be incremented even in this case */
                        P(powner->lock);
                        powner->seqid += 1;
                        V(powner->lock);

                        res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                        return res_OPEN4.status;
                    }

                    /* Open the file */
                    if(cache_inode_open_by_name(pentry_parent,
                                                &filename,
                                                pentry_lookup,
                                                data->pclient,
                                                openflags,
                                                data->pcontext,
                                                &cache_status) != CACHE_INODE_SUCCESS)
                    {
                        /* Seqid has to be incremented even in this case */
                        P(powner->lock);
                        powner->seqid += 1;
                        V(powner->lock);

                        res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                        res_OPEN4.status = NFS4ERR_ACCESS;
                        return res_OPEN4.status;
                    }

                    res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 2;
                    if((res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val =
                                (uint32_t *) Mem_Alloc(res_OPEN4.OPEN4res_u.resok4.attrset.
                                                       bitmap4_len * sizeof(uint32_t))) == NULL)
                    {
                        res_OPEN4.status = NFS4ERR_SERVERFAULT;
                        return res_OPEN4.status;
                    }

                    memset(&(res_OPEN4.OPEN4res_u.resok4.cinfo.after), 0,
                           sizeof(changeid4));
                    res_OPEN4.OPEN4res_u.resok4.cinfo.after =
                        (changeid4) pentry_parent->internal_md.mod_time;
                    res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = TRUE;

                    res_OPEN4.OPEN4res_u.resok4.stateid.seqid = pfile_state->seqid;
                    memcpy(res_OPEN4.OPEN4res_u.resok4.stateid.other,
                           pfile_state->stateid_other, 12);

                    /* No delegation */
                    res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type =
                        OPEN_DELEGATE_NONE;
                    res_OPEN4.OPEN4res_u.resok4.rflags = OPEN4_RESULT_LOCKTYPE_POSIX;

                    /* Now produce the filehandle to this file */
                    if((pnewfsal_handle =
                                cache_inode_get_fsal_handle(pentry_lookup, &cache_status)) == NULL)
                    {
                        res_OPEN4.status = nfs4_Errno(cache_status);
                        return res_OPEN4.status;
                    }

                    /* Allocation of a new file handle */
                    if((rc = nfs4_AllocateFH(&newfh4)) != NFS4_OK)
                    {
                        res_OPEN4.status = rc;
                        return res_OPEN4.status;
                    }

                    /* Building a new fh */
                    if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data))
                    {
                        res_OPEN4.status = NFS4ERR_SERVERFAULT;
                        return res_OPEN4.status;
                    }

                    /* This new fh replaces the current FH */
                    data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len;
                    memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val,
                           newfh4.nfs_fh4_len);

                    data->current_entry = pentry_lookup;
                    data->current_filetype = REGULAR_FILE;

                    res_OPEN4.status = NFS4_OK;
                    return res_OPEN4.status;
                }

                /* if open is EXCLUSIVE, but verifier is the same, return NFS4_OK (RFC3530 page 173) */
                if(arg_OPEN4.openhow.openflag4_u.how.mode == EXCLUSIVE4)
                {
                    if((pentry_lookup != NULL)
                            && (pentry_lookup->internal_md.type == REGULAR_FILE))
                    {
                        pstate_found_iterate = NULL;
                        pstate_previous_iterate = NULL;

                        do
                        {
                            cache_inode_state_iterate(pentry_lookup,
                                                      &pstate_found_iterate,
                                                      pstate_previous_iterate,
                                                      data->pclient,
                                                      data->pcontext, &cache_status);
                            if(cache_status == CACHE_INODE_STATE_ERROR)
                                break;

                            if(cache_status == CACHE_INODE_INVALID_ARGUMENT)
                            {
                                /* Seqid has to be incremented even in this case */
                                P(powner->lock);
                                powner->seqid += 1;
                                V(powner->lock);

                                res_OPEN4.status = NFS4ERR_INVAL;
                                return res_OPEN4.status;
                            }

                            /* Check is open_owner is the same */
                            if(pstate_found_iterate != NULL)
                            {
                                if((pstate_found_iterate->state_type ==
                                        CACHE_INODE_STATE_SHARE)
                                        && !memcmp(arg_OPEN4.owner.owner.owner_val,
                                                   pstate_found_iterate->powner->owner_val,
                                                   pstate_found_iterate->powner->owner_len)
                                        && !memcmp(pstate_found_iterate->state_data.share.
                                                   oexcl_verifier,
                                                   arg_OPEN4.openhow.openflag4_u.how.
                                                   createhow4_u.createverf, NFS4_VERIFIER_SIZE))
                                {

                                    /* A former open EXCLUSIVE with same owner and verifier was found, resend it */
                                    res_OPEN4.OPEN4res_u.resok4.stateid.seqid =
                                        pstate_found_iterate->seqid;
                                    memcpy(res_OPEN4.OPEN4res_u.resok4.stateid.other,
                                           pstate_found_iterate->stateid_other, 12);

                                    memset(&(res_OPEN4.OPEN4res_u.resok4.cinfo.after), 0,
                                           sizeof(changeid4));
                                    res_OPEN4.OPEN4res_u.resok4.cinfo.after =
                                        (changeid4) pentry_parent->internal_md.mod_time;
                                    res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = TRUE;

                                    /* No delegation */
                                    res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type =
                                        OPEN_DELEGATE_NONE;
                                    res_OPEN4.OPEN4res_u.resok4.rflags =
                                        OPEN4_RESULT_LOCKTYPE_POSIX;

                                    /* Now produce the filehandle to this file */
                                    if((pnewfsal_handle =
                                                cache_inode_get_fsal_handle(pentry_lookup,
                                                                            &cache_status)) == NULL)
                                    {
                                        res_OPEN4.status = nfs4_Errno(cache_status);
                                        return res_OPEN4.status;
                                    }

                                    /* Allocation of a new file handle */
                                    if((rc = nfs4_AllocateFH(&newfh4)) != NFS4_OK)
                                    {
                                        res_OPEN4.status = rc;
                                        return res_OPEN4.status;
                                    }

                                    /* Building a new fh */
                                    if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data))
                                    {
                                        res_OPEN4.status = NFS4ERR_SERVERFAULT;
                                        return res_OPEN4.status;
                                    }

                                    /* This new fh replaces the current FH */
                                    data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len;
                                    memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val,
                                           newfh4.nfs_fh4_len);

                                    data->current_entry = pentry_lookup;
                                    data->current_filetype = REGULAR_FILE;

                                    /* regular exit */
                                    res_OPEN4.status = NFS4_OK;
                                    return res_OPEN4.status;
                                }

                            }
                            /* if( pstate_found_iterate != NULL ) */
                            pstate_previous_iterate = pstate_found_iterate;
                        }
                        while(pstate_found_iterate != NULL);
                    }
                }

                /* Managing GUARDED4 mode */
                if(cache_status != CACHE_INODE_SUCCESS)
                    res_OPEN4.status = nfs4_Errno(cache_status);
                else
                    res_OPEN4.status = NFS4ERR_EXIST;       /* File already exists */
                return res_OPEN4.status;
            }

            /*  if( cache_status != CACHE_INODE_NOT_FOUND ), if file already exists basically */
            LogFullDebug(COMPONENT_NFS_V4, "    OPEN open.how = %d\n", arg_OPEN4.openhow.openflag4_u.how.mode);

            create_arg.use_pnfs = FALSE;
#ifdef _USE_PNFS
            /*  set the file has "managed via pNFS" */
            if(data->pexport->options & EXPORT_OPTION_USE_PNFS)
                create_arg.use_pnfs = TRUE;
#endif                          /* _USE_PNFS */

            /* Create the file, if we reach this point, it does not exist, we can create it */
            if((pentry_newfile = cache_inode_create(pentry_parent,
                                                    &filename,
                                                    REGULAR_FILE,
                                                    mode,
                                                    &create_arg,
                                                    &attr_newfile,
                                                    data->ht,
                                                    data->pclient,
                                                    data->pcontext, &cache_status)) == NULL)
            {
                /* If the file already exists, this is not an error if open mode is UNCHECKED */
                if(cache_status != CACHE_INODE_ENTRY_EXISTS)
                {
                    res_OPEN4.status = nfs4_Errno(cache_status);
                    return res_OPEN4.status;
                }
                else
                {
                    /* If this point is reached, then the file already exists, cache_status == CACHE_INODE_ENTRY_EXISTS and pentry_newfile == NULL
                       This probably means EXCLUSIVE4 mode is used and verifier matches. pentry_newfile is then set to pentry_lookup */
                    pentry_newfile = pentry_lookup;
                }
            }

            /* Prepare state management structure */
            candidate_type = CACHE_INODE_STATE_SHARE;
            candidate_data.share.share_deny = arg_OPEN4.share_deny;
            candidate_data.share.share_access = arg_OPEN4.share_access;
            candidate_data.share.lockheld = 0;

            /* If file is opened under mode EXCLUSIVE4, open verifier should be kept to detect non vicious double open */
            if(arg_OPEN4.openhow.openflag4_u.how.mode == EXCLUSIVE4)
            {
                strncpy(candidate_data.share.oexcl_verifier,
                        arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createverf,
                        NFS4_VERIFIER_SIZE);
            }

            if(cache_inode_add_state(pentry_newfile,
                                     candidate_type,
                                     &candidate_data,
                                     powner,
                                     data->pclient,
                                     data->pcontext,
                                     &pfile_state, &cache_status) != CACHE_INODE_SUCCESS)
            {
                /* Seqid has to be incremented even in this case */
                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);

                res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                return res_OPEN4.status;
            }

            if(AttrProvided == TRUE)      /* Set the attribute if provided */
            {
                if((cache_status = cache_inode_setattr(pentry_newfile,
                                                       &sattr,
                                                       data->ht,
                                                       data->pclient,
                                                       data->pcontext,
                                                       &cache_status)) !=
                        CACHE_INODE_SUCCESS)
                {
                    res_OPEN4.status = nfs4_Errno(cache_status);
                    return res_OPEN4.status;
                }

            }

            /* Set the openflags variable */
            if(arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE)
                openflags |= FSAL_O_RDONLY;
            if(arg_OPEN4.share_deny & OPEN4_SHARE_DENY_READ)
                openflags |= FSAL_O_WRONLY;
            if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE)
                openflags = FSAL_O_RDWR;
            if(arg_OPEN4.share_access != 0)
                openflags = FSAL_O_RDWR;    /* @todo : BUGAZOMEU : Something better later */

            /* Open the file */
            if(cache_inode_open_by_name(pentry_parent,
                                        &filename,
                                        pentry_newfile,
                                        data->pclient,
                                        openflags,
                                        data->pcontext,
                                        &cache_status) != CACHE_INODE_SUCCESS)
            {
                /* Seqid has to be incremented even in this case */
                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);

                res_OPEN4.status = NFS4ERR_ACCESS;
                return res_OPEN4.status;
            }

            break;

        case OPEN4_NOCREATE:
            /* It was not a creation, but a regular open */
            /* The filehandle to the new file replaces the current filehandle */
            if(pentry_newfile == NULL)
            {
                if((pentry_newfile = cache_inode_lookup(pentry_parent,
                                                        &filename,
                                                        &attr_newfile,
                                                        data->ht,
                                                        data->pclient,
                                                        data->pcontext,
                                                        &cache_status)) == NULL)
                {
                    res_OPEN4.status = nfs4_Errno(cache_status);
                    return res_OPEN4.status;
                }
            }

            /* OPEN4 is to be done on a file */
            if(pentry_newfile->internal_md.type != REGULAR_FILE)
            {
                if(pentry_newfile->internal_md.type == DIR_BEGINNING
                        || pentry_newfile->internal_md.type == DIR_CONTINUE)
                {
                    res_OPEN4.status = NFS4ERR_ISDIR;
                    return res_OPEN4.status;
                }
                else if(pentry_newfile->internal_md.type == SYMBOLIC_LINK)
                {
                    res_OPEN4.status = NFS4ERR_SYMLINK;
                    return res_OPEN4.status;
                }
                else
                {
                    res_OPEN4.status = NFS4ERR_INVAL;
                    return res_OPEN4.status;
                }
            }

            /* If the file is opened for write, OPEN4 while deny share write access,
             * in this case, check caller has write access to the file */
            if(arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE)
            {
                if(cache_inode_access(pentry_newfile,
                                      FSAL_W_OK,
                                      data->ht,
                                      data->pclient,
                                      data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
                {
                    res_OPEN4.status = NFS4ERR_ACCESS;
                    return res_OPEN4.status;
                }
                openflags = FSAL_O_WRONLY;
            }

            /* Same check on read: check for readability of a file before opening it for read */
            if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_READ)
            {
                if(cache_inode_access(pentry_newfile,
                                      FSAL_R_OK,
                                      data->ht,
                                      data->pclient,
                                      data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
                {
                    res_OPEN4.status = NFS4ERR_ACCESS;
                    return res_OPEN4.status;
                }
                openflags = FSAL_O_RDONLY;
            }

            /* Same check on write */
            if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE)
            {
                if(cache_inode_access(pentry_newfile,
                                      FSAL_W_OK,
                                      data->ht,
                                      data->pclient,
                                      data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
                {
                    res_OPEN4.status = NFS4ERR_ACCESS;
                    return res_OPEN4.status;
                }
                openflags = FSAL_O_RDWR;
            }

            /* Try to find if the same open_owner already has acquired a stateid for this file */
            pstate_found_iterate = NULL;
            pstate_previous_iterate = NULL;
            do
            {
                cache_inode_state_iterate(pentry_newfile,
                                          &pstate_found_iterate,
                                          pstate_previous_iterate,
                                          data->pclient, data->pcontext, &cache_status);
                if(cache_status == CACHE_INODE_STATE_ERROR)
                    break;          /* Get out of the loop */

                if(cache_status == CACHE_INODE_INVALID_ARGUMENT)
                {
                    res_OPEN4.status = NFS4ERR_INVAL;
                    return res_OPEN4.status;
                }

                /* Check is open_owner is the same */
                if(pstate_found_iterate != NULL)
                {
                    if((pstate_found_iterate->state_type == CACHE_INODE_STATE_SHARE) &&
                            (pstate_found_iterate->powner->clientid == arg_OPEN4.owner.clientid)
                            &&
                            ((pstate_found_iterate->powner->owner_len ==
                              arg_OPEN4.owner.owner.owner_len)
                             &&
                             (!memcmp
                              (arg_OPEN4.owner.owner.owner_val,
                               pstate_found_iterate->powner->owner_val,
                               pstate_found_iterate->powner->owner_len))))
                    {
                        /* We'll be re-using the found state */
                        pstate_found_same_owner = pstate_found_iterate;
                    }
                    else
                    {

                        /* This is a different owner, check for possible conflicts */

                        if(memcmp(arg_OPEN4.owner.owner.owner_val,
                                  pstate_found_iterate->powner->owner_val,
                                  pstate_found_iterate->powner->owner_len))
                        {
                            switch (pstate_found_iterate->state_type)
                            {
                            case CACHE_INODE_STATE_SHARE:
                                if((pstate_found_iterate->state_data.share.
                                        share_access & OPEN4_SHARE_ACCESS_WRITE)
                                        && (arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE))
                                {
                                    res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                                    return res_OPEN4.status;
                                }

                                break;
                            }
                        }

                    }

                    /* In all cases opening in read access a read denied file or write access to a write denied file
                     * should fail, even if the owner is the same, see discussion in 14.2.16 and 8.9 */
                    if(pstate_found_iterate->state_type == CACHE_INODE_STATE_SHARE)
                    {
                        /* deny read access on read denied file */
                        if((pstate_found_iterate->state_data.share.
                                share_deny & OPEN4_SHARE_DENY_READ)
                                && (arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_READ))
                        {
                            /* Seqid has to be incremented even in this case */
                            P(powner->lock);
                            powner->seqid += 1;
                            V(powner->lock);

                            powner->seqid += 1;
                            res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                            return res_OPEN4.status;
                        }

                        /* deny write access on write denied file */
                        if((pstate_found_iterate->state_data.share.
                                share_deny & OPEN4_SHARE_DENY_WRITE)
                                && (arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE))
                        {
                            /* Seqid has to be incremented even in this case */
                            P(powner->lock);
                            powner->seqid += 1;
                            V(powner->lock);

                            res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                            return res_OPEN4.status;
                        }

                    }

                }
                /*  if( pstate_found_iterate != NULL ) */
                pstate_previous_iterate = pstate_found_iterate;
            }
            while(pstate_found_iterate != NULL);

            if(pstate_found_same_owner != NULL)
            {
                pfile_state = pstate_found_same_owner;
                pfile_state->seqid += 1;

                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);

            }
            else
            {
                /* Set the state for the related file */
                /* Prepare state management structure */
                candidate_type = CACHE_INODE_STATE_SHARE;
                candidate_data.share.share_deny = arg_OPEN4.share_deny;
                candidate_data.share.share_access = arg_OPEN4.share_access;

                if(cache_inode_add_state(pentry_newfile,
                                         candidate_type,
                                         &candidate_data,
                                         powner,
                                         data->pclient,
                                         data->pcontext,
                                         &pfile_state,
                                         &cache_status) != CACHE_INODE_SUCCESS)
                {
                    /* Seqid has to be incremented even in this case */
                    P(powner->lock);
                    powner->seqid += 1;
                    V(powner->lock);

                    res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                    return res_OPEN4.status;
                }
            }

            /* Open the file */
            if(cache_inode_open_by_name(pentry_parent,
                                        &filename,
                                        pentry_newfile,
                                        data->pclient,
                                        openflags,
                                        data->pcontext,
                                        &cache_status) != CACHE_INODE_SUCCESS)
            {
                /* Seqid has to be incremented even in this case */
                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);

                res_OPEN4.status = NFS4ERR_ACCESS;
                return res_OPEN4.status;
            }
            break;

        default:
            /* Seqid has to be incremented even in this case */
            if(powner != NULL)
            {
                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);
            }

            res_OPEN4.status = NFS4ERR_INVAL;
            return res_OPEN4.status;
            break;
        }                       /* switch( arg_OPEN4.openhow.opentype ) */

        break;

    case CLAIM_PREVIOUS:
        break;

    default:
        /* Seqid has to be incremented even in this case */
        if(powner != NULL)
        {
            P(powner->lock);
            powner->seqid += 1;
            V(powner->lock);
        }

        res_OPEN4.status = NFS4ERR_INVAL;
        return res_OPEN4.status;
        break;
    }                           /*  switch(  arg_OPEN4.claim.claim ) */

    /* Now produce the filehandle to this file */
    if((pnewfsal_handle =
                cache_inode_get_fsal_handle(pentry_newfile, &cache_status)) == NULL)
    {
        res_OPEN4.status = nfs4_Errno(cache_status);
        return res_OPEN4.status;
    }

    /* Allocation of a new file handle */
    if((rc = nfs4_AllocateFH(&newfh4)) != NFS4_OK)
    {
        res_OPEN4.status = rc;
        return res_OPEN4.status;
    }

    /* Building a new fh */
    if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data))
    {
        res_OPEN4.status = NFS4ERR_SERVERFAULT;
        return res_OPEN4.status;
    }

    /* This new fh replaces the current FH */
    data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len;
    memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val, newfh4.nfs_fh4_len);

    data->current_entry = pentry_newfile;
    data->current_filetype = REGULAR_FILE;

    /* No do not need newfh any more */
    Mem_Free((char *)newfh4.nfs_fh4_val);

    /* Status of parent directory after the operation */
    if((cache_status = cache_inode_getattr(pentry_parent,
                                           &attr_parent,
                                           data->ht,
                                           data->pclient,
                                           data->pcontext,
                                           &cache_status)) != CACHE_INODE_SUCCESS)
    {
        res_OPEN4.status = nfs4_Errno(cache_status);
        return res_OPEN4.status;
    }

    res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 2;
    if((res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val =
                (uint32_t *) Mem_Alloc(res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len *
                                       sizeof(uint32_t))) == NULL)
    {
        res_OPEN4.status = NFS4ERR_SERVERFAULT;
        return res_OPEN4.status;
    }
    res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val[0] = 0;       /* No Attributes set */
    res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val[1] = 0;       /* No Attributes set */

    if(arg_OPEN4.openhow.opentype == OPEN4_CREATE)
    {
        tmp_int = 2;
        tmp_attr[0] = FATTR4_SIZE;
        tmp_attr[1] = FATTR4_MODE;
        nfs4_list_to_bitmap4(&(res_OPEN4.OPEN4res_u.resok4.attrset), &tmp_int, tmp_attr);
        res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 2;
    }

    res_OPEN4.OPEN4res_u.resok4.cinfo.after =
        (changeid4) pentry_parent->internal_md.mod_time;
    res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = TRUE;

    res_OPEN4.OPEN4res_u.resok4.stateid.seqid = powner->seqid;
    memcpy(res_OPEN4.OPEN4res_u.resok4.stateid.other, pfile_state->stateid_other, 12);

    /* No delegation */
    res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type = OPEN_DELEGATE_NONE;

    res_OPEN4.OPEN4res_u.resok4.rflags = OPEN4_RESULT_LOCKTYPE_POSIX;

    /* regular exit */
    res_OPEN4.status = NFS4_OK;
    return res_OPEN4.status;
}                               /* nfs41_op_open */
Beispiel #9
0
fsal_status_t PROXYFSAL_symlink(proxyfsal_handle_t * parent_directory_handle,   /* IN */
                                fsal_name_t * p_linkname,       /* IN */
                                fsal_path_t * p_linkcontent,    /* IN */
                                proxyfsal_op_context_t * p_context,     /* IN */
                                fsal_accessmode_t accessmode,   /* IN (ignored) */
                                proxyfsal_handle_t * link_handle,       /* OUT */
                                fsal_attrib_list_t * link_attributes    /* [ IN/OUT ] */
    )
{

  int rc;

  COMPOUND4args argnfs4;
  COMPOUND4res resnfs4;
  nfs_fh4 nfs4fh;
  bitmap4 bitmap;
  uint32_t bitmap_val[2];
  uint32_t bitmap_res[2];
  uint32_t bitmap_mkdir[2];
  uint32_t bitmap_getattr_res[2];
  uint32_t bitmap_conv_val[2];
  fattr4 input_attr;
  bitmap4 convert_bitmap;
  component4 name;
  char nameval[MAXNAMLEN];
  component4 linkname;
  char linknameval[MAXNAMLEN];
  char padfilehandle[FSAL_PROXY_FILEHANDLE_MAX_LEN];

  fsal_proxy_internal_fattr_t fattr_internal;
  fsal_attrib_list_t create_mode_attr;
  fsal_attrib_list_t attributes;

#define FSAL_SYMLINK_NB_OP_ALLOC 4
#define FSAL_SYMLINK_VAL_BUFFER  1024

  nfs_argop4 argoparray[FSAL_SYMLINK_NB_OP_ALLOC];
  nfs_resop4 resoparray[FSAL_SYMLINK_NB_OP_ALLOC];

  char fattr_val[FSAL_SYMLINK_VAL_BUFFER];
  struct timeval timeout = TIMEOUTRPC;

  /* sanity checks.
   * note : link_attributes is optional.
   */
  if(!parent_directory_handle ||
     !p_context || !link_handle || !p_linkname || !p_linkcontent)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink);

  /* Tests if symlinking is allowed by configuration. */

  if(!global_fs_info.symlink_support)
    Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_symlink);

  /* Setup results structures */
  argnfs4.argarray.argarray_val = argoparray;
  resnfs4.resarray.resarray_val = resoparray;
  argnfs4.minorversion = 0;
  /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Symlink" ; */
  argnfs4.tag.utf8string_val = NULL;
  argnfs4.tag.utf8string_len = 0;
  argnfs4.argarray.argarray_len = 0;

  input_attr.attrmask.bitmap4_val = bitmap_val;
  input_attr.attrmask.bitmap4_len = 2;

  input_attr.attr_vals.attrlist4_val = fattr_val;
  input_attr.attr_vals.attrlist4_len = FSAL_SYMLINK_VAL_BUFFER;

  fsal_internal_proxy_setup_fattr(&fattr_internal);

  convert_bitmap.bitmap4_val = bitmap_conv_val;
  convert_bitmap.bitmap4_len = 2;

  memset((char *)&name, 0, sizeof(component4));
  name.utf8string_val = nameval;
  if(fsal_internal_proxy_fsal_name_2_utf8(p_linkname, &name) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink);

  memset((char *)&linkname, 0, sizeof(component4));
  linkname.utf8string_val = linknameval;
  if(fsal_internal_proxy_fsal_path_2_utf8(p_linkcontent, &linkname) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink);

  /* Get NFSv4 File handle */
  if(fsal_internal_proxy_extract_fh(&nfs4fh, parent_directory_handle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink);

  bitmap.bitmap4_val = bitmap_mkdir;
  bitmap.bitmap4_len = 2;
  fsal_internal_proxy_create_fattr_bitmap(&bitmap);

  create_mode_attr.asked_attributes = FSAL_ATTR_MODE;
  create_mode_attr.mode = accessmode;
  fsal_interval_proxy_fsalattr2bitmap4(&create_mode_attr, &convert_bitmap);

  if(nfs4_FSALattr_To_Fattr(NULL,       /* no exportlist required here */
                            &create_mode_attr, &input_attr, NULL,       /* no compound data required here */
                            NULL,       /* No fh here, filehandle is not a settable attribute */
                            &convert_bitmap) == -1)
    Return(ERR_FSAL_INVAL, -1, INDEX_FSAL_symlink);

#define FSAL_SYMLINK_IDX_OP_PUTFH     0
#define FSAL_SYMLINK_IDX_OP_SYMLINK   1
#define FSAL_SYMLINK_IDX_OP_GETFH     2
#define FSAL_SYMLINK_IDX_OP_GETATTR   3
  COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
  COMPOUNDV4_ARG_ADD_OP_SYMLINK(argnfs4, name, linkname, input_attr);
  COMPOUNDV4_ARG_ADD_OP_GETFH(argnfs4);
  COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);

  resnfs4.resarray.resarray_val[FSAL_SYMLINK_IDX_OP_SYMLINK].nfs_resop4_u.opcreate.
      CREATE4res_u.resok4.attrset.bitmap4_val = bitmap_res;
  resnfs4.resarray.resarray_val[FSAL_SYMLINK_IDX_OP_SYMLINK].nfs_resop4_u.opcreate.
      CREATE4res_u.resok4.attrset.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_SYMLINK_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
      GETFH4res_u.resok4.object.nfs_fh4_val = (char *)padfilehandle;
  resnfs4.resarray.resarray_val[FSAL_SYMLINK_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
      GETFH4res_u.resok4.object.nfs_fh4_len = FSAL_PROXY_FILEHANDLE_MAX_LEN;

  resnfs4.resarray.resarray_val[FSAL_SYMLINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_getattr_res;
  resnfs4.resarray.resarray_val[FSAL_SYMLINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_SYMLINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
      (char *)&fattr_internal;
  resnfs4.resarray.resarray_val[FSAL_SYMLINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
      sizeof(fattr_internal);

  TakeTokenFSCall();

  /* Call the NFSv4 function */
  COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
  if(rc != RPC_SUCCESS)
    {
      ReleaseTokenFSCall();

      Return(ERR_FSAL_IO, 0, INDEX_FSAL_symlink);
    }

  ReleaseTokenFSCall();

  /* >> convert error code, and return on error << */
  if(resnfs4.status != NFS4_OK)
    return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_symlink);

  /* Use NFSv4 service function to build the FSAL_attr */
  if(nfs4_Fattr_To_FSAL_attr(&attributes,
                             &resnfs4.resarray.resarray_val[FSAL_SYMLINK_IDX_OP_GETATTR].
                             nfs_resop4_u.opgetattr.GETATTR4res_u.resok4.
                             obj_attributes) != NFS4_OK)
    {
      FSAL_CLEAR_MASK(attributes.asked_attributes);
      FSAL_SET_MASK(attributes.asked_attributes, FSAL_ATTR_RDATTR_ERR);

      Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_symlink);
    }

  if(link_attributes)
    {
      memcpy(link_attributes, &attributes, sizeof(attributes));
    }

  if(fsal_internal_proxy_create_fh
     (&
      (resnfs4.resarray.resarray_val[FSAL_SYMLINK_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
       GETFH4res_u.resok4.object), FSAL_TYPE_LNK, attributes.fileid,
      link_handle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_symlink);

  /* OK */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_symlink);
}
Beispiel #10
0
fsal_status_t PROXYFSAL_unlink(proxyfsal_handle_t * parentdir_handle,   /* IN */
                               fsal_name_t * p_object_name,     /* IN */
                               proxyfsal_op_context_t * p_context,      /* IN */
                               fsal_attrib_list_t * parentdir_attributes        /* [IN/OUT ] */
    )
{
  int rc;
  COMPOUND4args argnfs4;
  COMPOUND4res resnfs4;
  nfs_fh4 nfs4fh;
  bitmap4 bitmap;
  uint32_t bitmap_val[2];
  component4 name;
  char nameval[MAXNAMLEN];

#define FSAL_UNLINK_NB_OP_ALLOC 3
  nfs_argop4 argoparray[FSAL_UNLINK_NB_OP_ALLOC];
  nfs_resop4 resoparray[FSAL_UNLINK_NB_OP_ALLOC];
  uint32_t bitmap_res[2];

  fsal_proxy_internal_fattr_t fattr_internal;
  struct timeval timeout = TIMEOUTRPC;

  /* sanity checks.
   * note : parentdir_attributes are optional.
   *        parentdir_handle is mandatory,
   *        because, we do not allow to delete FS root !
   */
  if(!parentdir_handle || !p_context || !p_object_name)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_unlink);

  /* Setup results structures */
  argnfs4.argarray.argarray_val = argoparray;
  resnfs4.resarray.resarray_val = resoparray;
  fsal_internal_proxy_setup_fattr(&fattr_internal);
  argnfs4.minorversion = 0;
  /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Unlink" ; */
  argnfs4.tag.utf8string_val = NULL;
  argnfs4.tag.utf8string_len = 0;
  argnfs4.argarray.argarray_len = 0;

  /* >> retrieve root handle filehandle here << */
  bitmap.bitmap4_val = bitmap_val;
  bitmap.bitmap4_len = 2;

  fsal_internal_proxy_create_fattr_bitmap(&bitmap);

  if(fsal_internal_proxy_extract_fh(&nfs4fh, parentdir_handle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_unlink);

  memset((char *)&name, 0, sizeof(component4));
  name.utf8string_val = nameval;
  if(fsal_internal_proxy_fsal_name_2_utf8(p_object_name, &name) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_unlink);

#define FSAL_UNLINK_IDX_OP_PUTFH      0
#define FSAL_UNLINK_IDX_OP_REMOVE     1
#define FSAL_UNLINK_IDX_OP_GETATTR    2

  COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
  COMPOUNDV4_ARG_ADD_OP_REMOVE(argnfs4, name);
  COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);

  resnfs4.resarray.resarray_val[FSAL_UNLINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res;
  resnfs4.resarray.resarray_val[FSAL_UNLINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_UNLINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
      (char *)&fattr_internal;
  resnfs4.resarray.resarray_val[FSAL_UNLINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
      sizeof(fattr_internal);

  TakeTokenFSCall();

  /* Call the NFSv4 function */
  COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
  if(rc != RPC_SUCCESS)
    {
      ReleaseTokenFSCall();

      Return(ERR_FSAL_IO, rc, INDEX_FSAL_unlink);
    }

  ReleaseTokenFSCall();

  if(resnfs4.status != NFS4_OK)
    return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_unlink);

  /* >> get post op attributes for the parent, if they are asked,
   * and your filesystem didn't return them << */

  if(parentdir_attributes)
    {

      if(nfs4_Fattr_To_FSAL_attr(parentdir_attributes,
                                 &resnfs4.resarray.
                                 resarray_val[FSAL_UNLINK_IDX_OP_GETATTR].nfs_resop4_u.
                                 opgetattr.GETATTR4res_u.resok4.obj_attributes) != NFS4_OK)
        {
          FSAL_CLEAR_MASK(parentdir_attributes->asked_attributes);
          FSAL_SET_MASK(parentdir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);

          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_unlink);
        }

    }

  /* OK */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_unlink);

}
Beispiel #11
0
/**
 * FSAL_create:
 * Create a regular file.
 *
 * \param parent_directory_handle (input):
 *        Handle of the parent directory where the file is to be created.
 * \param p_filename (input):
 *        Pointer to the name of the file to be created.
 * \param cred (input):
 *        Authentication context for the operation (user, export...).
 * \param accessmode (input):
 *        Mode for the file to be created.
 *        (the umask defined into the FSAL configuration file
 *        will be applied on it).
 * \param object_handle (output):
 *        Pointer to the handle of the created file.
 * \param object_attributes (optionnal input/output): 
 *        The postop attributes of the created file.
 *        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).
 *        Can be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_STALE        (parent_directory_handle does not address an existing object)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *        - Other error codes can be returned :
 *          ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ...
 *            
 *        NB: if getting postop attributes failed,
 *        the function does not return an error
 *        but the FSAL_ATTR_RDATTR_ERR bit is set in
 *        the object_attributes->asked_attributes field.
 */
fsal_status_t PROXYFSAL_create(proxyfsal_handle_t * parent_directory_handle,    /* IN */
                               fsal_name_t * p_filename,        /* IN */
                               proxyfsal_op_context_t * p_context,      /* IN */
                               fsal_accessmode_t accessmode,    /* IN */
                               proxyfsal_handle_t * object_handle,      /* OUT */
                               fsal_attrib_list_t * object_attributes   /* [ IN/OUT ] */
    )
{
  int rc;
  COMPOUND4args argnfs4;
  COMPOUND4res resnfs4;
  nfs_fh4 nfs4fh;
  bitmap4 bitmap;
  uint32_t bitmap_val[2];
  uint32_t bitmap_res[2];
  uint32_t bitmap_conv_val[2];
  uint32_t bitmap_create[2];
  uint32_t bitmap_getattr_res[2];
  fattr4 input_attr;
  bitmap4 convert_bitmap;
  component4 name;
  char nameval[MAXNAMLEN];
  char padfilehandle[FSAL_PROXY_FILEHANDLE_MAX_LEN];
  fsal_status_t fsal_status;
  proxyfsal_file_t fd;

#define FSAL_CREATE_NB_OP_ALLOC 4
#define FSAL_CREATE_VAL_BUFFER  1024

  fsal_proxy_internal_fattr_t fattr_internal;
  fsal_attrib_list_t create_mode_attr;
  fsal_attrib_list_t attributes;
  nfs_argop4 argoparray[FSAL_CREATE_NB_OP_ALLOC];
  nfs_resop4 resoparray[FSAL_CREATE_NB_OP_ALLOC];
  char fattr_val[FSAL_CREATE_VAL_BUFFER];
  struct timeval timeout = { 25, 0 };
  char owner_val[FSAL_PROXY_OWNER_LEN];
  unsigned int owner_len = 0;

  /* sanity checks.
   * note : object_attributes is optional.
   */
  if(!parent_directory_handle || !p_context || !object_handle || !p_filename)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create);

  PRINT_HANDLE("FSAL_create", parent_directory_handle);

  /* Create the owner */
  snprintf(owner_val, FSAL_PROXY_OWNER_LEN, "GANESHA/PROXY: pid=%u ctx=%p file=%llu",
           getpid(), p_context, (unsigned long long int)p_context->file_counter);
  owner_len = strnlen(owner_val, FSAL_PROXY_OWNER_LEN);
  p_context->file_counter += 1;

  /* Setup results structures */
  argnfs4.argarray.argarray_val = argoparray;
  resnfs4.resarray.resarray_val = resoparray;
  argnfs4.minorversion = 0;
  /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Mkdir" ; */
  argnfs4.tag.utf8string_val = NULL;
  argnfs4.tag.utf8string_len = 0;
  argnfs4.argarray.argarray_len = 0;

  input_attr.attrmask.bitmap4_val = bitmap_val;
  input_attr.attrmask.bitmap4_len = 2;

  input_attr.attr_vals.attrlist4_val = fattr_val;
  input_attr.attr_vals.attrlist4_len = FSAL_CREATE_VAL_BUFFER;

  fsal_internal_proxy_setup_fattr(&fattr_internal);

  convert_bitmap.bitmap4_val = bitmap_conv_val;
  convert_bitmap.bitmap4_len = 2;

  memset((char *)&name, 0, sizeof(component4));
  name.utf8string_val = nameval;
  if(fsal_internal_proxy_fsal_name_2_utf8(p_filename, &name) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create);

  /* Get NFSv4 File handle */
  if(fsal_internal_proxy_extract_fh(&nfs4fh, parent_directory_handle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create);

  if(isFullDebug(COMPONENT_FSAL))
    {
      char outstr[1024];

      nfs4_sprint_fhandle(&nfs4fh, outstr);
      LogFullDebug(COMPONENT_FSAL, "FSAL_CREATE: extracted server (as client) parent handle=%s\n",
                   outstr);
    }

  bitmap.bitmap4_val = bitmap_create;
  bitmap.bitmap4_len = 2;
  fsal_internal_proxy_create_fattr_bitmap(&bitmap);

  create_mode_attr.asked_attributes = FSAL_ATTR_MODE;
  create_mode_attr.mode = accessmode;
  fsal_interval_proxy_fsalattr2bitmap4(&create_mode_attr, &convert_bitmap);

  if(nfs4_FSALattr_To_Fattr(NULL,       /* no exportlist required here */
                            &create_mode_attr, &input_attr, NULL,       /* no compound data required here */
                            NULL,       /* No fh here, filehandle is not a settable attribute */
                            &convert_bitmap) == -1)
    Return(ERR_FSAL_INVAL, -1, INDEX_FSAL_create);

#define FSAL_CREATE_IDX_OP_PUTFH       0
#define FSAL_CREATE_IDX_OP_OPEN_CREATE 1
#define FSAL_CREATE_IDX_OP_GETFH       2
#define FSAL_CREATE_IDX_OP_GETATTR     3
  COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
  COMPOUNDV4_ARG_ADD_OP_OPEN_CREATE(argnfs4, name, input_attr, p_context->clientid,
                                    owner_val, owner_len);
  COMPOUNDV4_ARG_ADD_OP_GETFH(argnfs4);
  COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);

  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.opopen.
      OPEN4res_u.resok4.attrset.bitmap4_val = bitmap_res;
  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.opopen.
      OPEN4res_u.resok4.attrset.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
      GETFH4res_u.resok4.object.nfs_fh4_val = (char *)padfilehandle;
  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
      GETFH4res_u.resok4.object.nfs_fh4_len = FSAL_PROXY_FILEHANDLE_MAX_LEN;

  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_getattr_res;
  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
      (char *)&fattr_internal;
  resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
      sizeof(fattr_internal);

  TakeTokenFSCall();

  /* Call the NFSv4 function */
  COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
  if(rc != RPC_SUCCESS)
    {
      ReleaseTokenFSCall();

      Return(ERR_FSAL_IO, rc, INDEX_FSAL_create);
    }

  ReleaseTokenFSCall();

  /* >> convert error code, and return on error << */
  if(resnfs4.status != NFS4_OK)
    return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_create);

  /* Use NFSv4 service function to build the FSAL_attr */
  if(nfs4_Fattr_To_FSAL_attr(&attributes,
                             &resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].
                             nfs_resop4_u.opgetattr.GETATTR4res_u.resok4.
                             obj_attributes) != 1)
    {
      FSAL_CLEAR_MASK(attributes.asked_attributes);
      FSAL_SET_MASK(attributes.asked_attributes, FSAL_ATTR_RDATTR_ERR);

      Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_create);

    }

  /* Return attributes if asked */
  if(object_attributes)
    {
      memcpy(object_attributes, &attributes, sizeof(attributes));
    }

  if(isFullDebug(COMPONENT_FSAL))
    {
      char outstr[1024];

      nfs4_sprint_fhandle(&nfs4fh, outstr);
      LogFullDebug(COMPONENT_FSAL, "FSAL_CREATE: extracted server (as client) created file handle=%s\n",
           outstr);
    }

  if(fsal_internal_proxy_create_fh
     (&
      (resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETFH].nfs_resop4_u.opgetfh.
       GETFH4res_u.resok4.object), FSAL_TYPE_FILE, attributes.fileid,
      object_handle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create);

  /* Keep the information into the file descriptor as well */
  memcpy((char *)&fd.fhandle, (char *)object_handle, sizeof(fd.fhandle));

  fd.openflags = FSAL_O_RDWR;
  fd.current_offset = 0;
  fd.pcontext = p_context;

  /* Keep the returned stateid for later use */
  fd.stateid.seqid =
      resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.opopen.
      OPEN4res_u.resok4.stateid.seqid;
  memcpy((char *)fd.stateid.other,
         resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.
         opopen.OPEN4res_u.resok4.stateid.other, 12);

  /* See if a OPEN_CONFIRM is required */
  if(resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.opopen.
     OPEN4res_u.resok4.rflags & OPEN4_RESULT_CONFIRM)
    {
      fsal_status = FSAL_proxy_open_confirm(&fd);
      if(FSAL_IS_ERROR(fsal_status))
        Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_create);
    }
#ifdef _FSAL_CREATE_CLOSE_FILE
  /* The craeted file is still opened, to preserve the correct seqid for later use, we close it */
  fsal_status = FSAL_close(&fd);
  if(FSAL_IS_ERROR(fsal_status))
    Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_create);
#endif

  /* OK */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_create);
}                               /* FSAL_create */
Beispiel #12
0
/**
 * FSAL_link:
 * Create a hardlink.
 *
 * \param target_handle (input):
 *        Handle of the target object.
 * \param dir_handle (input):
 *        Pointer to the directory handle where
 *        the hardlink is to be created.
 * \param p_link_name (input):
 *        Pointer to the name of the hardlink to be created.
 * \param cred (input):
 *        Authentication context for the operation (user,...).
 * \param accessmode (input):
 *        Mode for the directory to be created.
 *        (the umask defined into the FSAL configuration file
 *        will be applied on it).
 * \param attributes (optionnal input/output): 
 *        The post_operation attributes of the linked 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)
 *        - ERR_FSAL_STALE        (target_handle or dir_handle does not address an existing object)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *        - Other error codes can be returned :
 *          ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ...
 *            
 *        NB: if getting postop attributes failed,
 *        the function does not return an error
 *        but the FSAL_ATTR_RDATTR_ERR bit is set in
 *        the attributes->asked_attributes field.
 */
fsal_status_t PROXYFSAL_link(proxyfsal_handle_t * target_handle,        /* IN */
                             proxyfsal_handle_t * dir_handle,   /* IN */
                             fsal_name_t * p_link_name, /* IN */
                             proxyfsal_op_context_t * p_context,        /* IN */
                             fsal_attrib_list_t * attributes    /* [ IN/OUT ] */
    )
{
  int rc;

  COMPOUND4args argnfs4;
  COMPOUND4res resnfs4;
  nfs_fh4 nfs4fh_target;
  nfs_fh4 nfs4fh_dest;
  bitmap4 bitmap;
  uint32_t bitmap_val[2];
  uint32_t bitmap_res[2];
  component4 name;
  char nameval[MAXNAMLEN];

  fsal_proxy_internal_fattr_t fattr_internal;

  struct timeval timeout = { 25, 0 };

  /* sanity checks.
   * note : attributes is optional.
   */
  if(!target_handle || !dir_handle || !p_context || !p_link_name)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link);

  /* Tests if hardlinking is allowed by configuration. */

  if(!global_fs_info.link_support)
    Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_link);

#define FSAL_LINK_NB_OP_ALLOC 6
  nfs_argop4 argoparray[FSAL_LINK_NB_OP_ALLOC];
  nfs_resop4 resoparray[FSAL_LINK_NB_OP_ALLOC];

  /* Setup results structures */
  argnfs4.argarray.argarray_val = argoparray;
  resnfs4.resarray.resarray_val = resoparray;
  fsal_internal_proxy_setup_fattr(&fattr_internal);
  argnfs4.minorversion = 0;
  /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Link" ; */
  argnfs4.tag.utf8string_val = NULL;
  argnfs4.tag.utf8string_len = 0;
  argnfs4.argarray.argarray_len = 0;

  bitmap.bitmap4_val = bitmap_val;
  bitmap.bitmap4_len = 2;
  fsal_internal_proxy_create_fattr_bitmap(&bitmap);

  if(fsal_internal_proxy_extract_fh(&nfs4fh_target, target_handle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link);

  if(fsal_internal_proxy_extract_fh(&nfs4fh_dest, dir_handle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link);

  memset((char *)&name, 0, sizeof(component4));
  name.utf8string_val = nameval;
  if(fsal_internal_proxy_fsal_name_2_utf8(p_link_name, &name) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link);

#define FSAL_LINK_IDX_OP_PUTFH_TARGET 0
#define FSAL_LINK_IDX_OP_SAVEFH       1
#define FSAL_LINK_IDX_OP_PUTFH_DEST   2
#define FSAL_LINK_IDX_OP_LINK         3
#define FSAL_LINK_IDX_OP_RESTOREFH    4
#define FSAL_LINK_IDX_OP_GETATTR      5
  COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh_target);
  COMPOUNDV4_ARG_ADD_OP_SAVEFH(argnfs4);
  COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh_dest);
  COMPOUNDV4_ARG_ADD_OP_LINK(argnfs4, name);
  COMPOUNDV4_ARG_ADD_OP_RESTOREFH(argnfs4);
  COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);

  resnfs4.resarray.resarray_val[FSAL_LINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res;
  resnfs4.resarray.resarray_val[FSAL_LINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_LINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
      (char *)&fattr_internal;
  resnfs4.resarray.resarray_val[FSAL_LINK_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
      sizeof(fattr_internal);

  TakeTokenFSCall();

  /* Call the NFSv4 function */
  COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
  if(rc != RPC_SUCCESS)
    {
      ReleaseTokenFSCall();

      Return(ERR_FSAL_IO, rc, INDEX_FSAL_link);
    }

  ReleaseTokenFSCall();

  if(resnfs4.status != NFS4_OK)
    return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_link);

  if(attributes)
    {
      /* Use NFSv4 service function to build the FSAL_attr */
      if(nfs4_Fattr_To_FSAL_attr(attributes,
                                 &resnfs4.resarray.
                                 resarray_val[FSAL_LINK_IDX_OP_GETATTR].nfs_resop4_u.
                                 opgetattr.GETATTR4res_u.resok4.obj_attributes) != 1)
        {
          FSAL_CLEAR_MASK(attributes->asked_attributes);
          FSAL_SET_MASK(attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);

          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_link);
        }
    }

  /* OK */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link);

}
Beispiel #13
0
fsal_status_t PROXYFSAL_truncate(fsal_handle_t * file_hdl,       /* IN */
                                 fsal_op_context_t * context,    /* IN */
                                 fsal_size_t length,    /* IN */
                                 fsal_file_t * file_descriptor, /* [IN|OUT] */
                                 fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */
    )
{

  int rc;

  COMPOUND4args argnfs4;
  COMPOUND4res resnfs4;
  nfs_fh4 nfs4fh;
  uint64_t fileid;
  fsal_status_t fsal_status;
  fsal_attrib_list_t open_attrs;
  bitmap4 inbitmap;
  bitmap4 convert_bitmap;
  uint32_t inbitmap_val[2];
  uint32_t bitmap_res[2];
  uint32_t bitmap_set[2];
  uint32_t bitmap_conv_val[2];
  proxyfsal_handle_t * filehandle = (proxyfsal_handle_t *)file_hdl;
  proxyfsal_op_context_t * p_context = (proxyfsal_op_context_t *)context;

#define FSAL_TRUNCATE_NB_OP_ALLOC 3
  nfs_argop4 argoparray[FSAL_TRUNCATE_NB_OP_ALLOC];
  nfs_resop4 resoparray[FSAL_TRUNCATE_NB_OP_ALLOC];

  fsal_attrib_list_t fsal_attr_set;
  fattr4 fattr_set;
  fsal_proxy_internal_fattr_t fattr_internal;
  struct timeval timeout = TIMEOUTRPC;

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

  if(filehandle->data.object_type_reminder != FSAL_TYPE_FILE)
    {
      Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_truncate);
    }

  if(file_descriptor == NULL)
    {
      /* Use the stateless version */
      fsal_status = FSAL_proxy_truncate_stateless(file_hdl,
                                                  context, length, object_attributes);
      Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_truncate);
    }

  /* First, we need to get the fileid on a filehandle base */
  fsal_status = FSAL_DigestHandle(context->export_context,
                                  FSAL_DIGEST_FILEID4, file_hdl, (caddr_t) & fileid);
  if(FSAL_IS_ERROR(fsal_status))
    {
      Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_truncate);
    }

  /* Then we have of open the file by fileid */
  open_attrs.asked_attributes = FSAL_ATTRS_POSIX;
  fsal_status = FSAL_open_by_fileid(file_hdl,
                                    fileid,
                                    context, FSAL_O_RDWR, file_descriptor, &open_attrs);
  if(FSAL_IS_ERROR(fsal_status))
    {
      Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_truncate);
    }

  /* Setup results structures */
  argnfs4.argarray.argarray_val = argoparray;
  resnfs4.resarray.resarray_val = resoparray;
  fsal_internal_proxy_setup_fattr(&fattr_internal);
  argnfs4.minorversion = 0;
  /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Truncate" ; */
  argnfs4.tag.utf8string_val = NULL;
  argnfs4.tag.utf8string_len = 0;
  argnfs4.argarray.argarray_len = 0;

  /* Get NFSv4 File handle */
  if(fsal_internal_proxy_extract_fh(&nfs4fh, file_hdl) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_truncate);

  /* Get prepared for truncate */
  fsal_attr_set.asked_attributes = FSAL_ATTR_SIZE;
  fsal_attr_set.filesize = length;

  convert_bitmap.bitmap4_val = bitmap_conv_val;
  convert_bitmap.bitmap4_len = 2;

  fsal_interval_proxy_fsalattr2bitmap4(&fsal_attr_set, &convert_bitmap);

  if(nfs4_FSALattr_To_Fattr(NULL,       /* no exportlist required here */
                            &fsal_attr_set, &fattr_set, NULL,   /* no compound data required here */
                            NULL,       /* No fh here, filehandle is not a settable attribute */
                            &convert_bitmap) == -1)
    Return(ERR_FSAL_INVAL, -1, INDEX_FSAL_truncate);

  inbitmap.bitmap4_val = inbitmap_val;
  inbitmap.bitmap4_len = 2;
  fsal_internal_proxy_create_fattr_bitmap(&inbitmap);

#define FSAL_TRUNCATE_IDX_OP_PUTFH     0
#define FSAL_TRUNCATE_IDX_OP_SETATTR   1
#define FSAL_TRUNCATE_IDX_OP_GETATTR   2
  COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
  COMPOUNDV4_ARG_ADD_OP_SETATTR(argnfs4, fattr_set);
  COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, inbitmap);

  /* For ATTR_SIZE, stateid is needed */
  argnfs4.argarray.argarray_val[FSAL_TRUNCATE_IDX_OP_SETATTR].nfs_argop4_u.opsetattr.
      stateid.seqid = ((proxyfsal_file_t *)file_descriptor)->stateid.seqid;
  memcpy(argnfs4.argarray.argarray_val[FSAL_TRUNCATE_IDX_OP_SETATTR].nfs_argop4_u.
         opsetattr.stateid.other, ((proxyfsal_file_t *)file_descriptor)->stateid.other, 12);

  resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res;
  resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
      (char *)&fattr_internal;
  resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
      sizeof(fattr_internal);

  resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_SETATTR].nfs_resop4_u.opsetattr.
      attrsset.bitmap4_val = bitmap_set;
  resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_SETATTR].nfs_resop4_u.opsetattr.
      attrsset.bitmap4_len = 2;

  TakeTokenFSCall();

  COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
  if(rc != RPC_SUCCESS)
    {
      ReleaseTokenFSCall();

      Return(ERR_FSAL_IO, 0, INDEX_FSAL_truncate);
    }

  ReleaseTokenFSCall();

  if(resnfs4.status != NFS4_OK)
    return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_truncate);

  /* >> interpret error code << */

  /* >> Optionnaly retrieve post op attributes
   * If your filesystem truncate call can't return them,
   * you can proceed like this : <<
   */
  if(object_attributes)
    {
      if(nfs4_Fattr_To_FSAL_attr(object_attributes,
                                 &resnfs4.resarray.
                                 resarray_val[FSAL_TRUNCATE_IDX_OP_GETATTR].nfs_resop4_u.
                                 opgetattr.GETATTR4res_u.resok4.obj_attributes) != NFS4_OK)
        {
          FSAL_CLEAR_MASK(object_attributes->asked_attributes);
          FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);

          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_truncate);
        }

    }

  /* Close the previously opened filedescriptor */
  fsal_status = FSAL_close_by_fileid(file_descriptor, fileid);
  if(FSAL_IS_ERROR(fsal_status))
    {
      Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_truncate);
    }

  /* No error occured */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_truncate);
}
Beispiel #14
0
/**
 * PROXYFSAL_access :
 * Tests whether the user or entity identified by the p_context structure
 * can access the object identified by object_handle,
 * as indicated by the access_type parameter.
 *
 * \param object_handle (input):
 *        The handle of the object to test permissions on.
 * \param p_context (input):
 *        Authentication context for the operation (export entry, user,...).
 * \param access_type (input):
 *        Indicates the permissions to be tested.
 *        This is an inclusive OR of the permissions
 *        to be checked for the user specified by p_context.
 *        Permissions constants are :
 *        - FSAL_R_OK : test for read permission
 *        - FSAL_W_OK : test for write permission
 *        - FSAL_X_OK : test for exec permission
 *        - FSAL_F_OK : test for file existence
 * \param object_attributes (optional 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).
 *        Can be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error, asked permission is granted)
 *        - ERR_FSAL_ACCESS       (object permissions doesn't fit asked access type)
 *        - ERR_FSAL_STALE        (object_handle does not address an existing object)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *        - Other error codes when something anormal occurs.
 */
fsal_status_t PROXYFSAL_access(fsal_handle_t * object_handle,      /* IN */
                               fsal_op_context_t *context,      /* IN */
                               fsal_accessflags_t access_type,  /* IN */
                               fsal_attrib_list_t * object_attributes   /* [ IN/OUT ] */
    )
{

  int rc;
  COMPOUND4args argnfs4;
  COMPOUND4res resnfs4;
  bitmap4 bitmap;
  uint32_t bitmap_val[2];
  uint32_t bitmap_res[2];
  uint32_t accessflag = 0;
  proxyfsal_op_context_t * p_context = (proxyfsal_op_context_t *)context;

  fsal_proxy_internal_fattr_t fattr_internal;

  struct timeval __attribute__ ((__unused__)) timeout = TIMEOUTRPC;
  nfs_fh4 nfs4fh;

#define FSAL_ACCESS_NB_OP_ACCESS 3

  nfs_argop4 argoparray[FSAL_ACCESS_NB_OP_ACCESS];
  nfs_resop4 resoparray[FSAL_ACCESS_NB_OP_ACCESS];

  /* sanity checks.
   * note : object_attributes is optional in PROXYFSAL_access.
   */
  if(!object_handle || !p_context)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_access);

  /* Setup results structures */
  argnfs4.argarray.argarray_val = argoparray;
  resnfs4.resarray.resarray_val = resoparray;
  fsal_internal_proxy_setup_fattr(&fattr_internal);
  argnfs4.minorversion = 0;
  /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Access" ; */
  argnfs4.tag.utf8string_val = NULL;
  argnfs4.tag.utf8string_len = 0;
  argnfs4.argarray.argarray_len = 0;

  bitmap.bitmap4_val = bitmap_val;
  bitmap.bitmap4_len = 2;
  fsal_internal_proxy_create_fattr_bitmap(&bitmap);

  /* Set up access flags */
  if(access_type & FSAL_R_OK)
    accessflag |= ACCESS4_READ;

  if(access_type & FSAL_X_OK)
    accessflag |= ACCESS4_LOOKUP;

  if(access_type & FSAL_W_OK)
    accessflag |= (ACCESS4_MODIFY & ACCESS4_EXTEND);

  if(access_type & FSAL_F_OK)
    accessflag |= ACCESS4_LOOKUP;

  /* >> convert your fsal access type to your FS access type << */

  /* Get NFSv4 File handle */
  if(fsal_internal_proxy_extract_fh(&nfs4fh, object_handle) == FALSE)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_access);

#define FSAL_ACCESS_IDX_OP_PUTFH    0
#define FSAL_ACCESS_IDX_OP_ACCESS   1
#define FSAL_ACCESS_IDX_OP_GETATTR  2

  COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh);
  COMPOUNDV4_ARG_ADD_OP_ACCESS(argnfs4, accessflag);
  COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap);

  resnfs4.resarray.resarray_val[FSAL_ACCESS_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res;
  resnfs4.resarray.resarray_val[FSAL_ACCESS_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2;

  resnfs4.resarray.resarray_val[FSAL_ACCESS_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val =
      (char *)&fattr_internal;
  resnfs4.resarray.resarray_val[FSAL_ACCESS_IDX_OP_GETATTR].nfs_resop4_u.opgetattr.
      GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len =
      sizeof(fattr_internal);

  TakeTokenFSCall();

  /* Call the NFSv4 function */
  COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
  if(rc != RPC_SUCCESS)
    {
      ReleaseTokenFSCall();

      Return(ERR_FSAL_IO, resnfs4.status, INDEX_FSAL_access);
    }

  ReleaseTokenFSCall();

  /* >> convert the returned code, an return it on error << */
  if(resnfs4.status != NFS4_OK)
    return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_access);

  /* get attributes if object_attributes is not null.
   * If an error occures during getattr operation,
   * an error bit is set in the output structure.
   */
  if(object_attributes)
    {
      /* Use NFSv4 service function to build the FSAL_attr */
      if(nfs4_Fattr_To_FSAL_attr(object_attributes,
                                 &resnfs4.resarray.
                                 resarray_val[FSAL_ACCESS_IDX_OP_GETATTR].nfs_resop4_u.
                                 opgetattr.GETATTR4res_u.resok4.obj_attributes) != NFS4_OK)
        {
          FSAL_CLEAR_MASK(object_attributes->asked_attributes);
          FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);

          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_access);
        }

    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_access);

}