1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00

Fix for NT redirector bug where deltree fails if the resume key

indexes are changed between directory scans. This fix does what
NT4.x SP3 does in that it stops using resume keys and returns
zero instead. We now use the filename in findnext to continue
the search in the correct place (as NT does).
Jeremy.
(This used to be commit b813fb22c4)
This commit is contained in:
Jeremy Allison 1998-02-26 19:53:55 +00:00
parent 64095b2486
commit de3badf479
3 changed files with 72 additions and 17 deletions

View File

@ -164,7 +164,7 @@ int dptr_create(int cnum,char *path, BOOL expect_close,int pid);
BOOL dptr_fill(char *buf1,unsigned int key);
BOOL dptr_zero(char *buf);
void *dptr_fetch(char *buf,int *num);
void *dptr_fetch_lanman2(char *params,int dptr_num);
void *dptr_fetch_lanman2(int dptr_num);
BOOL dir_check_ftype(int cnum,int mode,struct stat *st,int dirtype);
BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend);
void *OpenDir(int cnum, char *name, BOOL use_veto);

View File

@ -393,21 +393,16 @@ void *dptr_fetch(char *buf,int *num)
}
/****************************************************************************
fetch the dir ptr and seek it given the lanman2 parameter block
fetch the dir ptr.
****************************************************************************/
void *dptr_fetch_lanman2(char *params,int dptr_num)
void *dptr_fetch_lanman2(int dptr_num)
{
void *p = dptr_get(dptr_num,dircounter++);
uint32 resume_key = SVAL(params,6);
BOOL uses_resume_key = BITSETW(params+10,2);
BOOL continue_bit = BITSETW(params+10,3);
if (!p) {
DEBUG(3,("fetched null dirptr %d\n",dptr_num));
return(NULL);
}
if(uses_resume_key && !continue_bit)
SeekDir(p,resume_key);
DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
return(p);
}

View File

@ -301,7 +301,8 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
pstring fname;
BOOL matched;
char *p, *pdata = *ppdata;
int reskey=0, prev_dirpos=0;
uint32 reskey=0;
int prev_dirpos=0;
int mode=0;
uint32 size=0,len;
uint32 mdate=0, adate=0, cdate=0;
@ -336,7 +337,14 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
prev_dirpos = TellDir(Connections[cnum].dirptr);
dname = ReadDirName(Connections[cnum].dirptr);
reskey = TellDir(Connections[cnum].dirptr);
/*
* Due to bugs in NT client redirectors we are not using
* resume keys any more - set them to zero.
* Check out the related comments in findfirst/findnext.
* JRA.
*/
reskey = 0;
DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
@ -796,6 +804,7 @@ static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsiz
BOOL close_if_end = BITSETW(params+10,1);
BOOL requires_resume_key = BITSETW(params+10,2);
BOOL continue_bit = BITSETW(params+10,3);
pstring resume_name;
pstring mask;
pstring directory;
char *p;
@ -807,11 +816,15 @@ static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsiz
BOOL out_of_space = False;
int space_remaining;
*mask = *directory = 0;
*mask = *directory = *resume_name = 0;
DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, close_after_request=%d, close_if_end = %d requires_resume_key = %d resume_key = %d continue=%d level = %d\n",
pstrcpy( resume_name, params+12);
DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
close_after_request=%d, close_if_end = %d requires_resume_key = %d \
resume_key = %d resume name = %s continue=%d level = %d\n",
dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
requires_resume_key, resume_key, continue_bit, info_level));
requires_resume_key, resume_key, resume_name, continue_bit, info_level));
switch (info_level)
{
@ -839,7 +852,7 @@ static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsiz
return(ERROR(ERRDOS,ERRnomem));
/* Check that the dptr is valid */
if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(dptr_num)))
return(ERROR(ERRDOS,ERRnofiles));
string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
@ -871,9 +884,56 @@ static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsiz
space_remaining = max_data_bytes;
out_of_space = False;
/* If we have a resume key - seek to the correct position. */
if(requires_resume_key && !continue_bit)
SeekDir(Connections[cnum].dirptr, resume_key);
/*
* Seek to the correct position. We no longer use the resume key but
* depend on the last file name instead.
*/
if(requires_resume_key && *resume_name && !continue_bit)
{
/*
* Fix for NT redirector problem triggered by resume key indexes
* changing between directory scans. We now return a resume key of 0
* and instead look for the filename to continue from (also given
* to us by NT/95/smbfs/smbclient). If no other scans have been done between the
* findfirst/findnext (as is usual) then the directory pointer
* should already be at the correct place. Check this by scanning
* backwards looking for an exact (ie. case sensitive) filename match.
* If we get to the beginning of the directory and haven't found it then scan
* forwards again looking for a match. JRA.
*/
int current_pos, start_pos;
char *dname;
void *dirptr = Connections[cnum].dirptr;
start_pos = TellDir(dirptr);
for(current_pos = start_pos; current_pos >= 0; current_pos--)
{
SeekDir(dirptr, current_pos);
dname = ReadDirName(dirptr);
if(dname && strcsequal( resume_name, dname))
{
SeekDir(dirptr, current_pos+1);
break;
}
}
/*
* Scan forward from start if not found going backwards.
*/
if(current_pos < 0)
{
SeekDir(dirptr, start_pos);
for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
{
if(strcsequal( resume_name, dname))
{
SeekDir(dirptr, current_pos+1);
break;
}
} /* end for */
} /* end if current_pos */
} /* end if requires_resume_key && !continue_bit */
for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
{