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