rpc_parse/parse_misc.c : defined a new BUFFER5 struct
[kai/samba-autobuild/.git] / source3 / smbd / nttrans.c
index 596d15c2c778a5961ee1ac78b2f05e65e1f6a272..5c26c7f57809635e58a7a9d717e05e38ae46903b 100644 (file)
@@ -25,7 +25,6 @@
 extern int DEBUGLEVEL;
 extern int Protocol;
 extern int Client;  
-extern int oplock_sock;
 extern int smb_read_error;
 extern int global_oplock_break;
 extern int chain_size;
@@ -33,9 +32,12 @@ extern BOOL case_sensitive;
 extern BOOL case_preserve;
 extern BOOL short_case_preserve;
 
+static void remove_pending_change_notify_requests_by_mid(int mid);
+
 static char *known_nt_pipes[] = {
   "\\LANMAN",
   "\\srvsvc",
+  "\\svcctl",
   "\\samr",
   "\\wkssvc",
   "\\NETLOGON",
@@ -43,6 +45,8 @@ static char *known_nt_pipes[] = {
   "\\ntsvcs",
   "\\lsass",
   "\\lsarpc",
+  "\\winreg",
+  "\\spoolss",
   NULL
 };
 
@@ -230,6 +234,39 @@ static int send_nt_replies(char *outbuf, int bufsize, char *params,
   return 0;
 }
 
+/****************************************************************************
+ (Hopefully) temporary call to fix bugs in NT5.0beta2. This OS sends unicode
+ strings in NT calls AND DOESN'T SET THE UNICODE BIT !!!!!!!
+****************************************************************************/
+
+static void my_wcstombs(char *dst, uint16 *src, size_t len)
+{
+  size_t i;
+
+  for(i = 0; i < len; i++)
+    dst[i] = (char)SVAL(src,i*2);
+}
+
+static void get_filename( char *fname, char *inbuf, int data_offset, int data_len, int fname_len)
+{
+  if(data_len - fname_len > 1) {
+    /*
+     * NT 5.0 Beta 2 has kindly sent us a UNICODE string
+     * without bothering to set the unicode bit. How kind.
+     *
+     * Firstly - ensure that the data offset is aligned
+     * on a 2 byte boundary - add one if not.
+     */
+    fname_len = fname_len/2;
+    if(data_offset & 1)
+      data_offset++;
+    my_wcstombs( fname, (uint16 *)(inbuf+data_offset), fname_len);
+  } else {
+    StrnCpy(fname,inbuf+data_offset,fname_len);
+  }
+  fname[fname_len] = '\0';
+}
+
 /****************************************************************************
  Save case statics.
 ****************************************************************************/
@@ -277,87 +314,160 @@ static void restore_case_semantics(uint32 file_attributes)
 
 static int map_create_disposition( uint32 create_disposition)
 {
+  int ret;
+
   switch( create_disposition ) {
   case FILE_CREATE:
     /* create if not exist, fail if exist */
-    return 0x10;
+    ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_FAIL);
+    break;
   case FILE_SUPERSEDE:
   case FILE_OVERWRITE_IF:
     /* create if not exist, trunc if exist */
-    return 0x12;
+    ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE);
+    break;
   case FILE_OPEN:
     /* fail if not exist, open if exists */
-    return 0x1;
+    ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN);
+    break;
   case FILE_OPEN_IF:
     /* create if not exist, open if exists */
-    return 0x11;
+    ret = (FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_OPEN);
+    break;
   case FILE_OVERWRITE:
     /* fail if not exist, truncate if exists */
-    return 0x2;
+    ret = (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE);
+    break;
   default:
     DEBUG(0,("map_create_disposition: Incorrect value for create_disposition = %d\n",
              create_disposition ));
     return -1;
   }
+
+  DEBUG(10,("map_create_disposition: Mapped create_disposition %lx to %x\n",
+        (unsigned long)create_disposition, ret ));
+
+  return ret;
 }
 
 /****************************************************************************
  Utility function to map share modes.
 ****************************************************************************/
 
-static int map_share_mode( uint32 desired_access, uint32 share_access, uint32 file_attributes)
+static int map_share_mode( char *fname, uint32 desired_access, uint32 share_access, uint32 file_attributes)
 {
   int smb_open_mode = -1;
 
   switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA) ) {
   case FILE_READ_DATA:
-    smb_open_mode = 0;
+    smb_open_mode = DOS_OPEN_RDONLY;
     break;
   case FILE_WRITE_DATA:
-    smb_open_mode = 1;
+    smb_open_mode = DOS_OPEN_WRONLY;
     break;
   case FILE_READ_DATA|FILE_WRITE_DATA:
-    smb_open_mode = 2;
+    smb_open_mode = DOS_OPEN_RDWR;
     break;
   }
 
+  /*
+   * NB. For DELETE_ACCESS we should really check the
+   * directory permissions, as that is what controls
+   * delete, and for WRITE_DAC_ACCESS we should really
+   * check the ownership, as that is what controls the
+   * chmod. Note that this is *NOT* a security hole (this
+   * note is for you, Andrew) as we are not *allowing*
+   * the access at this point, the actual unlink or
+   * chown or chmod call would do this. We are just helping
+   * clients out by telling them if they have a hope
+   * of any of this succeeding. POSIX acls may still
+   * deny the real call. JRA.
+   */
+
   if (smb_open_mode == -1) {
-    if(desired_access & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES))
-      smb_open_mode = 2;
-    else if( desired_access & FILE_EXECUTE)
-      smb_open_mode = 0;
+    if(desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|
+                              FILE_EXECUTE|FILE_READ_ATTRIBUTES|
+                              FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS))
+      smb_open_mode = DOS_OPEN_RDONLY;
     else {
-      DEBUG(0,("map_share_mode: Incorrect value for desired_access = %x\n",
-             desired_access));
+      DEBUG(0,("map_share_mode: Incorrect value %lx for desired_access to file %s\n",
+             (unsigned long)desired_access, fname));
       return -1;
     }
   }
 
-  /* Add in the requested share mode - ignore FILE_SHARE_DELETE for now. */
+  /*
+   * Set the special bit that means allow share delete.
+   * This is held outside the normal share mode bits at 1<<15.
+   * JRA.
+   */
+
+  if(share_access & FILE_SHARE_DELETE)
+    smb_open_mode |= ALLOW_SHARE_DELETE;
+
+  /* Add in the requested share mode. */
   switch( share_access & (FILE_SHARE_READ|FILE_SHARE_WRITE)) {
   case FILE_SHARE_READ:
-    smb_open_mode |= (DENY_WRITE<<4);
+    smb_open_mode |= SET_DENY_MODE(DENY_WRITE);
     break;
   case FILE_SHARE_WRITE:
-    smb_open_mode |= (DENY_READ<<4);
+    smb_open_mode |= SET_DENY_MODE(DENY_READ);
     break;
   case (FILE_SHARE_READ|FILE_SHARE_WRITE):
-    smb_open_mode |= (DENY_NONE<<4);
+    smb_open_mode |= SET_DENY_MODE(DENY_NONE);
     break;
   case FILE_SHARE_NONE:
-    smb_open_mode |= (DENY_ALL<<4);
+    smb_open_mode |= SET_DENY_MODE(DENY_ALL);
     break;
   }
 
   /*
-   * Handle a O_SYNC request.
+   * Handle an O_SYNC request.
    */
+
   if(file_attributes & FILE_FLAG_WRITE_THROUGH)
-    smb_open_mode |= (1<<14);
+    smb_open_mode |= FILE_SYNC_OPENMODE;
 
+  DEBUG(10,("map_share_mode: Mapped desired access %lx, share access %lx, file attributes %lx \
+to open_mode %x\n", (unsigned long)desired_access, (unsigned long)share_access,
+                    (unsigned long)file_attributes, smb_open_mode ));
   return smb_open_mode;
 }
 
+/*
+ * This is a *disgusting* hack.
+ * This is *so* bad that even I'm embarrassed (and I
+ * have no shame). Here's the deal :
+ * Until we get the correct SPOOLSS code into smbd
+ * then when we're running with NT SMB support then
+ * NT makes this call with a level of zero, and then
+ * immediately follows it with an open request to
+ * the \\SRVSVC pipe. If we allow that open to
+ * succeed then NT barfs when it cannot open the
+ * \\SPOOLSS pipe immediately after and continually
+ * whines saying "Printer name is invalid" forever
+ * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
+ * to fail, then NT downgrades to using the downlevel code
+ * and everything works as well as before. I hate
+ * myself for adding this code.... JRA.
+ *
+ * The HACK_FAIL_TIME define allows only a 2
+ * second window for this to occur, just in
+ * case...
+ */
+
+static BOOL fail_next_srvsvc = False;
+static time_t fail_time;
+#define HACK_FAIL_TIME 2 /* In seconds. */
+
+void fail_next_srvsvc_open(void)
+{
+  fail_next_srvsvc = True;
+  fail_time = time(NULL);
+  DEBUG(10,("fail_next_srvsvc_open: setting up timeout close of \\srvsvc pipe for print fix.\n"));
+}
+
 /****************************************************************************
  Reply to an NT create and X call on a pipe.
 ****************************************************************************/
@@ -376,6 +486,26 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
                if( strequal(fname,known_nt_pipes[i]))
                        break;
     
+       /*
+        * HACK alert.... see above - JRA.
+        */
+
+       if(fail_next_srvsvc && (time(NULL) > fail_time + HACK_FAIL_TIME)) {
+               fail_next_srvsvc = False;
+               fail_time = (time_t)0;
+               DEBUG(10,("nt_open_pipe: End of timeout close of \\srvsvc pipe for print fix.\n"));
+       }
+
+       if(fail_next_srvsvc && strequal(fname, "\\srvsvc")) {
+               fail_next_srvsvc = False;
+               DEBUG(10,("nt_open_pipe: Deliberately failing open of \\srvsvc pipe for print fix.\n"));
+               return(ERROR(ERRSRV,ERRaccess));
+       }
+
+       /*
+        * End hack alert.... see above - JRA.
+        */
+
        if ( known_nt_pipes[i] == NULL )
                return(ERROR(ERRSRV,ERRaccess));
     
@@ -396,6 +526,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
 /****************************************************************************
  Reply to an NT create and X call.
 ****************************************************************************/
+
 int reply_ntcreate_and_X(connection_struct *conn,
                         char *inbuf,char *outbuf,int length,int bufsize)
 {  
@@ -405,18 +536,21 @@ int reply_ntcreate_and_X(connection_struct *conn,
        uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes);
        uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
        uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
+       uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions);
        uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)),
                               ((uint32)sizeof(fname)-1));
+       uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid);
        int smb_ofun;
        int smb_open_mode;
        int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
        /* Breakout the oplock request bits so we can set the
           reply bits separately. */
        int oplock_request = 0;
-       int unixmode, pnum = -1;
-       int fmode=0,mtime=0,rmode=0;
-       off_t file_len = 0;
-       struct stat sbuf;
+    mode_t unixmode;
+       int pnum = -1;
+       int fmode=0,rmode=0;
+       SMB_OFF_T file_len = 0;
+       SMB_STRUCT_STAT sbuf;
        int smb_action = 0;
        BOOL bad_path = False;
        files_struct *fsp=NULL;
@@ -430,27 +564,61 @@ int reply_ntcreate_and_X(connection_struct *conn,
        if((smb_ofun = map_create_disposition( create_disposition )) == -1)
                return(ERROR(ERRDOS,ERRbadaccess));
 
-       /*
-        * Now contruct the smb_open_mode value from the desired access
-        * and the share access.
-        */
-       
-       if((smb_open_mode = map_share_mode(desired_access, 
-                                          share_access, 
-                                          file_attributes)) == -1) {
-               return(ERROR(ERRDOS,ERRbadaccess));
-       }
-
        /*
         * Get the file name.
         */
-       StrnCpy(fname,smb_buf(inbuf),fname_len);
-       fname[fname_len] = '\0';
+
+    if(root_dir_fid != 0) {
+      /*
+       * This filename is relative to a directory fid.
+       */
+      files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid);
+      size_t dir_name_len;
+
+      if(!dir_fsp || !dir_fsp->is_directory)
+        return(ERROR(ERRDOS,ERRbadfid));
+
+      /*
+       * Copy in the base directory name.
+       */
+
+      pstrcpy( fname, dir_fsp->fsp_name );
+      dir_name_len = strlen(fname);
+
+      /*
+       * Ensure it ends in a '\'.
+       */
+
+      if(fname[dir_name_len-1] != '\\' && fname[dir_name_len-1] != '/') {
+        pstrcat(fname, "\\");
+        dir_name_len++;
+      }
+
+      if(fname_len + dir_name_len >= sizeof(pstring))
+        return(ERROR(ERRSRV,ERRfilespecs));
+
+      get_filename(&fname[dir_name_len], inbuf, smb_buf(inbuf)-inbuf, 
+                   smb_buflen(inbuf),fname_len);
+#if 0
+      StrnCpy(&fname[dir_name_len], smb_buf(inbuf),fname_len);
+      fname[dir_name_len+fname_len] = '\0';
+#endif
+
+    } else {
+      
+      get_filename(fname, inbuf, smb_buf(inbuf)-inbuf, 
+                   smb_buflen(inbuf),fname_len);
+
+#if 0
+         StrnCpy(fname,smb_buf(inbuf),fname_len);
+      fname[fname_len] = '\0';
+#endif
+    }
        
        /* If it's an IPC, use the pipe handler. */
 
-       if (IS_IPC(conn)) {
-
+       if (IS_IPC(conn) && lp_nt_pipe_support() && lp_security() != SEC_SHARE)
+       {
                int ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum);
                if(ret != 0)
                        return ret;
@@ -480,6 +648,17 @@ int reply_ntcreate_and_X(connection_struct *conn,
                return chain_reply(inbuf,outbuf,length,bufsize);
        }
 
+       /*
+        * Now contruct the smb_open_mode value from the filename, 
+     * desired access and the share access.
+        */
+       
+       if((smb_open_mode = map_share_mode(fname, desired_access, 
+                                          share_access, 
+                                          file_attributes)) == -1) {
+               return(ERROR(ERRDOS,ERRbadaccess));
+       }
+
        /*
         * Ordinary file or directory.
         */
@@ -490,7 +669,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
                
        set_posix_case_semantics(file_attributes);
                
-       unix_convert(fname,conn,0,&bad_path);
+       unix_convert(fname,conn,0,&bad_path,NULL);
                
        fsp = file_new();
        if (!fsp) {
@@ -519,11 +698,11 @@ int reply_ntcreate_and_X(connection_struct *conn,
         * If it's a request for a directory open, deal with it separately.
         */
 
-       if(flags & OPEN_DIRECTORY) {
+       if(create_options & FILE_DIRECTORY_FILE) {
                oplock_request = 0;
                
-               open_directory(fsp, conn, fname, smb_ofun, 
-                              unixmode, &smb_action);
+               open_directory(fsp, conn, fname, smb_ofun, unixmode, 
+                              &smb_action);
                        
                restore_case_semantics(file_attributes);
 
@@ -549,7 +728,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
                 * before issuing an oplock break request to
                 * our client. JRA.  */
 
-               open_file_shared(fsp,conn,fname,smb_open_mode,
+               open_file_shared(fsp,conn,fname,smb_open_mode,
                                 smb_ofun,unixmode,
                                 oplock_request,&rmode,&smb_action);
 
@@ -573,7 +752,9 @@ int reply_ntcreate_and_X(connection_struct *conn,
                        if(errno == EISDIR) {
                                oplock_request = 0;
                                
-                               open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action);
+                               open_directory(fsp, conn, fname, 
+                                              smb_ofun, unixmode, 
+                                              &smb_action);
                                
                                if(!fsp->open) {
                                        file_free(fsp);
@@ -596,13 +777,15 @@ int reply_ntcreate_and_X(connection_struct *conn,
        }
                
        if(fsp->is_directory) {
-               if(sys_stat(fsp->fsp_name, &sbuf) != 0) {
+               if(fsp->conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False),
+                                          &sbuf) != 0) {
                        close_directory(fsp);
                        restore_case_semantics(file_attributes);
                        return(ERROR(ERRDOS,ERRnoaccess));
                }
        } else {
-               if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
+               if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) 
+                   != 0) {
                        close_file(fsp,False);
                        restore_case_semantics(file_attributes);
                        return(ERROR(ERRDOS,ERRnoaccess));
@@ -615,7 +798,6 @@ int reply_ntcreate_and_X(connection_struct *conn,
        fmode = dos_mode(conn,fname,&sbuf);
        if(fmode == 0)
                fmode = FILE_ATTRIBUTE_NORMAL;
-       mtime = sbuf.st_mtime;
        if (!fsp->is_directory && (fmode & aDIR)) {
                close_file(fsp,False);
                return(ERROR(ERRDOS,ERRnoaccess));
@@ -659,13 +841,10 @@ int reply_ntcreate_and_X(connection_struct *conn,
        put_long_date(p,sbuf.st_mtime); /* change time */
        p += 8;
        SIVAL(p,0,fmode); /* File Attributes. */
-       p += 12;
-#if OFF_T_IS_64_BITS
-       SIVAL(p,0, file_len & 0xFFFFFFFF);
-       SIVAL(p,4, file_len >> 32);
-#else /* OFF_T_IS_64_BITS */
-       SIVAL(p,0,file_len);
-#endif /* OFF_T_IS_64_BITS */
+       p += 4;
+       SOFF_T(p, 0, file_len);
+       p += 8;
+       SOFF_T(p,0,file_len);
        p += 12;
        SCVAL(p,0,fsp->is_directory ? 1 : 0);
        
@@ -690,18 +869,21 @@ static int call_nt_transact_create(connection_struct *conn,
   uint32 file_attributes = IVAL(params,20);
   uint32 share_access = IVAL(params,24);
   uint32 create_disposition = IVAL(params,28);
+  uint32 create_options = IVAL(params,32);
   uint32 fname_len = MIN(((uint32)IVAL(params,44)),
                          ((uint32)sizeof(fname)-1));
+  uint16 root_dir_fid = (uint16)IVAL(params,4);
   int smb_ofun;
   int smb_open_mode;
   int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
   /* Breakout the oplock request bits so we can set the
      reply bits separately. */
   int oplock_request = 0;
-  int unixmode, pnum = -1;
-  int fmode=0,mtime=0,rmode=0;
-  off_t file_len = 0;
-  struct stat sbuf;
+  mode_t unixmode;
+  int pnum = -1;
+  int fmode=0,rmode=0;
+  SMB_OFF_T file_len = 0;
+  SMB_STRUCT_STAT sbuf;
   int smb_action = 0;
   BOOL bad_path = False;
   files_struct *fsp = NULL;
@@ -716,19 +898,46 @@ static int call_nt_transact_create(connection_struct *conn,
     return(ERROR(ERRDOS,ERRbadaccess));
 
   /*
-   * Now contruct the smb_open_mode value from the desired access
-   * and the share access.
+   * Get the file name.
    */
 
-  if((smb_open_mode = map_share_mode( desired_access, share_access, file_attributes)) == -1)
-    return(ERROR(ERRDOS,ERRbadaccess));
+  if(root_dir_fid != 0) {
+    /*
+     * This filename is relative to a directory fid.
+     */
 
-  /*
-   * Get the file name.
-   */
+    files_struct *dir_fsp = file_fsp(params,4);
+    size_t dir_name_len;
 
-  StrnCpy(fname,params+53,fname_len);
-  fname[fname_len] = '\0';
+    if(!dir_fsp || !dir_fsp->is_directory)
+      return(ERROR(ERRDOS,ERRbadfid));
+
+    /*
+     * Copy in the base directory name.
+     */
+
+    pstrcpy( fname, dir_fsp->fsp_name );
+    dir_name_len = strlen(fname);
+
+    /*
+     * Ensure it ends in a '\'.
+     */
+
+    if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
+      pstrcat(fname, "\\");
+      dir_name_len++;
+    }
+
+    if(fname_len + dir_name_len >= sizeof(pstring))
+      return(ERROR(ERRSRV,ERRfilespecs));
+
+    StrnCpy(&fname[dir_name_len], params+53, fname_len);
+    fname[dir_name_len+fname_len] = '\0';
+
+  } else {
+    StrnCpy(fname,params+53,fname_len);
+    fname[fname_len] = '\0';
+  }
 
   /* If it's an IPC, use the pipe handler. */
   if (IS_IPC(conn)) {
@@ -743,7 +952,7 @@ static int call_nt_transact_create(connection_struct *conn,
 
     set_posix_case_semantics(file_attributes);
 
-    unix_convert(fname,conn,0,&bad_path);
+    unix_convert(fname,conn,0,&bad_path,NULL);
     
     fsp = file_new();
     if (!fsp) {
@@ -768,11 +977,19 @@ static int call_nt_transact_create(connection_struct *conn,
     oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
     oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
 
+    /*
+     * Now contruct the smb_open_mode value from the desired access
+     * and the share access.
+     */
+
+    if((smb_open_mode = map_share_mode( fname, desired_access, share_access, file_attributes)) == -1)
+      return(ERROR(ERRDOS,ERRbadaccess));
+
     /*
      * If it's a request for a directory open, deal with it separately.
      */
 
-    if(flags & OPEN_DIRECTORY) {
+    if(create_options & FILE_DIRECTORY_FILE) {
 
       oplock_request = 0;
 
@@ -794,8 +1011,8 @@ static int call_nt_transact_create(connection_struct *conn,
        * Ordinary file case.
        */
 
-      open_file_shared(fsp,conn,fname,smb_open_mode,smb_ofun,unixmode,
-                       oplock_request,&rmode,&smb_action);
+      open_file_shared(fsp,conn,fname,smb_open_mode,smb_ofun,
+                      unixmode,oplock_request,&rmode,&smb_action);
 
       if (!fsp->open) { 
         if((errno == ENOENT) && bad_path) {
@@ -809,7 +1026,7 @@ static int call_nt_transact_create(connection_struct *conn,
         return(UNIXERROR(ERRDOS,ERRnoaccess));
       } 
   
-      if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
+      if (fsp->conn->vfs_ops.fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
         close_file(fsp,False);
 
         restore_case_semantics(file_attributes);
@@ -821,7 +1038,6 @@ static int call_nt_transact_create(connection_struct *conn,
       fmode = dos_mode(conn,fname,&sbuf);
       if(fmode == 0)
         fmode = FILE_ATTRIBUTE_NORMAL;
-      mtime = sbuf.st_mtime;
 
       if (fmode & aDIR) {
         close_file(fsp,False);
@@ -887,13 +1103,10 @@ static int call_nt_transact_create(connection_struct *conn,
     put_long_date(p,sbuf.st_mtime); /* change time */
     p += 8;
     SIVAL(p,0,fmode); /* File Attributes. */
-    p += 12;
-#if OFF_T_IS_64_BITS
-      SIVAL(p,0, file_len & 0xFFFFFFFF);
-      SIVAL(p,4, (file_len >> 32));
-#else /* OFF_T_IS_64_BITS */
-      SIVAL(p,0,file_len);
-#endif /* OFF_T_IS_64_BITS */
+    p += 4;
+    SOFF_T(p,0,file_len);
+    p += 8;
+    SOFF_T(p,0,file_len);
   }
 
   /* Send the required number of replies */
@@ -1045,7 +1258,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp)
  Delete entries by mid from the change notify pending queue. Always send reply.
 *****************************************************************************/
 
-void remove_pending_change_notify_requests_by_mid(int mid)
+static void remove_pending_change_notify_requests_by_mid(int mid)
 {
   change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue );
   change_notify_buf *prev = NULL;
@@ -1084,7 +1297,7 @@ void process_pending_change_notify_queue(time_t t)
    */
 
   while((cnbp != NULL) && (cnbp->next_check_time <= t)) {
-    struct stat st;
+    SMB_STRUCT_STAT st;
     files_struct *fsp = cnbp->fsp;
     connection_struct *conn = cnbp->conn;
     uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : 
@@ -1121,7 +1334,7 @@ void process_pending_change_notify_queue(time_t t)
       continue;
     }
 
-    if(sys_stat(fsp->fsp_name, &st) < 0) {
+    if(fsp->conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), &st) < 0) {
       DEBUG(0,("process_pending_change_notify_queue: Unable to stat directory %s. \
 Error was %s.\n", fsp->fsp_name, strerror(errno) ));
       /*
@@ -1171,7 +1384,7 @@ static int call_nt_transact_notify_change(connection_struct *conn,
   char *setup = *ppsetup;
   files_struct *fsp;
   change_notify_buf *cnbp;
-  struct stat st;
+  SMB_STRUCT_STAT st;
 
   fsp = file_fsp(setup,4);
 
@@ -1200,7 +1413,7 @@ static int call_nt_transact_notify_change(connection_struct *conn,
    * Store the current timestamp on the directory we are monitoring.
    */
 
-  if(sys_stat(fsp->fsp_name, &st) < 0) {
+  if(fsp->conn->vfs_ops.stat(dos_to_unix(fsp->fsp_name, False), &st) < 0) {
     DEBUG(0,("call_nt_transact_notify_change: Unable to stat name = %s. \
 Error was %s\n", fsp->fsp_name, strerror(errno) ));
     free((char *)cnbp);
@@ -1239,7 +1452,13 @@ static int call_nt_transact_query_security_desc(connection_struct *conn,
                                                 int bufsize, 
                                                 char **ppsetup, char **ppparams, char **ppdata)
 {
-  DEBUG(0,("call_nt_transact_query_security_desc: Currently not implemented.\n"));
+  static BOOL logged_message = False;
+
+  if(!logged_message) {
+    DEBUG(0,("call_nt_transact_query_security_desc: Currently not implemented.\n"));
+    logged_message = True; /* Only print this once... */
+  }
+
   return(ERROR(ERRSRV,ERRnosupport));
 }
    
@@ -1254,8 +1473,13 @@ static int call_nt_transact_set_security_desc(connection_struct *conn,
                                               char **ppsetup, 
                                              char **ppparams, char **ppdata)
 {
-       DEBUG(0,("call_nt_transact_set_security_desc: Currently not implemented.\n"));
-       return(ERROR(ERRSRV,ERRnosupport));
+  static BOOL logged_message = False;
+
+  if(!logged_message) {
+    DEBUG(0,("call_nt_transact_set_security_desc: Currently not implemented.\n"));
+    logged_message = True; /* Only print this once... */
+  }
+  return(ERROR(ERRSRV,ERRnosupport));
 }
    
 /****************************************************************************
@@ -1266,8 +1490,13 @@ static int call_nt_transact_ioctl(connection_struct *conn,
                                   int bufsize, 
                                   char **ppsetup, char **ppparams, char **ppdata)
 {
-       DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n"));
-       return(ERROR(ERRSRV,ERRnosupport));
+  static BOOL logged_message = False;
+
+  if(!logged_message) {
+    DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n"));
+    logged_message = True; /* Only print this once... */
+  }
+  return(ERROR(ERRSRV,ERRnosupport));
 }
    
 /****************************************************************************
@@ -1366,8 +1595,7 @@ due to being in oplock break state.\n" ));
     while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
       BOOL ret;
 
-      ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
-                             SMB_SECONDARY_WAIT);
+      ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
 
       if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
         outsize = set_message(outbuf,0,0,True);