Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into ctdb-merge
[amitay/samba.git] / source3 / smbd / filename.c
1 /*
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
8
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.
13
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.
18
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/>.
21 */
22
23 /*
24  * New hash table stat cache code added by Ying Chen.
25  */
26
27 #include "includes.h"
28
29 static bool scan_directory(connection_struct *conn, const char *path,
30                            char *name, char **found_name);
31 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
32                                   connection_struct *conn,
33                                   const char *orig_path,
34                                   const char *basepath,
35                                   const char *streamname,
36                                   SMB_STRUCT_STAT *pst,
37                                   char **path);
38
39 /****************************************************************************
40  Mangle the 2nd name and check if it is then equal to the first name.
41 ****************************************************************************/
42
43 static bool mangled_equal(const char *name1,
44                         const char *name2,
45                         const struct share_params *p)
46 {
47         char mname[13];
48
49         if (!name_to_8_3(name2, mname, False, p)) {
50                 return False;
51         }
52         return strequal(name1, mname);
53 }
54
55 /****************************************************************************
56  Cope with the differing wildcard and non-wildcard error cases.
57 ****************************************************************************/
58
59 static NTSTATUS determine_path_error(const char *name,
60                         bool allow_wcard_last_component)
61 {
62         const char *p;
63
64         if (!allow_wcard_last_component) {
65                 /* Error code within a pathname. */
66                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
67         }
68
69         /* We're terminating here so we
70          * can be a little slower and get
71          * the error code right. Windows
72          * treats the last part of the pathname
73          * separately I think, so if the last
74          * component is a wildcard then we treat
75          * this ./ as "end of component" */
76
77         p = strchr(name, '/');
78
79         if (!p && (ms_has_wild(name) || ISDOT(name))) {
80                 /* Error code at the end of a pathname. */
81                 return NT_STATUS_OBJECT_NAME_INVALID;
82         } else {
83                 /* Error code within a pathname. */
84                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
85         }
86 }
87
88 /****************************************************************************
89 This routine is called to convert names from the dos namespace to unix
90 namespace. It needs to handle any case conversions, mangling, format
91 changes etc.
92
93 We assume that we have already done a chdir() to the right "root" directory
94 for this service.
95
96 The function will return an NTSTATUS error if some part of the name except for
97 the last part cannot be resolved, else NT_STATUS_OK.
98
99 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't
100 get any fatal errors that should immediately terminate the calling
101 SMB processing whilst resolving.
102
103 If the saved_last_component != 0, then the unmodified last component
104 of the pathname is returned there. This is used in an exceptional
105 case in reply_mv (so far). If saved_last_component == 0 then nothing
106 is returned there.
107
108 If last_component_wcard is true then a MS wildcard was detected and
109 should be allowed in the last component of the path only.
110
111 On exit from unix_convert, if *pst was not null, then the file stat
112 struct will be returned if the file exists and was found, if not this
113 stat struct will be filled with zeros (and this can be detected by checking
114 for nlinks = 0, which can never be true for any file).
115 ****************************************************************************/
116
117 NTSTATUS unix_convert(TALLOC_CTX *ctx,
118                         connection_struct *conn,
119                         const char *orig_path,
120                         bool allow_wcard_last_component,
121                         char **pp_conv_path,
122                         char **pp_saved_last_component,
123                         SMB_STRUCT_STAT *pst)
124 {
125         SMB_STRUCT_STAT st;
126         char *start, *end;
127         char *dirpath = NULL;
128         char *name = NULL;
129         char *stream = NULL;
130         bool component_was_mangled = False;
131         bool name_has_wildcard = False;
132         NTSTATUS result;
133
134         SET_STAT_INVALID(*pst);
135         *pp_conv_path = NULL;
136         if(pp_saved_last_component) {
137                 *pp_saved_last_component = NULL;
138         }
139
140         if (conn->printer) {
141                 /* we don't ever use the filenames on a printer share as a
142                         filename - so don't convert them */
143                 if (!(*pp_conv_path = talloc_strdup(ctx,orig_path))) {
144                         return NT_STATUS_NO_MEMORY;
145                 }
146                 return NT_STATUS_OK;
147         }
148
149         DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path));
150
151         /*
152          * Conversion to basic unix format is already done in
153          * check_path_syntax().
154          */
155
156         /*
157          * Names must be relative to the root of the service - any leading /.
158          * and trailing /'s should have been trimmed by check_path_syntax().
159          */
160
161 #ifdef DEVELOPER
162         SMB_ASSERT(*orig_path != '/');
163 #endif
164
165         /*
166          * If we trimmed down to a single '\0' character
167          * then we should use the "." directory to avoid
168          * searching the cache, but not if we are in a
169          * printing share.
170          * As we know this is valid we can return true here.
171          */
172
173         if (!*orig_path) {
174                 if (!(name = talloc_strdup(ctx,"."))) {
175                         return NT_STATUS_NO_MEMORY;
176                 }
177                 if (SMB_VFS_STAT(conn,name,&st) == 0) {
178                         *pst = st;
179                 } else {
180                         return map_nt_error_from_unix(errno);
181                 }
182                 DEBUG(5,("conversion finished \"\" -> %s\n",name));
183                 goto done;
184         }
185
186         if (orig_path[0] == '.' && (orig_path[1] == '/' ||
187                                 orig_path[1] == '\0')) {
188                 /* Start of pathname can't be "." only. */
189                 if (orig_path[1] == '\0' || orig_path[2] == '\0') {
190                         result = NT_STATUS_OBJECT_NAME_INVALID;
191                 } else {
192                         result =determine_path_error(
193                                 &orig_path[2], allow_wcard_last_component);
194                 }
195                 return result;
196         }
197
198         /*
199          * Ensure saved_last_component is valid even if file exists.
200          */
201
202         if(pp_saved_last_component) {
203                 end = strrchr_m(orig_path, '/');
204                 if (end) {
205                         *pp_saved_last_component = talloc_strdup(ctx, end + 1);
206                 } else {
207                         *pp_saved_last_component = talloc_strdup(ctx,
208                                                         orig_path);
209                 }
210         }
211
212         if (!(name = talloc_strdup(ctx, orig_path))) {
213                 DEBUG(0, ("talloc_strdup failed\n"));
214                 return NT_STATUS_NO_MEMORY;
215         }
216
217         if (!lp_posix_pathnames()) {
218                 stream = strchr_m(name, ':');
219
220                 if (stream != NULL) {
221                         char *tmp = talloc_strdup(ctx, stream);
222                         if (tmp == NULL) {
223                                 TALLOC_FREE(name);
224                                 return NT_STATUS_NO_MEMORY;
225                         }
226                         *stream = '\0';
227                         stream = tmp;
228                 }
229         }
230
231         /*
232          * Large directory fix normalization. If we're case sensitive, and
233          * the case preserving parameters are set to "no", normalize the case of
234          * the incoming filename from the client WHETHER IT EXISTS OR NOT !
235          * This is in conflict with the current (3.0.20) man page, but is
236          * what people expect from the "large directory howto". I'll update
237          * the man page. Thanks to jht@samba.org for finding this. JRA.
238          */
239
240         if (conn->case_sensitive && !conn->case_preserve &&
241                         !conn->short_case_preserve) {
242                 strnorm(name, lp_defaultcase(SNUM(conn)));
243         }
244
245         start = name;
246
247         /* If we're providing case insentive semantics or
248          * the underlying filesystem is case insensitive,
249          * then a case-normalized hit in the stat-cache is
250          * authoratitive. JRA.
251          */
252
253         if((!conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) &&
254                         stat_cache_lookup(conn, &name, &dirpath, &start, &st)) {
255                 *pst = st;
256                 goto done;
257         }
258
259         /*
260          * Make sure "dirpath" is an allocated string, we use this for
261          * building the directories with asprintf and free it.
262          */
263
264         if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) {
265                 DEBUG(0, ("talloc_strdup failed\n"));
266                 TALLOC_FREE(name);
267                 return NT_STATUS_NO_MEMORY;
268         }
269
270         /*
271          * stat the name - if it exists then we are all done!
272          */
273
274         if (SMB_VFS_STAT(conn,name,&st) == 0) {
275                 /* Ensure we catch all names with in "/."
276                    this is disallowed under Windows. */
277                 const char *p = strstr(name, "/."); /* mb safe. */
278                 if (p) {
279                         if (p[2] == '/') {
280                                 /* Error code within a pathname. */
281                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
282                                 goto fail;
283                         } else if (p[2] == '\0') {
284                                 /* Error code at the end of a pathname. */
285                                 result = NT_STATUS_OBJECT_NAME_INVALID;
286                                 goto fail;
287                         }
288                 }
289                 stat_cache_add(orig_path, name, conn->case_sensitive);
290                 DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
291                 *pst = st;
292                 goto done;
293         }
294
295         DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
296                                 name, dirpath, start));
297
298         /*
299          * A special case - if we don't have any mangling chars and are case
300          * sensitive or the underlying filesystem is case insentive then searching
301          * won't help.
302          */
303
304         if ((conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) &&
305                         !mangle_is_mangled(name, conn->params)) {
306                 goto done;
307         }
308
309         /*
310          * is_mangled() was changed to look at an entire pathname, not
311          * just a component. JRA.
312          */
313
314         if (mangle_is_mangled(start, conn->params)) {
315                 component_was_mangled = True;
316         }
317
318         /*
319          * Now we need to recursively match the name against the real
320          * directory structure.
321          */
322
323         /*
324          * Match each part of the path name separately, trying the names
325          * as is first, then trying to scan the directory for matching names.
326          */
327
328         for (; start ; start = (end?end+1:(char *)NULL)) {
329                 /*
330                  * Pinpoint the end of this section of the filename.
331                  */
332                 /* mb safe. '/' can't be in any encoded char. */
333                 end = strchr(start, '/');
334
335                 /*
336                  * Chop the name at this point.
337                  */
338                 if (end) {
339                         *end = 0;
340                 }
341
342                 if (pp_saved_last_component) {
343                         TALLOC_FREE(*pp_saved_last_component);
344                         *pp_saved_last_component = talloc_strdup(ctx,
345                                                         end ? end + 1 : start);
346                         if (!*pp_saved_last_component) {
347                                 DEBUG(0, ("talloc failed\n"));
348                                 return NT_STATUS_NO_MEMORY;
349                         }
350                 }
351
352                 /* The name cannot have a component of "." */
353
354                 if (ISDOT(start)) {
355                         if (!end)  {
356                                 /* Error code at the end of a pathname. */
357                                 result = NT_STATUS_OBJECT_NAME_INVALID;
358                         } else {
359                                 result = determine_path_error(end+1,
360                                                 allow_wcard_last_component);
361                         }
362                         goto fail;
363                 }
364
365                 /* The name cannot have a wildcard if it's not
366                    the last component. */
367
368                 name_has_wildcard = ms_has_wild(start);
369
370                 /* Wildcard not valid anywhere. */
371                 if (name_has_wildcard && !allow_wcard_last_component) {
372                         result = NT_STATUS_OBJECT_NAME_INVALID;
373                         goto fail;
374                 }
375
376                 /* Wildcards never valid within a pathname. */
377                 if (name_has_wildcard && end) {
378                         result = NT_STATUS_OBJECT_NAME_INVALID;
379                         goto fail;
380                 }
381
382                 /*
383                  * Check if the name exists up to this point.
384                  */
385
386                 if (SMB_VFS_STAT(conn,name, &st) == 0) {
387                         /*
388                          * It exists. it must either be a directory or this must
389                          * be the last part of the path for it to be OK.
390                          */
391                         if (end && !(st.st_mode & S_IFDIR)) {
392                                 /*
393                                  * An intermediate part of the name isn't
394                                  * a directory.
395                                  */
396                                 DEBUG(5,("Not a dir %s\n",start));
397                                 *end = '/';
398                                 /*
399                                  * We need to return the fact that the
400                                  * intermediate name resolution failed. This
401                                  * is used to return an error of ERRbadpath
402                                  * rather than ERRbadfile. Some Windows
403                                  * applications depend on the difference between
404                                  * these two errors.
405                                  */
406                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
407                                 goto fail;
408                         }
409
410                         if (!end) {
411                                 /*
412                                  * We just scanned for, and found the end of
413                                  * the path. We must return the valid stat
414                                  * struct. JRA.
415                                  */
416
417                                 *pst = st;
418                         }
419
420                 } else {
421                         char *found_name = NULL;
422
423                         /* Stat failed - ensure we don't use it. */
424                         SET_STAT_INVALID(st);
425
426                         /*
427                          * Reset errno so we can detect
428                          * directory open errors.
429                          */
430                         errno = 0;
431
432                         /*
433                          * Try to find this part of the path in the directory.
434                          */
435
436                         if (name_has_wildcard ||
437                             !scan_directory(conn, dirpath,
438                                     start, &found_name)) {
439                                 char *unmangled;
440
441                                 if (end) {
442                                         /*
443                                          * An intermediate part of the name
444                                          * can't be found.
445                                          */
446                                         DEBUG(5,("Intermediate not found %s\n",
447                                                         start));
448                                         *end = '/';
449
450                                         /*
451                                          * We need to return the fact that the
452                                          * intermediate name resolution failed.
453                                          * This is used to return an error of
454                                          * ERRbadpath rather than ERRbadfile.
455                                          * Some Windows applications depend on
456                                          * the difference between these two
457                                          * errors.
458                                          */
459
460                                         /*
461                                          * ENOENT, ENOTDIR and ELOOP all map
462                                          * to NT_STATUS_OBJECT_PATH_NOT_FOUND
463                                          * in the filename walk.
464                                          */
465
466                                         if (errno == ENOENT ||
467                                                         errno == ENOTDIR ||
468                                                         errno == ELOOP) {
469                                                 result =
470                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
471                                         }
472                                         else {
473                                                 result =
474                                                 map_nt_error_from_unix(errno);
475                                         }
476                                         goto fail;
477                                 }
478
479                                 /* ENOENT is the only valid error here. */
480                                 if (errno != ENOENT) {
481                                         /*
482                                          * ENOTDIR and ELOOP both map to
483                                          * NT_STATUS_OBJECT_PATH_NOT_FOUND
484                                          * in the filename walk.
485                                          */
486                                         if (errno == ENOTDIR ||
487                                                         errno == ELOOP) {
488                                                 result =
489                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
490                                         }
491                                         else {
492                                                 result =
493                                                 map_nt_error_from_unix(errno);
494                                         }
495                                         goto fail;
496                                 }
497
498                                 /*
499                                  * Just the last part of the name doesn't exist.
500                                  * We need to strupper() or strlower() it as
501                                  * this conversion may be used for file creation
502                                  * purposes. Fix inspired by
503                                  * Thomas Neumann <t.neumann@iku-ag.de>.
504                                  */
505                                 if (!conn->case_preserve ||
506                                     (mangle_is_8_3(start, False,
507                                                    conn->params) &&
508                                                  !conn->short_case_preserve)) {
509                                         strnorm(start,
510                                                 lp_defaultcase(SNUM(conn)));
511                                 }
512
513                                 /*
514                                  * check on the mangled stack to see if we can
515                                  * recover the base of the filename.
516                                  */
517
518                                 if (mangle_is_mangled(start, conn->params)
519                                     && mangle_lookup_name_from_8_3(ctx,
520                                                         start,
521                                                         &unmangled,
522                                                         conn->params)) {
523                                         char *tmp;
524                                         size_t start_ofs = start - name;
525
526                                         if (*dirpath != '\0') {
527                                                 tmp = talloc_asprintf(ctx,
528                                                         "%s/%s", dirpath,
529                                                         unmangled);
530                                                 TALLOC_FREE(unmangled);
531                                         }
532                                         else {
533                                                 tmp = unmangled;
534                                         }
535                                         if (tmp == NULL) {
536                                                 DEBUG(0, ("talloc failed\n"));
537                                                 return NT_STATUS_NO_MEMORY;
538                                         }
539                                         TALLOC_FREE(name);
540                                         name = tmp;
541                                         start = name + start_ofs;
542                                         end = start + strlen(start);
543                                 }
544
545                                 DEBUG(5,("New file %s\n",start));
546                                 goto done;
547                         }
548
549
550                         /*
551                          * Restore the rest of the string. If the string was
552                          * mangled the size may have changed.
553                          */
554                         if (end) {
555                                 char *tmp;
556                                 size_t start_ofs = start - name;
557
558                                 if (*dirpath != '\0') {
559                                         tmp = talloc_asprintf(ctx,
560                                                 "%s/%s/%s", dirpath,
561                                                 found_name, end+1);
562                                 }
563                                 else {
564                                         tmp = talloc_asprintf(ctx,
565                                                 "%s/%s", found_name,
566                                                 end+1);
567                                 }
568                                 if (tmp == NULL) {
569                                         DEBUG(0, ("talloc_asprintf failed\n"));
570                                         return NT_STATUS_NO_MEMORY;
571                                 }
572                                 TALLOC_FREE(name);
573                                 name = tmp;
574                                 start = name + start_ofs;
575                                 end = start + strlen(found_name);
576                                 *end = '\0';
577                         } else {
578                                 char *tmp;
579                                 size_t start_ofs = start - name;
580
581                                 if (*dirpath != '\0') {
582                                         tmp = talloc_asprintf(ctx,
583                                                 "%s/%s", dirpath,
584                                                 found_name);
585                                 } else {
586                                         tmp = talloc_strdup(ctx,
587                                                 found_name);
588                                 }
589                                 if (tmp == NULL) {
590                                         DEBUG(0, ("talloc failed\n"));
591                                         return NT_STATUS_NO_MEMORY;
592                                 }
593                                 TALLOC_FREE(name);
594                                 name = tmp;
595                                 start = name + start_ofs;
596
597                                 /*
598                                  * We just scanned for, and found the end of
599                                  * the path. We must return a valid stat struct
600                                  * if it exists. JRA.
601                                  */
602
603                                 if (SMB_VFS_STAT(conn,name, &st) == 0) {
604                                         *pst = st;
605                                 } else {
606                                         SET_STAT_INVALID(st);
607                                 }
608                         }
609
610                         TALLOC_FREE(found_name);
611                 } /* end else */
612
613 #ifdef DEVELOPER
614                 if (VALID_STAT(st) &&
615                     get_delete_on_close_flag(vfs_file_id_from_sbuf(conn,
616                                     &st))) {
617                         result = NT_STATUS_DELETE_PENDING;
618                         goto fail;
619                 }
620 #endif
621
622                 /*
623                  * Add to the dirpath that we have resolved so far.
624                  */
625
626                 if (*dirpath != '\0') {
627                         char *tmp = talloc_asprintf(ctx,
628                                         "%s/%s", dirpath, start);
629                         if (!tmp) {
630                                 DEBUG(0, ("talloc_asprintf failed\n"));
631                                 return NT_STATUS_NO_MEMORY;
632                         }
633                         TALLOC_FREE(dirpath);
634                         dirpath = tmp;
635                 }
636                 else {
637                         TALLOC_FREE(dirpath);
638                         if (!(dirpath = talloc_strdup(ctx,start))) {
639                                 DEBUG(0, ("talloc_strdup failed\n"));
640                                 return NT_STATUS_NO_MEMORY;
641                         }
642                 }
643
644                 /*
645                  * Don't cache a name with mangled or wildcard components
646                  * as this can change the size.
647                  */
648
649                 if(!component_was_mangled && !name_has_wildcard) {
650                         stat_cache_add(orig_path, dirpath,
651                                         conn->case_sensitive);
652                 }
653
654                 /*
655                  * Restore the / that we wiped out earlier.
656                  */
657                 if (end) {
658                         *end = '/';
659                 }
660         }
661
662         /*
663          * Don't cache a name with mangled or wildcard components
664          * as this can change the size.
665          */
666
667         if(!component_was_mangled && !name_has_wildcard) {
668                 stat_cache_add(orig_path, name, conn->case_sensitive);
669         }
670
671         /*
672          * The name has been resolved.
673          */
674
675         DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
676
677  done:
678         if (stream != NULL) {
679                 char *tmp = NULL;
680
681                 result = build_stream_path(ctx, conn, orig_path, name, stream,
682                                            pst, &tmp);
683                 if (!NT_STATUS_IS_OK(result)) {
684                         goto fail;
685                 }
686
687                 DEBUG(10, ("build_stream_path returned %s\n", tmp));
688
689                 TALLOC_FREE(name);
690                 name = tmp;
691         }
692         *pp_conv_path = name;
693         TALLOC_FREE(dirpath);
694         return NT_STATUS_OK;
695  fail:
696         DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
697         if (*dirpath != '\0') {
698                 *pp_conv_path = talloc_asprintf(ctx,
699                                 "%s/%s", dirpath, start);
700         } else {
701                 *pp_conv_path = talloc_strdup(ctx, start);
702         }
703         if (!*pp_conv_path) {
704                 DEBUG(0, ("talloc_asprintf failed\n"));
705                 return NT_STATUS_NO_MEMORY;
706         }
707         TALLOC_FREE(name);
708         TALLOC_FREE(dirpath);
709         return result;
710 }
711
712 /****************************************************************************
713  Check a filename - possibly calling check_reduced_name.
714  This is called by every routine before it allows an operation on a filename.
715  It does any final confirmation necessary to ensure that the filename is
716  a valid one for the user to access.
717 ****************************************************************************/
718
719 NTSTATUS check_name(connection_struct *conn, const char *name)
720 {
721         if (IS_VETO_PATH(conn, name))  {
722                 /* Is it not dot or dot dot. */
723                 if (!((name[0] == '.') && (!name[1] ||
724                                         (name[1] == '.' && !name[2])))) {
725                         DEBUG(5,("check_name: file path name %s vetoed\n",
726                                                 name));
727                         return map_nt_error_from_unix(ENOENT);
728                 }
729         }
730
731         if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
732                 NTSTATUS status = check_reduced_name(conn,name);
733                 if (!NT_STATUS_IS_OK(status)) {
734                         DEBUG(5,("check_name: name %s failed with %s\n",name,
735                                                 nt_errstr(status)));
736                         return status;
737                 }
738         }
739
740         return NT_STATUS_OK;
741 }
742
743 /****************************************************************************
744  Check if two filenames are equal.
745  This needs to be careful about whether we are case sensitive.
746 ****************************************************************************/
747
748 static bool fname_equal(const char *name1, const char *name2,
749                 bool case_sensitive)
750 {
751         /* Normal filename handling */
752         if (case_sensitive) {
753                 return(strcmp(name1,name2) == 0);
754         }
755
756         return(strequal(name1,name2));
757 }
758
759 /****************************************************************************
760  Scan a directory to find a filename, matching without case sensitivity.
761  If the name looks like a mangled name then try via the mangling functions
762 ****************************************************************************/
763
764 static bool scan_directory(connection_struct *conn, const char *path,
765                            char *name, char **found_name)
766 {
767         struct smb_Dir *cur_dir;
768         const char *dname;
769         bool mangled;
770         char *unmangled_name = NULL;
771         long curpos;
772         TALLOC_CTX *ctx = talloc_tos();
773
774         mangled = mangle_is_mangled(name, conn->params);
775
776         /* handle null paths */
777         if ((path == NULL) || (*path == 0)) {
778                 path = ".";
779         }
780
781         /* If we have a case-sensitive filesystem, it doesn't do us any
782          * good to search for a name. If a case variation of the name was
783          * there, then the original stat(2) would have found it.
784          */
785         if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
786                 errno = ENOENT;
787                 return False;
788         }
789
790         /*
791          * The incoming name can be mangled, and if we de-mangle it
792          * here it will not compare correctly against the filename (name2)
793          * read from the directory and then mangled by the name_to_8_3()
794          * call. We need to mangle both names or neither.
795          * (JRA).
796          *
797          * Fix for bug found by Dina Fine. If in case sensitive mode then
798          * the mangle cache is no good (3 letter extension could be wrong
799          * case - so don't demangle in this case - leave as mangled and
800          * allow the mangling of the directory entry read (which is done
801          * case insensitively) to match instead. This will lead to more
802          * false positive matches but we fail completely without it. JRA.
803          */
804
805         if (mangled && !conn->case_sensitive) {
806                 mangled = !mangle_lookup_name_from_8_3(ctx,
807                                                 name,
808                                                 &unmangled_name,
809                                                 conn->params);
810                 if (!mangled) {
811                         /* Name is now unmangled. */
812                         name = unmangled_name;
813                 }
814         }
815
816         /* open the directory */
817         if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) {
818                 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
819                 TALLOC_FREE(unmangled_name);
820                 return(False);
821         }
822
823         /* now scan for matching names */
824         curpos = 0;
825         while ((dname = ReadDirName(cur_dir, &curpos))) {
826
827                 /* Is it dot or dot dot. */
828                 if (ISDOT(dname) || ISDOTDOT(dname)) {
829                         continue;
830                 }
831
832                 /*
833                  * At this point dname is the unmangled name.
834                  * name is either mangled or not, depending on the state
835                  * of the "mangled" variable. JRA.
836                  */
837
838                 /*
839                  * Check mangled name against mangled name, or unmangled name
840                  * against unmangled name.
841                  */
842
843                 if ((mangled && mangled_equal(name,dname,conn->params)) ||
844                         fname_equal(name, dname, conn->case_sensitive)) {
845                         /* we've found the file, change it's name and return */
846                         *found_name = talloc_strdup(ctx,dname);
847                         TALLOC_FREE(unmangled_name);
848                         TALLOC_FREE(cur_dir);
849                         if (!*found_name) {
850                                 errno = ENOMEM;
851                                 return False;
852                         }
853                         return(True);
854                 }
855         }
856
857         TALLOC_FREE(unmangled_name);
858         TALLOC_FREE(cur_dir);
859         errno = ENOENT;
860         return False;
861 }
862
863 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
864                                   connection_struct *conn,
865                                   const char *orig_path,
866                                   const char *basepath,
867                                   const char *streamname,
868                                   SMB_STRUCT_STAT *pst,
869                                   char **path)
870 {
871         SMB_STRUCT_STAT st;
872         char *result = NULL;
873         NTSTATUS status;
874         unsigned int i, num_streams;
875         struct stream_struct *streams = NULL;
876
877         result = talloc_asprintf(mem_ctx, "%s%s", basepath, streamname);
878         if (result == NULL) {
879                 return NT_STATUS_NO_MEMORY;
880         }
881
882         if (SMB_VFS_STAT(conn, result, &st) == 0) {
883                 *pst = st;
884                 *path = result;
885                 return NT_STATUS_OK;
886         }
887
888         if (errno != ENOENT) {
889                 status = map_nt_error_from_unix(errno);
890                 DEBUG(10, ("vfs_stat failed: %s\n", nt_errstr(status)));
891                 goto fail;
892         }
893
894         status = SMB_VFS_STREAMINFO(conn, NULL, basepath, mem_ctx,
895                                     &num_streams, &streams);
896
897         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
898                 SET_STAT_INVALID(*pst);
899                 *path = result;
900                 return NT_STATUS_OK;
901         }
902
903         if (!NT_STATUS_IS_OK(status)) {
904                 DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status)));
905                 goto fail;
906         }
907
908         for (i=0; i<num_streams; i++) {
909                 DEBUG(10, ("comparing [%s] and [%s]: ",
910                            streamname, streams[i].name));
911                 if (fname_equal(streamname, streams[i].name,
912                                 conn->case_sensitive)) {
913                         DEBUGADD(10, ("equal\n"));
914                         break;
915                 }
916                 DEBUGADD(10, ("not equal\n"));
917         }
918
919         if (i == num_streams) {
920                 SET_STAT_INVALID(*pst);
921                 *path = result;
922                 TALLOC_FREE(streams);
923                 return NT_STATUS_OK;
924         }
925
926         TALLOC_FREE(result);
927
928         result = talloc_asprintf(mem_ctx, "%s%s", basepath, streams[i].name);
929         if (result == NULL) {
930                 status = NT_STATUS_NO_MEMORY;
931                 goto fail;
932         }
933
934         SET_STAT_INVALID(*pst);
935
936         if (SMB_VFS_STAT(conn, result, pst) == 0) {
937                 stat_cache_add(orig_path, result, conn->case_sensitive);
938         }
939
940         *path = result;
941         TALLOC_FREE(streams);
942         return NT_STATUS_OK;
943
944  fail:
945         TALLOC_FREE(result);
946         TALLOC_FREE(streams);
947         return status;
948 }