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