On Mon, May 30, 2005 at 05:09:15PM +0200, Mair Wolfgang-awm013 wrote:
> Hello,
> 
> I'm having problems with using smbclient on a win2k share. The server runs 
> samba 3.0.14a on Solaris 9.
> 
> I want to tar the whole directory of a share. Into a file on the server
> 
> What I found out so far is, that it works until a maximum file count of 35. 
> It is not size dependant but if the file count in that share exceeds more 
> than 35 the smbclient hangs for ever and with the time is consuming up all 
> the available memory. Until the server hangs as well due to a lack of memory 
> space. 
> 
> Any ideas would be greatly appreciated.

This is probably the "infinate spin" reading directories
bug which we've fixed in SVN. Try this patch for 3.0.14a.

Jeremy
--- libsmb/clilist.c.orig       2005-04-13 23:14:24.000000000 -0700
+++ libsmb/clilist.c    2005-05-31 16:18:33.603556265 -0700
@@ -22,6 +22,8 @@
 
 #include "includes.h"
 
+extern file_info def_finfo;
+
 /****************************************************************************
  Interpret a long filename structure - this is mostly guesses at the moment.
  The length of the structure is returned
@@ -29,16 +31,20 @@
  by NT and 2 is used by OS/2
 ****************************************************************************/
 
-static size_t interpret_long_filename(struct cli_state *cli,
-                                  int level,char *p,file_info *finfo)
+static size_t interpret_long_filename(struct cli_state *cli, int level,char 
*p,file_info *finfo,
+                                       uint32 *p_resume_key, DATA_BLOB 
*p_last_name_raw, uint32 *p_last_name_raw_len)
 {
-       extern file_info def_finfo;
        file_info finfo2;
        int len;
        char *base = p;
 
-       if (!finfo) finfo = &finfo2;
+       if (!finfo) {
+               finfo = &finfo2;
+       }
 
+       if (p_resume_key) {
+               *p_resume_key = 0;
+       }
        memcpy(finfo,&def_finfo,sizeof(*finfo));
 
        switch (level) {
@@ -84,6 +90,10 @@
                {
                        size_t namelen, slen;
                        p += 4; /* next entry offset */
+
+                       if (p_resume_key) {
+                               *p_resume_key = IVAL(p,0);
+                       }
                        p += 4; /* fileindex */
                                
                        /* these dates appear to arrive in a
@@ -130,6 +140,22 @@
                        clistr_pull(cli, finfo->name, p,
                                    sizeof(finfo->name),
                                    namelen, 0);
+
+                       /* To be robust in the face of unicode conversion 
failures
+                          we need to copy the raw bytes of the last name seen 
here.
+                          Namelen doesn't include the terminating unicode 
null, so
+                          copy it here. */
+
+                       if (p_last_name_raw && p_last_name_raw_len) {
+                               if (namelen + 2 > p_last_name_raw->length) {
+                                       memset(p_last_name_raw->data, '\0', 
sizeof(p_last_name_raw->length));
+                                       *p_last_name_raw_len = 0;
+                               } else {
+                                       memcpy(p_last_name_raw->data, p, 
namelen);
+                                       SSVAL(p_last_name_raw->data, namelen, 
0);
+                                       *p_last_name_raw_len = namelen + 2;
+                               }
+                       }
                        return (size_t)IVAL(base, 0);
                }
        }
@@ -145,7 +171,7 @@
 int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, 
                 void (*fn)(const char *, file_info *, const char *, void *), 
void *state)
 {
-#if 0
+#if 1
        int max_matches = 1366; /* Match W2k - was 512. */
 #else
        int max_matches = 512;
@@ -169,6 +195,9 @@
        uint16 setup;
        pstring param;
        const char *mnt;
+       uint32 resume_key = 0;
+       uint32 last_name_raw_len = 0;
+       DATA_BLOB last_name_raw = data_blob(NULL, 2*sizeof(pstring));
 
        /* NT uses 260, OS/2 uses 2. Both accept 1. */
        info_level = (cli->capabilities&CAP_NT_SMBS)?260:1;
@@ -203,13 +232,19 @@
                        SSVAL(param,0,ff_dir_handle);
                        SSVAL(param,2,max_matches); /* max count */
                        SSVAL(param,4,info_level); 
-                       SIVAL(param,6,0); /* ff_resume_key */
+                       /* For W2K servers serving out FAT filesystems we 
*must* set the
+                          resume key. If it's not FAT then it's returned as 
zero. */
+                       SIVAL(param,6,resume_key); /* ff_resume_key */
                        /* NB. *DON'T* use continue here. If you do it seems 
that W2K and bretheren
                           can miss filenames. Use last filename continue 
instead. JRA */
                        
SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END));
        /* resume required + close on end */
                        p = param+12;
-                       p += clistr_push(cli, param+12, mask, sizeof(param)-12, 
-                                        STR_TERMINATE);
+                       if (last_name_raw_len && (last_name_raw_len < 
(sizeof(param)-12))) {
+                               memcpy(p, last_name_raw.data, 
last_name_raw_len);
+                               p += last_name_raw_len;
+                       } else {
+                               p += clistr_push(cli, param+12, mask, 
sizeof(param)-12, STR_TERMINATE);
+                       }
                }
 
                param_len = PTR_DIFF(p, param);
@@ -276,7 +311,8 @@
                                /* Last entry - fixup the last offset length. */
                                SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
                        }
-                       p2 += interpret_long_filename(cli,info_level,p2,&finfo);
+                       p2 += interpret_long_filename(cli,info_level,p2,&finfo,
+                                                       
&resume_key,&last_name_raw,&last_name_raw_len);
                }
 
                if (ff_lastname > 0) {
@@ -316,12 +352,13 @@
        mnt = cli_cm_get_mntpoint( cli );
 
        for (p=dirlist,i=0;i<total_received;i++) {
-               p += interpret_long_filename(cli,info_level,p,&finfo);
+               p += 
interpret_long_filename(cli,info_level,p,&finfo,NULL,NULL,NULL);
                fn( mnt,&finfo, Mask, state );
        }
 
-       /* free up the dirlist buffer */
+       /* free up the dirlist buffer and last name raw blob */
        SAFE_FREE(dirlist);
+       data_blob_free(&last_name_raw);
        return(total_received);
 }
 
@@ -332,7 +369,6 @@
 
 static int interpret_short_filename(struct cli_state *cli, char *p,file_info 
*finfo)
 {
-       extern file_info def_finfo;
 
        *finfo = def_finfo;
 
-- 
To unsubscribe from this list go to the following URL and read the
instructions:  https://lists.samba.org/mailman/listinfo/samba

Reply via email to