int nfs4_op_remove(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
{
  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_remove";

  cache_entry_t        * parent_entry = NULL;
  fsal_attrib_list_t     attr_parent;
  fsal_name_t            name;
  cache_inode_status_t   cache_status;

  resp->resop = NFS4_OP_REMOVE;
  res_REMOVE4.status = NFS4_OK;

  /*
   * Do basic checks on a filehandle
   * Delete arg_REMOVE4.target in directory pointed by currentFH
   * Make sure the currentFH is pointed a directory
   */
  res_REMOVE4.status = nfs4_sanity_check_FH(data, DIRECTORY);
  if(res_REMOVE4.status != NFS4_OK)
    return res_REMOVE4.status;

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

  if (nfs_in_grace())
    {
      res_REMOVE4.status = NFS4ERR_GRACE;
      return res_REMOVE4.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_remove_xattr(op, data, resp);

  /* Get the parent entry (aka the current one in the compound data) */
  parent_entry = data->current_entry;

  /* We have to keep track of the 'change' file attribute for reply structure */
  memset(&(res_REMOVE4.REMOVE4res_u.resok4.cinfo.before), 0, sizeof(changeid4));
  res_REMOVE4.REMOVE4res_u.resok4.cinfo.before =
       cache_inode_get_changeid4(parent_entry);

  /* Check for name length */
  if(arg_REMOVE4.target.utf8string_len > FSAL_MAX_NAME_LEN)
    {
      res_REMOVE4.status = NFS4ERR_NAMETOOLONG;
      return res_REMOVE4.status;
    }

  /* get the filename from the argument, it should not be empty */
  if(arg_REMOVE4.target.utf8string_len == 0)
    {
      res_REMOVE4.status = NFS4ERR_INVAL;
      return res_REMOVE4.status;
    }

  /* NFS4_OP_REMOVE can delete files as well as directory, it replaces NFS3_RMDIR and NFS3_REMOVE
   * because of this, we have to know if object is a directory or not */
  if((cache_status =
      cache_inode_error_convert(FSAL_buffdesc2name
                                ((fsal_buffdesc_t *) & arg_REMOVE4.target,
                                 &name))) != CACHE_INODE_SUCCESS)
    {
      res_REMOVE4.status = nfs4_Errno(cache_status);
      return res_REMOVE4.status;
    }

  /* Test RM7: remiving '.' should return NFS4ERR_BADNAME */
  if(!FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT)
     || !FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT_DOT))
    {
      res_REMOVE4.status = NFS4ERR_BADNAME;
      return res_REMOVE4.status;
    }

  if((cache_status = cache_inode_remove(parent_entry,
                                        &name,
                                        &attr_parent,
                                        data->pcontext,
                                        &cache_status)) != CACHE_INODE_SUCCESS)
    {
      res_REMOVE4.status = nfs4_Errno(cache_status);
      return res_REMOVE4.status;
    }

  res_REMOVE4.REMOVE4res_u.resok4.cinfo.after
       = cache_inode_get_changeid4(parent_entry);

  /* Operation was not atomic .... */
  res_REMOVE4.REMOVE4res_u.resok4.cinfo.atomic = FALSE;

  /* If you reach this point, everything was ok */

  res_REMOVE4.status = NFS4_OK;

  return NFS4_OK;
}                               /* nfs4_op_remove */
Example #2
0
int nfs4_op_remove(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
{
  cache_entry_t *parent_entry = NULL;

  fsal_attrib_list_t attr_parent;
  fsal_name_t name;

  cache_inode_status_t cache_status;
#ifdef _USE_PNFS
  pnfs_file_t pnfs_file;
#endif

  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_remove";

  resp->resop = NFS4_OP_REMOVE;
  res_REMOVE4.status = NFS4_OK;

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

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

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

  /* Pseudo Fs is explictely a Read-Only File system */
  if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
    {
      res_REMOVE4.status = NFS4ERR_ROFS;
      return res_REMOVE4.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_remove_xattr(op, data, resp);

  /* Get the parent entry (aka the current one in the compound data) */
  parent_entry = data->current_entry;

  /* We have to keep track of the 'change' file attribute for reply structure */
  memset(&(res_REMOVE4.REMOVE4res_u.resok4.cinfo.before), 0, sizeof(changeid4));
  res_REMOVE4.REMOVE4res_u.resok4.cinfo.before =
      (changeid4) parent_entry->internal_md.mod_time;

  /* The operation delete object named arg_REMOVE4.target in directory pointed bt cuurentFH */
  /* Make sur the currentFH is pointed a directory */
  if(data->current_filetype != DIR_BEGINNING && data->current_filetype != DIR_CONTINUE)
    {
      res_REMOVE4.status = NFS4ERR_NOTDIR;
      return res_REMOVE4.status;
    }

  /* Check for name length */
  if(arg_REMOVE4.target.utf8string_len > FSAL_MAX_NAME_LEN)
    {
      res_REMOVE4.status = NFS4ERR_NAMETOOLONG;
      return res_REMOVE4.status;
    }

  /* get the filename from the argument, it should not be empty */
  if(arg_REMOVE4.target.utf8string_len == 0)
    {
      res_REMOVE4.status = NFS4ERR_INVAL;
      return res_REMOVE4.status;
    }

  /* NFS4_OP_REMOVE can delete files as well as directory, it replaces NFS3_RMDIR and NFS3_REMOVE
   * because of this, we have to know if object is a directory or not */
  if((cache_status =
      cache_inode_error_convert(FSAL_buffdesc2name
                                ((fsal_buffdesc_t *) & arg_REMOVE4.target,
                                 &name))) != CACHE_INODE_SUCCESS)
    {
      res_REMOVE4.status = nfs4_Errno(cache_status);
      return res_REMOVE4.status;
    }

  /* Test RM7: remiving '.' should return NFS4ERR_BADNAME */
  if(!FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT)
     || !FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT_DOT))
    {
      res_REMOVE4.status = NFS4ERR_BADNAME;
      return res_REMOVE4.status;
    }

  if((cache_status = cache_inode_remove(parent_entry,
                                        &name,
                                        &attr_parent,
                                        data->ht,
                                        data->pclient,
                                        data->pcontext,
                                        &cache_status)) != CACHE_INODE_SUCCESS)
    {
      res_REMOVE4.status = nfs4_Errno(cache_status);
      return res_REMOVE4.status;
    }

  /* We have to keep track of the 'change' file attribute for reply structure */
  memset(&(res_REMOVE4.REMOVE4res_u.resok4.cinfo.before), 0, sizeof(changeid4));
  res_REMOVE4.REMOVE4res_u.resok4.cinfo.after =
      (changeid4) parent_entry->internal_md.mod_time;

  /* Operation was not atomic .... */
  res_REMOVE4.REMOVE4res_u.resok4.cinfo.atomic = TRUE;

  /* If you reach this point, everything was ok */

  res_REMOVE4.status = NFS4_OK;

  return NFS4_OK;
}                               /* nfs4_op_remove */
int nfs4_op_remove(struct nfs_argop4 *op,
                   compound_data_t *data,
                   struct nfs_resop4 *resp)
{
  REMOVE4args *const arg_REMOVE4 = &op->nfs_argop4_u.opremove;
  REMOVE4res *const res_REMOVE4 = &resp->nfs_resop4_u.opremove;
  cache_entry_t        * parent_entry = NULL;
  char                 * name = NULL;
  cache_inode_status_t   cache_status = CACHE_INODE_SUCCESS;

  resp->resop = NFS4_OP_REMOVE;
  res_REMOVE4->status = NFS4_OK;

  /*
   * Do basic checks on a filehandle
   * Delete arg_REMOVE4.target in directory pointed by currentFH
   * Make sure the currentFH is pointed a directory
   */
  res_REMOVE4->status = nfs4_sanity_check_FH(data, DIRECTORY, false);
  if(res_REMOVE4->status != NFS4_OK)
    goto out;

  /* Validate and convert the UFT8 target to a regular string */
  res_REMOVE4->status = nfs4_utf8string2dynamic(&arg_REMOVE4->target,
						UTF8_SCAN_ALL,
						&name);
  if (res_REMOVE4->status != NFS4_OK) {
      goto out;
  }

  if (nfs_in_grace())
    {
      res_REMOVE4->status = NFS4ERR_GRACE;
      goto out;
    }

  /* If Filehandle points to a xattr object, manage it via the xattrs specific functions */
  if(nfs4_Is_Fh_Xattr(&(data->currentFH)))
    {
      res_REMOVE4->status = nfs4_op_remove_xattr(op, data, resp);
      goto out;
    }

  /* Get the parent entry (aka the current one in the compound data) */
  parent_entry = data->current_entry;

  /* We have to keep track of the 'change' file attribute for reply structure */
  memset(&(res_REMOVE4->REMOVE4res_u.resok4.cinfo.before),
	 0, sizeof(changeid4));
  res_REMOVE4->REMOVE4res_u.resok4.cinfo.before =
       cache_inode_get_changeid4(parent_entry);


  cache_status = cache_inode_remove(parent_entry,
				    name,
				    data->req_ctx);
  if (cache_status != CACHE_INODE_SUCCESS)
    {
      res_REMOVE4->status = nfs4_Errno(cache_status);
      goto out;
    }

  res_REMOVE4->REMOVE4res_u.resok4.cinfo.after
       = cache_inode_get_changeid4(parent_entry);

  /* Operation was not atomic .... */
  res_REMOVE4->REMOVE4res_u.resok4.cinfo.atomic = FALSE;

  /* If you reach this point, everything was ok */

  res_REMOVE4->status = NFS4_OK;

 out:

  if (name) {
    gsh_free(name);
    name = NULL;
  }

  return res_REMOVE4->status;
}                               /* nfs4_op_remove */