s3: Fix some False/NULL hickups
[kai/samba-autobuild/.git] / source3 / smbd / dir.c
1 /*
2    Unix SMB/CIFS implementation.
3    Directory handling routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "libcli/security/security.h"
26 #include "lib/util/bitmap.h"
27
28 /*
29    This module implements directory related functions for Samba.
30 */
31
32 /* "Special" directory offsets. */
33 #define END_OF_DIRECTORY_OFFSET ((long)-1)
34 #define START_OF_DIRECTORY_OFFSET ((long)0)
35 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
36
37 /* Make directory handle internals available. */
38
39 struct name_cache_entry {
40         char *name;
41         long offset;
42 };
43
44 struct smb_Dir {
45         connection_struct *conn;
46         SMB_STRUCT_DIR *dir;
47         long offset;
48         char *dir_path;
49         size_t name_cache_size;
50         struct name_cache_entry *name_cache;
51         unsigned int name_cache_index;
52         unsigned int file_number;
53 };
54
55 struct dptr_struct {
56         struct dptr_struct *next, *prev;
57         int dnum;
58         uint16 spid;
59         struct connection_struct *conn;
60         struct smb_Dir *dir_hnd;
61         bool expect_close;
62         char *wcard;
63         uint32 attr;
64         char *path;
65         bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
66         bool did_stat; /* Optimisation for non-wcard searches. */
67 };
68
69 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
70                         files_struct *fsp,
71                         const char *mask,
72                         uint32 attr);
73
74 #define INVALID_DPTR_KEY (-3)
75
76 /****************************************************************************
77  Make a dir struct.
78 ****************************************************************************/
79
80 bool make_dir_struct(TALLOC_CTX *ctx,
81                         char *buf,
82                         const char *mask,
83                         const char *fname,
84                         SMB_OFF_T size,
85                         uint32 mode,
86                         time_t date,
87                         bool uc)
88 {
89         char *p;
90         char *mask2 = talloc_strdup(ctx, mask);
91
92         if (!mask2) {
93                 return False;
94         }
95
96         if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
97                 size = 0;
98         }
99
100         memset(buf+1,' ',11);
101         if ((p = strchr_m(mask2,'.')) != NULL) {
102                 *p = 0;
103                 push_ascii(buf+1,mask2,8, 0);
104                 push_ascii(buf+9,p+1,3, 0);
105                 *p = '.';
106         } else {
107                 push_ascii(buf+1,mask2,11, 0);
108         }
109
110         memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
111         SCVAL(buf,21,mode);
112         srv_put_dos_date(buf,22,date);
113         SSVAL(buf,26,size & 0xFFFF);
114         SSVAL(buf,28,(size >> 16)&0xFFFF);
115         /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
116            Strange, but verified on W2K3. Needed for OS/2. JRA. */
117         push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
118         DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
119         return True;
120 }
121
122 /****************************************************************************
123  Initialise the dir bitmap.
124 ****************************************************************************/
125
126 bool init_dptrs(struct smbd_server_connection *sconn)
127 {
128         if (sconn->searches.dptr_bmap) {
129                 return true;
130         }
131
132         sconn->searches.dptr_bmap = bitmap_talloc(
133                 sconn, MAX_DIRECTORY_HANDLES);
134
135         if (sconn->searches.dptr_bmap == NULL) {
136                 return false;
137         }
138
139         return true;
140 }
141
142 /****************************************************************************
143  Idle a dptr - the directory is closed but the control info is kept.
144 ****************************************************************************/
145
146 static void dptr_idle(struct dptr_struct *dptr)
147 {
148         if (dptr->dir_hnd) {
149                 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
150                 TALLOC_FREE(dptr->dir_hnd);
151         }
152 }
153
154 /****************************************************************************
155  Idle the oldest dptr.
156 ****************************************************************************/
157
158 static void dptr_idleoldest(struct smbd_server_connection *sconn)
159 {
160         struct dptr_struct *dptr;
161
162         /*
163          * Go to the end of the list.
164          */
165         dptr = DLIST_TAIL(sconn->searches.dirptrs);
166
167         if(!dptr) {
168                 DEBUG(0,("No dptrs available to idle ?\n"));
169                 return;
170         }
171
172         /*
173          * Idle the oldest pointer.
174          */
175
176         for(; dptr; dptr = DLIST_PREV(dptr)) {
177                 if (dptr->dir_hnd) {
178                         dptr_idle(dptr);
179                         return;
180                 }
181         }
182 }
183
184 /****************************************************************************
185  Get the struct dptr_struct for a dir index.
186 ****************************************************************************/
187
188 static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
189                                     int key, bool forclose)
190 {
191         struct dptr_struct *dptr;
192
193         for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) {
194                 if(dptr->dnum == key) {
195                         if (!forclose && !dptr->dir_hnd) {
196                                 if (sconn->searches.dirhandles_open >= MAX_OPEN_DIRECTORIES)
197                                         dptr_idleoldest(sconn);
198                                 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
199                                 if (!(dptr->dir_hnd = OpenDir(
200                                               NULL, dptr->conn, dptr->path,
201                                               dptr->wcard, dptr->attr))) {
202                                         DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
203                                                 strerror(errno)));
204                                         return NULL;
205                                 }
206                         }
207                         DLIST_PROMOTE(sconn->searches.dirptrs,dptr);
208                         return dptr;
209                 }
210         }
211         return(NULL);
212 }
213
214 /****************************************************************************
215  Get the dir path for a dir index.
216 ****************************************************************************/
217
218 char *dptr_path(struct smbd_server_connection *sconn, int key)
219 {
220         struct dptr_struct *dptr = dptr_get(sconn, key, false);
221         if (dptr)
222                 return(dptr->path);
223         return(NULL);
224 }
225
226 /****************************************************************************
227  Get the dir wcard for a dir index.
228 ****************************************************************************/
229
230 char *dptr_wcard(struct smbd_server_connection *sconn, int key)
231 {
232         struct dptr_struct *dptr = dptr_get(sconn, key, false);
233         if (dptr)
234                 return(dptr->wcard);
235         return(NULL);
236 }
237
238 /****************************************************************************
239  Get the dir attrib for a dir index.
240 ****************************************************************************/
241
242 uint16 dptr_attr(struct smbd_server_connection *sconn, int key)
243 {
244         struct dptr_struct *dptr = dptr_get(sconn, key, false);
245         if (dptr)
246                 return(dptr->attr);
247         return(0);
248 }
249
250 /****************************************************************************
251  Close a dptr (internal func).
252 ****************************************************************************/
253
254 static void dptr_close_internal(struct dptr_struct *dptr)
255 {
256         struct smbd_server_connection *sconn = dptr->conn->sconn;
257
258         DEBUG(4,("closing dptr key %d\n",dptr->dnum));
259
260         if (sconn == NULL) {
261                 goto done;
262         }
263
264         if (sconn->using_smb2) {
265                 goto done;
266         }
267
268         DLIST_REMOVE(sconn->searches.dirptrs, dptr);
269
270         /*
271          * Free the dnum in the bitmap. Remember the dnum value is always 
272          * biased by one with respect to the bitmap.
273          */
274
275         if (!bitmap_query(sconn->searches.dptr_bmap, dptr->dnum - 1)) {
276                 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
277                         dptr->dnum ));
278         }
279
280         bitmap_clear(sconn->searches.dptr_bmap, dptr->dnum - 1);
281
282 done:
283         TALLOC_FREE(dptr->dir_hnd);
284
285         /* Lanman 2 specific code */
286         SAFE_FREE(dptr->wcard);
287         SAFE_FREE(dptr->path);
288         SAFE_FREE(dptr);
289 }
290
291 /****************************************************************************
292  Close a dptr given a key.
293 ****************************************************************************/
294
295 void dptr_close(struct smbd_server_connection *sconn, int *key)
296 {
297         struct dptr_struct *dptr;
298
299         if(*key == INVALID_DPTR_KEY)
300                 return;
301
302         /* OS/2 seems to use -1 to indicate "close all directories" */
303         if (*key == -1) {
304                 struct dptr_struct *next;
305                 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
306                         next = dptr->next;
307                         dptr_close_internal(dptr);
308                 }
309                 *key = INVALID_DPTR_KEY;
310                 return;
311         }
312
313         dptr = dptr_get(sconn, *key, true);
314
315         if (!dptr) {
316                 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
317                 return;
318         }
319
320         dptr_close_internal(dptr);
321
322         *key = INVALID_DPTR_KEY;
323 }
324
325 /****************************************************************************
326  Close all dptrs for a cnum.
327 ****************************************************************************/
328
329 void dptr_closecnum(connection_struct *conn)
330 {
331         struct dptr_struct *dptr, *next;
332         struct smbd_server_connection *sconn = conn->sconn;
333
334         if (sconn == NULL) {
335                 return;
336         }
337
338         for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
339                 next = dptr->next;
340                 if (dptr->conn == conn) {
341                         dptr_close_internal(dptr);
342                 }
343         }
344 }
345
346 /****************************************************************************
347  Idle all dptrs for a cnum.
348 ****************************************************************************/
349
350 void dptr_idlecnum(connection_struct *conn)
351 {
352         struct dptr_struct *dptr;
353         struct smbd_server_connection *sconn = conn->sconn;
354
355         if (sconn == NULL) {
356                 return;
357         }
358
359         for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) {
360                 if (dptr->conn == conn && dptr->dir_hnd) {
361                         dptr_idle(dptr);
362                 }
363         }
364 }
365
366 /****************************************************************************
367  Close a dptr that matches a given path, only if it matches the spid also.
368 ****************************************************************************/
369
370 void dptr_closepath(struct smbd_server_connection *sconn,
371                     char *path,uint16 spid)
372 {
373         struct dptr_struct *dptr, *next;
374         for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
375                 next = dptr->next;
376                 if (spid == dptr->spid && strequal(dptr->path,path))
377                         dptr_close_internal(dptr);
378         }
379 }
380
381 /****************************************************************************
382  Try and close the oldest handle not marked for
383  expect close in the hope that the client has
384  finished with that one.
385 ****************************************************************************/
386
387 static void dptr_close_oldest(struct smbd_server_connection *sconn,
388                               bool old)
389 {
390         struct dptr_struct *dptr;
391
392         /*
393          * Go to the end of the list.
394          */
395         for(dptr = sconn->searches.dirptrs; dptr && dptr->next; dptr = dptr->next)
396                 ;
397
398         if(!dptr) {
399                 DEBUG(0,("No old dptrs available to close oldest ?\n"));
400                 return;
401         }
402
403         /*
404          * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
405          * does not have expect_close set. If 'old' is false, close
406          * one of the new dnum handles.
407          */
408
409         for(; dptr; dptr = DLIST_PREV(dptr)) {
410                 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
411                         (!old && (dptr->dnum > 255))) {
412                                 dptr_close_internal(dptr);
413                                 return;
414                 }
415         }
416 }
417
418 /****************************************************************************
419  Create a new dir ptr. If the flag old_handle is true then we must allocate
420  from the bitmap range 0 - 255 as old SMBsearch directory handles are only
421  one byte long. If old_handle is false we allocate from the range
422  256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
423  a directory handle is never zero.
424  wcard must not be zero.
425 ****************************************************************************/
426
427 NTSTATUS dptr_create(connection_struct *conn, files_struct *fsp,
428                 const char *path, bool old_handle, bool expect_close,uint16 spid,
429                 const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
430 {
431         struct smbd_server_connection *sconn = conn->sconn;
432         struct dptr_struct *dptr = NULL;
433         struct smb_Dir *dir_hnd;
434
435         if (fsp && fsp->is_directory && fsp->fh->fd != -1) {
436                 path = fsp->fsp_name->base_name;
437         }
438
439         DEBUG(5,("dptr_create dir=%s\n", path));
440
441         if (sconn == NULL) {
442                 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
443                 return NT_STATUS_INTERNAL_ERROR;
444         }
445
446         if (!wcard) {
447                 return NT_STATUS_INVALID_PARAMETER;
448         }
449
450         if (fsp) {
451                 if (!(fsp->access_mask & SEC_DIR_LIST)) {
452                         DEBUG(5,("dptr_create: directory %s "
453                                 "not open for LIST access\n",
454                                 path));
455                         return NT_STATUS_ACCESS_DENIED;
456                 }
457                 dir_hnd = OpenDir_fsp(NULL, conn, fsp, wcard, attr);
458         } else {
459                 int ret;
460                 struct smb_filename *smb_dname = NULL;
461                 NTSTATUS status = create_synthetic_smb_fname(talloc_tos(),
462                                                 path,
463                                                 NULL,
464                                                 NULL,
465                                                 &smb_dname);
466                 if (!NT_STATUS_IS_OK(status)) {
467                         return status;
468                 }
469                 if (lp_posix_pathnames()) {
470                         ret = SMB_VFS_LSTAT(conn, smb_dname);
471                 } else {
472                         ret = SMB_VFS_STAT(conn, smb_dname);
473                 }
474                 if (ret == -1) {
475                         return map_nt_error_from_unix(errno);
476                 }
477                 if (!S_ISDIR(smb_dname->st.st_ex_mode)) {
478                         return NT_STATUS_NOT_A_DIRECTORY;
479                 }
480                 status = smbd_check_access_rights(conn,
481                                                 smb_dname,
482                                                 SEC_DIR_LIST);
483                 if (!NT_STATUS_IS_OK(status)) {
484                         return status;
485                 }
486                 dir_hnd = OpenDir(NULL, conn, path, wcard, attr);
487         }
488
489         if (!dir_hnd) {
490                 return map_nt_error_from_unix(errno);
491         }
492
493         if (sconn->searches.dirhandles_open >= MAX_OPEN_DIRECTORIES) {
494                 dptr_idleoldest(sconn);
495         }
496
497         dptr = SMB_MALLOC_P(struct dptr_struct);
498         if(!dptr) {
499                 DEBUG(0,("malloc fail in dptr_create.\n"));
500                 TALLOC_FREE(dir_hnd);
501                 return NT_STATUS_NO_MEMORY;
502         }
503
504         ZERO_STRUCTP(dptr);
505
506         dptr->path = SMB_STRDUP(path);
507         if (!dptr->path) {
508                 SAFE_FREE(dptr);
509                 TALLOC_FREE(dir_hnd);
510                 return NT_STATUS_NO_MEMORY;
511         }
512         dptr->conn = conn;
513         dptr->dir_hnd = dir_hnd;
514         dptr->spid = spid;
515         dptr->expect_close = expect_close;
516         dptr->wcard = SMB_STRDUP(wcard);
517         if (!dptr->wcard) {
518                 SAFE_FREE(dptr->path);
519                 SAFE_FREE(dptr);
520                 TALLOC_FREE(dir_hnd);
521                 return NT_STATUS_NO_MEMORY;
522         }
523         if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
524                 dptr->has_wild = True;
525         } else {
526                 dptr->has_wild = wcard_has_wild;
527         }
528
529         dptr->attr = attr;
530
531         if (sconn->using_smb2) {
532                 goto done;
533         }
534
535         if(old_handle) {
536
537                 /*
538                  * This is an old-style SMBsearch request. Ensure the
539                  * value we return will fit in the range 1-255.
540                  */
541
542                 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
543
544                 if(dptr->dnum == -1 || dptr->dnum > 254) {
545
546                         /*
547                          * Try and close the oldest handle not marked for
548                          * expect close in the hope that the client has
549                          * finished with that one.
550                          */
551
552                         dptr_close_oldest(sconn, true);
553
554                         /* Now try again... */
555                         dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
556                         if(dptr->dnum == -1 || dptr->dnum > 254) {
557                                 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
558                                 SAFE_FREE(dptr->path);
559                                 SAFE_FREE(dptr->wcard);
560                                 SAFE_FREE(dptr);
561                                 TALLOC_FREE(dir_hnd);
562                                 return NT_STATUS_TOO_MANY_OPENED_FILES;
563                         }
564                 }
565         } else {
566
567                 /*
568                  * This is a new-style trans2 request. Allocate from
569                  * a range that will return 256 - MAX_DIRECTORY_HANDLES.
570                  */
571
572                 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
573
574                 if(dptr->dnum == -1 || dptr->dnum < 255) {
575
576                         /*
577                          * Try and close the oldest handle close in the hope that
578                          * the client has finished with that one. This will only
579                          * happen in the case of the Win98 client bug where it leaks
580                          * directory handles.
581                          */
582
583                         dptr_close_oldest(sconn, false);
584
585                         /* Now try again... */
586                         dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
587
588                         if(dptr->dnum == -1 || dptr->dnum < 255) {
589                                 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
590                                 SAFE_FREE(dptr->path);
591                                 SAFE_FREE(dptr->wcard);
592                                 SAFE_FREE(dptr);
593                                 TALLOC_FREE(dir_hnd);
594                                 return NT_STATUS_TOO_MANY_OPENED_FILES;
595                         }
596                 }
597         }
598
599         bitmap_set(sconn->searches.dptr_bmap, dptr->dnum);
600
601         dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
602
603         DLIST_ADD(sconn->searches.dirptrs, dptr);
604
605 done:
606         DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
607                 dptr->dnum,path,expect_close));  
608
609         *dptr_ret = dptr;
610
611         return NT_STATUS_OK;
612 }
613
614
615 /****************************************************************************
616  Wrapper functions to access the lower level directory handles.
617 ****************************************************************************/
618
619 void dptr_CloseDir(files_struct *fsp)
620 {
621         if (fsp->dptr) {
622 /*
623  * Ugly hack. We have defined fdopendir to return ENOSYS if dirfd also isn't
624  * present. I hate Solaris. JRA.
625  */
626 #ifdef HAVE_DIRFD
627                 if (fsp->fh->fd != -1 &&
628                                 fsp->dptr->dir_hnd &&
629                                 dirfd(fsp->dptr->dir_hnd->dir)) {
630                         /* The call below closes the underlying fd. */
631                         fsp->fh->fd = -1;
632                 }
633 #endif
634                 dptr_close_internal(fsp->dptr);
635                 fsp->dptr = NULL;
636         }
637 }
638
639 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
640 {
641         SeekDir(dptr->dir_hnd, offset);
642 }
643
644 long dptr_TellDir(struct dptr_struct *dptr)
645 {
646         return TellDir(dptr->dir_hnd);
647 }
648
649 bool dptr_has_wild(struct dptr_struct *dptr)
650 {
651         return dptr->has_wild;
652 }
653
654 int dptr_dnum(struct dptr_struct *dptr)
655 {
656         return dptr->dnum;
657 }
658
659 /****************************************************************************
660  Return the next visible file name, skipping veto'd and invisible files.
661 ****************************************************************************/
662
663 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
664                                            long *poffset, SMB_STRUCT_STAT *pst,
665                                            char **ptalloced)
666 {
667         /* Normal search for the next file. */
668         const char *name;
669         char *talloced = NULL;
670
671         while ((name = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced))
672                != NULL) {
673                 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
674                         *ptalloced = talloced;
675                         return name;
676                 }
677                 TALLOC_FREE(talloced);
678         }
679         return NULL;
680 }
681
682 /****************************************************************************
683  Return the next visible file name, skipping veto'd and invisible files.
684 ****************************************************************************/
685
686 char *dptr_ReadDirName(TALLOC_CTX *ctx,
687                         struct dptr_struct *dptr,
688                         long *poffset,
689                         SMB_STRUCT_STAT *pst)
690 {
691         struct smb_filename smb_fname_base;
692         char *name = NULL;
693         const char *name_temp = NULL;
694         char *talloced = NULL;
695         char *pathreal = NULL;
696         char *found_name = NULL;
697         int ret;
698
699         SET_STAT_INVALID(*pst);
700
701         if (dptr->has_wild || dptr->did_stat) {
702                 name_temp = dptr_normal_ReadDirName(dptr, poffset, pst,
703                                                     &talloced);
704                 if (name_temp == NULL) {
705                         return NULL;
706                 }
707                 if (talloced != NULL) {
708                         return talloc_move(ctx, &talloced);
709                 }
710                 return talloc_strdup(ctx, name_temp);
711         }
712
713         /* If poffset is -1 then we know we returned this name before and we
714          * have no wildcards. We're at the end of the directory. */
715         if (*poffset == END_OF_DIRECTORY_OFFSET) {
716                 return NULL;
717         }
718
719         /* We know the stored wcard contains no wildcard characters.
720          * See if we can match with a stat call. If we can't, then set
721          * did_stat to true to ensure we only do this once and keep
722          * searching. */
723
724         dptr->did_stat = true;
725
726         /* First check if it should be visible. */
727         if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard,
728             pst, true))
729         {
730                 /* This only returns false if the file was found, but
731                    is explicitly not visible. Set us to end of
732                    directory, but return NULL as we know we can't ever
733                    find it. */
734                 goto ret;
735         }
736
737         if (VALID_STAT(*pst)) {
738                 name = talloc_strdup(ctx, dptr->wcard);
739                 goto ret;
740         }
741
742         pathreal = talloc_asprintf(ctx,
743                                 "%s/%s",
744                                 dptr->path,
745                                 dptr->wcard);
746         if (!pathreal)
747                 return NULL;
748
749         /* Create an smb_filename with stream_name == NULL. */
750         ZERO_STRUCT(smb_fname_base);
751         smb_fname_base.base_name = pathreal;
752
753         if (SMB_VFS_STAT(dptr->conn, &smb_fname_base) == 0) {
754                 *pst = smb_fname_base.st;
755                 name = talloc_strdup(ctx, dptr->wcard);
756                 goto clean;
757         } else {
758                 /* If we get any other error than ENOENT or ENOTDIR
759                    then the file exists we just can't stat it. */
760                 if (errno != ENOENT && errno != ENOTDIR) {
761                         name = talloc_strdup(ctx, dptr->wcard);
762                         goto clean;
763                 }
764         }
765
766         /* Stat failed. We know this is authoratiative if we are
767          * providing case sensitive semantics or the underlying
768          * filesystem is case sensitive.
769          */
770         if (dptr->conn->case_sensitive ||
771             !(dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
772         {
773                 goto clean;
774         }
775
776         /*
777          * Try case-insensitive stat if the fs has the ability. This avoids
778          * scanning the whole directory.
779          */
780         ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn, dptr->path, dptr->wcard,
781                                         ctx, &found_name);
782         if (ret == 0) {
783                 name = found_name;
784                 goto clean;
785         } else if (errno == ENOENT) {
786                 /* The case-insensitive lookup was authoritative. */
787                 goto clean;
788         }
789
790         TALLOC_FREE(pathreal);
791
792         name_temp = dptr_normal_ReadDirName(dptr, poffset, pst, &talloced);
793         if (name_temp == NULL) {
794                 return NULL;
795         }
796         if (talloced != NULL) {
797                 return talloc_move(ctx, &talloced);
798         }
799         return talloc_strdup(ctx, name_temp);
800
801 clean:
802         TALLOC_FREE(pathreal);
803 ret:
804         /* We need to set the underlying dir_hnd offset to -1
805          * also as this function is usually called with the
806          * output from TellDir. */
807         dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
808         return name;
809 }
810
811 /****************************************************************************
812  Search for a file by name, skipping veto'ed and not visible files.
813 ****************************************************************************/
814
815 bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
816 {
817         SET_STAT_INVALID(*pst);
818
819         if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
820                 /* This is a singleton directory and we're already at the end. */
821                 *poffset = END_OF_DIRECTORY_OFFSET;
822                 return False;
823         }
824
825         return SearchDir(dptr->dir_hnd, name, poffset);
826 }
827
828 /****************************************************************************
829  Add the name we're returning into the underlying cache.
830 ****************************************************************************/
831
832 void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset)
833 {
834         DirCacheAdd(dptr->dir_hnd, name, offset);
835 }
836
837 /****************************************************************************
838  Initialize variables & state data at the beginning of all search SMB requests.
839 ****************************************************************************/
840 void dptr_init_search_op(struct dptr_struct *dptr)
841 {
842         SMB_VFS_INIT_SEARCH_OP(dptr->conn, dptr->dir_hnd->dir);
843 }
844
845 /****************************************************************************
846  Fill the 5 byte server reserved dptr field.
847 ****************************************************************************/
848
849 bool dptr_fill(struct smbd_server_connection *sconn,
850                char *buf1,unsigned int key)
851 {
852         unsigned char *buf = (unsigned char *)buf1;
853         struct dptr_struct *dptr = dptr_get(sconn, key, false);
854         uint32 offset;
855         if (!dptr) {
856                 DEBUG(1,("filling null dirptr %d\n",key));
857                 return(False);
858         }
859         offset = (uint32)TellDir(dptr->dir_hnd);
860         DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
861                 (long)dptr->dir_hnd,(int)offset));
862         buf[0] = key;
863         SIVAL(buf,1,offset);
864         return(True);
865 }
866
867 /****************************************************************************
868  Fetch the dir ptr and seek it given the 5 byte server field.
869 ****************************************************************************/
870
871 struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
872                                char *buf, int *num)
873 {
874         unsigned int key = *(unsigned char *)buf;
875         struct dptr_struct *dptr = dptr_get(sconn, key, false);
876         uint32 offset;
877         long seekoff;
878
879         if (!dptr) {
880                 DEBUG(3,("fetched null dirptr %d\n",key));
881                 return(NULL);
882         }
883         *num = key;
884         offset = IVAL(buf,1);
885         if (offset == (uint32)-1) {
886                 seekoff = END_OF_DIRECTORY_OFFSET;
887         } else {
888                 seekoff = (long)offset;
889         }
890         SeekDir(dptr->dir_hnd,seekoff);
891         DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
892                 key, dptr->path, (int)seekoff));
893         return(dptr);
894 }
895
896 /****************************************************************************
897  Fetch the dir ptr.
898 ****************************************************************************/
899
900 struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
901                                        int dptr_num)
902 {
903         struct dptr_struct *dptr  = dptr_get(sconn, dptr_num, false);
904
905         if (!dptr) {
906                 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
907                 return(NULL);
908         }
909         DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr->path));
910         return(dptr);
911 }
912
913 /****************************************************************************
914  Check that a file matches a particular file type.
915 ****************************************************************************/
916
917 bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
918 {
919         uint32 mask;
920
921         /* Check the "may have" search bits. */
922         if (((mode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) != 0)
923                 return False;
924
925         /* Check the "must have" bits, which are the may have bits shifted eight */
926         /* If must have bit is set, the file/dir can not be returned in search unless the matching
927                 file attribute is set */
928         mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
929         if(mask) {
930                 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))) == mask)   /* check if matching attribute present */
931                         return True;
932                 else
933                         return False;
934         }
935
936         return True;
937 }
938
939 static bool mangle_mask_match(connection_struct *conn,
940                 const char *filename,
941                 const char *mask)
942 {
943         char mname[13];
944
945         if (!name_to_8_3(filename,mname,False,conn->params)) {
946                 return False;
947         }
948         return mask_match_search(mname,mask,False);
949 }
950
951 bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
952                            struct dptr_struct *dirptr,
953                            const char *mask,
954                            uint32_t dirtype,
955                            bool dont_descend,
956                            bool ask_sharemode,
957                            bool (*match_fn)(TALLOC_CTX *ctx,
958                                             void *private_data,
959                                             const char *dname,
960                                             const char *mask,
961                                             char **_fname),
962                            bool (*mode_fn)(TALLOC_CTX *ctx,
963                                            void *private_data,
964                                            struct smb_filename *smb_fname,
965                                            uint32_t *_mode),
966                            void *private_data,
967                            char **_fname,
968                            struct smb_filename **_smb_fname,
969                            uint32_t *_mode,
970                            long *_prev_offset)
971 {
972         connection_struct *conn = dirptr->conn;
973         bool needslash;
974
975         *_smb_fname = NULL;
976         *_mode = 0;
977
978         needslash = ( dirptr->path[strlen(dirptr->path) -1] != '/');
979
980         while (true) {
981                 long cur_offset;
982                 long prev_offset;
983                 SMB_STRUCT_STAT sbuf;
984                 char *dname = NULL;
985                 bool isdots;
986                 char *fname = NULL;
987                 char *pathreal = NULL;
988                 struct smb_filename smb_fname;
989                 uint32_t mode = 0;
990                 bool ok;
991                 NTSTATUS status;
992
993                 cur_offset = dptr_TellDir(dirptr);
994                 prev_offset = cur_offset;
995                 dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf);
996
997                 DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
998                         (long)dirptr, cur_offset));
999
1000                 if (dname == NULL) {
1001                         return false;
1002                 }
1003
1004                 isdots = (ISDOT(dname) || ISDOTDOT(dname));
1005                 if (dont_descend && !isdots) {
1006                         TALLOC_FREE(dname);
1007                         continue;
1008                 }
1009
1010                 /*
1011                  * fname may get mangled, dname is never mangled.
1012                  * Whenever we're accessing the filesystem we use
1013                  * pathreal which is composed from dname.
1014                  */
1015
1016                 ok = match_fn(ctx, private_data, dname, mask, &fname);
1017                 if (!ok) {
1018                         TALLOC_FREE(dname);
1019                         continue;
1020                 }
1021
1022                 pathreal = talloc_asprintf(ctx, "%s%s%s",
1023                                            dirptr->path,
1024                                            needslash?"/":"",
1025                                            dname);
1026                 if (!pathreal) {
1027                         TALLOC_FREE(dname);
1028                         TALLOC_FREE(fname);
1029                         return false;
1030                 }
1031
1032                 /* Create smb_fname with NULL stream_name. */
1033                 ZERO_STRUCT(smb_fname);
1034                 smb_fname.base_name = pathreal;
1035                 smb_fname.st = sbuf;
1036
1037                 ok = mode_fn(ctx, private_data, &smb_fname, &mode);
1038                 if (!ok) {
1039                         TALLOC_FREE(dname);
1040                         TALLOC_FREE(fname);
1041                         TALLOC_FREE(pathreal);
1042                         continue;
1043                 }
1044
1045                 if (!dir_check_ftype(conn, mode, dirtype)) {
1046                         DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1047                                 fname, (unsigned int)mode, (unsigned int)dirtype));
1048                         TALLOC_FREE(dname);
1049                         TALLOC_FREE(fname);
1050                         TALLOC_FREE(pathreal);
1051                         continue;
1052                 }
1053
1054                 if (ask_sharemode) {
1055                         struct timespec write_time_ts;
1056                         struct file_id fileid;
1057
1058                         fileid = vfs_file_id_from_sbuf(conn,
1059                                                        &smb_fname.st);
1060                         get_file_infos(fileid, 0, NULL, &write_time_ts);
1061                         if (!null_timespec(write_time_ts)) {
1062                                 update_stat_ex_mtime(&smb_fname.st,
1063                                                      write_time_ts);
1064                         }
1065                 }
1066
1067                 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1068                         "fname=%s (%s)\n",
1069                         mask, smb_fname_str_dbg(&smb_fname),
1070                         dname, fname));
1071
1072                 DirCacheAdd(dirptr->dir_hnd, dname, cur_offset);
1073
1074                 TALLOC_FREE(dname);
1075
1076                 status = copy_smb_filename(ctx, &smb_fname, _smb_fname);
1077                 TALLOC_FREE(pathreal);
1078                 if (!NT_STATUS_IS_OK(status)) {
1079                         return false;
1080                 }
1081                 *_fname = fname;
1082                 *_mode = mode;
1083                 *_prev_offset = prev_offset;
1084
1085                 return true;
1086         }
1087
1088         return false;
1089 }
1090
1091 /****************************************************************************
1092  Get an 8.3 directory entry.
1093 ****************************************************************************/
1094
1095 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
1096                                      void *private_data,
1097                                      const char *dname,
1098                                      const char *mask,
1099                                      char **_fname)
1100 {
1101         connection_struct *conn = (connection_struct *)private_data;
1102
1103         if ((strcmp(mask,"*.*") == 0) ||
1104             mask_match_search(dname, mask, false) ||
1105             mangle_mask_match(conn, dname, mask)) {
1106                 char mname[13];
1107                 const char *fname;
1108
1109                 if (!mangle_is_8_3(dname, false, conn->params)) {
1110                         bool ok = name_to_8_3(dname, mname, false,
1111                                               conn->params);
1112                         if (!ok) {
1113                                 return false;
1114                         }
1115                         fname = mname;
1116                 } else {
1117                         fname = dname;
1118                 }
1119
1120                 *_fname = talloc_strdup(ctx, fname);
1121                 if (*_fname == NULL) {
1122                         return false;
1123                 }
1124
1125                 return true;
1126         }
1127
1128         return false;
1129 }
1130
1131 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx,
1132                                     void *private_data,
1133                                     struct smb_filename *smb_fname,
1134                                     uint32_t *_mode)
1135 {
1136         connection_struct *conn = (connection_struct *)private_data;
1137
1138         if (!VALID_STAT(smb_fname->st)) {
1139                 if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
1140                         DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1141                                  "Couldn't stat [%s]. Error "
1142                                  "= %s\n",
1143                                  smb_fname_str_dbg(smb_fname),
1144                                  strerror(errno)));
1145                         return false;
1146                 }
1147         }
1148
1149         *_mode = dos_mode(conn, smb_fname);
1150         return true;
1151 }
1152
1153 bool get_dir_entry(TALLOC_CTX *ctx,
1154                 struct dptr_struct *dirptr,
1155                 const char *mask,
1156                 uint32_t dirtype,
1157                 char **_fname,
1158                 SMB_OFF_T *_size,
1159                 uint32_t *_mode,
1160                 struct timespec *_date,
1161                 bool check_descend,
1162                 bool ask_sharemode)
1163 {
1164         connection_struct *conn = dirptr->conn;
1165         char *fname = NULL;
1166         struct smb_filename *smb_fname = NULL;
1167         uint32_t mode = 0;
1168         long prev_offset;
1169         bool ok;
1170
1171         ok = smbd_dirptr_get_entry(ctx,
1172                                    dirptr,
1173                                    mask,
1174                                    dirtype,
1175                                    check_descend,
1176                                    ask_sharemode,
1177                                    smbd_dirptr_8_3_match_fn,
1178                                    smbd_dirptr_8_3_mode_fn,
1179                                    conn,
1180                                    &fname,
1181                                    &smb_fname,
1182                                    &mode,
1183                                    &prev_offset);
1184         if (!ok) {
1185                 return false;
1186         }
1187
1188         *_fname = talloc_move(ctx, &fname);
1189         *_size = smb_fname->st.st_ex_size;
1190         *_mode = mode;
1191         *_date = smb_fname->st.st_ex_mtime;
1192         TALLOC_FREE(smb_fname);
1193         return true;
1194 }
1195
1196 /*******************************************************************
1197  Check to see if a user can read a file. This is only approximate,
1198  it is used as part of the "hide unreadable" option. Don't
1199  use it for anything security sensitive.
1200 ********************************************************************/
1201
1202 static bool user_can_read_file(connection_struct *conn,
1203                                struct smb_filename *smb_fname)
1204 {
1205         /*
1206          * Never hide files from the root user.
1207          * We use (uid_t)0 here not sec_initial_uid()
1208          * as make test uses a single user context.
1209          */
1210
1211         if (get_current_uid(conn) == (uid_t)0) {
1212                 return True;
1213         }
1214
1215         return NT_STATUS_IS_OK(smbd_check_access_rights(conn,
1216                                 smb_fname,
1217                                 FILE_READ_DATA));
1218 }
1219
1220 /*******************************************************************
1221  Check to see if a user can write a file (and only files, we do not
1222  check dirs on this one). This is only approximate,
1223  it is used as part of the "hide unwriteable" option. Don't
1224  use it for anything security sensitive.
1225 ********************************************************************/
1226
1227 static bool user_can_write_file(connection_struct *conn,
1228                                 const struct smb_filename *smb_fname)
1229 {
1230         /*
1231          * Never hide files from the root user.
1232          * We use (uid_t)0 here not sec_initial_uid()
1233          * as make test uses a single user context.
1234          */
1235
1236         if (get_current_uid(conn) == (uid_t)0) {
1237                 return True;
1238         }
1239
1240         SMB_ASSERT(VALID_STAT(smb_fname->st));
1241
1242         /* Pseudo-open the file */
1243
1244         if(S_ISDIR(smb_fname->st.st_ex_mode)) {
1245                 return True;
1246         }
1247
1248         return can_write_to_file(conn, smb_fname);
1249 }
1250
1251 /*******************************************************************
1252   Is a file a "special" type ?
1253 ********************************************************************/
1254
1255 static bool file_is_special(connection_struct *conn,
1256                             const struct smb_filename *smb_fname)
1257 {
1258         /*
1259          * Never hide files from the root user.
1260          * We use (uid_t)0 here not sec_initial_uid()
1261          * as make test uses a single user context.
1262          */
1263
1264         if (get_current_uid(conn) == (uid_t)0) {
1265                 return False;
1266         }
1267
1268         SMB_ASSERT(VALID_STAT(smb_fname->st));
1269
1270         if (S_ISREG(smb_fname->st.st_ex_mode) ||
1271             S_ISDIR(smb_fname->st.st_ex_mode) ||
1272             S_ISLNK(smb_fname->st.st_ex_mode))
1273                 return False;
1274
1275         return True;
1276 }
1277
1278 /*******************************************************************
1279  Should the file be seen by the client?
1280  NOTE: A successful return is no guarantee of the file's existence.
1281 ********************************************************************/
1282
1283 bool is_visible_file(connection_struct *conn, const char *dir_path,
1284                      const char *name, SMB_STRUCT_STAT *pst, bool use_veto)
1285 {
1286         bool hide_unreadable = lp_hideunreadable(SNUM(conn));
1287         bool hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
1288         bool hide_special = lp_hide_special_files(SNUM(conn));
1289         char *entry = NULL;
1290         struct smb_filename *smb_fname_base = NULL;
1291         NTSTATUS status;
1292         bool ret = false;
1293
1294         if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1295                 return True; /* . and .. are always visible. */
1296         }
1297
1298         /* If it's a vetoed file, pretend it doesn't even exist */
1299         if (use_veto && IS_VETO_PATH(conn, name)) {
1300                 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1301                 return False;
1302         }
1303
1304         if (hide_unreadable || hide_unwriteable || hide_special) {
1305                 entry = talloc_asprintf(talloc_tos(), "%s/%s", dir_path, name);
1306                 if (!entry) {
1307                         ret = false;
1308                         goto out;
1309                 }
1310
1311                 /* Create an smb_filename with stream_name == NULL. */
1312                 status = create_synthetic_smb_fname(talloc_tos(), entry, NULL,
1313                                                     pst, &smb_fname_base);
1314                 if (!NT_STATUS_IS_OK(status)) {
1315                         ret = false;
1316                         goto out;
1317                 }
1318
1319                 /* If the file name does not exist, there's no point checking
1320                  * the configuration options. We succeed, on the basis that the
1321                  * checks *might* have passed if the file was present.
1322                  */
1323                 if (!VALID_STAT(*pst)) {
1324                         if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
1325                                 ret = true;
1326                                 goto out;
1327                         } else {
1328                                 *pst = smb_fname_base->st;
1329                         }
1330                 }
1331
1332                 /* Honour _hide unreadable_ option */
1333                 if (hide_unreadable &&
1334                     !user_can_read_file(conn, smb_fname_base)) {
1335                         DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1336                                  entry ));
1337                         ret = false;
1338                         goto out;
1339                 }
1340                 /* Honour _hide unwriteable_ option */
1341                 if (hide_unwriteable && !user_can_write_file(conn,
1342                                                              smb_fname_base)) {
1343                         DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1344                                  entry ));
1345                         ret = false;
1346                         goto out;
1347                 }
1348                 /* Honour _hide_special_ option */
1349                 if (hide_special && file_is_special(conn, smb_fname_base)) {
1350                         DEBUG(10,("is_visible_file: file %s is special.\n",
1351                                  entry ));
1352                         ret = false;
1353                         goto out;
1354                 }
1355         }
1356
1357         ret = true;
1358  out:
1359         TALLOC_FREE(smb_fname_base);
1360         TALLOC_FREE(entry);
1361         return ret;
1362 }
1363
1364 static int smb_Dir_destructor(struct smb_Dir *dirp)
1365 {
1366         if (dirp->dir) {
1367 #ifdef HAVE_DIRFD
1368                 if (dirp->conn->sconn) {
1369                         files_struct *fsp = file_find_fd(dirp->conn->sconn,
1370                                                 dirfd(dirp->dir));
1371                         if (fsp) {
1372                                 /* The call below closes the underlying fd. */
1373                                 fsp->fh->fd = -1;
1374                         }
1375                 }
1376 #endif
1377                 SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1378         }
1379         if (dirp->conn->sconn && !dirp->conn->sconn->using_smb2) {
1380                 dirp->conn->sconn->searches.dirhandles_open--;
1381         }
1382         return 0;
1383 }
1384
1385 /*******************************************************************
1386  Open a directory.
1387 ********************************************************************/
1388
1389 struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
1390                         const char *name,
1391                         const char *mask,
1392                         uint32 attr)
1393 {
1394         struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir);
1395         struct smbd_server_connection *sconn = conn->sconn;
1396
1397         if (!dirp) {
1398                 return NULL;
1399         }
1400
1401         dirp->conn = conn;
1402         dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1403
1404         dirp->dir_path = talloc_strdup(dirp, name);
1405         if (!dirp->dir_path) {
1406                 errno = ENOMEM;
1407                 goto fail;
1408         }
1409
1410         if (sconn && !sconn->using_smb2) {
1411                 sconn->searches.dirhandles_open++;
1412         }
1413         talloc_set_destructor(dirp, smb_Dir_destructor);
1414
1415         dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1416         if (!dirp->dir) {
1417                 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path,
1418                          strerror(errno) ));
1419                 goto fail;
1420         }
1421
1422         return dirp;
1423
1424   fail:
1425         TALLOC_FREE(dirp);
1426         return NULL;
1427 }
1428
1429 /*******************************************************************
1430  Open a directory from an fsp.
1431 ********************************************************************/
1432
1433 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
1434                         files_struct *fsp,
1435                         const char *mask,
1436                         uint32 attr)
1437 {
1438         struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir);
1439         struct smbd_server_connection *sconn = conn->sconn;
1440
1441         if (!dirp) {
1442                 return NULL;
1443         }
1444
1445         dirp->conn = conn;
1446         dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1447
1448         dirp->dir_path = talloc_strdup(dirp, fsp->fsp_name->base_name);
1449         if (!dirp->dir_path) {
1450                 errno = ENOMEM;
1451                 goto fail;
1452         }
1453
1454         if (sconn && !sconn->using_smb2) {
1455                 sconn->searches.dirhandles_open++;
1456         }
1457         talloc_set_destructor(dirp, smb_Dir_destructor);
1458
1459         if (fsp->is_directory && fsp->fh->fd != -1) {
1460                 dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
1461                 if (dirp->dir == NULL) {
1462                         DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1463                                 "NULL (%s)\n",
1464                                 dirp->dir_path,
1465                                 strerror(errno)));
1466                         if (errno != ENOSYS) {
1467                                 return NULL;
1468                         }
1469                 }
1470         }
1471
1472         if (dirp->dir == NULL) {
1473                 /* FDOPENDIR didn't work. Use OPENDIR instead. */
1474                 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1475         }
1476
1477         if (!dirp->dir) {
1478                 DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp->dir_path,
1479                          strerror(errno) ));
1480                 goto fail;
1481         }
1482
1483         return dirp;
1484
1485   fail:
1486         TALLOC_FREE(dirp);
1487         return NULL;
1488 }
1489
1490
1491 /*******************************************************************
1492  Read from a directory.
1493  Return directory entry, current offset, and optional stat information.
1494  Don't check for veto or invisible files.
1495 ********************************************************************/
1496
1497 const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
1498                         SMB_STRUCT_STAT *sbuf, char **ptalloced)
1499 {
1500         const char *n;
1501         char *talloced = NULL;
1502         connection_struct *conn = dirp->conn;
1503
1504         /* Cheat to allow . and .. to be the first entries returned. */
1505         if (((*poffset == START_OF_DIRECTORY_OFFSET) ||
1506              (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2))
1507         {
1508                 if (dirp->file_number == 0) {
1509                         n = ".";
1510                         *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1511                 } else {
1512                         n = "..";
1513                         *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1514                 }
1515                 dirp->file_number++;
1516                 *ptalloced = NULL;
1517                 return n;
1518         } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
1519                 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1520                 return NULL;
1521         } else {
1522                 /* A real offset, seek to it. */
1523                 SeekDir(dirp, *poffset);
1524         }
1525
1526         while ((n = vfs_readdirname(conn, dirp->dir, sbuf, &talloced))) {
1527                 /* Ignore . and .. - we've already returned them. */
1528                 if (*n == '.') {
1529                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1530                                 TALLOC_FREE(talloced);
1531                                 continue;
1532                         }
1533                 }
1534                 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1535                 *ptalloced = talloced;
1536                 dirp->file_number++;
1537                 return n;
1538         }
1539         *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1540         *ptalloced = NULL;
1541         return NULL;
1542 }
1543
1544 /*******************************************************************
1545  Rewind to the start.
1546 ********************************************************************/
1547
1548 void RewindDir(struct smb_Dir *dirp, long *poffset)
1549 {
1550         SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1551         dirp->file_number = 0;
1552         dirp->offset = START_OF_DIRECTORY_OFFSET;
1553         *poffset = START_OF_DIRECTORY_OFFSET;
1554 }
1555
1556 /*******************************************************************
1557  Seek a dir.
1558 ********************************************************************/
1559
1560 void SeekDir(struct smb_Dir *dirp, long offset)
1561 {
1562         if (offset != dirp->offset) {
1563                 if (offset == START_OF_DIRECTORY_OFFSET) {
1564                         RewindDir(dirp, &offset);
1565                         /*
1566                          * Ok we should really set the file number here
1567                          * to 1 to enable ".." to be returned next. Trouble
1568                          * is I'm worried about callers using SeekDir(dirp,0)
1569                          * as equivalent to RewindDir(). So leave this alone
1570                          * for now.
1571                          */
1572                 } else if  (offset == DOT_DOT_DIRECTORY_OFFSET) {
1573                         RewindDir(dirp, &offset);
1574                         /*
1575                          * Set the file number to 2 - we want to get the first
1576                          * real file entry (the one we return after "..")
1577                          * on the next ReadDir.
1578                          */
1579                         dirp->file_number = 2;
1580                 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1581                         ; /* Don't seek in this case. */
1582                 } else {
1583                         SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1584                 }
1585                 dirp->offset = offset;
1586         }
1587 }
1588
1589 /*******************************************************************
1590  Tell a dir position.
1591 ********************************************************************/
1592
1593 long TellDir(struct smb_Dir *dirp)
1594 {
1595         return(dirp->offset);
1596 }
1597
1598 /*******************************************************************
1599  Add an entry into the dcache.
1600 ********************************************************************/
1601
1602 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1603 {
1604         struct name_cache_entry *e;
1605
1606         if (dirp->name_cache_size == 0) {
1607                 return;
1608         }
1609
1610         if (dirp->name_cache == NULL) {
1611                 dirp->name_cache = talloc_zero_array(
1612                         dirp, struct name_cache_entry, dirp->name_cache_size);
1613
1614                 if (dirp->name_cache == NULL) {
1615                         return;
1616                 }
1617         }
1618
1619         dirp->name_cache_index = (dirp->name_cache_index+1) %
1620                                         dirp->name_cache_size;
1621         e = &dirp->name_cache[dirp->name_cache_index];
1622         TALLOC_FREE(e->name);
1623         e->name = talloc_strdup(dirp, name);
1624         e->offset = offset;
1625 }
1626
1627 /*******************************************************************
1628  Find an entry by name. Leave us at the offset after it.
1629  Don't check for veto or invisible files.
1630 ********************************************************************/
1631
1632 bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1633 {
1634         int i;
1635         const char *entry = NULL;
1636         char *talloced = NULL;
1637         connection_struct *conn = dirp->conn;
1638
1639         /* Search back in the name cache. */
1640         if (dirp->name_cache_size && dirp->name_cache) {
1641                 for (i = dirp->name_cache_index; i >= 0; i--) {
1642                         struct name_cache_entry *e = &dirp->name_cache[i];
1643                         if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1644                                 *poffset = e->offset;
1645                                 SeekDir(dirp, e->offset);
1646                                 return True;
1647                         }
1648                 }
1649                 for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
1650                         struct name_cache_entry *e = &dirp->name_cache[i];
1651                         if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1652                                 *poffset = e->offset;
1653                                 SeekDir(dirp, e->offset);
1654                                 return True;
1655                         }
1656                 }
1657         }
1658
1659         /* Not found in the name cache. Rewind directory and start from scratch. */
1660         SMB_VFS_REWINDDIR(conn, dirp->dir);
1661         dirp->file_number = 0;
1662         *poffset = START_OF_DIRECTORY_OFFSET;
1663         while ((entry = ReadDirName(dirp, poffset, NULL, &talloced))) {
1664                 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1665                         TALLOC_FREE(talloced);
1666                         return True;
1667                 }
1668                 TALLOC_FREE(talloced);
1669         }
1670         return False;
1671 }
1672
1673 /*****************************************************************
1674  Is this directory empty ?
1675 *****************************************************************/
1676
1677 NTSTATUS can_delete_directory(struct connection_struct *conn,
1678                               const char *dirname)
1679 {
1680         NTSTATUS status = NT_STATUS_OK;
1681         long dirpos = 0;
1682         const char *dname = NULL;
1683         char *talloced = NULL;
1684         SMB_STRUCT_STAT st;
1685         struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
1686                                         dirname, NULL, 0);
1687
1688         if (!dir_hnd) {
1689                 return map_nt_error_from_unix(errno);
1690         }
1691
1692         while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) {
1693                 /* Quick check for "." and ".." */
1694                 if (dname[0] == '.') {
1695                         if (!dname[1] || (dname[1] == '.' && !dname[2])) {
1696                                 TALLOC_FREE(talloced);
1697                                 continue;
1698                         }
1699                 }
1700
1701                 if (!is_visible_file(conn, dirname, dname, &st, True)) {
1702                         TALLOC_FREE(talloced);
1703                         continue;
1704                 }
1705
1706                 DEBUG(10,("can_delete_directory: got name %s - can't delete\n",
1707                          dname ));
1708                 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1709                 break;
1710         }
1711         TALLOC_FREE(talloced);
1712         TALLOC_FREE(dir_hnd);
1713
1714         return status;
1715 }