diff options
author | Jeremy Allison <jra@samba.org> | 1998-02-26 19:53:55 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 1998-02-26 19:53:55 +0000 |
commit | de3badf479eb08c19d4abc0625488effc79dc1fd (patch) | |
tree | 5993befe61e7ab92b7425d2351ff1da771c368a3 | |
parent | 64095b2486e3aca286103e28e400da3e40b14556 (diff) | |
download | samba-de3badf479eb08c19d4abc0625488effc79dc1fd.tar.gz samba-de3badf479eb08c19d4abc0625488effc79dc1fd.tar.bz2 samba-de3badf479eb08c19d4abc0625488effc79dc1fd.zip |
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 b813fb22c4c1b0ee48667e99e82434d20266bbf2)
-rw-r--r-- | source3/include/proto.h | 2 | ||||
-rw-r--r-- | source3/smbd/dir.c | 9 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 78 |
3 files changed, 72 insertions, 17 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 6f8edb445e..802d9973df 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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); diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index d751653263..a34406cc65 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -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); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 893f1adc66..35272ae3d9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -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; + + 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 continue=%d level = %d\n", + 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++) { |