Makefile.in: Moved blocking lock code into smbd/blocking.c for link purposes.
authorJeremy Allison <jra@samba.org>
Wed, 19 Aug 1998 01:49:34 +0000 (01:49 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 19 Aug 1998 01:49:34 +0000 (01:49 +0000)
include/includes.h: Added nterr.h.
locking/locking.c: Moved blocking lock code into smbd/blocking.c for link purposes.
smbd/close.c: Added blocking lock removal to file close.
smbd/filename.c: Tidied up unix_convert() so I could read it (:-) in preparation
                 for the stat_cache code.
smbd/nttrans.c: Added WRITE_ATTRIBUTES check.
smbd/reply.c: Fixed multibyte char problem in wildcard mask.
Jeremy.
(This used to be commit 148eaba3dadb1d0bd3ac3ef53da3d9811636e89a)

source3/Makefile.in
source3/include/includes.h
source3/include/proto.h
source3/locking/locking.c
source3/smbd/close.c
source3/smbd/filename.c
source3/smbd/nttrans.c
source3/smbd/reply.c

index dfb2d0e80b51e8b0e69225f1358cbec0d3cc49a1..b9fd30d9ba523348562c62374ce86e50fa1e8626 100644 (file)
@@ -126,7 +126,7 @@ SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
             smbd/groupname.o smbd/ipc.o smbd/mangle.o smbd/negprot.o \
             smbd/message.o smbd/nttrans.o smbd/pipes.o smbd/predict.o \
             smbd/quotas.o smbd/reply.o smbd/ssl.o smbd/trans2.o smbd/uid.o \
-           smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o \
+           smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o smbd/blocking.o \
            smbd/process.o smbd/oplock.o smbd/service.o smbd/error.o
 
 PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/printing.o
index 3fd5f7be087cd44f36a5b0bd0cf9f490d52818be..a2419bc42c1158af4ca517990f4d25f67329d1d2 100644 (file)
@@ -329,6 +329,8 @@ extern int errno;
 #include "kanji.h"
 #include "charset.h"
 
+#include "nterr.h"
+
 #ifndef MAXCODEPAGELINES
 #define MAXCODEPAGELINES 256
 #endif
index 07e3b70dbace60c978a830b651ace2b90bb31de0..9b7267658d3bf15c158b00dce0d96886c608c108 100644 (file)
@@ -480,8 +480,6 @@ char *smb_errstr(char *inbuf);
 
 /*The following definitions come from  locking/locking.c  */
 
-BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num);
-void process_blocking_lock_queue(time_t t);
 BOOL is_locked(files_struct *fsp,connection_struct *conn,
               uint32 count,uint32 offset, int lock_type);
 BOOL do_lock(files_struct *fsp,connection_struct *conn,
@@ -1899,6 +1897,13 @@ uint32 lookup_user_rid(char *user_name, uint32 *rid);
 
 BOOL api_wkssvc_rpc(pipes_struct *p, prs_struct *data);
 
+/*The following definitions come from  smbd/blocking.c  */
+
+BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num);
+void remove_pending_lock_requests_by_fid(files_struct *fsp);
+void remove_pending_lock_requests_by_mid(int mid);
+void process_blocking_lock_queue(time_t t);
+
 /*The following definitions come from  smbd/chgpasswd.c  */
 
 BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root);
index 873e382b4692ceaeedd20144ec00ba646e98a0f1..f5e27317b5cd913a25543519937c0f62e89ad110 100644 (file)
 
 #include "includes.h"
 extern int DEBUGLEVEL;
-extern int Client;
 
 static struct share_ops *share_ops;
 
-#if 0 /* JRATEST - blocking lock code - under development. */
-
-/****************************************************************************
- This is the structure to queue to implement blocking locks.
- notify. It consists of the requesting SMB and the expiry time.
-*****************************************************************************/
-
-typedef struct {
-  ubi_slNode msg_next;
-  time_t expire_time;
-  int lock_num;
-  char *inbuf;
-  int length;
-} blocking_lock_record;
-
-static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0};
-
-/****************************************************************************
- Function to push a blocking lockingX request onto the lock queue.
-****************************************************************************/
-
-BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num)
-{
-  blocking_lock_record *blr;
-  files_struct *fsp = file_fsp(inbuf,smb_vwv2);
-
-  /*
-   * Now queue an entry on the blocking lock queue. We setup
-   * the expiration time here.
-   */
-
-  if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) {
-    DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" ));
-    return False;
-  }
-
-  if((blr->inbuf = (char *)malloc(length)) == NULL) {
-    DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" ));
-    free((char *)blr);
-    return False;
-  }
-
-  memcpy(blr->inbuf, inbuf, length);
-  blr->length = length;
-  blr->lock_num = lock_num;
-  blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout;
-
-  ubi_slAddTail(&blocking_lock_queue, blr);
-
-  DEBUG(3,("push_blocking_lock_request: lock request blocked with expiry time %d \
-for fnum = %d, name = %s\n", blr->expire_time, fsp->fnum, fsp->name ));
-
-  return True;
-}
-
-/****************************************************************************
- Return a blocking lock success SMB.
-*****************************************************************************/
-static void blocking_lock_reply_success(blocking_lock_record *blr)
-{
-  extern int chain_size;
-  extern char *OutBuffer;
-  char *outbuf = OutBuffer;
-  int bufsize = BUFFER_SIZE;
-  char *inbuf = blr->inbuf;
-  files_struct *fsp = file_fsp(inbuf,smb_vwv2);
-  int outsize = 0;
-
-  construct_reply_common(inbuf, outbuf);
-  set_message(outbuf,2,0,True);
-
-  /*
-   * As this message is a lockingX call we must handle
-   * any following chained message correctly.
-   * This is normally handled in construct_reply(),
-   * but as that calls switch_message, we can't use
-   * that here and must set up the chain info manually.
-   */
-
-  chain_size = 0;
-
-  outsize = chain_reply(inbuf,outbuf,blr->length,bufsize);
-
-  outsize += chain_size;
-
-  if(outsize > 4)
-    smb_setlen(outbuf,outsize - 4);
-
-  send_smb(Client,outbuf);
-}
-
-/****************************************************************************
- Return a lock fail error. Undo all the locks we have obtained first.
-*****************************************************************************/
-
-static void blocking_lock_reply_error(blocking_lock_record *blr, int eclass, int32 ecode)
-{
-  extern char *OutBuffer;
-  char *outbuf = OutBuffer;
-  int bufsize = BUFFER_SIZE;
-  char *inbuf = blr->inbuf;
-  files_struct *fsp = file_fsp(inbuf,smb_vwv2);
-  uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
-  uint16 num_locks = SVAL(inbuf,smb_vwv7);
-  uint32 count, offset;
-  int lock_num = blr->lock_num;
-  char *data;
-  int i;
-
-  data = smb_buf(inbuf) + 10*num_ulocks;
-
-  /* 
-   * Data now points at the beginning of the list
-   * of smb_lkrng structs.
-   */
-
-  for(i = blr->lock_num; i >= 0; i--) {
-    count = IVAL(data,SMB_LKLEN_OFFSET(i));
-    offset = IVAL(data,SMB_LKOFF_OFFSET(i));
-    do_unlock(fsp,conn,count,offset,&dummy1,&dummy2);
-  }
-
-  construct_reply_common(inbuf, outbuf);
-  ERROR(eclass,ecode);
-  send_smb(Client,outbuf);
-}
-
-/****************************************************************************
- Attempt to finish off getting all pending blocking locks.
- Returns True if we want to be removed from the list.
-*****************************************************************************/
-
-static BOOL blocking_lock_record_process(blocking_lock_record *blr)
-{
-  char *inbuf = blr->inbuf;
-  unsigned char locktype = CVAL(inbuf,smb_vwv3);
-  files_struct *fsp = file_fsp(inbuf,smb_vwv2);
-  uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
-  uint16 num_locks = SVAL(inbuf,smb_vwv7);
-  uint32 count, offset;
-  int lock_num = blr->lock_num;
-  char *data;
-  int eclass=0;
-  uint32 ecode=0;
-
-  data = smb_buf(inbuf) + 10*num_ulocks;
-
-  /* 
-   * Data now points at the beginning of the list
-   * of smb_lkrng structs.
-   */
-
-  for(; blr->lock_num < num_locks; blr->lock_num++) {
-    count = IVAL(data,SMB_LKLEN_OFFSET(blr->lock_num));
-    offset = IVAL(data,SMB_LKOFF_OFFSET(blr->lock_num));
-    if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
-                &eclass, &ecode))
-      break;
-  }
-
-  if(blr->lock_num == num_locks) {
-
-    /*
-     * Success - we got all the locks.
-     */
-
-    DEBUG(3,("blocking_lock_record_process fnum=%d type=%d num_locks=%d\n",
-          fsp->fnum, (unsigned int)locktype, num_locks) );
-
-    blocking_lock_reply_success(blr);
-    return True;
-
-  } else if((errno != EACCES) && (errno != EAGAIN)) {
-
-    /*
-     * We have other than a "can't get lock" POSIX
-     * error. Free any locks we had and return an error.
-     * Return True so we get dequeued.
-     */
-
-    blocking_lock_reply_error(blr, eclass, ecode);
-    return True;
-  }
-
-  /*
-   * Still can't get all the locks - keep waiting.
-   */
-
-  DEBUG(10,("blocking_lock_record_process: only got %d locks of %d needed for fnum = %d. \
-Waiting....\n", blr->lock_num, num_locks, fsp->fnum));
-
-  return False;
-}
-
-/****************************************************************************
- Process the blocking lock queue. Note that this is only called as root.
-*****************************************************************************/
-
-void process_blocking_lock_queue(time_t t)
-{
-  blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue );
-  blocking_lock_record *prev = NULL;
-
-  if(blr == NULL)
-    return;
-
-  /*
-   * Go through the queue and see if we can get any of the locks.
-   */
-
-  while(blr != NULL) {
-    files_struct *fsp = NULL;
-    uint16 vuid;
-
-    /*
-     * Ensure we don't have any old chain_fnum values
-     * sitting around....
-     */
-    file_chain_reset();
-
-    fsp = file_fsp(blr->inbuf,smb_vwv2);
-    vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID :
-                  SVAL(blr->inbuf,smb_uid);
-
-    DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n",
-          fsp->fnum, fsp->name ));
-
-    if((blr->expire_time != -1) && (blr->expire_time > t)) {
-      /*
-       * Lock expired - throw away all previously
-       * obtained locks and return lock error.
-       */
-      DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",
-          fsp->fnum, fsp->name ));
-
-      blocking_lock_reply_error(blr,ERRSRV,ERRaccess);
-      free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
-      blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
-      continue;
-    }
-
-    if(!become_user(conn,vuid)) {
-      DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",
-            vuid ));
-      /*
-       * Remove the entry and return an error to the client.
-       */
-      blocking_lock_reply_error(blr,ERRSRV,ERRaccess);
-      free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
-      blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
-      continue;
-    }
-
-    if(!become_service(conn,True)) {
-      DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
-      /*
-       * Remove the entry and return an error to the client.
-       */
-      blocking_lock_reply_error(blr,ERRSRV,ERRaccess);
-      free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
-      blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
-      unbecome_user();
-      continue;
-    }
-
-    /*
-     * Go through the remaining locks and try and obtain them.
-     * The call returns True if all locks were obtained successfully
-     * and False if we still need to wait.
-     */
-
-    if(blocking_lock_record_process(blr)) {
-      free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
-      blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
-      unbecome_user();
-      continue;
-    }
-
-    unbecome_user();
-
-    /*
-     * Move to the next in the list.
-     */
-    prev = blr;
-    blr = (blocking_lock_record *)ubi_slNext(blr);
-  }
-}
-#endif /* JRATEST */
-
 /****************************************************************************
  Utility function to map a lock type correctly depending on the real open
  mode of a file.
index 9bc0a89338f19ccc5aae62e544be66aa1190b07a..b8063ca3f4222c164f653ff17befd65ffe6467f7 100644 (file)
@@ -142,6 +142,8 @@ void close_file(files_struct *fsp, BOOL normal_close)
                string_free(&fsp->fsp_name);
        }
 
+       remove_pending_lock_requests_by_fid(fsp);
+
        file_free(fsp);
 }
 
@@ -151,10 +153,6 @@ void close_file(files_struct *fsp, BOOL normal_close)
   
 void close_directory(files_struct *fsp)
 {
-       /* TODO - walk the list of pending
-          change notify requests and free
-          any pertaining to this fsp. */
-
        remove_pending_change_notify_requests_by_fid(fsp);
 
        /*
index a6a9e7e7f010986ee5ac24be5c92eb27e371a6d2..ab5851fb5e442b9dbee9e7f515d9f859bf9e85c3 100644 (file)
@@ -102,6 +102,7 @@ used to pick the correct error code to return between ENOENT and ENOTDIR
 as Windows applications depend on ERRbadpath being returned if a component
 of a pathname does not exist.
 ****************************************************************************/
+
 BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component, BOOL *bad_path)
 {
   struct stat st;
@@ -115,17 +116,24 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
   if(saved_last_component)
     *saved_last_component = 0;
 
-  /* convert to basic unix format - removing \ chars and cleaning it up */
+  /* 
+   * Convert to basic unix format - removing \ chars and cleaning it up.
+   */
+
   unix_format(name);
   unix_clean_name(name);
 
-  /* names must be relative to the root of the service - trim any leading /.
-   also trim trailing /'s */
+  /* 
+   * Names must be relative to the root of the service - trim any leading /.
+   * also trim trailing /'s.
+   */
+
   trim_string(name,"/","/");
 
   /*
    * Ensure saved_last_component is valid even if file exists.
    */
+
   if(saved_last_component) {
     end = strrchr(name, '/');
     if(end)
@@ -138,23 +146,30 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
       (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
     strnorm(name);
 
-  /* check if it's a printer file */
-  if (conn->printer)
-    {
-      if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
-       {
-         char *s;
-         fstring name2;
-         slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine);
-         /* sanitise the name */
-         for (s=name2 ; *s ; s++)
-           if (!issafe(*s)) *s = '_';
-         pstrcpy(name,(char *)mktemp(name2));    
-       }      
-      return(True);
-    }
+  /* 
+   * Check if it's a printer file.
+   */
+  if (conn->printer) {
+    if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) {
+      char *s;
+      fstring name2;
+      slprintf(name2,sizeof(name2)-1,"%.6s.XXXXXX",remote_machine);
+
+      /* 
+       * Sanitise the name.
+       */
+
+      for (s=name2 ; *s ; s++)
+        if (!issafe(*s)) *s = '_';
+          pstrcpy(name,(char *)mktemp(name2));   
+    }      
+    return(True);
+  }
+
+  /* 
+   * stat the name - if it exists then we are all done!
+   */
 
-  /* stat the name - if it exists then we are all done! */
   if (sys_stat(name,&st) == 0)
     return(True);
 
@@ -162,109 +177,144 @@ BOOL unix_convert(char *name,connection_struct *conn,char *saved_last_component,
 
   DEBUG(5,("unix_convert(%s)\n",name));
 
-  /* a special case - if we don't have any mangling chars and are case
-     sensitive then searching won't help */
+  /* 
+   * A special case - if we don't have any mangling chars and are case
+   * sensitive then searching won't help.
+   */
+
   if (case_sensitive && !is_mangled(name) && 
       !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
     return(False);
 
-  /* now we need to recursively match the name against the real 
-     directory structure */
+  /* 
+   * Now we need to recursively match the name against the real 
+   * directory structure.
+   */
 
   start = name;
   while (strncmp(start,"./",2) == 0)
     start += 2;
 
-  /* now match each part of the path name separately, trying the names
-     as is first, then trying to scan the directory for matching names */
-  for (;start;start = (end?end+1:(char *)NULL)) 
-    {
-      /* pinpoint the end of this section of the filename */
+  /* 
+   * Match each part of the path name separately, trying the names
+   * as is first, then trying to scan the directory for matching names.
+   */
+
+  for (;start;start = (end?end+1:(char *)NULL)) {
+      /* 
+       * Pinpoint the end of this section of the filename.
+       */
       end = strchr(start, '/');
 
-      /* chop the name at this point */
-      if (end)         *end = 0;
+      /* 
+       * Chop the name at this point.
+       */
+      if (end) 
+        *end = 0;
 
       if(saved_last_component != 0)
         pstrcpy(saved_last_component, end ? end + 1 : start);
 
-      /* check if the name exists up to this point */
-      if (sys_stat(name, &st) == 0) 
-       {
-         /* it exists. it must either be a directory or this must be
-            the last part of the path for it to be OK */
-         if (end && !(st.st_mode & S_IFDIR)) 
-           {
-             /* an intermediate part of the name isn't a directory */
-             DEBUG(5,("Not a dir %s\n",start));
-             *end = '/';
-             return(False);
-           }
-       }
-      else 
-       {
-         pstring rest;
-
-         *rest = 0;
-
-         /* remember the rest of the pathname so it can be restored
-            later */
-         if (end) pstrcpy(rest,end+1);
-
-         /* try to find this part of the path in the directory */
-         if (strchr(start,'?') || strchr(start,'*') ||
-             !scan_directory(dirpath, start, conn, end?True:False))
-           {
-             if (end) 
-               {
-                 /* an intermediate part of the name can't be found */
-                 DEBUG(5,("Intermediate not found %s\n",start));
-                 *end = '/';
-                  /* We need to return the fact that the intermediate
-                     name resolution failed. This is used to return an
-                     error of ERRbadpath rather than ERRbadfile. Some
-                     Windows applications depend on the difference between
-                     these two errors.
-                   */
-                  *bad_path = True;
-                 return(False);
-               }
+      /* 
+       * Check if the name exists up to this point.
+       */
+      if (sys_stat(name, &st) == 0) {
+        /*
+         * It exists. it must either be a directory or this must be
+         * the last part of the path for it to be OK.
+         */
+        if (end && !(st.st_mode & S_IFDIR)) {
+          /*
+           * An intermediate part of the name isn't a directory.
+            */
+          DEBUG(5,("Not a dir %s\n",start));
+          *end = '/';
+          return(False);
+        }
+      } else {
+        pstring rest;
+
+        *rest = 0;
+
+        /*
+         * Remember the rest of the pathname so it can be restored
+         * later.
+         */
+
+        if (end)
+          pstrcpy(rest,end+1);
+
+        /*
+         * Try to find this part of the path in the directory.
+         */
+        if (strchr(start,'?') || strchr(start,'*') ||
+            !scan_directory(dirpath, start, conn, end?True:False)) {
+          if (end) {
+            /*
+             * An intermediate part of the name can't be found.
+             */
+            DEBUG(5,("Intermediate not found %s\n",start));
+            *end = '/';
+
+            /* 
+             * We need to return the fact that the intermediate
+             * name resolution failed. This is used to return an
+             * error of ERRbadpath rather than ERRbadfile. Some
+             * Windows applications depend on the difference between
+             * these two errors.
+             */
+            *bad_path = True;
+            return(False);
+          }
              
-             /* just the last part of the name doesn't exist */
-             /* we may need to strupper() or strlower() it in case
-                this conversion is being used for file creation 
-                purposes */
-             /* if the filename is of mixed case then don't normalise it */
-             if (!case_preserve && 
-                 (!strhasupper(start) || !strhaslower(start)))         
-               strnorm(start);
-
-             /* check on the mangled stack to see if we can recover the 
-                base of the filename */
-             if (is_mangled(start))
-               check_mangled_cache( start );
-
-             DEBUG(5,("New file %s\n",start));
-             return(True); 
-           }
-
-         /* restore the rest of the string */
-         if (end) 
-           {
-             pstrcpy(start+strlen(start)+1,rest);
-             end = start + strlen(start);
-           }
-       }
+          /* 
+           * Just the last part of the name doesn't exist.
+              * We may need to strupper() or strlower() it in case
+           * this conversion is being used for file creation 
+           * purposes. If the filename is of mixed case then 
+           * don't normalise it.
+           */
+
+          if (!case_preserve && (!strhasupper(start) || !strhaslower(start)))          
+            strnorm(start);
+
+          /*
+           * check on the mangled stack to see if we can recover the 
+           * base of the filename.
+           */
+
+          if (is_mangled(start))
+            check_mangled_cache( start );
+
+          DEBUG(5,("New file %s\n",start));
+          return(True); 
+        }
 
-      /* add to the dirpath that we have resolved so far */
-      if (*dirpath) pstrcat(dirpath,"/");
+      /* 
+       * Restore the rest of the string.
+       */
+      if (end) {
+        pstrcpy(start+strlen(start)+1,rest);
+        end = start + strlen(start);
+      }
+    } /* end else */
+
+    /* 
+     * Add to the dirpath that we have resolved so far.
+     */
+    if (*dirpath) pstrcat(dirpath,"/");
       pstrcat(dirpath,start);
 
-      /* restore the / that we wiped out earlier */
-      if (end) *end = '/';
-    }
+    /* 
+     * Restore the / that we wiped out earlier.
+     */
+    if (end)
+      *end = '/';
+  }
   
-  /* the name has been resolved */
+  /* 
+   * The name has been resolved.
+   */
   DEBUG(5,("conversion finished %s\n",name));
   return(True);
 }
index b5ed42fbb3cc90b1d0947da1239fe07015b6e1f2..9a9fc51d36e2ca66d8629c497fb439f84944aa72 100644 (file)
@@ -321,7 +321,7 @@ static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 fi
   }
 
   if (smb_open_mode == -1) {
-    if(desired_access & DELETE_ACCESS)
+    if(desired_access & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES))
       smb_open_mode = 2;
     else if( desired_access & FILE_EXECUTE)
       smb_open_mode = 0;
@@ -909,12 +909,11 @@ int reply_ntcancel(connection_struct *conn,
 {
        /*
         * Go through and cancel any pending change notifies.
-        * TODO: When we add blocking locks we will add cancel
-        * for them here too.
         */
        
        int mid = SVAL(inbuf,smb_mid);
        remove_pending_change_notify_requests_by_mid(mid);
+       remove_pending_lock_requests_by_mid(mid);
        
        DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid));
 
index 6b91d9d152aaa8c468bbaf24916f1f2b70cdaa8e..28fed8bc0436768ca782398c03e0773bb68ac6bb 100644 (file)
@@ -1051,14 +1051,24 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
   mask_convert(mask);
 
   {
-    for (p=mask; *p; p++)
+    int skip;
+    p = mask;
+    while(*p)
+    {
+      if((skip = skip_multibyte_char( *p )) != 0 )
       {
-       if (*p != '?' && *p != '*' && !isdoschar(*p))
-         {
-           DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
-           *p = '?';
-         }
+        p += skip;
       }
+      else
+      {
+        if (*p != '?' && *p != '*' && !isdoschar(*p))
+        {
+          DEBUG(5,("Invalid char [%c] in search mask?\n",*p));
+          *p = '?';
+        }
+        p++;
+      }
+    }
   }
 
   if (!strchr(mask,'.') && strlen(mask)>8)
@@ -3569,8 +3579,8 @@ dev = %x, inode = %x\n",
     count = IVAL(data,SMB_LKLEN_OFFSET(i)); 
     offset = IVAL(data,SMB_LKOFF_OFFSET(i)); 
     if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK),
-                &eclass, &ecode))
-#if 0 /* JRATEST - blocking lock code. */
+                &eclass, &ecode)) {
+#if 0 /* JRATEST */
       if((ecode == ERRlock) && (lock_timeout != 0)) {
         /*
          * A blocking lock was requested. Package up
@@ -3579,8 +3589,10 @@ dev = %x, inode = %x\n",
          */
         if(push_blocking_lock_request(inbuf, length, lock_timeout, i))
           return -1;
+      }
 #endif /* JRATEST */
       break;
+    }
   }
 
   /* If any of the above locks failed, then we must unlock