1996-05-04 11:50:46 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-04 11:50:46 +04:00
Directory handling routines
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
1996-05-04 11:50:46 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
/*
This module implements directory related functions for Samba .
*/
1999-12-13 16:27:58 +03:00
typedef struct _dptr_struct {
struct _dptr_struct * next , * prev ;
int dnum ;
uint16 spid ;
1998-08-14 21:38:29 +04:00
connection_struct * conn ;
void * ptr ;
BOOL expect_close ;
char * wcard ; /* Field only used for trans2_ searches */
uint16 attr ; /* Field only used for trans2_ searches */
char * path ;
1999-12-13 16:27:58 +03:00
} dptr_struct ;
1996-05-04 11:50:46 +04:00
1999-12-13 16:27:58 +03:00
static struct bitmap * dptr_bmap ;
static dptr_struct * dirptrs ;
1996-05-04 11:50:46 +04:00
static int dptrs_open = 0 ;
1999-12-13 16:27:58 +03:00
# define INVALID_DPTR_KEY (-3)
1996-05-04 11:50:46 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Initialise the dir bitmap .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1996-05-04 11:50:46 +04:00
void init_dptrs ( void )
{
2003-01-03 21:50:13 +03:00
static BOOL dptrs_init = False ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
if ( dptrs_init )
return ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
dptr_bmap = bitmap_allocate ( MAX_DIRECTORY_HANDLES ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( ! dptr_bmap )
exit_server ( " out of memory in init_dptrs " ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
dptrs_init = True ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Idle a dptr - the directory is closed but the control info is kept .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static void dptr_idle ( dptr_struct * dptr )
1996-05-04 11:50:46 +04:00
{
2003-01-03 21:50:13 +03:00
if ( dptr - > ptr ) {
DEBUG ( 4 , ( " Idling dptr dnum %d \n " , dptr - > dnum ) ) ;
dptrs_open - - ;
CloseDir ( dptr - > ptr ) ;
dptr - > ptr = NULL ;
}
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Idle the oldest dptr .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1996-05-04 11:50:46 +04:00
static void dptr_idleoldest ( void )
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr ;
/*
* Go to the end of the list .
*/
for ( dptr = dirptrs ; dptr & & dptr - > next ; dptr = dptr - > next )
;
if ( ! dptr ) {
DEBUG ( 0 , ( " No dptrs available to idle ? \n " ) ) ;
return ;
}
/*
* Idle the oldest pointer .
*/
for ( ; dptr ; dptr = dptr - > prev ) {
if ( dptr - > ptr ) {
dptr_idle ( dptr ) ;
return ;
}
}
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Get the dptr_struct for a dir index .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static dptr_struct * dptr_get ( int key , BOOL forclose )
1996-05-04 11:50:46 +04:00
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr ;
for ( dptr = dirptrs ; dptr ; dptr = dptr - > next ) {
if ( dptr - > dnum = = key ) {
if ( ! forclose & & ! dptr - > ptr ) {
if ( dptrs_open > = MAX_OPEN_DIRECTORIES )
dptr_idleoldest ( ) ;
DEBUG ( 4 , ( " Reopening dptr key %d \n " , key ) ) ;
if ( ( dptr - > ptr = OpenDir ( dptr - > conn , dptr - > path , True ) ) )
dptrs_open + + ;
}
DLIST_PROMOTE ( dirptrs , dptr ) ;
return dptr ;
}
}
return ( NULL ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Get the dptr ptr for a dir index .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static void * dptr_ptr ( int key )
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr = dptr_get ( key , False ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( dptr )
return ( dptr - > ptr ) ;
return ( NULL ) ;
1999-12-13 16:27:58 +03:00
}
/****************************************************************************
Get the dir path for a dir index .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-05-04 11:50:46 +04:00
char * dptr_path ( int key )
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr = dptr_get ( key , False ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( dptr )
return ( dptr - > path ) ;
return ( NULL ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Get the dir wcard for a dir index ( lanman2 specific ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1996-05-04 11:50:46 +04:00
char * dptr_wcard ( int key )
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr = dptr_get ( key , False ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( dptr )
return ( dptr - > wcard ) ;
return ( NULL ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Set the dir wcard for a dir index ( lanman2 specific ) .
Returns 0 on ok , 1 on fail .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1996-05-04 11:50:46 +04:00
BOOL dptr_set_wcard ( int key , char * wcard )
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr = dptr_get ( key , False ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( dptr ) {
dptr - > wcard = wcard ;
return True ;
}
return False ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Set the dir attrib for a dir index ( lanman2 specific ) .
Returns 0 on ok , 1 on fail .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1996-05-04 11:50:46 +04:00
BOOL dptr_set_attr ( int key , uint16 attr )
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr = dptr_get ( key , False ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( dptr ) {
dptr - > attr = attr ;
return True ;
}
return False ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Get the dir attrib for a dir index ( lanman2 specific )
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1996-05-04 11:50:46 +04:00
uint16 dptr_attr ( int key )
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr = dptr_get ( key , False ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( dptr )
return ( dptr - > attr ) ;
return ( 0 ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Close a dptr ( internal func ) .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static void dptr_close_internal ( dptr_struct * dptr )
1996-05-04 11:50:46 +04:00
{
2003-01-03 21:50:13 +03:00
DEBUG ( 4 , ( " closing dptr key %d \n " , dptr - > dnum ) ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
DLIST_REMOVE ( dirptrs , dptr ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
/*
* Free the dnum in the bitmap . Remember the dnum value is always
* biased by one with respect to the bitmap .
*/
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( bitmap_query ( dptr_bmap , dptr - > dnum - 1 ) ! = True ) {
DEBUG ( 0 , ( " dptr_close_internal : Error - closing dnum = %d and bitmap not set ! \n " ,
1999-12-13 16:27:58 +03:00
dptr - > dnum ) ) ;
2003-01-03 21:50:13 +03:00
}
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
bitmap_clear ( dptr_bmap , dptr - > dnum - 1 ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( dptr - > ptr ) {
CloseDir ( dptr - > ptr ) ;
dptrs_open - - ;
}
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
/* Lanman 2 specific code */
SAFE_FREE ( dptr - > wcard ) ;
string_set ( & dptr - > path , " " ) ;
SAFE_FREE ( dptr ) ;
1999-12-13 16:27:58 +03:00
}
/****************************************************************************
Close a dptr given a key .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void dptr_close ( int * key )
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( * key = = INVALID_DPTR_KEY )
return ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
/* OS/2 seems to use -1 to indicate "close all directories" */
if ( * key = = - 1 ) {
dptr_struct * next ;
for ( dptr = dirptrs ; dptr ; dptr = next ) {
next = dptr - > next ;
dptr_close_internal ( dptr ) ;
}
* key = INVALID_DPTR_KEY ;
return ;
}
1996-05-05 15:23:23 +04:00
2003-01-03 21:50:13 +03:00
dptr = dptr_get ( * key , True ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( ! dptr ) {
DEBUG ( 0 , ( " Invalid key %d given to dptr_close \n " , * key ) ) ;
return ;
}
1996-05-05 15:23:23 +04:00
2003-01-03 21:50:13 +03:00
dptr_close_internal ( dptr ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
* key = INVALID_DPTR_KEY ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Close all dptrs for a cnum .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1998-08-14 21:38:29 +04:00
void dptr_closecnum ( connection_struct * conn )
1996-05-04 11:50:46 +04:00
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr , * next ;
for ( dptr = dirptrs ; dptr ; dptr = next ) {
next = dptr - > next ;
if ( dptr - > conn = = conn )
dptr_close_internal ( dptr ) ;
}
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Idle all dptrs for a cnum .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1998-08-14 21:38:29 +04:00
void dptr_idlecnum ( connection_struct * conn )
1996-05-04 11:50:46 +04:00
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr ;
for ( dptr = dirptrs ; dptr ; dptr = dptr - > next ) {
if ( dptr - > conn = = conn & & dptr - > ptr )
dptr_idle ( dptr ) ;
}
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Close a dptr that matches a given path , only if it matches the spid also .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
void dptr_closepath ( char * path , uint16 spid )
1996-05-04 11:50:46 +04:00
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr , * next ;
for ( dptr = dirptrs ; dptr ; dptr = next ) {
next = dptr - > next ;
if ( spid = = dptr - > spid & & strequal ( dptr - > path , path ) )
dptr_close_internal ( dptr ) ;
}
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Start a directory listing .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2003-01-03 11:28:12 +03:00
static BOOL start_dir ( connection_struct * conn , pstring directory )
1996-05-04 11:50:46 +04:00
{
2003-01-03 21:50:13 +03:00
const char * dir2 ;
2003-01-03 11:28:12 +03:00
2003-01-03 21:50:13 +03:00
DEBUG ( 5 , ( " start_dir dir=%s \n " , directory ) ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
if ( ! check_name ( directory , conn ) )
return ( False ) ;
2003-01-03 11:28:12 +03:00
2003-01-03 21:50:13 +03:00
/* use a const pointer from here on */
dir2 = directory ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
if ( ! * dir2 )
dir2 = " . " ;
conn - > dirptr = OpenDir ( conn , directory , True ) ;
if ( conn - > dirptr ) {
dptrs_open + + ;
string_set ( & conn - > dirpath , directory ) ;
return ( True ) ;
}
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
return ( False ) ;
1996-05-04 11:50:46 +04:00
}
1999-12-13 16:27:58 +03:00
/****************************************************************************
Try and close the oldest handle not marked for
expect close in the hope that the client has
finished with that one .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void dptr_close_oldest ( BOOL old )
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr ;
/*
* Go to the end of the list .
*/
for ( dptr = dirptrs ; dptr & & dptr - > next ; dptr = dptr - > next )
;
if ( ! dptr ) {
DEBUG ( 0 , ( " No old dptrs available to close oldest ? \n " ) ) ;
return ;
}
/*
* If ' old ' is true , close the oldest oldhandle dnum ( ie . 1 < dnum < 256 ) that
* does not have expect_close set . If ' old ' is false , close
* one of the new dnum handles .
*/
for ( ; dptr ; dptr = dptr - > prev ) {
if ( ( old & & ( dptr - > dnum < 256 ) & & ! dptr - > expect_close ) | |
( ! old & & ( dptr - > dnum > 255 ) ) ) {
dptr_close_internal ( dptr ) ;
return ;
}
}
1999-12-13 16:27:58 +03:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Create a new dir ptr . If the flag old_handle is true then we must allocate
from the bitmap range 0 - 255 as old SMBsearch directory handles are only
one byte long . If old_handle is false we allocate from the range
256 - MAX_DIRECTORY_HANDLES . We bias the number we return by 1 to ensure
a directory handle is never zero . All the above is folklore taught to
me at Andrew ' s knee . . . . : - ) : - ) . JRA .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2003-01-03 11:28:12 +03:00
int dptr_create ( connection_struct * conn , pstring path , BOOL old_handle , BOOL expect_close , uint16 spid )
1996-05-04 11:50:46 +04:00
{
2003-01-03 21:50:13 +03:00
dptr_struct * dptr ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
if ( ! start_dir ( conn , path ) )
return ( - 2 ) ; /* Code to say use a unix error return code. */
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
if ( dptrs_open > = MAX_OPEN_DIRECTORIES )
dptr_idleoldest ( ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
dptr = ( dptr_struct * ) malloc ( sizeof ( dptr_struct ) ) ;
if ( ! dptr ) {
DEBUG ( 0 , ( " malloc fail in dptr_create. \n " ) ) ;
return - 1 ;
}
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
ZERO_STRUCTP ( dptr ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( old_handle ) {
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
/*
* This is an old - style SMBsearch request . Ensure the
* value we return will fit in the range 1 - 255.
*/
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
dptr - > dnum = bitmap_find ( dptr_bmap , 0 ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( dptr - > dnum = = - 1 | | dptr - > dnum > 254 ) {
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
/*
* Try and close the oldest handle not marked for
* expect close in the hope that the client has
* finished with that one .
*/
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
dptr_close_oldest ( True ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
/* Now try again... */
dptr - > dnum = bitmap_find ( dptr_bmap , 0 ) ;
if ( dptr - > dnum = = - 1 | | dptr - > dnum > 254 ) {
DEBUG ( 0 , ( " dptr_create: returned %d: Error - all old dirptrs in use ? \n " , dptr - > dnum ) ) ;
SAFE_FREE ( dptr ) ;
return - 1 ;
}
}
} else {
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
/*
* This is a new - style trans2 request . Allocate from
* a range that will return 256 - MAX_DIRECTORY_HANDLES .
*/
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
dptr - > dnum = bitmap_find ( dptr_bmap , 255 ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( dptr - > dnum = = - 1 | | dptr - > dnum < 255 ) {
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
/*
* Try and close the oldest handle close in the hope that
* the client has finished with that one . This will only
* happen in the case of the Win98 client bug where it leaks
* directory handles .
*/
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
dptr_close_oldest ( False ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
/* Now try again... */
dptr - > dnum = bitmap_find ( dptr_bmap , 255 ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
if ( dptr - > dnum = = - 1 | | dptr - > dnum < 255 ) {
DEBUG ( 0 , ( " dptr_create: returned %d: Error - all new dirptrs in use ? \n " , dptr - > dnum ) ) ;
SAFE_FREE ( dptr ) ;
return - 1 ;
}
}
}
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
bitmap_set ( dptr_bmap , dptr - > dnum ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
dptr - > dnum + = 1 ; /* Always bias the dnum by one - no zero dnums allowed. */
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
dptr - > ptr = conn - > dirptr ;
string_set ( & dptr - > path , path ) ;
dptr - > conn = conn ;
dptr - > spid = spid ;
dptr - > expect_close = expect_close ;
dptr - > wcard = NULL ; /* Only used in lanman2 searches */
dptr - > attr = 0 ; /* Only used in lanman2 searches */
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
DLIST_ADD ( dirptrs , dptr ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
DEBUG ( 3 , ( " creating new dirptr %d for path %s, expect_close = %d \n " ,
dptr - > dnum , path , expect_close ) ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
return ( dptr - > dnum ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Fill the 5 byte server reserved dptr field .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1997-07-24 21:25:11 +04:00
BOOL dptr_fill ( char * buf1 , unsigned int key )
1996-05-04 11:50:46 +04:00
{
2003-01-03 21:50:13 +03:00
unsigned char * buf = ( unsigned char * ) buf1 ;
void * p = dptr_ptr ( key ) ;
uint32 offset ;
if ( ! p ) {
DEBUG ( 1 , ( " filling null dirptr %d \n " , key ) ) ;
return ( False ) ;
}
offset = TellDir ( p ) ;
DEBUG ( 6 , ( " fill on key %u dirptr 0x%lx now at %d \n " , key ,
( long ) p , ( int ) offset ) ) ;
buf [ 0 ] = key ;
SIVAL ( buf , 1 , offset | DPTR_MASK ) ;
return ( True ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Fetch the dir ptr and seek it given the 5 byte server field .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1997-07-24 21:25:11 +04:00
void * dptr_fetch ( char * buf , int * num )
1996-05-04 11:50:46 +04:00
{
2003-01-03 21:50:13 +03:00
unsigned int key = * ( unsigned char * ) buf ;
void * p = dptr_ptr ( key ) ;
uint32 offset ;
if ( ! p ) {
DEBUG ( 3 , ( " fetched null dirptr %d \n " , key ) ) ;
return ( NULL ) ;
}
* num = key ;
offset = IVAL ( buf , 1 ) & ~ DPTR_MASK ;
SeekDir ( p , offset ) ;
DEBUG ( 3 , ( " fetching dirptr %d for path %s at offset %d \n " ,
key , dptr_path ( key ) , offset ) ) ;
return ( p ) ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Fetch the dir ptr .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1998-02-26 22:53:55 +03:00
void * dptr_fetch_lanman2 ( int dptr_num )
1996-05-04 11:50:46 +04:00
{
2003-01-03 21:50:13 +03:00
void * p = dptr_ptr ( dptr_num ) ;
if ( ! p ) {
DEBUG ( 3 , ( " fetched null dirptr %d \n " , dptr_num ) ) ;
return ( NULL ) ;
}
DEBUG ( 3 , ( " fetching dirptr %d for path %s \n " , dptr_num , dptr_path ( dptr_num ) ) ) ;
return ( p ) ;
1996-05-04 11:50:46 +04:00
}
1996-06-05 19:16:09 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Check a filetype for being valid .
1996-06-05 19:16:09 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1998-09-02 00:11:54 +04:00
BOOL dir_check_ftype ( connection_struct * conn , int mode , SMB_STRUCT_STAT * st , int dirtype )
1996-06-05 19:16:09 +04:00
{
2002-09-25 19:19:00 +04:00
int mask ;
/* Check the "may have" search bits. */
if ( ( ( mode & ~ dirtype ) & ( aHIDDEN | aSYSTEM | aDIR ) ) ! = 0 )
return False ;
/* Check the "must have" bits, which are the may have bits shifted eight */
/* If must have bit is set, the file/dir can not be returned in search unless the matching
file attribute is set */
mask = ( ( dirtype > > 8 ) & ( aDIR | aARCH | aRONLY | aHIDDEN | aSYSTEM ) ) ; /* & 0x37 */
if ( mask ) {
if ( ( mask & ( mode & ( aDIR | aARCH | aRONLY | aHIDDEN | aSYSTEM ) ) ) = = mask ) /* check if matching attribute present */
return True ;
else
return False ;
}
return True ;
1996-06-05 19:16:09 +04:00
}
2003-03-18 01:56:13 +03:00
static BOOL mangle_mask_match ( connection_struct * conn , fstring filename , char * mask )
2002-07-15 14:35:28 +04:00
{
mangle_map ( filename , True , False , SNUM ( conn ) ) ;
return mask_match ( filename , mask , False ) ;
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Get an 8.3 directory entry .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2003-03-18 01:56:13 +03:00
BOOL get_dir_entry ( connection_struct * conn , char * mask , int dirtype , pstring fname ,
1998-09-03 22:40:31 +04:00
SMB_OFF_T * size , int * mode , time_t * date , BOOL check_descend )
1996-05-04 11:50:46 +04:00
{
2003-03-18 01:56:13 +03:00
const char * dname ;
2003-01-03 21:50:13 +03:00
BOOL found = False ;
SMB_STRUCT_STAT sbuf ;
pstring path ;
pstring pathreal ;
BOOL isrootdir ;
pstring filename ;
BOOL needslash ;
* path = * pathreal = * filename = 0 ;
isrootdir = ( strequal ( conn - > dirpath , " ./ " ) | |
strequal ( conn - > dirpath , " . " ) | |
strequal ( conn - > dirpath , " / " ) ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
needslash = ( conn - > dirpath [ strlen ( conn - > dirpath ) - 1 ] ! = ' / ' ) ;
1997-05-20 04:32:51 +04:00
2003-01-03 21:50:13 +03:00
if ( ! conn - > dirptr )
return ( False ) ;
2001-02-08 23:47:09 +03:00
2003-01-03 21:50:13 +03:00
while ( ! found ) {
dname = ReadDirName ( conn - > dirptr ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
DEBUG ( 6 , ( " readdir on dirptr 0x%lx now at offset %d \n " ,
( long ) conn - > dirptr , TellDir ( conn - > dirptr ) ) ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
if ( dname = = NULL )
return ( False ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
pstrcpy ( filename , dname ) ;
/* notice the special *.* handling. This appears to be the only difference
between the wildcard handling in this routine and in the trans2 routines .
see masktest for a demo
*/
if ( ( strcmp ( mask , " *.* " ) = = 0 ) | |
mask_match ( filename , mask , False ) | |
mangle_mask_match ( conn , filename , mask ) ) {
if ( isrootdir & & ( strequal ( filename , " .. " ) | | strequal ( filename , " . " ) ) )
continue ;
if ( ! mangle_is_8_3 ( filename , False ) )
mangle_map ( filename , True , False , SNUM ( conn ) ) ;
pstrcpy ( fname , filename ) ;
* path = 0 ;
pstrcpy ( path , conn - > dirpath ) ;
if ( needslash )
pstrcat ( path , " / " ) ;
pstrcpy ( pathreal , path ) ;
pstrcat ( path , fname ) ;
pstrcat ( pathreal , dname ) ;
if ( conn - > vfs_ops . stat ( conn , pathreal , & sbuf ) ! = 0 ) {
DEBUG ( 5 , ( " Couldn't stat 1 [%s]. Error = %s \n " , path , strerror ( errno ) ) ) ;
continue ;
}
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
* mode = dos_mode ( conn , pathreal , & sbuf ) ;
1999-12-13 16:27:58 +03:00
2003-01-03 21:50:13 +03:00
if ( ! dir_check_ftype ( conn , * mode , & sbuf , dirtype ) ) {
DEBUG ( 5 , ( " [%s] attribs didn't match %x \n " , filename , dirtype ) ) ;
continue ;
}
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
* size = sbuf . st_size ;
* date = sbuf . st_mtime ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
DEBUG ( 3 , ( " get_dir_entry mask=[%s] found %s fname=%s \n " , mask , pathreal , fname ) ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
found = True ;
}
}
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
return ( found ) ;
}
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
typedef struct {
int pos ;
int numentries ;
int mallocsize ;
char * data ;
char * current ;
1996-05-04 11:50:46 +04:00
} Dir ;
2001-04-16 19:16:31 +04:00
/*******************************************************************
2002-09-25 19:19:00 +04:00
Check to see if a user can read a file . This is only approximate ,
it is used as part of the " hide unreadable " option . Don ' t
use it for anything security sensitive .
2001-04-16 19:16:31 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-12-17 22:16:22 +03:00
2002-09-25 19:19:00 +04:00
static BOOL user_can_read_file ( connection_struct * conn , char * name , SMB_STRUCT_STAT * pst )
2001-04-16 19:16:31 +04:00
{
2001-12-17 22:16:22 +03:00
extern struct current_user current_user ;
SEC_DESC * psd = NULL ;
size_t sd_size ;
files_struct * fsp ;
int smb_action ;
NTSTATUS status ;
uint32 access_granted ;
2002-07-15 14:35:28 +04:00
/*
* If user is a member of the Admin group
* we never hide files from them .
*/
if ( conn - > admin_user )
return True ;
/* If we can't stat it does not show it */
2002-09-25 19:19:00 +04:00
if ( ! VALID_STAT ( * pst ) & & ( vfs_stat ( conn , name , pst ) ! = 0 ) )
2001-12-17 22:16:22 +03:00
return False ;
/* Pseudo-open the file (note - no fd's created). */
2002-09-25 19:19:00 +04:00
if ( S_ISDIR ( pst - > st_mode ) )
fsp = open_directory ( conn , name , pst , 0 , SET_DENY_MODE ( DENY_NONE ) , ( FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN ) ,
2001-12-17 22:16:22 +03:00
unix_mode ( conn , aRONLY | aDIR , name ) , & smb_action ) ;
else
2003-01-03 21:50:13 +03:00
fsp = open_file_stat ( conn , name , pst ) ;
2002-03-20 03:46:53 +03:00
2001-12-17 22:16:22 +03:00
if ( ! fsp )
return False ;
/* Get NT ACL -allocated in main loop talloc context. No free needed here. */
sd_size = conn - > vfs_ops . fget_nt_acl ( fsp , fsp - > fd , & psd ) ;
2003-01-03 21:50:13 +03:00
close_file ( fsp , True ) ;
2001-12-17 22:16:22 +03:00
/* No access if SD get failed. */
if ( ! sd_size )
return False ;
return se_access_check ( psd , current_user . nt_user_token , FILE_READ_DATA ,
& access_granted , & status ) ;
2001-04-16 19:16:31 +04:00
}
2002-08-17 19:27:10 +04:00
/*******************************************************************
2002-09-25 19:19:00 +04:00
Check to see if a user can write a file ( and only files , we do not
check dirs on this one ) . This is only approximate ,
it is used as part of the " hide unwriteable " option . Don ' t
use it for anything security sensitive .
2002-08-17 19:27:10 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-09-25 19:19:00 +04:00
static BOOL user_can_write_file ( connection_struct * conn , char * name , SMB_STRUCT_STAT * pst )
2002-08-17 19:27:10 +04:00
{
extern struct current_user current_user ;
SEC_DESC * psd = NULL ;
size_t sd_size ;
files_struct * fsp ;
int smb_action ;
int access_mode ;
NTSTATUS status ;
uint32 access_granted ;
/*
* If user is a member of the Admin group
* we never hide files from them .
*/
if ( conn - > admin_user )
return True ;
/* If we can't stat it does not show it */
2002-09-25 19:19:00 +04:00
if ( ! VALID_STAT ( * pst ) & & ( vfs_stat ( conn , name , pst ) ! = 0 ) )
2002-08-17 19:27:10 +04:00
return False ;
/* Pseudo-open the file (note - no fd's created). */
2002-09-25 19:19:00 +04:00
if ( S_ISDIR ( pst - > st_mode ) )
2002-08-17 19:27:10 +04:00
return True ;
else
2002-09-25 19:19:00 +04:00
fsp = open_file_shared1 ( conn , name , pst , FILE_WRITE_ATTRIBUTES , SET_DENY_MODE ( DENY_NONE ) ,
2002-08-17 19:27:10 +04:00
( FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN ) , 0 , 0 , & access_mode , & smb_action ) ;
if ( ! fsp )
return False ;
/* Get NT ACL -allocated in main loop talloc context. No free needed here. */
sd_size = conn - > vfs_ops . fget_nt_acl ( fsp , fsp - > fd , & psd ) ;
close_file ( fsp , False ) ;
/* No access if SD get failed. */
if ( ! sd_size )
return False ;
return se_access_check ( psd , current_user . nt_user_token , FILE_WRITE_DATA ,
& access_granted , & status ) ;
}
2002-09-25 19:19:00 +04:00
/*******************************************************************
Is a file a " special " type ?
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL file_is_special ( connection_struct * conn , char * name , SMB_STRUCT_STAT * pst )
{
/*
* If user is a member of the Admin group
* we never hide files from them .
*/
if ( conn - > admin_user )
return True ;
/* If we can't stat it does not show it */
if ( ! VALID_STAT ( * pst ) & & ( vfs_stat ( conn , name , pst ) ! = 0 ) )
return True ;
if ( S_ISREG ( pst - > st_mode ) | | S_ISDIR ( pst - > st_mode ) | | S_ISLNK ( pst - > st_mode ) )
return False ;
return True ;
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
1999-12-13 16:27:58 +03:00
Open a directory .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2003-01-03 11:28:12 +03:00
void * OpenDir ( connection_struct * conn , const char * name , BOOL use_veto )
1996-05-04 11:50:46 +04:00
{
2002-07-15 14:35:28 +04:00
Dir * dirp ;
2003-01-03 11:28:12 +03:00
const char * n ;
2002-07-15 14:35:28 +04:00
DIR * p = conn - > vfs_ops . opendir ( conn , name ) ;
int used = 0 ;
if ( ! p )
return ( NULL ) ;
dirp = ( Dir * ) malloc ( sizeof ( Dir ) ) ;
if ( ! dirp ) {
DEBUG ( 0 , ( " Out of memory in OpenDir \n " ) ) ;
conn - > vfs_ops . closedir ( conn , p ) ;
return ( NULL ) ;
}
dirp - > pos = dirp - > numentries = dirp - > mallocsize = 0 ;
dirp - > data = dirp - > current = NULL ;
while ( True ) {
int l ;
BOOL normal_entry = True ;
2002-09-25 19:19:00 +04:00
SMB_STRUCT_STAT st ;
char * entry = NULL ;
2002-07-15 14:35:28 +04:00
if ( used = = 0 ) {
n = " . " ;
normal_entry = False ;
} else if ( used = = 2 ) {
n = " .. " ;
normal_entry = False ;
} else {
n = vfs_readdirname ( conn , p ) ;
if ( n = = NULL )
break ;
if ( ( strcmp ( " . " , n ) = = 0 ) | | ( strcmp ( " .. " , n ) = = 0 ) )
continue ;
normal_entry = True ;
}
2002-09-25 19:19:00 +04:00
ZERO_STRUCT ( st ) ;
2002-07-15 14:35:28 +04:00
l = strlen ( n ) + 1 ;
/* If it's a vetoed file, pretend it doesn't even exist */
if ( normal_entry & & use_veto & & conn & & IS_VETO_PATH ( conn , n ) )
continue ;
/* Honour _hide unreadable_ option */
if ( normal_entry & & conn & & lp_hideunreadable ( SNUM ( conn ) ) ) {
int ret = 0 ;
2001-04-16 19:16:31 +04:00
2002-09-25 19:19:00 +04:00
if ( entry | | asprintf ( & entry , " %s/%s/%s " , conn - > origpath , name , n ) > 0 ) {
ret = user_can_read_file ( conn , entry , & st ) ;
2002-07-15 14:35:28 +04:00
}
2002-09-25 19:19:00 +04:00
if ( ! ret ) {
SAFE_FREE ( entry ) ;
2002-07-15 14:35:28 +04:00
continue ;
2002-09-25 19:19:00 +04:00
}
2002-07-15 14:35:28 +04:00
}
2002-08-17 19:27:10 +04:00
/* Honour _hide unwriteable_ option */
if ( normal_entry & & conn & & lp_hideunwriteable_files ( SNUM ( conn ) ) ) {
int ret = 0 ;
2002-09-25 19:19:00 +04:00
if ( entry | | asprintf ( & entry , " %s/%s/%s " , conn - > origpath , name , n ) > 0 ) {
ret = user_can_write_file ( conn , entry , & st ) ;
}
if ( ! ret ) {
2002-08-17 19:27:10 +04:00
SAFE_FREE ( entry ) ;
2002-09-25 19:19:00 +04:00
continue ;
}
}
/* Honour _hide_special_ option */
if ( normal_entry & & conn & & lp_hide_special_files ( SNUM ( conn ) ) ) {
int ret = 0 ;
if ( entry | | asprintf ( & entry , " %s/%s/%s " , conn - > origpath , name , n ) > 0 ) {
ret = file_is_special ( conn , entry , & st ) ;
2002-08-17 19:27:10 +04:00
}
2002-09-25 19:19:00 +04:00
if ( ret ) {
SAFE_FREE ( entry ) ;
2002-08-17 19:27:10 +04:00
continue ;
2002-09-25 19:19:00 +04:00
}
2002-08-17 19:27:10 +04:00
}
2002-09-25 19:19:00 +04:00
SAFE_FREE ( entry ) ;
2002-07-15 14:35:28 +04:00
if ( used + l > dirp - > mallocsize ) {
int s = MAX ( used + l , used + 2000 ) ;
char * r ;
r = ( char * ) Realloc ( dirp - > data , s ) ;
if ( ! r ) {
DEBUG ( 0 , ( " Out of memory in OpenDir \n " ) ) ;
break ;
}
dirp - > data = r ;
dirp - > mallocsize = s ;
dirp - > current = dirp - > data ;
}
2003-03-18 01:56:13 +03:00
safe_strcpy_base ( dirp - > data + used , n , dirp - > data , dirp - > mallocsize ) ;
2002-07-15 14:35:28 +04:00
used + = l ;
dirp - > numentries + + ;
}
conn - > vfs_ops . closedir ( conn , p ) ;
return ( ( void * ) dirp ) ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
1999-12-13 16:27:58 +03:00
Close a directory .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1996-05-04 11:50:46 +04:00
void CloseDir ( void * p )
{
2003-01-03 21:50:13 +03:00
if ( ! p )
return ;
SAFE_FREE ( ( ( Dir * ) p ) - > data ) ;
SAFE_FREE ( p ) ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
1999-12-13 16:27:58 +03:00
Read from a directory .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2003-03-18 01:56:13 +03:00
const char * ReadDirName ( void * p )
1996-05-04 11:50:46 +04:00
{
2003-01-03 21:50:13 +03:00
char * ret ;
Dir * dirp = ( Dir * ) p ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
if ( ! dirp | | ! dirp - > current | | dirp - > pos > = dirp - > numentries )
return ( NULL ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
ret = dirp - > current ;
dirp - > current = skip_string ( dirp - > current , 1 ) ;
dirp - > pos + + ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
return ( ret ) ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
1999-12-13 16:27:58 +03:00
Seek a dir .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1996-05-04 11:50:46 +04:00
BOOL SeekDir ( void * p , int pos )
{
2003-01-03 21:50:13 +03:00
Dir * dirp = ( Dir * ) p ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
if ( ! dirp )
return ( False ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
if ( pos < dirp - > pos ) {
dirp - > current = dirp - > data ;
dirp - > pos = 0 ;
}
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
while ( dirp - > pos < pos & & ReadDirName ( p ) )
;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
return ( dirp - > pos = = pos ) ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
1999-12-13 16:27:58 +03:00
Tell a dir position .
1996-05-04 11:50:46 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1996-05-04 11:50:46 +04:00
int TellDir ( void * p )
{
2003-01-03 21:50:13 +03:00
Dir * dirp = ( Dir * ) p ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
if ( ! dirp )
return ( - 1 ) ;
1996-05-04 11:50:46 +04:00
2003-01-03 21:50:13 +03:00
return ( dirp - > pos ) ;
1996-05-04 11:50:46 +04:00
}
2000-01-05 22:59:42 +03:00
/*******************************************************************************
This section manages a global directory cache .
( It should probably be split into a separate module . crh )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-05-04 11:50:46 +04:00
2000-01-05 22:59:42 +03:00
typedef struct {
2003-01-03 21:50:13 +03:00
ubi_dlNode node ;
char * path ;
char * name ;
char * dname ;
int snum ;
2000-01-05 22:59:42 +03:00
} dir_cache_entry ;
1997-10-16 05:03:18 +04:00
1998-07-24 11:43:13 +04:00
static ubi_dlNewList ( dir_cache ) ;
1997-10-16 05:03:18 +04:00
2000-01-05 22:59:42 +03:00
/*****************************************************************************
Add an entry to the directory cache .
Input : path -
name -
dname -
snum -
Output : None .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-03-18 01:56:13 +03:00
void DirCacheAdd ( const char * path , const char * name , const char * dname , int snum )
2000-01-05 22:59:42 +03:00
{
2003-01-03 21:50:13 +03:00
int pathlen ;
int namelen ;
dir_cache_entry * entry ;
1997-10-16 05:03:18 +04:00
2003-01-03 21:50:13 +03:00
/*
* Allocate the structure & string space in one go so that it can be freed
* in one call to free ( ) .
*/
pathlen = strlen ( path ) + 1 ; /* Bytes required to store path (with nul). */
namelen = strlen ( name ) + 1 ; /* Bytes required to store name (with nul). */
entry = ( dir_cache_entry * ) malloc ( sizeof ( dir_cache_entry )
+ pathlen
+ namelen
+ strlen ( dname ) + 1 ) ;
if ( NULL = = entry ) /* Not adding to the cache is not fatal, */
return ; /* so just return as if nothing happened. */
/* Set pointers correctly and load values. */
2003-02-28 02:54:58 +03:00
entry - > path = memcpy ( ( char * ) & entry [ 1 ] , path , strlen ( path ) + 1 ) ;
entry - > name = memcpy ( & ( entry - > path [ pathlen ] ) , name , strlen ( name ) + 1 ) ;
entry - > dname = memcpy ( & ( entry - > name [ namelen ] ) , dname , strlen ( dname ) + 1 ) ;
2003-01-03 21:50:13 +03:00
entry - > snum = snum ;
/* Add the new entry to the linked list. */
( void ) ubi_dlAddHead ( dir_cache , entry ) ;
DEBUG ( 4 , ( " Added dir cache entry %s %s -> %s \n " , path , name , dname ) ) ;
/* Free excess cache entries. */
while ( DIRCACHESIZE < dir_cache - > count )
safe_free ( ubi_dlRemTail ( dir_cache ) ) ;
2000-01-05 22:59:42 +03:00
}
1997-10-16 05:03:18 +04:00
2000-01-05 22:59:42 +03:00
/*****************************************************************************
Search for an entry to the directory cache .
Input : path -
name -
snum -
Output : The dname string of the located entry , or NULL if the entry was
not found .
Notes : This uses a linear search , which is is okay because of
the small size of the cache . Use a splay tree or hash
for large caches .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-10-16 05:03:18 +04:00
2003-01-03 11:28:12 +03:00
char * DirCacheCheck ( const char * path , const char * name , int snum )
2000-01-05 22:59:42 +03:00
{
2003-01-03 21:50:13 +03:00
dir_cache_entry * entry ;
for ( entry = ( dir_cache_entry * ) ubi_dlFirst ( dir_cache ) ;
NULL ! = entry ;
entry = ( dir_cache_entry * ) ubi_dlNext ( entry ) ) {
if ( entry - > snum = = snum
2003-02-28 00:37:30 +03:00
& & entry - > name & & 0 = = strcmp ( name , entry - > name )
& & entry - > path & & 0 = = strcmp ( path , entry - > path ) ) {
2003-01-03 21:50:13 +03:00
DEBUG ( 4 , ( " Got dir cache hit on %s %s -> %s \n " , path , name , entry - > dname ) ) ;
return ( entry - > dname ) ;
}
}
return ( NULL ) ;
2000-01-05 22:59:42 +03:00
}
/*****************************************************************************
Remove all cache entries which have an snum that matches the input .
Input : snum -
Output : None .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-10-16 05:03:18 +04:00
1998-07-29 07:08:05 +04:00
void DirCacheFlush ( int snum )
{
dir_cache_entry * entry ;
ubi_dlNodePtr next ;
for ( entry = ( dir_cache_entry * ) ubi_dlFirst ( dir_cache ) ;
NULL ! = entry ; ) {
next = ubi_dlNext ( entry ) ;
if ( entry - > snum = = snum )
2001-09-17 15:25:41 +04:00
safe_free ( ubi_dlRemThis ( dir_cache , entry ) ) ;
1998-07-29 07:08:05 +04:00
entry = ( dir_cache_entry * ) next ;
}
2000-01-05 22:59:42 +03:00
}