r1841: Fix for #1606, can't launch dos exe's.
[ira/wip.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 (chain_size ==0 && (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                                 set_use_sendfile(SNUM(conn), False);
1753                                 goto normal_read;
1754                         }
1755
1756                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1757                                 fsp->fsp_name, strerror(errno) ));
1758                         exit_server("send_file_readbraw sendfile failed");
1759                 }
1760
1761         }
1762
1763   normal_read:
1764 #endif
1765
1766         if (nread > 0) {
1767                 ret = read_file(fsp,outbuf+4,startpos,nread);
1768 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1769                 if (ret < mincount)
1770                         ret = 0;
1771 #else
1772                 if (ret < nread)
1773                         ret = 0;
1774 #endif
1775         }
1776
1777         _smb_setlen(outbuf,ret);
1778         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1779                 fail_readraw();
1780 }
1781
1782 /****************************************************************************
1783  Reply to a readbraw (core+ protocol).
1784 ****************************************************************************/
1785
1786 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1787 {
1788         extern struct current_user current_user;
1789         ssize_t maxcount,mincount;
1790         size_t nread = 0;
1791         SMB_OFF_T startpos;
1792         char *header = outbuf;
1793         files_struct *fsp;
1794         START_PROFILE(SMBreadbraw);
1795
1796         if (srv_is_signing_active()) {
1797                 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1798         }
1799
1800         /*
1801          * Special check if an oplock break has been issued
1802          * and the readraw request croses on the wire, we must
1803          * return a zero length response here.
1804          */
1805
1806         if(global_oplock_break) {
1807                 _smb_setlen(header,0);
1808                 if (write_data(smbd_server_fd(),header,4) != 4)
1809                         fail_readraw();
1810                 DEBUG(5,("readbraw - oplock break finished\n"));
1811                 END_PROFILE(SMBreadbraw);
1812                 return -1;
1813         }
1814
1815         fsp = file_fsp(inbuf,smb_vwv0);
1816
1817         if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1818                 /*
1819                  * fsp could be NULL here so use the value from the packet. JRA.
1820                  */
1821                 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1822                 _smb_setlen(header,0);
1823                 if (write_data(smbd_server_fd(),header,4) != 4)
1824                         fail_readraw();
1825                 END_PROFILE(SMBreadbraw);
1826                 return(-1);
1827         }
1828
1829         CHECK_FSP(fsp,conn);
1830
1831         flush_write_cache(fsp, READRAW_FLUSH);
1832
1833         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1834         if(CVAL(inbuf,smb_wct) == 10) {
1835                 /*
1836                  * This is a large offset (64 bit) read.
1837                  */
1838 #ifdef LARGE_SMB_OFF_T
1839
1840                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1841
1842 #else /* !LARGE_SMB_OFF_T */
1843
1844                 /*
1845                  * Ensure we haven't been sent a >32 bit offset.
1846                  */
1847
1848                 if(IVAL(inbuf,smb_vwv8) != 0) {
1849                         DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1850 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1851                         _smb_setlen(header,0);
1852                         if (write_data(smbd_server_fd(),header,4) != 4)
1853                                 fail_readraw();
1854                         END_PROFILE(SMBreadbraw);
1855                         return(-1);
1856                 }
1857
1858 #endif /* LARGE_SMB_OFF_T */
1859
1860                 if(startpos < 0) {
1861                         DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1862                         _smb_setlen(header,0);
1863                         if (write_data(smbd_server_fd(),header,4) != 4)
1864                                 fail_readraw();
1865                         END_PROFILE(SMBreadbraw);
1866                         return(-1);
1867                 }      
1868         }
1869         maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1870         mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1871
1872         /* ensure we don't overrun the packet size */
1873         maxcount = MIN(65535,maxcount);
1874
1875         if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1876                 SMB_OFF_T size = fsp->size;
1877                 SMB_OFF_T sizeneeded = startpos + maxcount;
1878   
1879                 if (size < sizeneeded) {
1880                         SMB_STRUCT_STAT st;
1881                         if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1882                                 size = st.st_size;
1883                         if (!fsp->can_write) 
1884                                 fsp->size = size;
1885                 }
1886
1887                 if (startpos >= size)
1888                         nread = 0;
1889                 else
1890                         nread = MIN(maxcount,(size - startpos));          
1891         }
1892
1893 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1894         if (nread < mincount)
1895                 nread = 0;
1896 #endif
1897   
1898         DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1899                                 (int)maxcount, (int)mincount, (int)nread ) );
1900   
1901         send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1902
1903         DEBUG(5,("readbraw finished\n"));
1904         END_PROFILE(SMBreadbraw);
1905         return -1;
1906 }
1907
1908 /****************************************************************************
1909  Reply to a lockread (core+ protocol).
1910 ****************************************************************************/
1911
1912 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1913 {
1914         ssize_t nread = -1;
1915         char *data;
1916         int outsize = 0;
1917         SMB_OFF_T startpos;
1918         size_t numtoread;
1919         NTSTATUS status;
1920         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1921         BOOL my_lock_ctx = False;
1922         START_PROFILE(SMBlockread);
1923
1924         CHECK_FSP(fsp,conn);
1925         CHECK_READ(fsp);
1926
1927         release_level_2_oplocks_on_change(fsp);
1928
1929         numtoread = SVAL(inbuf,smb_vwv1);
1930         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1931   
1932         outsize = set_message(outbuf,5,3,True);
1933         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1934         data = smb_buf(outbuf) + 3;
1935         
1936         /*
1937          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1938          * protocol request that predates the read/write lock concept. 
1939          * Thus instead of asking for a read lock here we need to ask
1940          * for a write lock. JRA.
1941          * Note that the requested lock size is unaffected by max_recv.
1942          */
1943         
1944         status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), 
1945                          (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1946
1947         if (NT_STATUS_V(status)) {
1948 #if 0
1949                 /*
1950                  * We used to make lockread a blocking lock. It turns out
1951                  * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1952                  * tester. JRA.
1953                  */
1954
1955                 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1956                         /*
1957                          * A blocking lock was requested. Package up
1958                          * this smb into a queued request and push it
1959                          * onto the blocking lock queue.
1960                          */
1961                         if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1962                                                                 (SMB_BIG_UINT)numtoread)) {
1963                                 END_PROFILE(SMBlockread);
1964                                 return -1;
1965                         }
1966                 }
1967 #endif
1968                 END_PROFILE(SMBlockread);
1969                 return ERROR_NT(status);
1970         }
1971
1972         /*
1973          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1974          */
1975
1976         if (numtoread > max_recv) {
1977                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1978 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1979                         (unsigned int)numtoread, (unsigned int)max_recv ));
1980                 numtoread = MIN(numtoread,max_recv);
1981         }
1982         nread = read_file(fsp,data,startpos,numtoread);
1983
1984         if (nread < 0) {
1985                 END_PROFILE(SMBlockread);
1986                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1987         }
1988         
1989         outsize += nread;
1990         SSVAL(outbuf,smb_vwv0,nread);
1991         SSVAL(outbuf,smb_vwv5,nread+3);
1992         SSVAL(smb_buf(outbuf),1,nread);
1993         
1994         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1995                  fsp->fnum, (int)numtoread, (int)nread));
1996
1997         END_PROFILE(SMBlockread);
1998         return(outsize);
1999 }
2000
2001 /****************************************************************************
2002  Reply to a read.
2003 ****************************************************************************/
2004
2005 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2006 {
2007         size_t numtoread;
2008         ssize_t nread = 0;
2009         char *data;
2010         SMB_OFF_T startpos;
2011         int outsize = 0;
2012         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2013         START_PROFILE(SMBread);
2014
2015         CHECK_FSP(fsp,conn);
2016         CHECK_READ(fsp);
2017
2018         numtoread = SVAL(inbuf,smb_vwv1);
2019         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2020
2021         outsize = set_message(outbuf,5,3,True);
2022         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2023         /*
2024          * The requested read size cannot be greater than max_recv. JRA.
2025          */
2026         if (numtoread > max_recv) {
2027                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2028 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2029                         (unsigned int)numtoread, (unsigned int)max_recv ));
2030                 numtoread = MIN(numtoread,max_recv);
2031         }
2032
2033         data = smb_buf(outbuf) + 3;
2034   
2035         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2036                 END_PROFILE(SMBread);
2037                 return ERROR_DOS(ERRDOS,ERRlock);
2038         }
2039
2040         if (numtoread > 0)
2041                 nread = read_file(fsp,data,startpos,numtoread);
2042
2043         if (nread < 0) {
2044                 END_PROFILE(SMBread);
2045                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2046         }
2047   
2048         outsize += nread;
2049         SSVAL(outbuf,smb_vwv0,nread);
2050         SSVAL(outbuf,smb_vwv5,nread+3);
2051         SCVAL(smb_buf(outbuf),0,1);
2052         SSVAL(smb_buf(outbuf),1,nread);
2053   
2054         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2055                 fsp->fnum, (int)numtoread, (int)nread ) );
2056
2057         END_PROFILE(SMBread);
2058         return(outsize);
2059 }
2060
2061 /****************************************************************************
2062  Reply to a read and X - possibly using sendfile.
2063 ****************************************************************************/
2064
2065 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, 
2066                 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2067 {
2068         ssize_t nread = -1;
2069         char *data = smb_buf(outbuf);
2070
2071 #if defined(WITH_SENDFILE)
2072         /*
2073          * We can only use sendfile on a non-chained packet 
2074          * but we can use on a non-oplocked file. tridge proved this
2075          * on a train in Germany :-). JRA.
2076          */
2077
2078         if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2079                         (lp_write_cache_size(SNUM(conn)) == 0) ) {
2080                 SMB_STRUCT_STAT sbuf;
2081                 DATA_BLOB header;
2082
2083                 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2084                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2085
2086                 if (startpos > sbuf.st_size)
2087                         goto normal_read;
2088
2089                 if (smb_maxcnt > (sbuf.st_size - startpos))
2090                         smb_maxcnt = (sbuf.st_size - startpos);
2091
2092                 if (smb_maxcnt == 0)
2093                         goto normal_read;
2094
2095                 /* 
2096                  * Set up the packet header before send. We
2097                  * assume here the sendfile will work (get the
2098                  * correct amount of data).
2099                  */
2100
2101                 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2102                 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2103                 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2104                 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2105                 SCVAL(outbuf,smb_vwv0,0xFF);
2106                 set_message(outbuf,12,smb_maxcnt,False);
2107                 header.data = outbuf;
2108                 header.length = data - outbuf;
2109                 header.free = NULL;
2110
2111                 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
2112                         /*
2113                          * Special hack for broken Linux with no 64 bit clean sendfile. If we
2114                          * return ENOSYS then pretend we just got a normal read.
2115                          */
2116                         if (errno == ENOSYS) {
2117                                 set_use_sendfile(SNUM(conn), False);
2118                                 goto normal_read;
2119                         }
2120
2121                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2122                                 fsp->fsp_name, strerror(errno) ));
2123                         exit_server("send_file_readX sendfile failed");
2124                 }
2125
2126                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2127                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2128                 return -1;
2129         }
2130
2131   normal_read:
2132
2133 #endif
2134
2135         nread = read_file(fsp,data,startpos,smb_maxcnt);
2136   
2137         if (nread < 0) {
2138                 END_PROFILE(SMBreadX);
2139                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2140         }
2141
2142         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2143         SSVAL(outbuf,smb_vwv5,nread);
2144         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2145         SSVAL(smb_buf(outbuf),-2,nread);
2146   
2147         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2148                 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2149
2150         return nread;
2151 }
2152
2153 /****************************************************************************
2154  Reply to a read and X.
2155 ****************************************************************************/
2156
2157 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2158 {
2159         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2160         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2161         ssize_t nread = -1;
2162         size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2163 #if 0
2164         size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2165 #endif
2166
2167         START_PROFILE(SMBreadX);
2168
2169         /* If it's an IPC, pass off the pipe handler. */
2170         if (IS_IPC(conn)) {
2171                 END_PROFILE(SMBreadX);
2172                 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2173         }
2174
2175         CHECK_FSP(fsp,conn);
2176         CHECK_READ(fsp);
2177
2178         set_message(outbuf,12,0,True);
2179
2180         if(CVAL(inbuf,smb_wct) == 12) {
2181 #ifdef LARGE_SMB_OFF_T
2182                 /*
2183                  * This is a large offset (64 bit) read.
2184                  */
2185                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2186
2187 #else /* !LARGE_SMB_OFF_T */
2188
2189                 /*
2190                  * Ensure we haven't been sent a >32 bit offset.
2191                  */
2192
2193                 if(IVAL(inbuf,smb_vwv10) != 0) {
2194                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2195 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2196                         END_PROFILE(SMBreadX);
2197                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2198                 }
2199
2200 #endif /* LARGE_SMB_OFF_T */
2201
2202         }
2203
2204         if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2205                 END_PROFILE(SMBreadX);
2206                 return ERROR_DOS(ERRDOS,ERRlock);
2207         }
2208
2209         nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2210         if (nread != -1)
2211                 nread = chain_reply(inbuf,outbuf,length,bufsize);
2212
2213         END_PROFILE(SMBreadX);
2214         return nread;
2215 }
2216
2217 /****************************************************************************
2218  Reply to a writebraw (core+ or LANMAN1.0 protocol).
2219 ****************************************************************************/
2220
2221 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2222 {
2223         ssize_t nwritten=0;
2224         ssize_t total_written=0;
2225         size_t numtowrite=0;
2226         size_t tcount;
2227         SMB_OFF_T startpos;
2228         char *data=NULL;
2229         BOOL write_through;
2230         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2231         int outsize = 0;
2232         START_PROFILE(SMBwritebraw);
2233
2234         if (srv_is_signing_active()) {
2235                 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2236         }
2237
2238         CHECK_FSP(fsp,conn);
2239         CHECK_WRITE(fsp);
2240   
2241         tcount = IVAL(inbuf,smb_vwv1);
2242         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2243         write_through = BITSETW(inbuf+smb_vwv7,0);
2244
2245         /* We have to deal with slightly different formats depending
2246                 on whether we are using the core+ or lanman1.0 protocol */
2247
2248         if(Protocol <= PROTOCOL_COREPLUS) {
2249                 numtowrite = SVAL(smb_buf(inbuf),-2);
2250                 data = smb_buf(inbuf);
2251         } else {
2252                 numtowrite = SVAL(inbuf,smb_vwv10);
2253                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2254         }
2255
2256         /* force the error type */
2257         SCVAL(inbuf,smb_com,SMBwritec);
2258         SCVAL(outbuf,smb_com,SMBwritec);
2259
2260         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2261                 END_PROFILE(SMBwritebraw);
2262                 return(ERROR_DOS(ERRDOS,ERRlock));
2263         }
2264
2265         if (numtowrite>0)
2266                 nwritten = write_file(fsp,data,startpos,numtowrite);
2267   
2268         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2269                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2270
2271         if (nwritten < (ssize_t)numtowrite)  {
2272                 END_PROFILE(SMBwritebraw);
2273                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2274         }
2275
2276         total_written = nwritten;
2277
2278         /* Return a message to the redirector to tell it to send more bytes */
2279         SCVAL(outbuf,smb_com,SMBwritebraw);
2280         SSVALS(outbuf,smb_vwv0,-1);
2281         outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2282         if (!send_smb(smbd_server_fd(),outbuf))
2283                 exit_server("reply_writebraw: send_smb failed.");
2284   
2285         /* Now read the raw data into the buffer and write it */
2286         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2287                 exit_server("secondary writebraw failed");
2288         }
2289   
2290         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2291         numtowrite = smb_len(inbuf);
2292
2293         /* Set up outbuf to return the correct return */
2294         outsize = set_message(outbuf,1,0,True);
2295         SCVAL(outbuf,smb_com,SMBwritec);
2296         SSVAL(outbuf,smb_vwv0,total_written);
2297
2298         if (numtowrite != 0) {
2299
2300                 if (numtowrite > BUFFER_SIZE) {
2301                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2302                                 (unsigned int)numtowrite ));
2303                         exit_server("secondary writebraw failed");
2304                 }
2305
2306                 if (tcount > nwritten+numtowrite) {
2307                         DEBUG(3,("Client overestimated the write %d %d %d\n",
2308                                 (int)tcount,(int)nwritten,(int)numtowrite));
2309                 }
2310
2311                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2312                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2313                                 strerror(errno) ));
2314                         exit_server("secondary writebraw failed");
2315                 }
2316
2317                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2318
2319                 if (nwritten < (ssize_t)numtowrite) {
2320                         SCVAL(outbuf,smb_rcls,ERRHRD);
2321                         SSVAL(outbuf,smb_err,ERRdiskfull);      
2322                 }
2323
2324                 if (nwritten > 0)
2325                         total_written += nwritten;
2326         }
2327  
2328         if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2329                 sync_file(conn,fsp);
2330
2331         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2332                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2333
2334         /* we won't return a status if write through is not selected - this follows what WfWg does */
2335         END_PROFILE(SMBwritebraw);
2336         if (!write_through && total_written==tcount) {
2337
2338 #if RABBIT_PELLET_FIX
2339                 /*
2340                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2341                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2342                  */
2343                 if (!send_keepalive(smbd_server_fd()))
2344                         exit_server("reply_writebraw: send of keepalive failed");
2345 #endif
2346                 return(-1);
2347         }
2348
2349         return(outsize);
2350 }
2351
2352 /****************************************************************************
2353  Reply to a writeunlock (core+).
2354 ****************************************************************************/
2355
2356 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
2357                       int size, int dum_buffsize)
2358 {
2359         ssize_t nwritten = -1;
2360         size_t numtowrite;
2361         SMB_OFF_T startpos;
2362         char *data;
2363         NTSTATUS status = NT_STATUS_OK;
2364         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2365         int outsize = 0;
2366         START_PROFILE(SMBwriteunlock);
2367         
2368         CHECK_FSP(fsp,conn);
2369         CHECK_WRITE(fsp);
2370
2371         numtowrite = SVAL(inbuf,smb_vwv1);
2372         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2373         data = smb_buf(inbuf) + 3;
2374   
2375         if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, 
2376                       WRITE_LOCK,False)) {
2377                 END_PROFILE(SMBwriteunlock);
2378                 return ERROR_DOS(ERRDOS,ERRlock);
2379         }
2380
2381         /* The special X/Open SMB protocol handling of
2382            zero length writes is *NOT* done for
2383            this call */
2384         if(numtowrite == 0)
2385                 nwritten = 0;
2386         else
2387                 nwritten = write_file(fsp,data,startpos,numtowrite);
2388   
2389         if (lp_syncalways(SNUM(conn)))
2390                 sync_file(conn,fsp);
2391
2392         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2393                 END_PROFILE(SMBwriteunlock);
2394                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2395         }
2396
2397         if (numtowrite) {
2398                 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite, 
2399                                    (SMB_BIG_UINT)startpos);
2400                 if (NT_STATUS_V(status)) {
2401                         END_PROFILE(SMBwriteunlock);
2402                         return ERROR_NT(status);
2403                 }
2404         }
2405         
2406         outsize = set_message(outbuf,1,0,True);
2407         
2408         SSVAL(outbuf,smb_vwv0,nwritten);
2409         
2410         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2411                  fsp->fnum, (int)numtowrite, (int)nwritten));
2412         
2413         END_PROFILE(SMBwriteunlock);
2414         return outsize;
2415 }
2416
2417 /****************************************************************************
2418  Reply to a write.
2419 ****************************************************************************/
2420
2421 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2422 {
2423         size_t numtowrite;
2424         ssize_t nwritten = -1;
2425         SMB_OFF_T startpos;
2426         char *data;
2427         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2428         int outsize = 0;
2429         START_PROFILE(SMBwrite);
2430
2431         /* If it's an IPC, pass off the pipe handler. */
2432         if (IS_IPC(conn)) {
2433                 END_PROFILE(SMBwrite);
2434                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2435         }
2436
2437         CHECK_FSP(fsp,conn);
2438         CHECK_WRITE(fsp);
2439
2440         numtowrite = SVAL(inbuf,smb_vwv1);
2441         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2442         data = smb_buf(inbuf) + 3;
2443   
2444         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2445                 END_PROFILE(SMBwrite);
2446                 return ERROR_DOS(ERRDOS,ERRlock);
2447         }
2448
2449         /*
2450          * X/Open SMB protocol says that if smb_vwv1 is
2451          * zero then the file size should be extended or
2452          * truncated to the size given in smb_vwv[2-3].
2453          */
2454
2455         if(numtowrite == 0) {
2456                 /*
2457                  * This is actually an allocate call, and set EOF. JRA.
2458                  */
2459                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2460                 if (nwritten < 0) {
2461                         END_PROFILE(SMBwrite);
2462                         return ERROR_NT(NT_STATUS_DISK_FULL);
2463                 }
2464                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2465                 if (nwritten < 0) {
2466                         END_PROFILE(SMBwrite);
2467                         return ERROR_NT(NT_STATUS_DISK_FULL);
2468                 }
2469         } else
2470                 nwritten = write_file(fsp,data,startpos,numtowrite);
2471   
2472         if (lp_syncalways(SNUM(conn)))
2473                 sync_file(conn,fsp);
2474
2475         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2476                 END_PROFILE(SMBwrite);
2477                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2478         }
2479
2480         outsize = set_message(outbuf,1,0,True);
2481   
2482         SSVAL(outbuf,smb_vwv0,nwritten);
2483
2484         if (nwritten < (ssize_t)numtowrite) {
2485                 SCVAL(outbuf,smb_rcls,ERRHRD);
2486                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2487         }
2488   
2489         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2490
2491         END_PROFILE(SMBwrite);
2492         return(outsize);
2493 }
2494
2495 /****************************************************************************
2496  Reply to a write and X.
2497 ****************************************************************************/
2498
2499 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2500 {
2501         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2502         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2503         size_t numtowrite = SVAL(inbuf,smb_vwv10);
2504         BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2505         ssize_t nwritten = -1;
2506         unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2507         unsigned int smblen = smb_len(inbuf);
2508         char *data;
2509         BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2510         START_PROFILE(SMBwriteX);
2511
2512         /* If it's an IPC, pass off the pipe handler. */
2513         if (IS_IPC(conn)) {
2514                 END_PROFILE(SMBwriteX);
2515                 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2516         }
2517
2518         CHECK_FSP(fsp,conn);
2519         CHECK_WRITE(fsp);
2520
2521         /* Deal with possible LARGE_WRITEX */
2522         if (large_writeX)
2523                 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2524
2525         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2526                 END_PROFILE(SMBwriteX);
2527                 return ERROR_DOS(ERRDOS,ERRbadmem);
2528         }
2529
2530         data = smb_base(inbuf) + smb_doff;
2531
2532         if(CVAL(inbuf,smb_wct) == 14) {
2533 #ifdef LARGE_SMB_OFF_T
2534                 /*
2535                  * This is a large offset (64 bit) write.
2536                  */
2537                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2538
2539 #else /* !LARGE_SMB_OFF_T */
2540
2541                 /*
2542                  * Ensure we haven't been sent a >32 bit offset.
2543                  */
2544
2545                 if(IVAL(inbuf,smb_vwv12) != 0) {
2546                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2547 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2548                         END_PROFILE(SMBwriteX);
2549                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2550                 }
2551
2552 #endif /* LARGE_SMB_OFF_T */
2553         }
2554
2555         if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2556                 END_PROFILE(SMBwriteX);
2557                 return ERROR_DOS(ERRDOS,ERRlock);
2558         }
2559
2560         /* X/Open SMB protocol says that, unlike SMBwrite
2561         if the length is zero then NO truncation is
2562         done, just a write of zero. To truncate a file,
2563         use SMBwrite. */
2564
2565         if(numtowrite == 0)
2566                 nwritten = 0;
2567         else
2568                 nwritten = write_file(fsp,data,startpos,numtowrite);
2569   
2570         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2571                 END_PROFILE(SMBwriteX);
2572                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2573         }
2574
2575         set_message(outbuf,6,0,True);
2576   
2577         SSVAL(outbuf,smb_vwv2,nwritten);
2578         if (large_writeX)
2579                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2580
2581         if (nwritten < (ssize_t)numtowrite) {
2582                 SCVAL(outbuf,smb_rcls,ERRHRD);
2583                 SSVAL(outbuf,smb_err,ERRdiskfull);      
2584         }
2585
2586         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2587                 fsp->fnum, (int)numtowrite, (int)nwritten));
2588
2589         if (lp_syncalways(SNUM(conn)) || write_through)
2590                 sync_file(conn,fsp);
2591
2592         END_PROFILE(SMBwriteX);
2593         return chain_reply(inbuf,outbuf,length,bufsize);
2594 }
2595
2596 /****************************************************************************
2597  Reply to a lseek.
2598 ****************************************************************************/
2599
2600 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2601 {
2602         SMB_OFF_T startpos;
2603         SMB_OFF_T res= -1;
2604         int mode,umode;
2605         int outsize = 0;
2606         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2607         START_PROFILE(SMBlseek);
2608
2609         CHECK_FSP(fsp,conn);
2610
2611         flush_write_cache(fsp, SEEK_FLUSH);
2612
2613         mode = SVAL(inbuf,smb_vwv1) & 3;
2614         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2615         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2616
2617         switch (mode) {
2618                 case 0:
2619                         umode = SEEK_SET;
2620                         res = startpos;
2621                         break;
2622                 case 1:
2623                         umode = SEEK_CUR;
2624                         res = fsp->pos + startpos;
2625                         break;
2626                 case 2:
2627                         umode = SEEK_END;
2628                         break;
2629                 default:
2630                         umode = SEEK_SET;
2631                         res = startpos;
2632                         break;
2633         }
2634
2635         if (umode == SEEK_END) {
2636                 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2637                         if(errno == EINVAL) {
2638                                 SMB_OFF_T current_pos = startpos;
2639                                 SMB_STRUCT_STAT sbuf;
2640
2641                                 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2642                                         END_PROFILE(SMBlseek);
2643                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2644                                 }
2645
2646                                 current_pos += sbuf.st_size;
2647                                 if(current_pos < 0)
2648                                         res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2649                         }
2650                 }
2651
2652                 if(res == -1) {
2653                         END_PROFILE(SMBlseek);
2654                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2655                 }
2656         }
2657
2658         fsp->pos = res;
2659   
2660         outsize = set_message(outbuf,2,0,True);
2661         SIVAL(outbuf,smb_vwv0,res);
2662   
2663         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2664                 fsp->fnum, (double)startpos, (double)res, mode));
2665
2666         END_PROFILE(SMBlseek);
2667         return(outsize);
2668 }
2669
2670 /****************************************************************************
2671  Reply to a flush.
2672 ****************************************************************************/
2673
2674 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2675 {
2676         int outsize = set_message(outbuf,0,0,True);
2677         uint16 fnum = SVAL(inbuf,smb_vwv0);
2678         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2679         START_PROFILE(SMBflush);
2680
2681         if (fnum != 0xFFFF)
2682                 CHECK_FSP(fsp,conn);
2683         
2684         if (!fsp) {
2685                 file_sync_all(conn);
2686         } else {
2687                 sync_file(conn,fsp);
2688         }
2689         
2690         DEBUG(3,("flush\n"));
2691         END_PROFILE(SMBflush);
2692         return(outsize);
2693 }
2694
2695 /****************************************************************************
2696  Reply to a exit.
2697 ****************************************************************************/
2698
2699 int reply_exit(connection_struct *conn, 
2700                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2701 {
2702         int outsize;
2703         START_PROFILE(SMBexit);
2704
2705         file_close_pid(SVAL(inbuf,smb_pid));
2706
2707         outsize = set_message(outbuf,0,0,True);
2708
2709         DEBUG(3,("exit\n"));
2710
2711         END_PROFILE(SMBexit);
2712         return(outsize);
2713 }
2714
2715 /****************************************************************************
2716  Reply to a close - has to deal with closing a directory opened by NT SMB's.
2717 ****************************************************************************/
2718
2719 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2720                 int dum_buffsize)
2721 {
2722         extern struct current_user current_user;
2723         int outsize = 0;
2724         time_t mtime;
2725         int32 eclass = 0, err = 0;
2726         files_struct *fsp = NULL;
2727         START_PROFILE(SMBclose);
2728
2729         outsize = set_message(outbuf,0,0,True);
2730
2731         /* If it's an IPC, pass off to the pipe handler. */
2732         if (IS_IPC(conn)) {
2733                 END_PROFILE(SMBclose);
2734                 return reply_pipe_close(conn, inbuf,outbuf);
2735         }
2736
2737         fsp = file_fsp(inbuf,smb_vwv0);
2738
2739         /*
2740          * We can only use CHECK_FSP if we know it's not a directory.
2741          */
2742
2743         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2744                 END_PROFILE(SMBclose);
2745                 return ERROR_DOS(ERRDOS,ERRbadfid);
2746         }
2747
2748         if(fsp->is_directory) {
2749                 /*
2750                  * Special case - close NT SMB directory handle.
2751                  */
2752                 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2753                 close_file(fsp,True);
2754         } else {
2755                 /*
2756                  * Close ordinary file.
2757                  */
2758                 int close_err;
2759                 pstring file_name;
2760
2761                 /* Save the name for time set in close. */
2762                 pstrcpy( file_name, fsp->fsp_name);
2763
2764                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2765                          fsp->fd, fsp->fnum,
2766                          conn->num_files_open));
2767  
2768                 /*
2769                  * close_file() returns the unix errno if an error
2770                  * was detected on close - normally this is due to
2771                  * a disk full error. If not then it was probably an I/O error.
2772                  */
2773  
2774                 if((close_err = close_file(fsp,True)) != 0) {
2775                         errno = close_err;
2776                         END_PROFILE(SMBclose);
2777                         return (UNIXERROR(ERRHRD,ERRgeneral));
2778                 }
2779
2780                 /*
2781                  * Now take care of any time sent in the close.
2782                  */
2783
2784                 mtime = make_unix_date3(inbuf+smb_vwv1);
2785                 
2786                 /* try and set the date */
2787                 set_filetime(conn, file_name, mtime);
2788
2789         }  
2790
2791         /* We have a cached error */
2792         if(eclass || err) {
2793                 END_PROFILE(SMBclose);
2794                 return ERROR_DOS(eclass,err);
2795         }
2796
2797         END_PROFILE(SMBclose);
2798         return(outsize);
2799 }
2800
2801 /****************************************************************************
2802  Reply to a writeclose (Core+ protocol).
2803 ****************************************************************************/
2804
2805 int reply_writeclose(connection_struct *conn,
2806                      char *inbuf,char *outbuf, int size, int dum_buffsize)
2807 {
2808         size_t numtowrite;
2809         ssize_t nwritten = -1;
2810         int outsize = 0;
2811         int close_err = 0;
2812         SMB_OFF_T startpos;
2813         char *data;
2814         time_t mtime;
2815         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2816         START_PROFILE(SMBwriteclose);
2817
2818         CHECK_FSP(fsp,conn);
2819         CHECK_WRITE(fsp);
2820
2821         numtowrite = SVAL(inbuf,smb_vwv1);
2822         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2823         mtime = make_unix_date3(inbuf+smb_vwv4);
2824         data = smb_buf(inbuf) + 1;
2825   
2826         if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2827                 END_PROFILE(SMBwriteclose);
2828                 return ERROR_DOS(ERRDOS,ERRlock);
2829         }
2830   
2831         nwritten = write_file(fsp,data,startpos,numtowrite);
2832
2833         set_filetime(conn, fsp->fsp_name,mtime);
2834   
2835         /*
2836          * More insanity. W2K only closes the file if writelen > 0.
2837          * JRA.
2838          */
2839
2840         if (numtowrite) {
2841                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2842                         fsp->fsp_name ));
2843                 close_err = close_file(fsp,True);
2844         }
2845
2846         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2847                  fsp->fnum, (int)numtowrite, (int)nwritten,
2848                  conn->num_files_open));
2849   
2850         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2851                 END_PROFILE(SMBwriteclose);
2852                 return(UNIXERROR(ERRHRD,ERRdiskfull));
2853         }
2854  
2855         if(close_err != 0) {
2856                 errno = close_err;
2857                 END_PROFILE(SMBwriteclose);
2858                 return(UNIXERROR(ERRHRD,ERRgeneral));
2859         }
2860  
2861         outsize = set_message(outbuf,1,0,True);
2862   
2863         SSVAL(outbuf,smb_vwv0,nwritten);
2864         END_PROFILE(SMBwriteclose);
2865         return(outsize);
2866 }
2867
2868 /****************************************************************************
2869  Reply to a lock.
2870 ****************************************************************************/
2871
2872 int reply_lock(connection_struct *conn,
2873                char *inbuf,char *outbuf, int length, int dum_buffsize)
2874 {
2875         int outsize = set_message(outbuf,0,0,True);
2876         SMB_BIG_UINT count,offset;
2877         NTSTATUS status;
2878         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2879         BOOL my_lock_ctx = False;
2880
2881         START_PROFILE(SMBlock);
2882
2883         CHECK_FSP(fsp,conn);
2884
2885         release_level_2_oplocks_on_change(fsp);
2886
2887         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2888         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2889
2890         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2891                  fsp->fd, fsp->fnum, (double)offset, (double)count));
2892
2893         status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2894         if (NT_STATUS_V(status)) {
2895 #if 0
2896                 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2897                 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2898                         /*
2899                          * A blocking lock was requested. Package up
2900                          * this smb into a queued request and push it
2901                          * onto the blocking lock queue.
2902                          */
2903                         if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2904                                 END_PROFILE(SMBlock);
2905                                 return -1;
2906                         }
2907                 }
2908 #endif
2909                 END_PROFILE(SMBlock);
2910                 return ERROR_NT(status);
2911         }
2912
2913         END_PROFILE(SMBlock);
2914         return(outsize);
2915 }
2916
2917 /****************************************************************************
2918  Reply to a unlock.
2919 ****************************************************************************/
2920
2921 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
2922                  int dum_buffsize)
2923 {
2924         int outsize = set_message(outbuf,0,0,True);
2925         SMB_BIG_UINT count,offset;
2926         NTSTATUS status;
2927         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2928         START_PROFILE(SMBunlock);
2929
2930         CHECK_FSP(fsp,conn);
2931         
2932         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2933         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2934         
2935         status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2936         if (NT_STATUS_V(status)) {
2937                 END_PROFILE(SMBunlock);
2938                 return ERROR_NT(status);
2939         }
2940
2941         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2942                     fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2943         
2944         END_PROFILE(SMBunlock);
2945         return(outsize);
2946 }
2947
2948 /****************************************************************************
2949  Reply to a tdis.
2950 ****************************************************************************/
2951
2952 int reply_tdis(connection_struct *conn, 
2953                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2954 {
2955         int outsize = set_message(outbuf,0,0,True);
2956         uint16 vuid;
2957         START_PROFILE(SMBtdis);
2958
2959         vuid = SVAL(inbuf,smb_uid);
2960
2961         if (!conn) {
2962                 DEBUG(4,("Invalid connection in tdis\n"));
2963                 END_PROFILE(SMBtdis);
2964                 return ERROR_DOS(ERRSRV,ERRinvnid);
2965         }
2966
2967         conn->used = False;
2968
2969         close_cnum(conn,vuid);
2970   
2971         END_PROFILE(SMBtdis);
2972         return outsize;
2973 }
2974
2975 /****************************************************************************
2976  Reply to a echo.
2977 ****************************************************************************/
2978
2979 int reply_echo(connection_struct *conn,
2980                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2981 {
2982         int smb_reverb = SVAL(inbuf,smb_vwv0);
2983         int seq_num;
2984         unsigned int data_len = smb_buflen(inbuf);
2985         int outsize = set_message(outbuf,1,data_len,True);
2986         START_PROFILE(SMBecho);
2987
2988         if (data_len > BUFFER_SIZE) {
2989                 DEBUG(0,("reply_echo: data_len too large.\n"));
2990                 END_PROFILE(SMBecho);
2991                 return -1;
2992         }
2993
2994         /* copy any incoming data back out */
2995         if (data_len > 0)
2996                 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2997
2998         if (smb_reverb > 100) {
2999                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3000                 smb_reverb = 100;
3001         }
3002
3003         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3004                 SSVAL(outbuf,smb_vwv0,seq_num);
3005
3006                 smb_setlen(outbuf,outsize - 4);
3007
3008                 if (!send_smb(smbd_server_fd(),outbuf))
3009                         exit_server("reply_echo: send_smb failed.");
3010         }
3011
3012         DEBUG(3,("echo %d times\n", smb_reverb));
3013
3014         smb_echo_count++;
3015
3016         END_PROFILE(SMBecho);
3017         return -1;
3018 }
3019
3020 /****************************************************************************
3021  Reply to a printopen.
3022 ****************************************************************************/
3023
3024 int reply_printopen(connection_struct *conn, 
3025                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3026 {
3027         int outsize = 0;
3028         files_struct *fsp;
3029         START_PROFILE(SMBsplopen);
3030         
3031         if (!CAN_PRINT(conn)) {
3032                 END_PROFILE(SMBsplopen);
3033                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3034         }
3035
3036         /* Open for exclusive use, write only. */
3037         fsp = print_fsp_open(conn, NULL);
3038
3039         if (!fsp) {
3040                 END_PROFILE(SMBsplopen);
3041                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3042         }
3043
3044         outsize = set_message(outbuf,1,0,True);
3045         SSVAL(outbuf,smb_vwv0,fsp->fnum);
3046   
3047         DEBUG(3,("openprint fd=%d fnum=%d\n",
3048                  fsp->fd, fsp->fnum));
3049
3050         END_PROFILE(SMBsplopen);
3051         return(outsize);
3052 }
3053
3054 /****************************************************************************
3055  Reply to a printclose.
3056 ****************************************************************************/
3057
3058 int reply_printclose(connection_struct *conn,
3059                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3060 {
3061         int outsize = set_message(outbuf,0,0,True);
3062         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3063         int close_err = 0;
3064         START_PROFILE(SMBsplclose);
3065
3066         CHECK_FSP(fsp,conn);
3067
3068         if (!CAN_PRINT(conn)) {
3069                 END_PROFILE(SMBsplclose);
3070                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3071         }
3072   
3073         DEBUG(3,("printclose fd=%d fnum=%d\n",
3074                  fsp->fd,fsp->fnum));
3075   
3076         close_err = close_file(fsp,True);
3077
3078         if(close_err != 0) {
3079                 errno = close_err;
3080                 END_PROFILE(SMBsplclose);
3081                 return(UNIXERROR(ERRHRD,ERRgeneral));
3082         }
3083
3084         END_PROFILE(SMBsplclose);
3085         return(outsize);
3086 }
3087
3088 /****************************************************************************
3089  Reply to a printqueue.
3090 ****************************************************************************/
3091
3092 int reply_printqueue(connection_struct *conn,
3093                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3094 {
3095         int outsize = set_message(outbuf,2,3,True);
3096         int max_count = SVAL(inbuf,smb_vwv0);
3097         int start_index = SVAL(inbuf,smb_vwv1);
3098         START_PROFILE(SMBsplretq);
3099
3100         /* we used to allow the client to get the cnum wrong, but that
3101            is really quite gross and only worked when there was only
3102            one printer - I think we should now only accept it if they
3103            get it right (tridge) */
3104         if (!CAN_PRINT(conn)) {
3105                 END_PROFILE(SMBsplretq);
3106                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3107         }
3108
3109         SSVAL(outbuf,smb_vwv0,0);
3110         SSVAL(outbuf,smb_vwv1,0);
3111         SCVAL(smb_buf(outbuf),0,1);
3112         SSVAL(smb_buf(outbuf),1,0);
3113   
3114         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3115                  start_index, max_count));
3116
3117         {
3118                 print_queue_struct *queue = NULL;
3119                 print_status_struct status;
3120                 char *p = smb_buf(outbuf) + 3;
3121                 int count = print_queue_status(SNUM(conn), &queue, &status);
3122                 int num_to_get = ABS(max_count);
3123                 int first = (max_count>0?start_index:start_index+max_count+1);
3124                 int i;
3125
3126                 if (first >= count)
3127                         num_to_get = 0;
3128                 else
3129                         num_to_get = MIN(num_to_get,count-first);
3130     
3131
3132                 for (i=first;i<first+num_to_get;i++) {
3133                         put_dos_date2(p,0,queue[i].time);
3134                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3135                         SSVAL(p,5, queue[i].job);
3136                         SIVAL(p,7,queue[i].size);
3137                         SCVAL(p,11,0);
3138                         srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3139                         p += 28;
3140                 }
3141
3142                 if (count > 0) {
3143                         outsize = set_message(outbuf,2,28*count+3,False); 
3144                         SSVAL(outbuf,smb_vwv0,count);
3145                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3146                         SCVAL(smb_buf(outbuf),0,1);
3147                         SSVAL(smb_buf(outbuf),1,28*count);
3148                 }
3149
3150                 SAFE_FREE(queue);
3151           
3152                 DEBUG(3,("%d entries returned in queue\n",count));
3153         }
3154   
3155         END_PROFILE(SMBsplretq);
3156         return(outsize);
3157 }
3158
3159 /****************************************************************************
3160  Reply to a printwrite.
3161 ****************************************************************************/
3162
3163 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3164 {
3165         int numtowrite;
3166         int outsize = set_message(outbuf,0,0,True);
3167         char *data;
3168         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3169
3170         START_PROFILE(SMBsplwr);
3171   
3172         if (!CAN_PRINT(conn)) {
3173                 END_PROFILE(SMBsplwr);
3174                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3175         }
3176
3177         CHECK_FSP(fsp,conn);
3178         CHECK_WRITE(fsp);
3179
3180         numtowrite = SVAL(smb_buf(inbuf),1);
3181         data = smb_buf(inbuf) + 3;
3182   
3183         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3184                 END_PROFILE(SMBsplwr);
3185                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3186         }
3187
3188         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3189   
3190         END_PROFILE(SMBsplwr);
3191         return(outsize);
3192 }
3193
3194 /****************************************************************************
3195  The guts of the mkdir command, split out so it may be called by the NT SMB
3196  code. 
3197 ****************************************************************************/
3198
3199 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3200 {
3201         BOOL bad_path = False;
3202         SMB_STRUCT_STAT sbuf;
3203         int ret= -1;
3204         
3205         unix_convert(directory,conn,0,&bad_path,&sbuf);
3206
3207         if( strchr_m(directory, ':')) {
3208                 return NT_STATUS_NOT_A_DIRECTORY;
3209         }
3210
3211         if (ms_has_wild(directory)) {
3212                 return NT_STATUS_OBJECT_NAME_INVALID;
3213         }
3214
3215         if (bad_path) {
3216                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3217         }
3218
3219         if (check_name(directory, conn))
3220                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
3221         
3222         if (ret == -1) {
3223                 if(errno == ENOENT) {
3224                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3225                 }
3226                 return map_nt_error_from_unix(errno);
3227         }
3228         
3229         return NT_STATUS_OK;
3230 }
3231
3232 /****************************************************************************
3233  Reply to a mkdir.
3234 ****************************************************************************/
3235
3236 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3237 {
3238         pstring directory;
3239         int outsize;
3240         NTSTATUS status;
3241         START_PROFILE(SMBmkdir);
3242  
3243         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3244         if (!NT_STATUS_IS_OK(status)) {
3245                 END_PROFILE(SMBmkdir);
3246                 return ERROR_NT(status);
3247         }
3248
3249         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3250
3251         status = mkdir_internal(conn, directory);
3252         if (!NT_STATUS_IS_OK(status)) {
3253                 END_PROFILE(SMBmkdir);
3254                 return ERROR_NT(status);
3255         }
3256
3257         outsize = set_message(outbuf,0,0,True);
3258
3259         DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3260
3261         END_PROFILE(SMBmkdir);
3262         return(outsize);
3263 }
3264
3265 /****************************************************************************
3266  Static function used by reply_rmdir to delete an entire directory
3267  tree recursively. Return False on ok, True on fail.
3268 ****************************************************************************/
3269
3270 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3271 {
3272         const char *dname = NULL;
3273         BOOL ret = False;
3274         void *dirptr = OpenDir(conn, directory, False);
3275
3276         if(dirptr == NULL)
3277                 return True;
3278
3279         while((dname = ReadDirName(dirptr))) {
3280                 pstring fullname;
3281                 SMB_STRUCT_STAT st;
3282
3283                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3284                         continue;
3285
3286                 /* Construct the full name. */
3287                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3288                         errno = ENOMEM;
3289                         ret = True;
3290                         break;
3291                 }
3292
3293                 pstrcpy(fullname, directory);
3294                 pstrcat(fullname, "/");
3295                 pstrcat(fullname, dname);
3296
3297                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3298                         ret = True;
3299                         break;
3300                 }
3301
3302                 if(st.st_mode & S_IFDIR) {
3303                         if(recursive_rmdir(conn, fullname)!=0) {
3304                                 ret = True;
3305                                 break;
3306                         }
3307                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3308                                 ret = True;
3309                                 break;
3310                         }
3311                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3312                         ret = True;
3313                         break;
3314                 }
3315         }
3316         CloseDir(dirptr);
3317         return ret;
3318 }
3319
3320 /****************************************************************************
3321  The internals of the rmdir code - called elsewhere.
3322 ****************************************************************************/
3323
3324 BOOL rmdir_internals(connection_struct *conn, char *directory)
3325 {
3326         BOOL ok;
3327
3328         ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3329         if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3330                 /* 
3331                  * Check to see if the only thing in this directory are
3332                  * vetoed files/directories. If so then delete them and
3333                  * retry. If we fail to delete any of them (and we *don't*
3334                  * do a recursive delete) then fail the rmdir.
3335                  */
3336                 BOOL all_veto_files = True;
3337                 const char *dname;
3338                 void *dirptr = OpenDir(conn, directory, False);
3339
3340                 if(dirptr != NULL) {
3341                         int dirpos = TellDir(dirptr);
3342                         while ((dname = ReadDirName(dirptr))) {
3343                                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3344                                         continue;
3345                                 if(!IS_VETO_PATH(conn, dname)) {
3346                                         all_veto_files = False;
3347                                         break;
3348                                 }
3349                         }
3350
3351                         if(all_veto_files) {
3352                                 SeekDir(dirptr,dirpos);
3353                                 while ((dname = ReadDirName(dirptr))) {
3354                                         pstring fullname;
3355                                         SMB_STRUCT_STAT st;
3356
3357                                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3358                                                 continue;
3359
3360                                         /* Construct the full name. */
3361                                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3362                                                 errno = ENOMEM;
3363                                                 break;
3364                                         }
3365
3366                                         pstrcpy(fullname, directory);
3367                                         pstrcat(fullname, "/");
3368                                         pstrcat(fullname, dname);
3369                      
3370                                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3371                                                 break;
3372                                         if(st.st_mode & S_IFDIR) {
3373                                                 if(lp_recursive_veto_delete(SNUM(conn))) {
3374                                                         if(recursive_rmdir(conn, fullname) != 0)
3375                                                                 break;
3376                                                 }
3377                                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3378                                                         break;
3379                                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3380                                                 break;
3381                                 }
3382                                 CloseDir(dirptr);
3383                                 /* Retry the rmdir */
3384                                 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3385                         } else {
3386                                 CloseDir(dirptr);
3387                         }
3388                 } else {
3389                         errno = ENOTEMPTY;
3390                 }
3391         }
3392
3393         if (!ok)
3394                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3395
3396         return ok;
3397 }
3398
3399 /****************************************************************************
3400  Reply to a rmdir.
3401 ****************************************************************************/
3402
3403 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3404 {
3405         pstring directory;
3406         int outsize = 0;
3407         BOOL ok = False;
3408         BOOL bad_path = False;
3409         SMB_STRUCT_STAT sbuf;
3410         NTSTATUS status;
3411         START_PROFILE(SMBrmdir);
3412
3413         srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3414         if (!NT_STATUS_IS_OK(status)) {
3415                 END_PROFILE(SMBrmdir);
3416                 return ERROR_NT(status);
3417         }
3418
3419         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3420
3421         unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3422         if (bad_path) {
3423                 END_PROFILE(SMBrmdir);
3424                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3425         }
3426   
3427         if (check_name(directory,conn)) {
3428                 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3429                 ok = rmdir_internals(conn, directory);
3430         }
3431   
3432         if (!ok) {
3433                 END_PROFILE(SMBrmdir);
3434                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3435         }
3436  
3437         outsize = set_message(outbuf,0,0,True);
3438   
3439         DEBUG( 3, ( "rmdir %s\n", directory ) );
3440   
3441         END_PROFILE(SMBrmdir);
3442         return(outsize);
3443 }
3444
3445 /*******************************************************************
3446  Resolve wildcards in a filename rename.
3447  Note that name is in UNIX charset and thus potentially can be more
3448  than fstring buffer (255 bytes) especially in default UTF-8 case.
3449  Therefore, we use pstring inside and all calls should ensure that
3450  name2 is at least pstring-long (they do already)
3451 ********************************************************************/
3452
3453 static BOOL resolve_wildcards(const char *name1, char *name2)
3454 {
3455         pstring root1,root2;
3456         pstring ext1,ext2;
3457         char *p,*p2, *pname1, *pname2;
3458         int available_space, actual_space;
3459         
3460
3461         pname1 = strrchr_m(name1,'/');
3462         pname2 = strrchr_m(name2,'/');
3463
3464         if (!pname1 || !pname2)
3465                 return(False);
3466   
3467         pstrcpy(root1,pname1);
3468         pstrcpy(root2,pname2);
3469         p = strrchr_m(root1,'.');
3470         if (p) {
3471                 *p = 0;
3472                 pstrcpy(ext1,p+1);
3473         } else {
3474                 pstrcpy(ext1,"");    
3475         }
3476         p = strrchr_m(root2,'.');
3477         if (p) {
3478                 *p = 0;
3479                 pstrcpy(ext2,p+1);
3480         } else {
3481                 pstrcpy(ext2,"");    
3482         }
3483
3484         p = root1;
3485         p2 = root2;
3486         while (*p2) {
3487                 if (*p2 == '?') {
3488                         *p2 = *p;
3489                         p2++;
3490                 } else if (*p2 == '*') {
3491                         pstrcpy(p2, p);
3492                         break;
3493                 } else {
3494                         p2++;
3495                 }
3496                 if (*p)
3497                         p++;
3498         }
3499
3500         p = ext1;
3501         p2 = ext2;
3502         while (*p2) {
3503                 if (*p2 == '?') {
3504                         *p2 = *p;
3505                         p2++;
3506                 } else if (*p2 == '*') {
3507                         pstrcpy(p2, p);
3508                         break;
3509                 } else {
3510                         p2++;
3511                 }
3512                 if (*p)
3513                         p++;
3514         }
3515
3516         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3517         
3518         if (ext2[0]) {
3519                 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3520                 if (actual_space >= available_space - 1) {
3521                         DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3522                                 actual_space - available_space));
3523                 }
3524         } else {
3525                 pstrcpy_base(pname2, root2, name2);
3526         }
3527
3528         return(True);
3529 }
3530
3531 /****************************************************************************
3532  Ensure open files have their names updates.
3533 ****************************************************************************/
3534
3535 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3536 {
3537         files_struct *fsp;
3538         BOOL did_rename = False;
3539
3540         for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3541                 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3542                         fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3543                         fsp->fsp_name, newname ));
3544                 string_set(&fsp->fsp_name, newname);
3545                 did_rename = True;
3546         }
3547
3548         if (!did_rename)
3549                 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3550                         (unsigned int)dev, (double)inode, newname ));
3551 }
3552
3553 /****************************************************************************
3554  Rename an open file - given an fsp.
3555 ****************************************************************************/
3556
3557 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3558 {
3559         SMB_STRUCT_STAT sbuf;
3560         BOOL bad_path = False;
3561         pstring newname_last_component;
3562         NTSTATUS error = NT_STATUS_OK;
3563         BOOL dest_exists;
3564         BOOL rcdest = True;
3565
3566         ZERO_STRUCT(sbuf);
3567         rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3568
3569         /* Quick check for "." and ".." */
3570         if (!bad_path && newname_last_component[0] == '.') {
3571                 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3572                         return NT_STATUS_ACCESS_DENIED;
3573                 }
3574         }
3575         if (!rcdest && bad_path) {
3576                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3577         }
3578
3579         /* Ensure newname contains a '/' */
3580         if(strrchr_m(newname,'/') == 0) {
3581                 pstring tmpstr;
3582                 
3583                 pstrcpy(tmpstr, "./");
3584                 pstrcat(tmpstr, newname);
3585                 pstrcpy(newname, tmpstr);
3586         }
3587
3588         /*
3589          * Check for special case with case preserving and not
3590          * case sensitive. If the old last component differs from the original
3591          * last component only by case, then we should allow
3592          * the rename (user is trying to change the case of the
3593          * filename).
3594          */
3595
3596         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3597                         strequal(newname, fsp->fsp_name)) {
3598                 char *p;
3599                 pstring newname_modified_last_component;
3600
3601                 /*
3602                  * Get the last component of the modified name.
3603                  * Note that we guarantee that newname contains a '/'
3604                  * character above.
3605                  */
3606                 p = strrchr_m(newname,'/');
3607                 pstrcpy(newname_modified_last_component,p+1);
3608                         
3609                 if(strcsequal(newname_modified_last_component, 
3610                               newname_last_component) == False) {
3611                         /*
3612                          * Replace the modified last component with
3613                          * the original.
3614                          */
3615                         pstrcpy(p+1, newname_last_component);
3616                 }
3617         }
3618
3619         /*
3620          * If the src and dest names are identical - including case,
3621          * don't do the rename, just return success.
3622          */
3623
3624         if (strcsequal(fsp->fsp_name, newname)) {
3625                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3626                         newname));
3627                 return NT_STATUS_OK;
3628         }
3629
3630         dest_exists = vfs_object_exist(conn,newname,NULL);
3631
3632         if(!replace_if_exists && dest_exists) {
3633                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3634                         fsp->fsp_name,newname));
3635                 return NT_STATUS_OBJECT_NAME_COLLISION;
3636         }
3637
3638         error = can_rename(newname,conn,attrs,&sbuf);
3639
3640         if (dest_exists && !NT_STATUS_IS_OK(error)) {
3641                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3642                         nt_errstr(error), fsp->fsp_name,newname));
3643                 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3644                         error = NT_STATUS_ACCESS_DENIED;
3645                 return error;
3646         }
3647
3648         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3649                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3650                         fsp->fsp_name,newname));
3651                 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3652                 return NT_STATUS_OK;    
3653         }
3654
3655         if (errno == ENOTDIR || errno == EISDIR)
3656                 error = NT_STATUS_OBJECT_NAME_COLLISION;
3657         else
3658                 error = map_nt_error_from_unix(errno);
3659                 
3660         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3661                 nt_errstr(error), fsp->fsp_name,newname));
3662
3663         return error;
3664 }
3665
3666 /****************************************************************************
3667  The guts of the rename command, split out so it may be called by the NT SMB
3668  code. 
3669 ****************************************************************************/
3670
3671 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3672 {
3673         pstring directory;
3674         pstring mask;
3675         pstring last_component_src;
3676         pstring last_component_dest;
3677         char *p;
3678         BOOL has_wild;
3679         BOOL bad_path_src = False;
3680         BOOL bad_path_dest = False;
3681         int count=0;
3682         NTSTATUS error = NT_STATUS_OK;
3683         BOOL rc = True;
3684         BOOL rcdest = True;
3685         SMB_STRUCT_STAT sbuf1, sbuf2;
3686
3687         *directory = *mask = 0;
3688
3689         ZERO_STRUCT(sbuf1);
3690         ZERO_STRUCT(sbuf2);
3691
3692         rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3693         if (!rc && bad_path_src) {
3694                 if (ms_has_wild(last_component_src))
3695                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3696                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3697         }
3698
3699         /* Quick check for "." and ".." */
3700         if (last_component_src[0] == '.') {
3701                 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3702                         return NT_STATUS_OBJECT_NAME_INVALID;
3703                 }
3704         }
3705
3706         rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3707
3708         /* Quick check for "." and ".." */
3709         if (last_component_dest[0] == '.') {
3710                 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3711                         return NT_STATUS_OBJECT_NAME_INVALID;
3712                 }
3713         }
3714
3715         /*
3716          * Split the old name into directory and last component
3717          * strings. Note that unix_convert may have stripped off a 
3718          * leading ./ from both name and newname if the rename is 
3719          * at the root of the share. We need to make sure either both
3720          * name and newname contain a / character or neither of them do
3721          * as this is checked in resolve_wildcards().
3722          */
3723
3724         p = strrchr_m(name,'/');
3725         if (!p) {
3726                 pstrcpy(directory,".");
3727                 pstrcpy(mask,name);
3728         } else {
3729                 *p = 0;
3730                 pstrcpy(directory,name);
3731                 pstrcpy(mask,p+1);
3732                 *p = '/'; /* Replace needed for exceptional test below. */
3733         }
3734
3735         /*
3736          * We should only check the mangled cache
3737          * here if unix_convert failed. This means
3738          * that the path in 'mask' doesn't exist
3739          * on the file system and so we need to look
3740          * for a possible mangle. This patch from
3741          * Tine Smukavec <valentin.smukavec@hermes.si>.
3742          */
3743
3744         if (!rc && mangle_is_mangled(mask))
3745                 mangle_check_cache( mask, sizeof(pstring)-1 );
3746
3747         has_wild = ms_has_wild(mask);
3748
3749         if (!has_wild) {
3750                 /*
3751                  * No wildcards - just process the one file.
3752                  */
3753                 BOOL is_short_name = mangle_is_8_3(name, True);
3754
3755                 /* Add a terminating '/' to the directory name. */
3756                 pstrcat(directory,"/");
3757                 pstrcat(directory,mask);
3758                 
3759                 /* Ensure newname contains a '/' also */
3760                 if(strrchr_m(newname,'/') == 0) {
3761                         pstring tmpstr;
3762                         
3763                         pstrcpy(tmpstr, "./");
3764                         pstrcat(tmpstr, newname);
3765                         pstrcpy(newname, tmpstr);
3766                 }
3767                 
3768                 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3769 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n", 
3770                          conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory, 
3771                          newname, last_component_dest, is_short_name));
3772
3773                 /*
3774                  * Check for special case with case preserving and not
3775                  * case sensitive, if directory and newname are identical,
3776                  * and the old last component differs from the original
3777                  * last component only by case, then we should allow
3778                  * the rename (user is trying to change the case of the
3779                  * filename).
3780                  */
3781                 if((conn->case_sensitive == False) && 
3782                    (((conn->case_preserve == True) && 
3783                      (is_short_name == False)) || 
3784                     ((conn->short_case_preserve == True) && 
3785                      (is_short_name == True))) &&
3786                    strcsequal(directory, newname)) {
3787                         pstring modified_last_component;
3788
3789                         /*
3790                          * Get the last component of the modified name.
3791                          * Note that we guarantee that newname contains a '/'
3792                          * character above.
3793                          */
3794                         p = strrchr_m(newname,'/');
3795                         pstrcpy(modified_last_component,p+1);
3796                         
3797                         if(strcsequal(modified_last_component, 
3798                                       last_component_dest) == False) {
3799                                 /*
3800                                  * Replace the modified last component with
3801                                  * the original.
3802                                  */
3803                                 pstrcpy(p+1, last_component_dest);
3804                         }
3805                 }
3806         
3807                 resolve_wildcards(directory,newname);
3808         
3809                 /*
3810                  * The source object must exist.
3811                  */
3812
3813                 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3814                         DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3815                                 directory,newname));
3816
3817                         if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3818                                 /*
3819                                  * Must return different errors depending on whether the parent
3820                                  * directory existed or not.
3821                                  */
3822
3823                                 p = strrchr_m(directory, '/');
3824                                 if (!p)
3825                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3826                                 *p = '\0';
3827                                 if (vfs_object_exist(conn, directory, NULL))
3828                                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3829                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3830                         }
3831                         error = map_nt_error_from_unix(errno);
3832                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3833                                 nt_errstr(error), directory,newname));
3834
3835                         return error;
3836                 }
3837
3838                 if (!rcdest && bad_path_dest) {
3839                         if (ms_has_wild(last_component_dest))
3840                                 return NT_STATUS_OBJECT_NAME_INVALID;
3841                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3842                 }
3843
3844                 error = can_rename(directory,conn,attrs,&sbuf1);
3845
3846                 if (!NT_STATUS_IS_OK(error)) {
3847                         DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3848                                 nt_errstr(error), directory,newname));
3849                         return error;
3850                 }
3851
3852                 /*
3853                  * If the src and dest names are identical - including case,
3854                  * don't do the rename, just return success.
3855                  */
3856
3857                 if (strcsequal(directory, newname)) {
3858                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3859                         DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3860                         return NT_STATUS_OK;
3861                 }
3862
3863                 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3864                         DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3865                                 directory,newname));
3866                         return NT_STATUS_OBJECT_NAME_COLLISION;
3867                 }
3868
3869                 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3870                         DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3871                                 directory,newname));
3872                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3873                         return NT_STATUS_OK;    
3874                 }
3875
3876                 if (errno == ENOTDIR || errno == EISDIR)
3877                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3878                 else
3879                         error = map_nt_error_from_unix(errno);
3880                 
3881                 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3882                         nt_errstr(error), directory,newname));
3883
3884                 return error;
3885         } else {
3886                 /*
3887                  * Wildcards - process each file that matches.
3888                  */
3889                 void *dirptr = NULL;
3890                 const char *dname;
3891                 pstring destname;
3892                 
3893                 if (check_name(directory,conn))
3894                         dirptr = OpenDir(conn, directory, True);
3895                 
3896                 if (dirptr) {
3897                         error = NT_STATUS_NO_SUCH_FILE;
3898 /*                      Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
3899                         
3900                         if (strequal(mask,"????????.???"))
3901                                 pstrcpy(mask,"*");
3902                         
3903                         while ((dname = ReadDirName(dirptr))) {
3904                                 pstring fname;
3905                                 BOOL sysdir_entry = False;
3906
3907                                 pstrcpy(fname,dname);
3908                                 
3909                                 /* Quick check for "." and ".." */
3910                                 if (fname[0] == '.') {
3911                                         if (!fname[1] || (fname[1] == '.' && !fname[2])) {
3912                                                 if (attrs & aDIR) {
3913                                                         sysdir_entry = True;
3914                                                 } else {
3915                                                         continue;
3916                                                 }
3917                                         }
3918                                 }
3919
3920                                 if(!mask_match(fname, mask, conn->case_sensitive))
3921                                         continue;
3922                                 
3923                                 if (sysdir_entry) {
3924                                         error = NT_STATUS_OBJECT_NAME_INVALID;
3925                                         break;
3926                                 }
3927
3928                                 error = NT_STATUS_ACCESS_DENIED;
3929                                 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3930                                 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3931                                         error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3932                                         DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3933                                         continue;
3934                                 }
3935                                 error = can_rename(fname,conn,attrs,&sbuf1);
3936                                 if (!NT_STATUS_IS_OK(error)) {
3937                                         DEBUG(6,("rename %s refused\n", fname));
3938                                         continue;
3939                                 }
3940                                 pstrcpy(destname,newname);
3941                                 
3942                                 if (!resolve_wildcards(fname,destname)) {
3943                                         DEBUG(6,("resolve_wildcards %s %s failed\n", 
3944                                                  fname, destname));
3945                                         continue;
3946                                 }
3947                                 
3948                                 if (strcsequal(fname,destname)) {
3949                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3950                                         DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
3951                                         count++;
3952                                         error = NT_STATUS_OK;
3953                                         continue;
3954                                 }
3955
3956                                 if (!replace_if_exists && 
3957                                     vfs_file_exist(conn,destname, NULL)) {
3958                                         DEBUG(6,("file_exist %s\n", destname));
3959                                         error = NT_STATUS_OBJECT_NAME_COLLISION;
3960                                         continue;
3961                                 }
3962                                 
3963                                 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3964                                         rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3965                                         count++;
3966                                         error = NT_STATUS_OK;
3967                                 }
3968                                 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3969                         }
3970                         CloseDir(dirptr);
3971                 }
3972
3973                 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
3974                         if (!rcdest && bad_path_dest) {
3975                                 if (ms_has_wild(last_component_dest))
3976                                         return NT_STATUS_OBJECT_NAME_INVALID;
3977                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3978                         }
3979                 }
3980         }
3981         
3982         if (count == 0 && NT_STATUS_IS_OK(error)) {
3983                 error = map_nt_error_from_unix(errno);
3984         }
3985         
3986         return error;
3987 }
3988
3989 /****************************************************************************
3990  Reply to a mv.
3991 ****************************************************************************/
3992
3993 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
3994              int dum_buffsize)
3995 {
3996         int outsize = 0;
3997         pstring name;
3998         pstring newname;
3999         char *p;
4000         uint16 attrs = SVAL(inbuf,smb_vwv0);
4001         NTSTATUS status;
4002
4003         START_PROFILE(SMBmv);
4004
4005         p = smb_buf(inbuf) + 1;
4006         p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4007         if (!NT_STATUS_IS_OK(status)) {
4008                 END_PROFILE(SMBmv);
4009                 return ERROR_NT(status);
4010         }
4011         p++;
4012         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4013         if (!NT_STATUS_IS_OK(status)) {
4014                 END_PROFILE(SMBmv);
4015                 return ERROR_NT(status);
4016         }
4017         
4018         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4019         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4020         
4021         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4022         
4023         status = rename_internals(conn, name, newname, attrs, False);
4024         if (!NT_STATUS_IS_OK(status)) {
4025                 END_PROFILE(SMBmv);
4026                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4027                         /* We have re-scheduled this call. */
4028                         clear_cached_errors();
4029                         return -1;
4030                 }
4031                 return ERROR_NT(status);
4032         }
4033
4034         /*
4035          * Win2k needs a changenotify request response before it will
4036          * update after a rename..
4037          */     
4038         process_pending_change_notify_queue((time_t)0);
4039         outsize = set_message(outbuf,0,0,True);
4040   
4041         END_PROFILE(SMBmv);
4042         return(outsize);
4043 }
4044
4045 /*******************************************************************
4046  Copy a file as part of a reply_copy.
4047 ******************************************************************/
4048
4049 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4050                       int count,BOOL target_is_directory, int *err_ret)
4051 {
4052         int Access,action;
4053         SMB_STRUCT_STAT src_sbuf, sbuf2;
4054         SMB_OFF_T ret=-1;
4055         files_struct *fsp1,*fsp2;
4056         pstring dest;
4057         uint32 dosattrs;
4058  
4059         *err_ret = 0;
4060
4061         pstrcpy(dest,dest1);
4062         if (target_is_directory) {
4063                 char *p = strrchr_m(src,'/');
4064                 if (p) 
4065                         p++;
4066                 else
4067                         p = src;
4068                 pstrcat(dest,"/");
4069                 pstrcat(dest,p);
4070         }
4071
4072         if (!vfs_file_exist(conn,src,&src_sbuf))
4073                 return(False);
4074
4075         fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4076                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4077                                         &Access,&action);
4078
4079         if (!fsp1)
4080                 return(False);
4081
4082         if (!target_is_directory && count)
4083                 ofun = FILE_EXISTS_OPEN;
4084
4085         dosattrs = dos_mode(conn, src, &src_sbuf);
4086         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4087                 ZERO_STRUCTP(&sbuf2);
4088
4089         fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4090                         ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4091
4092         if (!fsp2) {
4093                 close_file(fsp1,False);
4094                 return(False);
4095         }
4096
4097         if ((ofun&3) == 1) {
4098                 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4099                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4100                         /*
4101                          * Stop the copy from occurring.
4102                          */
4103                         ret = -1;
4104                         src_sbuf.st_size = 0;
4105                 }
4106         }
4107   
4108         if (src_sbuf.st_size)
4109                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4110
4111         close_file(fsp1,False);
4112
4113         /* Ensure the modtime is set correctly on the destination file. */
4114         fsp2->pending_modtime = src_sbuf.st_mtime;
4115
4116         /*
4117          * As we are opening fsp1 read-only we only expect
4118          * an error on close on fsp2 if we are out of space.
4119          * Thus we don't look at the error return from the
4120          * close of fsp1.
4121          */
4122         *err_ret = close_file(fsp2,False);
4123
4124         return(ret == (SMB_OFF_T)src_sbuf.st_size);
4125 }
4126
4127 /****************************************************************************
4128  Reply to a file copy.
4129 ****************************************************************************/
4130
4131 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4132 {
4133         int outsize = 0;
4134         pstring name;
4135         pstring directory;
4136         pstring mask,newname;
4137         char *p;
4138         int count=0;
4139         int error = ERRnoaccess;
4140         int err = 0;
4141         BOOL has_wild;
4142         BOOL exists=False;
4143         int tid2 = SVAL(inbuf,smb_vwv0);
4144         int ofun = SVAL(inbuf,smb_vwv1);
4145         int flags = SVAL(inbuf,smb_vwv2);
4146         BOOL target_is_directory=False;
4147         BOOL bad_path1 = False;
4148         BOOL bad_path2 = False;
4149         BOOL rc = True;
4150         SMB_STRUCT_STAT sbuf1, sbuf2;
4151         NTSTATUS status;
4152
4153         START_PROFILE(SMBcopy);
4154
4155         *directory = *mask = 0;
4156
4157         p = smb_buf(inbuf);
4158         p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4159         if (!NT_STATUS_IS_OK(status)) {
4160                 END_PROFILE(SMBcopy);
4161                 return ERROR_NT(status);
4162         }
4163         p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4164         if (!NT_STATUS_IS_OK(status)) {
4165                 END_PROFILE(SMBcopy);
4166                 return ERROR_NT(status);
4167         }
4168    
4169         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4170    
4171         if (tid2 != conn->cnum) {
4172                 /* can't currently handle inter share copies XXXX */
4173                 DEBUG(3,("Rejecting inter-share copy\n"));
4174                 END_PROFILE(SMBcopy);
4175                 return ERROR_DOS(ERRSRV,ERRinvdevice);
4176         }
4177
4178         RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4179         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4180
4181         rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4182         unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4183
4184         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4185
4186         if ((flags&1) && target_is_directory) {
4187                 END_PROFILE(SMBcopy);
4188                 return ERROR_DOS(ERRDOS,ERRbadfile);
4189         }
4190
4191         if ((flags&2) && !target_is_directory) {
4192                 END_PROFILE(SMBcopy);
4193                 return ERROR_DOS(ERRDOS,ERRbadpath);
4194         }
4195
4196         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4197                 /* wants a tree copy! XXXX */
4198                 DEBUG(3,("Rejecting tree copy\n"));
4199                 END_PROFILE(SMBcopy);
4200                 return ERROR_DOS(ERRSRV,ERRerror);
4201         }
4202
4203         p = strrchr_m(name,'/');
4204         if (!p) {
4205                 pstrcpy(directory,"./");
4206                 pstrcpy(mask,name);
4207         } else {
4208                 *p = 0;
4209                 pstrcpy(directory,name);
4210                 pstrcpy(mask,p+1);
4211         }
4212
4213         /*
4214          * We should only check the mangled cache
4215          * here if unix_convert failed. This means
4216          * that the path in 'mask' doesn't exist
4217          * on the file system and so we need to look
4218          * for a possible mangle. This patch from
4219          * Tine Smukavec <valentin.smukavec@hermes.si>.
4220          */
4221
4222         if (!rc && mangle_is_mangled(mask))
4223                 mangle_check_cache( mask, sizeof(pstring)-1 );
4224
4225         has_wild = ms_has_wild(mask);
4226
4227         if (!has_wild) {
4228                 pstrcat(directory,"/");
4229                 pstrcat(directory,mask);
4230                 if (resolve_wildcards(directory,newname) &&
4231                                 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4232                         count++;
4233                 if(!count && err) {
4234                         errno = err;
4235                         END_PROFILE(SMBcopy);
4236                         return(UNIXERROR(ERRHRD,ERRgeneral));
4237                 }
4238                 if (!count) {
4239                         exists = vfs_file_exist(conn,directory,NULL);
4240                 }
4241         } else {
4242                 void *dirptr = NULL;
4243                 const char *dname;
4244                 pstring destname;
4245
4246                 if (check_name(directory,conn))
4247                         dirptr = OpenDir(conn, directory, True);
4248
4249                 if (dirptr) {
4250                         error = ERRbadfile;
4251
4252                         if (strequal(mask,"????????.???"))
4253                                 pstrcpy(mask,"*");
4254
4255                         while ((dname = ReadDirName(dirptr))) {
4256                                 pstring fname;
4257                                 pstrcpy(fname,dname);
4258     
4259                                 if(!mask_match(fname, mask, conn->case_sensitive))
4260                                         continue;
4261
4262                                 error = ERRnoaccess;
4263                                 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4264                                 pstrcpy(destname,newname);
4265                                 if (resolve_wildcards(fname,destname) && 
4266                                                 copy_file(fname,destname,conn,ofun,
4267                                                 count,target_is_directory,&err))
4268                                         count++;
4269                                 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4270                         }
4271                         CloseDir(dirptr);
4272                 }
4273         }
4274   
4275         if (count == 0) {
4276                 if(err) {
4277                         /* Error on close... */
4278                         errno = err;
4279                         END_PROFILE(SMBcopy);
4280                         return(UNIXERROR(ERRHRD,ERRgeneral));
4281                 }
4282
4283                 if (exists) {
4284                         END_PROFILE(SMBcopy);
4285                         return ERROR_DOS(ERRDOS,error);
4286                 } else {
4287                         if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4288                                 unix_ERR_class = ERRDOS;
4289                                 unix_ERR_code = ERRbadpath;
4290                         }
4291                         END_PROFILE(SMBcopy);
4292                         return(UNIXERROR(ERRDOS,error));
4293                 }
4294         }
4295   
4296         outsize = set_message(outbuf,1,0,True);
4297         SSVAL(outbuf,smb_vwv0,count);
4298
4299         END_PROFILE(SMBcopy);
4300         return(outsize);
4301 }
4302
4303 /****************************************************************************
4304  Reply to a setdir.
4305 ****************************************************************************/
4306
4307 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4308 {
4309         int snum;
4310         int outsize = 0;
4311         BOOL ok = False;
4312         pstring newdir;
4313         NTSTATUS status;
4314
4315         START_PROFILE(pathworks_setdir);
4316   
4317         snum = SNUM(conn);
4318         if (!CAN_SETDIR(snum)) {
4319                 END_PROFILE(pathworks_setdir);
4320                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4321         }
4322
4323         srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4324         if (!NT_STATUS_IS_OK(status)) {
4325                 END_PROFILE(pathworks_setdir);
4326                 return ERROR_NT(status);
4327         }
4328   
4329         if (strlen(newdir) == 0) {
4330                 ok = True;
4331         } else {
4332                 ok = vfs_directory_exist(conn,newdir,NULL);
4333                 if (ok)
4334                         string_set(&conn->connectpath,newdir);
4335         }
4336   
4337         if (!ok) {
4338                 END_PROFILE(pathworks_setdir);
4339                 return ERROR_DOS(ERRDOS,ERRbadpath);
4340         }
4341   
4342         outsize = set_message(outbuf,0,0,True);
4343         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4344   
4345         DEBUG(3,("setdir %s\n", newdir));
4346
4347         END_PROFILE(pathworks_setdir);
4348         return(outsize);
4349 }
4350
4351 /****************************************************************************
4352  Get a lock pid, dealing with large count requests.
4353 ****************************************************************************/
4354
4355 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4356 {
4357         if(!large_file_format)
4358                 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4359         else
4360                 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4361 }
4362
4363 /****************************************************************************
4364  Get a lock count, dealing with large count requests.
4365 ****************************************************************************/
4366
4367 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4368 {
4369         SMB_BIG_UINT count = 0;
4370
4371         if(!large_file_format) {
4372                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4373         } else {
4374
4375 #if defined(HAVE_LONGLONG)
4376                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4377                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4378 #else /* HAVE_LONGLONG */
4379
4380                 /*
4381                  * NT4.x seems to be broken in that it sends large file (64 bit)
4382                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4383                  * negotiated. For boxes without large unsigned ints truncate the
4384                  * lock count by dropping the top 32 bits.
4385                  */
4386
4387                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4388                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4389                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4390                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4391                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4392                 }
4393
4394                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4395 #endif /* HAVE_LONGLONG */
4396         }
4397
4398         return count;
4399 }
4400
4401 #if !defined(HAVE_LONGLONG)
4402 /****************************************************************************
4403  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4404 ****************************************************************************/
4405
4406 static uint32 map_lock_offset(uint32 high, uint32 low)
4407 {
4408         unsigned int i;
4409         uint32 mask = 0;
4410         uint32 highcopy = high;
4411  
4412         /*
4413          * Try and find out how many significant bits there are in high.
4414          */
4415  
4416         for(i = 0; highcopy; i++)
4417                 highcopy >>= 1;
4418  
4419         /*
4420          * We use 31 bits not 32 here as POSIX
4421          * lock offsets may not be negative.
4422          */
4423  
4424         mask = (~0) << (31 - i);
4425  
4426         if(low & mask)
4427                 return 0; /* Fail. */
4428  
4429         high <<= (31 - i);
4430  
4431         return (high|low);
4432 }
4433 #endif /* !defined(HAVE_LONGLONG) */
4434
4435 /****************************************************************************
4436  Get a lock offset, dealing with large offset requests.
4437 ****************************************************************************/
4438
4439 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4440 {
4441         SMB_BIG_UINT offset = 0;
4442
4443         *err = False;
4444
4445         if(!large_file_format) {
4446                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4447         } else {
4448
4449 #if defined(HAVE_LONGLONG)
4450                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4451                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4452 #else /* HAVE_LONGLONG */
4453
4454                 /*
4455                  * NT4.x seems to be broken in that it sends large file (64 bit)
4456                  * lockingX calls even if the CAP_LARGE_FILES was *not*
4457                  * negotiated. For boxes without large unsigned ints mangle the
4458                  * lock offset by mapping the top 32 bits onto the lower 32.
4459                  */
4460       
4461                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4462                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4463                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4464                         uint32 new_low = 0;
4465
4466                         if((new_low = map_lock_offset(high, low)) == 0) {
4467                                 *err = True;
4468                                 return (SMB_BIG_UINT)-1;
4469                         }
4470
4471                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4472                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4473                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4474                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4475                 }
4476
4477                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4478 #endif /* HAVE_LONGLONG */
4479         }
4480
4481         return offset;
4482 }
4483
4484 /****************************************************************************
4485  Reply to a lockingX request.
4486 ****************************************************************************/
4487
4488 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4489 {
4490         files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4491         unsigned char locktype = CVAL(inbuf,smb_vwv3);
4492         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4493         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4494         uint16 num_locks = SVAL(inbuf,smb_vwv7);
4495         SMB_BIG_UINT count = 0, offset = 0;
4496         uint16 lock_pid;
4497         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4498         int i;
4499         char *data;
4500         BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4501         BOOL err;
4502         BOOL my_lock_ctx = False;
4503         NTSTATUS status;
4504
4505         START_PROFILE(SMBlockingX);
4506         
4507         CHECK_FSP(fsp,conn);
4508         
4509         data = smb_buf(inbuf);
4510
4511         if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4512                 /* we don't support these - and CANCEL_LOCK makes w2k
4513                    and XP reboot so I don't really want to be
4514                    compatible! (tridge) */
4515                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4516         }
4517         
4518         /* Check if this is an oplock break on a file
4519            we have granted an oplock on.
4520         */
4521         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4522                 /* Client can insist on breaking to none. */
4523                 BOOL break_to_none = (oplocklevel == 0);
4524                 
4525                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4526                          (unsigned int)oplocklevel, fsp->fnum ));
4527
4528                 /*
4529                  * Make sure we have granted an exclusive or batch oplock on this file.
4530                  */
4531                 
4532                 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4533                         DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4534 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4535
4536                         /* if this is a pure oplock break request then don't send a reply */
4537                         if (num_locks == 0 && num_ulocks == 0) {
4538                                 END_PROFILE(SMBlockingX);
4539                                 return -1;
4540                         } else {
4541                                 END_PROFILE(SMBlockingX);
4542                                 return ERROR_DOS(ERRDOS,ERRlock);
4543                         }
4544                 }
4545
4546                 if (remove_oplock(fsp, break_to_none) == False) {
4547                         DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4548                                  fsp->fsp_name ));
4549                 }
4550                 
4551                 /* if this is a pure oplock break request then don't send a reply */
4552                 if (num_locks == 0 && num_ulocks == 0) {
4553                         /* Sanity check - ensure a pure oplock break is not a
4554                            chained request. */
4555                         if(CVAL(inbuf,smb_vwv0) != 0xff)
4556                                 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4557                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
4558                         END_PROFILE(SMBlockingX);
4559                         return -1;
4560                 }
4561         }
4562
4563         /*
4564          * We do this check *after* we have checked this is not a oplock break
4565          * response message. JRA.
4566          */
4567         
4568         release_level_2_oplocks_on_change(fsp);
4569         
4570         /* Data now points at the beginning of the list
4571            of smb_unlkrng structs */
4572         for(i = 0; i < (int)num_ulocks; i++) {
4573                 lock_pid = get_lock_pid( data, i, large_file_format);
4574                 count = get_lock_count( data, i, large_file_format);
4575                 offset = get_lock_offset( data, i, large_file_format, &err);
4576                 
4577                 /*
4578                  * There is no error code marked "stupid client bug".... :-).
4579                  */
4580                 if(err) {
4581                         END_PROFILE(SMBlockingX);
4582                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4583                 }
4584
4585                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4586                           (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4587                 
4588                 status = do_unlock(fsp,conn,lock_pid,count,offset);
4589                 if (NT_STATUS_V(status)) {
4590                         END_PROFILE(SMBlockingX);
4591                         return ERROR_NT(status);
4592                 }
4593         }
4594
4595         /* Setup the timeout in seconds. */
4596
4597         lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4598         
4599         /* Now do any requested locks */
4600         data += ((large_file_format ? 20 : 10)*num_ulocks);
4601         
4602         /* Data now points at the beginning of the list
4603            of smb_lkrng structs */
4604         
4605         for(i = 0; i < (int)num_locks; i++) {
4606                 lock_pid = get_lock_pid( data, i, large_file_format);
4607                 count = get_lock_count( data, i, large_file_format);
4608                 offset = get_lock_offset( data, i, large_file_format, &err);
4609                 
4610                 /*
4611                  * There is no error code marked "stupid client bug".... :-).
4612                  */
4613                 if(err) {
4614                         END_PROFILE(SMBlockingX);
4615                         return ERROR_DOS(ERRDOS,ERRnoaccess);
4616                 }
4617                 
4618                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4619                         (double)offset, (double)count, (unsigned int)lock_pid,
4620                         fsp->fsp_name, (int)lock_timeout ));
4621                 
4622                 status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
4623                                  ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4624                 if (NT_STATUS_V(status)) {
4625                         /*
4626                          * Interesting fact found by IFSTEST /t LockOverlappedTest...
4627                          * Even if it's our own lock context, we need to wait here as
4628                          * there may be an unlock on the way.
4629                          * So I removed a "&& !my_lock_ctx" from the following
4630                          * if statement. JRA.
4631                          */
4632                         if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4633                                 /*
4634                                  * A blocking lock was requested. Package up
4635                                  * this smb into a queued request and push it
4636                                  * onto the blocking lock queue.
4637                                  */
4638                                 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4639                                         END_PROFILE(SMBlockingX);
4640                                         return -1;
4641                                 }
4642                         }
4643                         break;
4644                 }
4645         }
4646         
4647         /* If any of the above locks failed, then we must unlock
4648            all of the previous locks (X/Open spec). */
4649         if (i != num_locks && num_locks != 0) {
4650                 /*
4651                  * Ensure we don't do a remove on the lock that just failed,
4652                  * as under POSIX rules, if we have a lock already there, we
4653                  * will delete it (and we shouldn't) .....
4654                  */
4655                 for(i--; i >= 0; i--) {
4656                         lock_pid = get_lock_pid( data, i, large_file_format);
4657                         count = get_lock_count( data, i, large_file_format);
4658                         offset = get_lock_offset( data, i, large_file_format, &err);
4659                         
4660                         /*
4661                          * There is no error code marked "stupid client bug".... :-).
4662                          */
4663                         if(err) {
4664                                 END_PROFILE(SMBlockingX);
4665                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4666                         }
4667                         
4668                         do_unlock(fsp,conn,lock_pid,count,offset);
4669                 }
4670                 END_PROFILE(SMBlockingX);
4671                 return ERROR_NT(status);
4672         }
4673
4674         set_message(outbuf,2,0,True);
4675         
4676         DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4677                     fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4678         
4679         END_PROFILE(SMBlockingX);
4680         return chain_reply(inbuf,outbuf,length,bufsize);
4681 }
4682
4683 /****************************************************************************
4684  Reply to a SMBreadbmpx (read block multiplex) request.
4685 ****************************************************************************/
4686
4687 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4688 {
4689         ssize_t nread = -1;
4690         ssize_t total_read;
4691         char *data;
4692         SMB_OFF_T startpos;
4693         int outsize;
4694         size_t maxcount;
4695         int max_per_packet;
4696         size_t tcount;
4697         int pad;
4698         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4699         START_PROFILE(SMBreadBmpx);
4700
4701         /* this function doesn't seem to work - disable by default */
4702         if (!lp_readbmpx()) {
4703                 END_PROFILE(SMBreadBmpx);
4704                 return ERROR_DOS(ERRSRV,ERRuseSTD);
4705         }
4706
4707         outsize = set_message(outbuf,8,0,True);
4708
4709         CHECK_FSP(fsp,conn);
4710         CHECK_READ(fsp);
4711
4712         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4713         maxcount = SVAL(inbuf,smb_vwv3);
4714
4715         data = smb_buf(outbuf);
4716         pad = ((long)data)%4;
4717         if (pad)
4718                 pad = 4 - pad;
4719         data += pad;
4720
4721         max_per_packet = bufsize-(outsize+pad);
4722         tcount = maxcount;
4723         total_read = 0;
4724
4725         if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4726                 END_PROFILE(SMBreadBmpx);
4727                 return ERROR_DOS(ERRDOS,ERRlock);
4728         }
4729
4730         do {
4731                 size_t N = MIN(max_per_packet,tcount-total_read);
4732   
4733                 nread = read_file(fsp,data,startpos,N);
4734
4735                 if (nread <= 0)
4736                         nread = 0;
4737
4738                 if (nread < (ssize_t)N)
4739                         tcount = total_read + nread;
4740
4741                 set_message(outbuf,8,nread,False);
4742                 SIVAL(outbuf,smb_vwv0,startpos);
4743                 SSVAL(outbuf,smb_vwv2,tcount);
4744                 SSVAL(outbuf,smb_vwv6,nread);
4745                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4746
4747                 if (!send_smb(smbd_server_fd(),outbuf))
4748                         exit_server("reply_readbmpx: send_smb failed.");
4749
4750                 total_read += nread;
4751                 startpos += nread;
4752         } while (total_read < (ssize_t)tcount);
4753
4754         END_PROFILE(SMBreadBmpx);
4755         return(-1);
4756 }
4757
4758 /****************************************************************************
4759  Reply to a SMBsetattrE.
4760 ****************************************************************************/
4761
4762 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4763 {
4764         struct utimbuf unix_times;
4765         int outsize = 0;
4766         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4767         START_PROFILE(SMBsetattrE);
4768
4769         outsize = set_message(outbuf,0,0,True);
4770
4771         if(!fsp || (fsp->conn != conn)) {
4772                 END_PROFILE(SMBgetattrE);
4773                 return ERROR_DOS(ERRDOS,ERRbadfid);
4774         }
4775
4776         /*
4777          * Convert the DOS times into unix times. Ignore create
4778          * time as UNIX can't set this.
4779          */
4780
4781         unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4782         unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4783   
4784         /* 
4785          * Patch from Ray Frush <frush@engr.colostate.edu>
4786          * Sometimes times are sent as zero - ignore them.
4787          */
4788
4789         if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4790                 /* Ignore request */
4791                 if( DEBUGLVL( 3 ) ) {
4792                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4793                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4794                 }
4795                 END_PROFILE(SMBsetattrE);
4796                 return(outsize);
4797         } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4798                 /* set modify time = to access time if modify time was 0 */
4799                 unix_times.modtime = unix_times.actime;
4800         }
4801
4802         /* Set the date on this file */
4803         if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4804                 END_PROFILE(SMBsetattrE);
4805                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4806         }
4807   
4808         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4809                 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4810
4811         END_PROFILE(SMBsetattrE);
4812         return(outsize);
4813 }
4814
4815
4816 /* Back from the dead for OS/2..... JRA. */
4817
4818 /****************************************************************************
4819  Reply to a SMBwritebmpx (write block multiplex primary) request.
4820 ****************************************************************************/
4821
4822 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4823 {
4824         size_t numtowrite;
4825         ssize_t nwritten = -1;
4826         int outsize = 0;
4827         SMB_OFF_T startpos;
4828         size_t tcount;
4829         BOOL write_through;
4830         int smb_doff;
4831         char *data;
4832         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4833         START_PROFILE(SMBwriteBmpx);
4834
4835         CHECK_FSP(fsp,conn);
4836         CHECK_WRITE(fsp);
4837         CHECK_ERROR(fsp);
4838
4839         tcount = SVAL(inbuf,smb_vwv1);
4840         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4841         write_through = BITSETW(inbuf+smb_vwv7,0);
4842         numtowrite = SVAL(inbuf,smb_vwv10);
4843         smb_doff = SVAL(inbuf,smb_vwv11);
4844
4845         data = smb_base(inbuf) + smb_doff;
4846
4847         /* If this fails we need to send an SMBwriteC response,
4848                 not an SMBwritebmpx - set this up now so we don't forget */
4849         SCVAL(outbuf,smb_com,SMBwritec);
4850
4851         if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4852                 END_PROFILE(SMBwriteBmpx);
4853                 return(ERROR_DOS(ERRDOS,ERRlock));
4854         }
4855
4856         nwritten = write_file(fsp,data,startpos,numtowrite);
4857
4858         if(lp_syncalways(SNUM(conn)) || write_through)
4859                 sync_file(conn,fsp);
4860   
4861         if(nwritten < (ssize_t)numtowrite) {
4862                 END_PROFILE(SMBwriteBmpx);
4863                 return(UNIXERROR(ERRHRD,ERRdiskfull));
4864         }
4865
4866         /* If the maximum to be written to this file
4867                 is greater than what we just wrote then set
4868                 up a secondary struct to be attached to this
4869                 fd, we will use this to cache error messages etc. */
4870
4871         if((ssize_t)tcount > nwritten) {
4872                 write_bmpx_struct *wbms;
4873                 if(fsp->wbmpx_ptr != NULL)
4874                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4875                 else
4876                         wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4877                 if(!wbms) {
4878                         DEBUG(0,("Out of memory in reply_readmpx\n"));
4879                         END_PROFILE(SMBwriteBmpx);
4880                         return(ERROR_DOS(ERRSRV,ERRnoresource));
4881                 }
4882                 wbms->wr_mode = write_through;
4883                 wbms->wr_discard = False; /* No errors yet */
4884                 wbms->wr_total_written = nwritten;
4885                 wbms->wr_errclass = 0;
4886                 wbms->wr_error = 0;
4887                 fsp->wbmpx_ptr = wbms;
4888         }
4889
4890         /* We are returning successfully, set the message type back to
4891                 SMBwritebmpx */
4892         SCVAL(outbuf,smb_com,SMBwriteBmpx);
4893   
4894         outsize = set_message(outbuf,1,0,True);
4895   
4896         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4897   
4898         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4899                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
4900
4901         if (write_through && tcount==nwritten) {
4902                 /* We need to send both a primary and a secondary response */
4903                 smb_setlen(outbuf,outsize - 4);
4904                 if (!send_smb(smbd_server_fd(),outbuf))
4905                         exit_server("reply_writebmpx: send_smb failed.");
4906
4907                 /* Now the secondary */
4908                 outsize = set_message(outbuf,1,0,True);
4909                 SCVAL(outbuf,smb_com,SMBwritec);
4910                 SSVAL(outbuf,smb_vwv0,nwritten);
4911         }
4912
4913         END_PROFILE(SMBwriteBmpx);
4914         return(outsize);
4915 }
4916
4917 /****************************************************************************
4918  Reply to a SMBwritebs (write block multiplex secondary) request.
4919 ****************************************************************************/
4920
4921 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4922 {
4923         size_t numtowrite;
4924         ssize_t nwritten = -1;
4925         int outsize = 0;
4926         SMB_OFF_T startpos;
4927         size_t tcount;
4928         BOOL write_through;
4929         int smb_doff;
4930         char *data;
4931         write_bmpx_struct *wbms;
4932         BOOL send_response = False; 
4933         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4934         START_PROFILE(SMBwriteBs);
4935
4936         CHECK_FSP(fsp,conn);
4937         CHECK_WRITE(fsp);
4938
4939         tcount = SVAL(inbuf,smb_vwv1);
4940         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4941         numtowrite = SVAL(inbuf,smb_vwv6);
4942         smb_doff = SVAL(inbuf,smb_vwv7);
4943
4944         data = smb_base(inbuf) + smb_doff;
4945
4946         /* We need to send an SMBwriteC response, not an SMBwritebs */
4947         SCVAL(outbuf,smb_com,SMBwritec);
4948
4949         /* This fd should have an auxiliary struct attached,
4950                 check that it does */
4951         wbms = fsp->wbmpx_ptr;
4952         if(!wbms) {
4953                 END_PROFILE(SMBwriteBs);
4954                 return(-1);
4955         }
4956
4957         /* If write through is set we can return errors, else we must cache them */
4958         write_through = wbms->wr_mode;
4959
4960         /* Check for an earlier error */
4961         if(wbms->wr_discard) {
4962                 END_PROFILE(SMBwriteBs);
4963                 return -1; /* Just discard the packet */
4964         }
4965
4966         nwritten = write_file(fsp,data,startpos,numtowrite);
4967
4968         if(lp_syncalways(SNUM(conn)) || write_through)
4969                 sync_file(conn,fsp);
4970   
4971         if (nwritten < (ssize_t)numtowrite) {
4972                 if(write_through) {
4973                         /* We are returning an error - we can delete the aux struct */
4974                         if (wbms)
4975                                 free((char *)wbms);
4976                         fsp->wbmpx_ptr = NULL;
4977                         END_PROFILE(SMBwriteBs);
4978                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
4979                 }
4980                 END_PROFILE(SMBwriteBs);
4981                 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4982         }
4983
4984         /* Increment the total written, if this matches tcount
4985                 we can discard the auxiliary struct (hurrah !) and return a writeC */
4986         wbms->wr_total_written += nwritten;
4987         if(wbms->wr_total_written >= tcount) {
4988                 if (write_through) {
4989                         outsize = set_message(outbuf,1,0,True);
4990                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
4991                         send_response = True;
4992                 }
4993
4994                 free((char *)wbms);
4995                 fsp->wbmpx_ptr = NULL;
4996         }
4997
4998         if(send_response) {
4999                 END_PROFILE(SMBwriteBs);
5000                 return(outsize);
5001         }
5002
5003         END_PROFILE(SMBwriteBs);
5004         return(-1);
5005 }
5006
5007 /****************************************************************************
5008  Reply to a SMBgetattrE.
5009 ****************************************************************************/
5010
5011 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5012 {
5013         SMB_STRUCT_STAT sbuf;
5014         int outsize = 0;
5015         int mode;
5016         files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5017         START_PROFILE(SMBgetattrE);
5018
5019         outsize = set_message(outbuf,11,0,True);
5020
5021         if(!fsp || (fsp->conn != conn)) {
5022                 END_PROFILE(SMBgetattrE);
5023                 return ERROR_DOS(ERRDOS,ERRbadfid);
5024         }
5025
5026         /* Do an fstat on this file */
5027         if(fsp_stat(fsp, &sbuf)) {
5028                 END_PROFILE(SMBgetattrE);
5029                 return(UNIXERROR(ERRDOS,ERRnoaccess));
5030         }
5031   
5032         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5033   
5034         /*
5035          * Convert the times into dos times. Set create
5036          * date to be last modify date as UNIX doesn't save
5037          * this.
5038          */
5039
5040         put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5041         put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5042         put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5043
5044         if (mode & aDIR) {
5045                 SIVAL(outbuf,smb_vwv6,0);
5046                 SIVAL(outbuf,smb_vwv8,0);
5047         } else {
5048                 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
5049                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5050                 SIVAL(outbuf,smb_vwv8,allocation_size);
5051         }
5052         SSVAL(outbuf,smb_vwv10, mode);
5053   
5054         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5055   
5056         END_PROFILE(SMBgetattrE);
5057         return(outsize);
5058 }