1/* 2 Unix SMB/CIFS implementation. 3 Directory handling routines 4 Copyright (C) Andrew Tridgell 1992-1998 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20 21#include "includes.h" 22 23/* 24 This module implements directory related functions for Samba. 25*/ 26 27/* Make directory handle internals available. */ 28 29#define NAME_CACHE_SIZE 100 30 31struct name_cache_entry { 32 char *name; 33 long offset; 34}; 35 36struct smb_Dir { 37 connection_struct *conn; 38 DIR *dir; 39 long offset; 40 char *dir_path; 41 struct name_cache_entry *name_cache; 42 unsigned int name_cache_index; 43}; 44 45struct dptr_struct { 46 struct dptr_struct *next, *prev; 47 int dnum; 48 uint16 spid; 49 struct connection_struct *conn; 50 struct smb_Dir *dir_hnd; 51 BOOL expect_close; 52 char *wcard; 53 uint16 attr; 54 char *path; 55 BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */ 56}; 57 58static struct bitmap *dptr_bmap; 59static struct dptr_struct *dirptrs; 60static int dirhandles_open = 0; 61 62#define INVALID_DPTR_KEY (-3) 63 64/**************************************************************************** 65 Initialise the dir bitmap. 66****************************************************************************/ 67 68void init_dptrs(void) 69{ 70 static BOOL dptrs_init=False; 71 72 if (dptrs_init) 73 return; 74 75 dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES); 76 77 if (!dptr_bmap) 78 exit_server("out of memory in init_dptrs"); 79 80 dptrs_init = True; 81} 82 83/**************************************************************************** 84 Idle a dptr - the directory is closed but the control info is kept. 85****************************************************************************/ 86 87static void dptr_idle(struct dptr_struct *dptr) 88{ 89 if (dptr->dir_hnd) { 90 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum)); 91 CloseDir(dptr->dir_hnd); 92 dptr->dir_hnd = NULL; 93 } 94} 95 96/**************************************************************************** 97 Idle the oldest dptr. 98****************************************************************************/ 99 100static void dptr_idleoldest(void) 101{ 102 struct dptr_struct *dptr; 103 104 /* 105 * Go to the end of the list. 106 */ 107 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next) 108 ; 109 110 if(!dptr) { 111 DEBUG(0,("No dptrs available to idle ?\n")); 112 return; 113 } 114 115 /* 116 * Idle the oldest pointer. 117 */ 118 119 for(; dptr; dptr = dptr->prev) { 120 if (dptr->dir_hnd) { 121 dptr_idle(dptr); 122 return; 123 } 124 } 125} 126 127/**************************************************************************** 128 Get the struct dptr_struct for a dir index. 129****************************************************************************/ 130 131static struct dptr_struct *dptr_get(int key, BOOL forclose) 132{ 133 struct dptr_struct *dptr; 134 135 for(dptr = dirptrs; dptr; dptr = dptr->next) { 136 if(dptr->dnum == key) { 137 if (!forclose && !dptr->dir_hnd) { 138 if (dirhandles_open >= MAX_OPEN_DIRECTORIES) 139 dptr_idleoldest(); 140 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key)); 141 if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path))) { 142 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path, 143 strerror(errno))); 144 return False; 145 } 146 } 147 DLIST_PROMOTE(dirptrs,dptr); 148 return dptr; 149 } 150 } 151 return(NULL); 152} 153 154/**************************************************************************** 155 Get the dir path for a dir index. 156****************************************************************************/ 157 158char *dptr_path(int key) 159{ 160 struct dptr_struct *dptr = dptr_get(key, False); 161 if (dptr) 162 return(dptr->path); 163 return(NULL); 164} 165 166/**************************************************************************** 167 Get the dir wcard for a dir index. 168****************************************************************************/ 169 170char *dptr_wcard(int key) 171{ 172 struct dptr_struct *dptr = dptr_get(key, False); 173 if (dptr) 174 return(dptr->wcard); 175 return(NULL); 176} 177 178/**************************************************************************** 179 Get the dir attrib for a dir index. 180****************************************************************************/ 181 182uint16 dptr_attr(int key) 183{ 184 struct dptr_struct *dptr = dptr_get(key, False); 185 if (dptr) 186 return(dptr->attr); 187 return(0); 188} 189 190/**************************************************************************** 191 Set the dir wcard for a dir index. 192 Returns 0 on ok, 1 on fail. 193****************************************************************************/ 194 195BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr) 196{ 197 struct dptr_struct *dptr = dptr_get(key, False); 198 199 if (dptr) { 200 dptr->attr = attr; 201 dptr->wcard = SMB_STRDUP(wcard); 202 if (!dptr->wcard) 203 return False; 204 if (wcard[0] == '.' && wcard[1] == 0) { 205 dptr->has_wild = True; 206 } else { 207 dptr->has_wild = ms_has_wild(wcard); 208 } 209 return True; 210 } 211 return False; 212} 213 214/**************************************************************************** 215 Close a dptr (internal func). 216****************************************************************************/ 217 218static void dptr_close_internal(struct dptr_struct *dptr) 219{ 220 DEBUG(4,("closing dptr key %d\n",dptr->dnum)); 221 222 DLIST_REMOVE(dirptrs, dptr); 223 224 /* 225 * Free the dnum in the bitmap. Remember the dnum value is always 226 * biased by one with respect to the bitmap. 227 */ 228 229 if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) { 230 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n", 231 dptr->dnum )); 232 } 233 234 bitmap_clear(dptr_bmap, dptr->dnum - 1); 235 236 if (dptr->dir_hnd) { 237 CloseDir(dptr->dir_hnd); 238 } 239 240 /* Lanman 2 specific code */ 241 SAFE_FREE(dptr->wcard); 242 string_set(&dptr->path,""); 243 SAFE_FREE(dptr); 244} 245 246/**************************************************************************** 247 Close a dptr given a key. 248****************************************************************************/ 249 250void dptr_close(int *key) 251{ 252 struct dptr_struct *dptr; 253 254 if(*key == INVALID_DPTR_KEY) 255 return; 256 257 /* OS/2 seems to use -1 to indicate "close all directories" */ 258 if (*key == -1) { 259 struct dptr_struct *next; 260 for(dptr = dirptrs; dptr; dptr = next) { 261 next = dptr->next; 262 dptr_close_internal(dptr); 263 } 264 *key = INVALID_DPTR_KEY; 265 return; 266 } 267 268 dptr = dptr_get(*key, True); 269 270 if (!dptr) { 271 DEBUG(0,("Invalid key %d given to dptr_close\n", *key)); 272 return; 273 } 274 275 dptr_close_internal(dptr); 276 277 *key = INVALID_DPTR_KEY; 278} 279 280/**************************************************************************** 281 Close all dptrs for a cnum. 282****************************************************************************/ 283 284void dptr_closecnum(connection_struct *conn) 285{ 286 struct dptr_struct *dptr, *next; 287 for(dptr = dirptrs; dptr; dptr = next) { 288 next = dptr->next; 289 if (dptr->conn == conn) 290 dptr_close_internal(dptr); 291 } 292} 293 294/**************************************************************************** 295 Idle all dptrs for a cnum. 296****************************************************************************/ 297 298void dptr_idlecnum(connection_struct *conn) 299{ 300 struct dptr_struct *dptr; 301 for(dptr = dirptrs; dptr; dptr = dptr->next) { 302 if (dptr->conn == conn && dptr->dir_hnd) 303 dptr_idle(dptr); 304 } 305} 306 307/**************************************************************************** 308 Close a dptr that matches a given path, only if it matches the spid also. 309****************************************************************************/ 310 311void dptr_closepath(char *path,uint16 spid) 312{ 313 struct dptr_struct *dptr, *next; 314 for(dptr = dirptrs; dptr; dptr = next) { 315 next = dptr->next; 316 if (spid == dptr->spid && strequal(dptr->path,path)) 317 dptr_close_internal(dptr); 318 } 319} 320 321/**************************************************************************** 322 Try and close the oldest handle not marked for 323 expect close in the hope that the client has 324 finished with that one. 325****************************************************************************/ 326 327static void dptr_close_oldest(BOOL old) 328{ 329 struct dptr_struct *dptr; 330 331 /* 332 * Go to the end of the list. 333 */ 334 for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next) 335 ; 336 337 if(!dptr) { 338 DEBUG(0,("No old dptrs available to close oldest ?\n")); 339 return; 340 } 341 342 /* 343 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that 344 * does not have expect_close set. If 'old' is false, close 345 * one of the new dnum handles. 346 */ 347 348 for(; dptr; dptr = dptr->prev) { 349 if ((old && (dptr->dnum < 256) && !dptr->expect_close) || 350 (!old && (dptr->dnum > 255))) { 351 dptr_close_internal(dptr); 352 return; 353 } 354 } 355} 356 357/**************************************************************************** 358 Create a new dir ptr. If the flag old_handle is true then we must allocate 359 from the bitmap range 0 - 255 as old SMBsearch directory handles are only 360 one byte long. If old_handle is false we allocate from the range 361 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure 362 a directory handle is never zero. 363****************************************************************************/ 364 365int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid) 366{ 367 struct dptr_struct *dptr = NULL; 368 struct smb_Dir *dir_hnd; 369 const char *dir2; 370 371 DEBUG(5,("dptr_create dir=%s\n", path)); 372 373 if (!check_name(path,conn)) 374 return(-2); /* Code to say use a unix error return code. */ 375 376 /* use a const pointer from here on */ 377 dir2 = path; 378 if (!*dir2) 379 dir2 = "."; 380 381 dir_hnd = OpenDir(conn, dir2); 382 if (!dir_hnd) { 383 return (-2); 384 } 385 386 string_set(&conn->dirpath,dir2); 387 388 if (dirhandles_open >= MAX_OPEN_DIRECTORIES) 389 dptr_idleoldest(); 390 391 dptr = SMB_MALLOC_P(struct dptr_struct); 392 if(!dptr) { 393 DEBUG(0,("malloc fail in dptr_create.\n")); 394 CloseDir(dir_hnd); 395 return -1; 396 } 397 398 ZERO_STRUCTP(dptr); 399 400 if(old_handle) { 401 402 /* 403 * This is an old-style SMBsearch request. Ensure the 404 * value we return will fit in the range 1-255. 405 */ 406 407 dptr->dnum = bitmap_find(dptr_bmap, 0); 408 409 if(dptr->dnum == -1 || dptr->dnum > 254) { 410 411 /* 412 * Try and close the oldest handle not marked for 413 * expect close in the hope that the client has 414 * finished with that one. 415 */ 416 417 dptr_close_oldest(True); 418 419 /* Now try again... */ 420 dptr->dnum = bitmap_find(dptr_bmap, 0); 421 if(dptr->dnum == -1 || dptr->dnum > 254) { 422 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum)); 423 SAFE_FREE(dptr); 424 CloseDir(dir_hnd); 425 return -1; 426 } 427 } 428 } else { 429 430 /* 431 * This is a new-style trans2 request. Allocate from 432 * a range that will return 256 - MAX_DIRECTORY_HANDLES. 433 */ 434 435 dptr->dnum = bitmap_find(dptr_bmap, 255); 436 437 if(dptr->dnum == -1 || dptr->dnum < 255) { 438 439 /* 440 * Try and close the oldest handle close in the hope that 441 * the client has finished with that one. This will only 442 * happen in the case of the Win98 client bug where it leaks 443 * directory handles. 444 */ 445 446 dptr_close_oldest(False); 447 448 /* Now try again... */ 449 dptr->dnum = bitmap_find(dptr_bmap, 255); 450 451 if(dptr->dnum == -1 || dptr->dnum < 255) { 452 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum)); 453 SAFE_FREE(dptr); 454 CloseDir(dir_hnd); 455 return -1; 456 } 457 } 458 } 459 460 bitmap_set(dptr_bmap, dptr->dnum); 461 462 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */ 463 464 string_set(&dptr->path,dir2); 465 dptr->conn = conn; 466 dptr->dir_hnd = dir_hnd; 467 dptr->spid = spid; 468 dptr->expect_close = expect_close; 469 dptr->wcard = NULL; /* Only used in lanman2 searches */ 470 dptr->attr = 0; /* Only used in lanman2 searches */ 471 dptr->has_wild = True; /* Only used in lanman2 searches */ 472 473 DLIST_ADD(dirptrs, dptr); 474 475 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n", 476 dptr->dnum,path,expect_close)); 477 478 conn->dirptr = dptr; 479 480 return(dptr->dnum); 481} 482 483 484/**************************************************************************** 485 Wrapper functions to access the lower level directory handles. 486****************************************************************************/ 487 488int dptr_CloseDir(struct dptr_struct *dptr) 489{ 490 return CloseDir(dptr->dir_hnd); 491} 492 493void dptr_SeekDir(struct dptr_struct *dptr, long offset) 494{ 495 SeekDir(dptr->dir_hnd, offset); 496} 497 498long dptr_TellDir(struct dptr_struct *dptr) 499{ 500 return TellDir(dptr->dir_hnd); 501} 502 503/**************************************************************************** 504 Return the next visible file name, skipping veto'd and invisible files. 505****************************************************************************/ 506 507static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst) 508{ 509 /* Normal search for the next file. */ 510 const char *name; 511 while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) { 512 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) { 513 return name; 514 } 515 } 516 return NULL; 517} 518 519/**************************************************************************** 520 Return the next visible file name, skipping veto'd and invisible files. 521****************************************************************************/ 522 523const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst) 524{ 525 pstring pathreal; 526 527 ZERO_STRUCTP(pst); 528 529 if (dptr->has_wild) { 530 return dptr_normal_ReadDirName(dptr, poffset, pst); 531 } 532 533 /* If poffset is -1 then we know we returned this name before and we have 534 no wildcards. We're at the end of the directory. */ 535 if (*poffset == -1) { 536 return NULL; 537 } 538 539 /* We know the stored wcard contains no wildcard characters. See if we can match 540 with a stat call. If we can't, then set has_wild to true to 541 prevent us from doing this on every call. */ 542 543 /* First check if it should be visible. */ 544 if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) { 545 dptr->has_wild = True; 546 return dptr_normal_ReadDirName(dptr, poffset, pst); 547 } 548 549 if (VALID_STAT(*pst)) { 550 /* We need to set the underlying dir_hdn offset to -1 also as 551 this function is usually called with the output from TellDir. */ 552 dptr->dir_hnd->offset = *poffset = -1; 553 return dptr->wcard; 554 } 555 556 pstrcpy(pathreal,dptr->path); 557 pstrcat(pathreal,"/"); 558 pstrcat(pathreal,dptr->wcard); 559 560 if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) { 561 /* We need to set the underlying dir_hdn offset to -1 also as 562 this function is usually called with the output from TellDir. */ 563 dptr->dir_hnd->offset = *poffset = -1; 564 return dptr->wcard; 565 } else { 566 /* If we get any other error than ENOENT or ENOTDIR 567 then the file exists we just can't stat it. */ 568 if (errno != ENOENT && errno != ENOTDIR) { 569 /* We need to set the underlying dir_hdn offset to -1 also as 570 this function is usually called with the output from TellDir. */ 571 dptr->dir_hnd->offset = *poffset = -1; 572 return dptr->wcard; 573 } 574 } 575 576 dptr->has_wild = True; 577 578 /* In case sensitive mode we don't search - we know if it doesn't exist 579 with a stat we will fail. */ 580 581 if (dptr->conn->case_sensitive) { 582 /* We need to set the underlying dir_hdn offset to -1 also as 583 this function is usually called with the output from TellDir. */ 584 dptr->dir_hnd->offset = *poffset = -1; 585 return NULL; 586 } else { 587 return dptr_normal_ReadDirName(dptr, poffset, pst); 588 } 589} 590 591/**************************************************************************** 592 Search for a file by name, skipping veto'ed and not visible files. 593****************************************************************************/ 594 595BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst) 596{ 597 ZERO_STRUCTP(pst); 598 599 if (!dptr->has_wild && (dptr->dir_hnd->offset == -1)) { 600 /* This is a singleton directory and we're already at the end. */ 601 *poffset = -1; 602 return False; 603 } 604 605 while (SearchDir(dptr->dir_hnd, name, poffset) == True) { 606 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) { 607 return True; 608 } 609 } 610 return False; 611} 612 613/**************************************************************************** 614 Fill the 5 byte server reserved dptr field. 615****************************************************************************/ 616 617BOOL dptr_fill(char *buf1,unsigned int key) 618{ 619 unsigned char *buf = (unsigned char *)buf1; 620 struct dptr_struct *dptr = dptr_get(key, False); 621 uint32 offset; 622 if (!dptr) { 623 DEBUG(1,("filling null dirptr %d\n",key)); 624 return(False); 625 } 626 offset = TellDir(dptr->dir_hnd); 627 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key, 628 (long)dptr->dir_hnd,(int)offset)); 629 buf[0] = key; 630 SIVAL(buf,1,offset | DPTR_MASK); 631 return(True); 632} 633 634/**************************************************************************** 635 Fetch the dir ptr and seek it given the 5 byte server field. 636****************************************************************************/ 637 638struct dptr_struct *dptr_fetch(char *buf,int *num) 639{ 640 unsigned int key = *(unsigned char *)buf; 641 struct dptr_struct *dptr = dptr_get(key, False); 642 uint32 offset; 643 644 if (!dptr) { 645 DEBUG(3,("fetched null dirptr %d\n",key)); 646 return(NULL); 647 } 648 *num = key; 649 offset = IVAL(buf,1)&~DPTR_MASK; 650 SeekDir(dptr->dir_hnd,(long)offset); 651 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n", 652 key,dptr_path(key),offset)); 653 return(dptr); 654} 655 656/**************************************************************************** 657 Fetch the dir ptr. 658****************************************************************************/ 659 660struct dptr_struct *dptr_fetch_lanman2(int dptr_num) 661{ 662 struct dptr_struct *dptr = dptr_get(dptr_num, False); 663 664 if (!dptr) { 665 DEBUG(3,("fetched null dirptr %d\n",dptr_num)); 666 return(NULL); 667 } 668 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num))); 669 return(dptr); 670} 671 672/**************************************************************************** 673 Check a filetype for being valid. 674****************************************************************************/ 675 676BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype) 677{ 678 int mask; 679 680 /* Check the "may have" search bits. */ 681 if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) 682 return False; 683 684 /* Check the "must have" bits, which are the may have bits shifted eight */ 685 /* If must have bit is set, the file/dir can not be returned in search unless the matching 686 file attribute is set */ 687 mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */ 688 if(mask) { 689 if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask) /* check if matching attribute present */ 690 return True; 691 else 692 return False; 693 } 694 695 return True; 696} 697 698static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask) 699{ 700 mangle_map(filename,True,False,SNUM(conn)); 701 return mask_match(filename,mask,False); 702} 703 704/**************************************************************************** 705 Get an 8.3 directory entry. 706****************************************************************************/ 707 708BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname, 709 SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend) 710{ 711 const char *dname; 712 BOOL found = False; 713 SMB_STRUCT_STAT sbuf; 714 pstring path; 715 pstring pathreal; 716 BOOL isrootdir; 717 pstring filename; 718 BOOL needslash; 719 720 *path = *pathreal = *filename = 0; 721 722 isrootdir = (strequal(conn->dirpath,"./") || 723 strequal(conn->dirpath,".") || 724 strequal(conn->dirpath,"/")); 725 726 needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); 727 728 if (!conn->dirptr) 729 return(False); 730 731 while (!found) { 732 long curoff = dptr_TellDir(conn->dirptr); 733 dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf); 734 735 DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n", 736 (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd))); 737 738 if (dname == NULL) 739 return(False); 740 741 pstrcpy(filename,dname); 742 743 /* notice the special *.* handling. This appears to be the only difference 744 between the wildcard handling in this routine and in the trans2 routines. 745 see masktest for a demo 746 */ 747 if ((strcmp(mask,"*.*") == 0) || 748 mask_match(filename,mask,False) || 749 mangle_mask_match(conn,filename,mask)) { 750 if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) 751 continue; 752 753 if (!mangle_is_8_3(filename, False)) 754 mangle_map(filename,True,False,SNUM(conn)); 755 756 pstrcpy(fname,filename); 757 *path = 0; 758 pstrcpy(path,conn->dirpath); 759 if(needslash) 760 pstrcat(path,"/"); 761 pstrcpy(pathreal,path); 762 pstrcat(path,fname); 763 pstrcat(pathreal,dname); 764 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) { 765 DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); 766 continue; 767 } 768 769 *mode = dos_mode(conn,pathreal,&sbuf); 770 771 if (!dir_check_ftype(conn,*mode,dirtype)) { 772 DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); 773 continue; 774 } 775 776 *size = sbuf.st_size; 777 *date = sbuf.st_mtime; 778 779 DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname)); 780 781 found = True; 782 } 783 } 784 785 return(found); 786} 787 788/******************************************************************* 789 Check to see if a user can read a file. This is only approximate, 790 it is used as part of the "hide unreadable" option. Don't 791 use it for anything security sensitive. 792********************************************************************/ 793 794static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) 795{ 796 extern struct current_user current_user; 797 SEC_DESC *psd = NULL; 798 size_t sd_size; 799 files_struct *fsp; 800 int smb_action; 801 NTSTATUS status; 802 uint32 access_granted; 803 804 /* 805 * If user is a member of the Admin group 806 * we never hide files from them. 807 */ 808 809 if (conn->admin_user) 810 return True; 811 812 /* If we can't stat it does not show it */ 813 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) 814 return False; 815 816 /* Pseudo-open the file (note - no fd's created). */ 817 818 if(S_ISDIR(pst->st_mode)) 819 fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 820 &smb_action); 821 else 822 fsp = open_file_stat(conn, name, pst); 823 824 if (!fsp) 825 return False; 826 827 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ 828 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, 829 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); 830 close_file(fsp, True); 831 832 /* No access if SD get failed. */ 833 if (!sd_size) 834 return False; 835 836 return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA, 837 &access_granted, &status); 838} 839 840/******************************************************************* 841 Check to see if a user can write a file (and only files, we do not 842 check dirs on this one). This is only approximate, 843 it is used as part of the "hide unwriteable" option. Don't 844 use it for anything security sensitive. 845********************************************************************/ 846 847static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) 848{ 849 extern struct current_user current_user; 850 SEC_DESC *psd = NULL; 851 size_t sd_size; 852 files_struct *fsp; 853 int smb_action; 854 int access_mode; 855 NTSTATUS status; 856 uint32 access_granted; 857 858 /* 859 * If user is a member of the Admin group 860 * we never hide files from them. 861 */ 862 863 if (conn->admin_user) 864 return True; 865 866 /* If we can't stat it does not show it */ 867 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) 868 return False; 869 870 /* Pseudo-open the file (note - no fd's created). */ 871 872 if(S_ISDIR(pst->st_mode)) 873 return True; 874 else 875 fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE), 876 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, 877 &access_mode, &smb_action); 878 879 if (!fsp) 880 return False; 881 882 /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ 883 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, 884 (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); 885 close_file(fsp, False); 886 887 /* No access if SD get failed. */ 888 if (!sd_size) 889 return False; 890 891 return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA, 892 &access_granted, &status); 893} 894 895/******************************************************************* 896 Is a file a "special" type ? 897********************************************************************/ 898 899static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) 900{ 901 /* 902 * If user is a member of the Admin group 903 * we never hide files from them. 904 */ 905 906 if (conn->admin_user) 907 return False; 908 909 /* If we can't stat it does not show it */ 910 if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) 911 return True; 912 913 if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode)) 914 return False; 915 916 return True; 917} 918 919/******************************************************************* 920 Should the file be seen by the client ? 921********************************************************************/ 922 923BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto) 924{ 925 BOOL hide_unreadable = lp_hideunreadable(SNUM(conn)); 926 BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn)); 927 BOOL hide_special = lp_hide_special_files(SNUM(conn)); 928 929 ZERO_STRUCTP(pst); 930 931 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) { 932 return True; /* . and .. are always visible. */ 933 } 934 935 /* Foxconn added start pling 01/30/2012 */ 936 /* Only allow "admin" user to see admin paths */ 937 if (1) { 938 pstring full_path; 939 getcwd(full_path, sizeof(full_path)); 940 pstrcat(full_path, "/"); 941 if (strcmp(dir_path, "./")) { 942 pstrcat(full_path, dir_path); 943 pstrcat(full_path, "/"); 944 } 945 pstrcat(full_path, name); 946 947 /* "full_path" is in format "/tmp/mnt/usbx/partx/xxx", 948 * skip the leading /tmp/mnt/ */ 949 if (IS_ADMIN_PATH(conn, &full_path[9])) { 950 if (strcmp(conn->user, "admin") == 0) 951 return True; 952 else 953 return False; 954 } 955 } 956 /* Foxconn added end pling 01/30/2012 */ 957 958 /* If it's a vetoed file, pretend it doesn't even exist */ 959 if (use_veto && IS_VETO_PATH(conn, name)) { 960 return False; 961 } 962 963 if (hide_unreadable || hide_unwriteable || hide_special) { 964 char *entry = NULL; 965 966 if (asprintf(&entry, "%s/%s", dir_path, name) == -1) { 967 return False; 968 } 969 /* Honour _hide unreadable_ option */ 970 if (hide_unreadable && !user_can_read_file(conn, entry, pst)) { 971 SAFE_FREE(entry); 972 return False; 973 } 974 /* Honour _hide unwriteable_ option */ 975 if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) { 976 SAFE_FREE(entry); 977 return False; 978 } 979 /* Honour _hide_special_ option */ 980 if (hide_special && !file_is_special(conn, entry, pst)) { 981 SAFE_FREE(entry); 982 return False; 983 } 984 SAFE_FREE(entry); 985 } 986 return True; 987} 988 989/******************************************************************* 990 Open a directory. 991********************************************************************/ 992 993struct smb_Dir *OpenDir(connection_struct *conn, const char *name) 994{ 995 struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir); 996 if (!dirp) { 997 return NULL; 998 } 999 ZERO_STRUCTP(dirp); 1000 1001 dirp->conn = conn; 1002 1003 dirp->dir_path = SMB_STRDUP(name); 1004 if (!dirp->dir_path) { 1005 goto fail; 1006 } 1007 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path); 1008 if (!dirp->dir) { 1009 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) )); 1010 goto fail; 1011 } 1012 1013 dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE); 1014 if (!dirp->name_cache) { 1015 goto fail; 1016 } 1017 1018 dirhandles_open++; 1019 return dirp; 1020 1021 fail: 1022 1023 if (dirp) { 1024 if (dirp->dir) { 1025 SMB_VFS_CLOSEDIR(conn,dirp->dir); 1026 } 1027 SAFE_FREE(dirp->dir_path); 1028 SAFE_FREE(dirp->name_cache); 1029 SAFE_FREE(dirp); 1030 } 1031 return NULL; 1032} 1033 1034 1035/******************************************************************* 1036 Close a directory. 1037********************************************************************/ 1038 1039int CloseDir(struct smb_Dir *dirp) 1040{ 1041 int i, ret = 0; 1042 1043 if (dirp->dir) { 1044 ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir); 1045 } 1046 SAFE_FREE(dirp->dir_path); 1047 if (dirp->name_cache) { 1048 for (i = 0; i < NAME_CACHE_SIZE; i++) { 1049 SAFE_FREE(dirp->name_cache[i].name); 1050 } 1051 } 1052 SAFE_FREE(dirp->name_cache); 1053 SAFE_FREE(dirp); 1054 dirhandles_open--; 1055 return ret; 1056} 1057 1058/******************************************************************* 1059 Read from a directory. Also return current offset. 1060 Don't check for veto or invisible files. 1061********************************************************************/ 1062 1063const char *ReadDirName(struct smb_Dir *dirp, long *poffset) 1064{ 1065 const char *n; 1066 connection_struct *conn = dirp->conn; 1067 1068 SeekDir(dirp, *poffset); 1069 while ((n = vfs_readdirname(conn, dirp->dir))) { 1070 struct name_cache_entry *e; 1071 dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir); 1072 if (dirp->offset == -1) { 1073 return NULL; 1074 } 1075 dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE; 1076 1077 e = &dirp->name_cache[dirp->name_cache_index]; 1078 SAFE_FREE(e->name); 1079 e->name = SMB_STRDUP(n); 1080 *poffset = e->offset= dirp->offset; 1081 return e->name; 1082 } 1083 dirp->offset = -1; 1084 return NULL; 1085} 1086 1087/******************************************************************* 1088 Seek a dir. 1089********************************************************************/ 1090 1091void SeekDir(struct smb_Dir *dirp, long offset) 1092{ 1093 if (offset != dirp->offset) { 1094 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset); 1095 dirp->offset = offset; 1096 } 1097} 1098 1099/******************************************************************* 1100 Tell a dir position. 1101********************************************************************/ 1102 1103long TellDir(struct smb_Dir *dirp) 1104{ 1105 return(dirp->offset); 1106} 1107 1108/******************************************************************* 1109 Find an entry by name. Leave us at the offset after it. 1110 Don't check for veto or invisible files. 1111********************************************************************/ 1112 1113BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) 1114{ 1115 int i; 1116 const char *entry; 1117 connection_struct *conn = dirp->conn; 1118 1119 /* Search back in the name cache. */ 1120 for (i = dirp->name_cache_index; i >= 0; i--) { 1121 struct name_cache_entry *e = &dirp->name_cache[i]; 1122 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { 1123 *poffset = e->offset; 1124 SeekDir(dirp, e->offset); 1125 return True; 1126 } 1127 } 1128 for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) { 1129 struct name_cache_entry *e = &dirp->name_cache[i]; 1130 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) { 1131 *poffset = e->offset; 1132 SeekDir(dirp, e->offset); 1133 return True; 1134 } 1135 } 1136 1137 /* Not found in the name cache. Rewind directory and start from scratch. */ 1138 SMB_VFS_REWINDDIR(conn, dirp->dir); 1139 *poffset = 0; 1140 while ((entry = ReadDirName(dirp, poffset))) { 1141 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) { 1142 return True; 1143 } 1144 } 1145 return False; 1146} 1147