Deal with inheritance from parent directory when setting Windows
[jra/samba/.git] / source3 / smbd / filename.c
1 /*
2    Unix SMB/CIFS implementation.
3    filename handling routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 1999-2007
6    Copyright (C) Ying Chen 2000
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /*
24  * New hash table stat cache code added by Ying Chen.
25  */
26
27 #include "includes.h"
28
29 static bool scan_directory(connection_struct *conn, const char *path,
30                            char *name, char **found_name);
31 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
32                                   connection_struct *conn,
33                                   const char *orig_path,
34                                   const char *basepath,
35                                   const char *streamname,
36                                   SMB_STRUCT_STAT *pst,
37                                   char **path);
38
39 /****************************************************************************
40  Mangle the 2nd name and check if it is then equal to the first name.
41 ****************************************************************************/
42
43 static bool mangled_equal(const char *name1,
44                         const char *name2,
45                         const struct share_params *p)
46 {
47         char mname[13];
48
49         if (!name_to_8_3(name2, mname, False, p)) {
50                 return False;
51         }
52         return strequal(name1, mname);
53 }
54
55 /****************************************************************************
56  Cope with the differing wildcard and non-wildcard error cases.
57 ****************************************************************************/
58
59 static NTSTATUS determine_path_error(const char *name,
60                         bool allow_wcard_last_component)
61 {
62         const char *p;
63
64         if (!allow_wcard_last_component) {
65                 /* Error code within a pathname. */
66                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
67         }
68
69         /* We're terminating here so we
70          * can be a little slower and get
71          * the error code right. Windows
72          * treats the last part of the pathname
73          * separately I think, so if the last
74          * component is a wildcard then we treat
75          * this ./ as "end of component" */
76
77         p = strchr(name, '/');
78
79         if (!p && (ms_has_wild(name) || ISDOT(name))) {
80                 /* Error code at the end of a pathname. */
81                 return NT_STATUS_OBJECT_NAME_INVALID;
82         } else {
83                 /* Error code within a pathname. */
84                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
85         }
86 }
87
88 /****************************************************************************
89 This routine is called to convert names from the dos namespace to unix
90 namespace. It needs to handle any case conversions, mangling, format
91 changes etc.
92
93 We assume that we have already done a chdir() to the right "root" directory
94 for this service.
95
96 The function will return an NTSTATUS error if some part of the name except for
97 the last part cannot be resolved, else NT_STATUS_OK.
98
99 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't
100 get any fatal errors that should immediately terminate the calling
101 SMB processing whilst resolving.
102
103 If the saved_last_component != 0, then the unmodified last component
104 of the pathname is returned there. If saved_last_component == 0 then nothing
105 is returned there.
106
107 If last_component_wcard is true then a MS wildcard was detected and
108 should be allowed in the last component of the path only.
109
110 On exit from unix_convert, if *pst was not null, then the file stat
111 struct will be returned if the file exists and was found, if not this
112 stat struct will be filled with zeros (and this can be detected by checking
113 for nlinks = 0, which can never be true for any file).
114 ****************************************************************************/
115
116 NTSTATUS unix_convert(TALLOC_CTX *ctx,
117                         connection_struct *conn,
118                         const char *orig_path,
119                         bool allow_wcard_last_component,
120                         char **pp_conv_path,
121                         char **pp_saved_last_component,
122                         SMB_STRUCT_STAT *pst)
123 {
124         SMB_STRUCT_STAT st;
125         char *start, *end;
126         char *dirpath = NULL;
127         char *name = NULL;
128         char *stream = NULL;
129         bool component_was_mangled = False;
130         bool name_has_wildcard = False;
131         NTSTATUS result;
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         /*
198          * Ensure saved_last_component is valid even if file exists.
199          */
200
201         if(pp_saved_last_component) {
202                 end = strrchr_m(orig_path, '/');
203                 if (end) {
204                         *pp_saved_last_component = talloc_strdup(ctx, end + 1);
205                 } else {
206                         *pp_saved_last_component = talloc_strdup(ctx,
207                                                         orig_path);
208                 }
209         }
210
211         if (!(name = talloc_strdup(ctx, orig_path))) {
212                 DEBUG(0, ("talloc_strdup failed\n"));
213                 return NT_STATUS_NO_MEMORY;
214         }
215
216         if (!lp_posix_pathnames()) {
217                 stream = strchr_m(name, ':');
218
219                 if (stream != NULL) {
220                         char *tmp = talloc_strdup(ctx, stream);
221                         if (tmp == NULL) {
222                                 TALLOC_FREE(name);
223                                 return NT_STATUS_NO_MEMORY;
224                         }
225                         *stream = '\0';
226                         stream = tmp;
227                 }
228         }
229
230         /*
231          * Large directory fix normalization. If we're case sensitive, and
232          * the case preserving parameters are set to "no", normalize the case of
233          * the incoming filename from the client WHETHER IT EXISTS OR NOT !
234          * This is in conflict with the current (3.0.20) man page, but is
235          * what people expect from the "large directory howto". I'll update
236          * the man page. Thanks to jht@samba.org for finding this. JRA.
237          */
238
239         if (conn->case_sensitive && !conn->case_preserve &&
240                         !conn->short_case_preserve) {
241                 strnorm(name, lp_defaultcase(SNUM(conn)));
242         }
243
244         start = name;
245
246         /* If we're providing case insentive semantics or
247          * the underlying filesystem is case insensitive,
248          * then a case-normalized hit in the stat-cache is
249          * authoratitive. JRA.
250          */
251
252         if((!conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) &&
253                         stat_cache_lookup(conn, &name, &dirpath, &start, &st)) {
254                 *pst = st;
255                 goto done;
256         }
257
258         /*
259          * Make sure "dirpath" is an allocated string, we use this for
260          * building the directories with asprintf and free it.
261          */
262
263         if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) {
264                 DEBUG(0, ("talloc_strdup failed\n"));
265                 TALLOC_FREE(name);
266                 return NT_STATUS_NO_MEMORY;
267         }
268
269         /*
270          * stat the name - if it exists then we are all done!
271          */
272
273         if (SMB_VFS_STAT(conn,name,&st) == 0) {
274                 /* Ensure we catch all names with in "/."
275                    this is disallowed under Windows. */
276                 const char *p = strstr(name, "/."); /* mb safe. */
277                 if (p) {
278                         if (p[2] == '/') {
279                                 /* Error code within a pathname. */
280                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
281                                 goto fail;
282                         } else if (p[2] == '\0') {
283                                 /* Error code at the end of a pathname. */
284                                 result = NT_STATUS_OBJECT_NAME_INVALID;
285                                 goto fail;
286                         }
287                 }
288                 stat_cache_add(orig_path, name, conn->case_sensitive);
289                 DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
290                 *pst = st;
291                 goto done;
292         }
293
294         DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
295                                 name, dirpath, start));
296
297         /*
298          * A special case - if we don't have any mangling chars and are case
299          * sensitive or the underlying filesystem is case insentive then searching
300          * won't help.
301          */
302
303         if ((conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) &&
304                         !mangle_is_mangled(name, conn->params)) {
305                 goto done;
306         }
307
308         /*
309          * is_mangled() was changed to look at an entire pathname, not
310          * just a component. JRA.
311          */
312
313         if (mangle_is_mangled(start, conn->params)) {
314                 component_was_mangled = True;
315         }
316
317         /*
318          * Now we need to recursively match the name against the real
319          * directory structure.
320          */
321
322         /*
323          * Match each part of the path name separately, trying the names
324          * as is first, then trying to scan the directory for matching names.
325          */
326
327         for (; start ; start = (end?end+1:(char *)NULL)) {
328                 /*
329                  * Pinpoint the end of this section of the filename.
330                  */
331                 /* mb safe. '/' can't be in any encoded char. */
332                 end = strchr(start, '/');
333
334                 /*
335                  * Chop the name at this point.
336                  */
337                 if (end) {
338                         *end = 0;
339                 }
340
341                 if (pp_saved_last_component) {
342                         TALLOC_FREE(*pp_saved_last_component);
343                         *pp_saved_last_component = talloc_strdup(ctx,
344                                                         end ? end + 1 : start);
345                         if (!*pp_saved_last_component) {
346                                 DEBUG(0, ("talloc failed\n"));
347                                 return NT_STATUS_NO_MEMORY;
348                         }
349                 }
350
351                 /* The name cannot have a component of "." */
352
353                 if (ISDOT(start)) {
354                         if (!end)  {
355                                 /* Error code at the end of a pathname. */
356                                 result = NT_STATUS_OBJECT_NAME_INVALID;
357                         } else {
358                                 result = determine_path_error(end+1,
359                                                 allow_wcard_last_component);
360                         }
361                         goto fail;
362                 }
363
364                 /* The name cannot have a wildcard if it's not
365                    the last component. */
366
367                 name_has_wildcard = ms_has_wild(start);
368
369                 /* Wildcard not valid anywhere. */
370                 if (name_has_wildcard && !allow_wcard_last_component) {
371                         result = NT_STATUS_OBJECT_NAME_INVALID;
372                         goto fail;
373                 }
374
375                 /* Wildcards never valid within a pathname. */
376                 if (name_has_wildcard && end) {
377                         result = NT_STATUS_OBJECT_NAME_INVALID;
378                         goto fail;
379                 }
380
381                 /*
382                  * Check if the name exists up to this point.
383                  */
384
385                 if (SMB_VFS_STAT(conn,name, &st) == 0) {
386                         /*
387                          * It exists. it must either be a directory or this must
388                          * be the last part of the path for it to be OK.
389                          */
390                         if (end && !(st.st_mode & S_IFDIR)) {
391                                 /*
392                                  * An intermediate part of the name isn't
393                                  * a directory.
394                                  */
395                                 DEBUG(5,("Not a dir %s\n",start));
396                                 *end = '/';
397                                 /*
398                                  * We need to return the fact that the
399                                  * intermediate name resolution failed. This
400                                  * is used to return an error of ERRbadpath
401                                  * rather than ERRbadfile. Some Windows
402                                  * applications depend on the difference between
403                                  * these two errors.
404                                  */
405                                 result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
406                                 goto fail;
407                         }
408
409                         if (!end) {
410                                 /*
411                                  * We just scanned for, and found the end of
412                                  * the path. We must return the valid stat
413                                  * struct. JRA.
414                                  */
415
416                                 *pst = st;
417                         }
418
419                 } else {
420                         char *found_name = NULL;
421
422                         /* Stat failed - ensure we don't use it. */
423                         SET_STAT_INVALID(st);
424
425                         /*
426                          * Reset errno so we can detect
427                          * directory open errors.
428                          */
429                         errno = 0;
430
431                         /*
432                          * Try to find this part of the path in the directory.
433                          */
434
435                         if (name_has_wildcard ||
436                             !scan_directory(conn, dirpath,
437                                     start, &found_name)) {
438                                 char *unmangled;
439
440                                 if (end) {
441                                         /*
442                                          * An intermediate part of the name
443                                          * can't be found.
444                                          */
445                                         DEBUG(5,("Intermediate not found %s\n",
446                                                         start));
447                                         *end = '/';
448
449                                         /*
450                                          * We need to return the fact that the
451                                          * intermediate name resolution failed.
452                                          * This is used to return an error of
453                                          * ERRbadpath rather than ERRbadfile.
454                                          * Some Windows applications depend on
455                                          * the difference between these two
456                                          * errors.
457                                          */
458
459                                         /*
460                                          * ENOENT, ENOTDIR and ELOOP all map
461                                          * to NT_STATUS_OBJECT_PATH_NOT_FOUND
462                                          * in the filename walk.
463                                          */
464
465                                         if (errno == ENOENT ||
466                                                         errno == ENOTDIR ||
467                                                         errno == ELOOP) {
468                                                 result =
469                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
470                                         }
471                                         else {
472                                                 result =
473                                                 map_nt_error_from_unix(errno);
474                                         }
475                                         goto fail;
476                                 }
477
478                                 /* ENOENT is the only valid error here. */
479                                 if ((errno != 0) && (errno != ENOENT)) {
480                                         /*
481                                          * ENOTDIR and ELOOP both map to
482                                          * NT_STATUS_OBJECT_PATH_NOT_FOUND
483                                          * in the filename walk.
484                                          */
485                                         if (errno == ENOTDIR ||
486                                                         errno == ELOOP) {
487                                                 result =
488                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
489                                         }
490                                         else {
491                                                 result =
492                                                 map_nt_error_from_unix(errno);
493                                         }
494                                         goto fail;
495                                 }
496
497                                 /*
498                                  * Just the last part of the name doesn't exist.
499                                  * We need to strupper() or strlower() it as
500                                  * this conversion may be used for file creation
501                                  * purposes. Fix inspired by
502                                  * Thomas Neumann <t.neumann@iku-ag.de>.
503                                  */
504                                 if (!conn->case_preserve ||
505                                     (mangle_is_8_3(start, False,
506                                                    conn->params) &&
507                                                  !conn->short_case_preserve)) {
508                                         strnorm(start,
509                                                 lp_defaultcase(SNUM(conn)));
510                                 }
511
512                                 /*
513                                  * check on the mangled stack to see if we can
514                                  * recover the base of the filename.
515                                  */
516
517                                 if (mangle_is_mangled(start, conn->params)
518                                     && mangle_lookup_name_from_8_3(ctx,
519                                                         start,
520                                                         &unmangled,
521                                                         conn->params)) {
522                                         char *tmp;
523                                         size_t start_ofs = start - name;
524
525                                         if (*dirpath != '\0') {
526                                                 tmp = talloc_asprintf(ctx,
527                                                         "%s/%s", dirpath,
528                                                         unmangled);
529                                                 TALLOC_FREE(unmangled);
530                                         }
531                                         else {
532                                                 tmp = unmangled;
533                                         }
534                                         if (tmp == NULL) {
535                                                 DEBUG(0, ("talloc failed\n"));
536                                                 return NT_STATUS_NO_MEMORY;
537                                         }
538                                         TALLOC_FREE(name);
539                                         name = tmp;
540                                         start = name + start_ofs;
541                                         end = start + strlen(start);
542                                 }
543
544                                 DEBUG(5,("New file %s\n",start));
545                                 goto done;
546                         }
547
548
549                         /*
550                          * Restore the rest of the string. If the string was
551                          * mangled the size may have changed.
552                          */
553                         if (end) {
554                                 char *tmp;
555                                 size_t start_ofs = start - name;
556
557                                 if (*dirpath != '\0') {
558                                         tmp = talloc_asprintf(ctx,
559                                                 "%s/%s/%s", dirpath,
560                                                 found_name, end+1);
561                                 }
562                                 else {
563                                         tmp = talloc_asprintf(ctx,
564                                                 "%s/%s", found_name,
565                                                 end+1);
566                                 }
567                                 if (tmp == NULL) {
568                                         DEBUG(0, ("talloc_asprintf failed\n"));
569                                         return NT_STATUS_NO_MEMORY;
570                                 }
571                                 TALLOC_FREE(name);
572                                 name = tmp;
573                                 start = name + start_ofs;
574                                 end = start + strlen(found_name);
575                                 *end = '\0';
576                         } else {
577                                 char *tmp;
578                                 size_t start_ofs = start - name;
579
580                                 if (*dirpath != '\0') {
581                                         tmp = talloc_asprintf(ctx,
582                                                 "%s/%s", dirpath,
583                                                 found_name);
584                                 } else {
585                                         tmp = talloc_strdup(ctx,
586                                                 found_name);
587                                 }
588                                 if (tmp == NULL) {
589                                         DEBUG(0, ("talloc failed\n"));
590                                         return NT_STATUS_NO_MEMORY;
591                                 }
592                                 TALLOC_FREE(name);
593                                 name = tmp;
594                                 start = name + start_ofs;
595
596                                 /*
597                                  * We just scanned for, and found the end of
598                                  * the path. We must return a valid stat struct
599                                  * if it exists. JRA.
600                                  */
601
602                                 if (SMB_VFS_STAT(conn,name, &st) == 0) {
603                                         *pst = st;
604                                 } else {
605                                         SET_STAT_INVALID(st);
606                                 }
607                         }
608
609                         TALLOC_FREE(found_name);
610                 } /* end else */
611
612 #ifdef DEVELOPER
613                 /*
614                  * This sucks!
615                  * We should never provide different behaviors
616                  * depending on DEVELOPER!!!
617                  */
618                 if (VALID_STAT(st)) {
619                         bool delete_pending;
620                         get_file_infos(vfs_file_id_from_sbuf(conn, &st),
621                                        &delete_pending, NULL);
622                         if (delete_pending) {
623                                 result = NT_STATUS_DELETE_PENDING;
624                                 goto fail;
625                         }
626                 }
627 #endif
628
629                 /*
630                  * Add to the dirpath that we have resolved so far.
631                  */
632
633                 if (*dirpath != '\0') {
634                         char *tmp = talloc_asprintf(ctx,
635                                         "%s/%s", dirpath, start);
636                         if (!tmp) {
637                                 DEBUG(0, ("talloc_asprintf failed\n"));
638                                 return NT_STATUS_NO_MEMORY;
639                         }
640                         TALLOC_FREE(dirpath);
641                         dirpath = tmp;
642                 }
643                 else {
644                         TALLOC_FREE(dirpath);
645                         if (!(dirpath = talloc_strdup(ctx,start))) {
646                                 DEBUG(0, ("talloc_strdup failed\n"));
647                                 return NT_STATUS_NO_MEMORY;
648                         }
649                 }
650
651                 /*
652                  * Don't cache a name with mangled or wildcard components
653                  * as this can change the size.
654                  */
655
656                 if(!component_was_mangled && !name_has_wildcard) {
657                         stat_cache_add(orig_path, dirpath,
658                                         conn->case_sensitive);
659                 }
660
661                 /*
662                  * Restore the / that we wiped out earlier.
663                  */
664                 if (end) {
665                         *end = '/';
666                 }
667         }
668
669         /*
670          * Don't cache a name with mangled or wildcard components
671          * as this can change the size.
672          */
673
674         if(!component_was_mangled && !name_has_wildcard) {
675                 stat_cache_add(orig_path, name, conn->case_sensitive);
676         }
677
678         /*
679          * The name has been resolved.
680          */
681
682         DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
683
684  done:
685         if (stream != NULL) {
686                 char *tmp = NULL;
687
688                 result = build_stream_path(ctx, conn, orig_path, name, stream,
689                                            pst, &tmp);
690                 if (!NT_STATUS_IS_OK(result)) {
691                         goto fail;
692                 }
693
694                 DEBUG(10, ("build_stream_path returned %s\n", tmp));
695
696                 TALLOC_FREE(name);
697                 name = tmp;
698         }
699         *pp_conv_path = name;
700         TALLOC_FREE(dirpath);
701         return NT_STATUS_OK;
702  fail:
703         DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
704         if (*dirpath != '\0') {
705                 *pp_conv_path = talloc_asprintf(ctx,
706                                 "%s/%s", dirpath, start);
707         } else {
708                 *pp_conv_path = talloc_strdup(ctx, start);
709         }
710         if (!*pp_conv_path) {
711                 DEBUG(0, ("talloc_asprintf failed\n"));
712                 return NT_STATUS_NO_MEMORY;
713         }
714         TALLOC_FREE(name);
715         TALLOC_FREE(dirpath);
716         return result;
717 }
718
719 /****************************************************************************
720  Check a filename - possibly calling check_reduced_name.
721  This is called by every routine before it allows an operation on a filename.
722  It does any final confirmation necessary to ensure that the filename is
723  a valid one for the user to access.
724 ****************************************************************************/
725
726 NTSTATUS check_name(connection_struct *conn, const char *name)
727 {
728         if (IS_VETO_PATH(conn, name))  {
729                 /* Is it not dot or dot dot. */
730                 if (!((name[0] == '.') && (!name[1] ||
731                                         (name[1] == '.' && !name[2])))) {
732                         DEBUG(5,("check_name: file path name %s vetoed\n",
733                                                 name));
734                         return map_nt_error_from_unix(ENOENT);
735                 }
736         }
737
738         if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
739                 NTSTATUS status = check_reduced_name(conn,name);
740                 if (!NT_STATUS_IS_OK(status)) {
741                         DEBUG(5,("check_name: name %s failed with %s\n",name,
742                                                 nt_errstr(status)));
743                         return status;
744                 }
745         }
746
747         return NT_STATUS_OK;
748 }
749
750 /****************************************************************************
751  Check if two filenames are equal.
752  This needs to be careful about whether we are case sensitive.
753 ****************************************************************************/
754
755 static bool fname_equal(const char *name1, const char *name2,
756                 bool case_sensitive)
757 {
758         /* Normal filename handling */
759         if (case_sensitive) {
760                 return(strcmp(name1,name2) == 0);
761         }
762
763         return(strequal(name1,name2));
764 }
765
766 /****************************************************************************
767  Scan a directory to find a filename, matching without case sensitivity.
768  If the name looks like a mangled name then try via the mangling functions
769 ****************************************************************************/
770
771 static bool scan_directory(connection_struct *conn, const char *path,
772                            char *name, char **found_name)
773 {
774         struct smb_Dir *cur_dir;
775         const char *dname;
776         bool mangled;
777         char *unmangled_name = NULL;
778         long curpos;
779         TALLOC_CTX *ctx = talloc_tos();
780
781         mangled = mangle_is_mangled(name, conn->params);
782
783         /* handle null paths */
784         if ((path == NULL) || (*path == 0)) {
785                 path = ".";
786         }
787
788         /* If we have a case-sensitive filesystem, it doesn't do us any
789          * good to search for a name. If a case variation of the name was
790          * there, then the original stat(2) would have found it.
791          */
792         if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
793                 errno = ENOENT;
794                 return False;
795         }
796
797         /*
798          * The incoming name can be mangled, and if we de-mangle it
799          * here it will not compare correctly against the filename (name2)
800          * read from the directory and then mangled by the name_to_8_3()
801          * call. We need to mangle both names or neither.
802          * (JRA).
803          *
804          * Fix for bug found by Dina Fine. If in case sensitive mode then
805          * the mangle cache is no good (3 letter extension could be wrong
806          * case - so don't demangle in this case - leave as mangled and
807          * allow the mangling of the directory entry read (which is done
808          * case insensitively) to match instead. This will lead to more
809          * false positive matches but we fail completely without it. JRA.
810          */
811
812         if (mangled && !conn->case_sensitive) {
813                 mangled = !mangle_lookup_name_from_8_3(ctx,
814                                                 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(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 }