fix a bug that we've had for a long time where we don't handle EOF
authorAndrew Tridgell <tridge@samba.org>
Tue, 30 Jul 1996 15:47:30 +0000 (15:47 +0000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 30 Jul 1996 15:47:30 +0000 (15:47 +0000)
properly from clients, and end up looping like mad.

At least I _hope_ this is fixed.
(This used to be commit a7c7d7afe2ef81f4a74584ce9b71e54442f7e484)

source3/client/client.c
source3/include/proto.h
source3/include/smb.h
source3/lib/util.c
source3/smbd/chgpasswd.c
source3/smbd/reply.c
source3/smbd/server.c

index fde79c6e1bcd3c0b8098666312a0fc3e5c580e66..7c4795a8c301f598f93b9e91c94aa86d3afd1604 100644 (file)
@@ -768,7 +768,7 @@ static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (
       memcpy(p,status,21);
 
       send_smb(Client,outbuf);
-      receive_smb(Client,inbuf,CLIENT_TIMEOUT,False);
+      receive_smb(Client,inbuf,CLIENT_TIMEOUT);
 
       if (CVAL(inbuf,smb_rcls) != 0) 
        DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf)));      
index faddbc6a4927cd9edb69a06c0bdb60b760cf8550..60b8eed59a5c977277622045ba8b112eb9995b25 100644 (file)
@@ -636,7 +636,7 @@ BOOL check_file_sharing(int cnum,char *fname);
 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
                      int mode,int *Access,int *action);
 int seek_file(int fnum,int pos);
-int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact);
+int read_file(int fnum,char *data,int pos,int n);
 int write_file(int fnum,char *data,int n);
 BOOL become_service(int cnum,BOOL do_chdir);
 int find_service(char *service);
@@ -819,8 +819,7 @@ void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode
 void close_low_fds(void);
 int write_socket(int fd,char *buf,int len);
 int read_udp_socket(int fd,char *buf,int len);
-int set_blocking(int fd, BOOL set);
-int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL exact);
+int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out);
 int read_max_udp(int fd,char *buffer,int bufsize,int maxtime);
 int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew);
 BOOL send_keepalive(int client);
index 05924de35e8c992d9785bf4993d1013aa4b6b5d5..317f31b19ed4d18eb62ba0a6dd7d09b116860188 100644 (file)
@@ -111,11 +111,10 @@ EXTERN int syslog_level;
 #define DEBUG(level,body) ((DEBUGLEVEL>=(level))? (syslog_level = (level), Debug1 body):0)
 #endif
 
-/* this defines the error codes that receive_smb can put in smberrcode */
-#define SMBERR_OK 0
-#define SMBERR_TIMEOUT 1
-#define SMBERR_EOF 2
-#define SMBERR_ERROR 3
+/* this defines the error codes that receive_smb can put in smb_read_error */
+#define READ_TIMEOUT 1
+#define READ_EOF 2
+#define READ_ERROR 3
 
 
 #define DIR_STRUCT_SIZE 43
index ee4fca3ed37eb6e75cdfca3715b889d92ac41199..8c221a23b6c8a82416e5c343c4642cf204fc1984 100644 (file)
@@ -75,6 +75,8 @@ pstring user_socket_options="";
 pstring sesssetup_user="";
 
 
+int smb_read_error = 0;
+
 static char *filename_dos(char *path,char *buf);
 
 static BOOL stdout_logging = False;
@@ -1691,103 +1693,44 @@ int read_udp_socket(int fd,char *buf,int len)
   return(ret);
 }
 
-/****************************************************************************
-Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
-else
-if SYSV use O_NDELAY
-if BSD use FNDELAY
-****************************************************************************/
-int set_blocking(int fd, BOOL set)
-{
-int val;
-#ifdef O_NONBLOCK
-#define FLAG_TO_SET O_NONBLOCK
-#else
-#ifdef SYSV
-#define FLAG_TO_SET O_NDELAY
-#else /* BSD */
-#define FLAG_TO_SET FNDELAY
-#endif
-#endif
-
-  if((val = fcntl(fd, F_GETFL, 0))==-1)
-       return -1;
-  if(set) /* Turn blocking on - ie. clear nonblock flag */
-       val &= ~FLAG_TO_SET;
-  else
-    val |= FLAG_TO_SET;
-  return fcntl( fd, F_SETFL, val);
-#undef FLAG_TO_SET
-}
-
-
-/****************************************************************************
-Calculate the difference in timeout values. Return 1 if val1 > val2,
-0 if val1 == val2, -1 if val1 < val2. Stores result in retval. retval
-may be == val1 or val2
-****************************************************************************/
-static int tval_sub( struct timeval *retval, struct timeval *val1, struct timeval *val2)
-{
-  int usecdiff = val1->tv_usec - val2->tv_usec;
-  int secdiff = val1->tv_sec - val2->tv_sec;
-  if(usecdiff < 0) {
-    usecdiff = 1000000 + usecdiff;
-    secdiff--;
-  }
-  retval->tv_sec = secdiff;
-  retval->tv_usec = usecdiff;
-  if(secdiff < 0)
-    return -1;
-  if(secdiff > 0)
-    return 1;
-  return (usecdiff < 0 ) ? -1 : ((usecdiff > 0 ) ? 1 : 0);
-}
-
 /****************************************************************************
 read data from a device with a timout in msec.
 mincount = if timeout, minimum to read before returning
 maxcount = number to be read.
 ****************************************************************************/
-int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL exact)
+int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out)
 {
   fd_set fds;
   int selrtn;
   int readret;
   int nread = 0;
-  struct timeval timeout, tval1, tval2, tvaldiff;
-  int error_limit = 5;
+  struct timeval timeout;
 
   /* just checking .... */
   if (maxcnt <= 0) return(0);
 
-  if(time_out == -2)
-    time_out = DEFAULT_PIPE_TIMEOUT;
+  smb_read_error = 0;
 
   /* Blocking read */
-  if(time_out < 0) {
+  if (time_out <= 0) {
     if (mincnt == 0) mincnt = maxcnt;
 
-    while (nread < mincnt)
-      {
-       readret = read(fd, buf + nread, maxcnt - nread);
-       if (readret <= 0) return(nread);
-       nread += readret;
+    while (nread < mincnt) {
+      readret = read(fd, buf + nread, maxcnt - nread);
+      if (readret == 0) {
+       smb_read_error = READ_EOF;
+       return -1;
+      }
+
+      if (readret == -1) {
+       smb_read_error = READ_ERROR;
+       return -1;
       }
+      nread += readret;
+    }
     return(nread);
   }
   
-  /* Non blocking read */
-  if(time_out == 0) {
-    set_blocking(fd, False);
-    nread = read_data(fd, buf, mincnt);
-    if (nread < maxcnt)
-      nread += read(fd,buf+nread,maxcnt-nread);
-    if(nread == -1 && errno == EWOULDBLOCK)
-      nread = 0;
-    set_blocking(fd,True);
-    return nread;
-  }
-
   /* Most difficult - timeout read */
   /* If this is ever called on a disk file and 
         mincnt is greater then the filesize then
@@ -1798,69 +1741,40 @@ int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL
   timeout.tv_sec = time_out / 1000;
   timeout.tv_usec = 1000 * (time_out % 1000);
 
-  /* As most UNIXes don't modify the value of timeout
-     when they return from select we need to get the timeofday (in usec)
-     now, and also after the select returns so we know
-     how much time has elapsed */
-
-  if (exact)
-    GetTimeOfDay( &tval1);
-  nread = 0; /* Number of bytes we have read */
-
-  for(;;) 
+  for (nread=0; nread<mincnt; ) 
     {      
       FD_ZERO(&fds);
       FD_SET(fd,&fds);
       
       selrtn = sys_select(&fds,&timeout);
-      
+
       /* Check if error */
       if(selrtn == -1) {
+       /* something is wrong. Maybe the socket is dead? */
+       smb_read_error = READ_ERROR;
        return -1;
       }
       
       /* Did we timeout ? */
       if (selrtn == 0) {
-       if (nread < mincnt) return -1;
-       break; /* Yes */
+       smb_read_error = READ_TIMEOUT;
+       return -1;
       }
       
       readret = read(fd, buf+nread, maxcnt-nread);
-      if (readret == 0 && nread < mincnt) {
-       /* error_limit should not really be needed, but some systems
-          do strange things ...  I don't want to just continue
-          indefinately in case we get an infinite loop */
-       if (error_limit--) continue;
-       return(-1);
+      if (readret == 0) {
+       /* we got EOF on the file descriptor */
+       smb_read_error = READ_EOF;
+       return -1;
       }
 
-      if (readret < 0) {
-       /* force a particular error number for
-          portability */
-       DEBUG(5,("read gave error %s\n",strerror(errno)));
+      if (readret == -1) {
+       /* the descriptor is probably dead */
+       smb_read_error = READ_ERROR;
        return -1;
       }
       
       nread += readret;
-      
-      /* If we have read more than mincnt then return */
-      if (nread >= mincnt)
-       break;
-
-      /* We need to do another select - but first reduce the
-        time_out by the amount of time already elapsed - if
-        this is less than zero then return */
-      if (exact) {
-       GetTimeOfDay(&tval2);
-       (void)tval_sub( &tvaldiff, &tval2, &tval1);
-      
-       if (tval_sub(&timeout, &timeout, &tvaldiff) <= 0) 
-         break; /* We timed out */
-      }
-      
-      /* Save the time of day as we need to do the select 
-        again (saves a system call) */
-      tval1 = tval2;
     }
 
   /* Return the number we got */
@@ -1927,12 +1841,19 @@ int read_data(int fd,char *buffer,int N)
   int  ret;
   int total=0;  
  
+  smb_read_error = 0;
+
   while (total < N)
     {
       ret = read(fd,buffer + total,N - total);
-
-      if (ret <= 0)
-       return total;
+      if (ret == 0) {
+       smb_read_error = READ_EOF;
+       return 0;
+      }
+      if (ret == -1) {
+       smb_read_error = READ_ERROR;
+       return -1;
+      }
       total += ret;
     }
   return total;
@@ -2056,23 +1977,12 @@ int read_smb_length(int fd,char *inbuf,int timeout)
   while (!ok)
     {
       if (timeout > 0)
-       ok = (read_with_timeout(fd,buffer,4,4,timeout,False) == 4);
-      else     
+       ok = (read_with_timeout(fd,buffer,4,4,timeout) == 4);
+      else 
        ok = (read_data(fd,buffer,4) == 4);
 
       if (!ok)
-       {
-         if (timeout>0)
-           {
-             DEBUG(10,("select timeout (%d)\n", timeout));
-             return(-1);
-           }
-         else
-           {
-             DEBUG(6,("couldn't read from client\n"));
-             exit(1);
-           }
-       }
+       return(-1);
 
       len = smb_len(buffer);
       msg_type = CVAL(buffer,0);
@@ -2099,6 +2009,8 @@ BOOL receive_smb(int fd,char *buffer,int timeout)
 {
   int len,ret;
 
+  smb_read_error = 0;
+
   bzero(buffer,smb_size + 100);
 
   len = read_smb_length(fd,buffer,timeout);
@@ -2113,7 +2025,7 @@ BOOL receive_smb(int fd,char *buffer,int timeout)
 
   ret = read_data(fd,buffer+4,len);
   if (ret != len) {
-    DEBUG(0,("ERROR: Invalid SMB length. Expected %d got %d\n",len,ret));
+    smb_read_error = READ_ERROR;
     return False;
   }
 
index 809ac4d224cf2a0ddb873c962728fea517fe6f8e..54b49edf13bce44728fc78adf1dd97af2ec156f8 100644 (file)
@@ -178,7 +178,7 @@ static int expect(int master,char *expected,char *buf)
     }
 
     /* allow 4 seconds for some output to appear */
-    m = read_with_timeout(master, buf+n, 1, BUFSIZE-1-n, 4000, True);
+    m = read_with_timeout(master, buf+n, 1, BUFSIZE-1-n, 4000);
     if (m < 0) 
       return False;
 
index 13cc8efe5d3326663e3a8f814361317efe5a1352..d463b305c9c6a7ebdd0824517f8cd4aeb7fdbc9e 100644 (file)
@@ -1363,7 +1363,7 @@ int reply_readbraw(char *inbuf, char *outbuf)
             fname,startpos,nread,ret));
 
 #else
-  ret = read_file(fnum,header+4,startpos,nread,nread,-1,False);
+  ret = read_file(fnum,header+4,startpos,nread);
   if (ret < mincount) ret = 0;
 
   _smb_setlen(header,ret);
@@ -1405,7 +1405,7 @@ int reply_lockread(char *inbuf,char *outbuf)
   if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode))
     return (ERROR(eclass,ecode));
 
-  nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False);
+  nread = read_file(fnum,data,startpos,numtoread);
   
   if (nread < 0)
     return(UNIXERROR(ERRDOS,ERRnoaccess));
@@ -1450,7 +1450,7 @@ int reply_read(char *inbuf,char *outbuf)
     return(ERROR(ERRDOS,ERRlock));     
 
   if (numtoread > 0)
-    nread = read_file(fnum,data,startpos,numtoread,numtoread,-1,False);
+    nread = read_file(fnum,data,startpos,numtoread);
   
   if (nread < 0)
     return(UNIXERROR(ERRDOS,ERRnoaccess));
@@ -1495,7 +1495,7 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
 
   if (is_locked(fnum,cnum,smb_maxcnt,smb_offs))
     return(ERROR(ERRDOS,ERRlock));
-  nread = read_file(fnum,data,smb_offs,smb_maxcnt,smb_maxcnt,-1,False);
+  nread = read_file(fnum,data,smb_offs,smb_maxcnt);
   ok = True;
   
   if (nread < 0)
@@ -2934,7 +2934,7 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
     {
       int N = MIN(max_per_packet,tcount-total_read);
   
-      nread = read_file(fnum,data,startpos,N,N,-1,False);
+      nread = read_file(fnum,data,startpos,N);
 
       if (nread <= 0) nread = 0;
 
index 3ececed393a6a6bada83eb4955b3e6cc834529fd..e582ea735ab0b5b80a332858bd73ed4244c4e1fd 100644 (file)
@@ -48,6 +48,8 @@ extern BOOL short_case_preserve;
 extern BOOL case_mangle;
 extern time_t smb_last_time;
 
+extern int smb_read_error;
+
 extern pstring user_socket_options;
 
 connection_struct Connections[MAX_CONNECTIONS];
@@ -1263,41 +1265,35 @@ int seek_file(int fnum,int pos)
 /****************************************************************************
 read from a file
 ****************************************************************************/
-int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact)
+int read_file(int fnum,char *data,int pos,int n)
 {
-  int ret=0;
+  int ret=0,readret;
 
   if (!Files[fnum].can_write)
     {
-      ret = read_predict(Files[fnum].fd,
-                        pos,
-                        data,
-                        NULL,
-                        maxcnt);
+      ret = read_predict(Files[fnum].fd,pos,data,NULL,n);
 
       data += ret;
-      maxcnt -= ret;
-      mincnt = MAX(mincnt-ret,0);
+      n -= ret;
       pos += ret;
     }
 
 #if USE_MMAP
   if (Files[fnum].mmap_ptr)
     {
-      int num = MIN(maxcnt,Files[fnum].mmap_size-pos);
+      int num = MIN(n,Files[fnum].mmap_size-pos);
       if (num > 0)
        {
          memcpy(data,Files[fnum].mmap_ptr+pos,num);
          data += num;
          pos += num;
-         maxcnt -= num;
-         mincnt = MAX(mincnt-num,0);
+         n -= num;
          ret += num;
        }
     }
 #endif
 
-  if (maxcnt <= 0)
+  if (n <= 0)
     return(ret);
 
   if (seek_file(fnum,pos) != pos)
@@ -1306,13 +1302,10 @@ int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL
       return(ret);
     }
   
-  if (maxcnt > 0)
-    ret += read_with_timeout(Files[fnum].fd,
-                            data,
-                            mincnt,
-                            maxcnt,
-                            timeout,
-                            exact);
+  if (n > 0) {
+    readret = read(Files[fnum].fd,data,n);
+    if (readret > 0) ret += readret;
+  }
 
   return(ret);
 }
@@ -3437,9 +3430,14 @@ static void process(void)
          BOOL allidle = True;
          extern int keepalive;
 
-         /* check for socket failure */
-         if (errno) {
-           DEBUG(3,("receive_smb error (%s) exiting\n",strerror(errno)));
+         if (smb_read_error == READ_EOF) {
+           DEBUG(3,("end of file from client\n"));
+           return;
+         }
+
+         if (smb_read_error == READ_ERROR) {
+           DEBUG(3,("receive_smb error (%s) exiting\n",
+                    strerror(errno)));
            return;
          }