r23538: Fix for wild-card rename: We can't return directly on error, we need to
[sfrench/samba-autobuild/.git] / source / smbd / reply.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_send;
32 extern int max_recv;
33 unsigned int smb_echo_count = 0;
34 extern uint32 global_client_caps;
35
36 extern struct current_user current_user;
37 extern BOOL global_encrypted_passwords_negotiated;
38
39 /****************************************************************************
40  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
41  path or anything including wildcards.
42  We're assuming here that '/' is not the second byte in any multibyte char
43  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44  set.
45 ****************************************************************************/
46
47 /* Custom version for processing POSIX paths. */
48 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
49
50 static NTSTATUS check_path_syntax_internal(char *path,
51                                            BOOL posix_path,
52                                            BOOL *p_last_component_contains_wcard)
53 {
54         char *d = path;
55         const char *s = path;
56         NTSTATUS ret = NT_STATUS_OK;
57         BOOL start_of_name_component = True;
58
59         *p_last_component_contains_wcard = False;
60
61         while (*s) {
62                 if (IS_PATH_SEP(*s,posix_path)) {
63                         /*
64                          * Safe to assume is not the second part of a mb char
65                          * as this is handled below.
66                          */
67                         /* Eat multiple '/' or '\\' */
68                         while (IS_PATH_SEP(*s,posix_path)) {
69                                 s++;
70                         }
71                         if ((d != path) && (*s != '\0')) {
72                                 /* We only care about non-leading or trailing '/' or '\\' */
73                                 *d++ = '/';
74                         }
75
76                         start_of_name_component = True;
77                         /* New component. */
78                         *p_last_component_contains_wcard = False;
79                         continue;
80                 }
81
82                 if (start_of_name_component) {
83                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
84                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
85
86                                 /*
87                                  * No mb char starts with '.' so we're safe checking the directory separator here.
88                                  */
89
90                                 /* If  we just added a '/' - delete it */
91                                 if ((d > path) && (*(d-1) == '/')) {
92                                         *(d-1) = '\0';
93                                         d--;
94                                 }
95
96                                 /* Are we at the start ? Can't go back further if so. */
97                                 if (d <= path) {
98                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
99                                         break;
100                                 }
101                                 /* Go back one level... */
102                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
103                                 /* NOTE - if this assumption is invalid we are not in good shape... */
104                                 /* Decrement d first as d points to the *next* char to write into. */
105                                 for (d--; d > path; d--) {
106                                         if (*d == '/')
107                                                 break;
108                                 }
109                                 s += 2; /* Else go past the .. */
110                                 /* We're still at the start of a name component, just the previous one. */
111                                 continue;
112
113                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
114                                 if (posix_path) {
115                                         /* Eat the '.' */
116                                         s++;
117                                         continue;
118                                 }
119                         }
120
121                 }
122
123                 if (!(*s & 0x80)) {
124                         if (!posix_path) {
125                                 if (*s <= 0x1f) {
126                                         return NT_STATUS_OBJECT_NAME_INVALID;
127                                 }
128                                 switch (*s) {
129                                         case '*':
130                                         case '?':
131                                         case '<':
132                                         case '>':
133                                         case '"':
134                                                 *p_last_component_contains_wcard = True;
135                                                 break;
136                                         default:
137                                                 break;
138                                 }
139                         }
140                         *d++ = *s++;
141                 } else {
142                         size_t siz;
143                         /* Get the size of the next MB character. */
144                         next_codepoint(s,&siz);
145                         switch(siz) {
146                                 case 5:
147                                         *d++ = *s++;
148                                         /*fall through*/
149                                 case 4:
150                                         *d++ = *s++;
151                                         /*fall through*/
152                                 case 3:
153                                         *d++ = *s++;
154                                         /*fall through*/
155                                 case 2:
156                                         *d++ = *s++;
157                                         /*fall through*/
158                                 case 1:
159                                         *d++ = *s++;
160                                         break;
161                                 default:
162                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
163                                         *d = '\0';
164                                         return NT_STATUS_INVALID_PARAMETER;
165                         }
166                 }
167                 start_of_name_component = False;
168         }
169
170         *d = '\0';
171         return ret;
172 }
173
174 /****************************************************************************
175  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
176  No wildcards allowed.
177 ****************************************************************************/
178
179 NTSTATUS check_path_syntax(char *path)
180 {
181         BOOL ignore;
182         return check_path_syntax_internal(path, False, &ignore);
183 }
184
185 /****************************************************************************
186  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
187  Wildcards allowed - p_contains_wcard returns true if the last component contained
188  a wildcard.
189 ****************************************************************************/
190
191 NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
192 {
193         return check_path_syntax_internal(path, False, p_contains_wcard);
194 }
195
196 /****************************************************************************
197  Check the path for a POSIX client.
198  We're assuming here that '/' is not the second byte in any multibyte char
199  set (a safe assumption).
200 ****************************************************************************/
201
202 NTSTATUS check_path_syntax_posix(char *path)
203 {
204         BOOL ignore;
205         return check_path_syntax_internal(path, True, &ignore);
206 }
207
208 /****************************************************************************
209  Pull a string and check the path allowing a wilcard - provide for error return.
210 ****************************************************************************/
211
212 size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
213                                 NTSTATUS *err, BOOL *contains_wcard)
214 {
215         size_t ret;
216 #ifdef DEVELOPER
217         SMB_ASSERT(dest_len == sizeof(pstring));
218 #endif
219
220         if (src_len == 0) {
221                 ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags);
222         } else {
223                 ret = srvstr_pull( inbuf, dest, src, dest_len, src_len, flags);
224         }
225
226         *contains_wcard = False;
227
228         if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
229                 /* 
230                  * For a DFS path the function parse_dfs_path()
231                  * will do the path processing, just make a copy.
232                  */
233                 *err = NT_STATUS_OK;
234                 return ret;
235         }
236
237         if (lp_posix_pathnames()) {
238                 *err = check_path_syntax_posix(dest);
239         } else {
240                 *err = check_path_syntax_wcard(dest, contains_wcard);
241         }
242
243         return ret;
244 }
245
246 /****************************************************************************
247  Pull a string and check the path - provide for error return.
248 ****************************************************************************/
249
250 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
251 {
252         size_t ret;
253 #ifdef DEVELOPER
254         SMB_ASSERT(dest_len == sizeof(pstring));
255 #endif
256
257         if (src_len == 0) {
258                 ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags);
259         } else {
260                 ret = srvstr_pull( inbuf, dest, src, dest_len, src_len, flags);
261         }
262
263         if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
264                 /* 
265                  * For a DFS path the function parse_dfs_path()
266                  * will do the path processing, just make a copy.
267                  */
268                 *err = NT_STATUS_OK;
269                 return ret;
270         }
271
272         if (lp_posix_pathnames()) {
273                 *err = check_path_syntax_posix(dest);
274         } else {
275                 *err = check_path_syntax(dest);
276         }
277
278         return ret;
279 }
280
281 /****************************************************************************
282  Reply to a special message.
283 ****************************************************************************/
284
285 int reply_special(char *inbuf,char *outbuf)
286 {
287         int outsize = 4;
288         int msg_type = CVAL(inbuf,0);
289         int msg_flags = CVAL(inbuf,1);
290         fstring name1,name2;
291         char name_type = 0;
292         
293         static BOOL already_got_session = False;
294
295         *name1 = *name2 = 0;
296         
297         memset(outbuf,'\0',smb_size);
298
299         smb_setlen(inbuf,outbuf,0);
300         
301         switch (msg_type) {
302         case 0x81: /* session request */
303                 
304                 if (already_got_session) {
305                         exit_server_cleanly("multiple session request not permitted");
306                 }
307                 
308                 SCVAL(outbuf,0,0x82);
309                 SCVAL(outbuf,3,0);
310                 if (name_len(inbuf+4) > 50 || 
311                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
312                         DEBUG(0,("Invalid name length in session request\n"));
313                         return(0);
314                 }
315                 name_extract(inbuf,4,name1);
316                 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
317                 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
318                          name1,name2));      
319
320                 set_local_machine_name(name1, True);
321                 set_remote_machine_name(name2, True);
322
323                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
324                          get_local_machine_name(), get_remote_machine_name(),
325                          name_type));
326
327                 if (name_type == 'R') {
328                         /* We are being asked for a pathworks session --- 
329                            no thanks! */
330                         SCVAL(outbuf, 0,0x83);
331                         break;
332                 }
333
334                 /* only add the client's machine name to the list
335                    of possibly valid usernames if we are operating
336                    in share mode security */
337                 if (lp_security() == SEC_SHARE) {
338                         add_session_user(get_remote_machine_name());
339                 }
340
341                 reload_services(True);
342                 reopen_logs();
343
344                 already_got_session = True;
345                 break;
346                 
347         case 0x89: /* session keepalive request 
348                       (some old clients produce this?) */
349                 SCVAL(outbuf,0,SMBkeepalive);
350                 SCVAL(outbuf,3,0);
351                 break;
352                 
353         case 0x82: /* positive session response */
354         case 0x83: /* negative session response */
355         case 0x84: /* retarget session response */
356                 DEBUG(0,("Unexpected session response\n"));
357                 break;
358                 
359         case SMBkeepalive: /* session keepalive */
360         default:
361                 return(0);
362         }
363         
364         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
365                     msg_type, msg_flags));
366         
367         return(outsize);
368 }
369
370 /****************************************************************************
371  Reply to a tcon.
372  conn POINTER CAN BE NULL HERE !
373 ****************************************************************************/
374
375 int reply_tcon(connection_struct *conn,
376                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
377 {
378         const char *service;
379         pstring service_buf;
380         pstring password;
381         pstring dev;
382         int outsize = 0;
383         uint16 vuid = SVAL(inbuf,smb_uid);
384         int pwlen=0;
385         NTSTATUS nt_status;
386         char *p;
387         DATA_BLOB password_blob;
388         
389         START_PROFILE(SMBtcon);
390
391         *service_buf = *password = *dev = 0;
392
393         p = smb_buf(inbuf)+1;
394         p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
395         pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
396         p += pwlen;
397         p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
398
399         p = strrchr_m(service_buf,'\\');
400         if (p) {
401                 service = p+1;
402         } else {
403                 service = service_buf;
404         }
405
406         password_blob = data_blob(password, pwlen+1);
407
408         conn = make_connection(service,password_blob,dev,vuid,&nt_status);
409
410         data_blob_clear_free(&password_blob);
411   
412         if (!conn) {
413                 END_PROFILE(SMBtcon);
414                 return ERROR_NT(nt_status);
415         }
416   
417         outsize = set_message(inbuf,outbuf,2,0,True);
418         SSVAL(outbuf,smb_vwv0,max_recv);
419         SSVAL(outbuf,smb_vwv1,conn->cnum);
420         SSVAL(outbuf,smb_tid,conn->cnum);
421   
422         DEBUG(3,("tcon service=%s cnum=%d\n", 
423                  service, conn->cnum));
424   
425         END_PROFILE(SMBtcon);
426         return(outsize);
427 }
428
429 /****************************************************************************
430  Reply to a tcon and X.
431  conn POINTER CAN BE NULL HERE !
432 ****************************************************************************/
433
434 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
435 {
436         fstring service;
437         DATA_BLOB password;
438
439         /* what the cleint thinks the device is */
440         fstring client_devicetype;
441         /* what the server tells the client the share represents */
442         const char *server_devicetype;
443         NTSTATUS nt_status;
444         uint16 vuid = SVAL(inbuf,smb_uid);
445         int passlen = SVAL(inbuf,smb_vwv3);
446         pstring path;
447         char *p, *q;
448         uint16 tcon_flags = SVAL(inbuf,smb_vwv2);
449         
450         START_PROFILE(SMBtconX);        
451
452         *service = *client_devicetype = 0;
453
454         /* we might have to close an old one */
455         if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
456                 close_cnum(conn,vuid);
457         }
458
459         if (passlen > MAX_PASS_LEN) {
460                 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
461         }
462  
463         if (global_encrypted_passwords_negotiated) {
464                 password = data_blob(smb_buf(inbuf),passlen);
465                 if (lp_security() == SEC_SHARE) {
466                         /*
467                          * Security = share always has a pad byte
468                          * after the password.
469                          */
470                         p = smb_buf(inbuf) + passlen + 1;
471                 } else {
472                         p = smb_buf(inbuf) + passlen;
473                 }
474         } else {
475                 password = data_blob(smb_buf(inbuf),passlen+1);
476                 /* Ensure correct termination */
477                 password.data[passlen]=0;
478                 p = smb_buf(inbuf) + passlen + 1;
479         }
480
481         p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
482
483         /*
484          * the service name can be either: \\server\share
485          * or share directly like on the DELL PowerVault 705
486          */
487         if (*path=='\\') {      
488                 q = strchr_m(path+2,'\\');
489                 if (!q) {
490                         END_PROFILE(SMBtconX);
491                         return(ERROR_DOS(ERRDOS,ERRnosuchshare));
492                 }
493                 fstrcpy(service,q+1);
494         }
495         else
496                 fstrcpy(service,path);
497                 
498         p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
499
500         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
501
502         conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
503         
504         data_blob_clear_free(&password);
505
506         if (!conn) {
507                 END_PROFILE(SMBtconX);
508                 return ERROR_NT(nt_status);
509         }
510
511         if ( IS_IPC(conn) )
512                 server_devicetype = "IPC";
513         else if ( IS_PRINT(conn) )
514                 server_devicetype = "LPT1:";
515         else 
516                 server_devicetype = "A:";
517
518         if (Protocol < PROTOCOL_NT1) {
519                 set_message(inbuf,outbuf,2,0,True);
520                 p = smb_buf(outbuf);
521                 p += srvstr_push(outbuf, p, server_devicetype, -1, 
522                                  STR_TERMINATE|STR_ASCII);
523                 set_message_end(inbuf,outbuf,p);
524         } else {
525                 /* NT sets the fstype of IPC$ to the null string */
526                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
527                 
528                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
529                         /* Return permissions. */
530                         uint32 perm1 = 0;
531                         uint32 perm2 = 0;
532
533                         set_message(inbuf,outbuf,7,0,True);
534
535                         if (IS_IPC(conn)) {
536                                 perm1 = FILE_ALL_ACCESS;
537                                 perm2 = FILE_ALL_ACCESS;
538                         } else {
539                                 perm1 = CAN_WRITE(conn) ?
540                                                 SHARE_ALL_ACCESS :
541                                                 SHARE_READ_ONLY;
542                         }
543
544                         SIVAL(outbuf, smb_vwv3, perm1);
545                         SIVAL(outbuf, smb_vwv5, perm2);
546                 } else {
547                         set_message(inbuf,outbuf,3,0,True);
548                 }
549
550                 p = smb_buf(outbuf);
551                 p += srvstr_push(outbuf, p, server_devicetype, -1, 
552                                  STR_TERMINATE|STR_ASCII);
553                 p += srvstr_push(outbuf, p, fstype, -1, 
554                                  STR_TERMINATE);
555                 
556                 set_message_end(inbuf,outbuf,p);
557                 
558                 /* what does setting this bit do? It is set by NT4 and
559                    may affect the ability to autorun mounted cdroms */
560                 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
561                                 (lp_csc_policy(SNUM(conn)) << 2));
562                 
563                 init_dfsroot(conn, inbuf, outbuf);
564         }
565
566   
567         DEBUG(3,("tconX service=%s \n",
568                  service));
569   
570         /* set the incoming and outgoing tid to the just created one */
571         SSVAL(inbuf,smb_tid,conn->cnum);
572         SSVAL(outbuf,smb_tid,conn->cnum);
573
574         END_PROFILE(SMBtconX);
575         return chain_reply(inbuf,outbuf,length,bufsize);
576 }
577
578 /****************************************************************************
579  Reply to an unknown type.
580 ****************************************************************************/
581
582 int reply_unknown(char *inbuf,char *outbuf)
583 {
584         int type;
585         type = CVAL(inbuf,smb_com);
586   
587         DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
588                  smb_fn_name(type), type, type));
589   
590         return(ERROR_DOS(ERRSRV,ERRunknownsmb));
591 }
592
593 /****************************************************************************
594  Reply to an ioctl.
595  conn POINTER CAN BE NULL HERE !
596 ****************************************************************************/
597
598 int reply_ioctl(connection_struct *conn,
599                 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
600 {
601         uint16 device     = SVAL(inbuf,smb_vwv1);
602         uint16 function   = SVAL(inbuf,smb_vwv2);
603         uint32 ioctl_code = (device << 16) + function;
604         int replysize, outsize;
605         char *p;
606         START_PROFILE(SMBioctl);
607
608         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
609
610         switch (ioctl_code) {
611             case IOCTL_QUERY_JOB_INFO:
612                 replysize = 32;
613                 break;
614             default:
615                 END_PROFILE(SMBioctl);
616                 return(ERROR_DOS(ERRSRV,ERRnosupport));
617         }
618
619         outsize = set_message(inbuf,outbuf,8,replysize+1,True);
620         SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
621         SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
622         SSVAL(outbuf,smb_vwv6,52);        /* Offset to data */
623         p = smb_buf(outbuf) + 1;          /* Allow for alignment */
624
625         switch (ioctl_code) {
626                 case IOCTL_QUERY_JOB_INFO:                  
627                 {
628                         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
629                         if (!fsp) {
630                                 END_PROFILE(SMBioctl);
631                                 return(UNIXERROR(ERRDOS,ERRbadfid));
632                         }
633                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
634                         srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
635                         if (conn) {
636                                 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
637                         }
638                         break;
639                 }
640         }
641
642         END_PROFILE(SMBioctl);
643         return outsize;
644 }
645
646 /****************************************************************************
647  Strange checkpath NTSTATUS mapping.
648 ****************************************************************************/
649
650 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
651 {
652         /* Strange DOS error code semantics only for checkpath... */
653         if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
654                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
655                         /* We need to map to ERRbadpath */
656                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
657                 }
658         }
659         return status;
660 }
661         
662 /****************************************************************************
663  Reply to a checkpath.
664 ****************************************************************************/
665
666 int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
667 {
668         int outsize = 0;
669         pstring name;
670         SMB_STRUCT_STAT sbuf;
671         NTSTATUS status;
672
673         START_PROFILE(SMBcheckpath);
674
675         srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
676         if (!NT_STATUS_IS_OK(status)) {
677                 END_PROFILE(SMBcheckpath);
678                 status = map_checkpath_error(inbuf, status);
679                 return ERROR_NT(status);
680         }
681
682         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name);
683         if (!NT_STATUS_IS_OK(status)) {
684                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
685                         END_PROFILE(SMBcheckpath);
686                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
687                 }
688                 goto path_err;
689         }
690
691         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
692
693         status = unix_convert(conn, name, False, NULL, &sbuf);
694         if (!NT_STATUS_IS_OK(status)) {
695                 goto path_err;
696         }
697
698         status = check_name(conn, name);
699         if (!NT_STATUS_IS_OK(status)) {
700                 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
701                 goto path_err;
702         }
703
704         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
705                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
706                 status = map_nt_error_from_unix(errno);
707                 goto path_err;
708         }
709
710         if (!S_ISDIR(sbuf.st_mode)) {
711                 END_PROFILE(SMBcheckpath);
712                 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
713         }
714
715         outsize = set_message(inbuf,outbuf,0,0,False);
716
717         END_PROFILE(SMBcheckpath);
718         return outsize;
719
720   path_err:
721
722         END_PROFILE(SMBcheckpath);
723
724         /* We special case this - as when a Windows machine
725                 is parsing a path is steps through the components
726                 one at a time - if a component fails it expects
727                 ERRbadpath, not ERRbadfile.
728         */
729         status = map_checkpath_error(inbuf, status);
730         if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
731                 /*
732                  * Windows returns different error codes if
733                  * the parent directory is valid but not the
734                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
735                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
736                  * if the path is invalid.
737                  */
738                 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
739         }
740
741         return ERROR_NT(status);
742 }
743
744 /****************************************************************************
745  Reply to a getatr.
746 ****************************************************************************/
747
748 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
749 {
750         pstring fname;
751         int outsize = 0;
752         SMB_STRUCT_STAT sbuf;
753         int mode=0;
754         SMB_OFF_T size=0;
755         time_t mtime=0;
756         char *p;
757         NTSTATUS status;
758
759         START_PROFILE(SMBgetatr);
760
761         p = smb_buf(inbuf) + 1;
762         p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
763         if (!NT_STATUS_IS_OK(status)) {
764                 END_PROFILE(SMBgetatr);
765                 return ERROR_NT(status);
766         }
767
768         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
769         if (!NT_STATUS_IS_OK(status)) {
770                 END_PROFILE(SMBgetatr);
771                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
772                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
773                 }
774                 return ERROR_NT(status);
775         }
776   
777         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
778                 under WfWg - weird! */
779         if (*fname == '\0') {
780                 mode = aHIDDEN | aDIR;
781                 if (!CAN_WRITE(conn)) {
782                         mode |= aRONLY;
783                 }
784                 size = 0;
785                 mtime = 0;
786         } else {
787                 status = unix_convert(conn, fname, False, NULL,&sbuf);
788                 if (!NT_STATUS_IS_OK(status)) {
789                         END_PROFILE(SMBgetatr);
790                         return ERROR_NT(status);
791                 }
792                 status = check_name(conn, fname);
793                 if (!NT_STATUS_IS_OK(status)) {
794                         DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
795                         END_PROFILE(SMBgetatr);
796                         return ERROR_NT(status);
797                 }
798                 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
799                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
800                         return UNIXERROR(ERRDOS,ERRbadfile);
801                 }
802
803                 mode = dos_mode(conn,fname,&sbuf);
804                 size = sbuf.st_size;
805                 mtime = sbuf.st_mtime;
806                 if (mode & aDIR) {
807                         size = 0;
808                 }
809         }
810   
811         outsize = set_message(inbuf,outbuf,10,0,True);
812
813         SSVAL(outbuf,smb_vwv0,mode);
814         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
815                 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
816         } else {
817                 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
818         }
819         SIVAL(outbuf,smb_vwv3,(uint32)size);
820
821         if (Protocol >= PROTOCOL_NT1) {
822                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
823         }
824   
825         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
826   
827         END_PROFILE(SMBgetatr);
828         return(outsize);
829 }
830
831 /****************************************************************************
832  Reply to a setatr.
833 ****************************************************************************/
834
835 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
836 {
837         pstring fname;
838         int outsize = 0;
839         int mode;
840         time_t mtime;
841         SMB_STRUCT_STAT sbuf;
842         char *p;
843         NTSTATUS status;
844
845         START_PROFILE(SMBsetatr);
846
847         p = smb_buf(inbuf) + 1;
848         p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
849         if (!NT_STATUS_IS_OK(status)) {
850                 END_PROFILE(SMBsetatr);
851                 return ERROR_NT(status);
852         }
853
854         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
855         if (!NT_STATUS_IS_OK(status)) {
856                 END_PROFILE(SMBsetatr);
857                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
858                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
859                 }
860                 return ERROR_NT(status);
861         }
862   
863         status = unix_convert(conn, fname, False, NULL, &sbuf);
864         if (!NT_STATUS_IS_OK(status)) {
865                 END_PROFILE(SMBsetatr);
866                 return ERROR_NT(status);
867         }
868
869         status = check_name(conn, fname);
870         if (!NT_STATUS_IS_OK(status)) {
871                 END_PROFILE(SMBsetatr);
872                 return ERROR_NT(status);
873         }
874
875         if (fname[0] == '.' && fname[1] == '\0') {
876                 /*
877                  * Not sure here is the right place to catch this
878                  * condition. Might be moved to somewhere else later -- vl
879                  */
880                 END_PROFILE(SMBsetatr);
881                 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
882         }
883
884         mode = SVAL(inbuf,smb_vwv0);
885         mtime = srv_make_unix_date3(inbuf+smb_vwv1);
886   
887         if (mode != FILE_ATTRIBUTE_NORMAL) {
888                 if (VALID_STAT_OF_DIR(sbuf))
889                         mode |= aDIR;
890                 else
891                         mode &= ~aDIR;
892
893                 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
894                         END_PROFILE(SMBsetatr);
895                         return UNIXERROR(ERRDOS, ERRnoaccess);
896                 }
897         }
898
899         if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
900                 END_PROFILE(SMBsetatr);
901                 return UNIXERROR(ERRDOS, ERRnoaccess);
902         }
903  
904         outsize = set_message(inbuf,outbuf,0,0,False);
905   
906         DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
907   
908         END_PROFILE(SMBsetatr);
909         return(outsize);
910 }
911
912 /****************************************************************************
913  Reply to a dskattr.
914 ****************************************************************************/
915
916 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
917 {
918         int outsize = 0;
919         SMB_BIG_UINT dfree,dsize,bsize;
920         START_PROFILE(SMBdskattr);
921
922         if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
923                 END_PROFILE(SMBdskattr);
924                 return(UNIXERROR(ERRHRD,ERRgeneral));
925         }
926   
927         outsize = set_message(inbuf,outbuf,5,0,True);
928         
929         if (Protocol <= PROTOCOL_LANMAN2) {
930                 double total_space, free_space;
931                 /* we need to scale this to a number that DOS6 can handle. We
932                    use floating point so we can handle large drives on systems
933                    that don't have 64 bit integers 
934
935                    we end up displaying a maximum of 2G to DOS systems
936                 */
937                 total_space = dsize * (double)bsize;
938                 free_space = dfree * (double)bsize;
939
940                 dsize = (total_space+63*512) / (64*512);
941                 dfree = (free_space+63*512) / (64*512);
942                 
943                 if (dsize > 0xFFFF) dsize = 0xFFFF;
944                 if (dfree > 0xFFFF) dfree = 0xFFFF;
945
946                 SSVAL(outbuf,smb_vwv0,dsize);
947                 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
948                 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
949                 SSVAL(outbuf,smb_vwv3,dfree);
950         } else {
951                 SSVAL(outbuf,smb_vwv0,dsize);
952                 SSVAL(outbuf,smb_vwv1,bsize/512);
953                 SSVAL(outbuf,smb_vwv2,512);
954                 SSVAL(outbuf,smb_vwv3,dfree);
955         }
956
957         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
958
959         END_PROFILE(SMBdskattr);
960         return(outsize);
961 }
962
963 /****************************************************************************
964  Reply to a search.
965  Can be called from SMBsearch, SMBffirst or SMBfunique.
966 ****************************************************************************/
967
968 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
969 {
970         pstring mask;
971         pstring directory;
972         pstring fname;
973         SMB_OFF_T size;
974         uint32 mode;
975         time_t date;
976         uint32 dirtype;
977         int outsize = 0;
978         unsigned int numentries = 0;
979         unsigned int maxentries = 0;
980         BOOL finished = False;
981         char *p;
982         int status_len;
983         pstring path;
984         char status[21];
985         int dptr_num= -1;
986         BOOL check_descend = False;
987         BOOL expect_close = False;
988         NTSTATUS nt_status;
989         BOOL mask_contains_wcard = False;
990         BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
991
992         START_PROFILE(SMBsearch);
993
994         if (lp_posix_pathnames()) {
995                 END_PROFILE(SMBsearch);
996                 return reply_unknown(inbuf, outbuf);
997         }
998
999         *mask = *directory = *fname = 0;
1000
1001         /* If we were called as SMBffirst then we must expect close. */
1002         if(CVAL(inbuf,smb_com) == SMBffirst) {
1003                 expect_close = True;
1004         }
1005   
1006         outsize = set_message(inbuf,outbuf,1,3,True);
1007         maxentries = SVAL(inbuf,smb_vwv0); 
1008         dirtype = SVAL(inbuf,smb_vwv1);
1009         p = smb_buf(inbuf) + 1;
1010         p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
1011         if (!NT_STATUS_IS_OK(nt_status)) {
1012                 END_PROFILE(SMBsearch);
1013                 return ERROR_NT(nt_status);
1014         }
1015
1016         nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
1017         if (!NT_STATUS_IS_OK(nt_status)) {
1018                 END_PROFILE(SMBsearch);
1019                 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1020                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1021                 }
1022                 return ERROR_NT(nt_status);
1023         }
1024   
1025         p++;
1026         status_len = SVAL(p, 0);
1027         p += 2;
1028   
1029         /* dirtype &= ~aDIR; */
1030
1031         if (status_len == 0) {
1032                 SMB_STRUCT_STAT sbuf;
1033
1034                 pstrcpy(directory,path);
1035                 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1036                 if (!NT_STATUS_IS_OK(nt_status)) {
1037                         END_PROFILE(SMBsearch);
1038                         return ERROR_NT(nt_status);
1039                 }
1040
1041                 nt_status = check_name(conn, directory);
1042                 if (!NT_STATUS_IS_OK(nt_status)) {
1043                         END_PROFILE(SMBsearch);
1044                         return ERROR_NT(nt_status);
1045                 }
1046
1047                 p = strrchr_m(directory,'/');
1048                 if (!p) {
1049                         pstrcpy(mask,directory);
1050                         pstrcpy(directory,".");
1051                 } else {
1052                         *p = 0;
1053                         pstrcpy(mask,p+1);
1054                 }
1055
1056                 if (*directory == '\0') {
1057                         pstrcpy(directory,".");
1058                 }
1059                 memset((char *)status,'\0',21);
1060                 SCVAL(status,0,(dirtype & 0x1F));
1061         } else {
1062                 int status_dirtype;
1063
1064                 memcpy(status,p,21);
1065                 status_dirtype = CVAL(status,0) & 0x1F;
1066                 if (status_dirtype != (dirtype & 0x1F)) {
1067                         dirtype = status_dirtype;
1068                 }
1069
1070                 conn->dirptr = dptr_fetch(status+12,&dptr_num);      
1071                 if (!conn->dirptr) {
1072                         goto SearchEmpty;
1073                 }
1074                 string_set(&conn->dirpath,dptr_path(dptr_num));
1075                 pstrcpy(mask, dptr_wcard(dptr_num));
1076                 /*
1077                  * For a 'continue' search we have no string. So
1078                  * check from the initial saved string.
1079                  */
1080                 mask_contains_wcard = ms_has_wild(mask);
1081         }
1082
1083         p = smb_buf(outbuf) + 3;
1084      
1085         if (status_len == 0) {
1086                 nt_status = dptr_create(conn,
1087                                         directory,
1088                                         True,
1089                                         expect_close,
1090                                         SVAL(inbuf,smb_pid),
1091                                         mask,
1092                                         mask_contains_wcard,
1093                                         dirtype,
1094                                         &conn->dirptr);
1095                 if (!NT_STATUS_IS_OK(nt_status)) {
1096                         return ERROR_NT(nt_status);
1097                 }
1098                 dptr_num = dptr_dnum(conn->dirptr);
1099         } else {
1100                 dirtype = dptr_attr(dptr_num);
1101         }
1102
1103         DEBUG(4,("dptr_num is %d\n",dptr_num));
1104
1105         if ((dirtype&0x1F) == aVOLID) {   
1106                 memcpy(p,status,21);
1107                 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1108                                 0,aVOLID,0,!allow_long_path_components);
1109                 dptr_fill(p+12,dptr_num);
1110                 if (dptr_zero(p+12) && (status_len==0)) {
1111                         numentries = 1;
1112                 } else {
1113                         numentries = 0;
1114                 }
1115                 p += DIR_STRUCT_SIZE;
1116         } else {
1117                 unsigned int i;
1118                 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1119
1120                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1121                         conn->dirpath,lp_dontdescend(SNUM(conn))));
1122                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1123                         check_descend = True;
1124                 }
1125
1126                 for (i=numentries;(i<maxentries) && !finished;i++) {
1127                         finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1128                         if (!finished) {
1129                                 memcpy(p,status,21);
1130                                 make_dir_struct(p,mask,fname,size, mode,date,
1131                                                 !allow_long_path_components);
1132                                 if (!dptr_fill(p+12,dptr_num)) {
1133                                         break;
1134                                 }
1135                                 numentries++;
1136                                 p += DIR_STRUCT_SIZE;
1137                         }
1138                 }
1139         }
1140
1141   SearchEmpty:
1142
1143         /* If we were called as SMBffirst with smb_search_id == NULL
1144                 and no entries were found then return error and close dirptr 
1145                 (X/Open spec) */
1146
1147         if (numentries == 0) {
1148                 dptr_close(&dptr_num);
1149         } else if(expect_close && status_len == 0) {
1150                 /* Close the dptr - we know it's gone */
1151                 dptr_close(&dptr_num);
1152         }
1153
1154         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1155         if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1156                 dptr_close(&dptr_num);
1157         }
1158
1159         if ((numentries == 0) && !mask_contains_wcard) {
1160                 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1161         }
1162
1163         SSVAL(outbuf,smb_vwv0,numentries);
1164         SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1165         SCVAL(smb_buf(outbuf),0,5);
1166         SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1167
1168         /* The replies here are never long name. */
1169         SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1170         if (!allow_long_path_components) {
1171                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1172         }
1173
1174         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1175         SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1176           
1177         outsize += DIR_STRUCT_SIZE*numentries;
1178         smb_setlen(inbuf,outbuf,outsize - 4);
1179   
1180         if ((! *directory) && dptr_path(dptr_num))
1181                 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1182
1183         DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1184                 smb_fn_name(CVAL(inbuf,smb_com)), 
1185                 mask, directory, dirtype, numentries, maxentries ) );
1186
1187         END_PROFILE(SMBsearch);
1188         return(outsize);
1189 }
1190
1191 /****************************************************************************
1192  Reply to a fclose (stop directory search).
1193 ****************************************************************************/
1194
1195 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1196 {
1197         int outsize = 0;
1198         int status_len;
1199         pstring path;
1200         char status[21];
1201         int dptr_num= -2;
1202         char *p;
1203         NTSTATUS err;
1204         BOOL path_contains_wcard = False;
1205
1206         START_PROFILE(SMBfclose);
1207
1208         if (lp_posix_pathnames()) {
1209                 END_PROFILE(SMBfclose);
1210                 return reply_unknown(inbuf, outbuf);
1211         }
1212
1213         outsize = set_message(inbuf,outbuf,1,0,True);
1214         p = smb_buf(inbuf) + 1;
1215         p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1216         if (!NT_STATUS_IS_OK(err)) {
1217                 END_PROFILE(SMBfclose);
1218                 return ERROR_NT(err);
1219         }
1220         p++;
1221         status_len = SVAL(p,0);
1222         p += 2;
1223
1224         if (status_len == 0) {
1225                 END_PROFILE(SMBfclose);
1226                 return ERROR_DOS(ERRSRV,ERRsrverror);
1227         }
1228
1229         memcpy(status,p,21);
1230
1231         if(dptr_fetch(status+12,&dptr_num)) {
1232                 /*  Close the dptr - we know it's gone */
1233                 dptr_close(&dptr_num);
1234         }
1235
1236         SSVAL(outbuf,smb_vwv0,0);
1237
1238         DEBUG(3,("search close\n"));
1239
1240         END_PROFILE(SMBfclose);
1241         return(outsize);
1242 }
1243
1244 /****************************************************************************
1245  Reply to an open.
1246 ****************************************************************************/
1247
1248 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1249 {
1250         pstring fname;
1251         int outsize = 0;
1252         uint32 fattr=0;
1253         SMB_OFF_T size = 0;
1254         time_t mtime=0;
1255         int info;
1256         SMB_STRUCT_STAT sbuf;
1257         files_struct *fsp;
1258         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1259         int deny_mode;
1260         uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1261         uint32 access_mask;
1262         uint32 share_mode;
1263         uint32 create_disposition;
1264         uint32 create_options = 0;
1265         NTSTATUS status;
1266         START_PROFILE(SMBopen);
1267  
1268         deny_mode = SVAL(inbuf,smb_vwv0);
1269
1270         srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1271         if (!NT_STATUS_IS_OK(status)) {
1272                 END_PROFILE(SMBopen);
1273                 return ERROR_NT(status);
1274         }
1275
1276         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1277         if (!NT_STATUS_IS_OK(status)) {
1278                 END_PROFILE(SMBopen);
1279                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1280                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1281                 }
1282                 return ERROR_NT(status);
1283         }
1284
1285         status = unix_convert(conn, fname, False, NULL, &sbuf);
1286         if (!NT_STATUS_IS_OK(status)) {
1287                 END_PROFILE(SMBopen);
1288                 return ERROR_NT(status);
1289         }
1290     
1291         status = check_name(conn, fname);
1292         if (!NT_STATUS_IS_OK(status)) {
1293                 END_PROFILE(SMBopen);
1294                 return ERROR_NT(status);
1295         }
1296
1297         if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1298                         &access_mask, &share_mode, &create_disposition, &create_options)) {
1299                 END_PROFILE(SMBopen);
1300                 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1301         }
1302
1303         status = open_file_ntcreate(conn,fname,&sbuf,
1304                         access_mask,
1305                         share_mode,
1306                         create_disposition,
1307                         create_options,
1308                         dos_attr,
1309                         oplock_request,
1310                         &info, &fsp);
1311
1312         if (!NT_STATUS_IS_OK(status)) {
1313                 END_PROFILE(SMBopen);
1314                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1315                         /* We have re-scheduled this call. */
1316                         return -1;
1317                 }
1318                 return ERROR_NT(status);
1319         }
1320
1321         size = sbuf.st_size;
1322         fattr = dos_mode(conn,fname,&sbuf);
1323         mtime = sbuf.st_mtime;
1324
1325         if (fattr & aDIR) {
1326                 DEBUG(3,("attempt to open a directory %s\n",fname));
1327                 close_file(fsp,ERROR_CLOSE);
1328                 END_PROFILE(SMBopen);
1329                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1330         }
1331   
1332         outsize = set_message(inbuf,outbuf,7,0,True);
1333         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1334         SSVAL(outbuf,smb_vwv1,fattr);
1335         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1336                 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1337         } else {
1338                 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1339         }
1340         SIVAL(outbuf,smb_vwv4,(uint32)size);
1341         SSVAL(outbuf,smb_vwv6,deny_mode);
1342
1343         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1344                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1345         }
1346     
1347         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1348                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1349         }
1350         END_PROFILE(SMBopen);
1351         return(outsize);
1352 }
1353
1354 /****************************************************************************
1355  Reply to an open and X.
1356 ****************************************************************************/
1357
1358 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1359 {
1360         pstring fname;
1361         uint16 open_flags = SVAL(inbuf,smb_vwv2);
1362         int deny_mode = SVAL(inbuf,smb_vwv3);
1363         uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1364         /* Breakout the oplock request bits so we can set the
1365                 reply bits separately. */
1366         int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1367         int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1368         int oplock_request = ex_oplock_request | core_oplock_request;
1369 #if 0
1370         int smb_sattr = SVAL(inbuf,smb_vwv4); 
1371         uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1372 #endif
1373         int smb_ofun = SVAL(inbuf,smb_vwv8);
1374         uint32 fattr=0;
1375         int mtime=0;
1376         SMB_STRUCT_STAT sbuf;
1377         int smb_action = 0;
1378         files_struct *fsp;
1379         NTSTATUS status;
1380         SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1381         ssize_t retval = -1;
1382         uint32 access_mask;
1383         uint32 share_mode;
1384         uint32 create_disposition;
1385         uint32 create_options = 0;
1386
1387         START_PROFILE(SMBopenX);
1388
1389         /* If it's an IPC, pass off the pipe handler. */
1390         if (IS_IPC(conn)) {
1391                 if (lp_nt_pipe_support()) {
1392                         END_PROFILE(SMBopenX);
1393                         return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1394                 } else {
1395                         END_PROFILE(SMBopenX);
1396                         return ERROR_DOS(ERRSRV,ERRaccess);
1397                 }
1398         }
1399
1400         /* XXXX we need to handle passed times, sattr and flags */
1401         srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1402         if (!NT_STATUS_IS_OK(status)) {
1403                 END_PROFILE(SMBopenX);
1404                 return ERROR_NT(status);
1405         }
1406
1407         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1408         if (!NT_STATUS_IS_OK(status)) {
1409                 END_PROFILE(SMBopenX);
1410                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1411                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1412                 }
1413                 return ERROR_NT(status);
1414         }
1415
1416         status = unix_convert(conn, fname, False, NULL, &sbuf);
1417         if (!NT_STATUS_IS_OK(status)) {
1418                 END_PROFILE(SMBopenX);
1419                 return ERROR_NT(status);
1420         }
1421
1422         status = check_name(conn, fname);
1423         if (!NT_STATUS_IS_OK(status)) {
1424                 END_PROFILE(SMBopenX);
1425                 return ERROR_NT(status);
1426         }
1427
1428         if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1429                                 &access_mask,
1430                                 &share_mode,
1431                                 &create_disposition,
1432                                 &create_options)) {
1433                 END_PROFILE(SMBopenX);
1434                 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1435         }
1436
1437         status = open_file_ntcreate(conn,fname,&sbuf,
1438                         access_mask,
1439                         share_mode,
1440                         create_disposition,
1441                         create_options,
1442                         smb_attr,
1443                         oplock_request,
1444                         &smb_action, &fsp);
1445       
1446         if (!NT_STATUS_IS_OK(status)) {
1447                 END_PROFILE(SMBopenX);
1448                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1449                         /* We have re-scheduled this call. */
1450                         return -1;
1451                 }
1452                 return ERROR_NT(status);
1453         }
1454
1455         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1456            if the file is truncated or created. */
1457         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1458                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1459                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1460                         close_file(fsp,ERROR_CLOSE);
1461                         END_PROFILE(SMBopenX);
1462                         return ERROR_NT(NT_STATUS_DISK_FULL);
1463                 }
1464                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1465                 if (retval < 0) {
1466                         close_file(fsp,ERROR_CLOSE);
1467                         END_PROFILE(SMBopenX);
1468                         return ERROR_NT(NT_STATUS_DISK_FULL);
1469                 }
1470                 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1471         }
1472
1473         fattr = dos_mode(conn,fname,&sbuf);
1474         mtime = sbuf.st_mtime;
1475         if (fattr & aDIR) {
1476                 close_file(fsp,ERROR_CLOSE);
1477                 END_PROFILE(SMBopenX);
1478                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1479         }
1480
1481         /* If the caller set the extended oplock request bit
1482                 and we granted one (by whatever means) - set the
1483                 correct bit for extended oplock reply.
1484         */
1485
1486         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1487                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1488         }
1489
1490         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1491                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1492         }
1493
1494         /* If the caller set the core oplock request bit
1495                 and we granted one (by whatever means) - set the
1496                 correct bit for core oplock reply.
1497         */
1498
1499         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1500                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1501         }
1502
1503         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1504                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1505         }
1506
1507         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1508                 set_message(inbuf,outbuf,19,0,True);
1509         } else {
1510                 set_message(inbuf,outbuf,15,0,True);
1511         }
1512         SSVAL(outbuf,smb_vwv2,fsp->fnum);
1513         SSVAL(outbuf,smb_vwv3,fattr);
1514         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1515                 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1516         } else {
1517                 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1518         }
1519         SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1520         SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1521         SSVAL(outbuf,smb_vwv11,smb_action);
1522
1523         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1524                 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1525         }
1526
1527         END_PROFILE(SMBopenX);
1528         return chain_reply(inbuf,outbuf,length,bufsize);
1529 }
1530
1531 /****************************************************************************
1532  Reply to a SMBulogoffX.
1533  conn POINTER CAN BE NULL HERE !
1534 ****************************************************************************/
1535
1536 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1537 {
1538         uint16 vuid = SVAL(inbuf,smb_uid);
1539         user_struct *vuser = get_valid_user_struct(vuid);
1540         START_PROFILE(SMBulogoffX);
1541
1542         if(vuser == 0)
1543                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1544
1545         /* in user level security we are supposed to close any files
1546                 open by this user */
1547         if ((vuser != 0) && (lp_security() != SEC_SHARE))
1548                 file_close_user(vuid);
1549
1550         invalidate_vuid(vuid);
1551
1552         set_message(inbuf,outbuf,2,0,True);
1553
1554         DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1555
1556         END_PROFILE(SMBulogoffX);
1557         return chain_reply(inbuf,outbuf,length,bufsize);
1558 }
1559
1560 /****************************************************************************
1561  Reply to a mknew or a create.
1562 ****************************************************************************/
1563
1564 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1565 {
1566         pstring fname;
1567         int com;
1568         int outsize = 0;
1569         uint32 fattr = SVAL(inbuf,smb_vwv0);
1570         struct timespec ts[2];
1571         files_struct *fsp;
1572         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1573         SMB_STRUCT_STAT sbuf;
1574         NTSTATUS status;
1575         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1576         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1577         uint32 create_disposition;
1578         uint32 create_options = 0;
1579
1580         START_PROFILE(SMBcreate);
1581  
1582         com = SVAL(inbuf,smb_com);
1583
1584         ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1585
1586         srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1587         if (!NT_STATUS_IS_OK(status)) {
1588                 END_PROFILE(SMBcreate);
1589                 return ERROR_NT(status);
1590         }
1591
1592         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1593         if (!NT_STATUS_IS_OK(status)) {
1594                 END_PROFILE(SMBcreate);
1595                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1596                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1597                 }
1598                 return ERROR_NT(status);
1599         }
1600
1601         status = unix_convert(conn, fname, False, NULL, &sbuf);
1602         if (!NT_STATUS_IS_OK(status)) {
1603                 END_PROFILE(SMBcreate);
1604                 return ERROR_NT(status);
1605         }
1606
1607         status = check_name(conn, fname);
1608         if (!NT_STATUS_IS_OK(status)) {
1609                 END_PROFILE(SMBcreate);
1610                 return ERROR_NT(status);
1611         }
1612
1613         if (fattr & aVOLID) {
1614                 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1615         }
1616
1617         if(com == SMBmknew) {
1618                 /* We should fail if file exists. */
1619                 create_disposition = FILE_CREATE;
1620         } else {
1621                 /* Create if file doesn't exist, truncate if it does. */
1622                 create_disposition = FILE_OVERWRITE_IF;
1623         }
1624
1625         /* Open file using ntcreate. */
1626         status = open_file_ntcreate(conn,fname,&sbuf,
1627                                 access_mask,
1628                                 share_mode,
1629                                 create_disposition,
1630                                 create_options,
1631                                 fattr,
1632                                 oplock_request,
1633                                 NULL, &fsp);
1634   
1635         if (!NT_STATUS_IS_OK(status)) {
1636                 END_PROFILE(SMBcreate);
1637                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1638                         /* We have re-scheduled this call. */
1639                         return -1;
1640                 }
1641                 return ERROR_NT(status);
1642         }
1643  
1644         ts[0] = get_atimespec(&sbuf); /* atime. */
1645         file_ntimes(conn, fname, ts);
1646
1647         outsize = set_message(inbuf,outbuf,1,0,True);
1648         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1649
1650         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1651                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1652         }
1653  
1654         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1655                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1656         }
1657  
1658         DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1659         DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1660
1661         END_PROFILE(SMBcreate);
1662         return(outsize);
1663 }
1664
1665 /****************************************************************************
1666  Reply to a create temporary file.
1667 ****************************************************************************/
1668
1669 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1670 {
1671         pstring fname;
1672         int outsize = 0;
1673         uint32 fattr = SVAL(inbuf,smb_vwv0);
1674         files_struct *fsp;
1675         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1676         int tmpfd;
1677         SMB_STRUCT_STAT sbuf;
1678         char *p, *s;
1679         NTSTATUS status;
1680         unsigned int namelen;
1681
1682         START_PROFILE(SMBctemp);
1683
1684         srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1685         if (!NT_STATUS_IS_OK(status)) {
1686                 END_PROFILE(SMBctemp);
1687                 return ERROR_NT(status);
1688         }
1689         if (*fname) {
1690                 pstrcat(fname,"/TMXXXXXX");
1691         } else {
1692                 pstrcat(fname,"TMXXXXXX");
1693         }
1694
1695         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1696         if (!NT_STATUS_IS_OK(status)) {
1697                 END_PROFILE(SMBctemp);
1698                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1699                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1700                 }
1701                 return ERROR_NT(status);
1702         }
1703
1704         status = unix_convert(conn, fname, False, NULL, &sbuf);
1705         if (!NT_STATUS_IS_OK(status)) {
1706                 END_PROFILE(SMBctemp);
1707                 return ERROR_NT(status);
1708         }
1709
1710         status = check_name(conn, fname);
1711         if (!NT_STATUS_IS_OK(status)) {
1712                 END_PROFILE(SMBctemp);
1713                 return ERROR_NT(status);
1714         }
1715   
1716         tmpfd = smb_mkstemp(fname);
1717         if (tmpfd == -1) {
1718                 END_PROFILE(SMBctemp);
1719                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1720         }
1721
1722         SMB_VFS_STAT(conn,fname,&sbuf);
1723
1724         /* We should fail if file does not exist. */
1725         status = open_file_ntcreate(conn,fname,&sbuf,
1726                                 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1727                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1728                                 FILE_OPEN,
1729                                 0,
1730                                 fattr,
1731                                 oplock_request,
1732                                 NULL, &fsp);
1733
1734         /* close fd from smb_mkstemp() */
1735         close(tmpfd);
1736
1737         if (!NT_STATUS_IS_OK(status)) {
1738                 END_PROFILE(SMBctemp);
1739                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1740                         /* We have re-scheduled this call. */
1741                         return -1;
1742                 }
1743                 return ERROR_NT(status);
1744         }
1745
1746         outsize = set_message(inbuf,outbuf,1,0,True);
1747         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1748
1749         /* the returned filename is relative to the directory */
1750         s = strrchr_m(fname, '/');
1751         if (!s) {
1752                 s = fname;
1753         } else {
1754                 s++;
1755         }
1756
1757         p = smb_buf(outbuf);
1758 #if 0
1759         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1760            thing in the byte section. JRA */
1761         SSVALS(p, 0, -1); /* what is this? not in spec */
1762 #endif
1763         namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1764         p += namelen;
1765         outsize = set_message_end(inbuf,outbuf, p);
1766
1767         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1768                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1769         }
1770   
1771         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1772                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1773         }
1774
1775         DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1776         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1777                         (unsigned int)sbuf.st_mode ) );
1778
1779         END_PROFILE(SMBctemp);
1780         return(outsize);
1781 }
1782
1783 /*******************************************************************
1784  Check if a user is allowed to rename a file.
1785 ********************************************************************/
1786
1787 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1788                            uint16 dirtype, SMB_STRUCT_STAT *pst)
1789 {
1790         uint32 fmode;
1791
1792         if (!CAN_WRITE(conn)) {
1793                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1794         }
1795
1796         fmode = dos_mode(conn, fsp->fsp_name, pst);
1797         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1798                 return NT_STATUS_NO_SUCH_FILE;
1799         }
1800
1801         if (S_ISDIR(pst->st_mode)) {
1802                 return NT_STATUS_OK;
1803         }
1804
1805         if (fsp->access_mask & DELETE_ACCESS) {
1806                 return NT_STATUS_OK;
1807         }
1808
1809         return NT_STATUS_ACCESS_DENIED;
1810 }
1811
1812 /*******************************************************************
1813  * unlink a file with all relevant access checks
1814  *******************************************************************/
1815
1816 static NTSTATUS do_unlink(connection_struct *conn, char *fname,
1817                           uint32 dirtype, BOOL can_defer)
1818 {
1819         SMB_STRUCT_STAT sbuf;
1820         uint32 fattr;
1821         files_struct *fsp;
1822         uint32 dirtype_orig = dirtype;
1823         NTSTATUS status;
1824
1825         DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
1826
1827         if (!CAN_WRITE(conn)) {
1828                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1829         }
1830
1831         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1832                 return map_nt_error_from_unix(errno);
1833         }
1834
1835         fattr = dos_mode(conn,fname,&sbuf);
1836
1837         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1838                 dirtype = aDIR|aARCH|aRONLY;
1839         }
1840
1841         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1842         if (!dirtype) {
1843                 return NT_STATUS_NO_SUCH_FILE;
1844         }
1845
1846         if (!dir_check_ftype(conn, fattr, dirtype)) {
1847                 if (fattr & aDIR) {
1848                         return NT_STATUS_FILE_IS_A_DIRECTORY;
1849                 }
1850                 return NT_STATUS_NO_SUCH_FILE;
1851         }
1852
1853         if (dirtype_orig & 0x8000) {
1854                 /* These will never be set for POSIX. */
1855                 return NT_STATUS_NO_SUCH_FILE;
1856         }
1857
1858 #if 0
1859         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1860                 return NT_STATUS_FILE_IS_A_DIRECTORY;
1861         }
1862
1863         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1864                 return NT_STATUS_NO_SUCH_FILE;
1865         }
1866
1867         if (dirtype & 0xFF00) {
1868                 /* These will never be set for POSIX. */
1869                 return NT_STATUS_NO_SUCH_FILE;
1870         }
1871
1872         dirtype &= 0xFF;
1873         if (!dirtype) {
1874                 return NT_STATUS_NO_SUCH_FILE;
1875         }
1876
1877         /* Can't delete a directory. */
1878         if (fattr & aDIR) {
1879                 return NT_STATUS_FILE_IS_A_DIRECTORY;
1880         }
1881 #endif
1882
1883 #if 0 /* JRATEST */
1884         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1885                 return NT_STATUS_OBJECT_NAME_INVALID;
1886 #endif /* JRATEST */
1887
1888         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1889
1890           On a Windows share, a file with read-only dosmode can be opened with
1891           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1892           fails with NT_STATUS_CANNOT_DELETE error.
1893
1894           This semantic causes a problem that a user can not
1895           rename a file with read-only dosmode on a Samba share
1896           from a Windows command prompt (i.e. cmd.exe, but can rename
1897           from Windows Explorer).
1898         */
1899
1900         if (!lp_delete_readonly(SNUM(conn))) {
1901                 if (fattr & aRONLY) {
1902                         return NT_STATUS_CANNOT_DELETE;
1903                 }
1904         }
1905
1906         /* On open checks the open itself will check the share mode, so
1907            don't do it here as we'll get it wrong. */
1908
1909         status = open_file_ntcreate(conn, fname, &sbuf,
1910                                     DELETE_ACCESS,
1911                                     FILE_SHARE_NONE,
1912                                     FILE_OPEN,
1913                                     0,
1914                                     FILE_ATTRIBUTE_NORMAL,
1915                                     can_defer ? 0 : INTERNAL_OPEN_ONLY,
1916                                     NULL, &fsp);
1917
1918         if (!NT_STATUS_IS_OK(status)) {
1919                 DEBUG(10, ("open_file_ntcreate failed: %s\n",
1920                            nt_errstr(status)));
1921                 return status;
1922         }
1923
1924         /* The set is across all open files on this dev/inode pair. */
1925         if (!set_delete_on_close(fsp, True, &current_user.ut)) {
1926                 close_file(fsp, NORMAL_CLOSE);
1927                 return NT_STATUS_ACCESS_DENIED;
1928         }
1929
1930         return close_file(fsp,NORMAL_CLOSE);
1931 }
1932
1933 /****************************************************************************
1934  The guts of the unlink command, split out so it may be called by the NT SMB
1935  code.
1936 ****************************************************************************/
1937
1938 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
1939                           char *name, BOOL has_wild, BOOL can_defer)
1940 {
1941         pstring directory;
1942         pstring mask;
1943         char *p;
1944         int count=0;
1945         NTSTATUS status = NT_STATUS_OK;
1946         SMB_STRUCT_STAT sbuf;
1947         
1948         *directory = *mask = 0;
1949         
1950         status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1951         if (!NT_STATUS_IS_OK(status)) {
1952                 return status;
1953         }
1954         
1955         p = strrchr_m(name,'/');
1956         if (!p) {
1957                 pstrcpy(directory,".");
1958                 pstrcpy(mask,name);
1959         } else {
1960                 *p = 0;
1961                 pstrcpy(directory,name);
1962                 pstrcpy(mask,p+1);
1963         }
1964         
1965         /*
1966          * We should only check the mangled cache
1967          * here if unix_convert failed. This means
1968          * that the path in 'mask' doesn't exist
1969          * on the file system and so we need to look
1970          * for a possible mangle. This patch from
1971          * Tine Smukavec <valentin.smukavec@hermes.si>.
1972          */
1973         
1974         if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
1975                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
1976         
1977         if (!has_wild) {
1978                 pstrcat(directory,"/");
1979                 pstrcat(directory,mask);
1980                 if (dirtype == 0) {
1981                         dirtype = FILE_ATTRIBUTE_NORMAL;
1982                 }
1983
1984                 status = check_name(conn, directory);
1985                 if (!NT_STATUS_IS_OK(status)) {
1986                         return status;
1987                 }
1988
1989                 status = do_unlink(conn,directory,dirtype,can_defer);
1990                 if (!NT_STATUS_IS_OK(status)) {
1991                         return status;
1992                 }
1993
1994                 count++;
1995         } else {
1996                 struct smb_Dir *dir_hnd = NULL;
1997                 long offset = 0;
1998                 const char *dname;
1999                 
2000                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2001                         return NT_STATUS_OBJECT_NAME_INVALID;
2002                 }
2003
2004                 if (strequal(mask,"????????.???")) {
2005                         pstrcpy(mask,"*");
2006                 }
2007
2008                 status = check_name(conn, directory);
2009                 if (!NT_STATUS_IS_OK(status)) {
2010                         return status;
2011                 }
2012
2013                 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2014                 if (dir_hnd == NULL) {
2015                         return map_nt_error_from_unix(errno);
2016                 }
2017                 
2018                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2019                    the pattern matches against the long name, otherwise the short name 
2020                    We don't implement this yet XXXX
2021                 */
2022                 
2023                 status = NT_STATUS_NO_SUCH_FILE;
2024
2025                 while ((dname = ReadDirName(dir_hnd, &offset))) {
2026                         SMB_STRUCT_STAT st;
2027                         pstring fname;
2028                         pstrcpy(fname,dname);
2029
2030                         if (!is_visible_file(conn, directory, dname, &st, True)) {
2031                                 continue;
2032                         }
2033
2034                         /* Quick check for "." and ".." */
2035                         if (fname[0] == '.') {
2036                                 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2037                                         continue;
2038                                 }
2039                         }
2040
2041                         if(!mask_match(fname, mask, conn->case_sensitive)) {
2042                                 continue;
2043                         }
2044                                 
2045                         slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2046
2047                         status = check_name(conn, fname);
2048                         if (!NT_STATUS_IS_OK(status)) {
2049                                 CloseDir(dir_hnd);
2050                                 return status;
2051                         }
2052
2053                         status = do_unlink(conn, fname, dirtype, can_defer);
2054                         if (!NT_STATUS_IS_OK(status)) {
2055                                 continue;
2056                         }
2057
2058                         count++;
2059                         DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2060                                  fname));
2061                 }
2062                 CloseDir(dir_hnd);
2063         }
2064         
2065         if (count == 0 && NT_STATUS_IS_OK(status)) {
2066                 status = map_nt_error_from_unix(errno);
2067         }
2068
2069         return status;
2070 }
2071
2072 /****************************************************************************
2073  Reply to a unlink
2074 ****************************************************************************/
2075
2076 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
2077                  int dum_buffsize)
2078 {
2079         int outsize = 0;
2080         pstring name;
2081         uint32 dirtype;
2082         NTSTATUS status;
2083         BOOL path_contains_wcard = False;
2084
2085         START_PROFILE(SMBunlink);
2086
2087         dirtype = SVAL(inbuf,smb_vwv0);
2088         
2089         srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
2090         if (!NT_STATUS_IS_OK(status)) {
2091                 END_PROFILE(SMBunlink);
2092                 return ERROR_NT(status);
2093         }
2094
2095         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
2096         if (!NT_STATUS_IS_OK(status)) {
2097                 END_PROFILE(SMBunlink);
2098                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2099                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
2100                 }
2101                 return ERROR_NT(status);
2102         }
2103         
2104         DEBUG(3,("reply_unlink : %s\n",name));
2105         
2106         status = unlink_internals(conn, dirtype, name, path_contains_wcard,
2107                                   True);
2108         if (!NT_STATUS_IS_OK(status)) {
2109                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2110                         /* We have re-scheduled this call. */
2111                         return -1;
2112                 }
2113                 return ERROR_NT(status);
2114         }
2115
2116         outsize = set_message(inbuf,outbuf,0,0,False);
2117   
2118         END_PROFILE(SMBunlink);
2119         return outsize;
2120 }
2121
2122 /****************************************************************************
2123  Fail for readbraw.
2124 ****************************************************************************/
2125
2126 static void fail_readraw(void)
2127 {
2128         pstring errstr;
2129         slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2130                 strerror(errno) );
2131         exit_server_cleanly(errstr);
2132 }
2133
2134 /****************************************************************************
2135  Fake (read/write) sendfile. Returns -1 on read or write fail.
2136 ****************************************************************************/
2137
2138 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
2139 {
2140         size_t tosend = nread;
2141
2142         while (tosend > 0) {
2143                 ssize_t ret;
2144                 size_t cur_read;
2145
2146                 if (tosend > bufsize) {
2147                         cur_read = bufsize;
2148                 } else {
2149                         cur_read = tosend;
2150                 }
2151                 ret = read_file(fsp,buf,startpos,cur_read);
2152                 if (ret == -1) {
2153                         return -1;
2154                 }
2155
2156                 /* If we had a short read, fill with zeros. */
2157                 if (ret < cur_read) {
2158                         memset(buf, '\0', cur_read - ret);
2159                 }
2160
2161                 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2162                         return -1;
2163                 }
2164                 tosend -= cur_read;
2165                 startpos += cur_read;
2166         }
2167
2168         return (ssize_t)nread;
2169 }
2170
2171 /****************************************************************************
2172  Use sendfile in readbraw.
2173 ****************************************************************************/
2174
2175 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2176                 ssize_t mincount, char *outbuf, int out_buffsize)
2177 {
2178         ssize_t ret=0;
2179
2180 #if defined(WITH_SENDFILE)
2181         /*
2182          * We can only use sendfile on a non-chained packet 
2183          * but we can use on a non-oplocked file. tridge proved this
2184          * on a train in Germany :-). JRA.
2185          * reply_readbraw has already checked the length.
2186          */
2187
2188         if ( (chain_size == 0) && (nread > 0) &&
2189             (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2190                 DATA_BLOB header;
2191
2192                 _smb_setlen(outbuf,nread);
2193                 header.data = (uint8 *)outbuf;
2194                 header.length = 4;
2195                 header.free = NULL;
2196
2197                 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2198                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2199                         if (errno == ENOSYS) {
2200                                 goto normal_readbraw;
2201                         }
2202
2203                         /*
2204                          * Special hack for broken Linux with no working sendfile. If we
2205                          * return EINTR we sent the header but not the rest of the data.
2206                          * Fake this up by doing read/write calls.
2207                          */
2208                         if (errno == EINTR) {
2209                                 /* Ensure we don't do this again. */
2210                                 set_use_sendfile(SNUM(conn), False);
2211                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2212
2213                                 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2214                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2215                                                 fsp->fsp_name, strerror(errno) ));
2216                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2217                                 }
2218                                 return;
2219                         }
2220
2221                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2222                                 fsp->fsp_name, strerror(errno) ));
2223                         exit_server_cleanly("send_file_readbraw sendfile failed");
2224                 }
2225
2226                 return;
2227         }
2228 #endif
2229
2230 normal_readbraw:
2231
2232         if (nread > 0) {
2233                 ret = read_file(fsp,outbuf+4,startpos,nread);
2234 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2235                 if (ret < mincount)
2236                         ret = 0;
2237 #else
2238                 if (ret < nread)
2239                         ret = 0;
2240 #endif
2241         }
2242
2243         _smb_setlen(outbuf,ret);
2244         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2245                 fail_readraw();
2246 }
2247
2248 /****************************************************************************
2249  Reply to a readbraw (core+ protocol).
2250 ****************************************************************************/
2251
2252 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2253 {
2254         ssize_t maxcount,mincount;
2255         size_t nread = 0;
2256         SMB_OFF_T startpos;
2257         char *header = outbuf;
2258         files_struct *fsp;
2259         START_PROFILE(SMBreadbraw);
2260
2261         if (srv_is_signing_active()) {
2262                 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2263         }
2264
2265         /*
2266          * Special check if an oplock break has been issued
2267          * and the readraw request croses on the wire, we must
2268          * return a zero length response here.
2269          */
2270
2271         fsp = file_fsp(inbuf,smb_vwv0);
2272
2273         if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2274                 /*
2275                  * fsp could be NULL here so use the value from the packet. JRA.
2276                  */
2277                 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2278                 _smb_setlen(header,0);
2279                 if (write_data(smbd_server_fd(),header,4) != 4)
2280                         fail_readraw();
2281                 END_PROFILE(SMBreadbraw);
2282                 return(-1);
2283         }
2284
2285         CHECK_FSP(fsp,conn);
2286
2287         flush_write_cache(fsp, READRAW_FLUSH);
2288
2289         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2290         if(CVAL(inbuf,smb_wct) == 10) {
2291                 /*
2292                  * This is a large offset (64 bit) read.
2293                  */
2294 #ifdef LARGE_SMB_OFF_T
2295
2296                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2297
2298 #else /* !LARGE_SMB_OFF_T */
2299
2300                 /*
2301                  * Ensure we haven't been sent a >32 bit offset.
2302                  */
2303
2304                 if(IVAL(inbuf,smb_vwv8) != 0) {
2305                         DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2306 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2307                         _smb_setlen(header,0);
2308                         if (write_data(smbd_server_fd(),header,4) != 4)
2309                                 fail_readraw();
2310                         END_PROFILE(SMBreadbraw);
2311                         return(-1);
2312                 }
2313
2314 #endif /* LARGE_SMB_OFF_T */
2315
2316                 if(startpos < 0) {
2317                         DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2318                         _smb_setlen(header,0);
2319                         if (write_data(smbd_server_fd(),header,4) != 4)
2320                                 fail_readraw();
2321                         END_PROFILE(SMBreadbraw);
2322                         return(-1);
2323                 }      
2324         }
2325         maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2326         mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2327
2328         /* ensure we don't overrun the packet size */
2329         maxcount = MIN(65535,maxcount);
2330
2331         if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2332                 SMB_STRUCT_STAT st;
2333                 SMB_OFF_T size = 0;
2334   
2335                 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2336                         size = st.st_size;
2337                 }
2338
2339                 if (startpos >= size) {
2340                         nread = 0;
2341                 } else {
2342                         nread = MIN(maxcount,(size - startpos));          
2343                 }
2344         }
2345
2346 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2347         if (nread < mincount)
2348                 nread = 0;
2349 #endif
2350   
2351         DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2352                                 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2353   
2354         send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2355
2356         DEBUG(5,("readbraw finished\n"));
2357         END_PROFILE(SMBreadbraw);
2358         return -1;
2359 }
2360
2361 #undef DBGC_CLASS
2362 #define DBGC_CLASS DBGC_LOCKING
2363
2364 /****************************************************************************
2365  Reply to a lockread (core+ protocol).
2366 ****************************************************************************/
2367
2368 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2369 {
2370         ssize_t nread = -1;
2371         char *data;
2372         int outsize = 0;
2373         SMB_OFF_T startpos;
2374         size_t numtoread;
2375         NTSTATUS status;
2376         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2377         struct byte_range_lock *br_lck = NULL;
2378         START_PROFILE(SMBlockread);
2379
2380         CHECK_FSP(fsp,conn);
2381         if (!CHECK_READ(fsp,inbuf)) {
2382                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2383         }
2384
2385         release_level_2_oplocks_on_change(fsp);
2386
2387         numtoread = SVAL(inbuf,smb_vwv1);
2388         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2389   
2390         outsize = set_message(inbuf,outbuf,5,3,True);
2391         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2392         data = smb_buf(outbuf) + 3;
2393         
2394         /*
2395          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2396          * protocol request that predates the read/write lock concept. 
2397          * Thus instead of asking for a read lock here we need to ask
2398          * for a write lock. JRA.
2399          * Note that the requested lock size is unaffected by max_recv.
2400          */
2401         
2402         br_lck = do_lock(smbd_messaging_context(),
2403                         fsp,
2404                         (uint32)SVAL(inbuf,smb_pid), 
2405                         (SMB_BIG_UINT)numtoread,
2406                         (SMB_BIG_UINT)startpos,
2407                         WRITE_LOCK,
2408                         WINDOWS_LOCK,
2409                         False, /* Non-blocking lock. */
2410                         &status,
2411                         NULL);
2412         TALLOC_FREE(br_lck);
2413
2414         if (NT_STATUS_V(status)) {
2415                 END_PROFILE(SMBlockread);
2416                 return ERROR_NT(status);
2417         }
2418
2419         /*
2420          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2421          */
2422
2423         if (numtoread > max_recv) {
2424                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2425 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2426                         (unsigned int)numtoread, (unsigned int)max_recv ));
2427                 numtoread = MIN(numtoread,max_recv);
2428         }
2429         nread = read_file(fsp,data,startpos,numtoread);
2430
2431         if (nread < 0) {
2432                 END_PROFILE(SMBlockread);
2433                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2434         }
2435         
2436         outsize += nread;
2437         SSVAL(outbuf,smb_vwv0,nread);
2438         SSVAL(outbuf,smb_vwv5,nread+3);
2439         SSVAL(smb_buf(outbuf),1,nread);
2440         
2441         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2442                  fsp->fnum, (int)numtoread, (int)nread));
2443
2444         END_PROFILE(SMBlockread);
2445         return(outsize);
2446 }
2447
2448 #undef DBGC_CLASS
2449 #define DBGC_CLASS DBGC_ALL
2450
2451 /****************************************************************************
2452  Reply to a read.
2453 ****************************************************************************/
2454
2455 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2456 {
2457         size_t numtoread;
2458         ssize_t nread = 0;
2459         char *data;
2460         SMB_OFF_T startpos;
2461         int outsize = 0;
2462         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2463         START_PROFILE(SMBread);
2464
2465         CHECK_FSP(fsp,conn);
2466         if (!CHECK_READ(fsp,inbuf)) {
2467                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2468         }
2469
2470         numtoread = SVAL(inbuf,smb_vwv1);
2471         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2472
2473         outsize = set_message(inbuf,outbuf,5,3,True);
2474         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2475         /*
2476          * The requested read size cannot be greater than max_recv. JRA.
2477          */
2478         if (numtoread > max_recv) {
2479                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2480 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2481                         (unsigned int)numtoread, (unsigned int)max_recv ));
2482                 numtoread = MIN(numtoread,max_recv);
2483         }
2484
2485         data = smb_buf(outbuf) + 3;
2486   
2487         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2488                 END_PROFILE(SMBread);
2489                 return ERROR_DOS(ERRDOS,ERRlock);
2490         }
2491
2492         if (numtoread > 0)
2493                 nread = read_file(fsp,data,startpos,numtoread);
2494
2495         if (nread < 0) {
2496                 END_PROFILE(SMBread);
2497                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2498         }
2499   
2500         outsize += nread;
2501         SSVAL(outbuf,smb_vwv0,nread);
2502         SSVAL(outbuf,smb_vwv5,nread+3);
2503         SCVAL(smb_buf(outbuf),0,1);
2504         SSVAL(smb_buf(outbuf),1,nread);
2505   
2506         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2507                 fsp->fnum, (int)numtoread, (int)nread ) );
2508
2509         END_PROFILE(SMBread);
2510         return(outsize);
2511 }
2512
2513 /****************************************************************************
2514  Setup readX header.
2515 ****************************************************************************/
2516
2517 static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
2518 {
2519         int outsize;
2520         char *data = smb_buf(outbuf);
2521
2522         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2523         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2524         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2525         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2526         SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2527         SCVAL(outbuf,smb_vwv0,0xFF);
2528         outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
2529         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2530         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2531         return outsize;
2532 }
2533
2534 /****************************************************************************
2535  Reply to a read and X - possibly using sendfile.
2536 ****************************************************************************/
2537
2538 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2539                 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2540 {
2541         SMB_STRUCT_STAT sbuf;
2542         int outsize = 0;
2543         ssize_t nread = -1;
2544         char *data = smb_buf(outbuf);
2545
2546         if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2547                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2548         }
2549
2550         if (startpos > sbuf.st_size) {
2551                 smb_maxcnt = 0;
2552         }
2553
2554         if (smb_maxcnt > (sbuf.st_size - startpos)) {
2555                 smb_maxcnt = (sbuf.st_size - startpos);
2556         }
2557
2558         if (smb_maxcnt == 0) {
2559                 goto normal_read;
2560         }
2561
2562 #if defined(WITH_SENDFILE)
2563         /*
2564          * We can only use sendfile on a non-chained packet 
2565          * but we can use on a non-oplocked file. tridge proved this
2566          * on a train in Germany :-). JRA.
2567          */
2568
2569         if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2570             lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2571                 DATA_BLOB header;
2572
2573                 /* 
2574                  * Set up the packet header before send. We
2575                  * assume here the sendfile will work (get the
2576                  * correct amount of data).
2577                  */
2578
2579                 setup_readX_header(inbuf,outbuf,smb_maxcnt);
2580                 set_message(inbuf,outbuf,12,smb_maxcnt,False);
2581                 header.data = (uint8 *)outbuf;
2582                 header.length = data - outbuf;
2583                 header.free = NULL;
2584
2585                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2586                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2587                         if (errno == ENOSYS) {
2588                                 goto normal_read;
2589                         }
2590
2591                         /*
2592                          * Special hack for broken Linux with no working sendfile. If we
2593                          * return EINTR we sent the header but not the rest of the data.
2594                          * Fake this up by doing read/write calls.
2595                          */
2596
2597                         if (errno == EINTR) {
2598                                 /* Ensure we don't do this again. */
2599                                 set_use_sendfile(SNUM(conn), False);
2600                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2601
2602                                 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2603                                                         len_outbuf - (data-outbuf))) == -1) {
2604                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2605                                                 fsp->fsp_name, strerror(errno) ));
2606                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
2607                                 }
2608                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2609                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2610                                 /* Returning -1 here means successful sendfile. */
2611                                 return -1;
2612                         }
2613
2614                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2615                                 fsp->fsp_name, strerror(errno) ));
2616                         exit_server_cleanly("send_file_readX sendfile failed");
2617                 }
2618
2619                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2620                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2621                 /* Returning -1 here means successful sendfile. */
2622                 return -1;
2623         }
2624
2625 #endif
2626
2627 normal_read:
2628
2629         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
2630                 int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
2631                 /* Send out the header. */
2632                 if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
2633                         DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2634                                 fsp->fsp_name, strerror(errno) ));
2635                         exit_server_cleanly("send_file_readX sendfile failed");
2636                 }
2637                 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2638                                         len_outbuf - (data-outbuf))) == -1) {
2639                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2640                                 fsp->fsp_name, strerror(errno) ));
2641                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
2642                 }
2643                 return -1;
2644         } else {
2645                 nread = read_file(fsp,data,startpos,smb_maxcnt);
2646
2647                 if (nread < 0) {
2648                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2649                 }
2650
2651                 outsize = setup_readX_header(inbuf, outbuf,nread);
2652
2653                 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2654                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2655
2656                 /* Returning the number of bytes we want to send back - including header. */
2657                 return outsize;
2658         }
2659 }
2660
2661 /****************************************************************************
2662  Reply to a read and X.
2663 ****************************************************************************/
2664
2665 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2666 {
2667         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2668         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2669         ssize_t nread = -1;
2670         size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2671         BOOL big_readX = False;
2672 #if 0
2673         size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2674 #endif
2675
2676         START_PROFILE(SMBreadX);
2677
2678         /* If it's an IPC, pass off the pipe handler. */
2679         if (IS_IPC(conn)) {
2680                 END_PROFILE(SMBreadX);
2681                 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2682         }
2683
2684         CHECK_FSP(fsp,conn);
2685         if (!CHECK_READ(fsp,inbuf)) {
2686                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2687         }
2688
2689         set_message(inbuf,outbuf,12,0,True);
2690
2691         if (global_client_caps & CAP_LARGE_READX) {
2692                 size_t upper_size = SVAL(inbuf,smb_vwv7);
2693                 smb_maxcnt |= (upper_size<<16);
2694                 if (upper_size > 1) {
2695                         /* Can't do this on a chained packet. */
2696                         if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
2697                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2698                         }
2699                         /* We currently don't do this on signed or sealed data. */
2700                         if (srv_is_signing_active() || srv_encryption_on()) {
2701                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2702                         }
2703                         /* Is there room in the reply for this data ? */
2704                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
2705                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2706                         }
2707                         big_readX = True;
2708                 }
2709         }
2710
2711         if(CVAL(inbuf,smb_wct) == 12) {
2712 #ifdef LARGE_SMB_OFF_T
2713                 /*
2714                  * This is a large offset (64 bit) read.
2715                  */
2716                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2717
2718 #else /* !LARGE_SMB_OFF_T */
2719
2720                 /*
2721                  * Ensure we haven't been sent a >32 bit offset.
2722                  */
2723
2724                 if(IVAL(inbuf,smb_vwv10) != 0) {
2725                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2726 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2727                         END_PROFILE(SMBreadX);
2728                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2729                 }
2730
2731 #endif /* LARGE_SMB_OFF_T */
2732
2733         }
2734
2735         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2736                 END_PROFILE(SMBreadX);
2737                 return ERROR_DOS(ERRDOS,ERRlock);
2738         }
2739
2740         if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2741                 END_PROFILE(SMBreadX);
2742                 return -1;
2743         }
2744
2745         nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2746         /* Only call chain_reply if not an error. */
2747         if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2748                 nread = chain_reply(inbuf,outbuf,length,bufsize);
2749         }
2750
2751         END_PROFILE(SMBreadX);
2752         return nread;
2753 }
2754
2755 /****************************************************************************
2756  Reply to a writebraw (core+ or LANMAN1.0 protocol).
2757 ****************************************************************************/
2758
2759 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2760 {
2761         ssize_t nwritten=0;
2762         ssize_t total_written=0;
2763         size_t numtowrite=0;
2764         size_t tcount;
2765         SMB_OFF_T startpos;
2766         char *data=NULL;
2767         BOOL write_through;
2768         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2769         int outsize = 0;
2770         NTSTATUS status;
2771         START_PROFILE(SMBwritebraw);
2772
2773         if (srv_is_signing_active()) {
2774                 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2775         }
2776
2777         CHECK_FSP(fsp,conn);
2778         if (!CHECK_WRITE(fsp)) {
2779                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2780         }
2781   
2782         tcount = IVAL(inbuf,smb_vwv1);
2783         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2784         write_through = BITSETW(inbuf+smb_vwv7,0);
2785
2786         /* We have to deal with slightly different formats depending
2787                 on whether we are using the core+ or lanman1.0 protocol */
2788
2789         if(Protocol <= PROTOCOL_COREPLUS) {
2790                 numtowrite = SVAL(smb_buf(inbuf),-2);
2791                 data = smb_buf(inbuf);
2792         } else {
2793                 numtowrite = SVAL(inbuf,smb_vwv10);
2794                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2795         }
2796
2797         /* force the error type */
2798         SCVAL(inbuf,smb_com,SMBwritec);
2799         SCVAL(outbuf,smb_com,SMBwritec);
2800
2801         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2802                 END_PROFILE(SMBwritebraw);
2803                 return(ERROR_DOS(ERRDOS,ERRlock));
2804         }
2805
2806         if (numtowrite>0)
2807                 nwritten = write_file(fsp,data,startpos,numtowrite);
2808   
2809         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2810                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2811
2812         if (nwritten < (ssize_t)numtowrite)  {
2813                 END_PROFILE(SMBwritebraw);
2814                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2815         }
2816
2817         total_written = nwritten;
2818
2819         /* Return a message to the redirector to tell it to send more bytes */
2820         SCVAL(outbuf,smb_com,SMBwritebraw);
2821         SSVALS(outbuf,smb_vwv0,-1);
2822         outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2823         show_msg(outbuf);
2824         if (!send_smb(smbd_server_fd(),outbuf))
2825                 exit_server_cleanly("reply_writebraw: send_smb failed.");
2826   
2827         /* Now read the raw data into the buffer and write it */
2828         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2829                 exit_server_cleanly("secondary writebraw failed");
2830         }
2831   
2832         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2833         numtowrite = smb_len(inbuf);
2834
2835         /* Set up outbuf to return the correct return */
2836         outsize = set_message(inbuf,outbuf,1,0,True);
2837         SCVAL(outbuf,smb_com,SMBwritec);
2838
2839         if (numtowrite != 0) {
2840
2841                 if (numtowrite > BUFFER_SIZE) {
2842                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2843                                 (unsigned int)numtowrite ));
2844                         exit_server_cleanly("secondary writebraw failed");
2845                 }
2846
2847                 if (tcount > nwritten+numtowrite) {
2848                         DEBUG(3,("Client overestimated the write %d %d %d\n",
2849                                 (int)tcount,(int)nwritten,(int)numtowrite));
2850                 }
2851
2852                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2853                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2854                                 strerror(errno) ));
2855                         exit_server_cleanly("secondary writebraw failed");
2856                 }
2857
2858                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2859                 if (nwritten == -1) {
2860                         END_PROFILE(SMBwritebraw);
2861                         return(UNIXERROR(ERRHRD,ERRdiskfull));
2862                 }
2863
2864                 if (nwritten < (ssize_t)numtowrite) {
2865                         SCVAL(outbuf,smb_rcls,ERRHRD);
2866                         SSVAL(outbuf,smb_err,ERRdiskfull);      
2867                 }
2868
2869                 if (nwritten > 0)
2870                         total_written += nwritten;
2871         }
2872  
2873         SSVAL(outbuf,smb_vwv0,total_written);
2874
2875         status = sync_file(conn, fsp, write_through);
2876         if (!NT_STATUS_IS_OK(status)) {
2877                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
2878                         fsp->fsp_name, nt_errstr(status) ));
2879                 END_PROFILE(SMBwritebraw);
2880                 return ERROR_NT(status);
2881         }
2882
2883         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2884                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2885
2886         /* we won't return a status if write through is not selected - this follows what WfWg does */
2887         END_PROFILE(SMBwritebraw);
2888         if (!write_through && total_written==tcount) {
2889
2890 #if RABBIT_PELLET_FIX
2891                 /*
2892                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2893                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2894                  */
2895                 if (!send_keepalive(smbd_server_fd()))
2896                         exit_server_cleanly("reply_writebraw: send of keepalive failed");
2897 #endif
2898                 return(-1);
2899         }
2900
2901         return(outsize);
2902 }
2903
2904 #undef DBGC_CLASS
2905 #define DBGC_CLASS DBGC_LOCKING
2906
2907 /****************************************************************************
2908  Reply to a writeunlock (core+).
2909 ****************************************************************************/
2910
2911 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
2912                       int size, int dum_buffsize)
2913 {
2914         ssize_t nwritten = -1;
2915         size_t numtowrite;
2916         SMB_OFF_T startpos;
2917         char *data;
2918         NTSTATUS status = NT_STATUS_OK;
2919         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2920         int outsize = 0;
2921         START_PROFILE(SMBwriteunlock);
2922         
2923         CHECK_FSP(fsp,conn);
2924         if (!CHECK_WRITE(fsp)) {
2925                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2926         }
2927
2928         numtowrite = SVAL(inbuf,smb_vwv1);
2929         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2930         data = smb_buf(inbuf) + 3;
2931   
2932         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2933                 END_PROFILE(SMBwriteunlock);
2934                 return ERROR_DOS(ERRDOS,ERRlock);
2935         }
2936
2937         /* The special X/Open SMB protocol handling of
2938            zero length writes is *NOT* done for
2939            this call */
2940         if(numtowrite == 0) {
2941                 nwritten = 0;
2942         } else {
2943                 nwritten = write_file(fsp,data,startpos,numtowrite);
2944         }
2945   
2946         status = sync_file(conn, fsp, False /* write through */);
2947         if (!NT_STATUS_IS_OK(status)) {
2948                 END_PROFILE(SMBwriteunlock);
2949                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
2950                         fsp->fsp_name, nt_errstr(status) ));
2951                 return ERROR_NT(status);
2952         }
2953
2954         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2955                 END_PROFILE(SMBwriteunlock);
2956                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2957         }
2958
2959         if (numtowrite) {
2960                 status = do_unlock(smbd_messaging_context(),
2961                                 fsp,
2962                                 (uint32)SVAL(inbuf,smb_pid),
2963                                 (SMB_BIG_UINT)numtowrite, 
2964                                 (SMB_BIG_UINT)startpos,
2965                                 WINDOWS_LOCK);
2966
2967                 if (NT_STATUS_V(status)) {
2968                         END_PROFILE(SMBwriteunlock);
2969                         return ERROR_NT(status);
2970                 }
2971         }
2972         
2973         outsize = set_message(inbuf,outbuf,1,0,True);
2974         
2975         SSVAL(outbuf,smb_vwv0,nwritten);
2976         
2977         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2978                  fsp->fnum, (int)numtowrite, (int)nwritten));
2979         
2980         END_PROFILE(SMBwriteunlock);
2981         return outsize;
2982 }
2983
2984 #undef DBGC_CLASS
2985 #define DBGC_CLASS DBGC_ALL
2986
2987 /****************************************************************************
2988  Reply to a write.
2989 ****************************************************************************/
2990
2991 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2992 {
2993         size_t numtowrite;
2994         ssize_t nwritten = -1;
2995         SMB_OFF_T startpos;
2996         char *data;
2997         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2998         int outsize = 0;
2999         NTSTATUS status;
3000         START_PROFILE(SMBwrite);
3001
3002         /* If it's an IPC, pass off the pipe handler. */
3003         if (IS_IPC(conn)) {
3004                 END_PROFILE(SMBwrite);
3005                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3006         }
3007
3008         CHECK_FSP(fsp,conn);
3009         if (!CHECK_WRITE(fsp)) {
3010                 END_PROFILE(SMBwrite);
3011                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3012         }
3013
3014         numtowrite = SVAL(inbuf,smb_vwv1);
3015         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3016         data = smb_buf(inbuf) + 3;
3017   
3018         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3019                 END_PROFILE(SMBwrite);
3020                 return ERROR_DOS(ERRDOS,ERRlock);
3021         }
3022
3023         /*
3024          * X/Open SMB protocol says that if smb_vwv1 is
3025          * zero then the file size should be extended or
3026          * truncated to the size given in smb_vwv[2-3].
3027          */
3028
3029         if(numtowrite == 0) {
3030                 /*
3031                  * This is actually an allocate call, and set EOF. JRA.
3032                  */
3033                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3034                 if (nwritten < 0) {
3035                         END_PROFILE(SMBwrite);
3036                         return ERROR_NT(NT_STATUS_DISK_FULL);
3037                 }
3038                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3039                 if (nwritten < 0) {
3040                         END_PROFILE(SMBwrite);
3041                         return ERROR_NT(NT_STATUS_DISK_FULL);
3042                 }
3043         } else
3044                 nwritten = write_file(fsp,data,startpos,numtowrite);
3045   
3046         status = sync_file(conn, fsp, False);
3047         if (!NT_STATUS_IS_OK(status)) {
3048                 END_PROFILE(SMBwrite);
3049                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3050                         fsp->fsp_name, nt_errstr(status) ));
3051                 return ERROR_NT(status);
3052         }
3053
3054         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3055                 END_PROFILE(SMBwrite);
3056                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3057         }
3058
3059         outsize = set_message(inbuf,outbuf,1,0,True);
3060   
3061         SSVAL(outbuf,smb_vwv0,nwritten);
3062
3063         if (nwritten < (ssize_t)numtowrite) {
3064                 SCVAL(outbuf,smb_rcls,ERRHRD);
3065                 SSVAL(outbuf,smb_err,ERRdiskfull);      
3066         }
3067   
3068         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3069
3070         END_PROFILE(SMBwrite);
3071         return(outsize);
3072 }
3073
3074 /****************************************************************************
3075  Reply to a write and X.
3076 ****************************************************************************/
3077
3078 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3079 {
3080         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3081         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3082         size_t numtowrite = SVAL(inbuf,smb_vwv10);
3083         BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3084         ssize_t nwritten = -1;
3085         unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3086         unsigned int smblen = smb_len(inbuf);
3087         char *data;
3088         BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3089         NTSTATUS status;
3090         START_PROFILE(SMBwriteX);
3091
3092         /* If it's an IPC, pass off the pipe handler. */
3093         if (IS_IPC(conn)) {
3094                 END_PROFILE(SMBwriteX);
3095                 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3096         }
3097
3098         CHECK_FSP(fsp,conn);
3099         if (!CHECK_WRITE(fsp)) {
3100                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3101         }
3102
3103         set_message(inbuf,outbuf,6,0,True);
3104   
3105         /* Deal with possible LARGE_WRITEX */
3106         if (large_writeX) {
3107                 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3108         }
3109
3110         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3111                 END_PROFILE(SMBwriteX);
3112                 return ERROR_DOS(ERRDOS,ERRbadmem);
3113         }
3114
3115         data = smb_base(inbuf) + smb_doff;
3116
3117         if(CVAL(inbuf,smb_wct) == 14) {
3118 #ifdef LARGE_SMB_OFF_T
3119                 /*
3120                  * This is a large offset (64 bit) write.
3121                  */
3122                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3123
3124 #else /* !LARGE_SMB_OFF_T */
3125
3126                 /*
3127                  * Ensure we haven't been sent a >32 bit offset.
3128                  */