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