Rename "scan_directory" to "get_real_filename"
[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 bool get_real_filename(connection_struct *conn, const char *path,
30                               char *name, TALLOC_CTX *mem_ctx,
31                               char **found_name);
32 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
33                                   connection_struct *conn,
34                                   const char *orig_path,
35                                   const char *basepath,
36                                   const char *streamname,
37                                   SMB_STRUCT_STAT *pst,
38                                   char **path);
39
40 /****************************************************************************
41  Mangle the 2nd name and check if it is then equal to the first name.
42 ****************************************************************************/
43
44 static bool mangled_equal(const char *name1,
45                         const char *name2,
46                         const struct share_params *p)
47 {
48         char mname[13];
49
50         if (!name_to_8_3(name2, mname, False, p)) {
51                 return False;
52         }
53         return strequal(name1, mname);
54 }
55
56 /****************************************************************************
57  Cope with the differing wildcard and non-wildcard error cases.
58 ****************************************************************************/
59
60 static NTSTATUS determine_path_error(const char *name,
61                         bool allow_wcard_last_component)
62 {
63         const char *p;
64
65         if (!allow_wcard_last_component) {
66                 /* Error code within a pathname. */
67                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
68         }
69
70         /* We're terminating here so we
71          * can be a little slower and get
72          * the error code right. Windows
73          * treats the last part of the pathname
74          * separately I think, so if the last
75          * component is a wildcard then we treat
76          * this ./ as "end of component" */
77
78         p = strchr(name, '/');
79
80         if (!p && (ms_has_wild(name) || ISDOT(name))) {
81                 /* Error code at the end of a pathname. */
82                 return NT_STATUS_OBJECT_NAME_INVALID;
83         } else {
84                 /* Error code within a pathname. */
85                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
86         }
87 }
88
89 /****************************************************************************
90 This routine is called to convert names from the dos namespace to unix
91 namespace. It needs to handle any case conversions, mangling, format
92 changes etc.
93
94 We assume that we have already done a chdir() to the right "root" directory
95 for this service.
96
97 The function will return an NTSTATUS error if some part of the name except for
98 the last part cannot be resolved, else NT_STATUS_OK.
99
100 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't
101 get any fatal errors that should immediately terminate the calling
102 SMB processing whilst resolving.
103
104 If the saved_last_component != 0, then the unmodified last component
105 of the pathname is returned there. 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         if (!(name = talloc_strdup(ctx, orig_path))) {
199                 DEBUG(0, ("talloc_strdup failed\n"));
200                 return NT_STATUS_NO_MEMORY;
201         }
202
203         /*
204          * Large directory fix normalization. If we're case sensitive, and
205          * the case preserving parameters are set to "no", normalize the case of
206          * the incoming filename from the client WHETHER IT EXISTS OR NOT !
207          * This is in conflict with the current (3.0.20) man page, but is
208          * what people expect from the "large directory howto". I'll update
209          * the man page. Thanks to jht@samba.org for finding this. JRA.
210          */
211
212         if (conn->case_sensitive && !conn->case_preserve &&
213                         !conn->short_case_preserve) {
214                 strnorm(name, lp_defaultcase(SNUM(conn)));
215         }
216
217         /*
218          * Ensure saved_last_component is valid even if file exists.
219          */
220
221         if(pp_saved_last_component) {
222                 end = strrchr_m(name, '/');
223                 if (end) {
224                         *pp_saved_last_component = talloc_strdup(ctx, end + 1);
225                 } else {
226                         *pp_saved_last_component = talloc_strdup(ctx,
227                                                         name);
228                 }
229         }
230
231         if (!lp_posix_pathnames()) {
232                 stream = strchr_m(name, ':');
233
234                 if (stream != NULL) {
235                         char *tmp = talloc_strdup(ctx, stream);
236                         if (tmp == NULL) {
237                                 TALLOC_FREE(name);
238                                 return NT_STATUS_NO_MEMORY;
239                         }
240                         *stream = '\0';
241                         stream = tmp;
242                 }
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                             !get_real_filename(conn, dirpath, start,
438                                                talloc_tos(), &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 != 0) && (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                 /*
615                  * This sucks!
616                  * We should never provide different behaviors
617                  * depending on DEVELOPER!!!
618                  */
619                 if (VALID_STAT(st)) {
620                         bool delete_pending;
621                         get_file_infos(vfs_file_id_from_sbuf(conn, &st),
622                                        &delete_pending, NULL);
623                         if (delete_pending) {
624                                 result = NT_STATUS_DELETE_PENDING;
625                                 goto fail;
626                         }
627                 }
628 #endif
629
630                 /*
631                  * Add to the dirpath that we have resolved so far.
632                  */
633
634                 if (*dirpath != '\0') {
635                         char *tmp = talloc_asprintf(ctx,
636                                         "%s/%s", dirpath, start);
637                         if (!tmp) {
638                                 DEBUG(0, ("talloc_asprintf failed\n"));
639                                 return NT_STATUS_NO_MEMORY;
640                         }
641                         TALLOC_FREE(dirpath);
642                         dirpath = tmp;
643                 }
644                 else {
645                         TALLOC_FREE(dirpath);
646                         if (!(dirpath = talloc_strdup(ctx,start))) {
647                                 DEBUG(0, ("talloc_strdup failed\n"));
648                                 return NT_STATUS_NO_MEMORY;
649                         }
650                 }
651
652                 /*
653                  * Don't cache a name with mangled or wildcard components
654                  * as this can change the size.
655                  */
656
657                 if(!component_was_mangled && !name_has_wildcard) {
658                         stat_cache_add(orig_path, dirpath,
659                                         conn->case_sensitive);
660                 }
661
662                 /*
663                  * Restore the / that we wiped out earlier.
664                  */
665                 if (end) {
666                         *end = '/';
667                 }
668         }
669
670         /*
671          * Don't cache a name with mangled or wildcard components
672          * as this can change the size.
673          */
674
675         if(!component_was_mangled && !name_has_wildcard) {
676                 stat_cache_add(orig_path, name, conn->case_sensitive);
677         }
678
679         /*
680          * The name has been resolved.
681          */
682
683         DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
684
685  done:
686         if (stream != NULL) {
687                 char *tmp = NULL;
688
689                 result = build_stream_path(ctx, conn, orig_path, name, stream,
690                                            pst, &tmp);
691                 if (!NT_STATUS_IS_OK(result)) {
692                         goto fail;
693                 }
694
695                 DEBUG(10, ("build_stream_path returned %s\n", tmp));
696
697                 TALLOC_FREE(name);
698                 name = tmp;
699         }
700         *pp_conv_path = name;
701         TALLOC_FREE(dirpath);
702         return NT_STATUS_OK;
703  fail:
704         DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
705         if (*dirpath != '\0') {
706                 *pp_conv_path = talloc_asprintf(ctx,
707                                 "%s/%s", dirpath, start);
708         } else {
709                 *pp_conv_path = talloc_strdup(ctx, start);
710         }
711         if (!*pp_conv_path) {
712                 DEBUG(0, ("talloc_asprintf failed\n"));
713                 return NT_STATUS_NO_MEMORY;
714         }
715         TALLOC_FREE(name);
716         TALLOC_FREE(dirpath);
717         return result;
718 }
719
720 /****************************************************************************
721  Check a filename - possibly calling check_reduced_name.
722  This is called by every routine before it allows an operation on a filename.
723  It does any final confirmation necessary to ensure that the filename is
724  a valid one for the user to access.
725 ****************************************************************************/
726
727 NTSTATUS check_name(connection_struct *conn, const char *name)
728 {
729         if (IS_VETO_PATH(conn, name))  {
730                 /* Is it not dot or dot dot. */
731                 if (!((name[0] == '.') && (!name[1] ||
732                                         (name[1] == '.' && !name[2])))) {
733                         DEBUG(5,("check_name: file path name %s vetoed\n",
734                                                 name));
735                         return map_nt_error_from_unix(ENOENT);
736                 }
737         }
738
739         if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
740                 NTSTATUS status = check_reduced_name(conn,name);
741                 if (!NT_STATUS_IS_OK(status)) {
742                         DEBUG(5,("check_name: name %s failed with %s\n",name,
743                                                 nt_errstr(status)));
744                         return status;
745                 }
746         }
747
748         return NT_STATUS_OK;
749 }
750
751 /****************************************************************************
752  Check if two filenames are equal.
753  This needs to be careful about whether we are case sensitive.
754 ****************************************************************************/
755
756 static bool fname_equal(const char *name1, const char *name2,
757                 bool case_sensitive)
758 {
759         /* Normal filename handling */
760         if (case_sensitive) {
761                 return(strcmp(name1,name2) == 0);
762         }
763
764         return(strequal(name1,name2));
765 }
766
767 /****************************************************************************
768  Scan a directory to find a filename, matching without case sensitivity.
769  If the name looks like a mangled name then try via the mangling functions
770 ****************************************************************************/
771
772 static bool get_real_filename(connection_struct *conn, const char *path,
773                               char *name, TALLOC_CTX *mem_ctx,
774                               char **found_name)
775 {
776         struct smb_Dir *cur_dir;
777         const char *dname;
778         bool mangled;
779         char *unmangled_name = NULL;
780         long curpos;
781
782         mangled = mangle_is_mangled(name, conn->params);
783
784         /* handle null paths */
785         if ((path == NULL) || (*path == 0)) {
786                 path = ".";
787         }
788
789         /* If we have a case-sensitive filesystem, it doesn't do us any
790          * good to search for a name. If a case variation of the name was
791          * there, then the original stat(2) would have found it.
792          */
793         if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
794                 errno = ENOENT;
795                 return False;
796         }
797
798         /*
799          * The incoming name can be mangled, and if we de-mangle it
800          * here it will not compare correctly against the filename (name2)
801          * read from the directory and then mangled by the name_to_8_3()
802          * call. We need to mangle both names or neither.
803          * (JRA).
804          *
805          * Fix for bug found by Dina Fine. If in case sensitive mode then
806          * the mangle cache is no good (3 letter extension could be wrong
807          * case - so don't demangle in this case - leave as mangled and
808          * allow the mangling of the directory entry read (which is done
809          * case insensitively) to match instead. This will lead to more
810          * false positive matches but we fail completely without it. JRA.
811          */
812
813         if (mangled && !conn->case_sensitive) {
814                 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
815                                                        &unmangled_name,
816                                                        conn->params);
817                 if (!mangled) {
818                         /* Name is now unmangled. */
819                         name = unmangled_name;
820                 }
821         }
822
823         /* open the directory */
824         if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) {
825                 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
826                 TALLOC_FREE(unmangled_name);
827                 return(False);
828         }
829
830         /* now scan for matching names */
831         curpos = 0;
832         while ((dname = ReadDirName(cur_dir, &curpos))) {
833
834                 /* Is it dot or dot dot. */
835                 if (ISDOT(dname) || ISDOTDOT(dname)) {
836                         continue;
837                 }
838
839                 /*
840                  * At this point dname is the unmangled name.
841                  * name is either mangled or not, depending on the state
842                  * of the "mangled" variable. JRA.
843                  */
844
845                 /*
846                  * Check mangled name against mangled name, or unmangled name
847                  * against unmangled name.
848                  */
849
850                 if ((mangled && mangled_equal(name,dname,conn->params)) ||
851                         fname_equal(name, dname, conn->case_sensitive)) {
852                         /* we've found the file, change it's name and return */
853                         *found_name = talloc_strdup(mem_ctx, dname);
854                         TALLOC_FREE(unmangled_name);
855                         TALLOC_FREE(cur_dir);
856                         if (!*found_name) {
857                                 errno = ENOMEM;
858                                 return False;
859                         }
860                         return(True);
861                 }
862         }
863
864         TALLOC_FREE(unmangled_name);
865         TALLOC_FREE(cur_dir);
866         errno = ENOENT;
867         return False;
868 }
869
870 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
871                                   connection_struct *conn,
872                                   const char *orig_path,
873                                   const char *basepath,
874                                   const char *streamname,
875                                   SMB_STRUCT_STAT *pst,
876                                   char **path)
877 {
878         SMB_STRUCT_STAT st;
879         char *result = NULL;
880         NTSTATUS status;
881         unsigned int i, num_streams;
882         struct stream_struct *streams = NULL;
883
884         result = talloc_asprintf(mem_ctx, "%s%s", basepath, streamname);
885         if (result == NULL) {
886                 return NT_STATUS_NO_MEMORY;
887         }
888
889         if (SMB_VFS_STAT(conn, result, &st) == 0) {
890                 *pst = st;
891                 *path = result;
892                 return NT_STATUS_OK;
893         }
894
895         if (errno != ENOENT) {
896                 status = map_nt_error_from_unix(errno);
897                 DEBUG(10, ("vfs_stat failed: %s\n", nt_errstr(status)));
898                 goto fail;
899         }
900
901         status = SMB_VFS_STREAMINFO(conn, NULL, basepath, mem_ctx,
902                                     &num_streams, &streams);
903
904         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
905                 SET_STAT_INVALID(*pst);
906                 *path = result;
907                 return NT_STATUS_OK;
908         }
909
910         if (!NT_STATUS_IS_OK(status)) {
911                 DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status)));
912                 goto fail;
913         }
914
915         for (i=0; i<num_streams; i++) {
916                 DEBUG(10, ("comparing [%s] and [%s]: ",
917                            streamname, streams[i].name));
918                 if (fname_equal(streamname, streams[i].name,
919                                 conn->case_sensitive)) {
920                         DEBUGADD(10, ("equal\n"));
921                         break;
922                 }
923                 DEBUGADD(10, ("not equal\n"));
924         }
925
926         if (i == num_streams) {
927                 SET_STAT_INVALID(*pst);
928                 *path = result;
929                 TALLOC_FREE(streams);
930                 return NT_STATUS_OK;
931         }
932
933         TALLOC_FREE(result);
934
935         result = talloc_asprintf(mem_ctx, "%s%s", basepath, streams[i].name);
936         if (result == NULL) {
937                 status = NT_STATUS_NO_MEMORY;
938                 goto fail;
939         }
940
941         SET_STAT_INVALID(*pst);
942
943         if (SMB_VFS_STAT(conn, result, pst) == 0) {
944                 stat_cache_add(orig_path, result, conn->case_sensitive);
945         }
946
947         *path = result;
948         TALLOC_FREE(streams);
949         return NT_STATUS_OK;
950
951  fail:
952         TALLOC_FREE(result);
953         TALLOC_FREE(streams);
954         return status;
955 }