7178f82fcef86e1b5e236fc9e4a76d7b44f29486
[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         if (!name_has_wildcard) {
280                 /*
281                  * stat the name - if it exists then we are all done!
282                  */
283
284                 if (posix_pathnames) {
285                         ret = SMB_VFS_LSTAT(conn,name,&st);
286                 } else {
287                         ret = SMB_VFS_STAT(conn,name,&st);
288                 }
289
290                 if (ret == 0) {
291                         /* Ensure we catch all names with in "/."
292                            this is disallowed under Windows. */
293                         const char *p = strstr(name, "/."); /* mb safe. */
294                         if (p) {
295                                 if (p[2] == '/') {
296                                         /* Error code within a pathname. */
297                                         result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
298                                         goto fail;
299                                 } else if (p[2] == '\0') {
300                                         /* Error code at the end of a pathname. */
301                                         result = NT_STATUS_OBJECT_NAME_INVALID;
302                                         goto fail;
303                                 }
304                         }
305                         stat_cache_add(orig_path, name, conn->case_sensitive);
306                         DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
307                         *pst = st;
308                         goto done;
309                 }
310         }
311
312         DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
313                                 name, dirpath, start));
314
315         /*
316          * A special case - if we don't have any mangling chars and are case
317          * sensitive or the underlying filesystem is case insentive then searching
318          * won't help.
319          */
320
321         if ((conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) &&
322                         !mangle_is_mangled(name, conn->params)) {
323                 goto done;
324         }
325
326         /*
327          * is_mangled() was changed to look at an entire pathname, not
328          * just a component. JRA.
329          */
330
331         if (mangle_is_mangled(start, conn->params)) {
332                 component_was_mangled = True;
333         }
334
335         /*
336          * Now we need to recursively match the name against the real
337          * directory structure.
338          */
339
340         /*
341          * Match each part of the path name separately, trying the names
342          * as is first, then trying to scan the directory for matching names.
343          */
344
345         for (; start ; start = (end?end+1:(char *)NULL)) {
346                 /*
347                  * Pinpoint the end of this section of the filename.
348                  */
349                 /* mb safe. '/' can't be in any encoded char. */
350                 end = strchr(start, '/');
351
352                 /*
353                  * Chop the name at this point.
354                  */
355                 if (end) {
356                         *end = 0;
357                 }
358
359                 if (pp_saved_last_component) {
360                         TALLOC_FREE(*pp_saved_last_component);
361                         *pp_saved_last_component = talloc_strdup(ctx,
362                                                         end ? end + 1 : start);
363                         if (!*pp_saved_last_component) {
364                                 DEBUG(0, ("talloc failed\n"));
365                                 return NT_STATUS_NO_MEMORY;
366                         }
367                 }
368
369                 /* The name cannot have a component of "." */
370
371                 if (ISDOT(start)) {
372                         if (!end)  {
373                                 /* Error code at the end of a pathname. */
374                                 result = NT_STATUS_OBJECT_NAME_INVALID;
375                         } else {
376                                 result = determine_path_error(end+1,
377                                                 allow_wcard_last_component);
378                         }
379                         goto fail;
380                 }
381
382                 /* The name cannot have a wildcard if it's not
383                    the last component. */
384
385                 name_has_wildcard = ms_has_wild(start);
386
387                 /* Wildcards never valid within a pathname. */
388                 if (name_has_wildcard && end) {
389                         result = NT_STATUS_OBJECT_NAME_INVALID;
390                         goto fail;
391                 }
392
393                 if (name_has_wildcard) {
394                         DEBUG(5,("Wildcard %s\n",start));
395                         goto done;
396                 }
397
398                 /*
399                  * Check if the name exists up to this point.
400                  */
401
402                 if (posix_pathnames) {
403                         ret = SMB_VFS_LSTAT(conn,name, &st);
404                 } else {
405                         ret = SMB_VFS_STAT(conn,name, &st);
406                 }
407
408                 if (ret == 0) {
409                         /*
410                          * It exists. it must either be a directory or this must
411                          * be the last part of the path for it to be OK.
412                          */
413                         if (end && !S_ISDIR(st.st_ex_mode)) {
414                                 /*
415                                  * An intermediate part of the name isn't
416                                  * a directory.
417                                  */
418                                 DEBUG(5,("Not a dir %s\n",start));
419                                 *end = '/';
420                                 /*
421                                  * We need to return the fact that the
422                                  * intermediate name resolution failed. This
423                                  * is used to return an error of ERRbadpath
424                                  * rather than ERRbadfile. Some Windows
425                                  * applications depend on the difference between
426                                  * these two errors.
427                                  */
428                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
429                                 goto fail;
430                         }
431
432                         if (!end) {
433                                 /*
434                                  * We just scanned for, and found the end of
435                                  * the path. We must return the valid stat
436                                  * struct. JRA.
437                                  */
438
439                                 *pst = st;
440                         }
441
442                 } else {
443                         char *found_name = NULL;
444
445                         /* Stat failed - ensure we don't use it. */
446                         SET_STAT_INVALID(st);
447
448                         /*
449                          * Reset errno so we can detect
450                          * directory open errors.
451                          */
452                         errno = 0;
453
454                         /*
455                          * Try to find this part of the path in the directory.
456                          */
457
458                         if (name_has_wildcard ||
459                             (get_real_filename(conn, dirpath, start,
460                                                talloc_tos(),
461                                                &found_name) == -1)) {
462                                 char *unmangled;
463
464                                 if (end) {
465                                         /*
466                                          * An intermediate part of the name
467                                          * can't be found.
468                                          */
469                                         DEBUG(5,("Intermediate not found %s\n",
470                                                         start));
471                                         *end = '/';
472
473                                         /*
474                                          * We need to return the fact that the
475                                          * intermediate name resolution failed.
476                                          * This is used to return an error of
477                                          * ERRbadpath rather than ERRbadfile.
478                                          * Some Windows applications depend on
479                                          * the difference between these two
480                                          * errors.
481                                          */
482
483                                         /*
484                                          * ENOENT, ENOTDIR and ELOOP all map
485                                          * to NT_STATUS_OBJECT_PATH_NOT_FOUND
486                                          * in the filename walk.
487                                          */
488
489                                         if (errno == ENOENT ||
490                                                         errno == ENOTDIR ||
491                                                         errno == ELOOP) {
492                                                 result =
493                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
494                                         }
495                                         else {
496                                                 result =
497                                                 map_nt_error_from_unix(errno);
498                                         }
499                                         goto fail;
500                                 }
501
502                                 /*
503                                  * ENOENT/EACCESS are the only valid errors
504                                  * here. EACCESS needs handling here for
505                                  * "dropboxes", i.e. directories where users
506                                  * can only put stuff with permission -wx.
507                                  */
508                                 if ((errno != 0) && (errno != ENOENT)
509                                     && (errno != EACCES)) {
510                                         /*
511                                          * ENOTDIR and ELOOP both map to
512                                          * NT_STATUS_OBJECT_PATH_NOT_FOUND
513                                          * in the filename walk.
514                                          */
515                                         if (errno == ENOTDIR ||
516                                                         errno == ELOOP) {
517                                                 result =
518                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
519                                         } else {
520                                                 result =
521                                                 map_nt_error_from_unix(errno);
522                                         }
523                                         goto fail;
524                                 }
525
526                                 /*
527                                  * Just the last part of the name doesn't exist.
528                                  * We need to strupper() or strlower() it as
529                                  * this conversion may be used for file creation
530                                  * purposes. Fix inspired by
531                                  * Thomas Neumann <t.neumann@iku-ag.de>.
532                                  */
533                                 if (!conn->case_preserve ||
534                                     (mangle_is_8_3(start, False,
535                                                    conn->params) &&
536                                                  !conn->short_case_preserve)) {
537                                         strnorm(start,
538                                                 lp_defaultcase(SNUM(conn)));
539                                 }
540
541                                 /*
542                                  * check on the mangled stack to see if we can
543                                  * recover the base of the filename.
544                                  */
545
546                                 if (mangle_is_mangled(start, conn->params)
547                                     && mangle_lookup_name_from_8_3(ctx,
548                                                         start,
549                                                         &unmangled,
550                                                         conn->params)) {
551                                         char *tmp;
552                                         size_t start_ofs = start - name;
553
554                                         if (*dirpath != '\0') {
555                                                 tmp = talloc_asprintf(ctx,
556                                                         "%s/%s", dirpath,
557                                                         unmangled);
558                                                 TALLOC_FREE(unmangled);
559                                         }
560                                         else {
561                                                 tmp = unmangled;
562                                         }
563                                         if (tmp == NULL) {
564                                                 DEBUG(0, ("talloc failed\n"));
565                                                 return NT_STATUS_NO_MEMORY;
566                                         }
567                                         TALLOC_FREE(name);
568                                         name = tmp;
569                                         start = name + start_ofs;
570                                         end = start + strlen(start);
571                                 }
572
573                                 DEBUG(5,("New file %s\n",start));
574                                 goto done;
575                         }
576
577
578                         /*
579                          * Restore the rest of the string. If the string was
580                          * mangled the size may have changed.
581                          */
582                         if (end) {
583                                 char *tmp;
584                                 size_t start_ofs = start - name;
585
586                                 if (*dirpath != '\0') {
587                                         tmp = talloc_asprintf(ctx,
588                                                 "%s/%s/%s", dirpath,
589                                                 found_name, end+1);
590                                 }
591                                 else {
592                                         tmp = talloc_asprintf(ctx,
593                                                 "%s/%s", found_name,
594                                                 end+1);
595                                 }
596                                 if (tmp == NULL) {
597                                         DEBUG(0, ("talloc_asprintf failed\n"));
598                                         return NT_STATUS_NO_MEMORY;
599                                 }
600                                 TALLOC_FREE(name);
601                                 name = tmp;
602                                 start = name + start_ofs;
603                                 end = start + strlen(found_name);
604                                 *end = '\0';
605                         } else {
606                                 char *tmp;
607                                 size_t start_ofs = start - name;
608
609                                 if (*dirpath != '\0') {
610                                         tmp = talloc_asprintf(ctx,
611                                                 "%s/%s", dirpath,
612                                                 found_name);
613                                 } else {
614                                         tmp = talloc_strdup(ctx,
615                                                 found_name);
616                                 }
617                                 if (tmp == NULL) {
618                                         DEBUG(0, ("talloc failed\n"));
619                                         return NT_STATUS_NO_MEMORY;
620                                 }
621                                 TALLOC_FREE(name);
622                                 name = tmp;
623                                 start = name + start_ofs;
624
625                                 /*
626                                  * We just scanned for, and found the end of
627                                  * the path. We must return a valid stat struct
628                                  * if it exists. JRA.
629                                  */
630
631                                 if (posix_pathnames) {
632                                         ret = SMB_VFS_LSTAT(conn,name, &st);
633                                 } else {
634                                         ret = SMB_VFS_STAT(conn,name, &st);
635                                 }
636
637                                 if (ret == 0) {
638                                         *pst = st;
639                                 } else {
640                                         SET_STAT_INVALID(st);
641                                 }
642                         }
643
644                         TALLOC_FREE(found_name);
645                 } /* end else */
646
647 #ifdef DEVELOPER
648                 /*
649                  * This sucks!
650                  * We should never provide different behaviors
651                  * depending on DEVELOPER!!!
652                  */
653                 if (VALID_STAT(st)) {
654                         bool delete_pending;
655                         get_file_infos(vfs_file_id_from_sbuf(conn, &st),
656                                        &delete_pending, NULL);
657                         if (delete_pending) {
658                                 result = NT_STATUS_DELETE_PENDING;
659                                 goto fail;
660                         }
661                 }
662 #endif
663
664                 /*
665                  * Add to the dirpath that we have resolved so far.
666                  */
667
668                 if (*dirpath != '\0') {
669                         char *tmp = talloc_asprintf(ctx,
670                                         "%s/%s", dirpath, start);
671                         if (!tmp) {
672                                 DEBUG(0, ("talloc_asprintf failed\n"));
673                                 return NT_STATUS_NO_MEMORY;
674                         }
675                         TALLOC_FREE(dirpath);
676                         dirpath = tmp;
677                 }
678                 else {
679                         TALLOC_FREE(dirpath);
680                         if (!(dirpath = talloc_strdup(ctx,start))) {
681                                 DEBUG(0, ("talloc_strdup failed\n"));
682                                 return NT_STATUS_NO_MEMORY;
683                         }
684                 }
685
686                 /*
687                  * Don't cache a name with mangled or wildcard components
688                  * as this can change the size.
689                  */
690
691                 if(!component_was_mangled && !name_has_wildcard) {
692                         stat_cache_add(orig_path, dirpath,
693                                         conn->case_sensitive);
694                 }
695
696                 /*
697                  * Restore the / that we wiped out earlier.
698                  */
699                 if (end) {
700                         *end = '/';
701                 }
702         }
703
704         /*
705          * Don't cache a name with mangled or wildcard components
706          * as this can change the size.
707          */
708
709         if(!component_was_mangled && !name_has_wildcard) {
710                 stat_cache_add(orig_path, name, conn->case_sensitive);
711         }
712
713         /*
714          * The name has been resolved.
715          */
716
717         DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
718
719  done:
720         if (stream != NULL) {
721                 char *tmp = NULL;
722
723                 result = build_stream_path(ctx, conn, orig_path, name, stream,
724                                            pst, &tmp);
725                 if (!NT_STATUS_IS_OK(result)) {
726                         goto fail;
727                 }
728
729                 DEBUG(10, ("build_stream_path returned %s\n", tmp));
730
731                 TALLOC_FREE(name);
732                 name = tmp;
733         }
734         *pp_conv_path = name;
735         TALLOC_FREE(dirpath);
736         return NT_STATUS_OK;
737  fail:
738         DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
739         if (*dirpath != '\0') {
740                 *pp_conv_path = talloc_asprintf(ctx,
741                                 "%s/%s", dirpath, start);
742         } else {
743                 *pp_conv_path = talloc_strdup(ctx, start);
744         }
745         if (!*pp_conv_path) {
746                 DEBUG(0, ("talloc_asprintf failed\n"));
747                 return NT_STATUS_NO_MEMORY;
748         }
749         TALLOC_FREE(name);
750         TALLOC_FREE(dirpath);
751         return result;
752 }
753
754 /****************************************************************************
755  Check a filename - possibly calling check_reduced_name.
756  This is called by every routine before it allows an operation on a filename.
757  It does any final confirmation necessary to ensure that the filename is
758  a valid one for the user to access.
759 ****************************************************************************/
760
761 NTSTATUS check_name(connection_struct *conn, const char *name)
762 {
763         if (IS_VETO_PATH(conn, name))  {
764                 /* Is it not dot or dot dot. */
765                 if (!((name[0] == '.') && (!name[1] ||
766                                         (name[1] == '.' && !name[2])))) {
767                         DEBUG(5,("check_name: file path name %s vetoed\n",
768                                                 name));
769                         return map_nt_error_from_unix(ENOENT);
770                 }
771         }
772
773         if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
774                 NTSTATUS status = check_reduced_name(conn,name);
775                 if (!NT_STATUS_IS_OK(status)) {
776                         DEBUG(5,("check_name: name %s failed with %s\n",name,
777                                                 nt_errstr(status)));
778                         return status;
779                 }
780         }
781
782         return NT_STATUS_OK;
783 }
784
785 /****************************************************************************
786  Check if two filenames are equal.
787  This needs to be careful about whether we are case sensitive.
788 ****************************************************************************/
789
790 static bool fname_equal(const char *name1, const char *name2,
791                 bool case_sensitive)
792 {
793         /* Normal filename handling */
794         if (case_sensitive) {
795                 return(strcmp(name1,name2) == 0);
796         }
797
798         return(strequal(name1,name2));
799 }
800
801 /****************************************************************************
802  Scan a directory to find a filename, matching without case sensitivity.
803  If the name looks like a mangled name then try via the mangling functions
804 ****************************************************************************/
805
806 static int get_real_filename_full_scan(connection_struct *conn,
807                                        const char *path, const char *name,
808                                        bool mangled,
809                                        TALLOC_CTX *mem_ctx, char **found_name)
810 {
811         struct smb_Dir *cur_dir;
812         const char *dname;
813         char *unmangled_name = NULL;
814         long curpos;
815
816         /* handle null paths */
817         if ((path == NULL) || (*path == 0)) {
818                 path = ".";
819         }
820
821         /* If we have a case-sensitive filesystem, it doesn't do us any
822          * good to search for a name. If a case variation of the name was
823          * there, then the original stat(2) would have found it.
824          */
825         if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
826                 errno = ENOENT;
827                 return -1;
828         }
829
830         /*
831          * The incoming name can be mangled, and if we de-mangle it
832          * here it will not compare correctly against the filename (name2)
833          * read from the directory and then mangled by the name_to_8_3()
834          * call. We need to mangle both names or neither.
835          * (JRA).
836          *
837          * Fix for bug found by Dina Fine. If in case sensitive mode then
838          * the mangle cache is no good (3 letter extension could be wrong
839          * case - so don't demangle in this case - leave as mangled and
840          * allow the mangling of the directory entry read (which is done
841          * case insensitively) to match instead. This will lead to more
842          * false positive matches but we fail completely without it. JRA.
843          */
844
845         if (mangled && !conn->case_sensitive) {
846                 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
847                                                        &unmangled_name,
848                                                        conn->params);
849                 if (!mangled) {
850                         /* Name is now unmangled. */
851                         name = unmangled_name;
852                 }
853         }
854
855         /* open the directory */
856         if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) {
857                 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
858                 TALLOC_FREE(unmangled_name);
859                 return -1;
860         }
861
862         /* now scan for matching names */
863         curpos = 0;
864         while ((dname = ReadDirName(cur_dir, &curpos, NULL))) {
865
866                 /* Is it dot or dot dot. */
867                 if (ISDOT(dname) || ISDOTDOT(dname)) {
868                         continue;
869                 }
870
871                 /*
872                  * At this point dname is the unmangled name.
873                  * name is either mangled or not, depending on the state
874                  * of the "mangled" variable. JRA.
875                  */
876
877                 /*
878                  * Check mangled name against mangled name, or unmangled name
879                  * against unmangled name.
880                  */
881
882                 if ((mangled && mangled_equal(name,dname,conn->params)) ||
883                         fname_equal(name, dname, conn->case_sensitive)) {
884                         /* we've found the file, change it's name and return */
885                         *found_name = talloc_strdup(mem_ctx, dname);
886                         TALLOC_FREE(unmangled_name);
887                         TALLOC_FREE(cur_dir);
888                         if (!*found_name) {
889                                 errno = ENOMEM;
890                                 return -1;
891                         }
892                         return 0;
893                 }
894         }
895
896         TALLOC_FREE(unmangled_name);
897         TALLOC_FREE(cur_dir);
898         errno = ENOENT;
899         return -1;
900 }
901
902 /****************************************************************************
903  Wrapper around the vfs get_real_filename and the full directory scan
904  fallback.
905 ****************************************************************************/
906
907 int get_real_filename(connection_struct *conn, const char *path,
908                       const char *name, TALLOC_CTX *mem_ctx,
909                       char **found_name)
910 {
911         int ret;
912         bool mangled;
913
914         mangled = mangle_is_mangled(name, conn->params);
915
916         if (mangled) {
917                 return get_real_filename_full_scan(conn, path, name, mangled,
918                                                    mem_ctx, found_name);
919         }
920
921         /* Try the vfs first to take advantage of case-insensitive stat. */
922         ret = SMB_VFS_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name);
923
924         /*
925          * If the case-insensitive stat was successful, or returned an error
926          * other than EOPNOTSUPP then there is no need to fall back on the
927          * full directory scan.
928          */
929         if (ret == 0 || (ret == -1 && errno != EOPNOTSUPP)) {
930                 return ret;
931         }
932
933         return get_real_filename_full_scan(conn, path, name, mangled, mem_ctx,
934                                            found_name);
935 }
936
937 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
938                                   connection_struct *conn,
939                                   const char *orig_path,
940                                   const char *basepath,
941                                   const char *streamname,
942                                   SMB_STRUCT_STAT *pst,
943                                   char **path)
944 {
945         SMB_STRUCT_STAT st;
946         char *result = NULL;
947         NTSTATUS status;
948         unsigned int i, num_streams;
949         struct stream_struct *streams = NULL;
950
951         result = talloc_asprintf(mem_ctx, "%s%s", basepath, streamname);
952         if (result == NULL) {
953                 return NT_STATUS_NO_MEMORY;
954         }
955
956         if (SMB_VFS_STAT(conn, result, &st) == 0) {
957                 *pst = st;
958                 *path = result;
959                 return NT_STATUS_OK;
960         }
961
962         if (errno != ENOENT) {
963                 status = map_nt_error_from_unix(errno);
964                 DEBUG(10, ("vfs_stat failed: %s\n", nt_errstr(status)));
965                 goto fail;
966         }
967
968         status = SMB_VFS_STREAMINFO(conn, NULL, basepath, mem_ctx,
969                                     &num_streams, &streams);
970
971         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
972                 SET_STAT_INVALID(*pst);
973                 *path = result;
974                 return NT_STATUS_OK;
975         }
976
977         if (!NT_STATUS_IS_OK(status)) {
978                 DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status)));
979                 goto fail;
980         }
981
982         for (i=0; i<num_streams; i++) {
983                 DEBUG(10, ("comparing [%s] and [%s]: ",
984                            streamname, streams[i].name));
985                 if (fname_equal(streamname, streams[i].name,
986                                 conn->case_sensitive)) {
987                         DEBUGADD(10, ("equal\n"));
988                         break;
989                 }
990                 DEBUGADD(10, ("not equal\n"));
991         }
992
993         if (i == num_streams) {
994                 SET_STAT_INVALID(*pst);
995                 *path = result;
996                 TALLOC_FREE(streams);
997                 return NT_STATUS_OK;
998         }
999
1000         TALLOC_FREE(result);
1001
1002         result = talloc_asprintf(mem_ctx, "%s%s", basepath, streams[i].name);
1003         if (result == NULL) {
1004                 status = NT_STATUS_NO_MEMORY;
1005                 goto fail;
1006         }
1007
1008         SET_STAT_INVALID(*pst);
1009
1010         if (SMB_VFS_STAT(conn, result, pst) == 0) {
1011                 stat_cache_add(orig_path, result, conn->case_sensitive);
1012         }
1013
1014         *path = result;
1015         TALLOC_FREE(streams);
1016         return NT_STATUS_OK;
1017
1018  fail:
1019         TALLOC_FREE(result);
1020         TALLOC_FREE(streams);
1021         return status;
1022 }