~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/smbd/dir.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "smbd/globals.h"
 
23
 
 
24
/*
 
25
   This module implements directory related functions for Samba.
 
26
*/
 
27
 
 
28
/* "Special" directory offsets. */
 
29
#define END_OF_DIRECTORY_OFFSET ((long)-1)
 
30
#define START_OF_DIRECTORY_OFFSET ((long)0)
 
31
#define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
 
32
 
 
33
/* Make directory handle internals available. */
 
34
 
 
35
struct name_cache_entry {
 
36
        char *name;
 
37
        long offset;
 
38
};
 
39
 
 
40
struct smb_Dir {
 
41
        connection_struct *conn;
 
42
        SMB_STRUCT_DIR *dir;
 
43
        long offset;
 
44
        char *dir_path;
 
45
        size_t name_cache_size;
 
46
        struct name_cache_entry *name_cache;
 
47
        unsigned int name_cache_index;
 
48
        unsigned int file_number;
 
49
};
 
50
 
 
51
struct dptr_struct {
 
52
        struct dptr_struct *next, *prev;
 
53
        int dnum;
 
54
        uint16 spid;
 
55
        struct connection_struct *conn;
 
56
        struct smb_Dir *dir_hnd;
 
57
        bool expect_close;
 
58
        char *wcard;
 
59
        uint32 attr;
 
60
        char *path;
 
61
        bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
 
62
        bool did_stat; /* Optimisation for non-wcard searches. */
 
63
};
 
64
 
 
65
 
 
66
#define INVALID_DPTR_KEY (-3)
 
67
 
 
68
/****************************************************************************
 
69
 Make a dir struct.
 
70
****************************************************************************/
 
71
 
 
72
bool make_dir_struct(TALLOC_CTX *ctx,
 
73
                        char *buf,
 
74
                        const char *mask,
 
75
                        const char *fname,
 
76
                        SMB_OFF_T size,
 
77
                        uint32 mode,
 
78
                        time_t date,
 
79
                        bool uc)
 
80
{
 
81
        char *p;
 
82
        char *mask2 = talloc_strdup(ctx, mask);
 
83
 
 
84
        if (!mask2) {
 
85
                return False;
 
86
        }
 
87
 
 
88
        if ((mode & aDIR) != 0) {
 
89
                size = 0;
 
90
        }
 
91
 
 
92
        memset(buf+1,' ',11);
 
93
        if ((p = strchr_m(mask2,'.')) != NULL) {
 
94
                *p = 0;
 
95
                push_ascii(buf+1,mask2,8, 0);
 
96
                push_ascii(buf+9,p+1,3, 0);
 
97
                *p = '.';
 
98
        } else {
 
99
                push_ascii(buf+1,mask2,11, 0);
 
100
        }
 
101
 
 
102
        memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
 
103
        SCVAL(buf,21,mode);
 
104
        srv_put_dos_date(buf,22,date);
 
105
        SSVAL(buf,26,size & 0xFFFF);
 
106
        SSVAL(buf,28,(size >> 16)&0xFFFF);
 
107
        /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
 
108
           Strange, but verified on W2K3. Needed for OS/2. JRA. */
 
109
        push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
 
110
        DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
 
111
        return True;
 
112
}
 
113
 
 
114
/****************************************************************************
 
115
 Initialise the dir bitmap.
 
116
****************************************************************************/
 
117
 
 
118
void init_dptrs(void)
 
119
{
 
120
        if (dptr_bmap)
 
121
                return;
 
122
 
 
123
        dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
 
124
 
 
125
        if (!dptr_bmap)
 
126
                exit_server("out of memory in init_dptrs");
 
127
}
 
128
 
 
129
/****************************************************************************
 
130
 Idle a dptr - the directory is closed but the control info is kept.
 
131
****************************************************************************/
 
132
 
 
133
static void dptr_idle(struct dptr_struct *dptr)
 
134
{
 
135
        if (dptr->dir_hnd) {
 
136
                DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
 
137
                TALLOC_FREE(dptr->dir_hnd);
 
138
        }
 
139
}
 
140
 
 
141
/****************************************************************************
 
142
 Idle the oldest dptr.
 
143
****************************************************************************/
 
144
 
 
145
static void dptr_idleoldest(void)
 
146
{
 
147
        struct dptr_struct *dptr;
 
148
 
 
149
        /*
 
150
         * Go to the end of the list.
 
151
         */
 
152
        for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
 
153
                ;
 
154
 
 
155
        if(!dptr) {
 
156
                DEBUG(0,("No dptrs available to idle ?\n"));
 
157
                return;
 
158
        }
 
159
 
 
160
        /*
 
161
         * Idle the oldest pointer.
 
162
         */
 
163
 
 
164
        for(; dptr; dptr = dptr->prev) {
 
165
                if (dptr->dir_hnd) {
 
166
                        dptr_idle(dptr);
 
167
                        return;
 
168
                }
 
169
        }
 
170
}
 
171
 
 
172
/****************************************************************************
 
173
 Get the struct dptr_struct for a dir index.
 
174
****************************************************************************/
 
175
 
 
176
static struct dptr_struct *dptr_get(int key, bool forclose)
 
177
{
 
178
        struct dptr_struct *dptr;
 
179
 
 
180
        for(dptr = dirptrs; dptr; dptr = dptr->next) {
 
181
                if(dptr->dnum == key) {
 
182
                        if (!forclose && !dptr->dir_hnd) {
 
183
                                if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
 
184
                                        dptr_idleoldest();
 
185
                                DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
 
186
                                if (!(dptr->dir_hnd = OpenDir(
 
187
                                              NULL, dptr->conn, dptr->path,
 
188
                                              dptr->wcard, dptr->attr))) {
 
189
                                        DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
 
190
                                                strerror(errno)));
 
191
                                        return False;
 
192
                                }
 
193
                        }
 
194
                        DLIST_PROMOTE(dirptrs,dptr);
 
195
                        return dptr;
 
196
                }
 
197
        }
 
198
        return(NULL);
 
199
}
 
200
 
 
201
/****************************************************************************
 
202
 Get the dir path for a dir index.
 
203
****************************************************************************/
 
204
 
 
205
char *dptr_path(int key)
 
206
{
 
207
        struct dptr_struct *dptr = dptr_get(key, False);
 
208
        if (dptr)
 
209
                return(dptr->path);
 
210
        return(NULL);
 
211
}
 
212
 
 
213
/****************************************************************************
 
214
 Get the dir wcard for a dir index.
 
215
****************************************************************************/
 
216
 
 
217
char *dptr_wcard(int key)
 
218
{
 
219
        struct dptr_struct *dptr = dptr_get(key, False);
 
220
        if (dptr)
 
221
                return(dptr->wcard);
 
222
        return(NULL);
 
223
}
 
224
 
 
225
/****************************************************************************
 
226
 Get the dir attrib for a dir index.
 
227
****************************************************************************/
 
228
 
 
229
uint16 dptr_attr(int key)
 
230
{
 
231
        struct dptr_struct *dptr = dptr_get(key, False);
 
232
        if (dptr)
 
233
                return(dptr->attr);
 
234
        return(0);
 
235
}
 
236
 
 
237
/****************************************************************************
 
238
 Close a dptr (internal func).
 
239
****************************************************************************/
 
240
 
 
241
static void dptr_close_internal(struct dptr_struct *dptr)
 
242
{
 
243
        DEBUG(4,("closing dptr key %d\n",dptr->dnum));
 
244
 
 
245
        DLIST_REMOVE(dirptrs, dptr);
 
246
 
 
247
        /*
 
248
         * Free the dnum in the bitmap. Remember the dnum value is always 
 
249
         * biased by one with respect to the bitmap.
 
250
         */
 
251
 
 
252
        if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
 
253
                DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
 
254
                        dptr->dnum ));
 
255
        }
 
256
 
 
257
        bitmap_clear(dptr_bmap, dptr->dnum - 1);
 
258
 
 
259
        TALLOC_FREE(dptr->dir_hnd);
 
260
 
 
261
        /* Lanman 2 specific code */
 
262
        SAFE_FREE(dptr->wcard);
 
263
        string_set(&dptr->path,"");
 
264
        SAFE_FREE(dptr);
 
265
}
 
266
 
 
267
/****************************************************************************
 
268
 Close a dptr given a key.
 
269
****************************************************************************/
 
270
 
 
271
void dptr_close(int *key)
 
272
{
 
273
        struct dptr_struct *dptr;
 
274
 
 
275
        if(*key == INVALID_DPTR_KEY)
 
276
                return;
 
277
 
 
278
        /* OS/2 seems to use -1 to indicate "close all directories" */
 
279
        if (*key == -1) {
 
280
                struct dptr_struct *next;
 
281
                for(dptr = dirptrs; dptr; dptr = next) {
 
282
                        next = dptr->next;
 
283
                        dptr_close_internal(dptr);
 
284
                }
 
285
                *key = INVALID_DPTR_KEY;
 
286
                return;
 
287
        }
 
288
 
 
289
        dptr = dptr_get(*key, True);
 
290
 
 
291
        if (!dptr) {
 
292
                DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
 
293
                return;
 
294
        }
 
295
 
 
296
        dptr_close_internal(dptr);
 
297
 
 
298
        *key = INVALID_DPTR_KEY;
 
299
}
 
300
 
 
301
/****************************************************************************
 
302
 Close all dptrs for a cnum.
 
303
****************************************************************************/
 
304
 
 
305
void dptr_closecnum(connection_struct *conn)
 
306
{
 
307
        struct dptr_struct *dptr, *next;
 
308
        for(dptr = dirptrs; dptr; dptr = next) {
 
309
                next = dptr->next;
 
310
                if (dptr->conn == conn)
 
311
                        dptr_close_internal(dptr);
 
312
        }
 
313
}
 
314
 
 
315
/****************************************************************************
 
316
 Idle all dptrs for a cnum.
 
317
****************************************************************************/
 
318
 
 
319
void dptr_idlecnum(connection_struct *conn)
 
320
{
 
321
        struct dptr_struct *dptr;
 
322
        for(dptr = dirptrs; dptr; dptr = dptr->next) {
 
323
                if (dptr->conn == conn && dptr->dir_hnd)
 
324
                        dptr_idle(dptr);
 
325
        }
 
326
}
 
327
 
 
328
/****************************************************************************
 
329
 Close a dptr that matches a given path, only if it matches the spid also.
 
330
****************************************************************************/
 
331
 
 
332
void dptr_closepath(char *path,uint16 spid)
 
333
{
 
334
        struct dptr_struct *dptr, *next;
 
335
        for(dptr = dirptrs; dptr; dptr = next) {
 
336
                next = dptr->next;
 
337
                if (spid == dptr->spid && strequal(dptr->path,path))
 
338
                        dptr_close_internal(dptr);
 
339
        }
 
340
}
 
341
 
 
342
/****************************************************************************
 
343
 Try and close the oldest handle not marked for
 
344
 expect close in the hope that the client has
 
345
 finished with that one.
 
346
****************************************************************************/
 
347
 
 
348
static void dptr_close_oldest(bool old)
 
349
{
 
350
        struct dptr_struct *dptr;
 
351
 
 
352
        /*
 
353
         * Go to the end of the list.
 
354
         */
 
355
        for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
 
356
                ;
 
357
 
 
358
        if(!dptr) {
 
359
                DEBUG(0,("No old dptrs available to close oldest ?\n"));
 
360
                return;
 
361
        }
 
362
 
 
363
        /*
 
364
         * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
 
365
         * does not have expect_close set. If 'old' is false, close
 
366
         * one of the new dnum handles.
 
367
         */
 
368
 
 
369
        for(; dptr; dptr = dptr->prev) {
 
370
                if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
 
371
                        (!old && (dptr->dnum > 255))) {
 
372
                                dptr_close_internal(dptr);
 
373
                                return;
 
374
                }
 
375
        }
 
376
}
 
377
 
 
378
/****************************************************************************
 
379
 Create a new dir ptr. If the flag old_handle is true then we must allocate
 
380
 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
 
381
 one byte long. If old_handle is false we allocate from the range
 
382
 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
 
383
 a directory handle is never zero.
 
384
 wcard must not be zero.
 
385
****************************************************************************/
 
386
 
 
387
NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, bool expect_close,uint16 spid,
 
388
                const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
 
389
{
 
390
        struct dptr_struct *dptr = NULL;
 
391
        struct smb_Dir *dir_hnd;
 
392
        NTSTATUS status;
 
393
 
 
394
        DEBUG(5,("dptr_create dir=%s\n", path));
 
395
 
 
396
        if (!wcard) {
 
397
                return NT_STATUS_INVALID_PARAMETER;
 
398
        }
 
399
 
 
400
        status = check_name(conn,path);
 
401
        if (!NT_STATUS_IS_OK(status)) {
 
402
                return status;
 
403
        }
 
404
 
 
405
        dir_hnd = OpenDir(NULL, conn, path, wcard, attr);
 
406
        if (!dir_hnd) {
 
407
                return map_nt_error_from_unix(errno);
 
408
        }
 
409
 
 
410
        string_set(&conn->dirpath,path);
 
411
 
 
412
        if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
 
413
                dptr_idleoldest();
 
414
        }
 
415
 
 
416
        dptr = SMB_MALLOC_P(struct dptr_struct);
 
417
        if(!dptr) {
 
418
                DEBUG(0,("malloc fail in dptr_create.\n"));
 
419
                TALLOC_FREE(dir_hnd);
 
420
                return NT_STATUS_NO_MEMORY;
 
421
        }
 
422
 
 
423
        ZERO_STRUCTP(dptr);
 
424
 
 
425
        if(old_handle) {
 
426
 
 
427
                /*
 
428
                 * This is an old-style SMBsearch request. Ensure the
 
429
                 * value we return will fit in the range 1-255.
 
430
                 */
 
431
 
 
432
                dptr->dnum = bitmap_find(dptr_bmap, 0);
 
433
 
 
434
                if(dptr->dnum == -1 || dptr->dnum > 254) {
 
435
 
 
436
                        /*
 
437
                         * Try and close the oldest handle not marked for
 
438
                         * expect close in the hope that the client has
 
439
                         * finished with that one.
 
440
                         */
 
441
 
 
442
                        dptr_close_oldest(True);
 
443
 
 
444
                        /* Now try again... */
 
445
                        dptr->dnum = bitmap_find(dptr_bmap, 0);
 
446
                        if(dptr->dnum == -1 || dptr->dnum > 254) {
 
447
                                DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
 
448
                                SAFE_FREE(dptr);
 
449
                                TALLOC_FREE(dir_hnd);
 
450
                                return NT_STATUS_TOO_MANY_OPENED_FILES;
 
451
                        }
 
452
                }
 
453
        } else {
 
454
 
 
455
                /*
 
456
                 * This is a new-style trans2 request. Allocate from
 
457
                 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
 
458
                 */
 
459
 
 
460
                dptr->dnum = bitmap_find(dptr_bmap, 255);
 
461
 
 
462
                if(dptr->dnum == -1 || dptr->dnum < 255) {
 
463
 
 
464
                        /*
 
465
                         * Try and close the oldest handle close in the hope that
 
466
                         * the client has finished with that one. This will only
 
467
                         * happen in the case of the Win98 client bug where it leaks
 
468
                         * directory handles.
 
469
                         */
 
470
 
 
471
                        dptr_close_oldest(False);
 
472
 
 
473
                        /* Now try again... */
 
474
                        dptr->dnum = bitmap_find(dptr_bmap, 255);
 
475
 
 
476
                        if(dptr->dnum == -1 || dptr->dnum < 255) {
 
477
                                DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
 
478
                                SAFE_FREE(dptr);
 
479
                                TALLOC_FREE(dir_hnd);
 
480
                                return NT_STATUS_TOO_MANY_OPENED_FILES;
 
481
                        }
 
482
                }
 
483
        }
 
484
 
 
485
        bitmap_set(dptr_bmap, dptr->dnum);
 
486
 
 
487
        dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
 
488
 
 
489
        string_set(&dptr->path,path);
 
490
        dptr->conn = conn;
 
491
        dptr->dir_hnd = dir_hnd;
 
492
        dptr->spid = spid;
 
493
        dptr->expect_close = expect_close;
 
494
        dptr->wcard = SMB_STRDUP(wcard);
 
495
        if (!dptr->wcard) {
 
496
                bitmap_clear(dptr_bmap, dptr->dnum - 1);
 
497
                SAFE_FREE(dptr);
 
498
                TALLOC_FREE(dir_hnd);
 
499
                return NT_STATUS_NO_MEMORY;
 
500
        }
 
501
        if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
 
502
                dptr->has_wild = True;
 
503
        } else {
 
504
                dptr->has_wild = wcard_has_wild;
 
505
        }
 
506
 
 
507
        dptr->attr = attr;
 
508
 
 
509
        DLIST_ADD(dirptrs, dptr);
 
510
 
 
511
        DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
 
512
                dptr->dnum,path,expect_close));  
 
513
 
 
514
        *dptr_ret = dptr;
 
515
 
 
516
        return NT_STATUS_OK;
 
517
}
 
518
 
 
519
 
 
520
/****************************************************************************
 
521
 Wrapper functions to access the lower level directory handles.
 
522
****************************************************************************/
 
523
 
 
524
int dptr_CloseDir(struct dptr_struct *dptr)
 
525
{
 
526
        DLIST_REMOVE(dirptrs, dptr);
 
527
        TALLOC_FREE(dptr->dir_hnd);
 
528
        return 0;
 
529
}
 
530
 
 
531
void dptr_SeekDir(struct dptr_struct *dptr, long offset)
 
532
{
 
533
        SeekDir(dptr->dir_hnd, offset);
 
534
}
 
535
 
 
536
long dptr_TellDir(struct dptr_struct *dptr)
 
537
{
 
538
        return TellDir(dptr->dir_hnd);
 
539
}
 
540
 
 
541
bool dptr_has_wild(struct dptr_struct *dptr)
 
542
{
 
543
        return dptr->has_wild;
 
544
}
 
545
 
 
546
int dptr_dnum(struct dptr_struct *dptr)
 
547
{
 
548
        return dptr->dnum;
 
549
}
 
550
 
 
551
/****************************************************************************
 
552
 Return the next visible file name, skipping veto'd and invisible files.
 
553
****************************************************************************/
 
554
 
 
555
static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
 
556
                                           long *poffset, SMB_STRUCT_STAT *pst)
 
557
{
 
558
        /* Normal search for the next file. */
 
559
        const char *name;
 
560
        while ((name = ReadDirName(dptr->dir_hnd, poffset, pst)) != NULL) {
 
561
                if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
 
562
                        return name;
 
563
                }
 
564
        }
 
565
        return NULL;
 
566
}
 
567
 
 
568
/****************************************************************************
 
569
 Return the next visible file name, skipping veto'd and invisible files.
 
570
****************************************************************************/
 
571
 
 
572
char *dptr_ReadDirName(TALLOC_CTX *ctx,
 
573
                        struct dptr_struct *dptr,
 
574
                        long *poffset,
 
575
                        SMB_STRUCT_STAT *pst)
 
576
{
 
577
        char *name = NULL;
 
578
        char *pathreal = NULL;
 
579
        char *found_name = NULL;
 
580
        int ret;
 
581
        const char *name_temp = NULL;
 
582
 
 
583
        SET_STAT_INVALID(*pst);
 
584
 
 
585
        if (dptr->has_wild || dptr->did_stat) {
 
586
                name_temp = dptr_normal_ReadDirName(dptr, poffset, pst);
 
587
                name = talloc_strdup(ctx, name_temp);
 
588
                return name;
 
589
        }
 
590
 
 
591
        /* If poffset is -1 then we know we returned this name before and we
 
592
         * have no wildcards. We're at the end of the directory. */
 
593
        if (*poffset == END_OF_DIRECTORY_OFFSET) {
 
594
                return NULL;
 
595
        }
 
596
 
 
597
        /* We know the stored wcard contains no wildcard characters.
 
598
         * See if we can match with a stat call. If we can't, then set
 
599
         * did_stat to true to ensure we only do this once and keep
 
600
         * searching. */
 
601
 
 
602
        dptr->did_stat = true;
 
603
 
 
604
        /* First check if it should be visible. */
 
605
        if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard,
 
606
            pst, true))
 
607
        {
 
608
                /* This only returns false if the file was found, but
 
609
                   is explicitly not visible. Set us to end of
 
610
                   directory, but return NULL as we know we can't ever
 
611
                   find it. */
 
612
                goto ret;
 
613
        }
 
614
 
 
615
        if (VALID_STAT(*pst)) {
 
616
                name = talloc_strdup(ctx, dptr->wcard);
 
617
                goto ret;
 
618
        }
 
619
 
 
620
        pathreal = talloc_asprintf(ctx,
 
621
                                "%s/%s",
 
622
                                dptr->path,
 
623
                                dptr->wcard);
 
624
        if (!pathreal)
 
625
                return NULL;
 
626
 
 
627
        if (SMB_VFS_STAT(dptr->conn, pathreal, pst) == 0) {
 
628
                name = talloc_strdup(ctx, dptr->wcard);
 
629
                goto clean;
 
630
        } else {
 
631
                /* If we get any other error than ENOENT or ENOTDIR
 
632
                   then the file exists we just can't stat it. */
 
633
                if (errno != ENOENT && errno != ENOTDIR) {
 
634
                        name = talloc_strdup(ctx, dptr->wcard);
 
635
                        goto clean;
 
636
                }
 
637
        }
 
638
 
 
639
        /* Stat failed. We know this is authoratiative if we are
 
640
         * providing case sensitive semantics or the underlying
 
641
         * filesystem is case sensitive.
 
642
         */
 
643
        if (dptr->conn->case_sensitive ||
 
644
            !(dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
 
645
        {
 
646
                goto clean;
 
647
        }
 
648
 
 
649
        /*
 
650
         * Try case-insensitive stat if the fs has the ability. This avoids
 
651
         * scanning the whole directory.
 
652
         */
 
653
        ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn, dptr->path, dptr->wcard,
 
654
                                        ctx, &found_name);
 
655
        if (ret == 0) {
 
656
                name = found_name;
 
657
                goto clean;
 
658
        } else if (errno == ENOENT) {
 
659
                /* The case-insensitive lookup was authoritative. */
 
660
                goto clean;
 
661
        }
 
662
 
 
663
        TALLOC_FREE(pathreal);
 
664
 
 
665
        name_temp = dptr_normal_ReadDirName(dptr, poffset, pst);
 
666
        name = talloc_strdup(ctx, name_temp);
 
667
        return name;
 
668
 
 
669
clean:
 
670
        TALLOC_FREE(pathreal);
 
671
ret:
 
672
        /* We need to set the underlying dir_hnd offset to -1
 
673
         * also as this function is usually called with the
 
674
         * output from TellDir. */
 
675
        dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
 
676
        return name;
 
677
}
 
678
 
 
679
/****************************************************************************
 
680
 Search for a file by name, skipping veto'ed and not visible files.
 
681
****************************************************************************/
 
682
 
 
683
bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
 
684
{
 
685
        SET_STAT_INVALID(*pst);
 
686
 
 
687
        if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
 
688
                /* This is a singleton directory and we're already at the end. */
 
689
                *poffset = END_OF_DIRECTORY_OFFSET;
 
690
                return False;
 
691
        }
 
692
 
 
693
        return SearchDir(dptr->dir_hnd, name, poffset);
 
694
}
 
695
 
 
696
/****************************************************************************
 
697
 Add the name we're returning into the underlying cache.
 
698
****************************************************************************/
 
699
 
 
700
void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset)
 
701
{
 
702
        DirCacheAdd(dptr->dir_hnd, name, offset);
 
703
}
 
704
 
 
705
/****************************************************************************
 
706
 Initialize variables & state data at the beginning of all search SMB requests.
 
707
****************************************************************************/
 
708
void dptr_init_search_op(struct dptr_struct *dptr)
 
709
{
 
710
        SMB_VFS_INIT_SEARCH_OP(dptr->conn, dptr->dir_hnd->dir);
 
711
}
 
712
 
 
713
/****************************************************************************
 
714
 Fill the 5 byte server reserved dptr field.
 
715
****************************************************************************/
 
716
 
 
717
bool dptr_fill(char *buf1,unsigned int key)
 
718
{
 
719
        unsigned char *buf = (unsigned char *)buf1;
 
720
        struct dptr_struct *dptr = dptr_get(key, False);
 
721
        uint32 offset;
 
722
        if (!dptr) {
 
723
                DEBUG(1,("filling null dirptr %d\n",key));
 
724
                return(False);
 
725
        }
 
726
        offset = (uint32)TellDir(dptr->dir_hnd);
 
727
        DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
 
728
                (long)dptr->dir_hnd,(int)offset));
 
729
        buf[0] = key;
 
730
        SIVAL(buf,1,offset);
 
731
        return(True);
 
732
}
 
733
 
 
734
/****************************************************************************
 
735
 Fetch the dir ptr and seek it given the 5 byte server field.
 
736
****************************************************************************/
 
737
 
 
738
struct dptr_struct *dptr_fetch(char *buf,int *num)
 
739
{
 
740
        unsigned int key = *(unsigned char *)buf;
 
741
        struct dptr_struct *dptr = dptr_get(key, False);
 
742
        uint32 offset;
 
743
        long seekoff;
 
744
 
 
745
        if (!dptr) {
 
746
                DEBUG(3,("fetched null dirptr %d\n",key));
 
747
                return(NULL);
 
748
        }
 
749
        *num = key;
 
750
        offset = IVAL(buf,1);
 
751
        if (offset == (uint32)-1) {
 
752
                seekoff = END_OF_DIRECTORY_OFFSET;
 
753
        } else {
 
754
                seekoff = (long)offset;
 
755
        }
 
756
        SeekDir(dptr->dir_hnd,seekoff);
 
757
        DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
 
758
                key,dptr_path(key),(int)seekoff));
 
759
        return(dptr);
 
760
}
 
761
 
 
762
/****************************************************************************
 
763
 Fetch the dir ptr.
 
764
****************************************************************************/
 
765
 
 
766
struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
 
767
{
 
768
        struct dptr_struct *dptr  = dptr_get(dptr_num, False);
 
769
 
 
770
        if (!dptr) {
 
771
                DEBUG(3,("fetched null dirptr %d\n",dptr_num));
 
772
                return(NULL);
 
773
        }
 
774
        DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
 
775
        return(dptr);
 
776
}
 
777
 
 
778
/****************************************************************************
 
779
 Check that a file matches a particular file type.
 
780
****************************************************************************/
 
781
 
 
782
bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
 
783
{
 
784
        uint32 mask;
 
785
 
 
786
        /* Check the "may have" search bits. */
 
787
        if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
 
788
                return False;
 
789
 
 
790
        /* Check the "must have" bits, which are the may have bits shifted eight */
 
791
        /* If must have bit is set, the file/dir can not be returned in search unless the matching
 
792
                file attribute is set */
 
793
        mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
 
794
        if(mask) {
 
795
                if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask)   /* check if matching attribute present */
 
796
                        return True;
 
797
                else
 
798
                        return False;
 
799
        }
 
800
 
 
801
        return True;
 
802
}
 
803
 
 
804
static bool mangle_mask_match(connection_struct *conn,
 
805
                const char *filename,
 
806
                const char *mask)
 
807
{
 
808
        char mname[13];
 
809
 
 
810
        if (!name_to_8_3(filename,mname,False,conn->params)) {
 
811
                return False;
 
812
        }
 
813
        return mask_match_search(mname,mask,False);
 
814
}
 
815
 
 
816
/****************************************************************************
 
817
 Get an 8.3 directory entry.
 
818
****************************************************************************/
 
819
 
 
820
bool get_dir_entry(TALLOC_CTX *ctx,
 
821
                connection_struct *conn,
 
822
                const char *mask,
 
823
                uint32 dirtype,
 
824
                char **pp_fname_out,
 
825
                SMB_OFF_T *size,
 
826
                uint32 *mode,
 
827
                time_t *date,
 
828
                bool check_descend,
 
829
                bool ask_sharemode)
 
830
{
 
831
        char *dname = NULL;
 
832
        bool found = False;
 
833
        SMB_STRUCT_STAT sbuf;
 
834
        char *pathreal = NULL;
 
835
        char *filename = NULL;
 
836
        bool needslash;
 
837
 
 
838
        *pp_fname_out = NULL;
 
839
 
 
840
        needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
 
841
 
 
842
        if (!conn->dirptr) {
 
843
                return(False);
 
844
        }
 
845
 
 
846
        while (!found) {
 
847
                long curoff = dptr_TellDir(conn->dirptr);
 
848
                dname = dptr_ReadDirName(ctx, conn->dirptr, &curoff, &sbuf);
 
849
 
 
850
                DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
 
851
                        (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
 
852
 
 
853
                if (dname == NULL) {
 
854
                        return(False);
 
855
                }
 
856
 
 
857
                filename = dname;
 
858
 
 
859
                /* notice the special *.* handling. This appears to be the only difference
 
860
                        between the wildcard handling in this routine and in the trans2 routines.
 
861
                        see masktest for a demo
 
862
                */
 
863
                if ((strcmp(mask,"*.*") == 0) ||
 
864
                    mask_match_search(filename,mask,False) ||
 
865
                    mangle_mask_match(conn,filename,mask)) {
 
866
                        char mname[13];
 
867
 
 
868
                        if (!mangle_is_8_3(filename, False, conn->params)) {
 
869
                                if (!name_to_8_3(filename,mname,False,
 
870
                                           conn->params)) {
 
871
                                        TALLOC_FREE(filename);
 
872
                                        continue;
 
873
                                }
 
874
                                filename = talloc_strdup(ctx, mname);
 
875
                                if (!filename) {
 
876
                                        return False;
 
877
                                }
 
878
                        }
 
879
 
 
880
                        if (needslash) {
 
881
                                pathreal = talloc_asprintf(ctx,
 
882
                                                "%s/%s",
 
883
                                                conn->dirpath,
 
884
                                                dname);
 
885
                        } else {
 
886
                                pathreal = talloc_asprintf(ctx,
 
887
                                                "%s%s",
 
888
                                                conn->dirpath,
 
889
                                                dname);
 
890
                        }
 
891
                        if (!pathreal) {
 
892
                                TALLOC_FREE(filename);
 
893
                                return False;
 
894
                        }
 
895
 
 
896
                        if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
 
897
                                DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",
 
898
                                        pathreal, strerror(errno) ));
 
899
                                TALLOC_FREE(pathreal);
 
900
                                TALLOC_FREE(filename);
 
901
                                continue;
 
902
                        }
 
903
 
 
904
                        *mode = dos_mode(conn,pathreal,&sbuf);
 
905
 
 
906
                        if (!dir_check_ftype(conn,*mode,dirtype)) {
 
907
                                DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype));
 
908
                                TALLOC_FREE(pathreal);
 
909
                                TALLOC_FREE(filename);
 
910
                                continue;
 
911
                        }
 
912
 
 
913
                        *size = sbuf.st_size;
 
914
                        *date = sbuf.st_mtime;
 
915
 
 
916
                        if (ask_sharemode) {
 
917
                                struct timespec write_time_ts;
 
918
                                struct file_id fileid;
 
919
 
 
920
                                fileid = vfs_file_id_from_sbuf(conn, &sbuf);
 
921
                                get_file_infos(fileid, NULL, &write_time_ts);
 
922
                                if (!null_timespec(write_time_ts)) {
 
923
                                        *date = convert_timespec_to_time_t(write_time_ts);
 
924
                                }
 
925
                        }
 
926
 
 
927
                        DEBUG(3,("get_dir_entry mask=[%s] found %s "
 
928
                                "fname=%s (%s)\n",
 
929
                                mask,
 
930
                                pathreal,
 
931
                                dname,
 
932
                                filename));
 
933
 
 
934
                        found = True;
 
935
 
 
936
                        SMB_ASSERT(filename != NULL);
 
937
                        *pp_fname_out = filename;
 
938
 
 
939
                        DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff);
 
940
                        TALLOC_FREE(pathreal);
 
941
                }
 
942
 
 
943
                if (!found)
 
944
                        TALLOC_FREE(filename);
 
945
        }
 
946
 
 
947
        return(found);
 
948
}
 
949
 
 
950
/*******************************************************************
 
951
 Check to see if a user can read a file. This is only approximate,
 
952
 it is used as part of the "hide unreadable" option. Don't
 
953
 use it for anything security sensitive.
 
954
********************************************************************/
 
955
 
 
956
static bool user_can_read_file(connection_struct *conn, char *name)
 
957
{
 
958
        /*
 
959
         * If user is a member of the Admin group
 
960
         * we never hide files from them.
 
961
         */
 
962
 
 
963
        if (conn->admin_user) {
 
964
                return True;
 
965
        }
 
966
 
 
967
        return can_access_file_acl(conn, name, FILE_READ_DATA);
 
968
}
 
969
 
 
970
/*******************************************************************
 
971
 Check to see if a user can write a file (and only files, we do not
 
972
 check dirs on this one). This is only approximate,
 
973
 it is used as part of the "hide unwriteable" option. Don't
 
974
 use it for anything security sensitive.
 
975
********************************************************************/
 
976
 
 
977
static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
 
978
{
 
979
        /*
 
980
         * If user is a member of the Admin group
 
981
         * we never hide files from them.
 
982
         */
 
983
 
 
984
        if (conn->admin_user) {
 
985
                return True;
 
986
        }
 
987
 
 
988
        SMB_ASSERT(VALID_STAT(*pst));
 
989
 
 
990
        /* Pseudo-open the file */
 
991
 
 
992
        if(S_ISDIR(pst->st_mode)) {
 
993
                return True;
 
994
        }
 
995
 
 
996
        return can_write_to_file(conn, name, pst);
 
997
}
 
998
 
 
999
/*******************************************************************
 
1000
  Is a file a "special" type ?
 
1001
********************************************************************/
 
1002
 
 
1003
static bool file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
 
1004
{
 
1005
        /*
 
1006
         * If user is a member of the Admin group
 
1007
         * we never hide files from them.
 
1008
         */
 
1009
 
 
1010
        if (conn->admin_user)
 
1011
                return False;
 
1012
 
 
1013
        SMB_ASSERT(VALID_STAT(*pst));
 
1014
 
 
1015
        if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
 
1016
                return False;
 
1017
 
 
1018
        return True;
 
1019
}
 
1020
 
 
1021
/*******************************************************************
 
1022
 Should the file be seen by the client?
 
1023
 NOTE: A successful return is no guarantee of the file's existence.
 
1024
********************************************************************/
 
1025
 
 
1026
bool is_visible_file(connection_struct *conn, const char *dir_path,
 
1027
                     const char *name, SMB_STRUCT_STAT *pst, bool use_veto)
 
1028
{
 
1029
        bool hide_unreadable = lp_hideunreadable(SNUM(conn));
 
1030
        bool hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
 
1031
        bool hide_special = lp_hide_special_files(SNUM(conn));
 
1032
 
 
1033
        if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
 
1034
                return True; /* . and .. are always visible. */
 
1035
        }
 
1036
 
 
1037
        /* If it's a vetoed file, pretend it doesn't even exist */
 
1038
        if (use_veto && IS_VETO_PATH(conn, name)) {
 
1039
                DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
 
1040
                return False;
 
1041
        }
 
1042
 
 
1043
        if (hide_unreadable || hide_unwriteable || hide_special) {
 
1044
                char *entry = NULL;
 
1045
 
 
1046
                if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
 
1047
                        return False;
 
1048
                }
 
1049
 
 
1050
                /* If it's a dfs symlink, ignore _hide xxxx_ options */
 
1051
                if (lp_host_msdfs() &&
 
1052
                                lp_msdfs_root(SNUM(conn)) &&
 
1053
                                is_msdfs_link(conn, entry, NULL)) {
 
1054
                        SAFE_FREE(entry);
 
1055
                        return True;
 
1056
                }
 
1057
 
 
1058
                /* If the file name does not exist, there's no point checking
 
1059
                 * the configuration options. We succeed, on the basis that the
 
1060
                 * checks *might* have passed if the file was present.
 
1061
                 */
 
1062
                if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, entry, pst) != 0))
 
1063
                {
 
1064
                        SAFE_FREE(entry);
 
1065
                        return True;
 
1066
                }
 
1067
 
 
1068
                /* Honour _hide unreadable_ option */
 
1069
                if (hide_unreadable && !user_can_read_file(conn, entry)) {
 
1070
                        DEBUG(10,("is_visible_file: file %s is unreadable.\n",
 
1071
                                 entry ));
 
1072
                        SAFE_FREE(entry);
 
1073
                        return False;
 
1074
                }
 
1075
                /* Honour _hide unwriteable_ option */
 
1076
                if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
 
1077
                        DEBUG(10,("is_visible_file: file %s is unwritable.\n",
 
1078
                                 entry ));
 
1079
                        SAFE_FREE(entry);
 
1080
                        return False;
 
1081
                }
 
1082
                /* Honour _hide_special_ option */
 
1083
                if (hide_special && file_is_special(conn, entry, pst)) {
 
1084
                        DEBUG(10,("is_visible_file: file %s is special.\n",
 
1085
                                 entry ));
 
1086
                        SAFE_FREE(entry);
 
1087
                        return False;
 
1088
                }
 
1089
                SAFE_FREE(entry);
 
1090
        }
 
1091
        return True;
 
1092
}
 
1093
 
 
1094
static int smb_Dir_destructor(struct smb_Dir *dirp)
 
1095
{
 
1096
        if (dirp->dir) {
 
1097
                SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
 
1098
        }
 
1099
        dirhandles_open--;
 
1100
        return 0;
 
1101
}
 
1102
 
 
1103
/*******************************************************************
 
1104
 Open a directory.
 
1105
********************************************************************/
 
1106
 
 
1107
struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
 
1108
                        const char *name, const char *mask, uint32 attr)
 
1109
{
 
1110
        struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir);
 
1111
 
 
1112
        if (!dirp) {
 
1113
                return NULL;
 
1114
        }
 
1115
 
 
1116
        dirp->conn = conn;
 
1117
        dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
 
1118
 
 
1119
        dirp->dir_path = talloc_strdup(dirp, name);
 
1120
        if (!dirp->dir_path) {
 
1121
                errno = ENOMEM;
 
1122
                goto fail;
 
1123
        }
 
1124
 
 
1125
        dirhandles_open++;
 
1126
        talloc_set_destructor(dirp, smb_Dir_destructor);
 
1127
 
 
1128
        dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
 
1129
        if (!dirp->dir) {
 
1130
                DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path,
 
1131
                         strerror(errno) ));
 
1132
                goto fail;
 
1133
        }
 
1134
 
 
1135
        return dirp;
 
1136
 
 
1137
  fail:
 
1138
        TALLOC_FREE(dirp);
 
1139
        return NULL;
 
1140
}
 
1141
 
 
1142
/*******************************************************************
 
1143
 Read from a directory.
 
1144
 Return directory entry, current offset, and optional stat information.
 
1145
 Don't check for veto or invisible files.
 
1146
********************************************************************/
 
1147
 
 
1148
const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
 
1149
                        SMB_STRUCT_STAT *sbuf)
 
1150
{
 
1151
        const char *n;
 
1152
        connection_struct *conn = dirp->conn;
 
1153
 
 
1154
        /* Cheat to allow . and .. to be the first entries returned. */
 
1155
        if (((*poffset == START_OF_DIRECTORY_OFFSET) ||
 
1156
             (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2))
 
1157
        {
 
1158
                if (dirp->file_number == 0) {
 
1159
                        n = ".";
 
1160
                        *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
 
1161
                } else {
 
1162
                        *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
 
1163
                        n = "..";
 
1164
                }
 
1165
                dirp->file_number++;
 
1166
                return n;
 
1167
        } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
 
1168
                *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
 
1169
                return NULL;
 
1170
        } else {
 
1171
                /* A real offset, seek to it. */
 
1172
                SeekDir(dirp, *poffset);
 
1173
        }
 
1174
 
 
1175
        while ((n = vfs_readdirname(conn, dirp->dir, sbuf))) {
 
1176
                /* Ignore . and .. - we've already returned them. */
 
1177
                if (*n == '.') {
 
1178
                        if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
 
1179
                                continue;
 
1180
                        }
 
1181
                }
 
1182
                *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
 
1183
                dirp->file_number++;
 
1184
                return n;
 
1185
        }
 
1186
        *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
 
1187
        return NULL;
 
1188
}
 
1189
 
 
1190
/*******************************************************************
 
1191
 Rewind to the start.
 
1192
********************************************************************/
 
1193
 
 
1194
void RewindDir(struct smb_Dir *dirp, long *poffset)
 
1195
{
 
1196
        SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
 
1197
        dirp->file_number = 0;
 
1198
        dirp->offset = START_OF_DIRECTORY_OFFSET;
 
1199
        *poffset = START_OF_DIRECTORY_OFFSET;
 
1200
}
 
1201
 
 
1202
/*******************************************************************
 
1203
 Seek a dir.
 
1204
********************************************************************/
 
1205
 
 
1206
void SeekDir(struct smb_Dir *dirp, long offset)
 
1207
{
 
1208
        if (offset != dirp->offset) {
 
1209
                if (offset == START_OF_DIRECTORY_OFFSET) {
 
1210
                        RewindDir(dirp, &offset);
 
1211
                        /*
 
1212
                         * Ok we should really set the file number here
 
1213
                         * to 1 to enable ".." to be returned next. Trouble
 
1214
                         * is I'm worried about callers using SeekDir(dirp,0)
 
1215
                         * as equivalent to RewindDir(). So leave this alone
 
1216
                         * for now.
 
1217
                         */
 
1218
                } else if  (offset == DOT_DOT_DIRECTORY_OFFSET) {
 
1219
                        RewindDir(dirp, &offset);
 
1220
                        /*
 
1221
                         * Set the file number to 2 - we want to get the first
 
1222
                         * real file entry (the one we return after "..")
 
1223
                         * on the next ReadDir.
 
1224
                         */
 
1225
                        dirp->file_number = 2;
 
1226
                } else if (offset == END_OF_DIRECTORY_OFFSET) {
 
1227
                        ; /* Don't seek in this case. */
 
1228
                } else {
 
1229
                        SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
 
1230
                }
 
1231
                dirp->offset = offset;
 
1232
        }
 
1233
}
 
1234
 
 
1235
/*******************************************************************
 
1236
 Tell a dir position.
 
1237
********************************************************************/
 
1238
 
 
1239
long TellDir(struct smb_Dir *dirp)
 
1240
{
 
1241
        return(dirp->offset);
 
1242
}
 
1243
 
 
1244
/*******************************************************************
 
1245
 Add an entry into the dcache.
 
1246
********************************************************************/
 
1247
 
 
1248
void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
 
1249
{
 
1250
        struct name_cache_entry *e;
 
1251
 
 
1252
        if (dirp->name_cache_size == 0) {
 
1253
                return;
 
1254
        }
 
1255
 
 
1256
        if (dirp->name_cache == NULL) {
 
1257
                dirp->name_cache = TALLOC_ZERO_ARRAY(
 
1258
                        dirp, struct name_cache_entry, dirp->name_cache_size);
 
1259
 
 
1260
                if (dirp->name_cache == NULL) {
 
1261
                        return;
 
1262
                }
 
1263
        }
 
1264
 
 
1265
        dirp->name_cache_index = (dirp->name_cache_index+1) %
 
1266
                                        dirp->name_cache_size;
 
1267
        e = &dirp->name_cache[dirp->name_cache_index];
 
1268
        TALLOC_FREE(e->name);
 
1269
        e->name = talloc_strdup(dirp, name);
 
1270
        e->offset = offset;
 
1271
}
 
1272
 
 
1273
/*******************************************************************
 
1274
 Find an entry by name. Leave us at the offset after it.
 
1275
 Don't check for veto or invisible files.
 
1276
********************************************************************/
 
1277
 
 
1278
bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
 
1279
{
 
1280
        int i;
 
1281
        const char *entry;
 
1282
        connection_struct *conn = dirp->conn;
 
1283
 
 
1284
        /* Search back in the name cache. */
 
1285
        if (dirp->name_cache_size && dirp->name_cache) {
 
1286
                for (i = dirp->name_cache_index; i >= 0; i--) {
 
1287
                        struct name_cache_entry *e = &dirp->name_cache[i];
 
1288
                        if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
 
1289
                                *poffset = e->offset;
 
1290
                                SeekDir(dirp, e->offset);
 
1291
                                return True;
 
1292
                        }
 
1293
                }
 
1294
                for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
 
1295
                        struct name_cache_entry *e = &dirp->name_cache[i];
 
1296
                        if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
 
1297
                                *poffset = e->offset;
 
1298
                                SeekDir(dirp, e->offset);
 
1299
                                return True;
 
1300
                        }
 
1301
                }
 
1302
        }
 
1303
 
 
1304
        /* Not found in the name cache. Rewind directory and start from scratch. */
 
1305
        SMB_VFS_REWINDDIR(conn, dirp->dir);
 
1306
        dirp->file_number = 0;
 
1307
        *poffset = START_OF_DIRECTORY_OFFSET;
 
1308
        while ((entry = ReadDirName(dirp, poffset, NULL))) {
 
1309
                if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
 
1310
                        return True;
 
1311
                }
 
1312
        }
 
1313
        return False;
 
1314
}
 
1315
 
 
1316
/*****************************************************************
 
1317
 Is this directory empty ?
 
1318
*****************************************************************/
 
1319
 
 
1320
NTSTATUS can_delete_directory(struct connection_struct *conn,
 
1321
                                const char *dirname)
 
1322
{
 
1323
        NTSTATUS status = NT_STATUS_OK;
 
1324
        long dirpos = 0;
 
1325
        const char *dname;
 
1326
        SMB_STRUCT_STAT st;
 
1327
        struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, dirname,
 
1328
                                          NULL, 0);
 
1329
 
 
1330
        if (!dir_hnd) {
 
1331
                return map_nt_error_from_unix(errno);
 
1332
        }
 
1333
 
 
1334
        while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
 
1335
                /* Quick check for "." and ".." */
 
1336
                if (dname[0] == '.') {
 
1337
                        if (!dname[1] || (dname[1] == '.' && !dname[2])) {
 
1338
                                continue;
 
1339
                        }
 
1340
                }
 
1341
 
 
1342
                if (!is_visible_file(conn, dirname, dname, &st, True)) {
 
1343
                        continue;
 
1344
                }
 
1345
 
 
1346
                DEBUG(10,("can_delete_directory: got name %s - can't delete\n",
 
1347
                         dname ));
 
1348
                status = NT_STATUS_DIRECTORY_NOT_EMPTY;
 
1349
                break;
 
1350
        }
 
1351
        TALLOC_FREE(dir_hnd);
 
1352
 
 
1353
        return status;
 
1354
}