static NTSTATUS smb_file_rename_information(connection_struct *conn,
					    struct smb_request *req,
					    const char *pdata,
					    int total_data,
					    files_struct *fsp,
					    struct smb_filename *smb_fname_src)
{
	bool overwrite;
	uint32 root_fid;
	uint32 len;
	char *newname = NULL;
	struct smb_filename *smb_fname_dst = NULL;
	bool dest_has_wcard = False;
	NTSTATUS status = NT_STATUS_OK;
	char *p;
	TALLOC_CTX *ctx = talloc_tos();

	if (total_data < 13) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	overwrite = (CVAL(pdata,0) ? True : False);
	root_fid = IVAL(pdata,4);
	len = IVAL(pdata,8);

	if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
			      len, 0, &status,
			      &dest_has_wcard);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	DEBUG(10,("smb_file_rename_information: got name |%s|\n",
				newname));

	status = resolve_dfspath_wcard(ctx, conn,
				       req->flags2 & FLAGS2_DFS_PATHNAMES,
				       newname,
				       &newname,
				       &dest_has_wcard);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	/* Check the new name has no '/' characters. */
	if (strchr_m(newname, '/')) {
		return NT_STATUS_NOT_SUPPORTED;
	}

	if (fsp && fsp->base_fsp) {
		/* newname must be a stream name. */
		if (newname[0] != ':') {
			return NT_STATUS_NOT_SUPPORTED;
		}

		/* Create an smb_fname to call rename_internals_fsp() with. */
		status = create_synthetic_smb_fname(talloc_tos(),
		    fsp->base_fsp->fsp_name->base_name, newname, NULL,
		    &smb_fname_dst);
		if (!NT_STATUS_IS_OK(status)) {
			goto out;
		}

		/*
		 * Set the original last component, since
		 * rename_internals_fsp() requires it.
		 */
		smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
							      newname);
		if (smb_fname_dst->original_lcomp == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto out;
		}

	} else {
		/*
		 * Build up an smb_fname_dst based on the filename passed in.
		 * We basically just strip off the last component, and put on
		 * the newname instead.
		 */
		char *base_name = NULL;

		/* newname must *not* be a stream name. */
		if (newname[0] == ':') {
			return NT_STATUS_NOT_SUPPORTED;
		}

		/*
		 * Strip off the last component (filename) of the path passed
		 * in.
		 */
		base_name = talloc_strdup(ctx, smb_fname_src->base_name);
		if (!base_name) {
			return NT_STATUS_NO_MEMORY;
		}
		p = strrchr_m(base_name, '/');
		if (p) {
			p[1] = '\0';
		} else {
			base_name = talloc_strdup(ctx, "./");
			if (!base_name) {
				return NT_STATUS_NO_MEMORY;
			}
		}
		/* Append the new name. */
		base_name = talloc_asprintf_append(base_name,
				"%s",
				newname);
		if (!base_name) {
			return NT_STATUS_NO_MEMORY;
		}

		status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
				      (UCF_SAVE_LCOMP |
					  (dest_has_wcard ?
					      UCF_ALWAYS_ALLOW_WCARD_LCOMP :
					      0)));

		/* If an error we expect this to be
		 * NT_STATUS_OBJECT_PATH_NOT_FOUND */

		if (!NT_STATUS_IS_OK(status)) {
			if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
					    status)) {
				goto out;
			}
			/* Create an smb_fname to call rename_internals_fsp() */
			status = create_synthetic_smb_fname(ctx,
							    base_name, NULL,
							    NULL,
							    &smb_fname_dst);
			if (!NT_STATUS_IS_OK(status)) {
				goto out;
			}
		}
	}

	if (fsp) {
		DEBUG(10,("smb_file_rename_information: "
			  "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
			  fsp->fnum, fsp_str_dbg(fsp),
			  smb_fname_str_dbg(smb_fname_dst)));
		status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
					      overwrite);
	} else {
		DEBUG(10,("smb_file_rename_information: "
			  "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
			  smb_fname_str_dbg(smb_fname_src),
			  smb_fname_str_dbg(smb_fname_dst)));
		status = rename_internals(ctx, conn, req, smb_fname_src,
					  smb_fname_dst, 0, overwrite, false,
					  dest_has_wcard,
					  FILE_WRITE_ATTRIBUTES);
	}
 out:
	TALLOC_FREE(smb_fname_dst);
	return status;
}
static NTSTATUS smb_file_rename_information(connection_struct *conn,
					    struct smb_request *req,
					    const char *pdata,
					    int total_data,
					    files_struct *fsp,
					    struct smb_filename *smb_fname_src)
{
	bool overwrite;
	uint32 root_fid;
	uint32 len;
	char *newname = NULL;
	struct smb_filename *smb_fname_dst = NULL;
	bool dest_has_wcard = False;
	NTSTATUS status = NT_STATUS_OK;
	char *p;
	TALLOC_CTX *ctx = talloc_tos();

	if (total_data < 13) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	overwrite = (CVAL(pdata,0) ? True : False);
	root_fid = IVAL(pdata,4);
	len = IVAL(pdata,8);

	if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
			      len, 0, &status,
			      &dest_has_wcard);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	DEBUG(10,("smb_file_rename_information: got name |%s|\n",
				newname));

	status = resolve_dfspath_wcard(ctx, conn,
				       req->flags2 & FLAGS2_DFS_PATHNAMES,
				       newname,
				       &newname,
				       &dest_has_wcard);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	 
	if (strchr_m(newname, '/')) {
		return NT_STATUS_NOT_SUPPORTED;
	}

	if (fsp && fsp->base_fsp) {
		 
		if (newname[0] != ':') {
			return NT_STATUS_NOT_SUPPORTED;
		}

		 
		status = create_synthetic_smb_fname(talloc_tos(),
		    fsp->base_fsp->fsp_name->base_name, newname, NULL,
		    &smb_fname_dst);
		if (!NT_STATUS_IS_OK(status)) {
			goto out;
		}

		 
		smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
							      newname);
		if (smb_fname_dst->original_lcomp == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto out;
		}

	} else {
		 
		char *base_name = NULL;

		 
		if (newname[0] == ':') {
			return NT_STATUS_NOT_SUPPORTED;
		}

		 
		base_name = talloc_strdup(ctx, smb_fname_src->base_name);
		if (!base_name) {
			return NT_STATUS_NO_MEMORY;
		}
		p = strrchr_m(base_name, '/');
		if (p) {
			p[1] = '\0';
		} else {
			base_name = talloc_strdup(ctx, "./");
			if (!base_name) {
				return NT_STATUS_NO_MEMORY;
			}
		}
		 
		base_name = talloc_asprintf_append(base_name,
				"%s",
				newname);
		if (!base_name) {
			return NT_STATUS_NO_MEMORY;
		}

		status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
				      (UCF_SAVE_LCOMP |
					  (dest_has_wcard ?
					      UCF_ALWAYS_ALLOW_WCARD_LCOMP :
					      0)));

		 

		if (!NT_STATUS_IS_OK(status)) {
			if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
					    status)) {
				goto out;
			}
			 
			status = create_synthetic_smb_fname(ctx,
							    base_name, NULL,
							    NULL,
							    &smb_fname_dst);
			if (!NT_STATUS_IS_OK(status)) {
				goto out;
			}
		}
	}

	if (fsp) {
		DEBUG(10,("smb_file_rename_information: "
			  "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
			  fsp->fnum, fsp_str_dbg(fsp),
			  smb_fname_str_dbg(smb_fname_dst)));
		status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
					      overwrite);
	} else {
		DEBUG(10,("smb_file_rename_information: "
			  "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
			  smb_fname_str_dbg(smb_fname_src),
			  smb_fname_str_dbg(smb_fname_dst)));
		status = rename_internals(ctx, conn, req, smb_fname_src,
					  smb_fname_dst, 0, overwrite, false,
					  dest_has_wcard,
					  FILE_WRITE_ATTRIBUTES);
	}
 out:
	TALLOC_FREE(smb_fname_dst);
	return status;
}