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