int nfs4_op_link(struct nfs_argop4 *op, compound_data_t *data, struct nfs_resop4 *resp) { LINK4args * const arg_LINK4 = &op->nfs_argop4_u.oplink; LINK4res * const res_LINK4 = &resp->nfs_resop4_u.oplink; cache_entry_t *dir_entry = NULL; cache_entry_t *file_entry = NULL; cache_inode_status_t cache_status = CACHE_INODE_SUCCESS; char *newname = NULL; resp->resop = NFS4_OP_LINK; res_LINK4->status = NFS4_OK; /* Do basic checks on a filehandle */ res_LINK4->status = nfs4_sanity_check_FH(data, DIRECTORY, false); if (res_LINK4->status != NFS4_OK) goto out; res_LINK4->status = nfs4_sanity_check_saved_FH(data, -DIRECTORY, false); if (res_LINK4->status != NFS4_OK) goto out; /* * This operation creates a hard link, for the file * represented by the saved FH, in directory represented by * currentFH under the name arg_LINK4.target */ /* Validate and convert the UFT8 objname to a regular string */ res_LINK4->status = nfs4_utf8string2dynamic(&arg_LINK4->newname, UTF8_SCAN_ALL, &newname); if (res_LINK4->status != NFS4_OK) goto out; /* get info from compound data */ dir_entry = data->current_entry; res_LINK4->LINK4res_u.resok4.cinfo.before = cache_inode_get_changeid4(dir_entry); file_entry = data->saved_entry; /* make the link */ cache_status = cache_inode_link(file_entry, dir_entry, newname); if (cache_status != CACHE_INODE_SUCCESS) { res_LINK4->status = nfs4_Errno(cache_status); goto out; } res_LINK4->LINK4res_u.resok4.cinfo.after = cache_inode_get_changeid4(dir_entry); res_LINK4->LINK4res_u.resok4.cinfo.atomic = FALSE; res_LINK4->status = NFS4_OK; out: if (newname) gsh_free(newname); return res_LINK4->status; } /* nfs4_op_link */
int nfs4_op_restorefh(struct nfs_argop4 *op, compound_data_t *data, struct nfs_resop4 *resp) { RESTOREFH4res * const res_RESTOREFH = &resp->nfs_resop4_u.oprestorefh; /* First of all, set the reply to zero to make sure it contains no parasite information */ memset(resp, 0, sizeof(struct nfs_resop4)); resp->resop = NFS4_OP_RESTOREFH; res_RESTOREFH->status = NFS4_OK; LogFullDebugOpaque(COMPONENT_FILEHANDLE, "Saved FH %s", LEN_FH_STR, data->savedFH.nfs_fh4_val, data->savedFH.nfs_fh4_len); /* If there is no savedFH, then return an error */ if (nfs4_Is_Fh_Empty(&(data->savedFH)) == NFS4ERR_NOFILEHANDLE) { /* There is no current FH, return NFS4ERR_RESTOREFH * (cg RFC3530, page 202) */ res_RESTOREFH->status = NFS4ERR_RESTOREFH; return res_RESTOREFH->status; } /* Do basic checks on saved filehandle */ res_RESTOREFH->status = nfs4_sanity_check_saved_FH(data, NO_FILE_TYPE, true); if (res_RESTOREFH->status != NFS4_OK) return res_RESTOREFH->status; /* Determine if we can get a new export reference. If there is * no saved export, don't get a reference to it. */ if (data->saved_export != NULL) { if (!export_ready(data->saved_export)) { /* The SavedFH export has gone bad. */ res_RESTOREFH->status = NFS4ERR_STALE; return res_RESTOREFH->status; } get_gsh_export_ref(data->saved_export); } /* Copy the data from saved FH to current FH */ memcpy(data->currentFH.nfs_fh4_val, data->savedFH.nfs_fh4_val, data->savedFH.nfs_fh4_len); data->currentFH.nfs_fh4_len = data->savedFH.nfs_fh4_len; if (op_ctx->ctx_export != NULL) put_gsh_export(op_ctx->ctx_export); /* Restore the export information */ op_ctx->ctx_export = data->saved_export; if (op_ctx->ctx_export != NULL) op_ctx->fsal_export = op_ctx->ctx_export->fsal_export; *op_ctx->export_perms = data->saved_export_perms; /* No need to call nfs4_SetCompoundExport or nfs4_MakeCred * because we are restoring saved information, and the * credential checking may be skipped. */ /* Update the current entry */ set_current_entry(data, data->saved_obj); /* Restore the saved stateid */ data->current_stateid = data->saved_stateid; data->current_stateid_valid = data->saved_stateid_valid; /* Make RESTOREFH work right for DS handle */ if (data->current_ds != NULL) { data->current_ds = data->saved_ds; data->current_filetype = data->saved_filetype; ds_handle_get_ref(data->current_ds); } if (isFullDebug(COMPONENT_NFS_V4)) { char str[LEN_FH_STR]; sprint_fhandle4(str, &data->currentFH); LogFullDebug(COMPONENT_NFS_V4, "RESTORE FH: Current FH %s", str); } return NFS4_OK; } /* nfs4_op_restorefh */