r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need
[vlendec/samba-autobuild/.git] / source3 / smbd / reply.c
index 86ee331e6b2f8d71efb57330dbecb54eb8a32973..ff3c6832e4f33c1cd1eb047e8285166858b5dabf 100644 (file)
 extern enum protocol_types Protocol;
 extern int max_send;
 extern int max_recv;
-extern char magic_char;
-extern int global_oplock_break;
 unsigned int smb_echo_count = 0;
 extern uint32 global_client_caps;
 
+extern struct current_user current_user;
 extern BOOL global_encrypted_passwords_negotiated;
 
 /****************************************************************************
- Ensure we check the path in *exactly* the same way as W2K.
+ Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
  We're assuming here that '/' is not the second byte in any multibyte char
  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
  set.
 ****************************************************************************/
 
-NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names)
+NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
 {
        char *d = destname;
        const char *s = srcname;
@@ -118,34 +117,170 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w
                }
 
                if (!(*s & 0x80)) {
-                       if (allow_wcard_names) {
+                       if (*s <= 0x1f) {
+                               return NT_STATUS_OBJECT_NAME_INVALID;
+                       }
+                       switch (*s) {
+                               case '*':
+                               case '?':
+                               case '<':
+                               case '>':
+                               case '"':
+                                       return NT_STATUS_OBJECT_NAME_INVALID;
+                               default:
+                                       *d++ = *s++;
+                                       break;
+                       }
+               } else {
+                       switch(next_mb_char_size(s)) {
+                               case 4:
+                                       *d++ = *s++;
+                               case 3:
+                                       *d++ = *s++;
+                               case 2:
+                                       *d++ = *s++;
+                               case 1:
+                                       *d++ = *s++;
+                                       break;
+                               default:
+                                       DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
+                                       *d = '\0';
+                                       return NT_STATUS_INVALID_PARAMETER;
+                       }
+               }
+               if (start_of_name_component && num_bad_components) {
+                       num_bad_components++;
+               }
+               start_of_name_component = False;
+       }
+
+       if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
+               if (num_bad_components > 1) {
+                       ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+               }
+       }
+
+       *d = '\0';
+       return ret;
+}
+
+/****************************************************************************
+ Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
+ path or anything including wildcards.
+ We're assuming here that '/' is not the second byte in any multibyte char
+ set (a safe assumption). '\\' *may* be the second byte in a multibyte char
+ set.
+****************************************************************************/
+
+NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
+{
+       char *d = destname;
+       const char *s = srcname;
+       NTSTATUS ret = NT_STATUS_OK;
+       BOOL start_of_name_component = True;
+       unsigned int num_bad_components = 0;
+
+       *p_contains_wcard = False;
+
+       while (*s) {
+               if (IS_DIRECTORY_SEP(*s)) {
+                       /*
+                        * Safe to assume is not the second part of a mb char as this is handled below.
+                        */
+                       /* Eat multiple '/' or '\\' */
+                       while (IS_DIRECTORY_SEP(*s)) {
+                               s++;
+                       }
+                       if ((d != destname) && (*s != '\0')) {
+                               /* We only care about non-leading or trailing '/' or '\\' */
+                               *d++ = '/';
+                       }
+
+                       start_of_name_component = True;
+                       continue;
+               }
+
+               if (start_of_name_component) {
+                       if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
+                               /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
+
+                               /*
+                                * No mb char starts with '.' so we're safe checking the directory separator here.
+                                */
+
+                               /* If  we just added a '/' - delete it */
+                               if ((d > destname) && (*(d-1) == '/')) {
+                                       *(d-1) = '\0';
+                                       d--;
+                               }
+
+                               /* Are we at the start ? Can't go back further if so. */
+                               if (d <= destname) {
+                                       ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+                                       break;
+                               }
+                               /* Go back one level... */
+                               /* We know this is safe as '/' cannot be part of a mb sequence. */
+                               /* NOTE - if this assumption is invalid we are not in good shape... */
+                               /* Decrement d first as d points to the *next* char to write into. */
+                               for (d--; d > destname; d--) {
+                                       if (*d == '/')
+                                               break;
+                               }
+                               s += 2; /* Else go past the .. */
+                               /* We're still at the start of a name component, just the previous one. */
+
+                               if (num_bad_components) {
+                                       /* Hmmm. Should we only decrement the bad_components if
+                                          we're removing a bad component ? Need to check this. JRA. */
+                                       num_bad_components--;
+                               }
+
+                               continue;
+
+                       } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
+                               /* Component of pathname can't be "." only. */
+                               ret =  NT_STATUS_OBJECT_NAME_INVALID;
+                               num_bad_components++;
                                *d++ = *s++;
-                       } else {
+                               continue;
+                       }
+               }
+
+               if (!(*s & 0x80)) {
+                       if (*s <= 0x1f) {
+                               return NT_STATUS_OBJECT_NAME_INVALID;
+                       }
+                       if (!*p_contains_wcard) {
                                switch (*s) {
                                        case '*':
                                        case '?':
                                        case '<':
                                        case '>':
                                        case '"':
-                                               return NT_STATUS_OBJECT_NAME_INVALID;
+                                               *p_contains_wcard = True;
+                                               break;
                                        default:
-                                               *d++ = *s++;
                                                break;
                                }
                        }
+                       *d++ = *s++;
                } else {
                        switch(next_mb_char_size(s)) {
                                case 4:
                                        *d++ = *s++;
+                                       /*fall through*/
                                case 3:
                                        *d++ = *s++;
+                                       /*fall through*/
                                case 2:
                                        *d++ = *s++;
+                                       /*fall through*/
                                case 1:
                                        *d++ = *s++;
                                        break;
                                default:
-                                       DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
+                                       DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
                                        *d = '\0';
                                        return NT_STATUS_INVALID_PARAMETER;
                        }
@@ -159,26 +294,148 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w
        if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
                /* For some strange reason being called from findfirst changes
                   the num_components number to cause the error return to change. JRA. */
-               if (allow_wcard_names) {
-                       if (num_bad_components > 2) {
-                               ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+               if (num_bad_components > 2) {
+                       ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+               }
+       }
+
+       *d = '\0';
+       return ret;
+}
+
+/****************************************************************************
+ Check the path for a POSIX client.
+ We're assuming here that '/' is not the second byte in any multibyte char
+ set (a safe assumption).
+****************************************************************************/
+
+NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
+{
+       char *d = destname;
+       const char *s = srcname;
+       NTSTATUS ret = NT_STATUS_OK;
+       BOOL start_of_name_component = True;
+
+       while (*s) {
+               if (*s == '/') {
+                       /*
+                        * Safe to assume is not the second part of a mb char as this is handled below.
+                        */
+                       /* Eat multiple '/' or '\\' */
+                       while (*s == '/') {
+                               s++;
+                       }
+                       if ((d != destname) && (*s != '\0')) {
+                               /* We only care about non-leading or trailing '/' */
+                               *d++ = '/';
+                       }
+
+                       start_of_name_component = True;
+                       continue;
+               }
+
+               if (start_of_name_component) {
+                       if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
+                               /* Uh oh - "/../" or "/..\0" ! */
+
+                               /*
+                                * No mb char starts with '.' so we're safe checking the directory separator here.
+                                */
+
+                               /* If  we just added a '/' - delete it */
+                               if ((d > destname) && (*(d-1) == '/')) {
+                                       *(d-1) = '\0';
+                                       d--;
+                               }
+
+                               /* Are we at the start ? Can't go back further if so. */
+                               if (d <= destname) {
+                                       ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+                                       break;
+                               }
+                               /* Go back one level... */
+                               /* We know this is safe as '/' cannot be part of a mb sequence. */
+                               /* NOTE - if this assumption is invalid we are not in good shape... */
+                               /* Decrement d first as d points to the *next* char to write into. */
+                               for (d--; d > destname; d--) {
+                                       if (*d == '/')
+                                               break;
+                               }
+                               s += 2; /* Else go past the .. */
+                               continue;
+
+                       } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) {
+                               /* Eat the '.' */
+                               s++;
+                               continue;
                        }
+               }
+
+               if (!(*s & 0x80)) {
+                       *d++ = *s++;
                } else {
-                       if (num_bad_components > 1) {
-                               ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+                       switch(next_mb_char_size(s)) {
+                               case 4:
+                                       *d++ = *s++;
+                                       /*fall through*/
+                               case 3:
+                                       *d++ = *s++;
+                                       /*fall through*/
+                               case 2:
+                                       *d++ = *s++;
+                                       /*fall through*/
+                               case 1:
+                                       *d++ = *s++;
+                                       break;
+                               default:
+                                       DEBUG(0,("check_path_syntax_posix: character length assumptions invalid !\n"));
+                                       *d = '\0';
+                                       return NT_STATUS_INVALID_PARAMETER;
                        }
                }
+               start_of_name_component = False;
        }
 
        *d = '\0';
        return ret;
 }
 
+/****************************************************************************
+ Pull a string and check the path allowing a wilcard - provide for error return.
+****************************************************************************/
+
+size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
+                               NTSTATUS *err, BOOL *contains_wcard)
+{
+       pstring tmppath;
+       char *tmppath_ptr = tmppath;
+       size_t ret;
+#ifdef DEVELOPER
+       SMB_ASSERT(dest_len == sizeof(pstring));
+#endif
+
+       if (src_len == 0) {
+               ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
+       } else {
+               ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
+       }
+
+       *contains_wcard = False;
+
+       if (lp_posix_pathnames()) {
+               *err = check_path_syntax_posix(dest, tmppath);
+       } else {
+               *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
+       }
+
+       return ret;
+}
+
 /****************************************************************************
  Pull a string and check the path - provide for error return.
 ****************************************************************************/
 
-size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names)
+size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
 {
        pstring tmppath;
        char *tmppath_ptr = tmppath;
@@ -192,7 +449,12 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len
        } else {
                ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
        }
-       *err = check_path_syntax(dest, tmppath, allow_wcard_names);
+       if (lp_posix_pathnames()) {
+               *err = check_path_syntax_posix(dest, tmppath);
+       } else {
+               *err = check_path_syntax(dest, tmppath);
+       }
+
        return ret;
 }
 
@@ -287,6 +549,7 @@ int reply_special(char *inbuf,char *outbuf)
 
 /****************************************************************************
  Reply to a tcon.
+ conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
 int reply_tcon(connection_struct *conn,
@@ -345,6 +608,7 @@ int reply_tcon(connection_struct *conn,
 
 /****************************************************************************
  Reply to a tcon and X.
+ conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
@@ -361,7 +625,6 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        int passlen = SVAL(inbuf,smb_vwv3);
        pstring path;
        char *p, *q;
-       extern BOOL global_encrypted_passwords_negotiated;
        
        START_PROFILE(SMBtconX);        
 
@@ -479,6 +742,7 @@ int reply_unknown(char *inbuf,char *outbuf)
 
 /****************************************************************************
  Reply to an ioctl.
+ conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
 int reply_ioctl(connection_struct *conn,
@@ -544,9 +808,17 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
 
        START_PROFILE(SMBchkpth);
 
-       srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
+       srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBchkpth);
+
+               /* Strange DOS error code semantics only for chkpth... */
+               if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
+                       if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
+                               /* We need to map to ERRbadpath */
+                               status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+                       }
+               }
                return ERROR_NT(status);
        }
 
@@ -589,7 +861,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return(UNIXERROR(ERRDOS,ERRbadpath));
        }
 
-       outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,False);
        DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
 
        END_PROFILE(SMBchkpth);
@@ -616,7 +888,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        START_PROFILE(SMBgetatr);
 
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
+       p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBgetatr);
                return ERROR_NT(status);
@@ -661,14 +933,16 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        outsize = set_message(outbuf,10,0,True);
 
        SSVAL(outbuf,smb_vwv0,mode);
-       if(lp_dos_filetime_resolution(SNUM(conn)) )
-               put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
-       else
-               put_dos_date3(outbuf,smb_vwv1,mtime);
+       if(lp_dos_filetime_resolution(SNUM(conn)) ) {
+               srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
+       } else {
+               srv_put_dos_date3(outbuf,smb_vwv1,mtime);
+       }
        SIVAL(outbuf,smb_vwv3,(uint32)size);
 
-       if (Protocol >= PROTOCOL_NT1)
+       if (Protocol >= PROTOCOL_NT1) {
                SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
+       }
   
        DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
   
@@ -695,12 +969,14 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        START_PROFILE(SMBsetatr);
 
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
+       p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBsetatr);
                return ERROR_NT(status);
        }
 
+       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+  
        unix_convert(fname,conn,0,&bad_path,&sbuf);
        if (bad_path) {
                END_PROFILE(SMBsetatr);
@@ -708,7 +984,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        }
 
        mode = SVAL(inbuf,smb_vwv0);
-       mtime = make_unix_date3(inbuf+smb_vwv1);
+       mtime = srv_make_unix_date3(inbuf+smb_vwv1);
   
        if (mode != FILE_ATTRIBUTE_NORMAL) {
                if (VALID_STAT_OF_DIR(sbuf))
@@ -731,7 +1007,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
        }
  
-       outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,False);
   
        DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
   
@@ -749,7 +1025,10 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
        SMB_BIG_UINT dfree,dsize,bsize;
        START_PROFILE(SMBdskattr);
 
-       SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
+       if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
+               END_PROFILE(SMBdskattr);
+               return(UNIXERROR(ERRHRD,ERRgeneral));
+       }
   
        outsize = set_message(outbuf,5,0,True);
        
@@ -798,9 +1077,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        pstring directory;
        pstring fname;
        SMB_OFF_T size;
-       int mode;
+       uint32 mode;
        time_t date;
-       int dirtype;
+       uint32 dirtype;
        int outsize = 0;
        unsigned int numentries = 0;
        unsigned int maxentries = 0;
@@ -816,8 +1095,16 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        BOOL can_open = True;
        BOOL bad_path = False;
        NTSTATUS nt_status;
+       BOOL mask_contains_wcard = False;
+       BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
+
        START_PROFILE(SMBsearch);
 
+       if (lp_posix_pathnames()) {
+               END_PROFILE(SMBsearch);
+               return reply_unknown(inbuf, outbuf);
+       }
+
        *mask = *directory = *fname = 0;
 
        /* If we were called as SMBffirst then we must expect close. */
@@ -828,11 +1115,14 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        maxentries = SVAL(inbuf,smb_vwv0); 
        dirtype = SVAL(inbuf,smb_vwv1);
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
+       p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
        if (!NT_STATUS_IS_OK(nt_status)) {
                END_PROFILE(SMBsearch);
                return ERROR_NT(nt_status);
        }
+
+       RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
+  
        p++;
        status_len = SVAL(p, 0);
        p += 2;
@@ -890,7 +1180,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                ok = True;
      
                if (status_len == 0) {
-                       dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
+                       dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
                        if (dptr_num < 0) {
                                if(dptr_num == -2) {
                                        END_PROFILE(SMBsearch);
@@ -899,8 +1189,6 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                                END_PROFILE(SMBsearch);
                                return ERROR_DOS(ERRDOS,ERRnofids);
                        }
-                       dptr_set_wcard(dptr_num, SMB_STRDUP(mask));
-                       dptr_set_attr(dptr_num, dirtype);
                } else {
                        dirtype = dptr_attr(dptr_num);
                }
@@ -910,7 +1198,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                if (ok) {
                        if ((dirtype&0x1F) == aVOLID) {   
                                memcpy(p,status,21);
-                               make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0,conn->case_sensitive);
+                               make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
+                                               0,aVOLID,0,!allow_long_path_components);
                                dptr_fill(p+12,dptr_num);
                                if (dptr_zero(p+12) && (status_len==0))
                                        numentries = 1;
@@ -930,8 +1219,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                                        finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
                                        if (!finished) {
                                                memcpy(p,status,21);
-                                               make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive);
-                                               dptr_fill(p+12,dptr_num);
+                                               make_dir_struct(p,mask,fname,size, mode,date,
+                                                               !allow_long_path_components);
+                                               if (!dptr_fill(p+12,dptr_num)) {
+                                                       break;
+                                               }
                                                numentries++;
                                                p += DIR_STRUCT_SIZE;
                                        }
@@ -947,27 +1239,36 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                and no entries were found then return error and close dirptr 
                (X/Open spec) */
 
-       if(ok && expect_close && numentries == 0 && status_len == 0) {
-               /* Close the dptr - we know it's gone */
+       if (numentries == 0 || !ok) {
                dptr_close(&dptr_num);
-               return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
-       } else if (numentries == 0 || !ok) {
+       } else if(ok && expect_close && status_len == 0) {
+               /* Close the dptr - we know it's gone */
                dptr_close(&dptr_num);
-               return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
        }
 
        /* If we were called as SMBfunique, then we can close the dirptr now ! */
-       if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
+       if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
                dptr_close(&dptr_num);
+       }
+
+       if ((numentries == 0) && !mask_contains_wcard) {
+               return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
+       }
 
        SSVAL(outbuf,smb_vwv0,numentries);
        SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
        SCVAL(smb_buf(outbuf),0,5);
        SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
 
-       if (Protocol >= PROTOCOL_NT1)
-               SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
-  
+       /* The replies here are never long name. */
+       SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
+       if (!allow_long_path_components) {
+               SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
+       }
+
+       /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
+       SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
+         
        outsize += DIR_STRUCT_SIZE*numentries;
        smb_setlen(outbuf,outsize - 4);
   
@@ -995,12 +1296,18 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        int dptr_num= -2;
        char *p;
        NTSTATUS err;
+       BOOL path_contains_wcard = False;
 
        START_PROFILE(SMBfclose);
 
+       if (lp_posix_pathnames()) {
+               END_PROFILE(SMBfclose);
+               return reply_unknown(inbuf, outbuf);
+       }
+
        outsize = set_message(outbuf,1,0,True);
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
+       p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
        if (!NT_STATUS_IS_OK(err)) {
                END_PROFILE(SMBfclose);
                return ERROR_NT(err);
@@ -1037,22 +1344,26 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 {
        pstring fname;
        int outsize = 0;
-       int fmode=0;
-       int share_mode;
+       uint32 fattr=0;
        SMB_OFF_T size = 0;
        time_t mtime=0;
-       int rmode=0;
+       int info;
        SMB_STRUCT_STAT sbuf;
        BOOL bad_path = False;
        files_struct *fsp;
        int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
-       uint16 dos_attr = SVAL(inbuf,smb_vwv1);
+       int deny_mode;
+       uint32 dos_attr = SVAL(inbuf,smb_vwv1);
+       uint32 access_mask;
+       uint32 share_mode;
+       uint32 create_disposition;
+       uint32 create_options = 0;
        NTSTATUS status;
        START_PROFILE(SMBopen);
  
-       share_mode = SVAL(inbuf,smb_vwv0);
+       deny_mode = SVAL(inbuf,smb_vwv0);
 
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
+       srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBopen);
                return ERROR_NT(status);
@@ -1066,45 +1377,59 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
        }
     
-       fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
-                       (uint32)dos_attr, oplock_request,&rmode,NULL);
+       if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
+                       &access_mask, &share_mode, &create_disposition, &create_options)) {
+               END_PROFILE(SMBopen);
+               return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
+       }
 
-       if (!fsp) {
+       status = open_file_ntcreate(conn,fname,&sbuf,
+                       access_mask,
+                       share_mode,
+                       create_disposition,
+                       create_options,
+                       dos_attr,
+                       oplock_request,
+                       &info, &fsp);
+
+       if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBopen);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
-                       clear_cached_errors();
                        return -1;
                }
-               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+               return ERROR_NT(status);
        }
 
        size = sbuf.st_size;
-       fmode = dos_mode(conn,fname,&sbuf);
+       fattr = dos_mode(conn,fname,&sbuf);
        mtime = sbuf.st_mtime;
 
-       if (fmode & aDIR) {
+       if (fattr & aDIR) {
                DEBUG(3,("attempt to open a directory %s\n",fname));
-               close_file(fsp,False);
+               close_file(fsp,ERROR_CLOSE);
                END_PROFILE(SMBopen);
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
   
        outsize = set_message(outbuf,7,0,True);
        SSVAL(outbuf,smb_vwv0,fsp->fnum);
-       SSVAL(outbuf,smb_vwv1,fmode);
-       if(lp_dos_filetime_resolution(SNUM(conn)) )
-               put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
-       else
-               put_dos_date3(outbuf,smb_vwv2,mtime);
+       SSVAL(outbuf,smb_vwv1,fattr);
+       if(lp_dos_filetime_resolution(SNUM(conn)) ) {
+               srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
+       } else {
+               srv_put_dos_date3(outbuf,smb_vwv2,mtime);
+       }
        SIVAL(outbuf,smb_vwv4,(uint32)size);
-       SSVAL(outbuf,smb_vwv6,rmode);
+       SSVAL(outbuf,smb_vwv6,deny_mode);
 
-       if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+       if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
                SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+       }
     
-       if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+       if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
                SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+       }
        END_PROFILE(SMBopen);
        return(outsize);
 }
@@ -1116,26 +1441,34 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
        pstring fname;
-       int smb_mode = SVAL(inbuf,smb_vwv3);
-       int smb_attr = SVAL(inbuf,smb_vwv5);
+       uint16 open_flags = SVAL(inbuf,smb_vwv2);
+       int deny_mode = SVAL(inbuf,smb_vwv3);
+       uint32 smb_attr = SVAL(inbuf,smb_vwv5);
        /* 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;
+       int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
+       int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+       int oplock_request = ex_oplock_request | core_oplock_request;
 #if 0
-       int open_flags = SVAL(inbuf,smb_vwv2);
        int smb_sattr = SVAL(inbuf,smb_vwv4); 
        uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
 #endif
        int smb_ofun = SVAL(inbuf,smb_vwv8);
        SMB_OFF_T size=0;
-       int fmode=0,mtime=0,rmode=0;
+       uint32 fattr=0;
+       int mtime=0;
        SMB_STRUCT_STAT sbuf;
        int smb_action = 0;
        BOOL bad_path = False;
        files_struct *fsp;
        NTSTATUS status;
+       SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
+       ssize_t retval = -1;
+       uint32 access_mask;
+       uint32 share_mode;
+       uint32 create_disposition;
+       uint32 create_options = 0;
+
        START_PROFILE(SMBopenX);
 
        /* If it's an IPC, pass off the pipe handler. */
@@ -1150,7 +1483,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        }
 
        /* XXXX we need to handle passed times, sattr and flags */
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
+       srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBopenX);
                return ERROR_NT(status);
@@ -1163,25 +1496,58 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                END_PROFILE(SMBopenX);
                return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
        }
-    
-       fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
-                       oplock_request, &rmode,&smb_action);
+
+       if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
+                               &access_mask,
+                               &share_mode,
+                               &create_disposition,
+                               &create_options)) {
+               END_PROFILE(SMBopenX);
+               return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
+       }
+
+       status = open_file_ntcreate(conn,fname,&sbuf,
+                       access_mask,
+                       share_mode,
+                       create_disposition,
+                       create_options,
+                       smb_attr,
+                       oplock_request,
+                       &smb_action, &fsp);
       
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBopenX);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
-                       clear_cached_errors();
                        return -1;
                }
-               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+               return ERROR_NT(status);
        }
 
        size = sbuf.st_size;
-       fmode = dos_mode(conn,fname,&sbuf);
+
+       /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
+          if the file is truncated or created. */
+       if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
+               fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
+               if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
+                       close_file(fsp,ERROR_CLOSE);
+                       END_PROFILE(SMBopenX);
+                       return ERROR_NT(NT_STATUS_DISK_FULL);
+               }
+               retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
+               if (retval < 0) {
+                       close_file(fsp,ERROR_CLOSE);
+                       END_PROFILE(SMBopenX);
+                       return ERROR_NT(NT_STATUS_DISK_FULL);
+               }
+               size = get_allocation_size(conn,fsp,&sbuf);
+       }
+
+       fattr = dos_mode(conn,fname,&sbuf);
        mtime = sbuf.st_mtime;
-       if (fmode & aDIR) {
-               close_file(fsp,False);
+       if (fattr & aDIR) {
+               close_file(fsp,ERROR_CLOSE);
                END_PROFILE(SMBopenX);
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
@@ -1191,40 +1557,54 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                correct bit for extended oplock reply.
        */
 
-       if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
+       if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
                smb_action |= EXTENDED_OPLOCK_GRANTED;
+       }
 
-       if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+       if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
                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(conn)))
+       if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
                SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+       }
 
-       if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+       if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
                SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+       }
 
-       set_message(outbuf,15,0,True);
+       if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
+               set_message(outbuf,19,0,True);
+       } else {
+               set_message(outbuf,15,0,True);
+       }
        SSVAL(outbuf,smb_vwv2,fsp->fnum);
-       SSVAL(outbuf,smb_vwv3,fmode);
-       if(lp_dos_filetime_resolution(SNUM(conn)) )
-               put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
-       else
-               put_dos_date3(outbuf,smb_vwv4,mtime);
+       SSVAL(outbuf,smb_vwv3,fattr);
+       if(lp_dos_filetime_resolution(SNUM(conn)) ) {
+               srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
+       } else {
+               srv_put_dos_date3(outbuf,smb_vwv4,mtime);
+       }
        SIVAL(outbuf,smb_vwv6,(uint32)size);
-       SSVAL(outbuf,smb_vwv8,rmode);
+       SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
        SSVAL(outbuf,smb_vwv11,smb_action);
 
+       if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
+               SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
+       }
+
        END_PROFILE(SMBopenX);
        return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
 /****************************************************************************
  Reply to a SMBulogoffX.
+ conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
@@ -1260,19 +1640,22 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        pstring fname;
        int com;
        int outsize = 0;
-       int createmode;
-       int ofun = 0;
+       uint32 fattr = SVAL(inbuf,smb_vwv0);
        BOOL bad_path = False;
        files_struct *fsp;
        int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
        SMB_STRUCT_STAT sbuf;
        NTSTATUS status;
+       uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
+       uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
+       uint32 create_disposition;
+       uint32 create_options = 0;
+
        START_PROFILE(SMBcreate);
  
        com = SVAL(inbuf,smb_com);
 
-       createmode = SVAL(inbuf,smb_vwv0);
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
+       srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcreate);
                return ERROR_NT(status);
@@ -1286,42 +1669,50 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
        }
 
-       if (createmode & aVOLID)
+       if (fattr & aVOLID) {
                DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
-  
+       }
+
        if(com == SMBmknew) {
                /* We should fail if file exists. */
-               ofun = FILE_CREATE_IF_NOT_EXIST;
+               create_disposition = FILE_CREATE;
        } else {
-               /* SMBcreate - Create if file doesn't exist, truncate if it does. */
-               ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
-       }
-
-       /* Open file in dos compatibility share mode. */
-       fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB), 
-                       ofun, (uint32)createmode, oplock_request, NULL, NULL);
+               /* Create if file doesn't exist, truncate if it does. */
+               create_disposition = FILE_OVERWRITE_IF;
+       }
+
+       /* Open file using ntcreate. */
+       status = open_file_ntcreate(conn,fname,&sbuf,
+                               access_mask,
+                               share_mode,
+                               create_disposition,
+                               create_options,
+                               fattr,
+                               oplock_request,
+                               NULL, &fsp);
   
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcreate);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
-                       clear_cached_errors();
                        return -1;
                }
-               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+               return ERROR_NT(status);
        }
  
        outsize = set_message(outbuf,1,0,True);
        SSVAL(outbuf,smb_vwv0,fsp->fnum);
 
-       if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+       if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
                SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+       }
  
-       if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+       if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
                SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+       }
  
-       DEBUG( 2, ( "new file %s\n", fname ) );
-       DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
+       DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
+       DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
 
        END_PROFILE(SMBcreate);
        return(outsize);
@@ -1335,7 +1726,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 {
        pstring fname;
        int outsize = 0;
-       int createattr;
+       uint32 fattr = SVAL(inbuf,smb_vwv0);
        BOOL bad_path = False;
        files_struct *fsp;
        int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
@@ -1347,8 +1738,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 
        START_PROFILE(SMBctemp);
 
-       createattr = SVAL(inbuf,smb_vwv0);
-       srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
+       srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBctemp);
                return ERROR_NT(status);
@@ -1375,24 +1765,26 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 
        SMB_VFS_STAT(conn,fname,&sbuf);
 
-       /* Open file in dos compatibility share mode. */
        /* We should fail if file does not exist. */
-       fsp = open_file_shared(conn,fname,&sbuf,
-               SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
-               FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
-               (uint32)createattr, oplock_request, NULL, NULL);
+       status = open_file_ntcreate(conn,fname,&sbuf,
+                               FILE_GENERIC_READ | FILE_GENERIC_WRITE,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE,
+                               FILE_OPEN,
+                               0,
+                               fattr,
+                               oplock_request,
+                               NULL, &fsp);
 
        /* close fd from smb_mkstemp() */
        close(tmpfd);
 
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBctemp);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
-                       clear_cached_errors();
                        return -1;
                }
-               return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
+               return ERROR_NT(status);
        }
 
        outsize = set_message(outbuf,1,0,True);
@@ -1400,10 +1792,11 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 
        /* the returned filename is relative to the directory */
        s = strrchr_m(fname, '/');
-       if (!s)
+       if (!s) {
                s = fname;
-       else
+       } else {
                s++;
+       }
 
        p = smb_buf(outbuf);
 #if 0
@@ -1415,15 +1808,17 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        p += namelen;
        outsize = set_message_end(outbuf, p);
 
-       if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+       if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
                SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+       }
   
-       if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+       if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
                SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+       }
 
-       DEBUG( 2, ( "created temp file %s\n", fname ) );
-       DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
-                       fname, fsp->fd, sbuf.st_mode ) );
+       DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
+       DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
+                       (unsigned int)sbuf.st_mode ) );
 
        END_PROFILE(SMBctemp);
        return(outsize);
@@ -1433,40 +1828,38 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
  Check if a user is allowed to rename a file.
 ********************************************************************/
 
-static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, SMB_STRUCT_STAT *pst)
+static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
 {
-       int smb_action;
-       int access_mode;
        files_struct *fsp;
-       uint16 fmode;
+       uint32 fmode;
+       NTSTATUS status;
 
-       if (!CAN_WRITE(conn))
+       if (!CAN_WRITE(conn)) {
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
+       }
 
        fmode = dos_mode(conn,fname,pst);
-       if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
+       if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
                return NT_STATUS_NO_SUCH_FILE;
+       }
 
-       if (S_ISDIR(pst->st_mode))
+       if (S_ISDIR(pst->st_mode)) {
                return NT_STATUS_OK;
+       }
 
-       /* We need a better way to return NT status codes from open... */
-       unix_ERR_class = 0;
-       unix_ERR_code = 0;
-
-       fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
-               (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
+       status = open_file_ntcreate(conn, fname, pst,
+                               DELETE_ACCESS,
+                               FILE_SHARE_READ|FILE_SHARE_WRITE,
+                               FILE_OPEN,
+                               0,
+                               FILE_ATTRIBUTE_NORMAL,
+                               0,
+                               NULL, &fsp);
 
-       if (!fsp) {
-               NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
-               if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
-                       ret = NT_STATUS_SHARING_VIOLATION;
-               unix_ERR_class = 0;
-               unix_ERR_code = 0;
-               unix_ERR_ntstatus = NT_STATUS_OK;
-               return ret;
-       }
-       close_file(fsp,False);
+       if (!NT_STATUS_IS_OK(status)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+       close_file(fsp,NORMAL_CLOSE);
        return NT_STATUS_OK;
 }
 
@@ -1474,66 +1867,85 @@ static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype,
  Check if a user is allowed to delete a file.
 ********************************************************************/
 
-static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
+NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open)
 {
        SMB_STRUCT_STAT sbuf;
-       int fmode;
-       int smb_action;
-       int access_mode;
+       uint32 fattr;
        files_struct *fsp;
+       NTSTATUS status;
 
-       DEBUG(10,("can_delete: %s, dirtype = %d\n",
-               fname, dirtype ));
+       DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
 
-       if (!CAN_WRITE(conn))
+       if (!CAN_WRITE(conn)) {
                return NT_STATUS_MEDIA_WRITE_PROTECTED;
+       }
 
        if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
                if(errno == ENOENT) {
-                       if (bad_path)
+                       if (bad_path) {
                                return NT_STATUS_OBJECT_PATH_NOT_FOUND;
-                       else
+                       } else {
                                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+                       }
                }
                return map_nt_error_from_unix(errno);
        }
 
-       fmode = dos_mode(conn,fname,&sbuf);
+       fattr = dos_mode(conn,fname,&sbuf);
 
        /* Can't delete a directory. */
-       if (fmode & aDIR)
+       if (fattr & aDIR) {
                return NT_STATUS_FILE_IS_A_DIRECTORY;
+       }
+
 #if 0 /* JRATEST */
        else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
                return NT_STATUS_OBJECT_NAME_INVALID;
 #endif /* JRATEST */
 
-       if (!lp_delete_readonly(SNUM(conn))) {
-               if (fmode & aRONLY)
+       /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
+
+         On a Windows share, a file with read-only dosmode can be opened with
+         DELETE_ACCESS. But on a Samba share (delete readonly = no), it
+         fails with NT_STATUS_CANNOT_DELETE error.
+
+         This semantic causes a problem that a user can not
+         rename a file with read-only dosmode on a Samba share
+         from a Windows command prompt (i.e. cmd.exe, but can rename
+         from Windows Explorer).
+       */
+
+       if (!check_is_at_open && !lp_delete_readonly(SNUM(conn))) {
+               if (fattr & aRONLY) {
                        return NT_STATUS_CANNOT_DELETE;
+               }
        }
-       if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
+       if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) {
                return NT_STATUS_NO_SUCH_FILE;
+       }
 
-       /* We need a better way to return NT status codes from open... */
-       unix_ERR_class = 0;
-       unix_ERR_code = 0;
-
-       fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
-               (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
-
-       if (!fsp) {
-               NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
-               if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
-                       ret = unix_ERR_ntstatus;
-               else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
-                       ret = NT_STATUS_SHARING_VIOLATION;
-               unix_ERR_class = 0;
-               unix_ERR_code = 0;
-               unix_ERR_ntstatus = NT_STATUS_OK;
-               return ret;
-       }
-       close_file(fsp,False);
+       if (check_is_at_open) {
+               if (!can_delete_file_in_directory(conn, fname)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       } else {
+               /* On open checks the open itself will check the share mode, so
+                  don't do it here as we'll get it wrong. */
+
+               status = open_file_ntcreate(conn, fname, &sbuf,
+                                       DELETE_ACCESS,
+                                       FILE_SHARE_NONE,
+                                       FILE_OPEN,
+                                       0,
+                                       FILE_ATTRIBUTE_NORMAL,
+                                       0,
+                                       NULL, &fsp);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+               close_file(fsp,NORMAL_CLOSE);
+       }
        return NT_STATUS_OK;
 }
 
@@ -1542,30 +1954,19 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOO
  code.
 ****************************************************************************/
 
-NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
+NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild)
 {
        pstring directory;
        pstring mask;
        char *p;
        int count=0;
        NTSTATUS error = NT_STATUS_OK;
-       BOOL has_wild;
        BOOL bad_path = False;
        BOOL rc = True;
        SMB_STRUCT_STAT sbuf;
        
        *directory = *mask = 0;
        
-       /* We must check for wildcards in the name given
-        * directly by the client - before any unmangling.
-        * This prevents an unmangling of a UNIX name containing
-        * a DOS wildcard like '*' or '?' from unmangling into
-        * a wildcard delete which was not intended.
-        * FIX for #226. JRA.
-        */
-
-       has_wild = ms_has_wild(name);
-
        rc = unix_convert(name,conn,0,&bad_path,&sbuf);
        
        p = strrchr_m(name,'/');
@@ -1587,13 +1988,13 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
         * Tine Smukavec <valentin.smukavec@hermes.si>.
         */
        
-       if (!rc && mangle_is_mangled(mask))
-               mangle_check_cache( mask, sizeof(pstring)-1 );
+       if (!rc && mangle_is_mangled(mask,conn->params))
+               mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
        
        if (!has_wild) {
                pstrcat(directory,"/");
                pstrcat(directory,mask);
-               error = can_delete(directory,conn,dirtype,bad_path);
+               error = can_delete(conn,directory,dirtype,bad_path,False);
                if (!NT_STATUS_IS_OK(error))
                        return error;
 
@@ -1601,29 +2002,34 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
                        count++;
                }
        } else {
-               void *dirptr = NULL;
+               struct smb_Dir *dir_hnd = NULL;
                const char *dname;
                
+               if (strequal(mask,"????????.???"))
+                       pstrcpy(mask,"*");
+
                if (check_name(directory,conn))
-                       dirptr = OpenDir(conn, directory, True);
+                       dir_hnd = OpenDir(conn, directory, mask, dirtype);
                
                /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
                   the pattern matches against the long name, otherwise the short name 
                   We don't implement this yet XXXX
                */
                
-               if (dirptr) {
-                       error = NT_STATUS_NO_SUCH_FILE;
+               if (dir_hnd) {
                        long offset = 0;
+                       error = NT_STATUS_NO_SUCH_FILE;
 
-                       if (strequal(mask,"????????.???"))
-                               pstrcpy(mask,"*");
-
-                       while ((dname = ReadDirName(dirptr, &offset))) {
+                       while ((dname = ReadDirName(dir_hnd, &offset))) {
+                               SMB_STRUCT_STAT st;
                                pstring fname;
                                BOOL sys_direntry = False;
                                pstrcpy(fname,dname);
 
+                               if (!is_visible_file(conn, directory, dname, &st, True)) {
+                                       continue;
+                               }
+
                                /* Quick check for "." and ".." */
                                if (fname[0] == '.') {
                                        if (!fname[1] || (fname[1] == '.' && !fname[2])) {
@@ -1646,7 +2052,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
                                }
 
                                slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
-                               error = can_delete(fname,conn,dirtype,bad_path);
+                               error = can_delete(conn,fname,dirtype,bad_path,False);
                                if (!NT_STATUS_IS_OK(error)) {
                                        continue;
                                }
@@ -1654,7 +2060,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
                                        count++;
                                DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
                        }
-                       CloseDir(dirptr);
+                       CloseDir(dir_hnd);
                }
        }
        
@@ -1674,27 +2080,28 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
 {
        int outsize = 0;
        pstring name;
-       int dirtype;
+       uint32 dirtype;
        NTSTATUS status;
+       BOOL path_contains_wcard = False;
+
        START_PROFILE(SMBunlink);
-       
+
        dirtype = SVAL(inbuf,smb_vwv0);
        
-       srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
+       srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBunlink);
                return ERROR_NT(status);
        }
        
-       RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+       RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
        
        DEBUG(3,("reply_unlink : %s\n",name));
        
-       status = unlink_internals(conn, dirtype, name);
+       status = unlink_internals(conn, dirtype, name, path_contains_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
-                       clear_cached_errors();
                        return -1;
                }
                return ERROR_NT(status);
@@ -1706,7 +2113,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
         */
        process_pending_change_notify_queue((time_t)0);
        
-       outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,False);
   
        END_PROFILE(SMBunlink);
        return outsize;
@@ -1775,15 +2182,16 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st
         * reply_readbraw has already checked the length.
         */
 
-       if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
+       if ( (chain_size == 0) && (nread > 0) &&
+           (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
                DATA_BLOB header;
 
                _smb_setlen(outbuf,nread);
-               header.data = outbuf;
+               header.data = (uint8 *)outbuf;
                header.length = 4;
                header.free = NULL;
 
-               if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
+               if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
                        /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
                        if (errno == ENOSYS) {
                                goto normal_readbraw;
@@ -1840,7 +2248,6 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st
 
 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
 {
-       extern struct current_user current_user;
        ssize_t maxcount,mincount;
        size_t nread = 0;
        SMB_OFF_T startpos;
@@ -1858,15 +2265,6 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
         * return a zero length response here.
         */
 
-       if(global_oplock_break) {
-               _smb_setlen(header,0);
-               if (write_data(smbd_server_fd(),header,4) != 4)
-                       fail_readraw();
-               DEBUG(5,("readbraw - oplock break finished\n"));
-               END_PROFILE(SMBreadbraw);
-               return -1;
-       }
-
        fsp = file_fsp(inbuf,smb_vwv0);
 
        if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
@@ -1927,22 +2325,19 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
        /* ensure we don't overrun the packet size */
        maxcount = MIN(65535,maxcount);
 
-       if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
-               SMB_OFF_T size = fsp->size;
-               SMB_OFF_T sizeneeded = startpos + maxcount;
+       if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+               SMB_STRUCT_STAT st;
+               SMB_OFF_T size = 0;
   
-               if (size < sizeneeded) {
-                       SMB_STRUCT_STAT st;
-                       if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
-                               size = st.st_size;
-                       if (!fsp->can_write) 
-                               fsp->size = size;
+               if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
+                       size = st.st_size;
                }
 
-               if (startpos >= size)
+               if (startpos >= size) {
                        nread = 0;
-               else
+               } else {
                        nread = MIN(maxcount,(size - startpos));          
+               }
        }
 
 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
@@ -1950,8 +2345,8 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
                nread = 0;
 #endif
   
-       DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
-                               (int)maxcount, (int)mincount, (int)nread ) );
+       DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
+                               (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
   
        send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
 
@@ -1960,6 +2355,9 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
        return -1;
 }
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_LOCKING
+
 /****************************************************************************
  Reply to a lockread (core+ protocol).
 ****************************************************************************/
@@ -1977,7 +2375,9 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
        START_PROFILE(SMBlockread);
 
        CHECK_FSP(fsp,conn);
-       CHECK_READ(fsp);
+       if (!CHECK_READ(fsp,inbuf)) {
+               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       }
 
        release_level_2_oplocks_on_change(fsp);
 
@@ -1996,8 +2396,13 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
         * Note that the requested lock size is unaffected by max_recv.
         */
        
-       status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), 
-                        (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
+       status = do_lock_spin(fsp,
+                               (uint32)SVAL(inbuf,smb_pid), 
+                               (SMB_BIG_UINT)numtoread,
+                               (SMB_BIG_UINT)startpos,
+                               WRITE_LOCK,
+                               WINDOWS_LOCK,
+                               &my_lock_ctx);
 
        if (NT_STATUS_V(status)) {
 #if 0
@@ -2013,8 +2418,15 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
                         * this smb into a queued request and push it
                         * onto the blocking lock queue.
                         */
-                       if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
-                                                               (SMB_BIG_UINT)numtoread)) {
+                       if(push_blocking_lock_request(inbuf, length,
+                                       fsp,
+                                       -1,
+                                       0,
+                                       SVAL(inbuf,smb_pid),
+                                       WRITE_LOCK,
+                                       WINDOWS_LOCK,
+                                       (SMB_BIG_UINT)startpos,
+                                       (SMB_BIG_UINT)numtoread)) {
                                END_PROFILE(SMBlockread);
                                return -1;
                        }
@@ -2053,6 +2465,9 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
        return(outsize);
 }
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_ALL
+
 /****************************************************************************
  Reply to a read.
 ****************************************************************************/
@@ -2068,7 +2483,9 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        START_PROFILE(SMBread);
 
        CHECK_FSP(fsp,conn);
-       CHECK_READ(fsp);
+       if (!CHECK_READ(fsp,inbuf)) {
+               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       }
 
        numtoread = SVAL(inbuf,smb_vwv1);
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
@@ -2087,7 +2504,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
 
        data = smb_buf(outbuf) + 3;
   
-       if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
                END_PROFILE(SMBread);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -2131,12 +2548,12 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
         * on a train in Germany :-). JRA.
         */
 
-       if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
-                       (lp_write_cache_size(SNUM(conn)) == 0) ) {
+       if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
+           lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
                SMB_STRUCT_STAT sbuf;
                DATA_BLOB header;
 
-               if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
+               if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
                        return(UNIXERROR(ERRDOS,ERRnoaccess));
 
                if (startpos > sbuf.st_size)
@@ -2161,11 +2578,11 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
                SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
                SCVAL(outbuf,smb_vwv0,0xFF);
                set_message(outbuf,12,smb_maxcnt,False);
-               header.data = outbuf;
+               header.data = (uint8 *)outbuf;
                header.length = data - outbuf;
                header.free = NULL;
 
-               if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
+               if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
                        /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
                        if (errno == ENOSYS) {
                                goto normal_read;
@@ -2212,7 +2629,6 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
        nread = read_file(fsp,data,startpos,smb_maxcnt);
   
        if (nread < 0) {
-               END_PROFILE(SMBreadX);
                return(UNIXERROR(ERRDOS,ERRnoaccess));
        }
 
@@ -2253,7 +2669,9 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        }
 
        CHECK_FSP(fsp,conn);
-       CHECK_READ(fsp);
+       if (!CHECK_READ(fsp,inbuf)) {
+               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       }
 
        set_message(outbuf,12,0,True);
 
@@ -2293,11 +2711,16 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
 
        }
 
-       if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
                END_PROFILE(SMBreadX);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
 
+       if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
+               END_PROFILE(SMBreadX);
+               return -1;
+       }
+
        nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
        if (nread != -1)
                nread = chain_reply(inbuf,outbuf,length,bufsize);
@@ -2328,7 +2751,9 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
        }
 
        CHECK_FSP(fsp,conn);
-       CHECK_WRITE(fsp);
+       if (!CHECK_WRITE(fsp)) {
+               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       }
   
        tcount = IVAL(inbuf,smb_vwv1);
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
@@ -2349,7 +2774,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
        SCVAL(inbuf,smb_com,SMBwritec);
        SCVAL(outbuf,smb_com,SMBwritec);
 
-       if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
                END_PROFILE(SMBwritebraw);
                return(ERROR_DOS(ERRDOS,ERRlock));
        }
@@ -2371,6 +2796,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
        SCVAL(outbuf,smb_com,SMBwritebraw);
        SSVALS(outbuf,smb_vwv0,-1);
        outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
+       show_msg(outbuf);
        if (!send_smb(smbd_server_fd(),outbuf))
                exit_server("reply_writebraw: send_smb failed.");
   
@@ -2385,7 +2811,6 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
        /* Set up outbuf to return the correct return */
        outsize = set_message(outbuf,1,0,True);
        SCVAL(outbuf,smb_com,SMBwritec);
-       SSVAL(outbuf,smb_vwv0,total_written);
 
        if (numtowrite != 0) {
 
@@ -2417,8 +2842,9 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
                        total_written += nwritten;
        }
  
-       if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
-               sync_file(conn,fsp);
+       SSVAL(outbuf,smb_vwv0,total_written);
+
+       sync_file(conn, fsp, write_through);
 
        DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
                fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
@@ -2441,6 +2867,9 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
        return(outsize);
 }
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_LOCKING
+
 /****************************************************************************
  Reply to a writeunlock (core+).
 ****************************************************************************/
@@ -2458,13 +2887,15 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
        START_PROFILE(SMBwriteunlock);
        
        CHECK_FSP(fsp,conn);
-       CHECK_WRITE(fsp);
+       if (!CHECK_WRITE(fsp)) {
+               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       }
 
        numtowrite = SVAL(inbuf,smb_vwv1);
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
        data = smb_buf(inbuf) + 3;
   
-       if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
                END_PROFILE(SMBwriteunlock);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -2472,13 +2903,13 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
        /* The special X/Open SMB protocol handling of
           zero length writes is *NOT* done for
           this call */
-       if(numtowrite == 0)
+       if(numtowrite == 0) {
                nwritten = 0;
-       else
+       } else {
                nwritten = write_file(fsp,data,startpos,numtowrite);
+       }
   
-       if (lp_syncalways(SNUM(conn)))
-               sync_file(conn,fsp);
+       sync_file(conn, fsp, False /* write through */);
 
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
                END_PROFILE(SMBwriteunlock);
@@ -2486,8 +2917,12 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
        }
 
        if (numtowrite) {
-               status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, 
-                                  (SMB_BIG_UINT)startpos);
+               status = do_unlock(fsp,
+                               (uint32)SVAL(inbuf,smb_pid),
+                               (SMB_BIG_UINT)numtowrite, 
+                               (SMB_BIG_UINT)startpos,
+                               WINDOWS_LOCK);
+
                if (NT_STATUS_V(status)) {
                        END_PROFILE(SMBwriteunlock);
                        return ERROR_NT(status);
@@ -2505,6 +2940,9 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
        return outsize;
 }
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_ALL
+
 /****************************************************************************
  Reply to a write.
 ****************************************************************************/
@@ -2526,13 +2964,15 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
        }
 
        CHECK_FSP(fsp,conn);
-       CHECK_WRITE(fsp);
+       if (!CHECK_WRITE(fsp)) {
+               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       }
 
        numtowrite = SVAL(inbuf,smb_vwv1);
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
        data = smb_buf(inbuf) + 3;
   
-       if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
                END_PROFILE(SMBwrite);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -2560,8 +3000,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
        } else
                nwritten = write_file(fsp,data,startpos,numtowrite);
   
-       if (lp_syncalways(SNUM(conn)))
-               sync_file(conn,fsp);
+       sync_file(conn, fsp, False);
 
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
                END_PROFILE(SMBwrite);
@@ -2607,11 +3046,16 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
        }
 
        CHECK_FSP(fsp,conn);
-       CHECK_WRITE(fsp);
+       if (!CHECK_WRITE(fsp)) {
+               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       }
 
+       set_message(outbuf,6,0,True);
+  
        /* Deal with possible LARGE_WRITEX */
-       if (large_writeX)
+       if (large_writeX) {
                numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
+       }
 
        if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
                END_PROFILE(SMBwriteX);
@@ -2643,7 +3087,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
 #endif /* LARGE_SMB_OFF_T */
        }
 
-       if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
                END_PROFILE(SMBwriteX);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -2653,18 +3097,24 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
        done, just a write of zero. To truncate a file,
        use SMBwrite. */
 
-       if(numtowrite == 0)
+       if(numtowrite == 0) {
                nwritten = 0;
-       else
+       } else {
+
+               if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
+                                       fsp,data,startpos,numtowrite)) {
+                       END_PROFILE(SMBwriteX);
+                       return -1;
+               }
+
                nwritten = write_file(fsp,data,startpos,numtowrite);
+       }
   
        if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
                END_PROFILE(SMBwriteX);
                return(UNIXERROR(ERRHRD,ERRdiskfull));
        }
 
-       set_message(outbuf,6,0,True);
-  
        SSVAL(outbuf,smb_vwv2,nwritten);
        if (large_writeX)
                SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
@@ -2677,8 +3127,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
        DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
                fsp->fnum, (int)numtowrite, (int)nwritten));
 
-       if (lp_syncalways(SNUM(conn)) || write_through)
-               sync_file(conn,fsp);
+       sync_file(conn, fsp, write_through);
 
        END_PROFILE(SMBwriteX);
        return chain_reply(inbuf,outbuf,length,bufsize);
@@ -2712,7 +3161,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
                        break;
                case 1:
                        umode = SEEK_CUR;
-                       res = fsp->pos + startpos;
+                       res = fsp->fh->pos + startpos;
                        break;
                case 2:
                        umode = SEEK_END;
@@ -2724,19 +3173,19 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        }
 
        if (umode == SEEK_END) {
-               if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
+               if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
                        if(errno == EINVAL) {
                                SMB_OFF_T current_pos = startpos;
                                SMB_STRUCT_STAT sbuf;
 
-                               if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
+                               if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
                                        END_PROFILE(SMBlseek);
                                        return(UNIXERROR(ERRDOS,ERRnoaccess));
                                }
 
                                current_pos += sbuf.st_size;
                                if(current_pos < 0)
-                                       res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
+                                       res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
                        }
                }
 
@@ -2746,7 +3195,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
                }
        }
 
-       fsp->pos = res;
+       fsp->fh->pos = res;
   
        outsize = set_message(outbuf,2,0,True);
        SIVAL(outbuf,smb_vwv0,res);
@@ -2764,7 +3213,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
 
 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
 {
-       int outsize = set_message(outbuf,0,0,True);
+       int outsize = set_message(outbuf,0,0,False);
        uint16 fnum = SVAL(inbuf,smb_vwv0);
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
        START_PROFILE(SMBflush);
@@ -2775,7 +3224,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        if (!fsp) {
                file_sync_all(conn);
        } else {
-               sync_file(conn,fsp);
+               sync_file(conn,fsp, True);
        }
        
        DEBUG(3,("flush\n"));
@@ -2785,6 +3234,7 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int
 
 /****************************************************************************
  Reply to a exit.
+ conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
 int reply_exit(connection_struct *conn, 
@@ -2793,9 +3243,9 @@ int reply_exit(connection_struct *conn,
        int outsize;
        START_PROFILE(SMBexit);
 
-       file_close_pid(SVAL(inbuf,smb_pid));
+       file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
 
-       outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,False);
 
        DEBUG(3,("exit\n"));
 
@@ -2810,14 +3260,13 @@ int reply_exit(connection_struct *conn,
 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
                 int dum_buffsize)
 {
-       extern struct current_user current_user;
        int outsize = 0;
        time_t mtime;
        int32 eclass = 0, err = 0;
        files_struct *fsp = NULL;
        START_PROFILE(SMBclose);
 
-       outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,False);
 
        /* If it's an IPC, pass off to the pipe handler. */
        if (IS_IPC(conn)) {
@@ -2841,7 +3290,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
                 * Special case - close NT SMB directory handle.
                 */
                DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
-               close_file(fsp,True);
+               close_file(fsp,NORMAL_CLOSE);
        } else {
                /*
                 * Close ordinary file.
@@ -2853,30 +3302,27 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
                pstrcpy( file_name, fsp->fsp_name);
 
                DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
-                        fsp->fd, fsp->fnum,
+                        fsp->fh->fd, fsp->fnum,
                         conn->num_files_open));
  
+               /*
+                * Take care of any time sent in the close.
+                */
+
+               mtime = srv_make_unix_date3(inbuf+smb_vwv1);
+               fsp_set_pending_modtime(fsp, mtime);
+
                /*
                 * close_file() returns the unix errno if an error
                 * was detected on close - normally this is due to
                 * a disk full error. If not then it was probably an I/O error.
                 */
  
-               if((close_err = close_file(fsp,True)) != 0) {
+               if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) {
                        errno = close_err;
                        END_PROFILE(SMBclose);
                        return (UNIXERROR(ERRHRD,ERRgeneral));
                }
-
-               /*
-                * Now take care of any time sent in the close.
-                */
-
-               mtime = make_unix_date3(inbuf+smb_vwv1);
-               
-               /* try and set the date */
-               set_filetime(conn, file_name, mtime);
-
        }  
 
        /* We have a cached error */
@@ -2907,14 +3353,16 @@ int reply_writeclose(connection_struct *conn,
        START_PROFILE(SMBwriteclose);
 
        CHECK_FSP(fsp,conn);
-       CHECK_WRITE(fsp);
+       if (!CHECK_WRITE(fsp)) {
+               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       }
 
        numtowrite = SVAL(inbuf,smb_vwv1);
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
-       mtime = make_unix_date3(inbuf+smb_vwv4);
+       mtime = srv_make_unix_date3(inbuf+smb_vwv4);
        data = smb_buf(inbuf) + 1;
   
-       if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+       if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
                END_PROFILE(SMBwriteclose);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -2931,7 +3379,7 @@ int reply_writeclose(connection_struct *conn,
        if (numtowrite) {
                DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
                        fsp->fsp_name ));
-               close_err = close_file(fsp,True);
+               close_err = close_file(fsp,NORMAL_CLOSE);
        }
 
        DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
@@ -2956,6 +3404,9 @@ int reply_writeclose(connection_struct *conn,
        return(outsize);
 }
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_LOCKING
+
 /****************************************************************************
  Reply to a lock.
 ****************************************************************************/
@@ -2963,7 +3414,7 @@ int reply_writeclose(connection_struct *conn,
 int reply_lock(connection_struct *conn,
               char *inbuf,char *outbuf, int length, int dum_buffsize)
 {
-       int outsize = set_message(outbuf,0,0,True);
+       int outsize = set_message(outbuf,0,0,False);
        SMB_BIG_UINT count,offset;
        NTSTATUS status;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
@@ -2979,9 +3430,15 @@ int reply_lock(connection_struct *conn,
        offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
 
        DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
-                fsp->fd, fsp->fnum, (double)offset, (double)count));
-
-       status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
+                fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
+
+       status = do_lock_spin(fsp,
+                               (uint32)SVAL(inbuf,smb_pid),
+                               count,
+                               offset,
+                               WRITE_LOCK,
+                               WINDOWS_LOCK,
+                               &my_lock_ctx);
        if (NT_STATUS_V(status)) {
 #if 0
                /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
@@ -2991,7 +3448,14 @@ int reply_lock(connection_struct *conn,
                         * this smb into a queued request and push it
                         * onto the blocking lock queue.
                         */
-                       if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
+                       if(push_blocking_lock_request(inbuf, length,
+                               fsp,
+                               -1,
+                               0,
+                               SVAL(inbuf,smb_pid),
+                               WRITE_LOCK,
+                               WINDOWS_LOCK,
+                               offset, count)) {
                                END_PROFILE(SMBlock);
                                return -1;
                        }
@@ -3012,7 +3476,7 @@ int reply_lock(connection_struct *conn,
 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
                 int dum_buffsize)
 {
-       int outsize = set_message(outbuf,0,0,True);
+       int outsize = set_message(outbuf,0,0,False);
        SMB_BIG_UINT count,offset;
        NTSTATUS status;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
@@ -3023,27 +3487,36 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
        count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
        offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
        
-       status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
+       status = do_unlock(fsp,
+                       (uint32)SVAL(inbuf,smb_pid),
+                       count,
+                       offset,
+                       WINDOWS_LOCK);
+
        if (NT_STATUS_V(status)) {
                END_PROFILE(SMBunlock);
                return ERROR_NT(status);
        }
 
        DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
-                   fsp->fd, fsp->fnum, (double)offset, (double)count ) );
+                   fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
        
        END_PROFILE(SMBunlock);
        return(outsize);
 }
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_ALL
+
 /****************************************************************************
  Reply to a tdis.
+ conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
 int reply_tdis(connection_struct *conn, 
               char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-       int outsize = set_message(outbuf,0,0,True);
+       int outsize = set_message(outbuf,0,0,False);
        uint16 vuid;
        START_PROFILE(SMBtdis);
 
@@ -3065,6 +3538,7 @@ int reply_tdis(connection_struct *conn,
 
 /****************************************************************************
  Reply to a echo.
+ conn POINTER CAN BE NULL HERE !
 ****************************************************************************/
 
 int reply_echo(connection_struct *conn,
@@ -3096,6 +3570,7 @@ int reply_echo(connection_struct *conn,
 
                smb_setlen(outbuf,outsize - 4);
 
+               show_msg(outbuf);
                if (!send_smb(smbd_server_fd(),outbuf))
                        exit_server("reply_echo: send_smb failed.");
        }
@@ -3117,6 +3592,8 @@ int reply_printopen(connection_struct *conn,
 {
        int outsize = 0;
        files_struct *fsp;
+       NTSTATUS status;
+       
        START_PROFILE(SMBsplopen);
        
        if (!CAN_PRINT(conn)) {
@@ -3125,18 +3602,18 @@ int reply_printopen(connection_struct *conn,
        }
 
        /* Open for exclusive use, write only. */
-       fsp = print_fsp_open(conn, NULL);
+       status = print_fsp_open(conn, NULL, &fsp);
 
-       if (!fsp) {
+       if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBsplopen);
-               return(UNIXERROR(ERRDOS,ERRnoaccess));
+               return(ERROR_NT(status));
        }
 
        outsize = set_message(outbuf,1,0,True);
        SSVAL(outbuf,smb_vwv0,fsp->fnum);
   
        DEBUG(3,("openprint fd=%d fnum=%d\n",
-                fsp->fd, fsp->fnum));
+                fsp->fh->fd, fsp->fnum));
 
        END_PROFILE(SMBsplopen);
        return(outsize);
@@ -3149,7 +3626,7 @@ int reply_printopen(connection_struct *conn,
 int reply_printclose(connection_struct *conn,
                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-       int outsize = set_message(outbuf,0,0,True);
+       int outsize = set_message(outbuf,0,0,False);
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
        int close_err = 0;
        START_PROFILE(SMBsplclose);
@@ -3162,9 +3639,9 @@ int reply_printclose(connection_struct *conn,
        }
   
        DEBUG(3,("printclose fd=%d fnum=%d\n",
-                fsp->fd,fsp->fnum));
+                fsp->fh->fd,fsp->fnum));
   
-       close_err = close_file(fsp,True);
+       close_err = close_file(fsp,NORMAL_CLOSE);
 
        if(close_err != 0) {
                errno = close_err;
@@ -3221,7 +3698,7 @@ int reply_printqueue(connection_struct *conn,
     
 
                for (i=first;i<first+num_to_get;i++) {
-                       put_dos_date2(p,0,queue[i].time);
+                       srv_put_dos_date2(p,0,queue[i].time);
                        SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
                        SSVAL(p,5, queue[i].job);
                        SIVAL(p,7,queue[i].size);
@@ -3254,7 +3731,7 @@ int reply_printqueue(connection_struct *conn,
 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
        int numtowrite;
-       int outsize = set_message(outbuf,0,0,True);
+       int outsize = set_message(outbuf,0,0,False);
        char *data;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
 
@@ -3266,7 +3743,9 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_
        }
 
        CHECK_FSP(fsp,conn);
-       CHECK_WRITE(fsp);
+       if (!CHECK_WRITE(fsp)) {
+               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       }
 
        numtowrite = SVAL(smb_buf(inbuf),1);
        data = smb_buf(inbuf) + 3;
@@ -3287,29 +3766,32 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_
  code. 
 ****************************************************************************/
 
-NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
+NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
 {
-       BOOL bad_path = False;
-       SMB_STRUCT_STAT sbuf;
        int ret= -1;
        
-       unix_convert(directory,conn,0,&bad_path,&sbuf);
-
-       if( strchr_m(directory, ':')) {
-               return NT_STATUS_NOT_A_DIRECTORY;
-       }
-
-       if (ms_has_wild(directory)) {
-               return NT_STATUS_OBJECT_NAME_INVALID;
+       if(!CAN_WRITE(conn)) {
+               DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
+               errno = EACCES;
+               return map_nt_error_from_unix(errno);
        }
 
        if (bad_path) {
                return NT_STATUS_OBJECT_PATH_NOT_FOUND;
        }
 
-       if (check_name(directory, conn))
-               ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
-       
+       if (!check_name(directory, conn)) {
+               if(errno == ENOENT) {
+                       if (bad_path) {
+                               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+                       } else {
+                               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+                       }
+               }
+               return map_nt_error_from_unix(errno);
+       }
+
+       ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
        if (ret == -1) {
                if(errno == ENOENT) {
                        return NT_STATUS_OBJECT_NAME_NOT_FOUND;
@@ -3329,9 +3811,12 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        pstring directory;
        int outsize;
        NTSTATUS status;
+       BOOL bad_path = False;
+       SMB_STRUCT_STAT sbuf;
+
        START_PROFILE(SMBmkdir);
  
-       srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
+       srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmkdir);
                return ERROR_NT(status);
@@ -3339,13 +3824,50 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 
        RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
 
-       status = mkdir_internal(conn, directory);
+       unix_convert(directory,conn,0,&bad_path,&sbuf);
+
+       if( is_ntfs_stream_name(directory)) {
+               DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
+               END_PROFILE(SMBmkdir);
+               return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
+       }
+
+       status = mkdir_internal(conn, directory,bad_path);
        if (!NT_STATUS_IS_OK(status)) {
+
+               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION) &&
+                   !use_nt_status()) {
+                       /*
+                        * Yes, in the DOS error code case we get a
+                        * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
+                        * samba4 torture test.
+                        */
+                       status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
+               }
+
                END_PROFILE(SMBmkdir);
                return ERROR_NT(status);
        }
 
-       outsize = set_message(outbuf,0,0,True);
+       if (lp_inherit_owner(SNUM(conn))) {
+               /* Ensure we're checking for a symlink here.... */
+               /* We don't want to get caught by a symlink racer. */
+
+               if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
+                       END_PROFILE(SMBmkdir);
+                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+               }
+                                                                                                                                                   
+               if(!S_ISDIR(sbuf.st_mode)) {
+                       DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
+                       END_PROFILE(SMBmkdir);
+                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+               }
+
+               change_owner_to_parent(conn, NULL, directory, &sbuf);
+       }
+
+       outsize = set_message(outbuf,0,0,False);
 
        DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
 
@@ -3363,18 +3885,21 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
        const char *dname = NULL;
        BOOL ret = False;
        long offset = 0;
-       void *dirptr = OpenDir(conn, directory, False);
+       struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
 
-       if(dirptr == NULL)
+       if(dir_hnd == NULL)
                return True;
 
-       while((dname = ReadDirName(dirptr, &offset))) {
+       while((dname = ReadDirName(dir_hnd, &offset))) {
                pstring fullname;
                SMB_STRUCT_STAT st;
 
                if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
                        continue;
 
+               if (!is_visible_file(conn, directory, dname, &st, False))
+                       continue;
+
                /* Construct the full name. */
                if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
                        errno = ENOMEM;
@@ -3405,7 +3930,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
                        break;
                }
        }
-       CloseDir(dirptr);
+       CloseDir(dir_hnd);
        return ret;
 }
 
@@ -3416,6 +3941,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
 BOOL rmdir_internals(connection_struct *conn, char *directory)
 {
        BOOL ok;
+       SMB_STRUCT_STAT st;
 
        ok = (SMB_VFS_RMDIR(conn,directory) == 0);
        if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
@@ -3427,13 +3953,15 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
                 */
                BOOL all_veto_files = True;
                const char *dname;
-               void *dirptr = OpenDir(conn, directory, False);
+               struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
 
-               if(dirptr != NULL) {
-                       long dirpos = TellDir(dirptr);
-                       while ((dname = ReadDirName(dirptr,&dirpos))) {
+               if(dir_hnd != NULL) {
+                       long dirpos = 0;
+                       while ((dname = ReadDirName(dir_hnd,&dirpos))) {
                                if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
                                        continue;
+                               if (!is_visible_file(conn, directory, dname, &st, False))
+                                       continue;
                                if(!IS_VETO_PATH(conn, dname)) {
                                        all_veto_files = False;
                                        break;
@@ -3441,13 +3969,14 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
                        }
 
                        if(all_veto_files) {
-                               SeekDir(dirptr,dirpos);
-                               while ((dname = ReadDirName(dirptr,&dirpos))) {
+                               RewindDir(dir_hnd,&dirpos);
+                               while ((dname = ReadDirName(dir_hnd,&dirpos))) {
                                        pstring fullname;
-                                       SMB_STRUCT_STAT st;
 
                                        if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
                                                continue;
+                                       if (!is_visible_file(conn, directory, dname, &st, False))
+                                               continue;
 
                                        /* Construct the full name. */
                                        if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
@@ -3471,11 +4000,11 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
                                        } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
                                                break;
                                }
-                               CloseDir(dirptr);
+                               CloseDir(dir_hnd);
                                /* Retry the rmdir */
                                ok = (SMB_VFS_RMDIR(conn,directory) == 0);
                        } else {
-                               CloseDir(dirptr);
+                               CloseDir(dir_hnd);
                        }
                } else {
                        errno = ENOTEMPTY;
@@ -3502,7 +4031,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        NTSTATUS status;
        START_PROFILE(SMBrmdir);
 
-       srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
+       srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBrmdir);
                return ERROR_NT(status);
@@ -3526,7 +4055,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
        }
  
-       outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,False);
   
        DEBUG( 3, ( "rmdir %s\n", directory ) );
   
@@ -3621,15 +4150,24 @@ static BOOL resolve_wildcards(const char *name1, char *name2)
 }
 
 /****************************************************************************
- Ensure open files have their names updates.
+ Ensure open files have their names updated. Updated to notify other smbd's
+ asynchronously.
 ****************************************************************************/
 
-static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
+static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
+                               SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
 {
        files_struct *fsp;
        BOOL did_rename = False;
 
        for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
+               /* fsp_name is a relative path under the fsp. To change this for other
+                  sharepaths we need to manipulate relative paths. */
+               /* TODO - create the absolute path and manipulate the newname
+                  relative to the sharepath. */
+               if (fsp->conn != conn) {
+                       continue;
+               }
                DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
                        fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
                        fsp->fsp_name, newname ));
@@ -3637,16 +4175,49 @@ static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T
                did_rename = True;
        }
 
-       if (!did_rename)
+       if (!did_rename) {
                DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
                        (unsigned int)dev, (double)inode, newname ));
+       }
+
+       /* Send messages to all smbd's (not ourself) that the name has changed. */
+       rename_share_filename(lck, conn->connectpath, newname);
+}
+
+/****************************************************************************
+ We need to check if the source path is a parent directory of the destination
+ (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
+ refuse the rename with a sharing violation. Under UNIX the above call can
+ *succeed* if /foo/bar/baz is a symlink to another area in the share. We
+ probably need to check that the client is a Windows one before disallowing
+ this as a UNIX client (one with UNIX extensions) can know the source is a
+ symlink and make this decision intelligently. Found by an excellent bug
+ report from <AndyLiebman@aol.com>.
+****************************************************************************/
+
+static BOOL rename_path_prefix_equal(const char *src, const char *dest)
+{
+       const char *psrc = src;
+       const char *pdst = dest;
+       size_t slen;
+
+       if (psrc[0] == '.' && psrc[1] == '/') {
+               psrc += 2;
+       }
+       if (pdst[0] == '.' && pdst[1] == '/') {
+               pdst += 2;
+       }
+       if ((slen = strlen(psrc)) > strlen(pdst)) {
+               return False;
+       }
+       return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
 }
 
 /****************************************************************************
  Rename an open file - given an fsp.
 ****************************************************************************/
 
-NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
+NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists)
 {
        SMB_STRUCT_STAT sbuf;
        BOOL bad_path = False;
@@ -3654,6 +4225,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
        NTSTATUS error = NT_STATUS_OK;
        BOOL dest_exists;
        BOOL rcdest = True;
+       struct share_mode_lock *lck = NULL;
 
        ZERO_STRUCT(sbuf);
        rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
@@ -3727,7 +4299,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
-       error = can_rename(newname,conn,attrs,&sbuf);
+       error = can_rename(conn,newname,attrs,&sbuf);
 
        if (dest_exists && !NT_STATUS_IS_OK(error)) {
                DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
@@ -3737,17 +4309,27 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
                return error;
        }
 
+       if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
+
        if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
                DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
                        fsp->fsp_name,newname));
-               rename_open_files(conn, fsp->dev, fsp->inode, newname);
+               rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
+               TALLOC_FREE(lck);
                return NT_STATUS_OK;    
        }
 
-       if (errno == ENOTDIR || errno == EISDIR)
+       TALLOC_FREE(lck);
+
+       if (errno == ENOTDIR || errno == EISDIR) {
                error = NT_STATUS_OBJECT_NAME_COLLISION;
-       else
+       } else {
                error = map_nt_error_from_unix(errno);
+       }
                
        DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
                nt_errstr(error), fsp->fsp_name,newname));
@@ -3760,14 +4342,13 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
  code. 
 ****************************************************************************/
 
-NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
+NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild)
 {
        pstring directory;
        pstring mask;
        pstring last_component_src;
        pstring last_component_dest;
        char *p;
-       BOOL has_wild;
        BOOL bad_path_src = False;
        BOOL bad_path_dest = False;
        int count=0;
@@ -3775,6 +4356,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui
        BOOL rc = True;
        BOOL rcdest = True;
        SMB_STRUCT_STAT sbuf1, sbuf2;
+       struct share_mode_lock *lck = NULL;
 
        *directory = *mask = 0;
 
@@ -3833,16 +4415,14 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui
         * Tine Smukavec <valentin.smukavec@hermes.si>.
         */
 
-       if (!rc && mangle_is_mangled(mask))
-               mangle_check_cache( mask, sizeof(pstring)-1 );
-
-       has_wild = ms_has_wild(mask);
+       if (!rc && mangle_is_mangled(mask, conn->params))
+               mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
 
        if (!has_wild) {
                /*
                 * No wildcards - just process the one file.
                 */
-               BOOL is_short_name = mangle_is_8_3(name, True);
+               BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
 
                /* Add a terminating '/' to the directory name. */
                pstrcat(directory,"/");
@@ -3933,7 +4513,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                        return NT_STATUS_OBJECT_PATH_NOT_FOUND;
                }
 
-               error = can_rename(directory,conn,attrs,&sbuf1);
+               error = can_rename(conn,directory,attrs,&sbuf1);
 
                if (!NT_STATUS_IS_OK(error)) {
                        DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
@@ -3947,7 +4527,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                 */
 
                if (strcsequal(directory, newname)) {
-                       rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
+                       rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
                        DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
                        return NT_STATUS_OK;
                }
@@ -3958,13 +4538,21 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                        return NT_STATUS_OBJECT_NAME_COLLISION;
                }
 
+               if (rename_path_prefix_equal(directory, newname)) {
+                       return NT_STATUS_SHARING_VIOLATION;
+               }
+
+               lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
+
                if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
                        DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
                                directory,newname));
-                       rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
+                       rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
+                       TALLOC_FREE(lck);
                        return NT_STATUS_OK;    
                }
 
+               TALLOC_FREE(lck);
                if (errno == ENOTDIR || errno == EISDIR)
                        error = NT_STATUS_OBJECT_NAME_COLLISION;
                else
@@ -3978,22 +4566,22 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                /*
                 * Wildcards - process each file that matches.
                 */
-               void *dirptr = NULL;
+               struct smb_Dir *dir_hnd = NULL;
                const char *dname;
                pstring destname;
                
+               if (strequal(mask,"????????.???"))
+                       pstrcpy(mask,"*");
+                       
                if (check_name(directory,conn))
-                       dirptr = OpenDir(conn, directory, True);
+                       dir_hnd = OpenDir(conn, directory, mask, attrs);
                
-               if (dirptr) {
+               if (dir_hnd) {
                        long offset = 0;
                        error = NT_STATUS_NO_SUCH_FILE;
 /*                     Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
                        
-                       if (strequal(mask,"????????.???"))
-                               pstrcpy(mask,"*");
-                       
-                       while ((dname = ReadDirName(dirptr, &offset))) {
+                       while ((dname = ReadDirName(dir_hnd, &offset))) {
                                pstring fname;
                                BOOL sysdir_entry = False;
 
@@ -4010,6 +4598,9 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                                        }
                                }
 
+                               if (!is_visible_file(conn, directory, dname, &sbuf1, False))
+                                       continue;
+
                                if(!mask_match(fname, mask, conn->case_sensitive))
                                        continue;
                                
@@ -4025,7 +4616,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                                        DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
                                        continue;
                                }
-                               error = can_rename(fname,conn,attrs,&sbuf1);
+                               error = can_rename(conn,fname,attrs,&sbuf1);
                                if (!NT_STATUS_IS_OK(error)) {
                                        DEBUG(6,("rename %s refused\n", fname));
                                        continue;
@@ -4039,7 +4630,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                                }
                                
                                if (strcsequal(fname,destname)) {
-                                       rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
+                                       rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
                                        DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
                                        count++;
                                        error = NT_STATUS_OK;
@@ -4053,14 +4644,21 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
                                        continue;
                                }
                                
+                               if (rename_path_prefix_equal(fname, destname)) {
+                                       return NT_STATUS_SHARING_VIOLATION;
+                               }
+
+                               lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
+
                                if (!SMB_VFS_RENAME(conn,fname,destname)) {
-                                       rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
+                                       rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
                                        count++;
                                        error = NT_STATUS_OK;
                                }
+                               TALLOC_FREE(lck);
                                DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
                        }
-                       CloseDir(dirptr);
+                       CloseDir(dir_hnd);
                }
 
                if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
@@ -4090,35 +4688,35 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        pstring name;
        pstring newname;
        char *p;
-       uint16 attrs = SVAL(inbuf,smb_vwv0);
+       uint32 attrs = SVAL(inbuf,smb_vwv0);
        NTSTATUS status;
+       BOOL path_contains_wcard = False;
 
        START_PROFILE(SMBmv);
 
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
+       p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                return ERROR_NT(status);
        }
        p++;
-       p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
+       p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                return ERROR_NT(status);
        }
        
-       RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
-       RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
+       RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
+       RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
        
        DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
        
-       status = rename_internals(conn, name, newname, attrs, False);
+       status = rename_internals(conn, name, newname, attrs, False, path_contains_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
                        /* We have re-scheduled this call. */
-                       clear_cached_errors();
                        return -1;
                }
                return ERROR_NT(status);
@@ -4129,7 +4727,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
         * update after a rename..
         */     
        process_pending_change_notify_queue((time_t)0);
-       outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,False);
   
        END_PROFILE(SMBmv);
        return(outsize);
@@ -4139,56 +4737,78 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
  Copy a file as part of a reply_copy.
 ******************************************************************/
 
-static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
+BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
                      int count,BOOL target_is_directory, int *err_ret)
 {
-       int Access,action;
        SMB_STRUCT_STAT src_sbuf, sbuf2;
        SMB_OFF_T ret=-1;
        files_struct *fsp1,*fsp2;
        pstring dest;
        uint32 dosattrs;
+       uint32 new_create_disposition;
+       NTSTATUS status;
  
        *err_ret = 0;
 
        pstrcpy(dest,dest1);
        if (target_is_directory) {
                char *p = strrchr_m(src,'/');
-               if (p) 
+               if (p) {
                        p++;
-               else
+               } else {
                        p = src;
+               }
                pstrcat(dest,"/");
                pstrcat(dest,p);
        }
 
-       if (!vfs_file_exist(conn,src,&src_sbuf))
+       if (!vfs_file_exist(conn,src,&src_sbuf)) {
                return(False);
+       }
+
+       if (!target_is_directory && count) {
+               new_create_disposition = FILE_OPEN;
+       } else {
+               if (!map_open_params_to_ntcreate(dest1,0,ofun,
+                               NULL, NULL, &new_create_disposition, NULL)) {
+                       return(False);
+               }
+       }
 
-       fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
-                                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
-                                       &Access,&action);
+       status = open_file_ntcreate(conn,src,&src_sbuf,
+                       FILE_GENERIC_READ,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE,
+                       FILE_OPEN,
+                       0,
+                       FILE_ATTRIBUTE_NORMAL,
+                       INTERNAL_OPEN_ONLY,
+                       NULL, &fsp1);
 
-       if (!fsp1)
+       if (!NT_STATUS_IS_OK(status)) {
                return(False);
-
-       if (!target_is_directory && count)
-               ofun = FILE_EXISTS_OPEN;
+       }
 
        dosattrs = dos_mode(conn, src, &src_sbuf);
-       if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
+       if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
                ZERO_STRUCTP(&sbuf2);
+       }
 
-       fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
-                       ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
+       status = open_file_ntcreate(conn,dest,&sbuf2,
+                       FILE_GENERIC_WRITE,
+                       FILE_SHARE_READ|FILE_SHARE_WRITE,
+                       new_create_disposition,
+                       0,
+                       dosattrs,
+                       INTERNAL_OPEN_ONLY,
+                       NULL, &fsp2);
 
-       if (!fsp2) {
-               close_file(fsp1,False);
+       if (!NT_STATUS_IS_OK(status)) {
+               close_file(fsp1,ERROR_CLOSE);
                return(False);
        }
 
        if ((ofun&3) == 1) {
-               if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
+               if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
                        DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
                        /*
                         * Stop the copy from occurring.
@@ -4198,13 +4818,14 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
                }
        }
   
-       if (src_sbuf.st_size)
+       if (src_sbuf.st_size) {
                ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
+       }
 
-       close_file(fsp1,False);
+       close_file(fsp1,NORMAL_CLOSE);
 
        /* Ensure the modtime is set correctly on the destination file. */
-       fsp2->pending_modtime = src_sbuf.st_mtime;
+       fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
 
        /*
         * As we are opening fsp1 read-only we only expect
@@ -4212,7 +4833,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
         * Thus we don't look at the error return from the
         * close of fsp1.
         */
-       *err_ret = close_file(fsp2,False);
+       *err_ret = close_file(fsp2,NORMAL_CLOSE);
 
        return(ret == (SMB_OFF_T)src_sbuf.st_size);
 }
@@ -4239,21 +4860,22 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        BOOL target_is_directory=False;
        BOOL bad_path1 = False;
        BOOL bad_path2 = False;
+       BOOL path_contains_wcard1 = False;
+       BOOL path_contains_wcard2 = False;
        BOOL rc = True;
        SMB_STRUCT_STAT sbuf1, sbuf2;
        NTSTATUS status;
-
        START_PROFILE(SMBcopy);
 
        *directory = *mask = 0;
 
        p = smb_buf(inbuf);
-       p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
+       p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
        }
-       p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
+       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
@@ -4268,8 +4890,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_DOS(ERRSRV,ERRinvdevice);
        }
 
-       RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
-       RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
+       RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
+       RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
 
        rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
        unix_convert(newname,conn,0,&bad_path2,&sbuf2);
@@ -4312,10 +4934,10 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
         * Tine Smukavec <valentin.smukavec@hermes.si>.
         */
 
-       if (!rc && mangle_is_mangled(mask))
-               mangle_check_cache( mask, sizeof(pstring)-1 );
+       if (!rc && mangle_is_mangled(mask, conn->params))
+               mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
 
-       has_wild = ms_has_wild(mask);
+       has_wild = path_contains_wcard1;
 
        if (!has_wild) {
                pstrcat(directory,"/");
@@ -4332,24 +4954,27 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                        exists = vfs_file_exist(conn,directory,NULL);
                }
        } else {
-               void *dirptr = NULL;
+               struct smb_Dir *dir_hnd = NULL;
                const char *dname;
                pstring destname;
 
+               if (strequal(mask,"????????.???"))
+                       pstrcpy(mask,"*");
+
                if (check_name(directory,conn))
-                       dirptr = OpenDir(conn, directory, True);
+                       dir_hnd = OpenDir(conn, directory, mask, 0);
 
-               if (dirptr) {
+               if (dir_hnd) {
                        long offset = 0;
                        error = ERRbadfile;
 
-                       if (strequal(mask,"????????.???"))
-                               pstrcpy(mask,"*");
-
-                       while ((dname = ReadDirName(dirptr, &offset))) {
+                       while ((dname = ReadDirName(dir_hnd, &offset))) {
                                pstring fname;
                                pstrcpy(fname,dname);
     
+                               if (!is_visible_file(conn, directory, dname, &sbuf1, False))
+                                       continue;
+
                                if(!mask_match(fname, mask, conn->case_sensitive))
                                        continue;
 
@@ -4362,7 +4987,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                                        count++;
                                DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
                        }
-                       CloseDir(dirptr);
+                       CloseDir(dir_hnd);
                }
        }
   
@@ -4378,9 +5003,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                        END_PROFILE(SMBcopy);
                        return ERROR_DOS(ERRDOS,error);
                } else {
-                       if((errno == ENOENT) && (bad_path1 || bad_path2)) {
-                               unix_ERR_class = ERRDOS;
-                               unix_ERR_code = ERRbadpath;
+                       if((errno == ENOENT) && (bad_path1 || bad_path2) &&
+                          !use_nt_status()) {
+                               /* Samba 3.0.22 has ERRDOS/ERRbadpath in the
+                                * DOS error code case
+                                */
+                               return ERROR_DOS(ERRDOS, ERRbadpath);
                        }
                        END_PROFILE(SMBcopy);
                        return(UNIXERROR(ERRDOS,error));
@@ -4414,18 +5042,20 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
 
-       srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
+       srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(pathworks_setdir);
                return ERROR_NT(status);
        }
   
+       RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
+
        if (strlen(newdir) == 0) {
                ok = True;
        } else {
                ok = vfs_directory_exist(conn,newdir,NULL);
                if (ok)
-                       string_set(&conn->connectpath,newdir);
+                       set_conn_connectpath(conn,newdir);
        }
   
        if (!ok) {
@@ -4433,7 +5063,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_DOS(ERRDOS,ERRbadpath);
        }
   
-       outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,False);
        SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
   
        DEBUG(3,("setdir %s\n", newdir));
@@ -4442,16 +5072,19 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
        return(outsize);
 }
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_LOCKING
+
 /****************************************************************************
  Get a lock pid, dealing with large count requests.
 ****************************************************************************/
 
-uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
+uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
 {
        if(!large_file_format)
-               return SVAL(data,SMB_LPID_OFFSET(data_offset));
+               return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
        else
-               return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
+               return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
 }
 
 /****************************************************************************
@@ -4579,7 +5212,8 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma
  Reply to a lockingX request.
 ****************************************************************************/
 
-int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
+int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
+                  int length, int bufsize)
 {
        files_struct *fsp = file_fsp(inbuf,smb_vwv2);
        unsigned char locktype = CVAL(inbuf,smb_vwv3);
@@ -4587,14 +5221,15 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,
        uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
        uint16 num_locks = SVAL(inbuf,smb_vwv7);
        SMB_BIG_UINT count = 0, offset = 0;
-       uint16 lock_pid;
+       uint32 lock_pid;
        int32 lock_timeout = IVAL(inbuf,smb_vwv4);
        int i;
        char *data;
-       BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
+       BOOL large_file_format =
+               (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
        BOOL err;
        BOOL my_lock_ctx = False;
-       NTSTATUS status;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
 
        START_PROFILE(SMBlockingX);
        
@@ -4606,7 +5241,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,
                /* we don't support these - and CANCEL_LOCK makes w2k
                   and XP reboot so I don't really want to be
                   compatible! (tridge) */
-               return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+               return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
        }
        
        if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
@@ -4620,19 +5255,32 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,
        if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
                /* Client can insist on breaking to none. */
                BOOL break_to_none = (oplocklevel == 0);
-               
-               DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
-                        (unsigned int)oplocklevel, fsp->fnum ));
+               BOOL result;
+
+               DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
+                        "for fnum = %d\n", (unsigned int)oplocklevel,
+                        fsp->fnum ));
 
                /*
-                * Make sure we have granted an exclusive or batch oplock on this file.
+                * Make sure we have granted an exclusive or batch oplock on
+                * this file.
                 */
                
-               if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
-                       DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
-no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
+               if (fsp->oplock_type == 0) {
 
-                       /* if this is a pure oplock break request then don't send a reply */
+                       /* The Samba4 nbench simulator doesn't understand
+                          the difference between break to level2 and break
+                          to none from level2 - it sends oplock break
+                          replies in both cases. Don't keep logging an error
+                          message here - just ignore it. JRA. */
+
+                       DEBUG(5,("reply_lockingX: Error : oplock break from "
+                                "client for fnum = %d (oplock=%d) and no "
+                                "oplock granted on this file (%s).\n",
+                                fsp->fnum, fsp->oplock_type, fsp->fsp_name));
+
+                       /* if this is a pure oplock break request then don't
+                        * send a reply */
                        if (num_locks == 0 && num_ulocks == 0) {
                                END_PROFILE(SMBlockingX);
                                return -1;
@@ -4642,17 +5290,30 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
                        }
                }
 
-               if (remove_oplock(fsp, break_to_none) == False) {
-                       DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
-                                fsp->fsp_name ));
+               if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
+                   (break_to_none)) {
+                       result = remove_oplock(fsp);
+               } else {
+                       result = downgrade_oplock(fsp);
                }
                
-               /* if this is a pure oplock break request then don't send a reply */
+               if (!result) {
+                       DEBUG(0, ("reply_lockingX: error in removing "
+                                 "oplock on file %s\n", fsp->fsp_name));
+                       /* Hmmm. Is this panic justified? */
+                       smb_panic("internal tdb error");
+               }
+
+               reply_to_oplock_break_requests(fsp);
+
+               /* if this is a pure oplock break request then don't send a
+                * reply */
                if (num_locks == 0 && num_ulocks == 0) {
                        /* Sanity check - ensure a pure oplock break is not a
                           chained request. */
                        if(CVAL(inbuf,smb_vwv0) != 0xff)
-                               DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
+                               DEBUG(0,("reply_lockingX: Error : pure oplock "
+                                        "break is a chained %d request !\n",
                                         (unsigned int)CVAL(inbuf,smb_vwv0) ));
                        END_PROFILE(SMBlockingX);
                        return -1;
@@ -4681,10 +5342,16 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
                        return ERROR_DOS(ERRDOS,ERRnoaccess);
                }
 
-               DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
-                         (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
+               DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
+                         "pid %u, file %s\n", (double)offset, (double)count,
+                         (unsigned int)lock_pid, fsp->fsp_name ));
                
-               status = do_unlock(fsp,conn,lock_pid,count,offset);
+               status = do_unlock(fsp,
+                               lock_pid,
+                               count,
+                               offset,
+                               WINDOWS_LOCK);
+
                if (NT_STATUS_V(status)) {
                        END_PROFILE(SMBlockingX);
                        return ERROR_NT(status);
@@ -4702,6 +5369,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
           of smb_lkrng structs */
        
        for(i = 0; i < (int)num_locks; i++) {
+               enum brl_type lock_type = ((locktype & 1) ? READ_LOCK:WRITE_LOCK);
                lock_pid = get_lock_pid( data, i, large_file_format);
                count = get_lock_count( data, i, large_file_format);
                offset = get_lock_offset( data, i, large_file_format, &err);
@@ -4714,27 +5382,44 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
                        return ERROR_DOS(ERRDOS,ERRnoaccess);
                }
                
-               DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
-                       (double)offset, (double)count, (unsigned int)lock_pid,
-                       fsp->fsp_name, (int)lock_timeout ));
+               DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
+                         "%u, file %s timeout = %d\n", (double)offset,
+                         (double)count, (unsigned int)lock_pid,
+                         fsp->fsp_name, (int)lock_timeout ));
                
-               status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
-                                ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
+               status = do_lock_spin(fsp,
+                                       lock_pid,
+                                       count,
+                                       offset, 
+                                       lock_type,
+                                       WINDOWS_LOCK,
+                                       &my_lock_ctx);
+
                if (NT_STATUS_V(status)) {
                        /*
-                        * Interesting fact found by IFSTEST /t LockOverlappedTest...
-                        * Even if it's our own lock context, we need to wait here as
-                        * there may be an unlock on the way.
-                        * So I removed a "&& !my_lock_ctx" from the following
-                        * if statement. JRA.
+                        * Interesting fact found by IFSTEST /t
+                        * LockOverlappedTest...  Even if it's our own lock
+                        * context, we need to wait here as there may be an
+                        * unlock on the way.  So I removed a "&&
+                        * !my_lock_ctx" from the following if statement. JRA.
                         */
-                       if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
+                       if ((lock_timeout != 0) &&
+                           lp_blocking_locks(SNUM(conn)) &&
+                           ERROR_WAS_LOCK_DENIED(status)) {
                                /*
                                 * A blocking lock was requested. Package up
                                 * this smb into a queued request and push it
                                 * onto the blocking lock queue.
                                 */
-                               if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
+                               if(push_blocking_lock_request(inbuf, length,
+                                                             fsp,
+                                                             lock_timeout,
+                                                             i,
+                                                             lock_pid,
+                                                             lock_type,
+                                                             WINDOWS_LOCK,
+                                                             offset,
+                                                             count)) {
                                        END_PROFILE(SMBlockingX);
                                        return -1;
                                }
@@ -4754,17 +5439,23 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
                for(i--; i >= 0; i--) {
                        lock_pid = get_lock_pid( data, i, large_file_format);
                        count = get_lock_count( data, i, large_file_format);
-                       offset = get_lock_offset( data, i, large_file_format, &err);
+                       offset = get_lock_offset( data, i, large_file_format,
+                                                 &err);
                        
                        /*
-                        * There is no error code marked "stupid client bug".... :-).
+                        * There is no error code marked "stupid client
+                        * bug".... :-).
                         */
                        if(err) {
                                END_PROFILE(SMBlockingX);
                                return ERROR_DOS(ERRDOS,ERRnoaccess);
                        }
                        
-                       do_unlock(fsp,conn,lock_pid,count,offset);
+                       do_unlock(fsp,
+                               lock_pid,
+                               count,
+                               offset,
+                               WINDOWS_LOCK);
                }
                END_PROFILE(SMBlockingX);
                return ERROR_NT(status);
@@ -4772,13 +5463,16 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
 
        set_message(outbuf,2,0,True);
        
-       DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
-                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
+       DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
+                 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
        
        END_PROFILE(SMBlockingX);
        return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_ALL
+
 /****************************************************************************
  Reply to a SMBreadbmpx (read block multiplex) request.
 ****************************************************************************/
@@ -4806,7 +5500,9 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
        outsize = set_message(outbuf,8,0,True);
 
        CHECK_FSP(fsp,conn);
-       CHECK_READ(fsp);
+       if (!CHECK_READ(fsp,inbuf)) {
+               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       }
 
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
        maxcount = SVAL(inbuf,smb_vwv3);
@@ -4821,7 +5517,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
        tcount = maxcount;
        total_read = 0;
 
-       if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
                END_PROFILE(SMBreadBmpx);
                return ERROR_DOS(ERRDOS,ERRlock);
        }
@@ -4837,12 +5533,13 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
                if (nread < (ssize_t)N)
                        tcount = total_read + nread;
 
-               set_message(outbuf,8,nread,False);
+               set_message(outbuf,8,nread+pad,False);
                SIVAL(outbuf,smb_vwv0,startpos);
                SSVAL(outbuf,smb_vwv2,tcount);
                SSVAL(outbuf,smb_vwv6,nread);
                SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
 
+               show_msg(outbuf);
                if (!send_smb(smbd_server_fd(),outbuf))
                        exit_server("reply_readbmpx: send_smb failed.");
 
@@ -4865,10 +5562,10 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
        START_PROFILE(SMBsetattrE);
 
-       outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,False);
 
        if(!fsp || (fsp->conn != conn)) {
-               END_PROFILE(SMBgetattrE);
+               END_PROFILE(SMBsetattrE);
                return ERROR_DOS(ERRDOS,ERRbadfid);
        }
 
@@ -4877,15 +5574,15 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
         * time as UNIX can't set this.
         */
 
-       unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
-       unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
+       unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3);
+       unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5);
   
        /* 
         * Patch from Ray Frush <frush@engr.colostate.edu>
         * Sometimes times are sent as zero - ignore them.
         */
 
-       if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
+       if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
                /* Ignore request */
                if( DEBUGLVL( 3 ) ) {
                        dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
@@ -4893,12 +5590,13 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
                }
                END_PROFILE(SMBsetattrE);
                return(outsize);
-       } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
-               /* set modify time = to access time if modify time was 0 */
+       } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
+               /* set modify time = to access time if modify time was unset */
                unix_times.modtime = unix_times.actime;
        }
 
        /* Set the date on this file */
+       /* Should we set pending modtime here ? JRA */
        if(file_utime(conn, fsp->fsp_name, &unix_times)) {
                END_PROFILE(SMBsetattrE);
                return ERROR_DOS(ERRDOS,ERRnoaccess);
@@ -4932,8 +5630,12 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
        START_PROFILE(SMBwriteBmpx);
 
        CHECK_FSP(fsp,conn);
-       CHECK_WRITE(fsp);
-       CHECK_ERROR(fsp);
+       if (!CHECK_WRITE(fsp)) {
+               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       }
+       if (HAS_CACHED_ERROR(fsp)) {
+               return(CACHED_ERROR(fsp));
+       }
 
        tcount = SVAL(inbuf,smb_vwv1);
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
@@ -4947,15 +5649,14 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
                not an SMBwritebmpx - set this up now so we don't forget */
        SCVAL(outbuf,smb_com,SMBwritec);
 
-       if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
+       if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
                END_PROFILE(SMBwriteBmpx);
                return(ERROR_DOS(ERRDOS,ERRlock));
        }
 
        nwritten = write_file(fsp,data,startpos,numtowrite);
 
-       if(lp_syncalways(SNUM(conn)) || write_through)
-               sync_file(conn,fsp);
+       sync_file(conn, fsp, write_through);
   
        if(nwritten < (ssize_t)numtowrite) {
                END_PROFILE(SMBwriteBmpx);
@@ -5000,6 +5701,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
        if (write_through && tcount==nwritten) {
                /* We need to send both a primary and a secondary response */
                smb_setlen(outbuf,outsize - 4);
+               show_msg(outbuf);
                if (!send_smb(smbd_server_fd(),outbuf))
                        exit_server("reply_writebmpx: send_smb failed.");
 
@@ -5033,7 +5735,9 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
        START_PROFILE(SMBwriteBs);
 
        CHECK_FSP(fsp,conn);
-       CHECK_WRITE(fsp);
+       if (!CHECK_WRITE(fsp)) {
+               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+       }
 
        tcount = SVAL(inbuf,smb_vwv1);
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
@@ -5064,8 +5768,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
 
        nwritten = write_file(fsp,data,startpos,numtowrite);
 
-       if(lp_syncalways(SNUM(conn)) || write_through)
-               sync_file(conn,fsp);
+       sync_file(conn, fsp, write_through);
   
        if (nwritten < (ssize_t)numtowrite) {
                if(write_through) {
@@ -5076,8 +5779,12 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
                        END_PROFILE(SMBwriteBs);
                        return(ERROR_DOS(ERRHRD,ERRdiskfull));
                }
+               wbms->wr_errclass = ERRHRD;
+               wbms->wr_error = ERRdiskfull;
+               wbms->wr_status = NT_STATUS_DISK_FULL;
+               wbms->wr_discard = True;
                END_PROFILE(SMBwriteBs);
-               return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
+               return -1;
        }
 
        /* Increment the total written, if this matches tcount
@@ -5136,15 +5843,16 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
         * this.
         */
 
-       put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
-       put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
-       put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
+       srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
+       srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
+       /* Should we check pending modtime here ? JRA */
+       srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
 
        if (mode & aDIR) {
                SIVAL(outbuf,smb_vwv6,0);
                SIVAL(outbuf,smb_vwv8,0);
        } else {
-               uint32 allocation_size = get_allocation_size(fsp, &sbuf);
+               uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
                SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
                SIVAL(outbuf,smb_vwv8,allocation_size);
        }