s3-build: only include "fake_file.h" where needed.
[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 #include "fake_file.h"
29
30 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
31                                   connection_struct *conn,
32                                   const char *orig_path,
33                                   struct smb_filename *smb_fname);
34
35 /****************************************************************************
36  Mangle the 2nd name and check if it is then equal to the first name.
37 ****************************************************************************/
38
39 static bool mangled_equal(const char *name1,
40                         const char *name2,
41                         const struct share_params *p)
42 {
43         char mname[13];
44
45         if (!name_to_8_3(name2, mname, False, p)) {
46                 return False;
47         }
48         return strequal(name1, mname);
49 }
50
51 /****************************************************************************
52  Cope with the differing wildcard and non-wildcard error cases.
53 ****************************************************************************/
54
55 static NTSTATUS determine_path_error(const char *name,
56                         bool allow_wcard_last_component)
57 {
58         const char *p;
59
60         if (!allow_wcard_last_component) {
61                 /* Error code within a pathname. */
62                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
63         }
64
65         /* We're terminating here so we
66          * can be a little slower and get
67          * the error code right. Windows
68          * treats the last part of the pathname
69          * separately I think, so if the last
70          * component is a wildcard then we treat
71          * this ./ as "end of component" */
72
73         p = strchr(name, '/');
74
75         if (!p && (ms_has_wild(name) || ISDOT(name))) {
76                 /* Error code at the end of a pathname. */
77                 return NT_STATUS_OBJECT_NAME_INVALID;
78         } else {
79                 /* Error code within a pathname. */
80                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
81         }
82 }
83
84 static NTSTATUS check_for_dot_component(const struct smb_filename *smb_fname)
85 {
86         /* Ensure we catch all names with in "/."
87            this is disallowed under Windows and
88            in POSIX they've already been removed. */
89         const char *p = strstr(smb_fname->base_name, "/."); /*mb safe*/
90         if (p) {
91                 if (p[2] == '/') {
92                         /* Error code within a pathname. */
93                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
94                 } else if (p[2] == '\0') {
95                         /* Error code at the end of a pathname. */
96                         return NT_STATUS_OBJECT_NAME_INVALID;
97                 }
98         }
99         return NT_STATUS_OK;
100 }
101
102 /****************************************************************************
103 This routine is called to convert names from the dos namespace to unix
104 namespace. It needs to handle any case conversions, mangling, format changes,
105 streams etc.
106
107 We assume that we have already done a chdir() to the right "root" directory
108 for this service.
109
110 The function will return an NTSTATUS error if some part of the name except for
111 the last part cannot be resolved, else NT_STATUS_OK.
112
113 Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we
114 didn't get any fatal errors that should immediately terminate the calling SMB
115 processing whilst resolving.
116
117 If the UCF_SAVE_LCOMP flag is passed in, then the unmodified last component
118 of the pathname is set in smb_filename->original_lcomp.
119
120 If UCF_ALWAYS_ALLOW_WCARD_LCOMP is passed in, then a MS wildcard was detected
121 and should be allowed in the last component of the path only.
122
123 If the orig_path was a stream, smb_filename->base_name will point to the base
124 filename, and smb_filename->stream_name will point to the stream name.  If
125 orig_path was not a stream, then smb_filename->stream_name will be NULL.
126
127 On exit from unix_convert, the smb_filename->st stat struct will be populated
128 if the file exists and was found, if not this stat struct will be filled with
129 zeros (and this can be detected by checking for nlinks = 0, which can never be
130 true for any file).
131 ****************************************************************************/
132
133 NTSTATUS unix_convert(TALLOC_CTX *ctx,
134                       connection_struct *conn,
135                       const char *orig_path,
136                       struct smb_filename **smb_fname_out,
137                       uint32_t ucf_flags)
138 {
139         struct smb_filename *smb_fname = NULL;
140         char *start, *end;
141         char *dirpath = NULL;
142         char *stream = NULL;
143         bool component_was_mangled = False;
144         bool name_has_wildcard = False;
145         bool posix_pathnames = false;
146         bool allow_wcard_last_component =
147             (ucf_flags & UCF_ALWAYS_ALLOW_WCARD_LCOMP);
148         bool save_last_component = ucf_flags & UCF_SAVE_LCOMP;
149         NTSTATUS status;
150         int ret = -1;
151
152         *smb_fname_out = NULL;
153
154         smb_fname = talloc_zero(ctx, struct smb_filename);
155         if (smb_fname == NULL) {
156                 return NT_STATUS_NO_MEMORY;
157         }
158
159         if (conn->printer) {
160                 /* we don't ever use the filenames on a printer share as a
161                         filename - so don't convert them */
162                 if (!(smb_fname->base_name = talloc_strdup(smb_fname,
163                                                            orig_path))) {
164                         status = NT_STATUS_NO_MEMORY;
165                         goto err;
166                 }
167                 goto done;
168         }
169
170         DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path));
171
172         /*
173          * Conversion to basic unix format is already done in
174          * check_path_syntax().
175          */
176
177         /*
178          * Names must be relative to the root of the service - any leading /.
179          * and trailing /'s should have been trimmed by check_path_syntax().
180          */
181
182 #ifdef DEVELOPER
183         SMB_ASSERT(*orig_path != '/');
184 #endif
185
186         /*
187          * If we trimmed down to a single '\0' character
188          * then we should use the "." directory to avoid
189          * searching the cache, but not if we are in a
190          * printing share.
191          * As we know this is valid we can return true here.
192          */
193
194         if (!*orig_path) {
195                 if (!(smb_fname->base_name = talloc_strdup(smb_fname, "."))) {
196                         status = NT_STATUS_NO_MEMORY;
197                         goto err;
198                 }
199                 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
200                         status = map_nt_error_from_unix(errno);
201                         goto err;
202                 }
203                 DEBUG(5, ("conversion finished \"\" -> %s\n",
204                           smb_fname->base_name));
205                 goto done;
206         }
207
208         if (orig_path[0] == '.' && (orig_path[1] == '/' ||
209                                 orig_path[1] == '\0')) {
210                 /* Start of pathname can't be "." only. */
211                 if (orig_path[1] == '\0' || orig_path[2] == '\0') {
212                         status = NT_STATUS_OBJECT_NAME_INVALID;
213                 } else {
214                         status =determine_path_error(&orig_path[2],
215                             allow_wcard_last_component);
216                 }
217                 goto err;
218         }
219
220         /* Start with the full orig_path as given by the caller. */
221         if (!(smb_fname->base_name = talloc_strdup(smb_fname, orig_path))) {
222                 DEBUG(0, ("talloc_strdup failed\n"));
223                 status = NT_STATUS_NO_MEMORY;
224                 goto err;
225         }
226
227         /*
228          * Large directory fix normalization. If we're case sensitive, and
229          * the case preserving parameters are set to "no", normalize the case of
230          * the incoming filename from the client WHETHER IT EXISTS OR NOT !
231          * This is in conflict with the current (3.0.20) man page, but is
232          * what people expect from the "large directory howto". I'll update
233          * the man page. Thanks to jht@samba.org for finding this. JRA.
234          */
235
236         if (conn->case_sensitive && !conn->case_preserve &&
237                         !conn->short_case_preserve) {
238                 strnorm(smb_fname->base_name, lp_defaultcase(SNUM(conn)));
239         }
240
241         /*
242          * Ensure saved_last_component is valid even if file exists.
243          */
244
245         if(save_last_component) {
246                 end = strrchr_m(smb_fname->base_name, '/');
247                 if (end) {
248                         smb_fname->original_lcomp = talloc_strdup(smb_fname,
249                                                                   end + 1);
250                 } else {
251                         smb_fname->original_lcomp =
252                             talloc_strdup(smb_fname, smb_fname->base_name);
253                 }
254                 if (smb_fname->original_lcomp == NULL) {
255                         status = NT_STATUS_NO_MEMORY;
256                         goto err;
257                 }
258         }
259
260         posix_pathnames = (lp_posix_pathnames() ||
261                                 (ucf_flags & UCF_POSIX_PATHNAMES));
262
263         /*
264          * Strip off the stream, and add it back when we're done with the
265          * base_name.
266          */
267         if (!posix_pathnames) {
268                 stream = strchr_m(smb_fname->base_name, ':');
269
270                 if (stream != NULL) {
271                         char *tmp = talloc_strdup(smb_fname, stream);
272                         if (tmp == NULL) {
273                                 status = NT_STATUS_NO_MEMORY;
274                                 goto err;
275                         }
276                         /*
277                          * Since this is actually pointing into
278                          * smb_fname->base_name this truncates base_name.
279                          */
280                         *stream = '\0';
281                         stream = tmp;
282                 }
283         }
284
285         start = smb_fname->base_name;
286
287         /*
288          * If we're providing case insentive semantics or
289          * the underlying filesystem is case insensitive,
290          * then a case-normalized hit in the stat-cache is
291          * authoratitive. JRA.
292          *
293          * Note: We're only checking base_name.  The stream_name will be
294          * added and verified in build_stream_path().
295          */
296
297         if((!conn->case_sensitive || !(conn->fs_capabilities &
298                                        FILE_CASE_SENSITIVE_SEARCH)) &&
299             stat_cache_lookup(conn, &smb_fname->base_name, &dirpath, &start,
300                               &smb_fname->st)) {
301                 goto done;
302         }
303
304         /*
305          * Make sure "dirpath" is an allocated string, we use this for
306          * building the directories with asprintf and free it.
307          */
308
309         if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) {
310                 DEBUG(0, ("talloc_strdup failed\n"));
311                 status = NT_STATUS_NO_MEMORY;
312                 goto err;
313         }
314
315         /*
316          * If we have a wildcard we must walk the path to
317          * find where the error is, even if case sensitive
318          * is true.
319          */
320
321         name_has_wildcard = ms_has_wild(smb_fname->base_name);
322         if (name_has_wildcard && !allow_wcard_last_component) {
323                 /* Wildcard not valid anywhere. */
324                 status = NT_STATUS_OBJECT_NAME_INVALID;
325                 goto fail;
326         }
327
328         DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
329                  smb_fname->base_name, dirpath, start));
330
331         if (!name_has_wildcard) {
332                 /*
333                  * stat the name - if it exists then we can add the stream back (if
334                  * there was one) and be done!
335                  */
336
337                 if (posix_pathnames) {
338                         ret = SMB_VFS_LSTAT(conn, smb_fname);
339                 } else {
340                         ret = SMB_VFS_STAT(conn, smb_fname);
341                 }
342
343                 if (ret == 0) {
344                         status = check_for_dot_component(smb_fname);
345                         if (!NT_STATUS_IS_OK(status)) {
346                                 goto fail;
347                         }
348                         /* Add the path (not including the stream) to the cache. */
349                         stat_cache_add(orig_path, smb_fname->base_name,
350                                        conn->case_sensitive);
351                         DEBUG(5,("conversion of base_name finished %s -> %s\n",
352                                  orig_path, smb_fname->base_name));
353                         goto done;
354                 }
355
356                 /*
357                  * A special case - if we don't have any wildcards or mangling chars and are case
358                  * sensitive or the underlying filesystem is case insentive then searching
359                  * won't help.
360                  */
361
362                 if ((conn->case_sensitive || !(conn->fs_capabilities &
363                                         FILE_CASE_SENSITIVE_SEARCH)) &&
364                                 !mangle_is_mangled(smb_fname->base_name, conn->params)) {
365
366                         status = check_for_dot_component(smb_fname);
367                         if (!NT_STATUS_IS_OK(status)) {
368                                 goto fail;
369                         }
370
371                         /*
372                          * The stat failed. Could be ok as it could be
373                          * a new file.
374                          */
375
376                         if (errno == ENOTDIR || errno == ELOOP) {
377                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
378                                 goto fail;
379                         } else if (errno == ENOENT) {
380                                 /*
381                                  * Was it a missing last component ?
382                                  * or a missing intermediate component ?
383                                  */
384                                 struct smb_filename parent_fname;
385                                 ZERO_STRUCT(parent_fname);
386                                 if (!parent_dirname(ctx, smb_fname->base_name,
387                                                         &parent_fname.base_name,
388                                                         NULL)) {
389                                         status = NT_STATUS_NO_MEMORY;
390                                         goto fail;
391                                 }
392                                 if (posix_pathnames) {
393                                         ret = SMB_VFS_LSTAT(conn, &parent_fname);
394                                 } else {
395                                         ret = SMB_VFS_STAT(conn, &parent_fname);
396                                 }
397                                 if (ret == -1) {
398                                         if (errno == ENOTDIR ||
399                                                         errno == ENOENT ||
400                                                         errno == ELOOP) {
401                                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
402                                                 goto fail;
403                                         }
404                                 }
405                                 /*
406                                  * Missing last component is ok - new file.
407                                  * Also deal with permission denied elsewhere.
408                                  * Just drop out to done.
409                                  */
410                                 goto done;
411                         }
412                 }
413         }
414
415         /*
416          * is_mangled() was changed to look at an entire pathname, not
417          * just a component. JRA.
418          */
419
420         if (mangle_is_mangled(start, conn->params)) {
421                 component_was_mangled = True;
422         }
423
424         /*
425          * Now we need to recursively match the name against the real
426          * directory structure.
427          */
428
429         /*
430          * Match each part of the path name separately, trying the names
431          * as is first, then trying to scan the directory for matching names.
432          */
433
434         for (; start ; start = (end?end+1:(char *)NULL)) {
435                 /*
436                  * Pinpoint the end of this section of the filename.
437                  */
438                 /* mb safe. '/' can't be in any encoded char. */
439                 end = strchr(start, '/');
440
441                 /*
442                  * Chop the name at this point.
443                  */
444                 if (end) {
445                         *end = 0;
446                 }
447
448                 if (save_last_component) {
449                         TALLOC_FREE(smb_fname->original_lcomp);
450                         smb_fname->original_lcomp = talloc_strdup(smb_fname,
451                                                         end ? end + 1 : start);
452                         if (!smb_fname->original_lcomp) {
453                                 DEBUG(0, ("talloc failed\n"));
454                                 status = NT_STATUS_NO_MEMORY;
455                                 goto err;
456                         }
457                 }
458
459                 /* The name cannot have a component of "." */
460
461                 if (ISDOT(start)) {
462                         if (!end)  {
463                                 /* Error code at the end of a pathname. */
464                                 status = NT_STATUS_OBJECT_NAME_INVALID;
465                         } else {
466                                 status = determine_path_error(end+1,
467                                                 allow_wcard_last_component);
468                         }
469                         goto fail;
470                 }
471
472                 /* The name cannot have a wildcard if it's not
473                    the last component. */
474
475                 name_has_wildcard = ms_has_wild(start);
476
477                 /* Wildcards never valid within a pathname. */
478                 if (name_has_wildcard && end) {
479                         status = NT_STATUS_OBJECT_NAME_INVALID;
480                         goto fail;
481                 }
482
483                 /*
484                  * Check if the name exists up to this point.
485                  */
486
487                 if (posix_pathnames) {
488                         ret = SMB_VFS_LSTAT(conn, smb_fname);
489                 } else {
490                         ret = SMB_VFS_STAT(conn, smb_fname);
491                 }
492
493                 if (ret == 0) {
494                         /*
495                          * It exists. it must either be a directory or this must
496                          * be the last part of the path for it to be OK.
497                          */
498                         if (end && !S_ISDIR(smb_fname->st.st_ex_mode)) {
499                                 /*
500                                  * An intermediate part of the name isn't
501                                  * a directory.
502                                  */
503                                 DEBUG(5,("Not a dir %s\n",start));
504                                 *end = '/';
505                                 /*
506                                  * We need to return the fact that the
507                                  * intermediate name resolution failed. This
508                                  * is used to return an error of ERRbadpath
509                                  * rather than ERRbadfile. Some Windows
510                                  * applications depend on the difference between
511                                  * these two errors.
512                                  */
513                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
514                                 goto fail;
515                         }
516
517                 } else {
518                         char *found_name = NULL;
519
520                         /* Stat failed - ensure we don't use it. */
521                         SET_STAT_INVALID(smb_fname->st);
522
523                         /*
524                          * Reset errno so we can detect
525                          * directory open errors.
526                          */
527                         errno = 0;
528
529                         /*
530                          * Try to find this part of the path in the directory.
531                          */
532
533                         if (name_has_wildcard ||
534                             (get_real_filename(conn, dirpath, start,
535                                                talloc_tos(),
536                                                &found_name) == -1)) {
537                                 char *unmangled;
538
539                                 if (end) {
540                                         /*
541                                          * An intermediate part of the name
542                                          * can't be found.
543                                          */
544                                         DEBUG(5,("Intermediate not found %s\n",
545                                                         start));
546                                         *end = '/';
547
548                                         /*
549                                          * We need to return the fact that the
550                                          * intermediate name resolution failed.
551                                          * This is used to return an error of
552                                          * ERRbadpath rather than ERRbadfile.
553                                          * Some Windows applications depend on
554                                          * the difference between these two
555                                          * errors.
556                                          */
557
558                                         /*
559                                          * ENOENT, ENOTDIR and ELOOP all map
560                                          * to NT_STATUS_OBJECT_PATH_NOT_FOUND
561                                          * in the filename walk.
562                                          */
563
564                                         if (errno == ENOENT ||
565                                                         errno == ENOTDIR ||
566                                                         errno == ELOOP) {
567                                                 status =
568                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
569                                         }
570                                         else {
571                                                 status =
572                                                 map_nt_error_from_unix(errno);
573                                         }
574                                         goto fail;
575                                 }
576
577                                 /*
578                                  * ENOENT/EACCESS are the only valid errors
579                                  * here. EACCESS needs handling here for
580                                  * "dropboxes", i.e. directories where users
581                                  * can only put stuff with permission -wx.
582                                  */
583                                 if ((errno != 0) && (errno != ENOENT)
584                                     && (errno != EACCES)) {
585                                         /*
586                                          * ENOTDIR and ELOOP both map to
587                                          * NT_STATUS_OBJECT_PATH_NOT_FOUND
588                                          * in the filename walk.
589                                          */
590                                         if (errno == ENOTDIR ||
591                                                         errno == ELOOP) {
592                                                 status =
593                                                 NT_STATUS_OBJECT_PATH_NOT_FOUND;
594                                         } else {
595                                                 status =
596                                                 map_nt_error_from_unix(errno);
597                                         }
598                                         goto fail;
599                                 }
600
601                                 /*
602                                  * Just the last part of the name doesn't exist.
603                                  * We need to strupper() or strlower() it as
604                                  * this conversion may be used for file creation
605                                  * purposes. Fix inspired by
606                                  * Thomas Neumann <t.neumann@iku-ag.de>.
607                                  */
608                                 if (!conn->case_preserve ||
609                                     (mangle_is_8_3(start, False,
610                                                    conn->params) &&
611                                                  !conn->short_case_preserve)) {
612                                         strnorm(start,
613                                                 lp_defaultcase(SNUM(conn)));
614                                 }
615
616                                 /*
617                                  * check on the mangled stack to see if we can
618                                  * recover the base of the filename.
619                                  */
620
621                                 if (mangle_is_mangled(start, conn->params)
622                                     && mangle_lookup_name_from_8_3(ctx,
623                                                         start,
624                                                         &unmangled,
625                                                         conn->params)) {
626                                         char *tmp;
627                                         size_t start_ofs =
628                                             start - smb_fname->base_name;
629
630                                         if (*dirpath != '\0') {
631                                                 tmp = talloc_asprintf(
632                                                         smb_fname, "%s/%s",
633                                                         dirpath, unmangled);
634                                                 TALLOC_FREE(unmangled);
635                                         }
636                                         else {
637                                                 tmp = unmangled;
638                                         }
639                                         if (tmp == NULL) {
640                                                 DEBUG(0, ("talloc failed\n"));
641                                                 status = NT_STATUS_NO_MEMORY;
642                                                 goto err;
643                                         }
644                                         TALLOC_FREE(smb_fname->base_name);
645                                         smb_fname->base_name = tmp;
646                                         start =
647                                             smb_fname->base_name + start_ofs;
648                                         end = start + strlen(start);
649                                 }
650
651                                 DEBUG(5,("New file %s\n",start));
652                                 goto done;
653                         }
654
655
656                         /*
657                          * Restore the rest of the string. If the string was
658                          * mangled the size may have changed.
659                          */
660                         if (end) {
661                                 char *tmp;
662                                 size_t start_ofs =
663                                     start - smb_fname->base_name;
664
665                                 if (*dirpath != '\0') {
666                                         tmp = talloc_asprintf(smb_fname,
667                                                 "%s/%s/%s", dirpath,
668                                                 found_name, end+1);
669                                 }
670                                 else {
671                                         tmp = talloc_asprintf(smb_fname,
672                                                 "%s/%s", found_name,
673                                                 end+1);
674                                 }
675                                 if (tmp == NULL) {
676                                         DEBUG(0, ("talloc_asprintf failed\n"));
677                                         status = NT_STATUS_NO_MEMORY;
678                                         goto err;
679                                 }
680                                 TALLOC_FREE(smb_fname->base_name);
681                                 smb_fname->base_name = tmp;
682                                 start = smb_fname->base_name + start_ofs;
683                                 end = start + strlen(found_name);
684                                 *end = '\0';
685                         } else {
686                                 char *tmp;
687                                 size_t start_ofs =
688                                     start - smb_fname->base_name;
689
690                                 if (*dirpath != '\0') {
691                                         tmp = talloc_asprintf(smb_fname,
692                                                 "%s/%s", dirpath,
693                                                 found_name);
694                                 } else {
695                                         tmp = talloc_strdup(smb_fname,
696                                                 found_name);
697                                 }
698                                 if (tmp == NULL) {
699                                         DEBUG(0, ("talloc failed\n"));
700                                         status = NT_STATUS_NO_MEMORY;
701                                         goto err;
702                                 }
703                                 TALLOC_FREE(smb_fname->base_name);
704                                 smb_fname->base_name = tmp;
705                                 start = smb_fname->base_name + start_ofs;
706
707                                 /*
708                                  * We just scanned for, and found the end of
709                                  * the path. We must return a valid stat struct
710                                  * if it exists. JRA.
711                                  */
712
713                                 if (posix_pathnames) {
714                                         ret = SMB_VFS_LSTAT(conn, smb_fname);
715                                 } else {
716                                         ret = SMB_VFS_STAT(conn, smb_fname);
717                                 }
718
719                                 if (ret != 0) {
720                                         SET_STAT_INVALID(smb_fname->st);
721                                 }
722                         }
723
724                         TALLOC_FREE(found_name);
725                 } /* end else */
726
727 #ifdef DEVELOPER
728                 /*
729                  * This sucks!
730                  * We should never provide different behaviors
731                  * depending on DEVELOPER!!!
732                  */
733                 if (VALID_STAT(smb_fname->st)) {
734                         bool delete_pending;
735                         get_file_infos(vfs_file_id_from_sbuf(conn,
736                                                              &smb_fname->st),
737                                        &delete_pending, NULL);
738                         if (delete_pending) {
739                                 status = NT_STATUS_DELETE_PENDING;
740                                 goto fail;
741                         }
742                 }
743 #endif
744
745                 /*
746                  * Add to the dirpath that we have resolved so far.
747                  */
748
749                 if (*dirpath != '\0') {
750                         char *tmp = talloc_asprintf(ctx,
751                                         "%s/%s", dirpath, start);
752                         if (!tmp) {
753                                 DEBUG(0, ("talloc_asprintf failed\n"));
754                                 status = NT_STATUS_NO_MEMORY;
755                                 goto err;
756                         }
757                         TALLOC_FREE(dirpath);
758                         dirpath = tmp;
759                 }
760                 else {
761                         TALLOC_FREE(dirpath);
762                         if (!(dirpath = talloc_strdup(ctx,start))) {
763                                 DEBUG(0, ("talloc_strdup failed\n"));
764                                 status = NT_STATUS_NO_MEMORY;
765                                 goto err;
766                         }
767                 }
768
769                 /*
770                  * Cache the dirpath thus far. Don't cache a name with mangled
771                  * or wildcard components as this can change the size.
772                  */
773                 if(!component_was_mangled && !name_has_wildcard) {
774                         stat_cache_add(orig_path, dirpath,
775                                         conn->case_sensitive);
776                 }
777
778                 /*
779                  * Restore the / that we wiped out earlier.
780                  */
781                 if (end) {
782                         *end = '/';
783                 }
784         }
785
786         /*
787          * Cache the full path. Don't cache a name with mangled or wildcard
788          * components as this can change the size.
789          */
790
791         if(!component_was_mangled && !name_has_wildcard) {
792                 stat_cache_add(orig_path, smb_fname->base_name,
793                                conn->case_sensitive);
794         }
795
796         /*
797          * The name has been resolved.
798          */
799
800         DEBUG(5,("conversion finished %s -> %s\n", orig_path,
801                  smb_fname->base_name));
802
803  done:
804         /* Add back the stream if one was stripped off originally. */
805         if (stream != NULL) {
806                 smb_fname->stream_name = stream;
807
808                 /* Check path now that the base_name has been converted. */
809                 status = build_stream_path(ctx, conn, orig_path, smb_fname);
810                 if (!NT_STATUS_IS_OK(status)) {
811                         goto fail;
812                 }
813         }
814         TALLOC_FREE(dirpath);
815         *smb_fname_out = smb_fname;
816         return NT_STATUS_OK;
817  fail:
818         DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
819         if (*dirpath != '\0') {
820                 smb_fname->base_name = talloc_asprintf(smb_fname, "%s/%s",
821                                                        dirpath, start);
822         } else {
823                 smb_fname->base_name = talloc_strdup(smb_fname, start);
824         }
825         if (!smb_fname->base_name) {
826                 DEBUG(0, ("talloc_asprintf failed\n"));
827                 status = NT_STATUS_NO_MEMORY;
828                 goto err;
829         }
830
831         *smb_fname_out = smb_fname;
832         TALLOC_FREE(dirpath);
833         return status;
834  err:
835         TALLOC_FREE(smb_fname);
836         return status;
837 }
838
839 /****************************************************************************
840  Check a filename - possibly calling check_reduced_name.
841  This is called by every routine before it allows an operation on a filename.
842  It does any final confirmation necessary to ensure that the filename is
843  a valid one for the user to access.
844 ****************************************************************************/
845
846 NTSTATUS check_name(connection_struct *conn, const char *name)
847 {
848         if (IS_VETO_PATH(conn, name))  {
849                 /* Is it not dot or dot dot. */
850                 if (!((name[0] == '.') && (!name[1] ||
851                                         (name[1] == '.' && !name[2])))) {
852                         DEBUG(5,("check_name: file path name %s vetoed\n",
853                                                 name));
854                         return map_nt_error_from_unix(ENOENT);
855                 }
856         }
857
858         if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
859                 NTSTATUS status = check_reduced_name(conn,name);
860                 if (!NT_STATUS_IS_OK(status)) {
861                         DEBUG(5,("check_name: name %s failed with %s\n",name,
862                                                 nt_errstr(status)));
863                         return status;
864                 }
865         }
866
867         return NT_STATUS_OK;
868 }
869
870 /****************************************************************************
871  Check if two filenames are equal.
872  This needs to be careful about whether we are case sensitive.
873 ****************************************************************************/
874
875 static bool fname_equal(const char *name1, const char *name2,
876                 bool case_sensitive)
877 {
878         /* Normal filename handling */
879         if (case_sensitive) {
880                 return(strcmp(name1,name2) == 0);
881         }
882
883         return(strequal(name1,name2));
884 }
885
886 /****************************************************************************
887  Scan a directory to find a filename, matching without case sensitivity.
888  If the name looks like a mangled name then try via the mangling functions
889 ****************************************************************************/
890
891 static int get_real_filename_full_scan(connection_struct *conn,
892                                        const char *path, const char *name,
893                                        bool mangled,
894                                        TALLOC_CTX *mem_ctx, char **found_name)
895 {
896         struct smb_Dir *cur_dir;
897         const char *dname = NULL;
898         char *talloced = NULL;
899         char *unmangled_name = NULL;
900         long curpos;
901
902         /* handle null paths */
903         if ((path == NULL) || (*path == 0)) {
904                 path = ".";
905         }
906
907         /* If we have a case-sensitive filesystem, it doesn't do us any
908          * good to search for a name. If a case variation of the name was
909          * there, then the original stat(2) would have found it.
910          */
911         if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
912                 errno = ENOENT;
913                 return -1;
914         }
915
916         /*
917          * The incoming name can be mangled, and if we de-mangle it
918          * here it will not compare correctly against the filename (name2)
919          * read from the directory and then mangled by the name_to_8_3()
920          * call. We need to mangle both names or neither.
921          * (JRA).
922          *
923          * Fix for bug found by Dina Fine. If in case sensitive mode then
924          * the mangle cache is no good (3 letter extension could be wrong
925          * case - so don't demangle in this case - leave as mangled and
926          * allow the mangling of the directory entry read (which is done
927          * case insensitively) to match instead. This will lead to more
928          * false positive matches but we fail completely without it. JRA.
929          */
930
931         if (mangled && !conn->case_sensitive) {
932                 mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
933                                                        &unmangled_name,
934                                                        conn->params);
935                 if (!mangled) {
936                         /* Name is now unmangled. */
937                         name = unmangled_name;
938                 }
939         }
940
941         /* open the directory */
942         if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) {
943                 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
944                 TALLOC_FREE(unmangled_name);
945                 return -1;
946         }
947
948         /* now scan for matching names */
949         curpos = 0;
950         while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) {
951
952                 /* Is it dot or dot dot. */
953                 if (ISDOT(dname) || ISDOTDOT(dname)) {
954                         TALLOC_FREE(talloced);
955                         continue;
956                 }
957
958                 /*
959                  * At this point dname is the unmangled name.
960                  * name is either mangled or not, depending on the state
961                  * of the "mangled" variable. JRA.
962                  */
963
964                 /*
965                  * Check mangled name against mangled name, or unmangled name
966                  * against unmangled name.
967                  */
968
969                 if ((mangled && mangled_equal(name,dname,conn->params)) ||
970                         fname_equal(name, dname, conn->case_sensitive)) {
971                         /* we've found the file, change it's name and return */
972                         *found_name = talloc_strdup(mem_ctx, dname);
973                         TALLOC_FREE(unmangled_name);
974                         TALLOC_FREE(cur_dir);
975                         if (!*found_name) {
976                                 errno = ENOMEM;
977                                 TALLOC_FREE(talloced);
978                                 return -1;
979                         }
980                         TALLOC_FREE(talloced);
981                         return 0;
982                 }
983                 TALLOC_FREE(talloced);
984         }
985
986         TALLOC_FREE(unmangled_name);
987         TALLOC_FREE(cur_dir);
988         errno = ENOENT;
989         return -1;
990 }
991
992 /****************************************************************************
993  Wrapper around the vfs get_real_filename and the full directory scan
994  fallback.
995 ****************************************************************************/
996
997 int get_real_filename(connection_struct *conn, const char *path,
998                       const char *name, TALLOC_CTX *mem_ctx,
999                       char **found_name)
1000 {
1001         int ret;
1002         bool mangled;
1003
1004         mangled = mangle_is_mangled(name, conn->params);
1005
1006         if (mangled) {
1007                 return get_real_filename_full_scan(conn, path, name, mangled,
1008                                                    mem_ctx, found_name);
1009         }
1010
1011         /* Try the vfs first to take advantage of case-insensitive stat. */
1012         ret = SMB_VFS_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name);
1013
1014         /*
1015          * If the case-insensitive stat was successful, or returned an error
1016          * other than EOPNOTSUPP then there is no need to fall back on the
1017          * full directory scan.
1018          */
1019         if (ret == 0 || (ret == -1 && errno != EOPNOTSUPP)) {
1020                 return ret;
1021         }
1022
1023         return get_real_filename_full_scan(conn, path, name, mangled, mem_ctx,
1024                                            found_name);
1025 }
1026
1027 static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
1028                                   connection_struct *conn,
1029                                   const char *orig_path,
1030                                   struct smb_filename *smb_fname)
1031 {
1032         NTSTATUS status;
1033         unsigned int i, num_streams;
1034         struct stream_struct *streams = NULL;
1035
1036         if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1037                 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1038                 return NT_STATUS_OK;
1039         }
1040
1041         if (errno != ENOENT) {
1042                 DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno)));
1043                 status = map_nt_error_from_unix(errno);
1044                 goto fail;
1045         }
1046
1047         /* Fall back to a case-insensitive scan of all streams on the file. */
1048         status = SMB_VFS_STREAMINFO(conn, NULL, smb_fname->base_name, mem_ctx,
1049                                     &num_streams, &streams);
1050
1051         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1052                 SET_STAT_INVALID(smb_fname->st);
1053                 return NT_STATUS_OK;
1054         }
1055
1056         if (!NT_STATUS_IS_OK(status)) {
1057                 DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status)));
1058                 goto fail;
1059         }
1060
1061         for (i=0; i<num_streams; i++) {
1062                 DEBUG(10, ("comparing [%s] and [%s]: ",
1063                            smb_fname->stream_name, streams[i].name));
1064                 if (fname_equal(smb_fname->stream_name, streams[i].name,
1065                                 conn->case_sensitive)) {
1066                         DEBUGADD(10, ("equal\n"));
1067                         break;
1068                 }
1069                 DEBUGADD(10, ("not equal\n"));
1070         }
1071
1072         /* Couldn't find the stream. */
1073         if (i == num_streams) {
1074                 SET_STAT_INVALID(smb_fname->st);
1075                 TALLOC_FREE(streams);
1076                 return NT_STATUS_OK;
1077         }
1078
1079         DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
1080                 smb_fname->stream_name, streams[i].name));
1081
1082
1083         TALLOC_FREE(smb_fname->stream_name);
1084         smb_fname->stream_name = talloc_strdup(smb_fname, streams[i].name);
1085         if (smb_fname->stream_name == NULL) {
1086                 status = NT_STATUS_NO_MEMORY;
1087                 goto fail;
1088         }
1089
1090         SET_STAT_INVALID(smb_fname->st);
1091
1092         if (SMB_VFS_STAT(conn, smb_fname) == 0) {
1093                 DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
1094         }
1095         status = NT_STATUS_OK;
1096  fail:
1097         TALLOC_FREE(streams);
1098         return status;
1099 }
1100
1101 /**
1102  * Go through all the steps to validate a filename.
1103  *
1104  * @param ctx           talloc_ctx to allocate memory with.
1105  * @param conn          connection struct for vfs calls.
1106  * @param dfs_path      Whether this path requires dfs resolution.
1107  * @param name_in       The unconverted name.
1108  * @param ucf_flags     flags to pass through to unix_convert().
1109  *                      UCF_ALWAYS_ALLOW_WCARD_LCOMP will be OR'd in if
1110  *                      p_cont_wcard != NULL and is true and
1111  *                      UCF_COND_ALLOW_WCARD_LCOMP.
1112  * @param p_cont_wcard  If not NULL, will be set to true if the dfs path
1113  *                      resolution detects a wildcard.
1114  * @param pp_smb_fname  The final converted name will be allocated if the
1115  *                      return is NT_STATUS_OK.
1116  *
1117  * @return NT_STATUS_OK if all operations completed succesfully, appropriate
1118  *         error otherwise.
1119  */
1120 NTSTATUS filename_convert(TALLOC_CTX *ctx,
1121                                 connection_struct *conn,
1122                                 bool dfs_path,
1123                                 const char *name_in,
1124                                 uint32_t ucf_flags,
1125                                 bool *ppath_contains_wcard,
1126                                 struct smb_filename **pp_smb_fname)
1127 {
1128         NTSTATUS status;
1129         bool allow_wcards = (ucf_flags & (UCF_COND_ALLOW_WCARD_LCOMP|UCF_ALWAYS_ALLOW_WCARD_LCOMP));
1130         char *fname = NULL;
1131
1132         *pp_smb_fname = NULL;
1133
1134         status = resolve_dfspath_wcard(ctx, conn,
1135                                 dfs_path,
1136                                 name_in,
1137                                 allow_wcards,
1138                                 &fname,
1139                                 ppath_contains_wcard);
1140         if (!NT_STATUS_IS_OK(status)) {
1141                 DEBUG(10,("filename_convert: resolve_dfspath failed "
1142                         "for name %s with %s\n",
1143                         name_in,
1144                         nt_errstr(status) ));
1145                 return status;
1146         }
1147
1148         if (is_fake_file_path(name_in)) {
1149                 SMB_STRUCT_STAT st;
1150                 ZERO_STRUCT(st);
1151                 st.st_ex_nlink = 1;
1152                 status = create_synthetic_smb_fname_split(ctx,
1153                                                           name_in,
1154                                                           &st,
1155                                                           pp_smb_fname);
1156                 return status;
1157         }
1158
1159         /*
1160          * If the caller conditionally allows wildcard lookups, only add the
1161          * always allow if the path actually does contain a wildcard.
1162          */
1163         if (ucf_flags & UCF_COND_ALLOW_WCARD_LCOMP &&
1164             ppath_contains_wcard != NULL && *ppath_contains_wcard) {
1165                 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
1166         }
1167
1168         status = unix_convert(ctx, conn, fname, pp_smb_fname, ucf_flags);
1169         if (!NT_STATUS_IS_OK(status)) {
1170                 DEBUG(10,("filename_convert: unix_convert failed "
1171                         "for name %s with %s\n",
1172                         fname,
1173                         nt_errstr(status) ));
1174                 return status;
1175         }
1176
1177         status = check_name(conn, (*pp_smb_fname)->base_name);
1178         if (!NT_STATUS_IS_OK(status)) {
1179                 DEBUG(3,("filename_convert: check_name failed "
1180                         "for name %s with %s\n",
1181                         smb_fname_str_dbg(*pp_smb_fname),
1182                         nt_errstr(status) ));
1183                 TALLOC_FREE(*pp_smb_fname);
1184                 return status;
1185         }
1186
1187         return status;
1188 }