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