2 Unix SMB/CIFS implementation.
3 filename handling routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1999-2007
6 Copyright (C) Ying Chen 2000
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * New hash table stat cache code added by Ying Chen.
28 #include "system/filesys.h"
29 #include "fake_file.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
33 static int get_real_filename(connection_struct *conn,
34 struct smb_filename *path,
39 uint32_t ucf_flags_from_smb_request(struct smb_request *req)
41 uint32_t ucf_flags = 0;
44 if (req->posix_pathnames) {
45 ucf_flags |= UCF_POSIX_PATHNAMES;
47 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
48 ucf_flags |= UCF_DFS_PATHNAME;
50 if (req->flags2 & FLAGS2_REPARSE_PATH) {
51 ucf_flags |= UCF_GMT_PATHNAME;
58 uint32_t filename_create_ucf_flags(struct smb_request *req, uint32_t create_disposition)
60 uint32_t ucf_flags = 0;
62 ucf_flags |= ucf_flags_from_smb_request(req);
64 switch (create_disposition) {
71 case FILE_OVERWRITE_IF:
72 ucf_flags |= UCF_PREP_CREATEFILE;
79 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
80 connection_struct *conn,
81 struct smb_filename *smb_fname);
83 /****************************************************************************
84 Mangle the 2nd name and check if it is then equal to the first name.
85 ****************************************************************************/
87 static bool mangled_equal(const char *name1,
89 const struct share_params *p)
93 if (!name_to_8_3(name2, mname, False, p)) {
96 return strequal(name1, mname);
99 /****************************************************************************
100 Cope with the differing wildcard and non-wildcard error cases.
101 ****************************************************************************/
103 static NTSTATUS determine_path_error(const char *name,
104 bool allow_wcard_last_component,
105 bool posix_pathnames)
108 bool name_has_wild = false;
110 if (!allow_wcard_last_component) {
111 /* Error code within a pathname. */
112 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
115 /* We're terminating here so we
116 * can be a little slower and get
117 * the error code right. Windows
118 * treats the last part of the pathname
119 * separately I think, so if the last
120 * component is a wildcard then we treat
121 * this ./ as "end of component" */
123 p = strchr(name, '/');
125 if (!posix_pathnames) {
126 name_has_wild = ms_has_wild(name);
129 if (!p && (name_has_wild || ISDOT(name))) {
130 /* Error code at the end of a pathname. */
131 return NT_STATUS_OBJECT_NAME_INVALID;
133 /* Error code within a pathname. */
134 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
138 static NTSTATUS check_for_dot_component(const struct smb_filename *smb_fname)
140 /* Ensure we catch all names with in "/."
141 this is disallowed under Windows and
142 in POSIX they've already been removed. */
143 const char *p = strstr(smb_fname->base_name, "/."); /*mb safe*/
146 /* Error code within a pathname. */
147 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
148 } else if (p[2] == '\0') {
149 /* Error code at the end of a pathname. */
150 return NT_STATUS_OBJECT_NAME_INVALID;
156 /****************************************************************************
157 Optimization for common case where the missing part
158 is in the last component and the client already
159 sent the correct case.
160 Returns NT_STATUS_OK to mean continue the tree walk
161 (possibly with modified start pointer).
162 Any other NT_STATUS_XXX error means terminate the path
164 ****************************************************************************/
166 static NTSTATUS check_parent_exists(TALLOC_CTX *ctx,
167 connection_struct *conn,
168 bool posix_pathnames,
169 const struct smb_filename *smb_fname,
172 int *p_parent_stat_errno)
174 char *parent_name = NULL;
175 struct smb_filename *parent_fname = NULL;
176 const char *last_component = NULL;
180 if (!parent_dirname(ctx, smb_fname->base_name,
183 return NT_STATUS_NO_MEMORY;
186 if (!posix_pathnames) {
187 if (ms_has_wild(parent_name)) {
188 goto no_optimization_out;
193 * If there was no parent component in
194 * smb_fname->base_name then don't do this
197 if (smb_fname->base_name == last_component) {
198 goto no_optimization_out;
201 parent_fname = synthetic_smb_fname(ctx,
207 if (parent_fname == NULL) {
208 return NT_STATUS_NO_MEMORY;
211 if (posix_pathnames) {
212 ret = SMB_VFS_LSTAT(conn, parent_fname);
214 ret = SMB_VFS_STAT(conn, parent_fname);
217 /* If the parent stat failed, just continue
218 with the normal tree walk. */
222 * Optimization. Preserving the
223 * errno from the STAT/LSTAT here
224 * will allow us to save a duplicate
225 * STAT/LSTAT system call of the parent
226 * pathname in a hot code path in the caller.
228 if (p_parent_stat_errno != NULL) {
229 *p_parent_stat_errno = errno;
231 goto no_optimization_out;
234 status = check_for_dot_component(parent_fname);
235 if (!NT_STATUS_IS_OK(status)) {
239 /* Parent exists - set "start" to be the
240 * last component to shorten the tree walk. */
243 * Safe to use discard_const_p
244 * here as last_component points
245 * into our smb_fname->base_name.
247 *pp_start = discard_const_p(char, last_component);
249 /* Update dirpath. */
250 TALLOC_FREE(*pp_dirpath);
251 *pp_dirpath = talloc_strdup(ctx, parent_fname->base_name);
253 return NT_STATUS_NO_MEMORY;
256 DEBUG(5,("check_parent_exists: name "
257 "= %s, dirpath = %s, "
259 smb_fname->base_name,
268 * We must still return an *pp_dirpath
269 * initialized to ".", and a *pp_start
270 * pointing at smb_fname->base_name.
273 TALLOC_FREE(parent_name);
274 TALLOC_FREE(parent_fname);
276 *pp_dirpath = talloc_strdup(ctx, ".");
277 if (*pp_dirpath == NULL) {
278 return NT_STATUS_NO_MEMORY;
281 * Safe to use discard_const_p
282 * here as by convention smb_fname->base_name
283 * is allocated off ctx.
285 *pp_start = discard_const_p(char, smb_fname->base_name);
290 * Re-order a known good @GMT-token path.
293 static NTSTATUS rearrange_snapshot_path(struct smb_filename *smb_fname,
298 size_t gmt_len = endp - startp;
299 char gmt_store[gmt_len + 1];
301 const char *last_component = NULL;
305 DBG_DEBUG("|%s| -> ", smb_fname->base_name);
307 /* Save off the @GMT-token. */
308 memcpy(gmt_store, startp, gmt_len);
309 gmt_store[gmt_len] = '\0';
312 /* Remove any trailing '/' */
318 * @GMT-token was at end of path.
319 * Remove any preceding '/'
321 if (startp > smb_fname->base_name && startp[-1] == '/') {
326 /* Remove @GMT-token from the path. */
327 endlen = strlen(endp);
328 memmove(startp, endp, endlen + 1);
330 /* Split the remaining path into components. */
331 ret = parent_dirname(smb_fname,
332 smb_fname->base_name,
336 /* Must terminate debug with \n */
337 DBG_DEBUG("NT_STATUS_NO_MEMORY\n");
338 return NT_STATUS_NO_MEMORY;
342 if (last_component[0] == '\0') {
343 newstr = talloc_strdup(smb_fname,
346 newstr = talloc_asprintf(smb_fname,
352 newstr = talloc_asprintf(smb_fname,
360 TALLOC_FREE(smb_fname->base_name);
361 smb_fname->base_name = newstr;
363 DBG_DEBUG("|%s|\n", newstr);
369 * Strip a valid @GMT-token from any incoming filename path,
370 * adding any NTTIME encoded in the pathname into the
371 * twrp field of the passed in smb_fname.
373 * Valid @GMT-tokens look like @GMT-YYYY-MM-DD-HH-MM-SS
374 * at the *start* of a pathname component.
376 * If twrp is passed in then smb_fname->twrp is set to that
377 * value, and the @GMT-token part of the filename is removed
378 * and does not change the stored smb_fname->twrp.
382 NTSTATUS canonicalize_snapshot_path(struct smb_filename *smb_fname,
395 smb_fname->twrp = twrp;
398 if (!(ucf_flags & UCF_GMT_PATHNAME)) {
402 startp = strchr_m(smb_fname->base_name, '@');
403 if (startp == NULL) {
408 startp = strstr_m(startp, "@GMT-");
409 if (startp == NULL) {
414 if ((startp > smb_fname->base_name) && (startp[-1] != '/')) {
415 /* the GMT-token does not start a path-component */
419 endp = strptime(startp, GMT_FORMAT, &tm);
421 /* Not a valid timestring. */
425 if (endp[0] != '\0' && endp[0] != '/') {
427 * It is not a complete path component, i.e. the path
428 * component continues after the gmt-token.
433 status = rearrange_snapshot_path(smb_fname, startp, endp);
434 if (!NT_STATUS_IS_OK(status)) {
438 startp = smb_fname->base_name + GMT_NAME_LEN;
439 if (startp[0] == '/') {
443 tmp = talloc_strdup(smb_fname, startp);
445 return NT_STATUS_NO_MEMORY;
448 TALLOC_FREE(smb_fname->base_name);
449 smb_fname->base_name = tmp;
451 if (smb_fname->twrp == 0) {
454 unix_to_nt_time(&nt, t);
455 smb_fname->twrp = nt;
462 * Utility function to normalize case on an incoming client filename
463 * if required on this connection struct.
464 * Performs an in-place case conversion guaranteed to stay the same size.
467 static NTSTATUS normalize_filename_case(connection_struct *conn,
473 if (ucf_flags & UCF_POSIX_PATHNAMES) {
475 * POSIX never normalizes filename case.
479 if (!conn->case_sensitive) {
482 if (conn->case_preserve) {
485 if (conn->short_case_preserve) {
488 ok = strnorm(filename, lp_default_case(SNUM(conn)));
490 return NT_STATUS_INVALID_PARAMETER;
495 /****************************************************************************
496 This routine is called to convert names from the dos namespace to unix
497 namespace. It needs to handle any case conversions, mangling, format changes,
500 We assume that we have already done a chdir() to the right "root" directory
503 Conversion to basic unix format is already done in check_path_syntax().
505 Names must be relative to the root of the service - any leading /. and
506 trailing /'s should have been trimmed by check_path_syntax().
508 The function will return an NTSTATUS error if some part of the name except for
509 the last part cannot be resolved, else NT_STATUS_OK.
511 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we
512 didn't get any fatal errors that should immediately terminate the calling SMB
513 processing whilst resolving.
515 If UCF_ALWAYS_ALLOW_WCARD_LCOMP is passed in, then a MS wildcard
516 should be allowed in the last component of the path only.
518 If the orig_path was a stream, smb_filename->base_name will point to the base
519 filename, and smb_filename->stream_name will point to the stream name. If
520 orig_path was not a stream, then smb_filename->stream_name will be NULL.
522 On exit from unix_convert, the smb_filename->st stat struct will be populated
523 if the file exists and was found, if not this stat struct will be filled with
524 zeros (and this can be detected by checking for nlinks = 0, which can never be
526 ****************************************************************************/
530 struct connection_struct *conn;
531 struct smb_filename *smb_fname;
532 const char *orig_path;
538 bool component_was_mangled;
539 bool name_has_wildcard;
540 bool posix_pathnames;
541 bool allow_wcard_last_component;
545 bool short_case_preserve;
548 static NTSTATUS unix_convert_step_search_fail(struct uc_state *state)
554 * An intermediate part of the name
557 DBG_DEBUG("Intermediate [%s] missing\n",
562 * We need to return the fact that the
563 * intermediate name resolution failed.
564 * This is used to return an error of
565 * ERRbadpath rather than ERRbadfile.
566 * Some Windows applications depend on
567 * the difference between these two
572 * ENOENT, ENOTDIR and ELOOP all map
573 * to NT_STATUS_OBJECT_PATH_NOT_FOUND
574 * in the filename walk.
577 if (errno == ENOENT ||
581 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
583 return map_nt_error_from_unix(errno);
587 * ENOENT/EACCESS are the only valid errors
591 if (errno == EACCES) {
592 if ((state->ucf_flags & UCF_PREP_CREATEFILE) == 0) {
593 return NT_STATUS_ACCESS_DENIED;
596 * This is the dropbox
597 * behaviour. A dropbox is a
598 * directory with only -wx
600 * get_real_filename fails
601 * with EACCESS, it needs to
602 * list the directory. We
603 * nevertheless want to allow
604 * users creating a file.
610 if ((errno != 0) && (errno != ENOENT)) {
612 * ENOTDIR and ELOOP both map to
613 * NT_STATUS_OBJECT_PATH_NOT_FOUND
614 * in the filename walk.
616 if (errno == ENOTDIR || errno == ELOOP) {
617 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
619 return map_nt_error_from_unix(errno);
623 * POSIX pathnames must never call into mangling.
625 if (state->posix_pathnames) {
630 * Just the last part of the name doesn't exist.
631 * We need to strupper() or strlower() it as
632 * this conversion may be used for file creation
633 * purposes. Fix inspired by
634 * Thomas Neumann <t.neumann@iku-ag.de>.
636 if (!state->case_preserve ||
637 (mangle_is_8_3(state->name, false,
638 state->conn->params) &&
639 !state->short_case_preserve)) {
640 if (!strnorm(state->name,
641 lp_default_case(SNUM(state->conn)))) {
642 DBG_DEBUG("strnorm %s failed\n",
644 return NT_STATUS_INVALID_PARAMETER;
649 * check on the mangled stack to see if we can
650 * recover the base of the filename.
653 if (mangle_is_mangled(state->name, state->conn->params)
654 && mangle_lookup_name_from_8_3(state->mem_ctx,
657 state->conn->params)) {
660 state->name - state->smb_fname->base_name;
662 if (!ISDOT(state->dirpath)) {
663 tmp = talloc_asprintf(
664 state->smb_fname, "%s/%s",
665 state->dirpath, unmangled);
666 TALLOC_FREE(unmangled);
672 DBG_ERR("talloc failed\n");
673 return NT_STATUS_NO_MEMORY;
675 TALLOC_FREE(state->smb_fname->base_name);
676 state->smb_fname->base_name = tmp;
678 state->smb_fname->base_name + name_ofs;
679 state->end = state->name + strlen(state->name);
684 DBG_DEBUG("New file [%s]\n", state->name);
689 static NTSTATUS unix_convert_step_stat(struct uc_state *state)
691 struct smb_filename dname;
693 char *found_name = NULL;
697 * Check if the name exists up to this point.
700 DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(state->smb_fname));
702 ret = vfs_stat(state->conn, state->smb_fname);
705 * It exists. it must either be a directory or this must
706 * be the last part of the path for it to be OK.
708 if (state->end && !S_ISDIR(state->smb_fname->st.st_ex_mode)) {
710 * An intermediate part of the name isn't
713 DBG_DEBUG("Not a dir [%s]\n", state->name);
716 * We need to return the fact that the
717 * intermediate name resolution failed. This
718 * is used to return an error of ERRbadpath
719 * rather than ERRbadfile. Some Windows
720 * applications depend on the difference between
723 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
728 /* Stat failed - ensure we don't use it. */
729 SET_STAT_INVALID(state->smb_fname->st);
731 if (state->posix_pathnames) {
733 * For posix_pathnames, we're done.
734 * Don't blunder into the name_has_wildcard OR
735 * get_real_filename() codepaths as they may
736 * be doing case insensitive lookups. So when
737 * creating a new POSIX directory Foo they might
740 * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13803
742 if (state->end != NULL) {
743 const char *morepath = NULL;
745 * If this is intermediate we must
746 * restore the full path.
750 * If there are any more components
751 * after the failed LSTAT we cannot
754 morepath = strchr(state->end + 1, '/');
755 if (morepath != NULL) {
756 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
759 if (errno == ENOENT) {
760 /* New file or directory. */
764 if ((errno == EACCES) &&
765 (state->ucf_flags & UCF_PREP_CREATEFILE)) {
766 /* POSIX Dropbox case. */
771 return map_nt_error_from_unix(errno);
775 * Reset errno so we can detect
776 * directory open errors.
781 * Try to find this part of the path in the directory.
784 if (state->name_has_wildcard) {
785 return unix_convert_step_search_fail(state);
788 dname = (struct smb_filename) {
789 .base_name = state->dirpath,
790 .twrp = state->smb_fname->twrp,
793 /* handle null paths */
794 if ((dname.base_name == NULL) || (dname.base_name[0] == '\0')) {
795 dname.base_name = dot;
798 ret = get_real_filename(state->conn,
804 return unix_convert_step_search_fail(state);
808 * Restore the rest of the string. If the string was
809 * mangled the size may have changed.
814 state->name - state->smb_fname->base_name;
816 if (!ISDOT(state->dirpath)) {
817 tmp = talloc_asprintf(state->smb_fname,
818 "%s/%s/%s", state->dirpath,
819 found_name, state->end+1);
822 tmp = talloc_asprintf(state->smb_fname,
827 DBG_ERR("talloc_asprintf failed\n");
828 return NT_STATUS_NO_MEMORY;
830 TALLOC_FREE(state->smb_fname->base_name);
831 state->smb_fname->base_name = tmp;
832 state->name = state->smb_fname->base_name + name_ofs;
833 state->end = state->name + strlen(found_name);
838 state->name - state->smb_fname->base_name;
840 if (!ISDOT(state->dirpath)) {
841 tmp = talloc_asprintf(state->smb_fname,
842 "%s/%s", state->dirpath,
845 tmp = talloc_strdup(state->smb_fname,
849 DBG_ERR("talloc failed\n");
850 return NT_STATUS_NO_MEMORY;
852 TALLOC_FREE(state->smb_fname->base_name);
853 state->smb_fname->base_name = tmp;
854 state->name = state->smb_fname->base_name + name_ofs;
857 * We just scanned for, and found the end of
858 * the path. We must return a valid stat struct
862 ret = vfs_stat(state->conn, state->smb_fname);
864 SET_STAT_INVALID(state->smb_fname->st);
868 TALLOC_FREE(found_name);
872 static NTSTATUS unix_convert_step(struct uc_state *state)
877 * Pinpoint the end of this section of the filename.
879 /* mb safe. '/' can't be in any encoded char. */
880 state->end = strchr(state->name, '/');
883 * Chop the name at this point.
885 if (state->end != NULL) {
889 DBG_DEBUG("dirpath [%s] name [%s]\n", state->dirpath, state->name);
891 /* The name cannot have a component of "." */
893 if (ISDOT(state->name)) {
894 if (state->end == NULL) {
895 /* Error code at the end of a pathname. */
896 return NT_STATUS_OBJECT_NAME_INVALID;
898 return determine_path_error(state->end+1,
899 state->allow_wcard_last_component,
900 state->posix_pathnames);
903 /* The name cannot have a wildcard if it's not
904 the last component. */
906 if (!state->posix_pathnames) {
907 state->name_has_wildcard = ms_has_wild(state->name);
910 /* Wildcards never valid within a pathname. */
911 if (state->name_has_wildcard && state->end != NULL) {
912 return NT_STATUS_OBJECT_NAME_INVALID;
915 /* Skip the stat call if it's a wildcard end. */
916 if (state->name_has_wildcard) {
917 DBG_DEBUG("Wildcard [%s]\n", state->name);
922 status = unix_convert_step_stat(state);
923 if (!NT_STATUS_IS_OK(status)) {
931 * Add to the dirpath that we have resolved so far.
934 if (!ISDOT(state->dirpath)) {
935 char *tmp = talloc_asprintf(state->mem_ctx,
936 "%s/%s", state->dirpath, state->name);
938 DBG_ERR("talloc_asprintf failed\n");
939 return NT_STATUS_NO_MEMORY;
941 TALLOC_FREE(state->dirpath);
942 state->dirpath = tmp;
945 TALLOC_FREE(state->dirpath);
946 if (!(state->dirpath = talloc_strdup(state->mem_ctx,state->name))) {
947 DBG_ERR("talloc_strdup failed\n");
948 return NT_STATUS_NO_MEMORY;
953 * Cache the dirpath thus far. Don't cache a name with mangled
954 * or wildcard components as this can change the size.
956 if(!state->component_was_mangled && !state->name_has_wildcard) {
957 stat_cache_add(state->orig_path,
959 state->smb_fname->twrp,
960 state->case_sensitive);
964 * Restore the / that we wiped out earlier.
966 if (state->end != NULL) {
973 NTSTATUS unix_convert(TALLOC_CTX *mem_ctx,
974 connection_struct *conn,
975 const char *orig_path,
977 struct smb_filename **smb_fname_out,
980 struct uc_state uc_state;
981 struct uc_state *state = &uc_state;
985 *state = (struct uc_state) {
988 .orig_path = orig_path,
989 .ucf_flags = ucf_flags,
990 .posix_pathnames = (ucf_flags & UCF_POSIX_PATHNAMES),
991 .allow_wcard_last_component = (ucf_flags & UCF_ALWAYS_ALLOW_WCARD_LCOMP),
992 .case_sensitive = conn->case_sensitive,
993 .case_preserve = conn->case_preserve,
994 .short_case_preserve = conn->short_case_preserve,
997 *smb_fname_out = NULL;
999 if (state->posix_pathnames) {
1000 /* POSIX means ignore case settings on share. */
1001 state->case_sensitive = true;
1002 state->case_preserve = true;
1003 state->short_case_preserve = true;
1006 state->smb_fname = talloc_zero(state->mem_ctx, struct smb_filename);
1007 if (state->smb_fname == NULL) {
1008 return NT_STATUS_NO_MEMORY;
1011 if (state->conn->printer) {
1012 /* we don't ever use the filenames on a printer share as a
1013 filename - so don't convert them */
1014 state->smb_fname->base_name = talloc_strdup(
1015 state->smb_fname, state->orig_path);
1016 if (state->smb_fname->base_name == NULL) {
1017 status = NT_STATUS_NO_MEMORY;
1023 state->smb_fname->flags = state->posix_pathnames ? SMB_FILENAME_POSIX_PATH : 0;
1025 DBG_DEBUG("Called on file [%s]\n", state->orig_path);
1027 if (state->orig_path[0] == '/') {
1028 DBG_ERR("Path [%s] starts with '/'\n", state->orig_path);
1029 return NT_STATUS_OBJECT_NAME_INVALID;
1032 /* Start with the full orig_path as given by the caller. */
1033 state->smb_fname->base_name = talloc_strdup(
1034 state->smb_fname, state->orig_path);
1035 if (state->smb_fname->base_name == NULL) {
1036 DBG_ERR("talloc_strdup failed\n");
1037 status = NT_STATUS_NO_MEMORY;
1041 /* Canonicalize any @GMT- paths. */
1042 status = canonicalize_snapshot_path(state->smb_fname, ucf_flags, twrp);
1043 if (!NT_STATUS_IS_OK(status)) {
1048 * If we trimmed down to a single '\0' character
1049 * then we should use the "." directory to avoid
1050 * searching the cache, but not if we are in a
1052 * As we know this is valid we can return true here.
1055 if (state->smb_fname->base_name[0] == '\0') {
1056 state->smb_fname->base_name = talloc_strdup(state->smb_fname, ".");
1057 if (state->smb_fname->base_name == NULL) {
1058 status = NT_STATUS_NO_MEMORY;
1061 if (SMB_VFS_STAT(state->conn, state->smb_fname) != 0) {
1062 status = map_nt_error_from_unix(errno);
1065 DBG_DEBUG("conversion finished [] -> [%s]\n",
1066 state->smb_fname->base_name);
1070 if (state->orig_path[0] == '.' && (state->orig_path[1] == '/' ||
1071 state->orig_path[1] == '\0')) {
1072 /* Start of pathname can't be "." only. */
1073 if (state->orig_path[1] == '\0' || state->orig_path[2] == '\0') {
1074 status = NT_STATUS_OBJECT_NAME_INVALID;
1076 status =determine_path_error(&state->orig_path[2],
1077 state->allow_wcard_last_component,
1078 state->posix_pathnames);
1084 * Large directory fix normalization. If we're case sensitive, and
1085 * the case preserving parameters are set to "no", normalize the case of
1086 * the incoming filename from the client WHETHER IT EXISTS OR NOT !
1087 * This is in conflict with the current (3.0.20) man page, but is
1088 * what people expect from the "large directory howto". I'll update
1089 * the man page. Thanks to jht@samba.org for finding this. JRA.
1092 status = normalize_filename_case(state->conn,
1093 state->smb_fname->base_name,
1095 if (!NT_STATUS_IS_OK(status)) {
1096 DBG_ERR("normalize_filename_case %s failed\n",
1097 state->smb_fname->base_name);
1102 * Strip off the stream, and add it back when we're done with the
1105 if (!state->posix_pathnames) {
1106 state->stream = strchr_m(state->smb_fname->base_name, ':');
1108 if (state->stream != NULL) {
1109 char *tmp = talloc_strdup(state->smb_fname, state->stream);
1111 status = NT_STATUS_NO_MEMORY;
1115 * Since this is actually pointing into
1116 * smb_fname->base_name this truncates base_name.
1118 *state->stream = '\0';
1119 state->stream = tmp;
1121 if (state->smb_fname->base_name[0] == '\0') {
1123 * orig_name was just a stream name.
1124 * This is a stream on the root of
1125 * the share. Replace base_name with
1128 state->smb_fname->base_name =
1129 talloc_strdup(state->smb_fname, ".");
1130 if (state->smb_fname->base_name == NULL) {
1131 status = NT_STATUS_NO_MEMORY;
1134 if (SMB_VFS_STAT(state->conn, state->smb_fname) != 0) {
1135 status = map_nt_error_from_unix(errno);
1138 /* dirpath must exist. */
1139 state->dirpath = talloc_strdup(state->mem_ctx,".");
1140 if (state->dirpath == NULL) {
1141 status = NT_STATUS_NO_MEMORY;
1144 DBG_INFO("conversion finished [%s] -> [%s]\n",
1146 state->smb_fname->base_name);
1152 state->name = state->smb_fname->base_name;
1155 * If we're providing case insensitive semantics or
1156 * the underlying filesystem is case insensitive,
1157 * then a case-normalized hit in the stat-cache is
1158 * authoritative. JRA.
1160 * Note: We're only checking base_name. The stream_name will be
1161 * added and verified in build_stream_path().
1164 if (!state->case_sensitive ||
1165 !(state->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
1169 found = stat_cache_lookup(state->conn,
1170 state->posix_pathnames,
1171 &state->smb_fname->base_name,
1174 state->smb_fname->twrp,
1175 &state->smb_fname->st);
1182 * Make sure "dirpath" is an allocated string, we use this for
1183 * building the directories with talloc_asprintf and free it.
1186 if (state->dirpath == NULL) {
1187 state->dirpath = talloc_strdup(state->mem_ctx,".");
1188 if (state->dirpath == NULL) {
1189 DBG_ERR("talloc_strdup failed\n");
1190 status = NT_STATUS_NO_MEMORY;
1196 * If we have a wildcard we must walk the path to
1197 * find where the error is, even if case sensitive
1201 if (!state->posix_pathnames) {
1202 /* POSIX pathnames have no wildcards. */
1203 state->name_has_wildcard = ms_has_wild(state->smb_fname->base_name);
1204 if (state->name_has_wildcard && !state->allow_wcard_last_component) {
1205 /* Wildcard not valid anywhere. */
1206 status = NT_STATUS_OBJECT_NAME_INVALID;
1211 DBG_DEBUG("Begin: name [%s] dirpath [%s] name [%s]\n",
1212 state->smb_fname->base_name, state->dirpath, state->name);
1214 if (!state->name_has_wildcard) {
1215 int parent_stat_errno = 0;
1218 * stat the name - if it exists then we can add the stream back (if
1219 * there was one) and be done!
1222 ret = vfs_stat(state->conn, state->smb_fname);
1224 status = check_for_dot_component(state->smb_fname);
1225 if (!NT_STATUS_IS_OK(status)) {
1228 /* Add the path (not including the stream) to the cache. */
1229 stat_cache_add(state->orig_path,
1230 state->smb_fname->base_name,
1231 state->smb_fname->twrp,
1232 state->case_sensitive);
1233 DBG_DEBUG("Conversion of base_name finished "
1235 state->orig_path, state->smb_fname->base_name);
1239 /* Stat failed - ensure we don't use it. */
1240 SET_STAT_INVALID(state->smb_fname->st);
1243 * Note: we must continue processing a path if we get EACCES
1244 * from stat. With NFS4 permissions the file might be lacking
1245 * READ_ATTR, but if the parent has LIST permissions we can
1246 * resolve the path in the path traversal loop down below.
1249 if (errno == ENOENT) {
1250 /* Optimization when creating a new file - only
1251 the last component doesn't exist.
1252 NOTE : check_parent_exists() doesn't preserve errno.
1254 int saved_errno = errno;
1255 status = check_parent_exists(state->mem_ctx,
1257 state->posix_pathnames,
1261 &parent_stat_errno);
1262 errno = saved_errno;
1263 if (!NT_STATUS_IS_OK(status)) {
1269 * A special case - if we don't have any wildcards or mangling chars and are case
1270 * sensitive or the underlying filesystem is case insensitive then searching
1273 * NB. As POSIX sets state->case_sensitive as
1274 * true we will never call into mangle_is_mangled() here.
1277 if ((state->case_sensitive || !(state->conn->fs_capabilities &
1278 FILE_CASE_SENSITIVE_SEARCH)) &&
1279 !mangle_is_mangled(state->smb_fname->base_name, state->conn->params)) {
1281 status = check_for_dot_component(state->smb_fname);
1282 if (!NT_STATUS_IS_OK(status)) {
1287 * The stat failed. Could be ok as it could be
1291 if (errno == ENOTDIR || errno == ELOOP) {
1292 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1294 } else if (errno == ENOENT) {
1296 * Was it a missing last component ?
1297 * or a missing intermediate component ?
1301 * For this code path we can guarantee that
1302 * we have gone through check_parent_exists()
1303 * and it returned NT_STATUS_OK.
1305 * Either there was no parent component (".")
1306 * parent_stat_errno == 0 and we have a missing
1307 * last component here.
1309 * OR check_parent_exists() called STAT/LSTAT
1310 * and if it failed parent_stat_errno has been
1311 * set telling us if the parent existed or not.
1313 * Either way we can avoid another STAT/LSTAT
1314 * system call on the parent here.
1316 if (parent_stat_errno == ENOTDIR ||
1317 parent_stat_errno == ENOENT ||
1318 parent_stat_errno == ELOOP) {
1319 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1324 * Missing last component is ok - new file.
1325 * Also deal with permission denied elsewhere.
1326 * Just drop out to done.
1333 * We have a wildcard in the pathname.
1335 * Optimization for common case where the wildcard
1336 * is in the last component and the client already
1337 * sent the correct case.
1338 * NOTE : check_parent_exists() doesn't preserve errno.
1340 int saved_errno = errno;
1341 status = check_parent_exists(state->mem_ctx,
1343 state->posix_pathnames,
1348 errno = saved_errno;
1349 if (!NT_STATUS_IS_OK(status)) {
1355 * is_mangled() was changed to look at an entire pathname, not
1356 * just a component. JRA.
1359 if (state->posix_pathnames) {
1361 * POSIX names are never mangled and we must not
1362 * call into mangling functions.
1364 state->component_was_mangled = false;
1365 } else if (mangle_is_mangled(state->name, state->conn->params)) {
1366 state->component_was_mangled = true;
1370 * Now we need to recursively match the name against the real
1371 * directory structure.
1375 * Match each part of the path name separately, trying the names
1376 * as is first, then trying to scan the directory for matching names.
1379 for (; state->name ; state->name = (state->end ? state->end + 1:(char *)NULL)) {
1380 status = unix_convert_step(state);
1381 if (!NT_STATUS_IS_OK(status)) {
1382 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
1393 * Cache the full path. Don't cache a name with mangled or wildcard
1394 * components as this can change the size.
1397 if(!state->component_was_mangled && !state->name_has_wildcard) {
1398 stat_cache_add(state->orig_path,
1399 state->smb_fname->base_name,
1400 state->smb_fname->twrp,
1401 state->case_sensitive);
1405 * The name has been resolved.
1409 /* Add back the stream if one was stripped off originally. */
1410 if (state->stream != NULL) {
1411 state->smb_fname->stream_name = state->stream;
1413 /* Check path now that the base_name has been converted. */
1414 status = build_stream_path(state->mem_ctx, state->conn, state->smb_fname);
1415 if (!NT_STATUS_IS_OK(status)) {
1420 DBG_DEBUG("Conversion finished [%s] -> [%s]\n",
1421 state->orig_path, smb_fname_str_dbg(state->smb_fname));
1423 TALLOC_FREE(state->dirpath);
1424 *smb_fname_out = state->smb_fname;
1425 return NT_STATUS_OK;
1427 DBG_DEBUG("Conversion failed: dirpath [%s] name [%s]\n",
1428 state->dirpath, state->name);
1429 if ((state->dirpath != NULL) && !ISDOT(state->dirpath)) {
1430 state->smb_fname->base_name = talloc_asprintf(
1436 state->smb_fname->base_name = talloc_strdup(
1437 state->smb_fname, state->name);
1439 if (state->smb_fname->base_name == NULL) {
1440 DBG_ERR("talloc_asprintf failed\n");
1441 status = NT_STATUS_NO_MEMORY;
1445 *smb_fname_out = state->smb_fname;
1446 TALLOC_FREE(state->dirpath);
1449 TALLOC_FREE(state->smb_fname);
1453 /****************************************************************************
1454 Ensure a path is not vetoed.
1455 ****************************************************************************/
1457 static NTSTATUS check_veto_path(connection_struct *conn,
1458 const struct smb_filename *smb_fname)
1460 const char *name = smb_fname->base_name;
1462 if (IS_VETO_PATH(conn, name)) {
1463 /* Is it not dot or dot dot. */
1464 if (!(ISDOT(name) || ISDOTDOT(name))) {
1465 DEBUG(5,("check_veto_path: file path name %s vetoed\n",
1467 return map_nt_error_from_unix(ENOENT);
1470 return NT_STATUS_OK;
1473 /****************************************************************************
1474 Check a filename - possibly calling check_reduced_name.
1475 This is called by every routine before it allows an operation on a filename.
1476 It does any final confirmation necessary to ensure that the filename is
1477 a valid one for the user to access.
1478 ****************************************************************************/
1480 static NTSTATUS check_name(connection_struct *conn,
1481 const struct smb_filename *smb_fname)
1483 NTSTATUS status = check_veto_path(conn, smb_fname);
1485 if (!NT_STATUS_IS_OK(status)) {
1489 if (!lp_widelinks(SNUM(conn)) || !lp_follow_symlinks(SNUM(conn))) {
1490 status = check_reduced_name(conn, NULL, smb_fname);
1491 if (!NT_STATUS_IS_OK(status)) {
1492 DEBUG(5,("check_name: name %s failed with %s\n",
1493 smb_fname->base_name,
1494 nt_errstr(status)));
1499 return NT_STATUS_OK;
1502 /****************************************************************************
1503 Check if two filenames are equal.
1504 This needs to be careful about whether we are case sensitive.
1505 ****************************************************************************/
1507 static bool fname_equal(const char *name1, const char *name2,
1508 bool case_sensitive)
1510 /* Normal filename handling */
1511 if (case_sensitive) {
1512 return(strcmp(name1,name2) == 0);
1515 return(strequal(name1,name2));
1518 static bool sname_equal(const char *name1, const char *name2,
1519 bool case_sensitive)
1522 const char *s1 = NULL;
1523 const char *s2 = NULL;
1526 const char *e1 = NULL;
1527 const char *e2 = NULL;
1531 match = fname_equal(name1, name2, case_sensitive);
1536 if (name1[0] != ':') {
1539 if (name2[0] != ':') {
1543 e1 = strchr(s1, ':');
1547 n1 = PTR_DIFF(e1, s1);
1550 e2 = strchr(s2, ':');
1554 n2 = PTR_DIFF(e2, s2);
1557 /* Normal filename handling */
1558 if (case_sensitive) {
1559 return (strncmp(s1, s2, n1) == 0);
1563 * We can't use strnequal() here
1564 * as it takes the number of codepoints
1565 * and not the number of bytes.
1567 * So we make a copy before calling
1570 * Note that we TALLOC_FREE() in reverse order
1571 * in order to avoid memory fragmentation.
1574 c1 = talloc_strndup(talloc_tos(), s1, n1);
1575 c2 = talloc_strndup(talloc_tos(), s2, n2);
1576 if (c1 == NULL || c2 == NULL) {
1579 return (strncmp(s1, s2, n1) == 0);
1582 match = strequal(c1, c2);
1588 /****************************************************************************
1589 Scan a directory to find a filename, matching without case sensitivity.
1590 If the name looks like a mangled name then try via the mangling functions
1591 ****************************************************************************/
1593 int get_real_filename_full_scan(connection_struct *conn,
1597 TALLOC_CTX *mem_ctx,
1600 struct smb_Dir *cur_dir;
1601 const char *dname = NULL;
1602 char *talloced = NULL;
1603 char *unmangled_name = NULL;
1605 struct smb_filename *smb_fname = NULL;
1607 /* handle null paths */
1608 if ((path == NULL) || (*path == 0)) {
1612 /* If we have a case-sensitive filesystem, it doesn't do us any
1613 * good to search for a name. If a case variation of the name was
1614 * there, then the original stat(2) would have found it.
1616 if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
1622 * The incoming name can be mangled, and if we de-mangle it
1623 * here it will not compare correctly against the filename (name2)
1624 * read from the directory and then mangled by the name_to_8_3()
1625 * call. We need to mangle both names or neither.
1628 * Fix for bug found by Dina Fine. If in case sensitive mode then
1629 * the mangle cache is no good (3 letter extension could be wrong
1630 * case - so don't demangle in this case - leave as mangled and
1631 * allow the mangling of the directory entry read (which is done
1632 * case insensitively) to match instead. This will lead to more
1633 * false positive matches but we fail completely without it. JRA.
1636 if (mangled && !conn->case_sensitive) {
1637 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
1641 /* Name is now unmangled. */
1642 name = unmangled_name;
1646 smb_fname = synthetic_smb_fname(talloc_tos(),
1652 if (smb_fname == NULL) {
1653 TALLOC_FREE(unmangled_name);
1657 /* open the directory */
1658 if (!(cur_dir = OpenDir(talloc_tos(), conn, smb_fname, NULL, 0))) {
1659 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
1660 TALLOC_FREE(unmangled_name);
1661 TALLOC_FREE(smb_fname);
1665 TALLOC_FREE(smb_fname);
1667 /* now scan for matching names */
1669 while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) {
1671 /* Is it dot or dot dot. */
1672 if (ISDOT(dname) || ISDOTDOT(dname)) {
1673 TALLOC_FREE(talloced);
1678 * At this point dname is the unmangled name.
1679 * name is either mangled or not, depending on the state
1680 * of the "mangled" variable. JRA.
1684 * Check mangled name against mangled name, or unmangled name
1685 * against unmangled name.
1688 if ((mangled && mangled_equal(name,dname,conn->params)) ||
1689 fname_equal(name, dname, conn->case_sensitive)) {
1690 /* we've found the file, change it's name and return */
1691 *found_name = talloc_strdup(mem_ctx, dname);
1692 TALLOC_FREE(unmangled_name);
1693 TALLOC_FREE(cur_dir);
1696 TALLOC_FREE(talloced);
1699 TALLOC_FREE(talloced);
1702 TALLOC_FREE(talloced);
1705 TALLOC_FREE(unmangled_name);
1706 TALLOC_FREE(cur_dir);
1711 /****************************************************************************
1712 Wrapper around the vfs get_real_filename and the full directory scan
1714 ****************************************************************************/
1716 static int get_real_filename(connection_struct *conn,
1717 struct smb_filename *path,
1719 TALLOC_CTX *mem_ctx,
1725 mangled = mangle_is_mangled(name, conn->params);
1728 return get_real_filename_full_scan(conn,
1736 /* Try the vfs first to take advantage of case-insensitive stat. */
1737 ret = SMB_VFS_GET_REAL_FILENAME(conn,
1744 * If the case-insensitive stat was successful, or returned an error
1745 * other than EOPNOTSUPP then there is no need to fall back on the
1746 * full directory scan.
1748 if (ret == 0 || (ret == -1 && errno != EOPNOTSUPP)) {
1752 return get_real_filename_full_scan(conn,
1760 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
1761 connection_struct *conn,
1762 struct smb_filename *smb_fname)
1765 unsigned int i, num_streams = 0;
1766 struct stream_struct *streams = NULL;
1767 struct smb_filename *pathref = NULL;
1769 if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1770 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1771 return NT_STATUS_OK;
1774 if (errno != ENOENT) {
1775 DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno)));
1776 status = map_nt_error_from_unix(errno);
1780 if (smb_fname->fsp == NULL) {
1781 status = synthetic_pathref(mem_ctx,
1783 smb_fname->base_name,
1789 if (!NT_STATUS_IS_OK(status)) {
1790 if (NT_STATUS_EQUAL(status,
1791 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1792 TALLOC_FREE(pathref);
1793 SET_STAT_INVALID(smb_fname->st);
1794 return NT_STATUS_OK;
1796 DBG_DEBUG("synthetic_pathref failed: %s\n",
1801 pathref = smb_fname;
1804 /* Fall back to a case-insensitive scan of all streams on the file. */
1805 status = vfs_fstreaminfo(pathref->fsp, mem_ctx,
1806 &num_streams, &streams);
1807 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1808 SET_STAT_INVALID(smb_fname->st);
1809 TALLOC_FREE(pathref);
1810 return NT_STATUS_OK;
1813 if (!NT_STATUS_IS_OK(status)) {
1814 DEBUG(10, ("vfs_fstreaminfo failed: %s\n", nt_errstr(status)));
1818 for (i=0; i<num_streams; i++) {
1819 DEBUG(10, ("comparing [%s] and [%s]: ",
1820 smb_fname->stream_name, streams[i].name));
1821 if (sname_equal(smb_fname->stream_name, streams[i].name,
1822 conn->case_sensitive)) {
1823 DEBUGADD(10, ("equal\n"));
1826 DEBUGADD(10, ("not equal\n"));
1829 /* Couldn't find the stream. */
1830 if (i == num_streams) {
1831 SET_STAT_INVALID(smb_fname->st);
1832 TALLOC_FREE(pathref);
1833 TALLOC_FREE(streams);
1834 return NT_STATUS_OK;
1837 DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
1838 smb_fname->stream_name, streams[i].name));
1841 TALLOC_FREE(smb_fname->stream_name);
1842 smb_fname->stream_name = talloc_strdup(smb_fname, streams[i].name);
1843 if (smb_fname->stream_name == NULL) {
1844 status = NT_STATUS_NO_MEMORY;
1848 SET_STAT_INVALID(smb_fname->st);
1850 if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1851 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1853 status = NT_STATUS_OK;
1855 TALLOC_FREE(pathref);
1856 TALLOC_FREE(streams);
1861 * Lightweight function to just get last component
1862 * for rename / enumerate directory calls.
1865 char *get_original_lcomp(TALLOC_CTX *ctx,
1866 connection_struct *conn,
1867 const char *filename_in,
1870 struct smb_filename *smb_fname = NULL;
1871 char *last_slash = NULL;
1877 if (ucf_flags & UCF_DFS_PATHNAME) {
1878 status = dfs_redirect(ctx,
1882 !conn->sconn->using_smb2,
1885 if (!NT_STATUS_IS_OK(status)) {
1886 DBG_DEBUG("dfs_redirect "
1887 "failed for name %s with %s\n",
1892 filename_in = fname;
1893 ucf_flags &= ~UCF_DFS_PATHNAME;
1897 * NB. We don't need to care about
1898 * is_fake_file_path(filename_in) here as these
1899 * code paths don't ever return original_lcomp
1903 if (ucf_flags & UCF_GMT_PATHNAME) {
1905 * Ensure we don't return a @GMT
1906 * value as the last component.
1908 smb_fname = synthetic_smb_fname(ctx,
1914 if (smb_fname == NULL) {
1918 status = canonicalize_snapshot_path(smb_fname,
1921 if (!NT_STATUS_IS_OK(status)) {
1923 TALLOC_FREE(smb_fname);
1926 filename_in = smb_fname->base_name;
1928 last_slash = strrchr(filename_in, '/');
1929 if (last_slash != NULL) {
1930 orig_lcomp = talloc_strdup(ctx, last_slash+1);
1932 orig_lcomp = talloc_strdup(ctx, filename_in);
1934 /* We're done with any temp names here. */
1935 TALLOC_FREE(smb_fname);
1937 if (orig_lcomp == NULL) {
1940 status = normalize_filename_case(conn, orig_lcomp, ucf_flags);
1941 if (!NT_STATUS_IS_OK(status)) {
1942 TALLOC_FREE(orig_lcomp);
1949 * Go through all the steps to validate a filename.
1951 * @param ctx talloc_ctx to allocate memory with.
1952 * @param conn connection struct for vfs calls.
1953 * @param smbreq SMB request if we're using privileges.
1954 * @param name_in The unconverted name.
1955 * @param ucf_flags flags to pass through to unix_convert().
1956 * @param twrp Optional VSS time
1957 * @param p_cont_wcard If not NULL, will be set to true if the dfs path
1958 * resolution detects a wildcard.
1959 * @param _smb_fname The final converted name will be allocated if the
1960 * return is NT_STATUS_OK.
1962 * @return NT_STATUS_OK if all operations completed successfully, appropriate
1965 NTSTATUS filename_convert(TALLOC_CTX *ctx,
1966 connection_struct *conn,
1967 const char *name_in,
1970 struct smb_filename **_smb_fname)
1972 struct smb_filename *smb_fname = NULL;
1977 if (ucf_flags & UCF_DFS_PATHNAME) {
1979 NTTIME dfs_twrp = 0;
1980 status = dfs_redirect(ctx, conn,
1983 !conn->sconn->using_smb2,
1986 if (!NT_STATUS_IS_OK(status)) {
1987 DBG_DEBUG("dfs_redirect "
1988 "failed for name %s with %s\n",
1994 ucf_flags &= ~UCF_DFS_PATHNAME;
1995 if (twrp == 0 && dfs_twrp != 0) {
2000 if (is_fake_file_path(name_in)) {
2001 smb_fname = synthetic_smb_fname_split(ctx,
2003 (ucf_flags & UCF_POSIX_PATHNAMES));
2004 if (smb_fname == NULL) {
2005 return NT_STATUS_NO_MEMORY;
2007 smb_fname->st = (SMB_STRUCT_STAT) { .st_ex_nlink = 1 };
2008 smb_fname->st.st_ex_btime = (struct timespec){0, SAMBA_UTIME_OMIT};
2009 smb_fname->st.st_ex_atime = (struct timespec){0, SAMBA_UTIME_OMIT};
2010 smb_fname->st.st_ex_mtime = (struct timespec){0, SAMBA_UTIME_OMIT};
2011 smb_fname->st.st_ex_ctime = (struct timespec){0, SAMBA_UTIME_OMIT};
2013 *_smb_fname = smb_fname;
2014 return NT_STATUS_OK;
2017 status = unix_convert(ctx, conn, name_in, twrp, &smb_fname, ucf_flags);
2018 if (!NT_STATUS_IS_OK(status)) {
2019 DBG_DEBUG("unix_convert failed "
2020 "for name %s with %s\n",
2026 if ((ucf_flags & UCF_POSIX_PATHNAMES) &&
2027 VALID_STAT(smb_fname->st) &&
2028 S_ISLNK(smb_fname->st.st_ex_mode))
2030 status = check_veto_path(conn, smb_fname);
2031 if (!NT_STATUS_IS_OK(status)) {
2032 TALLOC_FREE(smb_fname);
2036 status = check_name(conn, smb_fname);
2038 if (!NT_STATUS_IS_OK(status)) {
2039 DBG_NOTICE("check_name failed "
2040 "for name %s with %s\n",
2041 smb_fname_str_dbg(smb_fname),
2043 TALLOC_FREE(smb_fname);
2047 if (!VALID_STAT(smb_fname->st)) {
2048 DBG_DEBUG("[%s] does not exist, skipping pathref fsp\n",
2049 smb_fname_str_dbg(smb_fname));
2050 *_smb_fname = smb_fname;
2051 return NT_STATUS_OK;
2054 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname);
2055 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2057 * We deal with symlinks here as we do in
2058 * SMB_VFS_CREATE_FILE(): return success for POSIX clients with
2059 * the notable difference that there will be no fsp in
2062 * For Windows (non POSIX) clients fail with
2063 * NT_STATUS_OBJECT_NAME_NOT_FOUND.
2065 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH &&
2066 S_ISLNK(smb_fname->st.st_ex_mode))
2068 status = NT_STATUS_OK;
2071 if (!NT_STATUS_IS_OK(status)) {
2072 DBG_DEBUG("open_pathref_fsp [%s] failed: %s\n",
2073 smb_fname_str_dbg(smb_fname),
2078 *_smb_fname = smb_fname;
2083 * Strip a @GMT component from an SMB1-DFS path. Could be anywhere
2087 static char *strip_gmt_from_raw_dfs(TALLOC_CTX *ctx,
2088 const char *name_in,
2089 bool posix_pathnames,
2093 struct smb_filename *smb_fname = NULL;
2094 char *name_out = NULL;
2096 smb_fname = synthetic_smb_fname(ctx,
2102 if (smb_fname == NULL) {
2105 if (!posix_pathnames) {
2107 * Raw DFS names are still '\\' separated.
2108 * canonicalize_snapshot_path() only works
2109 * on '/' separated paths. Convert.
2111 string_replace(smb_fname->base_name, '\\', '/');
2113 status = canonicalize_snapshot_path(smb_fname,
2116 if (!NT_STATUS_IS_OK(status)) {
2117 TALLOC_FREE(smb_fname);
2120 if (!posix_pathnames) {
2121 /* Replace as raw DFS names. */
2122 string_replace(smb_fname->base_name, '/', '\\');
2124 name_out = talloc_strdup(ctx, smb_fname->base_name);
2125 *_twrp = smb_fname->twrp;
2126 TALLOC_FREE(smb_fname);
2131 * Deal with the SMB1 semantics of sending a pathname with a
2132 * wildcard as the terminal component for a SMB1search or
2136 NTSTATUS filename_convert_smb1_search_path(TALLOC_CTX *ctx,
2137 connection_struct *conn,
2138 const char *name_in,
2140 struct smb_filename **_smb_fname_out,
2146 struct smb_filename *smb_fname = NULL;
2147 bool posix_pathnames = (ucf_flags & UCF_POSIX_PATHNAMES);
2149 TALLOC_CTX *frame = talloc_stackframe();
2151 *_smb_fname_out = NULL;
2154 DBG_DEBUG("name_in: %s\n", name_in);
2156 if (ucf_flags & UCF_DFS_PATHNAME) {
2158 * We've been given a raw DFS pathname.
2159 * In Windows mode this is separated by '\\'
2162 * We need to remove the last component
2163 * which must be a wildcard before passing
2164 * to dfs_redirect(). But the last component
2165 * may also be a @GMT- token so we have to
2166 * remove that first.
2168 char path_sep = posix_pathnames ? '/' : '\\';
2170 char *name_in_copy = NULL;
2171 char *last_component = NULL;
2173 /* Work on a copy of name_in. */
2174 if (ucf_flags & UCF_GMT_PATHNAME) {
2175 name_in_copy = strip_gmt_from_raw_dfs(frame,
2179 ucf_flags &= ~UCF_GMT_PATHNAME;
2181 name_in_copy = talloc_strdup(frame, name_in);
2183 if (name_in_copy == NULL) {
2185 return NT_STATUS_NO_MEMORY;
2189 * Now we know that the last component is the
2190 * wildcard. Copy it and truncate to remove it.
2192 p = strrchr_m(name_in_copy, path_sep);
2194 last_component = talloc_strdup(frame, name_in_copy);
2195 name_in_copy[0] = '\0';
2197 last_component = talloc_strdup(frame, p+1);
2200 if (last_component == NULL) {
2202 return NT_STATUS_NO_MEMORY;
2205 DBG_DEBUG("name_in_copy: %s\n", name_in);
2208 * Now we can call dfs_redirect()
2209 * on the name without wildcard.
2211 status = dfs_redirect(frame,
2215 !conn->sconn->using_smb2,
2218 if (!NT_STATUS_IS_OK(status)) {
2219 DBG_DEBUG("dfs_redirect "
2220 "failed for name %s with %s\n",
2226 /* Add the last component back. */
2227 if (fname[0] == '\0') {
2228 name_in = talloc_strdup(frame, last_component);
2230 name_in = talloc_asprintf(frame,
2236 if (name_in == NULL) {
2238 return NT_STATUS_NO_MEMORY;
2240 ucf_flags &= ~UCF_DFS_PATHNAME;
2242 DBG_DEBUG("After DFS redirect name_in: %s\n", name_in);
2245 smb_fname = synthetic_smb_fname(frame,
2251 SMB_FILENAME_POSIX_PATH : 0);
2252 if (smb_fname == NULL) {
2254 return NT_STATUS_NO_MEMORY;
2257 /* Canonicalize any @GMT- paths. */
2258 status = canonicalize_snapshot_path(smb_fname, ucf_flags, twrp);
2259 if (!NT_STATUS_IS_OK(status)) {
2264 /* Get the original lcomp. */
2265 mask = get_original_lcomp(frame,
2271 return NT_STATUS_NO_MEMORY;
2274 if (mask[0] == '\0') {
2275 /* Windows and OS/2 systems treat search on the root as * */
2277 mask = talloc_strdup(frame, "*");
2280 return NT_STATUS_NO_MEMORY;
2284 DBG_DEBUG("mask = %s\n", mask);
2287 * Remove the terminal component so
2288 * filename_convert never sees the mask.
2290 p = strrchr_m(smb_fname->base_name,'/');
2292 /* filename_convert handles a '\0' base_name. */
2293 smb_fname->base_name[0] = '\0';
2298 DBG_DEBUG("For filename_convert: smb_fname = %s\n",
2299 smb_fname_str_dbg(smb_fname));
2301 /* Convert the parent directory path. */
2302 status = filename_convert(frame,
2304 smb_fname->base_name,
2309 if (NT_STATUS_IS_OK(status)) {
2310 *_smb_fname_out = talloc_move(ctx, &smb_fname);
2311 *_mask_out = talloc_move(ctx, &mask);
2313 DBG_DEBUG("filename_convert error for %s: %s\n",
2314 smb_fname_str_dbg(smb_fname),
2323 * Build the full path from a dirfsp and dirfsp relative name
2325 struct smb_filename *full_path_from_dirfsp_atname(
2326 TALLOC_CTX *mem_ctx,
2327 const struct files_struct *dirfsp,
2328 const struct smb_filename *atname)
2330 struct smb_filename *fname = NULL;
2333 if (dirfsp == dirfsp->conn->cwd_fsp ||
2334 ISDOT(dirfsp->fsp_name->base_name) ||
2335 atname->base_name[0] == '/')
2337 path = talloc_strdup(mem_ctx, atname->base_name);
2339 path = talloc_asprintf(mem_ctx, "%s/%s",
2340 dirfsp->fsp_name->base_name,
2347 fname = synthetic_smb_fname(mem_ctx,
2349 atname->stream_name,
2354 if (fname == NULL) {