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 */
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 */