r18011: Should fix bug 3835.
authorDerrell Lipman <derrell@samba.org>
Sun, 3 Sep 2006 00:50:34 +0000 (00:50 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:39:48 +0000 (11:39 -0500)
Jeremy: requires your eyes...

If the remote connection timed out while cli_list() was retrieving its list of
files, the error was not returned to the user, e.g. via smbc_opendir(), so the
user didn't have a way to know to set the timeout longer and try again.  This
problem would occur when a very large directory is being read with a too-small
timeout on the cli.

Jeremy, although there were a couple of areas that needed to be handled, I
needed to make one change that you should bless, in libsmb/clientgen.c.  It
was setting

  cli->smb_rw_error = smb_read_error;

but smb_read_error is zero, so this had no effect.  I'm now doing

  cli->smb_rw_error = READ_TIMEOUT;

instead, and according to the OP, these (cumulative) changes (in a slightly
different form) solve the problem.

Please confirm this smb_rw_error change will have no other adverse effects
that you can see.

Derrell

examples/libsmbclient/Makefile
source/libsmb/clientgen.c
source/libsmb/clilist.c
source/libsmb/libsmbclient.c

index a88f4a240cd0a44f1b697a18dc926d9255fd63ca..11c3b77132d20486d7c42a3acc8c249d83da778e 100644 (file)
@@ -6,10 +6,12 @@ EXTLIB_INCL = -I/usr/include/gtk-1.2 \
              -I/usr/include/glib-1.2 \
              -I/usr/lib/glib/include
 
+
 DEFS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 CFLAGS = -O0 -g -I$(SAMBA_INCL) $(EXTLIB_INCL) $(DEFS)
 
 LDFLAGS = -L/usr/local/samba/lib
+LIBSMBCLIENT = /usr/local/samba/lib/libsmbclient.so
 
 TESTS= testsmbc \
        tree \
@@ -26,43 +28,43 @@ all:        $(TESTS) smbsh
 
 testsmbc: testsmbc.o 
        @echo Linking testsmbc
-       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lsmbclient
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT)
 
 tree: tree.o
        @echo Linking tree
-       @$(CC) `gtk-config --cflags` $(CFLAGS) $(LDFLAGS) -o $@ `gtk-config --libs` -lsmbclient $<
+       @$(CC) `gtk-config --cflags` $(CFLAGS) $(LDFLAGS) -o $@ `gtk-config --libs` $(LIBSMBCLIENT) $<
 
 testacl: testacl.o
        @echo Linking testacl
-       @$(CC) `gtk-config --cflags` $(CFLAGS) $(LDFLAGS) -o $@ `gtk-config --libs` -lsmbclient -lpopt $<
+       @$(CC) `gtk-config --cflags` $(CFLAGS) $(LDFLAGS) -o $@ `gtk-config --libs` $(LIBSMBCLIENT) -lpopt $<
 
 testbrowse: testbrowse.o
        @echo Linking testbrowse
-       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -lsmbclient -lpopt $<
+       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBSMBCLIENT) -lpopt $<
 
 testbrowse2: testbrowse2.o
        @echo Linking testbrowse2
-       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -lsmbclient -lpopt $<
+       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBSMBCLIENT) -lpopt $<
 
 teststat: teststat.o
        @echo Linking teststat
-       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ /usr/local/samba/lib/libsmbclient.so -lpopt $<
+       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBSMBCLIENT) -lpopt $<
 
 teststat2: teststat2.o
        @echo Linking teststat2
-       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ /usr/local/samba/lib/libsmbclient.so -lpopt $<
+       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBSMBCLIENT) -lpopt $<
 
 testchmod: testchmod.o
        @echo Linking testchmod
-       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ /usr/local/samba/lib/libsmbclient.so -lpopt $<
+       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBSMBCLIENT) -lpopt $<
 
 testutime: testutime.o
        @echo Linking testutime
-       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ /usr/local/samba/lib/libsmbclient.so -lpopt $<
+       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBSMBCLIENT) -lpopt $<
 
 testread: testread.o
        @echo Linking testread
-       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ /usr/local/samba/lib/libsmbclient.so -lpopt $<
+       @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBSMBCLIENT) -lpopt $<
 
 smbsh:
        make -C smbwrapper
index 4608d40d4629190a0197aaa82070a7c6f7154d56..3a84a5bd4d1afab8e81eaec58a3c615ced2cbf5e 100644 (file)
@@ -79,7 +79,6 @@ static BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
 
 BOOL cli_receive_smb(struct cli_state *cli)
 {
-       extern int smb_read_error;
        BOOL ret;
 
        /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
@@ -107,9 +106,9 @@ BOOL cli_receive_smb(struct cli_state *cli)
        }
 
        /* If the server is not responding, note that now */
-
        if (!ret) {
-               cli->smb_rw_error = smb_read_error;
+                DEBUG(0, ("Receiving SMB: Server stopped responding\n"));
+               cli->smb_rw_error = READ_TIMEOUT;
                close(cli->fd);
                cli->fd = -1;
                return ret;
index 18c058f9dfbd44d437ffddf55cf30f4f38752aea..22cb5930c26734b8705926d1777175dce728dbc3 100644 (file)
@@ -349,10 +349,17 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
 
        mnt = cli_cm_get_mntpoint( cli );
 
-       for (p=dirlist,i=0;i<total_received;i++) {
-               p += interpret_long_filename(cli,info_level,p,&finfo,NULL,NULL,NULL);
-               fn( mnt,&finfo, Mask, state );
-       }
+        /* see if the server disconnected or the connection otherwise failed */
+        if (cli_is_error(cli)) {
+                total_received = -1;
+        } else {
+                /* no connection problem.  let user function add each entry */
+                for (p=dirlist,i=0;i<total_received;i++) {
+                        p += interpret_long_filename(cli, info_level, p,
+                                                     &finfo,NULL,NULL,NULL);
+                        fn( mnt,&finfo, Mask, state );
+                }
+        }
 
        /* free up the dirlist buffer and last name raw blob */
        SAFE_FREE(dirlist);
index c74e18b13c152c91d70b7a29538e558748771006..101cc022110672e681cc1f9ba2b10f70017849d8 100644 (file)
@@ -2540,6 +2540,7 @@ static SMBCFILE *
 smbc_opendir_ctx(SMBCCTX *context,
                  const char *fname)
 {
+        int saved_errno;
        fstring server, share, user, password, options;
        pstring workgroup;
        pstring path;
@@ -2547,6 +2548,7 @@ smbc_opendir_ctx(SMBCCTX *context,
         char *p;
        SMBCSRV *srv  = NULL;
        SMBCFILE *dir = NULL;
+        struct _smbc_callbacks *cb;
        struct in_addr rem_ip;
 
        if (!context || !context->internal ||
@@ -2908,9 +2910,9 @@ smbc_opendir_ctx(SMBCCTX *context,
                                        SAFE_FREE(dir->fname);
                                        SAFE_FREE(dir);
                                }
-                               errno = smbc_errno(context, targetcli);
+                               saved_errno = smbc_errno(context, targetcli);
 
-                                if (errno == EINVAL) {
+                                if (saved_errno == EINVAL) {
                                     /*
                                      * See if they asked to opendir something
                                      * other than a directory.  If so, the
@@ -2926,12 +2928,34 @@ smbc_opendir_ctx(SMBCCTX *context,
                                         ! IS_DOS_DIR(mode)) {
 
                                         /* It is.  Correct the error value */
-                                        errno = ENOTDIR;
+                                        saved_errno = ENOTDIR;
                                     }
                                 }
 
-                               return NULL;
+                                /*
+                                 * If there was an error and the server is no
+                                 * good any more...
+                                 */
+                                cb = &context->callbacks;
+                                if (cli_is_error(targetcli) &&
+                                    cb->check_server_fn(context, srv)) {
+
+                                    /* ... then remove it. */
+                                    if (cb->remove_unused_server_fn(context,
+                                                                    srv)) { 
+                                        /*
+                                         * We could not remove the server
+                                         * completely, remove it from the
+                                         * cache so we will not get it
+                                         * again. It will be removed when the
+                                         * last file/dir is closed.
+                                         */
+                                        cb->remove_cached_srv_fn(context, srv);
+                                    }
+                                }
 
+                                errno = saved_errno;
+                               return NULL;
                        }
                }