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