+
+/**
+ * Go through all the steps to validate a filename.
+ *
+ * @param ctx talloc_ctx to allocate memory with.
+ * @param conn connection struct for vfs calls.
+ * @param dfs_path Whether this path requires dfs resolution.
+ * @param name_in The unconverted name.
+ * @param ucf_flags flags to pass through to unix_convert().
+ * UCF_ALWAYS_ALLOW_WCARD_LCOMP will be OR'd in if
+ * p_cont_wcard != NULL and is true and
+ * UCF_COND_ALLOW_WCARD_LCOMP.
+ * @param p_cont_wcard If not NULL, will be set to true if the dfs path
+ * resolution detects a wildcard.
+ * @param pp_smb_fname The final converted name will be allocated if the
+ * return is NT_STATUS_OK.
+ *
+ * @return NT_STATUS_OK if all operations completed succesfully, appropriate
+ * error otherwise.
+ */
+NTSTATUS filename_convert(TALLOC_CTX *ctx,
+ connection_struct *conn,
+ bool dfs_path,
+ const char *name_in,
+ uint32_t ucf_flags,
+ bool *ppath_contains_wcard,
+ struct smb_filename **pp_smb_fname)
+{
+ NTSTATUS status;
+ char *fname = NULL;
+
+ *pp_smb_fname = NULL;
+
+ status = resolve_dfspath_wcard(ctx, conn,
+ dfs_path,
+ name_in,
+ &fname,
+ ppath_contains_wcard);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("filename_convert: resolve_dfspath failed "
+ "for name %s with %s\n",
+ name_in,
+ nt_errstr(status) ));
+ return status;
+ }
+
+ if (is_fake_file_path(name_in)) {
+ SMB_STRUCT_STAT st;
+ ZERO_STRUCT(st);
+ st.st_ex_nlink = 1;
+ status = create_synthetic_smb_fname_split(ctx,
+ name_in,
+ &st,
+ pp_smb_fname);
+ return status;
+ }
+
+ /*
+ * If the caller conditionally allows wildcard lookups, only add the
+ * always allow if the path actually does contain a wildcard.
+ */
+ if (ucf_flags & UCF_COND_ALLOW_WCARD_LCOMP &&
+ ppath_contains_wcard != NULL && *ppath_contains_wcard) {
+ ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
+ }
+
+ status = unix_convert(ctx, conn, fname, pp_smb_fname, ucf_flags);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("filename_convert: unix_convert failed "
+ "for name %s with %s\n",
+ fname,
+ nt_errstr(status) ));
+ return status;
+ }
+
+ status = check_name(conn, (*pp_smb_fname)->base_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("filename_convert: check_name failed "
+ "for name %s with %s\n",
+ smb_fname_str_dbg(*pp_smb_fname),
+ nt_errstr(status) ));
+ TALLOC_FREE(*pp_smb_fname);
+ return status;
+ }
+
+ return status;
+}