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