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"
32 #include "libcli/smb/reparse.h"
33 #include "source3/smbd/dir.h"
35 uint32_t ucf_flags_from_smb_request(struct smb_request
*req
)
37 uint32_t ucf_flags
= 0;
43 if (req
->posix_pathnames
) {
44 ucf_flags
|= UCF_POSIX_PATHNAMES
;
46 if (!conn_using_smb2(req
->sconn
)) {
47 ucf_flags
|= UCF_LCOMP_LNK_OK
;
50 if (req
->flags2
& FLAGS2_DFS_PATHNAMES
) {
51 ucf_flags
|= UCF_DFS_PATHNAME
;
53 if (req
->flags2
& FLAGS2_REPARSE_PATH
) {
54 ucf_flags
|= UCF_GMT_PATHNAME
;
60 uint32_t filename_create_ucf_flags(struct smb_request
*req
, uint32_t create_disposition
)
62 uint32_t ucf_flags
= 0;
64 ucf_flags
|= ucf_flags_from_smb_request(req
);
66 switch (create_disposition
) {
73 case FILE_OVERWRITE_IF
:
74 ucf_flags
|= UCF_PREP_CREATEFILE
;
81 /****************************************************************************
82 Mangle the 2nd name and check if it is then equal to the first name.
83 ****************************************************************************/
85 static bool mangled_equal(const char *name1
,
87 const struct share_params
*p
)
91 if (!name_to_8_3(name2
, mname
, False
, p
)) {
94 return strequal(name1
, mname
);
98 * Strip a valid @GMT-token from any incoming filename path,
99 * adding any NTTIME encoded in the pathname into the
100 * twrp field of the passed in smb_fname.
102 * Valid @GMT-tokens look like @GMT-YYYY-MM-DD-HH-MM-SS
103 * at the *start* of a pathname component.
105 * If twrp is passed in then smb_fname->twrp is set to that
106 * value, and the @GMT-token part of the filename is removed
107 * and does not change the stored smb_fname->twrp.
111 NTSTATUS
canonicalize_snapshot_path(struct smb_filename
*smb_fname
,
118 smb_fname
->twrp
= twrp
;
121 if (!(ucf_flags
& UCF_GMT_PATHNAME
)) {
125 found
= extract_snapshot_token(smb_fname
->base_name
, &twrp
);
130 if (smb_fname
->twrp
== 0) {
131 smb_fname
->twrp
= twrp
;
137 static bool strnorm(char *s
, int case_default
)
139 if (case_default
== CASE_UPPER
)
140 return strupper_m(s
);
142 return strlower_m(s
);
146 * Utility function to normalize case on an incoming client filename
147 * if required on this connection struct.
148 * Performs an in-place case conversion guaranteed to stay the same size.
151 static NTSTATUS
normalize_filename_case(connection_struct
*conn
,
157 if (ucf_flags
& UCF_POSIX_PATHNAMES
) {
159 * POSIX never normalizes filename case.
163 if (!conn
->case_sensitive
) {
166 if (conn
->case_preserve
) {
169 if (conn
->short_case_preserve
) {
172 ok
= strnorm(filename
, lp_default_case(SNUM(conn
)));
174 return NT_STATUS_INVALID_PARAMETER
;
179 /****************************************************************************
180 Check if two filenames are equal.
181 This needs to be careful about whether we are case sensitive.
182 ****************************************************************************/
184 static bool fname_equal(const char *name1
, const char *name2
,
187 /* Normal filename handling */
188 if (case_sensitive
) {
189 return(strcmp(name1
,name2
) == 0);
192 return(strequal(name1
,name2
));
195 static bool sname_equal(const char *name1
, const char *name2
,
199 const char *s1
= NULL
;
200 const char *s2
= NULL
;
203 const char *e1
= NULL
;
204 const char *e2
= NULL
;
208 match
= fname_equal(name1
, name2
, case_sensitive
);
213 if (name1
[0] != ':') {
216 if (name2
[0] != ':') {
220 e1
= strchr(s1
, ':');
224 n1
= PTR_DIFF(e1
, s1
);
227 e2
= strchr(s2
, ':');
231 n2
= PTR_DIFF(e2
, s2
);
234 /* Normal filename handling */
235 if (case_sensitive
) {
236 return (strncmp(s1
, s2
, n1
) == 0);
240 * We can't use strnequal() here
241 * as it takes the number of codepoints
242 * and not the number of bytes.
244 * So we make a copy before calling
247 * Note that we TALLOC_FREE() in reverse order
248 * in order to avoid memory fragmentation.
251 c1
= talloc_strndup(talloc_tos(), s1
, n1
);
252 c2
= talloc_strndup(talloc_tos(), s2
, n2
);
253 if (c1
== NULL
|| c2
== NULL
) {
256 return (strncmp(s1
, s2
, n1
) == 0);
259 match
= strequal(c1
, c2
);
265 /****************************************************************************
266 Scan a directory to find a filename, matching without case sensitivity.
267 If the name looks like a mangled name then try via the mangling functions
268 ****************************************************************************/
270 NTSTATUS
get_real_filename_full_scan_at(struct files_struct
*dirfsp
,
276 struct connection_struct
*conn
= dirfsp
->conn
;
277 struct smb_Dir
*cur_dir
= NULL
;
278 const char *dname
= NULL
;
279 char *talloced
= NULL
;
280 char *unmangled_name
= NULL
;
283 /* If we have a case-sensitive filesystem, it doesn't do us any
284 * good to search for a name. If a case variation of the name was
285 * there, then the original stat(2) would have found it.
287 if (!mangled
&& !(conn
->fs_capabilities
& FILE_CASE_SENSITIVE_SEARCH
)) {
288 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
292 * The incoming name can be mangled, and if we de-mangle it
293 * here it will not compare correctly against the filename (name2)
294 * read from the directory and then mangled by the name_to_8_3()
295 * call. We need to mangle both names or neither.
298 * Fix for bug found by Dina Fine. If in case sensitive mode then
299 * the mangle cache is no good (3 letter extension could be wrong
300 * case - so don't demangle in this case - leave as mangled and
301 * allow the mangling of the directory entry read (which is done
302 * case insensitively) to match instead. This will lead to more
303 * false positive matches but we fail completely without it. JRA.
306 if (mangled
&& !conn
->case_sensitive
) {
307 mangled
= !mangle_lookup_name_from_8_3(talloc_tos(), name
,
311 /* Name is now unmangled. */
312 name
= unmangled_name
;
316 /* open the directory */
317 status
= OpenDir_from_pathref(talloc_tos(), dirfsp
, NULL
, 0, &cur_dir
);
318 if (!NT_STATUS_IS_OK(status
)) {
319 DBG_NOTICE("scan dir didn't open dir [%s]: %s\n",
322 TALLOC_FREE(unmangled_name
);
326 /* now scan for matching names */
327 while ((dname
= ReadDirName(cur_dir
, &talloced
))) {
329 /* Is it dot or dot dot. */
330 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
331 TALLOC_FREE(talloced
);
336 * At this point dname is the unmangled name.
337 * name is either mangled or not, depending on the state
338 * of the "mangled" variable. JRA.
342 * Check mangled name against mangled name, or unmangled name
343 * against unmangled name.
346 if ((mangled
&& mangled_equal(name
,dname
,conn
->params
)) ||
347 fname_equal(name
, dname
, conn
->case_sensitive
)) {
348 /* we've found the file, change it's name and return */
349 *found_name
= talloc_strdup(mem_ctx
, dname
);
350 TALLOC_FREE(unmangled_name
);
351 TALLOC_FREE(cur_dir
);
353 TALLOC_FREE(talloced
);
354 return NT_STATUS_NO_MEMORY
;
356 TALLOC_FREE(talloced
);
359 TALLOC_FREE(talloced
);
362 TALLOC_FREE(unmangled_name
);
363 TALLOC_FREE(cur_dir
);
364 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
367 /****************************************************************************
368 Wrapper around the vfs get_real_filename and the full directory scan
370 ****************************************************************************/
372 NTSTATUS
get_real_filename_at(struct files_struct
*dirfsp
,
377 struct connection_struct
*conn
= dirfsp
->conn
;
381 mangled
= mangle_is_mangled(name
, conn
->params
);
384 status
= get_real_filename_full_scan_at(
385 dirfsp
, name
, mangled
, mem_ctx
, found_name
);
389 /* Try the vfs first to take advantage of case-insensitive stat. */
390 status
= SMB_VFS_GET_REAL_FILENAME_AT(
391 dirfsp
->conn
, dirfsp
, name
, mem_ctx
, found_name
);
394 * If the case-insensitive stat was successful, or returned an error
395 * other than EOPNOTSUPP then there is no need to fall back on the
396 * full directory scan.
398 if (NT_STATUS_IS_OK(status
) ||
399 !NT_STATUS_EQUAL(status
, NT_STATUS_NOT_SUPPORTED
)) {
403 status
= get_real_filename_full_scan_at(
404 dirfsp
, name
, mangled
, mem_ctx
, found_name
);
409 * Lightweight function to just get last component
410 * for rename / enumerate directory calls.
413 char *get_original_lcomp(TALLOC_CTX
*ctx
,
414 connection_struct
*conn
,
415 const char *filename_in
,
418 char *last_slash
= NULL
;
422 last_slash
= strrchr(filename_in
, '/');
423 if (last_slash
!= NULL
) {
424 orig_lcomp
= talloc_strdup(ctx
, last_slash
+1);
426 orig_lcomp
= talloc_strdup(ctx
, filename_in
);
428 if (orig_lcomp
== NULL
) {
431 status
= normalize_filename_case(conn
, orig_lcomp
, ucf_flags
);
432 if (!NT_STATUS_IS_OK(status
)) {
433 TALLOC_FREE(orig_lcomp
);
440 * Get the correct capitalized stream name hanging off
441 * base_fsp. Equivalent of get_real_filename(), but for streams.
443 static NTSTATUS
get_real_stream_name(
445 struct files_struct
*base_fsp
,
446 const char *stream_name
,
449 unsigned int i
, num_streams
= 0;
450 struct stream_struct
*streams
= NULL
;
453 status
= vfs_fstreaminfo(
454 base_fsp
, talloc_tos(), &num_streams
, &streams
);
455 if (!NT_STATUS_IS_OK(status
)) {
459 for (i
=0; i
<num_streams
; i
++) {
460 bool equal
= sname_equal(stream_name
, streams
[i
].name
, false);
462 DBG_DEBUG("comparing [%s] and [%s]: %sequal\n",
465 equal
? "" : "not ");
468 *_found
= talloc_move(mem_ctx
, &streams
[i
].name
);
469 TALLOC_FREE(streams
);
474 TALLOC_FREE(streams
);
475 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
478 static bool filename_split_lcomp(
483 const char **_fname_rel
,
484 const char **_streamname
)
486 const char *lcomp
= NULL
;
487 const char *fname_rel
= NULL
;
488 const char *streamname
= NULL
;
489 char *dirname
= NULL
;
491 if (name_in
[0] == '\0') {
493 dirname
= talloc_strdup(mem_ctx
, "");
494 if (dirname
== NULL
) {
500 lcomp
= strrchr_m(name_in
, '/');
503 dirname
= talloc_strndup(mem_ctx
, name_in
, lcomp
- name_in
);
504 if (dirname
== NULL
) {
511 * No slash, dir is empty
513 dirname
= talloc_strdup(mem_ctx
, "");
514 if (dirname
== NULL
) {
518 if (!posix
&& (name_in
[0] == ':')) {
520 * Special case for stream on root directory
523 streamname
= name_in
;
531 streamname
= strchr_m(fname_rel
, ':');
533 if (streamname
!= NULL
) {
534 fname_rel
= talloc_strndup(
537 streamname
- fname_rel
);
538 if (fname_rel
== NULL
) {
539 TALLOC_FREE(dirname
);
547 *_fname_rel
= fname_rel
;
548 *_streamname
= streamname
;
553 * Create the correct capitalization of a file name to be created.
555 static NTSTATUS
filename_convert_normalize_new(
557 struct connection_struct
*conn
,
561 char *name
= name_in
;
565 if (!conn
->case_preserve
||
566 (mangle_is_8_3(name
, false,
568 !conn
->short_case_preserve
)) {
570 char *normalized
= talloc_strdup(mem_ctx
, name
);
571 if (normalized
== NULL
) {
572 return NT_STATUS_NO_MEMORY
;
575 strnorm(normalized
, lp_default_case(SNUM(conn
)));
579 if (mangle_is_mangled(name
, conn
->params
)) {
581 char *unmangled
= NULL
;
583 found
= mangle_lookup_name_from_8_3(
584 mem_ctx
, name
, &unmangled
, conn
->params
);
590 if (name
!= name_in
) {
597 NTSTATUS
safe_symlink_target_path(TALLOC_CTX
*mem_ctx
,
598 const char *connectpath
,
604 char *abs_target
= NULL
;
605 char *abs_target_canon
= NULL
;
606 const char *relative
= NULL
;
608 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
610 DBG_DEBUG("connectpath [%s] target [%s] unparsed [%zu]\n",
611 connectpath
, target
, unparsed
);
613 if (target
[0] == '/') {
614 abs_target
= talloc_strdup(mem_ctx
, target
);
615 } else if (dir
== NULL
) {
616 abs_target
= talloc_asprintf(mem_ctx
,
620 } else if (dir
[0] == '/') {
621 abs_target
= talloc_asprintf(mem_ctx
,
626 abs_target
= talloc_asprintf(mem_ctx
,
632 if (abs_target
== NULL
) {
636 abs_target_canon
= canonicalize_absolute_path(abs_target
, abs_target
);
637 if (abs_target_canon
== NULL
) {
641 DBG_DEBUG("abs_target_canon=%s\n", abs_target_canon
);
643 in_share
= subdir_of(
644 connectpath
, strlen(connectpath
), abs_target_canon
, &relative
);
646 DBG_DEBUG("wide link to %s\n", abs_target_canon
);
647 status
= (unparsed
!= 0) ? NT_STATUS_OBJECT_PATH_NOT_FOUND
648 : NT_STATUS_OBJECT_NAME_NOT_FOUND
;
652 *_relative
= talloc_strdup(mem_ctx
, relative
);
653 if (*_relative
== NULL
) {
657 status
= NT_STATUS_OK
;
659 TALLOC_FREE(abs_target
);
664 * Split up name_in as sent by the client into a directory pathref fsp
665 * and a relative smb_filename.
667 static NTSTATUS
filename_convert_dirfsp_nosymlink(
669 connection_struct
*conn
,
673 struct files_struct
**_dirfsp
,
674 struct smb_filename
**_smb_fname
,
675 struct reparse_data_buffer
**_symlink_err
)
677 struct smb_filename
*smb_dirname
= NULL
;
678 struct smb_filename
*smb_fname_rel
= NULL
;
679 struct smb_filename
*smb_fname
= NULL
;
680 struct reparse_data_buffer
*symlink_err
= NULL
;
681 const bool posix
= (ucf_flags
& UCF_POSIX_PATHNAMES
);
682 char *dirname
= NULL
;
683 const char *fname_rel
= NULL
;
684 const char *streamname
= NULL
;
685 char *saved_streamname
= NULL
;
686 struct files_struct
*base_fsp
= NULL
;
688 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
690 SMB_ASSERT(!(ucf_flags
& UCF_DFS_PATHNAME
));
692 if (is_fake_file_path(name_in
)) {
693 const struct timespec omit
= make_omit_timespec();
694 smb_fname
= synthetic_smb_fname_split(mem_ctx
, name_in
, posix
);
695 if (smb_fname
== NULL
) {
696 return NT_STATUS_NO_MEMORY
;
698 smb_fname
->st
= (SMB_STRUCT_STAT
){
700 .st_ex_mode
= S_IFREG
| 0644,
707 *_dirfsp
= conn
->cwd_fsp
;
708 *_smb_fname
= smb_fname
;
713 * Catch an invalid path of "." before we
714 * call filename_split_lcomp(). We need to
715 * do this as filename_split_lcomp() will
716 * use "." for the missing relative component
717 * when an empty name_in path is sent by
720 if (ISDOT(name_in
)) {
721 status
= NT_STATUS_OBJECT_NAME_INVALID
;
725 ok
= filename_split_lcomp(
733 status
= NT_STATUS_NO_MEMORY
;
737 if ((streamname
!= NULL
) &&
738 ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
) == 0)) {
739 status
= NT_STATUS_OBJECT_NAME_INVALID
;
744 bool name_has_wild
= ms_has_wild(dirname
);
745 name_has_wild
|= ms_has_wild(fname_rel
);
747 status
= NT_STATUS_OBJECT_NAME_INVALID
;
752 if (dirname
[0] == '\0') {
753 status
= synthetic_pathref(
760 posix
? SMB_FILENAME_POSIX_PATH
: 0,
763 status
= normalize_filename_case(conn
, dirname
, ucf_flags
);
764 if (!NT_STATUS_IS_OK(status
)) {
765 DBG_ERR("normalize_filename_case %s failed: %s\n",
771 status
= openat_pathref_fsp_nosymlink(mem_ctx
,
780 if (NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
)) {
781 struct symlink_reparse_struct
782 *lnk
= &symlink_err
->parsed
.lnk
;
783 size_t unparsed
= lnk
->unparsed_path_length
;
784 size_t name_in_len
, dirname_len
;
786 name_in_len
= strlen(name_in
);
787 dirname_len
= strlen(dirname
);
789 SMB_ASSERT(name_in_len
>= dirname_len
);
791 unparsed
+= (name_in_len
- dirname_len
);
793 if (unparsed
> UINT16_MAX
) {
794 status
= NT_STATUS_BUFFER_OVERFLOW
;
798 lnk
->unparsed_path_length
= unparsed
;
799 *_symlink_err
= symlink_err
;
805 if (!NT_STATUS_IS_OK(status
)) {
806 DBG_DEBUG("opening directory %s failed: %s\n",
809 TALLOC_FREE(dirname
);
811 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
813 * Except ACCESS_DENIED, everything else leads
816 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
822 if (!VALID_STAT_OF_DIR(smb_dirname
->st
)) {
823 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
826 smb_dirname
->fsp
->fsp_flags
.is_directory
= true;
829 * Only look at bad last component values
830 * once we know we have a valid directory. That
831 * way we won't confuse error messages from
832 * opening the directory path with error
833 * messages from a bad last component.
836 /* Relative filename can't be empty */
837 if (fname_rel
[0] == '\0') {
838 status
= NT_STATUS_OBJECT_NAME_INVALID
;
842 /* Relative filename can't be ".." */
843 if (ISDOTDOT(fname_rel
)) {
844 status
= NT_STATUS_OBJECT_NAME_INVALID
;
847 /* Relative name can only be dot if directory is empty. */
848 if (ISDOT(fname_rel
) && dirname
[0] != '\0') {
849 status
= NT_STATUS_OBJECT_NAME_INVALID
;
853 TALLOC_FREE(dirname
);
855 smb_fname_rel
= synthetic_smb_fname(
861 posix
? SMB_FILENAME_POSIX_PATH
: 0);
862 if (smb_fname_rel
== NULL
) {
863 status
= NT_STATUS_NO_MEMORY
;
867 if ((conn
->fs_capabilities
& FILE_NAMED_STREAMS
) &&
868 is_named_stream(smb_fname_rel
)) {
870 * Find the base_fsp first without the stream.
872 saved_streamname
= smb_fname_rel
->stream_name
;
873 smb_fname_rel
->stream_name
= NULL
;
876 status
= normalize_filename_case(
877 conn
, smb_fname_rel
->base_name
, ucf_flags
);
878 if (!NT_STATUS_IS_OK(status
)) {
879 DBG_ERR("normalize_filename_case %s failed: %s\n",
880 smb_fname_rel
->base_name
,
885 status
= openat_pathref_fsp_lcomp(smb_dirname
->fsp
,
889 if (NT_STATUS_IS_OK(status
) && S_ISLNK(smb_fname_rel
->st
.st_ex_mode
)) {
892 * Upper layers might need the link target. Here we
893 * still have the relname around, get the symlink err.
895 status
= read_symlink_reparse(mem_ctx
,
899 if (!NT_STATUS_IS_OK(status
)) {
900 DBG_DEBUG("Could not read symlink for %s: %s\n",
902 smb_fname_rel
->fsp
->fsp_name
),
908 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
) &&
909 !VALID_STAT(smb_fname_rel
->st
)) {
911 char *normalized
= NULL
;
914 * Creating a new file
917 status
= filename_convert_normalize_new(
920 smb_fname_rel
->base_name
,
922 if (!NT_STATUS_IS_OK(status
)) {
923 DBG_DEBUG("filename_convert_normalize_new failed: "
928 if (normalized
!= NULL
) {
929 smb_fname_rel
->base_name
= normalized
;
932 smb_fname_rel
->stream_name
= saved_streamname
;
934 smb_fname
= full_path_from_dirfsp_atname(
935 mem_ctx
, smb_dirname
->fsp
, smb_fname_rel
);
936 if (smb_fname
== NULL
) {
937 status
= NT_STATUS_NO_MEMORY
;
943 if (NT_STATUS_EQUAL(status
, NT_STATUS_NETWORK_OPEN_RESTRICTION
)) {
944 /* A vetoed file, pretend it's not there */
945 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
947 if (!NT_STATUS_IS_OK(status
)) {
951 if (saved_streamname
== NULL
) {
952 /* smb_fname must be allocated off mem_ctx. */
953 smb_fname
= cp_smb_filename(mem_ctx
,
954 smb_fname_rel
->fsp
->fsp_name
);
955 if (smb_fname
== NULL
) {
958 status
= move_smb_fname_fsp_link(smb_fname
, smb_fname_rel
);
959 if (!NT_STATUS_IS_OK(status
)) {
965 base_fsp
= smb_fname_rel
->fsp
;
966 smb_fname_fsp_unlink(smb_fname_rel
);
967 SET_STAT_INVALID(smb_fname_rel
->st
);
969 smb_fname_rel
->stream_name
= saved_streamname
;
971 status
= open_stream_pathref_fsp(&base_fsp
, smb_fname_rel
);
973 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
) &&
974 !conn
->case_sensitive
) {
977 status
= get_real_stream_name(
980 smb_fname_rel
->stream_name
,
983 if (NT_STATUS_IS_OK(status
)) {
984 smb_fname_rel
->stream_name
= found
;
986 status
= open_stream_pathref_fsp(
987 &base_fsp
, smb_fname_rel
);
991 if (NT_STATUS_IS_OK(status
)) {
992 /* smb_fname must be allocated off mem_ctx. */
993 smb_fname
= cp_smb_filename(mem_ctx
,
994 smb_fname_rel
->fsp
->fsp_name
);
995 if (smb_fname
== NULL
) {
998 status
= move_smb_fname_fsp_link(smb_fname
, smb_fname_rel
);
999 if (!NT_STATUS_IS_OK(status
)) {
1005 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1007 * Creating a new stream
1009 * We should save the already-open base fsp for
1010 * create_file_unixpath() somehow.
1012 smb_fname
= full_path_from_dirfsp_atname(
1013 mem_ctx
, smb_dirname
->fsp
, smb_fname_rel
);
1014 if (smb_fname
== NULL
) {
1015 status
= NT_STATUS_NO_MEMORY
;
1019 * When open_stream_pathref_fsp() returns
1020 * NT_STATUS_OBJECT_NAME_NOT_FOUND, smb_fname_rel->fsp
1021 * has been set to NULL, so we must free base_fsp separately
1022 * to prevent fd-leaks when opening a stream that doesn't
1026 file_free(NULL
, base_fsp
);
1031 if (!NT_STATUS_IS_OK(status
)) {
1036 *_dirfsp
= smb_dirname
->fsp
;
1037 *_smb_fname
= smb_fname
;
1038 *_symlink_err
= symlink_err
;
1040 smb_fname_fsp_unlink(smb_fname_rel
);
1041 TALLOC_FREE(smb_fname_rel
);
1042 return NT_STATUS_OK
;
1046 * If open_stream_pathref_fsp() returns an error, smb_fname_rel->fsp
1047 * has been set to NULL, so we must free base_fsp separately
1048 * to prevent fd-leaks when opening a stream that doesn't
1051 if (base_fsp
!= NULL
) {
1053 file_free(NULL
, base_fsp
);
1056 TALLOC_FREE(dirname
);
1057 TALLOC_FREE(smb_dirname
);
1058 TALLOC_FREE(smb_fname_rel
);
1062 NTSTATUS
filename_convert_dirfsp(
1063 TALLOC_CTX
*mem_ctx
,
1064 connection_struct
*conn
,
1065 const char *name_in
,
1068 struct files_struct
**_dirfsp
,
1069 struct smb_filename
**_smb_fname
)
1071 struct reparse_data_buffer
*symlink_err
= NULL
;
1072 struct symlink_reparse_struct
*lnk
= NULL
;
1074 char *target
= NULL
;
1075 char *safe_target
= NULL
;
1076 size_t symlink_redirects
= 0;
1080 if (symlink_redirects
> 40) {
1081 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1084 status
= filename_convert_dirfsp_nosymlink(mem_ctx
,
1093 if (NT_STATUS_IS_OK(status
) && S_ISLNK((*_smb_fname
)->st
.st_ex_mode
)) {
1095 * lcomp is a symlink
1097 if (ucf_flags
& UCF_LCOMP_LNK_OK
) {
1098 TALLOC_FREE(symlink_err
);
1099 return NT_STATUS_OK
;
1101 close_file_free(NULL
, _dirfsp
, ERROR_CLOSE
);
1102 status
= NT_STATUS_STOPPED_ON_SYMLINK
;
1105 if (!NT_STATUS_EQUAL(status
, NT_STATUS_STOPPED_ON_SYMLINK
)) {
1108 lnk
= &symlink_err
->parsed
.lnk
;
1111 * If we're on an MSDFS share, see if this is
1114 if (lp_host_msdfs() && lp_msdfs_root(SNUM(conn
)) &&
1115 strnequal(lnk
->substitute_name
, "msdfs:", 6))
1117 TALLOC_FREE(*_smb_fname
);
1118 TALLOC_FREE(symlink_err
);
1119 return NT_STATUS_PATH_NOT_COVERED
;
1122 if (!lp_follow_symlinks(SNUM(conn
))) {
1123 status
= (lnk
->unparsed_path_length
== 0)
1124 ? NT_STATUS_OBJECT_NAME_NOT_FOUND
1125 : NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1126 TALLOC_FREE(symlink_err
);
1131 * Right now, SMB2 and SMB1 always traverse symlinks
1132 * within the share. SMB1+POSIX traverses non-terminal
1133 * symlinks within the share.
1135 * When we add SMB2+POSIX we need to return
1136 * a NT_STATUS_STOPPED_ON_SYMLINK error here, using the
1137 * symlink target data read below if SMB2+POSIX has
1138 * UCF_POSIX_PATHNAMES set to cause the client to
1139 * resolve all symlinks locally.
1142 ret
= symlink_target_path(mem_ctx
,
1144 lnk
->unparsed_path_length
,
1145 lnk
->substitute_name
,
1146 lnk
->substitute_name
[0] != '/',
1150 return map_nt_error_from_unix(ret
);
1153 status
= safe_symlink_target_path(mem_ctx
,
1157 lnk
->unparsed_path_length
,
1159 TALLOC_FREE(symlink_err
);
1160 if (!NT_STATUS_IS_OK(status
)) {
1163 name_in
= safe_target
;
1165 symlink_redirects
+= 1;
1170 char *full_path_from_dirfsp_at_basename(TALLOC_CTX
*mem_ctx
,
1171 const struct files_struct
*dirfsp
,
1172 const char *at_base_name
)
1176 if (dirfsp
== dirfsp
->conn
->cwd_fsp
||
1177 ISDOT(dirfsp
->fsp_name
->base_name
) || at_base_name
[0] == '/') {
1178 path
= talloc_strdup(mem_ctx
, at_base_name
);
1180 path
= talloc_asprintf(mem_ctx
,
1182 dirfsp
->fsp_name
->base_name
,
1190 * Build the full path from a dirfsp and dirfsp relative name
1192 struct smb_filename
*
1193 full_path_from_dirfsp_atname(TALLOC_CTX
*mem_ctx
,
1194 const struct files_struct
*dirfsp
,
1195 const struct smb_filename
*atname
)
1197 struct smb_filename
*fname
= NULL
;
1200 path
= full_path_from_dirfsp_at_basename(mem_ctx
,
1207 fname
= synthetic_smb_fname(mem_ctx
,
1209 atname
->stream_name
,
1214 if (fname
== NULL
) {