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