clientgen.c: Added cli_mv() (used in a recent torture test).
authorJeremy Allison <jra@samba.org>
Sun, 30 Nov 1997 02:58:34 +0000 (02:58 +0000)
committerJeremy Allison <jra@samba.org>
Sun, 30 Nov 1997 02:58:34 +0000 (02:58 +0000)
reply.c: Changed reply_open_and_X to split out the oplock
request bits from core and extended and if an oplock was granted only set
the corresponding bit on reply.
server.c: Added code to dynamically allocate i/o buffers in oplock_break
(prevents recursion problems) , also made reset of sent_oplock_break
explicit.
Jeremy.

source/include/proto.h
source/libsmb/clientgen.c
source/smbd/reply.c
source/smbd/server.c

index c47b7582f308d9a6e79e9285083299f4e72d442b..7302fb4998e1d10436287ec5a5b795eec3ae1870 100644 (file)
@@ -65,6 +65,7 @@ BOOL cli_session_setup(struct cli_state *cli,
 BOOL cli_send_tconX(struct cli_state *cli, 
                    char *share, char *dev, char *pass, int passlen);
 BOOL cli_tdis(struct cli_state *cli);
+BOOL cli_mv(struct cli_state *cli, char *fname_src, char *fname_dst);
 BOOL cli_unlink(struct cli_state *cli, char *fname);
 BOOL cli_mkdir(struct cli_state *cli, char *dname);
 BOOL cli_rmdir(struct cli_state *cli, char *dname);
index 1bd55cffe864fc8c176a4a59bc7a96ce8f271a8d..69e940845ce66641024f9187c33c7272962a84f4 100644 (file)
@@ -573,6 +573,43 @@ BOOL cli_tdis(struct cli_state *cli)
        return CVAL(cli->inbuf,smb_rcls) == 0;
 }
 
+/****************************************************************************
+rename a file
+****************************************************************************/
+BOOL cli_mv(struct cli_state *cli, char *fname_src, char *fname_dst)
+{
+        char *p;
+
+        bzero(cli->outbuf,smb_size);
+        bzero(cli->inbuf,smb_size);
+
+        set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
+
+        CVAL(cli->outbuf,smb_com) = SMBmv;
+        SSVAL(cli->outbuf,smb_tid,cli->cnum);
+        cli_setup_packet(cli);
+
+        SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
+
+        p = smb_buf(cli->outbuf);
+        *p++ = 4;
+        strcpy(p,fname_src);
+        p = skip_string(p,1);
+        *p++ = 4;
+        strcpy(p,fname_dst);
+
+        send_smb(cli->fd,cli->outbuf);
+        if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
+                return False;
+        }
+
+        if (CVAL(cli->inbuf,smb_rcls) != 0) {
+                return False;
+        }
+
+        return True;
+}
+
 /****************************************************************************
 delete a file
 ****************************************************************************/
index ec94ab0552a4bc911502f9db3b509455530b4811..06b96b13d9f4b76076d82e4e1304fbb7291c1976 100644 (file)
@@ -1257,7 +1257,11 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   int fnum = -1;
   int smb_mode = SVAL(inbuf,smb_vwv3);
   int smb_attr = SVAL(inbuf,smb_vwv5);
-  BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
+  /* Breakout the oplock request bits so we can set the
+     reply bits separately. */
+  BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
+  BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+  BOOL oplock_request = ex_oplock_request | core_oplock_request;
 #if 0
   int open_flags = SVAL(inbuf,smb_vwv2);
   int smb_sattr = SVAL(inbuf,smb_vwv4); 
@@ -1324,13 +1328,29 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     return(ERROR(ERRDOS,ERRnoaccess));
   }
 
-  if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+  /* If the caller set the extended oplock request bit
+     and we granted one (by whatever means) - set the
+     correct bit for extended oplock reply.
+   */
+
+  if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
     smb_action |= EXTENDED_OPLOCK_GRANTED;
-    CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   }
 
-  if(fsp->granted_oplock) {
+  if(ex_oplock_request && fsp->granted_oplock) {
     smb_action |= EXTENDED_OPLOCK_GRANTED;
+  }
+
+  /* If the caller set the core oplock request bit
+     and we granted one (by whatever means) - set the
+     correct bit for core oplock reply.
+   */
+
+  if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+    CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+  }
+
+  if(core_oplock_request && fsp->granted_oplock) {
     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   }
 
index 77c8fc319f0d1491bcc0c1a0072e2f0d216e9675..9ca4ab5b7816907f6f76b3a9e77c11086a61b01b 100644 (file)
@@ -1326,6 +1326,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
       fsp->print_file = Connections[cnum].printer;
       fsp->modified = False;
       fsp->granted_oplock = False;
+      fsp->sent_oplock_break = False;
       fsp->cnum = cnum;
       string_set(&fsp->name,dos_to_unix(fname,False));
       fsp->wbmpx_ptr = NULL;      
@@ -1476,6 +1477,8 @@ void close_file(int fnum, BOOL normal_close)
   if(fs_p->granted_oplock == True)
     global_oplocks_open--;
 
+  fs_p->sent_oplock_break = False;
+
   DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
           timestring(),Connections[cnum].user,fs_p->name,
           Connections[cnum].num_files_open));
@@ -2773,22 +2776,6 @@ BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval)
   DEBUG(3,("%s oplock_break: called for dev = %x, inode = %x. Current \
 global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open));
 
-  if(inbuf == NULL)
-  {
-    inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
-    if(inbuf == NULL) {
-      DEBUG(0,("oplock_break: malloc fail for input buffer.\n"));
-      return False;
-    } 
-    outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
-    if(outbuf == NULL) {
-      DEBUG(0,("oplock_break: malloc fail for output buffer.\n"));
-      free(inbuf);
-      inbuf = NULL;
-      return False;
-    }
-  } 
-
   /* We need to search the file open table for the
      entry containing this dev and inode, and ensure
      we have an oplock on it. */
@@ -2831,16 +2818,35 @@ allowing break to succeed.\n", timestring(), dev, inode, fnum));
   /* mark the oplock break as sent - we don't want to send twice! */
   if (fsp->sent_oplock_break)
   {
-    DEBUG(0,("%s ERROR: oplock_break already sent for file %s (fnum = %d, dev = %x, inode = %x)\n", timestring(), fsp->name, fnum, dev, inode));
-    return True;
-  }
+    DEBUG(0,("%s oplock_break: ERROR: oplock_break already sent for file %s (fnum = %d, dev = %x, inode = %x)\n", timestring(), fsp->name, fnum, dev, inode));
 
-  fsp->sent_oplock_break = True;
+    /* We have to fail the open here as we cannot send another oplock break on this
+       file whilst we are awaiting a response from the client - neither can we
+       allow another open to succeed while we are waiting for the client. */
+    return False;
+  }
 
   /* Now comes the horrid part. We must send an oplock break to the client,
      and then process incoming messages until we get a close or oplock release.
+     At this point we know we need a new inbuf/outbuf buffer pair.
+     We cannot use these staticaly as we may recurse into here due to
+     messages crossing on the wire.
    */
 
+  if((inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL)
+  {
+    DEBUG(0,("oplock_break: malloc fail for input buffer.\n"));
+    return False;
+  }
+
+  if((outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL)
+  {
+    DEBUG(0,("oplock_break: malloc fail for output buffer.\n"));
+    free(inbuf);
+    inbuf = NULL;
+    return False;
+  }
+
   /* Prepare the SMBlockingX message. */
   bzero(outbuf,smb_size);
   set_message(outbuf,8,0,True);
@@ -2858,6 +2864,9 @@ allowing break to succeed.\n", timestring(), dev, inode, fnum));
  
   send_smb(Client, outbuf);
 
+  /* Remember we just sent an oplock break on this file. */
+  fsp->sent_oplock_break = True;
+
   /* We need this in case a readraw crosses on the wire. */
   global_oplock_break = True;
  
@@ -2909,6 +2918,10 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode));
     }
   }
 
+  /* Free the buffers we've been using to recurse. */
+  free(inbuf);
+  free(outbuf);
+
   /* We need this in case a readraw crossed on the wire. */
   if(global_oplock_break)
     global_oplock_break = False;
@@ -2932,6 +2945,7 @@ inode = %x).\n", timestring(), fsp->name, fnum, dev, inode));
        from the sharemode. */
     /* Paranoia.... */
     fsp->granted_oplock = False;
+    fsp->sent_oplock_break = False;
     global_oplocks_open--;
   }