r24383: Convert call_nt_transact_ioctl to the new API
[samba.git] / source / smbd / reply.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_recv;
32 unsigned int smb_echo_count = 0;
33 extern uint32 global_client_caps;
34
35 extern struct current_user current_user;
36 extern BOOL global_encrypted_passwords_negotiated;
37
38 /****************************************************************************
39  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
40  path or anything including wildcards.
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 /* Custom version for processing POSIX paths. */
47 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
48
49 static NTSTATUS check_path_syntax_internal(char *path,
50                                            BOOL posix_path,
51                                            BOOL *p_last_component_contains_wcard)
52 {
53         char *d = path;
54         const char *s = path;
55         NTSTATUS ret = NT_STATUS_OK;
56         BOOL start_of_name_component = True;
57
58         *p_last_component_contains_wcard = False;
59
60         while (*s) {
61                 if (IS_PATH_SEP(*s,posix_path)) {
62                         /*
63                          * Safe to assume is not the second part of a mb char
64                          * as this is handled below.
65                          */
66                         /* Eat multiple '/' or '\\' */
67                         while (IS_PATH_SEP(*s,posix_path)) {
68                                 s++;
69                         }
70                         if ((d != path) && (*s != '\0')) {
71                                 /* We only care about non-leading or trailing '/' or '\\' */
72                                 *d++ = '/';
73                         }
74
75                         start_of_name_component = True;
76                         /* New component. */
77                         *p_last_component_contains_wcard = False;
78                         continue;
79                 }
80
81                 if (start_of_name_component) {
82                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
83                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
84
85                                 /*
86                                  * No mb char starts with '.' so we're safe checking the directory separator here.
87                                  */
88
89                                 /* If  we just added a '/' - delete it */
90                                 if ((d > path) && (*(d-1) == '/')) {
91                                         *(d-1) = '\0';
92                                         d--;
93                                 }
94
95                                 /* Are we at the start ? Can't go back further if so. */
96                                 if (d <= path) {
97                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
98                                         break;
99                                 }
100                                 /* Go back one level... */
101                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
102                                 /* NOTE - if this assumption is invalid we are not in good shape... */
103                                 /* Decrement d first as d points to the *next* char to write into. */
104                                 for (d--; d > path; d--) {
105                                         if (*d == '/')
106                                                 break;
107                                 }
108                                 s += 2; /* Else go past the .. */
109                                 /* We're still at the start of a name component, just the previous one. */
110                                 continue;
111
112                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
113                                 if (posix_path) {
114                                         /* Eat the '.' */
115                                         s++;
116                                         continue;
117                                 }
118                         }
119
120                 }
121
122                 if (!(*s & 0x80)) {
123                         if (!posix_path) {
124                                 if (*s <= 0x1f) {
125                                         return NT_STATUS_OBJECT_NAME_INVALID;
126                                 }
127                                 switch (*s) {
128                                         case '*':
129                                         case '?':
130                                         case '<':
131                                         case '>':
132                                         case '"':
133                                                 *p_last_component_contains_wcard = True;
134                                                 break;
135                                         default:
136                                                 break;
137                                 }
138                         }
139                         *d++ = *s++;
140                 } else {
141                         size_t siz;
142                         /* Get the size of the next MB character. */
143                         next_codepoint(s,&siz);
144                         switch(siz) {
145                                 case 5:
146                                         *d++ = *s++;
147                                         /*fall through*/
148                                 case 4:
149                                         *d++ = *s++;
150                                         /*fall through*/
151                                 case 3:
152                                         *d++ = *s++;
153                                         /*fall through*/
154                                 case 2:
155                                         *d++ = *s++;
156                                         /*fall through*/
157                                 case 1:
158                                         *d++ = *s++;
159                                         break;
160                                 default:
161                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
162                                         *d = '\0';
163                                         return NT_STATUS_INVALID_PARAMETER;
164                         }
165                 }
166                 start_of_name_component = False;
167         }
168
169         *d = '\0';
170         return ret;
171 }
172
173 /****************************************************************************
174  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
175  No wildcards allowed.
176 ****************************************************************************/
177
178 NTSTATUS check_path_syntax(char *path)
179 {
180         BOOL ignore;
181         return check_path_syntax_internal(path, False, &ignore);
182 }
183
184 /****************************************************************************
185  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
186  Wildcards allowed - p_contains_wcard returns true if the last component contained
187  a wildcard.
188 ****************************************************************************/
189
190 NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
191 {
192         return check_path_syntax_internal(path, False, p_contains_wcard);
193 }
194
195 /****************************************************************************
196  Check the path for a POSIX client.
197  We're assuming here that '/' is not the second byte in any multibyte char
198  set (a safe assumption).
199 ****************************************************************************/
200
201 NTSTATUS check_path_syntax_posix(char *path)
202 {
203         BOOL ignore;
204         return check_path_syntax_internal(path, True, &ignore);
205 }
206
207 /****************************************************************************
208  Pull a string and check the path allowing a wilcard - provide for error return.
209 ****************************************************************************/
210
211 size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest,
212                              const char *src, size_t dest_len, size_t src_len,
213                              int flags, NTSTATUS *err, BOOL *contains_wcard)
214 {
215         size_t ret;
216 #ifdef DEVELOPER
217         SMB_ASSERT(dest_len == sizeof(pstring));
218 #endif
219
220         if (src_len == 0) {
221                 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
222                                       dest_len, flags);
223         } else {
224                 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
225                                   dest_len, src_len, flags);
226         }
227
228         *contains_wcard = False;
229
230         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
231                 /* 
232                  * For a DFS path the function parse_dfs_path()
233                  * will do the path processing, just make a copy.
234                  */
235                 *err = NT_STATUS_OK;
236                 return ret;
237         }
238
239         if (lp_posix_pathnames()) {
240                 *err = check_path_syntax_posix(dest);
241         } else {
242                 *err = check_path_syntax_wcard(dest, contains_wcard);
243         }
244
245         return ret;
246 }
247
248 /****************************************************************************
249  Pull a string and check the path - provide for error return.
250 ****************************************************************************/
251
252 size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest,
253                        const char *src, size_t dest_len, size_t src_len,
254                        int flags, NTSTATUS *err)
255 {
256         size_t ret;
257 #ifdef DEVELOPER
258         SMB_ASSERT(dest_len == sizeof(pstring));
259 #endif
260
261         if (src_len == 0) {
262                 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
263                                       dest_len, flags);
264         } else {
265                 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
266                                   dest_len, src_len, flags);
267         }
268
269         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270                 /* 
271                  * For a DFS path the function parse_dfs_path()
272                  * will do the path processing, just make a copy.
273                  */
274                 *err = NT_STATUS_OK;
275                 return ret;
276         }
277
278         if (lp_posix_pathnames()) {
279                 *err = check_path_syntax_posix(dest);
280         } else {
281                 *err = check_path_syntax(dest);
282         }
283
284         return ret;
285 }
286
287 /****************************************************************************
288  Check if we have a correct fsp pointing to a file. Replacement for the
289  CHECK_FSP macro.
290 ****************************************************************************/
291 BOOL check_fsp(connection_struct *conn, struct smb_request *req,
292                files_struct *fsp, struct current_user *user)
293 {
294         if (!(fsp) || !(conn)) {
295                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
296                 return False;
297         }
298         if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) {
299                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
300                 return False;
301         }
302         if ((fsp)->is_directory) {
303                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
304                 return False;
305         }
306         if ((fsp)->fh->fd == -1) {
307                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
308                 return False;
309         }
310         (fsp)->num_smb_operations++;
311         return True;
312 }
313
314 /****************************************************************************
315  Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
316 ****************************************************************************/
317
318 BOOL fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
319                       files_struct *fsp, struct current_user *user)
320 {
321         if ((fsp) && (conn) && ((conn)==(fsp)->conn)
322             && (current_user.vuid==(fsp)->vuid)) {
323                 return True;
324         }
325
326         reply_nterror(req, NT_STATUS_INVALID_HANDLE);
327         return False;
328 }
329
330 /****************************************************************************
331  Reply to a (netbios-level) special message.
332 ****************************************************************************/
333
334 void reply_special(char *inbuf)
335 {
336         int msg_type = CVAL(inbuf,0);
337         int msg_flags = CVAL(inbuf,1);
338         fstring name1,name2;
339         char name_type = 0;
340
341         /*
342          * We only really use 4 bytes of the outbuf, but for the smb_setlen
343          * calculation & friends (send_smb uses that) we need the full smb
344          * header.
345          */
346         char outbuf[smb_size];
347         
348         static BOOL already_got_session = False;
349
350         *name1 = *name2 = 0;
351         
352         memset(outbuf, '\0', sizeof(outbuf));
353
354         smb_setlen(inbuf,outbuf,0);
355         
356         switch (msg_type) {
357         case 0x81: /* session request */
358                 
359                 if (already_got_session) {
360                         exit_server_cleanly("multiple session request not permitted");
361                 }
362                 
363                 SCVAL(outbuf,0,0x82);
364                 SCVAL(outbuf,3,0);
365                 if (name_len(inbuf+4) > 50 || 
366                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
367                         DEBUG(0,("Invalid name length in session request\n"));
368                         return;
369                 }
370                 name_extract(inbuf,4,name1);
371                 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
372                 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
373                          name1,name2));      
374
375                 set_local_machine_name(name1, True);
376                 set_remote_machine_name(name2, True);
377
378                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
379                          get_local_machine_name(), get_remote_machine_name(),
380                          name_type));
381
382                 if (name_type == 'R') {
383                         /* We are being asked for a pathworks session --- 
384                            no thanks! */
385                         SCVAL(outbuf, 0,0x83);
386                         break;
387                 }
388
389                 /* only add the client's machine name to the list
390                    of possibly valid usernames if we are operating
391                    in share mode security */
392                 if (lp_security() == SEC_SHARE) {
393                         add_session_user(get_remote_machine_name());
394                 }
395
396                 reload_services(True);
397                 reopen_logs();
398
399                 already_got_session = True;
400                 break;
401                 
402         case 0x89: /* session keepalive request 
403                       (some old clients produce this?) */
404                 SCVAL(outbuf,0,SMBkeepalive);
405                 SCVAL(outbuf,3,0);
406                 break;
407                 
408         case 0x82: /* positive session response */
409         case 0x83: /* negative session response */
410         case 0x84: /* retarget session response */
411                 DEBUG(0,("Unexpected session response\n"));
412                 break;
413                 
414         case SMBkeepalive: /* session keepalive */
415         default:
416                 return;
417         }
418         
419         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
420                     msg_type, msg_flags));
421
422         send_smb(smbd_server_fd(), outbuf);
423         return;
424 }
425
426 /****************************************************************************
427  Reply to a tcon.
428  conn POINTER CAN BE NULL HERE !
429 ****************************************************************************/
430
431 int reply_tcon(connection_struct *conn,
432                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
433 {
434         TALLOC_CTX *ctx;
435         const char *service;
436         char *service_buf = NULL;
437         char *password = NULL;
438         char *dev = NULL;
439         int outsize = 0;
440         uint16 vuid = SVAL(inbuf,smb_uid);
441         int pwlen=0;
442         NTSTATUS nt_status;
443         char *p;
444         DATA_BLOB password_blob;
445
446         START_PROFILE(SMBtcon);
447
448         ctx = talloc_init("reply_tcon");
449         if (!ctx) {
450                 END_PROFILE(SMBtcon);
451                 return ERROR_NT(NT_STATUS_NO_MEMORY);
452         }
453
454         p = smb_buf(inbuf)+1;
455         p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
456                         &service_buf, p, STR_TERMINATE) + 1;
457         pwlen = srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
458                         &password, p, STR_TERMINATE) + 1;
459         p += pwlen;
460         p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
461                         &dev, p, STR_TERMINATE) + 1;
462
463         if (service_buf == NULL || password == NULL || dev == NULL) {
464                 TALLOC_FREE(ctx);
465                 END_PROFILE(SMBtcon);
466                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
467         }
468         p = strrchr_m(service_buf,'\\');
469         if (p) {
470                 service = p+1;
471         } else {
472                 service = service_buf;
473         }
474
475         password_blob = data_blob(password, pwlen+1);
476
477         conn = make_connection(service,password_blob,dev,vuid,&nt_status);
478
479         data_blob_clear_free(&password_blob);
480
481         if (!conn) {
482                 TALLOC_FREE(ctx);
483                 END_PROFILE(SMBtcon);
484                 return ERROR_NT(nt_status);
485         }
486
487         outsize = set_message(inbuf,outbuf,2,0,True);
488         SSVAL(outbuf,smb_vwv0,max_recv);
489         SSVAL(outbuf,smb_vwv1,conn->cnum);
490         SSVAL(outbuf,smb_tid,conn->cnum);
491
492         DEBUG(3,("tcon service=%s cnum=%d\n", 
493                  service, conn->cnum));
494
495         END_PROFILE(SMBtcon);
496         TALLOC_FREE(ctx);
497         return(outsize);
498 }
499
500 /****************************************************************************
501  Reply to a tcon and X.
502  conn POINTER CAN BE NULL HERE !
503 ****************************************************************************/
504
505 void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
506 {
507         char *service = NULL;
508         DATA_BLOB password;
509
510         TALLOC_CTX *ctx = NULL;
511         /* what the cleint thinks the device is */
512         char *client_devicetype = NULL;
513         /* what the server tells the client the share represents */
514         const char *server_devicetype;
515         NTSTATUS nt_status;
516         int passlen;
517         char *path = NULL;
518         char *p, *q;
519         uint16 tcon_flags;
520
521         START_PROFILE(SMBtconX);
522
523         if (req->wct < 4) {
524                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
525                 END_PROFILE(SMBtconX);
526                 return;
527         }
528
529         passlen = SVAL(req->inbuf,smb_vwv3);
530         tcon_flags = SVAL(req->inbuf,smb_vwv2);
531
532         /* we might have to close an old one */
533         if ((tcon_flags & 0x1) && conn) {
534                 close_cnum(conn,req->vuid);
535         }
536
537         if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
538                 reply_doserror(req, ERRDOS, ERRbuftoosmall);
539                 END_PROFILE(SMBtconX);
540                 return;
541         }
542
543         if (global_encrypted_passwords_negotiated) {
544                 password = data_blob(smb_buf(req->inbuf),passlen);
545                 if (lp_security() == SEC_SHARE) {
546                         /*
547                          * Security = share always has a pad byte
548                          * after the password.
549                          */
550                         p = smb_buf(req->inbuf) + passlen + 1;
551                 } else {
552                         p = smb_buf(req->inbuf) + passlen;
553                 }
554         } else {
555                 password = data_blob(smb_buf(req->inbuf),passlen+1);
556                 /* Ensure correct termination */
557                 password.data[passlen]=0;
558                 p = smb_buf(req->inbuf) + passlen + 1;
559         }
560
561         ctx = talloc_init("reply_tcon_and_X");
562         if (!ctx) {
563                 data_blob_clear_free(&password);
564                 reply_nterror(req, NT_STATUS_NO_MEMORY);
565                 END_PROFILE(SMBtconX);
566                 return;
567         }
568         p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
569                              STR_TERMINATE);
570
571         if (path == NULL) {
572                 data_blob_clear_free(&password);
573                 TALLOC_FREE(ctx);
574                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
575                 END_PROFILE(SMBtconX);
576                 return;
577         }
578
579         /*
580          * the service name can be either: \\server\share
581          * or share directly like on the DELL PowerVault 705
582          */
583         if (*path=='\\') {
584                 q = strchr_m(path+2,'\\');
585                 if (!q) {
586                         data_blob_clear_free(&password);
587                         TALLOC_FREE(ctx);
588                         reply_doserror(req, ERRDOS, ERRnosuchshare);
589                         END_PROFILE(SMBtconX);
590                         return;
591                 }
592                 service = q+1;
593         } else {
594                 service = path;
595         }
596
597         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
598                                 &client_devicetype, p,
599                                 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
600
601         if (client_devicetype == NULL) {
602                 data_blob_clear_free(&password);
603                 TALLOC_FREE(ctx);
604                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
605                 END_PROFILE(SMBtconX);
606                 return;
607         }
608
609         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
610
611         conn = make_connection(service, password, client_devicetype,
612                                req->vuid, &nt_status);
613
614         data_blob_clear_free(&password);
615
616         if (!conn) {
617                 TALLOC_FREE(ctx);
618                 reply_nterror(req, nt_status);
619                 END_PROFILE(SMBtconX);
620                 return;
621         }
622
623         if ( IS_IPC(conn) )
624                 server_devicetype = "IPC";
625         else if ( IS_PRINT(conn) )
626                 server_devicetype = "LPT1:";
627         else
628                 server_devicetype = "A:";
629
630         if (Protocol < PROTOCOL_NT1) {
631                 reply_outbuf(req, 2, 0);
632                 if (message_push_string(&req->outbuf, server_devicetype,
633                                         STR_TERMINATE|STR_ASCII) == -1) {
634                         TALLOC_FREE(ctx);
635                         reply_nterror(req, NT_STATUS_NO_MEMORY);
636                         END_PROFILE(SMBtconX);
637                         return;
638                 }
639         } else {
640                 /* NT sets the fstype of IPC$ to the null string */
641                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
642
643                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
644                         /* Return permissions. */
645                         uint32 perm1 = 0;
646                         uint32 perm2 = 0;
647
648                         reply_outbuf(req, 7, 0);
649
650                         if (IS_IPC(conn)) {
651                                 perm1 = FILE_ALL_ACCESS;
652                                 perm2 = FILE_ALL_ACCESS;
653                         } else {
654                                 perm1 = CAN_WRITE(conn) ?
655                                                 SHARE_ALL_ACCESS :
656                                                 SHARE_READ_ONLY;
657                         }
658
659                         SIVAL(req->outbuf, smb_vwv3, perm1);
660                         SIVAL(req->outbuf, smb_vwv5, perm2);
661                 } else {
662                         reply_outbuf(req, 3, 0);
663                 }
664
665                 if ((message_push_string(&req->outbuf, server_devicetype,
666                                          STR_TERMINATE|STR_ASCII) == -1)
667                     || (message_push_string(&req->outbuf, fstype,
668                                             STR_TERMINATE) == -1)) {
669                         TALLOC_FREE(ctx);
670                         reply_nterror(req, NT_STATUS_NO_MEMORY);
671                         END_PROFILE(SMBtconX);
672                         return;
673                 }
674
675                 /* what does setting this bit do? It is set by NT4 and
676                    may affect the ability to autorun mounted cdroms */
677                 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
678                       (lp_csc_policy(SNUM(conn)) << 2));
679
680                 init_dfsroot(conn, req->inbuf, req->outbuf);
681         }
682
683
684         DEBUG(3,("tconX service=%s \n",
685                  service));
686
687         /* set the incoming and outgoing tid to the just created one */
688         SSVAL(req->inbuf,smb_tid,conn->cnum);
689         SSVAL(req->outbuf,smb_tid,conn->cnum);
690
691         TALLOC_FREE(ctx);
692         END_PROFILE(SMBtconX);
693
694         chain_reply_new(req);
695         return;
696 }
697
698 /****************************************************************************
699  Reply to an unknown type.
700 ****************************************************************************/
701
702 int reply_unknown(char *inbuf,char *outbuf)
703 {
704         int type;
705         type = CVAL(inbuf,smb_com);
706   
707         DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
708                  smb_fn_name(type), type, type));
709   
710         return(ERROR_DOS(ERRSRV,ERRunknownsmb));
711 }
712
713 void reply_unknown_new(struct smb_request *req, uint8 type)
714 {
715         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
716                   smb_fn_name(type), type, type));
717         reply_doserror(req, ERRSRV, ERRunknownsmb);
718         return;
719 }
720
721 /****************************************************************************
722  Reply to an ioctl.
723  conn POINTER CAN BE NULL HERE !
724 ****************************************************************************/
725
726 int reply_ioctl(connection_struct *conn,
727                 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
728 {
729         uint16 device     = SVAL(inbuf,smb_vwv1);
730         uint16 function   = SVAL(inbuf,smb_vwv2);
731         uint32 ioctl_code = (device << 16) + function;
732         int replysize, outsize;
733         char *p;
734         START_PROFILE(SMBioctl);
735
736         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
737
738         switch (ioctl_code) {
739             case IOCTL_QUERY_JOB_INFO:
740                 replysize = 32;
741                 break;
742             default:
743                 END_PROFILE(SMBioctl);
744                 return(ERROR_DOS(ERRSRV,ERRnosupport));
745         }
746
747         outsize = set_message(inbuf,outbuf,8,replysize+1,True);
748         SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
749         SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
750         SSVAL(outbuf,smb_vwv6,52);        /* Offset to data */
751         p = smb_buf(outbuf) + 1;          /* Allow for alignment */
752
753         switch (ioctl_code) {
754                 case IOCTL_QUERY_JOB_INFO:                  
755                 {
756                         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
757                         if (!fsp) {
758                                 END_PROFILE(SMBioctl);
759                                 return(UNIXERROR(ERRDOS,ERRbadfid));
760                         }
761                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
762                         srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+2,
763                                     global_myname(), 15,
764                                     STR_TERMINATE|STR_ASCII);
765                         if (conn) {
766                                 srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
767                                             p+18, lp_servicename(SNUM(conn)),
768                                             13, STR_TERMINATE|STR_ASCII);
769                         }
770                         break;
771                 }
772         }
773
774         END_PROFILE(SMBioctl);
775         return outsize;
776 }
777
778 /****************************************************************************
779  Strange checkpath NTSTATUS mapping.
780 ****************************************************************************/
781
782 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
783 {
784         /* Strange DOS error code semantics only for checkpath... */
785         if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
786                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
787                         /* We need to map to ERRbadpath */
788                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
789                 }
790         }
791         return status;
792 }
793         
794 /****************************************************************************
795  Reply to a checkpath.
796 ****************************************************************************/
797
798 void reply_checkpath(connection_struct *conn, struct smb_request *req)
799 {
800         pstring name;
801         SMB_STRUCT_STAT sbuf;
802         NTSTATUS status;
803
804         START_PROFILE(SMBcheckpath);
805
806         srvstr_get_path((char *)req->inbuf, req->flags2, name,
807                         smb_buf(req->inbuf) + 1, sizeof(name), 0,
808                         STR_TERMINATE, &status);
809         if (!NT_STATUS_IS_OK(status)) {
810                 status = map_checkpath_error((char *)req->inbuf, status);
811                 reply_nterror(req, status);
812                 END_PROFILE(SMBcheckpath);
813                 return;
814         }
815
816         status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name);
817         if (!NT_STATUS_IS_OK(status)) {
818                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
819                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
820                                         ERRSRV, ERRbadpath);
821                         END_PROFILE(SMBcheckpath);
822                         return;
823                 }
824                 goto path_err;
825         }
826
827         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
828
829         status = unix_convert(conn, name, False, NULL, &sbuf);
830         if (!NT_STATUS_IS_OK(status)) {
831                 goto path_err;
832         }
833
834         status = check_name(conn, name);
835         if (!NT_STATUS_IS_OK(status)) {
836                 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
837                 goto path_err;
838         }
839
840         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
841                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
842                 status = map_nt_error_from_unix(errno);
843                 goto path_err;
844         }
845
846         if (!S_ISDIR(sbuf.st_mode)) {
847                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
848                                 ERRDOS, ERRbadpath);
849                 END_PROFILE(SMBcheckpath);
850                 return;
851         }
852
853         reply_outbuf(req, 0, 0);
854
855         END_PROFILE(SMBcheckpath);
856         return;
857
858   path_err:
859
860         END_PROFILE(SMBcheckpath);
861
862         /* We special case this - as when a Windows machine
863                 is parsing a path is steps through the components
864                 one at a time - if a component fails it expects
865                 ERRbadpath, not ERRbadfile.
866         */
867         status = map_checkpath_error((char *)req->inbuf, status);
868         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
869                 /*
870                  * Windows returns different error codes if
871                  * the parent directory is valid but not the
872                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
873                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
874                  * if the path is invalid.
875                  */
876                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
877                                 ERRDOS, ERRbadpath);
878                 return;
879         }
880
881         reply_nterror(req, status);
882 }
883
884 /****************************************************************************
885  Reply to a getatr.
886 ****************************************************************************/
887
888 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
889 {
890         pstring fname;
891         int outsize = 0;
892         SMB_STRUCT_STAT sbuf;
893         int mode=0;
894         SMB_OFF_T size=0;
895         time_t mtime=0;
896         char *p;
897         NTSTATUS status;
898
899         START_PROFILE(SMBgetatr);
900
901         p = smb_buf(inbuf) + 1;
902         p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
903                              sizeof(fname), 0, STR_TERMINATE, &status);
904         if (!NT_STATUS_IS_OK(status)) {
905                 END_PROFILE(SMBgetatr);
906                 return ERROR_NT(status);
907         }
908
909         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
910         if (!NT_STATUS_IS_OK(status)) {
911                 END_PROFILE(SMBgetatr);
912                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
913                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
914                 }
915                 return ERROR_NT(status);
916         }
917   
918         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
919                 under WfWg - weird! */
920         if (*fname == '\0') {
921                 mode = aHIDDEN | aDIR;
922                 if (!CAN_WRITE(conn)) {
923                         mode |= aRONLY;
924                 }
925                 size = 0;
926                 mtime = 0;
927         } else {
928                 status = unix_convert(conn, fname, False, NULL,&sbuf);
929                 if (!NT_STATUS_IS_OK(status)) {
930                         END_PROFILE(SMBgetatr);
931                         return ERROR_NT(status);
932                 }
933                 status = check_name(conn, fname);
934                 if (!NT_STATUS_IS_OK(status)) {
935                         DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
936                         END_PROFILE(SMBgetatr);
937                         return ERROR_NT(status);
938                 }
939                 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
940                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
941                         return UNIXERROR(ERRDOS,ERRbadfile);
942                 }
943
944                 mode = dos_mode(conn,fname,&sbuf);
945                 size = sbuf.st_size;
946                 mtime = sbuf.st_mtime;
947                 if (mode & aDIR) {
948                         size = 0;
949                 }
950         }
951   
952         outsize = set_message(inbuf,outbuf,10,0,True);
953
954         SSVAL(outbuf,smb_vwv0,mode);
955         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
956                 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
957         } else {
958                 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
959         }
960         SIVAL(outbuf,smb_vwv3,(uint32)size);
961
962         if (Protocol >= PROTOCOL_NT1) {
963                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
964         }
965   
966         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
967   
968         END_PROFILE(SMBgetatr);
969         return(outsize);
970 }
971
972 /****************************************************************************
973  Reply to a setatr.
974 ****************************************************************************/
975
976 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
977 {
978         pstring fname;
979         int outsize = 0;
980         int mode;
981         time_t mtime;
982         SMB_STRUCT_STAT sbuf;
983         char *p;
984         NTSTATUS status;
985
986         START_PROFILE(SMBsetatr);
987
988         p = smb_buf(inbuf) + 1;
989         p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
990                              sizeof(fname), 0, STR_TERMINATE, &status);
991         if (!NT_STATUS_IS_OK(status)) {
992                 END_PROFILE(SMBsetatr);
993                 return ERROR_NT(status);
994         }
995
996         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
997         if (!NT_STATUS_IS_OK(status)) {
998                 END_PROFILE(SMBsetatr);
999                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1000                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1001                 }
1002                 return ERROR_NT(status);
1003         }
1004   
1005         status = unix_convert(conn, fname, False, NULL, &sbuf);
1006         if (!NT_STATUS_IS_OK(status)) {
1007                 END_PROFILE(SMBsetatr);
1008                 return ERROR_NT(status);
1009         }
1010
1011         status = check_name(conn, fname);
1012         if (!NT_STATUS_IS_OK(status)) {
1013                 END_PROFILE(SMBsetatr);
1014                 return ERROR_NT(status);
1015         }
1016
1017         if (fname[0] == '.' && fname[1] == '\0') {
1018                 /*
1019                  * Not sure here is the right place to catch this
1020                  * condition. Might be moved to somewhere else later -- vl
1021                  */
1022                 END_PROFILE(SMBsetatr);
1023                 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
1024         }
1025
1026         mode = SVAL(inbuf,smb_vwv0);
1027         mtime = srv_make_unix_date3(inbuf+smb_vwv1);
1028   
1029         if (mode != FILE_ATTRIBUTE_NORMAL) {
1030                 if (VALID_STAT_OF_DIR(sbuf))
1031                         mode |= aDIR;
1032                 else
1033                         mode &= ~aDIR;
1034
1035                 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
1036                         END_PROFILE(SMBsetatr);
1037                         return UNIXERROR(ERRDOS, ERRnoaccess);
1038                 }
1039         }
1040
1041         if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
1042                 END_PROFILE(SMBsetatr);
1043                 return UNIXERROR(ERRDOS, ERRnoaccess);
1044         }
1045  
1046         outsize = set_message(inbuf,outbuf,0,0,False);
1047   
1048         DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1049   
1050         END_PROFILE(SMBsetatr);
1051         return(outsize);
1052 }
1053
1054 /****************************************************************************
1055  Reply to a dskattr.
1056 ****************************************************************************/
1057
1058 void reply_dskattr(connection_struct *conn, struct smb_request *req)
1059 {
1060         SMB_BIG_UINT dfree,dsize,bsize;
1061         START_PROFILE(SMBdskattr);
1062
1063         if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1064                 reply_unixerror(req, ERRHRD, ERRgeneral);
1065                 END_PROFILE(SMBdskattr);
1066                 return;
1067         }
1068
1069         reply_outbuf(req, 5, 0);
1070         
1071         if (Protocol <= PROTOCOL_LANMAN2) {
1072                 double total_space, free_space;
1073                 /* we need to scale this to a number that DOS6 can handle. We
1074                    use floating point so we can handle large drives on systems
1075                    that don't have 64 bit integers 
1076
1077                    we end up displaying a maximum of 2G to DOS systems
1078                 */
1079                 total_space = dsize * (double)bsize;
1080                 free_space = dfree * (double)bsize;
1081
1082                 dsize = (total_space+63*512) / (64*512);
1083                 dfree = (free_space+63*512) / (64*512);
1084                 
1085                 if (dsize > 0xFFFF) dsize = 0xFFFF;
1086                 if (dfree > 0xFFFF) dfree = 0xFFFF;
1087
1088                 SSVAL(req->outbuf,smb_vwv0,dsize);
1089                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1090                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1091                 SSVAL(req->outbuf,smb_vwv3,dfree);
1092         } else {
1093                 SSVAL(req->outbuf,smb_vwv0,dsize);
1094                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1095                 SSVAL(req->outbuf,smb_vwv2,512);
1096                 SSVAL(req->outbuf,smb_vwv3,dfree);
1097         }
1098
1099         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1100
1101         END_PROFILE(SMBdskattr);
1102         return;
1103 }
1104
1105 /****************************************************************************
1106  Reply to a search.
1107  Can be called from SMBsearch, SMBffirst or SMBfunique.
1108 ****************************************************************************/
1109
1110 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1111 {
1112         pstring mask;
1113         pstring directory;
1114         pstring fname;
1115         SMB_OFF_T size;
1116         uint32 mode;
1117         time_t date;
1118         uint32 dirtype;
1119         int outsize = 0;
1120         unsigned int numentries = 0;
1121         unsigned int maxentries = 0;
1122         BOOL finished = False;
1123         char *p;
1124         int status_len;
1125         pstring path;
1126         char status[21];
1127         int dptr_num= -1;
1128         BOOL check_descend = False;
1129         BOOL expect_close = False;
1130         NTSTATUS nt_status;
1131         BOOL mask_contains_wcard = False;
1132         BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1133
1134         START_PROFILE(SMBsearch);
1135
1136         if (lp_posix_pathnames()) {
1137                 END_PROFILE(SMBsearch);
1138                 return reply_unknown(inbuf, outbuf);
1139         }
1140
1141         *mask = *directory = *fname = 0;
1142
1143         /* If we were called as SMBffirst then we must expect close. */
1144         if(CVAL(inbuf,smb_com) == SMBffirst) {
1145                 expect_close = True;
1146         }
1147   
1148         outsize = set_message(inbuf,outbuf,1,3,True);
1149         maxentries = SVAL(inbuf,smb_vwv0); 
1150         dirtype = SVAL(inbuf,smb_vwv1);
1151         p = smb_buf(inbuf) + 1;
1152         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1153                                    sizeof(path), 0, STR_TERMINATE, &nt_status,
1154                                    &mask_contains_wcard);
1155         if (!NT_STATUS_IS_OK(nt_status)) {
1156                 END_PROFILE(SMBsearch);
1157                 return ERROR_NT(nt_status);
1158         }
1159
1160         nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
1161         if (!NT_STATUS_IS_OK(nt_status)) {
1162                 END_PROFILE(SMBsearch);
1163                 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1164                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1165                 }
1166                 return ERROR_NT(nt_status);
1167         }
1168   
1169         p++;
1170         status_len = SVAL(p, 0);
1171         p += 2;
1172   
1173         /* dirtype &= ~aDIR; */
1174
1175         if (status_len == 0) {
1176                 SMB_STRUCT_STAT sbuf;
1177
1178                 pstrcpy(directory,path);
1179                 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1180                 if (!NT_STATUS_IS_OK(nt_status)) {
1181                         END_PROFILE(SMBsearch);
1182                         return ERROR_NT(nt_status);
1183                 }
1184
1185                 nt_status = check_name(conn, directory);
1186                 if (!NT_STATUS_IS_OK(nt_status)) {
1187                         END_PROFILE(SMBsearch);
1188                         return ERROR_NT(nt_status);
1189                 }
1190
1191                 p = strrchr_m(directory,'/');
1192                 if (!p) {
1193                         pstrcpy(mask,directory);
1194                         pstrcpy(directory,".");
1195                 } else {
1196                         *p = 0;
1197                         pstrcpy(mask,p+1);
1198                 }
1199
1200                 if (*directory == '\0') {
1201                         pstrcpy(directory,".");
1202                 }
1203                 memset((char *)status,'\0',21);
1204                 SCVAL(status,0,(dirtype & 0x1F));
1205         } else {
1206                 int status_dirtype;
1207
1208                 memcpy(status,p,21);
1209                 status_dirtype = CVAL(status,0) & 0x1F;
1210                 if (status_dirtype != (dirtype & 0x1F)) {
1211                         dirtype = status_dirtype;
1212                 }
1213
1214                 conn->dirptr = dptr_fetch(status+12,&dptr_num);      
1215                 if (!conn->dirptr) {
1216                         goto SearchEmpty;
1217                 }
1218                 string_set(&conn->dirpath,dptr_path(dptr_num));
1219                 pstrcpy(mask, dptr_wcard(dptr_num));
1220                 /*
1221                  * For a 'continue' search we have no string. So
1222                  * check from the initial saved string.
1223                  */
1224                 mask_contains_wcard = ms_has_wild(mask);
1225         }
1226
1227         p = smb_buf(outbuf) + 3;
1228      
1229         if (status_len == 0) {
1230                 nt_status = dptr_create(conn,
1231                                         directory,
1232                                         True,
1233                                         expect_close,
1234                                         SVAL(inbuf,smb_pid),
1235                                         mask,
1236                                         mask_contains_wcard,
1237                                         dirtype,
1238                                         &conn->dirptr);
1239                 if (!NT_STATUS_IS_OK(nt_status)) {
1240                         return ERROR_NT(nt_status);
1241                 }
1242                 dptr_num = dptr_dnum(conn->dirptr);
1243         } else {
1244                 dirtype = dptr_attr(dptr_num);
1245         }
1246
1247         DEBUG(4,("dptr_num is %d\n",dptr_num));
1248
1249         if ((dirtype&0x1F) == aVOLID) {   
1250                 memcpy(p,status,21);
1251                 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1252                                 0,aVOLID,0,!allow_long_path_components);
1253                 dptr_fill(p+12,dptr_num);
1254                 if (dptr_zero(p+12) && (status_len==0)) {
1255                         numentries = 1;
1256                 } else {
1257                         numentries = 0;
1258                 }
1259                 p += DIR_STRUCT_SIZE;
1260         } else {
1261                 unsigned int i;
1262                 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1263
1264                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1265                         conn->dirpath,lp_dontdescend(SNUM(conn))));
1266                 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1267                         check_descend = True;
1268                 }
1269
1270                 for (i=numentries;(i<maxentries) && !finished;i++) {
1271                         finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1272                         if (!finished) {
1273                                 memcpy(p,status,21);
1274                                 make_dir_struct(p,mask,fname,size, mode,date,
1275                                                 !allow_long_path_components);
1276                                 if (!dptr_fill(p+12,dptr_num)) {
1277                                         break;
1278                                 }
1279                                 numentries++;
1280                                 p += DIR_STRUCT_SIZE;
1281                         }
1282                 }
1283         }
1284
1285   SearchEmpty:
1286
1287         /* If we were called as SMBffirst with smb_search_id == NULL
1288                 and no entries were found then return error and close dirptr 
1289                 (X/Open spec) */
1290
1291         if (numentries == 0) {
1292                 dptr_close(&dptr_num);
1293         } else if(expect_close && status_len == 0) {
1294                 /* Close the dptr - we know it's gone */
1295                 dptr_close(&dptr_num);
1296         }
1297
1298         /* If we were called as SMBfunique, then we can close the dirptr now ! */
1299         if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1300                 dptr_close(&dptr_num);
1301         }
1302
1303         if ((numentries == 0) && !mask_contains_wcard) {
1304                 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1305         }
1306
1307         SSVAL(outbuf,smb_vwv0,numentries);
1308         SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1309         SCVAL(smb_buf(outbuf),0,5);
1310         SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1311
1312         /* The replies here are never long name. */
1313         SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1314         if (!allow_long_path_components) {
1315                 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1316         }
1317
1318         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1319         SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1320           
1321         outsize += DIR_STRUCT_SIZE*numentries;
1322         smb_setlen(inbuf,outbuf,outsize - 4);
1323   
1324         if ((! *directory) && dptr_path(dptr_num))
1325                 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1326
1327         DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1328                 smb_fn_name(CVAL(inbuf,smb_com)), 
1329                 mask, directory, dirtype, numentries, maxentries ) );
1330
1331         END_PROFILE(SMBsearch);
1332         return(outsize);
1333 }
1334
1335 /****************************************************************************
1336  Reply to a fclose (stop directory search).
1337 ****************************************************************************/
1338
1339 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1340 {
1341         int outsize = 0;
1342         int status_len;
1343         pstring path;
1344         char status[21];
1345         int dptr_num= -2;
1346         char *p;
1347         NTSTATUS err;
1348         BOOL path_contains_wcard = False;
1349
1350         START_PROFILE(SMBfclose);
1351
1352         if (lp_posix_pathnames()) {
1353                 END_PROFILE(SMBfclose);
1354                 return reply_unknown(inbuf, outbuf);
1355         }
1356
1357         outsize = set_message(inbuf,outbuf,1,0,True);
1358         p = smb_buf(inbuf) + 1;
1359         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1360                                    sizeof(path), 0, STR_TERMINATE, &err,
1361                                    &path_contains_wcard);
1362         if (!NT_STATUS_IS_OK(err)) {
1363                 END_PROFILE(SMBfclose);
1364                 return ERROR_NT(err);
1365         }
1366         p++;
1367         status_len = SVAL(p,0);
1368         p += 2;
1369
1370         if (status_len == 0) {
1371                 END_PROFILE(SMBfclose);
1372                 return ERROR_DOS(ERRSRV,ERRsrverror);
1373         }
1374
1375         memcpy(status,p,21);
1376
1377         if(dptr_fetch(status+12,&dptr_num)) {
1378                 /*  Close the dptr - we know it's gone */
1379                 dptr_close(&dptr_num);
1380         }
1381
1382         SSVAL(outbuf,smb_vwv0,0);
1383
1384         DEBUG(3,("search close\n"));
1385
1386         END_PROFILE(SMBfclose);
1387         return(outsize);
1388 }
1389
1390 /****************************************************************************
1391  Reply to an open.
1392 ****************************************************************************/
1393
1394 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1395 {
1396         pstring fname;
1397         int outsize = 0;
1398         uint32 fattr=0;
1399         SMB_OFF_T size = 0;
1400         time_t mtime=0;
1401         int info;
1402         SMB_STRUCT_STAT sbuf;
1403         files_struct *fsp;
1404         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1405         int deny_mode;
1406         uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1407         uint32 access_mask;
1408         uint32 share_mode;
1409         uint32 create_disposition;
1410         uint32 create_options = 0;
1411         NTSTATUS status;
1412         struct smb_request req;
1413
1414         START_PROFILE(SMBopen);
1415
1416         init_smb_request(&req, (uint8 *)inbuf);
1417  
1418         deny_mode = SVAL(inbuf,smb_vwv0);
1419
1420         srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1421                         sizeof(fname), 0, STR_TERMINATE, &status);
1422         if (!NT_STATUS_IS_OK(status)) {
1423                 END_PROFILE(SMBopen);
1424                 return ERROR_NT(status);
1425         }
1426
1427         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1428         if (!NT_STATUS_IS_OK(status)) {
1429                 END_PROFILE(SMBopen);
1430                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1431                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1432                 }
1433                 return ERROR_NT(status);
1434         }
1435
1436         status = unix_convert(conn, fname, False, NULL, &sbuf);
1437         if (!NT_STATUS_IS_OK(status)) {
1438                 END_PROFILE(SMBopen);
1439                 return ERROR_NT(status);
1440         }
1441     
1442         status = check_name(conn, fname);
1443         if (!NT_STATUS_IS_OK(status)) {
1444                 END_PROFILE(SMBopen);
1445                 return ERROR_NT(status);
1446         }
1447
1448         if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1449                         &access_mask, &share_mode, &create_disposition, &create_options)) {
1450                 END_PROFILE(SMBopen);
1451                 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1452         }
1453
1454         status = open_file_ntcreate(conn, &req, fname, &sbuf,
1455                         access_mask,
1456                         share_mode,
1457                         create_disposition,
1458                         create_options,
1459                         dos_attr,
1460                         oplock_request,
1461                         &info, &fsp);
1462
1463         if (!NT_STATUS_IS_OK(status)) {
1464                 END_PROFILE(SMBopen);
1465                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1466                         /* We have re-scheduled this call. */
1467                         return -1;
1468                 }
1469                 return ERROR_NT(status);
1470         }
1471
1472         size = sbuf.st_size;
1473         fattr = dos_mode(conn,fname,&sbuf);
1474         mtime = sbuf.st_mtime;
1475
1476         if (fattr & aDIR) {
1477                 DEBUG(3,("attempt to open a directory %s\n",fname));
1478                 close_file(fsp,ERROR_CLOSE);
1479                 END_PROFILE(SMBopen);
1480                 return ERROR_DOS(ERRDOS,ERRnoaccess);
1481         }
1482   
1483         outsize = set_message(inbuf,outbuf,7,0,True);
1484         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1485         SSVAL(outbuf,smb_vwv1,fattr);
1486         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1487                 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1488         } else {
1489                 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1490         }
1491         SIVAL(outbuf,smb_vwv4,(uint32)size);
1492         SSVAL(outbuf,smb_vwv6,deny_mode);
1493
1494         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1495                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1496         }
1497     
1498         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1499                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1500         }
1501         END_PROFILE(SMBopen);
1502         return(outsize);
1503 }
1504
1505 /****************************************************************************
1506  Reply to an open and X.
1507 ****************************************************************************/
1508
1509 void reply_open_and_X(connection_struct *conn, struct smb_request *req)
1510 {
1511         pstring fname;
1512         uint16 open_flags;
1513         int deny_mode;
1514         uint32 smb_attr;
1515         /* Breakout the oplock request bits so we can set the
1516                 reply bits separately. */
1517         int ex_oplock_request;
1518         int core_oplock_request;
1519         int oplock_request;
1520 #if 0
1521         int smb_sattr = SVAL(req->inbuf,smb_vwv4);
1522         uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
1523 #endif
1524         int smb_ofun;
1525         uint32 fattr=0;
1526         int mtime=0;
1527         SMB_STRUCT_STAT sbuf;
1528         int smb_action = 0;
1529         files_struct *fsp;
1530         NTSTATUS status;
1531         SMB_BIG_UINT allocation_size;
1532         ssize_t retval = -1;
1533         uint32 access_mask;
1534         uint32 share_mode;
1535         uint32 create_disposition;
1536         uint32 create_options = 0;
1537
1538         START_PROFILE(SMBopenX);
1539
1540         if (req->wct < 15) {
1541                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1542                 END_PROFILE(SMBopenX);
1543                 return;
1544         }
1545
1546         open_flags = SVAL(req->inbuf,smb_vwv2);
1547         deny_mode = SVAL(req->inbuf,smb_vwv3);
1548         smb_attr = SVAL(req->inbuf,smb_vwv5);
1549         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1550         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1551         oplock_request = ex_oplock_request | core_oplock_request;
1552         smb_ofun = SVAL(req->inbuf,smb_vwv8);
1553         allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
1554
1555         /* If it's an IPC, pass off the pipe handler. */
1556         if (IS_IPC(conn)) {
1557                 if (lp_nt_pipe_support()) {
1558                         reply_open_pipe_and_X(conn, req);
1559                 } else {
1560                         reply_doserror(req, ERRSRV, ERRaccess);
1561                 }
1562                 END_PROFILE(SMBopenX);
1563                 return;
1564         }
1565
1566         /* XXXX we need to handle passed times, sattr and flags */
1567         srvstr_get_path((char *)req->inbuf, req->flags2, fname,
1568                         smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE,
1569                         &status);
1570         if (!NT_STATUS_IS_OK(status)) {
1571                 reply_nterror(req, status);
1572                 END_PROFILE(SMBopenX);
1573                 return;
1574         }
1575
1576         status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1577                                  fname);
1578         if (!NT_STATUS_IS_OK(status)) {
1579                 END_PROFILE(SMBopenX);
1580                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1581                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1582                                         ERRSRV, ERRbadpath);
1583                         return;
1584                 }
1585                 reply_nterror(req, status);
1586                 return;
1587         }
1588
1589         status = unix_convert(conn, fname, False, NULL, &sbuf);
1590         if (!NT_STATUS_IS_OK(status)) {
1591                 reply_nterror(req, status);
1592                 END_PROFILE(SMBopenX);
1593                 return;
1594         }
1595
1596         status = check_name(conn, fname);
1597         if (!NT_STATUS_IS_OK(status)) {
1598                 reply_nterror(req, status);
1599                 END_PROFILE(SMBopenX);
1600                 return;
1601         }
1602
1603         if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1604                                 &access_mask,
1605                                 &share_mode,
1606                                 &create_disposition,
1607                                 &create_options)) {
1608                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1609                 END_PROFILE(SMBopenX);
1610                 return;
1611         }
1612
1613         status = open_file_ntcreate(conn, req, fname, &sbuf,
1614                         access_mask,
1615                         share_mode,
1616                         create_disposition,
1617                         create_options,
1618                         smb_attr,
1619                         oplock_request,
1620                         &smb_action, &fsp);
1621       
1622         if (!NT_STATUS_IS_OK(status)) {
1623                 END_PROFILE(SMBopenX);
1624                 if (open_was_deferred(req->mid)) {
1625                         /* We have re-scheduled this call. */
1626                         return;
1627                 }
1628                 reply_nterror(req, status);
1629                 return;
1630         }
1631
1632         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1633            if the file is truncated or created. */
1634         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1635                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1636                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1637                         close_file(fsp,ERROR_CLOSE);
1638                         reply_nterror(req, NT_STATUS_DISK_FULL);
1639                         END_PROFILE(SMBopenX);
1640                         return;
1641                 }
1642                 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1643                 if (retval < 0) {
1644                         close_file(fsp,ERROR_CLOSE);
1645                         reply_nterror(req, NT_STATUS_DISK_FULL);
1646                         END_PROFILE(SMBopenX);
1647                         return;
1648                 }
1649                 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1650         }
1651
1652         fattr = dos_mode(conn,fname,&sbuf);
1653         mtime = sbuf.st_mtime;
1654         if (fattr & aDIR) {
1655                 close_file(fsp,ERROR_CLOSE);
1656                 reply_doserror(req, ERRDOS, ERRnoaccess);
1657                 END_PROFILE(SMBopenX);
1658                 return;
1659         }
1660
1661         /* If the caller set the extended oplock request bit
1662                 and we granted one (by whatever means) - set the
1663                 correct bit for extended oplock reply.
1664         */
1665
1666         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1667                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1668         }
1669
1670         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1671                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1672         }
1673
1674         /* If the caller set the core oplock request bit
1675                 and we granted one (by whatever means) - set the
1676                 correct bit for core oplock reply.
1677         */
1678
1679         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1680                 reply_outbuf(req, 19, 0);
1681         } else {
1682                 reply_outbuf(req, 15, 0);
1683         }
1684
1685         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1686                 SCVAL(req->outbuf, smb_flg,
1687                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1688         }
1689
1690         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1691                 SCVAL(req->outbuf, smb_flg,
1692                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1693         }
1694
1695         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1696         SSVAL(req->outbuf,smb_vwv3,fattr);
1697         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1698                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1699         } else {
1700                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1701         }
1702         SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1703         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1704         SSVAL(req->outbuf,smb_vwv11,smb_action);
1705
1706         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1707                 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1708         }
1709
1710         END_PROFILE(SMBopenX);
1711         chain_reply_new(req);
1712         return;
1713 }
1714
1715 /****************************************************************************
1716  Reply to a SMBulogoffX.
1717  conn POINTER CAN BE NULL HERE !
1718 ****************************************************************************/
1719
1720 void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
1721 {
1722         user_struct *vuser;
1723
1724         START_PROFILE(SMBulogoffX);
1725
1726         vuser = get_valid_user_struct(req->vuid);
1727
1728         if(vuser == NULL) {
1729                 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1730                          req->vuid));
1731         }
1732
1733         /* in user level security we are supposed to close any files
1734                 open by this user */
1735         if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1736                 file_close_user(req->vuid);
1737         }
1738
1739         invalidate_vuid(req->vuid);
1740
1741         reply_outbuf(req, 2, 0);
1742
1743         DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1744
1745         END_PROFILE(SMBulogoffX);
1746         chain_reply_new(req);
1747 }
1748
1749 /****************************************************************************
1750  Reply to a mknew or a create.
1751 ****************************************************************************/
1752
1753 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1754 {
1755         pstring fname;
1756         int com;
1757         int outsize = 0;
1758         uint32 fattr = SVAL(inbuf,smb_vwv0);
1759         struct timespec ts[2];
1760         files_struct *fsp;
1761         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1762         SMB_STRUCT_STAT sbuf;
1763         NTSTATUS status;
1764         uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1765         uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1766         uint32 create_disposition;
1767         uint32 create_options = 0;
1768         struct smb_request req;
1769
1770         START_PROFILE(SMBcreate);
1771
1772         init_smb_request(&req, (uint8 *)inbuf);
1773  
1774         com = SVAL(inbuf,smb_com);
1775
1776         ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1777
1778         srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1,
1779                         sizeof(fname), 0, STR_TERMINATE, &status);
1780         if (!NT_STATUS_IS_OK(status)) {
1781                 END_PROFILE(SMBcreate);
1782                 return ERROR_NT(status);
1783         }
1784
1785         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1786         if (!NT_STATUS_IS_OK(status)) {
1787                 END_PROFILE(SMBcreate);
1788                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1789                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1790                 }
1791                 return ERROR_NT(status);
1792         }
1793
1794         status = unix_convert(conn, fname, False, NULL, &sbuf);
1795         if (!NT_STATUS_IS_OK(status)) {
1796                 END_PROFILE(SMBcreate);
1797                 return ERROR_NT(status);
1798         }
1799
1800         status = check_name(conn, fname);
1801         if (!NT_STATUS_IS_OK(status)) {
1802                 END_PROFILE(SMBcreate);
1803                 return ERROR_NT(status);
1804         }
1805
1806         if (fattr & aVOLID) {
1807                 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1808         }
1809
1810         if(com == SMBmknew) {
1811                 /* We should fail if file exists. */
1812                 create_disposition = FILE_CREATE;
1813         } else {
1814                 /* Create if file doesn't exist, truncate if it does. */
1815                 create_disposition = FILE_OVERWRITE_IF;
1816         }
1817
1818         /* Open file using ntcreate. */
1819         status = open_file_ntcreate(conn, &req, fname, &sbuf,
1820                                 access_mask,
1821                                 share_mode,
1822                                 create_disposition,
1823                                 create_options,
1824                                 fattr,
1825                                 oplock_request,
1826                                 NULL, &fsp);
1827   
1828         if (!NT_STATUS_IS_OK(status)) {
1829                 END_PROFILE(SMBcreate);
1830                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1831                         /* We have re-scheduled this call. */
1832                         return -1;
1833                 }
1834                 return ERROR_NT(status);
1835         }
1836  
1837         ts[0] = get_atimespec(&sbuf); /* atime. */
1838         file_ntimes(conn, fname, ts);
1839
1840         outsize = set_message(inbuf,outbuf,1,0,True);
1841         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1842
1843         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1844                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1845         }
1846  
1847         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1848                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1849         }
1850  
1851         DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1852         DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1853
1854         END_PROFILE(SMBcreate);
1855         return(outsize);
1856 }
1857
1858 /****************************************************************************
1859  Reply to a create temporary file.
1860 ****************************************************************************/
1861
1862 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1863 {
1864         pstring fname;
1865         int outsize = 0;
1866         uint32 fattr = SVAL(inbuf,smb_vwv0);
1867         files_struct *fsp;
1868         int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1869         int tmpfd;
1870         SMB_STRUCT_STAT sbuf;
1871         char *p, *s;
1872         NTSTATUS status;
1873         unsigned int namelen;
1874         struct smb_request req;
1875
1876         START_PROFILE(SMBctemp);
1877
1878         init_smb_request(&req, (uint8 *)inbuf);
1879
1880         srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1881                         sizeof(fname), 0, STR_TERMINATE, &status);
1882         if (!NT_STATUS_IS_OK(status)) {
1883                 END_PROFILE(SMBctemp);
1884                 return ERROR_NT(status);
1885         }
1886         if (*fname) {
1887                 pstrcat(fname,"/TMXXXXXX");
1888         } else {
1889                 pstrcat(fname,"TMXXXXXX");
1890         }
1891
1892         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1893         if (!NT_STATUS_IS_OK(status)) {
1894                 END_PROFILE(SMBctemp);
1895                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1896                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1897                 }
1898                 return ERROR_NT(status);
1899         }
1900
1901         status = unix_convert(conn, fname, False, NULL, &sbuf);
1902         if (!NT_STATUS_IS_OK(status)) {
1903                 END_PROFILE(SMBctemp);
1904                 return ERROR_NT(status);
1905         }
1906
1907         status = check_name(conn, fname);
1908         if (!NT_STATUS_IS_OK(status)) {
1909                 END_PROFILE(SMBctemp);
1910                 return ERROR_NT(status);
1911         }
1912   
1913         tmpfd = smb_mkstemp(fname);
1914         if (tmpfd == -1) {
1915                 END_PROFILE(SMBctemp);
1916                 return(UNIXERROR(ERRDOS,ERRnoaccess));
1917         }
1918
1919         SMB_VFS_STAT(conn,fname,&sbuf);
1920
1921         /* We should fail if file does not exist. */
1922         status = open_file_ntcreate(conn, &req, fname, &sbuf,
1923                                 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1924                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
1925                                 FILE_OPEN,
1926                                 0,
1927                                 fattr,
1928                                 oplock_request,
1929                                 NULL, &fsp);
1930
1931         /* close fd from smb_mkstemp() */
1932         close(tmpfd);
1933
1934         if (!NT_STATUS_IS_OK(status)) {
1935                 END_PROFILE(SMBctemp);
1936                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1937                         /* We have re-scheduled this call. */
1938                         return -1;
1939                 }
1940                 return ERROR_NT(status);
1941         }
1942
1943         outsize = set_message(inbuf,outbuf,1,0,True);
1944         SSVAL(outbuf,smb_vwv0,fsp->fnum);
1945
1946         /* the returned filename is relative to the directory */
1947         s = strrchr_m(fname, '/');
1948         if (!s) {
1949                 s = fname;
1950         } else {
1951                 s++;
1952         }
1953
1954         p = smb_buf(outbuf);
1955 #if 0
1956         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1957            thing in the byte section. JRA */
1958         SSVALS(p, 0, -1); /* what is this? not in spec */
1959 #endif
1960         namelen = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, s, -1,
1961                               STR_ASCII|STR_TERMINATE);
1962         p += namelen;
1963         outsize = set_message_end(inbuf,outbuf, p);
1964
1965         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1966                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1967         }
1968   
1969         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1970                 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1971         }
1972
1973         DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1974         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1975                         (unsigned int)sbuf.st_mode ) );
1976
1977         END_PROFILE(SMBctemp);
1978         return(outsize);
1979 }
1980
1981 /*******************************************************************
1982  Check if a user is allowed to rename a file.
1983 ********************************************************************/
1984
1985 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1986                            uint16 dirtype, SMB_STRUCT_STAT *pst)
1987 {
1988         uint32 fmode;
1989
1990         if (!CAN_WRITE(conn)) {
1991                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1992         }
1993
1994         fmode = dos_mode(conn, fsp->fsp_name, pst);
1995         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1996                 return NT_STATUS_NO_SUCH_FILE;
1997         }
1998
1999         if (S_ISDIR(pst->st_mode)) {
2000                 return NT_STATUS_OK;
2001         }
2002
2003         if (fsp->access_mask & DELETE_ACCESS) {
2004                 return NT_STATUS_OK;
2005         }
2006
2007         return NT_STATUS_ACCESS_DENIED;
2008 }
2009
2010 /*******************************************************************
2011  * unlink a file with all relevant access checks
2012  *******************************************************************/
2013
2014 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
2015                           char *fname, uint32 dirtype)
2016 {
2017         SMB_STRUCT_STAT sbuf;
2018         uint32 fattr;
2019         files_struct *fsp;
2020         uint32 dirtype_orig = dirtype;
2021         NTSTATUS status;
2022
2023         DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2024
2025         if (!CAN_WRITE(conn)) {
2026                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2027         }
2028
2029         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2030                 return map_nt_error_from_unix(errno);
2031         }
2032
2033         fattr = dos_mode(conn,fname,&sbuf);
2034
2035         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2036                 dirtype = aDIR|aARCH|aRONLY;
2037         }
2038
2039         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2040         if (!dirtype) {
2041                 return NT_STATUS_NO_SUCH_FILE;
2042         }
2043
2044         if (!dir_check_ftype(conn, fattr, dirtype)) {
2045                 if (fattr & aDIR) {
2046                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2047                 }
2048                 return NT_STATUS_NO_SUCH_FILE;
2049         }
2050
2051         if (dirtype_orig & 0x8000) {
2052                 /* These will never be set for POSIX. */
2053                 return NT_STATUS_NO_SUCH_FILE;
2054         }
2055
2056 #if 0
2057         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2058                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2059         }
2060
2061         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2062                 return NT_STATUS_NO_SUCH_FILE;
2063         }
2064
2065         if (dirtype & 0xFF00) {
2066                 /* These will never be set for POSIX. */
2067                 return NT_STATUS_NO_SUCH_FILE;
2068         }
2069
2070         dirtype &= 0xFF;
2071         if (!dirtype) {
2072                 return NT_STATUS_NO_SUCH_FILE;
2073         }
2074
2075         /* Can't delete a directory. */
2076         if (fattr & aDIR) {
2077                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2078         }
2079 #endif
2080
2081 #if 0 /* JRATEST */
2082         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2083                 return NT_STATUS_OBJECT_NAME_INVALID;
2084 #endif /* JRATEST */
2085
2086         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2087
2088           On a Windows share, a file with read-only dosmode can be opened with
2089           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2090           fails with NT_STATUS_CANNOT_DELETE error.
2091
2092           This semantic causes a problem that a user can not
2093           rename a file with read-only dosmode on a Samba share
2094           from a Windows command prompt (i.e. cmd.exe, but can rename
2095           from Windows Explorer).
2096         */
2097
2098         if (!lp_delete_readonly(SNUM(conn))) {
2099                 if (fattr & aRONLY) {
2100                         return NT_STATUS_CANNOT_DELETE;
2101                 }
2102         }
2103
2104         /* On open checks the open itself will check the share mode, so
2105            don't do it here as we'll get it wrong. */
2106
2107         status = open_file_ntcreate(conn, req, fname, &sbuf,
2108                                     DELETE_ACCESS,
2109                                     FILE_SHARE_NONE,
2110                                     FILE_OPEN,
2111                                     0,
2112                                     FILE_ATTRIBUTE_NORMAL,
2113                                     req != NULL ? 0 : INTERNAL_OPEN_ONLY,
2114                                     NULL, &fsp);
2115
2116         if (!NT_STATUS_IS_OK(status)) {
2117                 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2118                            nt_errstr(status)));
2119                 return status;
2120         }
2121
2122         /* The set is across all open files on this dev/inode pair. */
2123         if (!set_delete_on_close(fsp, True, &current_user.ut)) {
2124                 close_file(fsp, NORMAL_CLOSE);
2125                 return NT_STATUS_ACCESS_DENIED;
2126         }
2127
2128         return close_file(fsp,NORMAL_CLOSE);
2129 }
2130
2131 /****************************************************************************
2132  The guts of the unlink command, split out so it may be called by the NT SMB
2133  code.
2134 ****************************************************************************/
2135
2136 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2137                           uint32 dirtype, char *name, BOOL has_wild)
2138 {
2139         pstring directory;
2140         pstring mask;
2141         char *p;
2142         int count=0;
2143         NTSTATUS status = NT_STATUS_OK;
2144         SMB_STRUCT_STAT sbuf;
2145         
2146         *directory = *mask = 0;
2147         
2148         status = unix_convert(conn, name, has_wild, NULL, &sbuf);
2149         if (!NT_STATUS_IS_OK(status)) {
2150                 return status;
2151         }
2152         
2153         p = strrchr_m(name,'/');
2154         if (!p) {
2155                 pstrcpy(directory,".");
2156                 pstrcpy(mask,name);
2157         } else {
2158                 *p = 0;
2159                 pstrcpy(directory,name);
2160                 pstrcpy(mask,p+1);
2161         }
2162         
2163         /*
2164          * We should only check the mangled cache
2165          * here if unix_convert failed. This means
2166          * that the path in 'mask' doesn't exist
2167          * on the file system and so we need to look
2168          * for a possible mangle. This patch from
2169          * Tine Smukavec <valentin.smukavec@hermes.si>.
2170          */
2171         
2172         if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
2173                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
2174         
2175         if (!has_wild) {
2176                 pstrcat(directory,"/");
2177                 pstrcat(directory,mask);
2178                 if (dirtype == 0) {
2179                         dirtype = FILE_ATTRIBUTE_NORMAL;
2180                 }
2181
2182                 status = check_name(conn, directory);
2183                 if (!NT_STATUS_IS_OK(status)) {
2184                         return status;
2185                 }
2186
2187                 status = do_unlink(conn, req, directory, dirtype);
2188                 if (!NT_STATUS_IS_OK(status)) {
2189                         return status;
2190                 }
2191
2192                 count++;
2193         } else {
2194                 struct smb_Dir *dir_hnd = NULL;
2195                 long offset = 0;
2196                 const char *dname;
2197                 
2198                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2199                         return NT_STATUS_OBJECT_NAME_INVALID;
2200                 }
2201
2202                 if (strequal(mask,"????????.???")) {
2203                         pstrcpy(mask,"*");
2204                 }
2205
2206                 status = check_name(conn, directory);
2207                 if (!NT_STATUS_IS_OK(status)) {
2208                         return status;
2209                 }
2210
2211                 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2212                 if (dir_hnd == NULL) {
2213                         return map_nt_error_from_unix(errno);
2214                 }
2215                 
2216                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2217                    the pattern matches against the long name, otherwise the short name 
2218                    We don't implement this yet XXXX
2219                 */
2220                 
2221                 status = NT_STATUS_NO_SUCH_FILE;
2222
2223                 while ((dname = ReadDirName(dir_hnd, &offset))) {
2224                         SMB_STRUCT_STAT st;
2225                         pstring fname;
2226                         pstrcpy(fname,dname);
2227
2228                         if (!is_visible_file(conn, directory, dname, &st, True)) {
2229                                 continue;
2230                         }
2231
2232                         /* Quick check for "." and ".." */
2233                         if (fname[0] == '.') {
2234                                 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2235                                         continue;
2236                                 }
2237                         }
2238
2239                         if(!mask_match(fname, mask, conn->case_sensitive)) {
2240                                 continue;
2241                         }
2242                                 
2243                         slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2244
2245                         status = check_name(conn, fname);
2246                         if (!NT_STATUS_IS_OK(status)) {
2247                                 CloseDir(dir_hnd);
2248                                 return status;
2249                         }
2250
2251                         status = do_unlink(conn, req, fname, dirtype);
2252                         if (!NT_STATUS_IS_OK(status)) {
2253                                 continue;
2254                         }
2255
2256                         count++;
2257                         DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2258                                  fname));
2259                 }
2260                 CloseDir(dir_hnd);
2261         }
2262         
2263         if (count == 0 && NT_STATUS_IS_OK(status)) {
2264                 status = map_nt_error_from_unix(errno);
2265         }
2266
2267         return status;
2268 }
2269
2270 /****************************************************************************
2271  Reply to a unlink
2272 ****************************************************************************/
2273
2274 void reply_unlink(connection_struct *conn, struct smb_request *req)
2275 {
2276         pstring name;
2277         uint32 dirtype;
2278         NTSTATUS status;
2279         BOOL path_contains_wcard = False;
2280
2281         START_PROFILE(SMBunlink);
2282
2283         if (req->wct < 1) {
2284                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2285                 END_PROFILE(SMBunlink);
2286                 return;
2287         }
2288
2289         dirtype = SVAL(req->inbuf,smb_vwv0);
2290         
2291         srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name,
2292                               smb_buf(req->inbuf) + 1, sizeof(name), 0,
2293                               STR_TERMINATE, &status, &path_contains_wcard);
2294         if (!NT_STATUS_IS_OK(status)) {
2295                 reply_nterror(req, status);
2296                 END_PROFILE(SMBunlink);
2297                 return;
2298         }
2299
2300         status = resolve_dfspath_wcard(conn,
2301                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
2302                                        name, &path_contains_wcard);
2303         if (!NT_STATUS_IS_OK(status)) {
2304                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2305                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2306                                         ERRSRV, ERRbadpath);
2307                         END_PROFILE(SMBunlink);
2308                         return;
2309                 }
2310                 reply_nterror(req, status);
2311                 END_PROFILE(SMBunlink);
2312                 return;
2313         }
2314         
2315         DEBUG(3,("reply_unlink : %s\n",name));
2316         
2317         status = unlink_internals(conn, req, dirtype, name,
2318                                   path_contains_wcard);
2319         if (!NT_STATUS_IS_OK(status)) {
2320                 if (open_was_deferred(req->mid)) {
2321                         /* We have re-scheduled this call. */
2322                         END_PROFILE(SMBunlink);
2323                         return;
2324                 }
2325                 reply_nterror(req, status);
2326                 END_PROFILE(SMBunlink);
2327                 return;
2328         }
2329
2330         reply_outbuf(req, 0, 0);
2331         END_PROFILE(SMBunlink);
2332
2333         return;
2334 }
2335
2336 /****************************************************************************
2337  Fail for readbraw.
2338 ****************************************************************************/
2339
2340 static void fail_readraw(void)
2341 {
2342         pstring errstr;
2343         slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2344                 strerror(errno) );
2345         exit_server_cleanly(errstr);
2346 }
2347
2348 /****************************************************************************
2349  Fake (read/write) sendfile. Returns -1 on read or write fail.
2350 ****************************************************************************/
2351
2352 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2353                              size_t nread)
2354 {
2355         size_t bufsize;
2356         size_t tosend = nread;
2357         char *buf;
2358
2359         if (nread == 0) {
2360                 return 0;
2361         }
2362
2363         bufsize = MIN(nread, 65536);
2364
2365         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2366                 return -1;
2367         }
2368
2369         while (tosend > 0) {
2370                 ssize_t ret;
2371                 size_t cur_read;
2372
2373                 if (tosend > bufsize) {
2374                         cur_read = bufsize;
2375                 } else {
2376                         cur_read = tosend;
2377                 }
2378                 ret = read_file(fsp,buf,startpos,cur_read);
2379                 if (ret == -1) {
2380                         SAFE_FREE(buf);
2381                         return -1;
2382                 }
2383
2384                 /* If we had a short read, fill with zeros. */
2385                 if (ret < cur_read) {
2386                         memset(buf, '\0', cur_read - ret);
2387                 }
2388
2389                 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2390                         SAFE_FREE(buf);
2391                         return -1;
2392                 }
2393                 tosend -= cur_read;
2394                 startpos += cur_read;
2395         }
2396
2397         SAFE_FREE(buf);
2398         return (ssize_t)nread;
2399 }
2400
2401 /****************************************************************************
2402  Use sendfile in readbraw.
2403 ****************************************************************************/
2404
2405 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2406                 ssize_t mincount, char *outbuf, int out_buffsize)
2407 {
2408         ssize_t ret=0;
2409
2410 #if defined(WITH_SENDFILE)
2411         /*
2412          * We can only use sendfile on a non-chained packet 
2413          * but we can use on a non-oplocked file. tridge proved this
2414          * on a train in Germany :-). JRA.
2415          * reply_readbraw has already checked the length.
2416          */
2417
2418         if ( (chain_size == 0) && (nread > 0) &&
2419             (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2420                 DATA_BLOB header;
2421
2422                 _smb_setlen(outbuf,nread);
2423                 header.data = (uint8 *)outbuf;
2424                 header.length = 4;
2425                 header.free = NULL;
2426
2427                 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2428                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2429                         if (errno == ENOSYS) {
2430                                 goto normal_readbraw;
2431                         }
2432
2433                         /*
2434                          * Special hack for broken Linux with no working sendfile. If we
2435                          * return EINTR we sent the header but not the rest of the data.
2436                          * Fake this up by doing read/write calls.
2437                          */
2438                         if (errno == EINTR) {
2439                                 /* Ensure we don't do this again. */
2440                                 set_use_sendfile(SNUM(conn), False);
2441                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2442
2443                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
2444                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2445                                                 fsp->fsp_name, strerror(errno) ));
2446                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2447                                 }
2448                                 return;
2449                         }
2450
2451                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2452                                 fsp->fsp_name, strerror(errno) ));
2453                         exit_server_cleanly("send_file_readbraw sendfile failed");
2454                 }
2455
2456                 return;
2457         }
2458 #endif
2459
2460 normal_readbraw:
2461
2462         if (nread > 0) {
2463                 ret = read_file(fsp,outbuf+4,startpos,nread);
2464 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2465                 if (ret < mincount)
2466                         ret = 0;
2467 #else
2468                 if (ret < nread)
2469                         ret = 0;
2470 #endif
2471         }
2472
2473         _smb_setlen(outbuf,ret);
2474         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2475                 fail_readraw();
2476 }
2477
2478 /****************************************************************************
2479  Reply to a readbraw (core+ protocol).
2480 ****************************************************************************/
2481
2482 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2483 {
2484         ssize_t maxcount,mincount;
2485         size_t nread = 0;
2486         SMB_OFF_T startpos;
2487         char *header = outbuf;
2488         files_struct *fsp;
2489         START_PROFILE(SMBreadbraw);
2490
2491         if (srv_is_signing_active()) {
2492                 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2493         }
2494
2495         /*
2496          * Special check if an oplock break has been issued
2497          * and the readraw request croses on the wire, we must
2498          * return a zero length response here.
2499          */
2500
2501         fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2502
2503         if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2504                 /*
2505                  * fsp could be NULL here so use the value from the packet. JRA.
2506                  */
2507                 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2508                 _smb_setlen(header,0);
2509                 if (write_data(smbd_server_fd(),header,4) != 4)
2510                         fail_readraw();
2511                 END_PROFILE(SMBreadbraw);
2512                 return(-1);
2513         }
2514
2515         CHECK_FSP(fsp,conn);
2516
2517         flush_write_cache(fsp, READRAW_FLUSH);
2518
2519         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2520         if(CVAL(inbuf,smb_wct) == 10) {
2521                 /*
2522                  * This is a large offset (64 bit) read.
2523                  */
2524 #ifdef LARGE_SMB_OFF_T
2525
2526                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2527
2528 #else /* !LARGE_SMB_OFF_T */
2529
2530                 /*
2531                  * Ensure we haven't been sent a >32 bit offset.
2532                  */
2533
2534                 if(IVAL(inbuf,smb_vwv8) != 0) {
2535                         DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2536 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2537                         _smb_setlen(header,0);
2538                         if (write_data(smbd_server_fd(),header,4) != 4)
2539                                 fail_readraw();
2540                         END_PROFILE(SMBreadbraw);
2541                         return(-1);
2542                 }
2543
2544 #endif /* LARGE_SMB_OFF_T */
2545
2546                 if(startpos < 0) {
2547                         DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2548                         _smb_setlen(header,0);
2549                         if (write_data(smbd_server_fd(),header,4) != 4)
2550                                 fail_readraw();
2551                         END_PROFILE(SMBreadbraw);
2552                         return(-1);
2553                 }      
2554         }
2555         maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2556         mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2557
2558         /* ensure we don't overrun the packet size */
2559         maxcount = MIN(65535,maxcount);
2560
2561         if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2562                 SMB_STRUCT_STAT st;
2563                 SMB_OFF_T size = 0;
2564   
2565                 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2566                         size = st.st_size;
2567                 }
2568
2569                 if (startpos >= size) {
2570                         nread = 0;
2571                 } else {
2572                         nread = MIN(maxcount,(size - startpos));          
2573                 }
2574         }
2575
2576 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2577         if (nread < mincount)
2578                 nread = 0;
2579 #endif
2580   
2581         DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2582                                 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2583   
2584         send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2585
2586         DEBUG(5,("readbraw finished\n"));
2587         END_PROFILE(SMBreadbraw);
2588         return -1;
2589 }
2590
2591 #undef DBGC_CLASS
2592 #define DBGC_CLASS DBGC_LOCKING
2593
2594 /****************************************************************************
2595  Reply to a lockread (core+ protocol).
2596 ****************************************************************************/
2597
2598 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2599 {
2600         ssize_t nread = -1;
2601         char *data;
2602         int outsize = 0;
2603         SMB_OFF_T startpos;
2604         size_t numtoread;
2605         NTSTATUS status;
2606         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2607         struct byte_range_lock *br_lck = NULL;
2608         START_PROFILE(SMBlockread);
2609
2610         CHECK_FSP(fsp,conn);
2611         if (!CHECK_READ(fsp,inbuf)) {
2612                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2613         }
2614
2615         release_level_2_oplocks_on_change(fsp);
2616
2617         numtoread = SVAL(inbuf,smb_vwv1);
2618         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2619   
2620         outsize = set_message(inbuf,outbuf,5,3,True);
2621         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2622         data = smb_buf(outbuf) + 3;
2623         
2624         /*
2625          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2626          * protocol request that predates the read/write lock concept. 
2627          * Thus instead of asking for a read lock here we need to ask
2628          * for a write lock. JRA.
2629          * Note that the requested lock size is unaffected by max_recv.
2630          */
2631         
2632         br_lck = do_lock(smbd_messaging_context(),
2633                         fsp,
2634                         (uint32)SVAL(inbuf,smb_pid), 
2635                         (SMB_BIG_UINT)numtoread,
2636                         (SMB_BIG_UINT)startpos,
2637                         WRITE_LOCK,
2638                         WINDOWS_LOCK,
2639                         False, /* Non-blocking lock. */
2640                         &status,
2641                         NULL);
2642         TALLOC_FREE(br_lck);
2643
2644         if (NT_STATUS_V(status)) {
2645                 END_PROFILE(SMBlockread);
2646                 return ERROR_NT(status);
2647         }
2648
2649         /*
2650          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2651          */
2652
2653         if (numtoread > max_recv) {
2654                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2655 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2656                         (unsigned int)numtoread, (unsigned int)max_recv ));
2657                 numtoread = MIN(numtoread,max_recv);
2658         }
2659         nread = read_file(fsp,data,startpos,numtoread);
2660
2661         if (nread < 0) {
2662                 END_PROFILE(SMBlockread);
2663                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2664         }
2665         
2666         outsize += nread;
2667         SSVAL(outbuf,smb_vwv0,nread);
2668         SSVAL(outbuf,smb_vwv5,nread+3);
2669         SSVAL(smb_buf(outbuf),1,nread);
2670         
2671         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2672                  fsp->fnum, (int)numtoread, (int)nread));
2673
2674         END_PROFILE(SMBlockread);
2675         return(outsize);
2676 }
2677
2678 #undef DBGC_CLASS
2679 #define DBGC_CLASS DBGC_ALL
2680
2681 /****************************************************************************
2682  Reply to a read.
2683 ****************************************************************************/
2684
2685 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2686 {
2687         size_t numtoread;
2688         ssize_t nread = 0;
2689         char *data;
2690         SMB_OFF_T startpos;
2691         int outsize = 0;
2692         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2693         START_PROFILE(SMBread);
2694
2695         CHECK_FSP(fsp,conn);
2696         if (!CHECK_READ(fsp,inbuf)) {
2697                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2698         }
2699
2700         numtoread = SVAL(inbuf,smb_vwv1);
2701         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2702
2703         outsize = set_message(inbuf,outbuf,5,3,True);
2704         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2705         /*
2706          * The requested read size cannot be greater than max_recv. JRA.
2707          */
2708         if (numtoread > max_recv) {
2709                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2710 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2711                         (unsigned int)numtoread, (unsigned int)max_recv ));
2712                 numtoread = MIN(numtoread,max_recv);
2713         }
2714
2715         data = smb_buf(outbuf) + 3;
2716   
2717         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2718                 END_PROFILE(SMBread);
2719                 return ERROR_DOS(ERRDOS,ERRlock);
2720         }
2721
2722         if (numtoread > 0)
2723                 nread = read_file(fsp,data,startpos,numtoread);
2724
2725         if (nread < 0) {
2726                 END_PROFILE(SMBread);
2727                 return(UNIXERROR(ERRDOS,ERRnoaccess));
2728         }
2729   
2730         outsize += nread;
2731         SSVAL(outbuf,smb_vwv0,nread);
2732         SSVAL(outbuf,smb_vwv5,nread+3);
2733         SCVAL(smb_buf(outbuf),0,1);
2734         SSVAL(smb_buf(outbuf),1,nread);
2735   
2736         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2737                 fsp->fnum, (int)numtoread, (int)nread ) );
2738
2739         END_PROFILE(SMBread);
2740         return(outsize);
2741 }
2742
2743 /****************************************************************************
2744  Setup readX header.
2745 ****************************************************************************/
2746
2747 static int setup_readX_header(const uint8 *inbuf, uint8 *outbuf,
2748                               size_t smb_maxcnt)
2749 {
2750         int outsize;
2751         char *data;
2752
2753         outsize = set_message((char *)inbuf, (char *)outbuf,12,smb_maxcnt,
2754                               False);
2755         data = smb_buf(outbuf);
2756
2757         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2758         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2759         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2760         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2761         SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2762         SCVAL(outbuf,smb_vwv0,0xFF);
2763         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2764         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2765         return outsize;
2766 }
2767
2768 /****************************************************************************
2769  Reply to a read and X - possibly using sendfile.
2770 ****************************************************************************/
2771
2772 static void send_file_readX(connection_struct *conn, struct smb_request *req,
2773                             files_struct *fsp, SMB_OFF_T startpos,
2774                             size_t smb_maxcnt)
2775 {
2776         SMB_STRUCT_STAT sbuf;
2777         ssize_t nread = -1;
2778
2779         if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2780                 reply_unixerror(req, ERRDOS, ERRnoaccess);
2781                 return;
2782         }
2783
2784         if (startpos > sbuf.st_size) {
2785                 smb_maxcnt = 0;
2786         } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
2787                 smb_maxcnt = (sbuf.st_size - startpos);
2788         }
2789
2790         if (smb_maxcnt == 0) {
2791                 goto normal_read;
2792         }
2793
2794 #if defined(WITH_SENDFILE)
2795         /*
2796          * We can only use sendfile on a non-chained packet 
2797          * but we can use on a non-oplocked file. tridge proved this
2798          * on a train in Germany :-). JRA.
2799          */
2800
2801         if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
2802             lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2803                 uint8 headerbuf[smb_size + 12 * 2];
2804                 DATA_BLOB header;
2805
2806                 /* 
2807                  * Set up the packet header before send. We
2808                  * assume here the sendfile will work (get the
2809                  * correct amount of data).
2810                  */
2811
2812                 header = data_blob_const(headerbuf, sizeof(headerbuf));
2813
2814                 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
2815                 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
2816
2817                 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2818                         /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2819                         if (errno == ENOSYS) {
2820                                 goto normal_read;
2821                         }
2822
2823                         /*
2824                          * Special hack for broken Linux with no working sendfile. If we
2825                          * return EINTR we sent the header but not the rest of the data.
2826                          * Fake this up by doing read/write calls.
2827                          */
2828
2829                         if (errno == EINTR) {
2830                                 /* Ensure we don't do this again. */
2831                                 set_use_sendfile(SNUM(conn), False);
2832                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2833                                 nread = fake_sendfile(fsp, startpos,
2834                                                       smb_maxcnt);
2835                                 if (nread == -1) {
2836                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2837                                                 fsp->fsp_name, strerror(errno) ));
2838                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
2839                                 }
2840                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2841                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2842                                 /* No outbuf here means successful sendfile. */
2843                                 TALLOC_FREE(req->outbuf);
2844                                 return;
2845                         }
2846
2847                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2848                                 fsp->fsp_name, strerror(errno) ));
2849                         exit_server_cleanly("send_file_readX sendfile failed");
2850                 }
2851
2852                 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2853                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2854                 /* No outbuf here means successful sendfile. */
2855                 TALLOC_FREE(req->outbuf);
2856                 return;
2857         }
2858
2859 #endif
2860
2861 normal_read:
2862
2863         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
2864                 uint8 headerbuf[smb_size + 2*12];
2865
2866                 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
2867                 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
2868
2869                 /* Send out the header. */
2870                 if (write_data(smbd_server_fd(), (char *)headerbuf,
2871                                sizeof(headerbuf)) != sizeof(headerbuf)) {
2872                         DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2873                                 fsp->fsp_name, strerror(errno) ));
2874                         exit_server_cleanly("send_file_readX sendfile failed");
2875                 }
2876                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
2877                 if (nread == -1) {
2878                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2879                                 fsp->fsp_name, strerror(errno) ));
2880                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
2881                 }
2882                 TALLOC_FREE(req->outbuf);
2883                 return;
2884         } else {
2885                 reply_outbuf(req, 12, smb_maxcnt);
2886
2887                 nread = read_file(fsp, smb_buf(req->outbuf), startpos,
2888                                   smb_maxcnt);
2889                 if (nread < 0) {
2890                         reply_unixerror(req, ERRDOS, ERRnoaccess);
2891                         return;
2892                 }
2893
2894                 setup_readX_header(req->inbuf, req->outbuf, nread);
2895
2896                 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2897                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2898
2899                 chain_reply_new(req);
2900
2901                 return;
2902         }
2903 }
2904
2905 /****************************************************************************
2906  Reply to a read and X.
2907 ****************************************************************************/
2908
2909 void reply_read_and_X(connection_struct *conn, struct smb_request *req)
2910 {
2911         files_struct *fsp;
2912         SMB_OFF_T startpos;
2913         size_t smb_maxcnt;
2914         BOOL big_readX = False;
2915 #if 0
2916         size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
2917 #endif
2918
2919         START_PROFILE(SMBreadX);
2920
2921         if ((req->wct != 10) && (req->wct != 12)) {
2922                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2923                 return;
2924         }
2925
2926         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
2927         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
2928         smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
2929
2930         /* If it's an IPC, pass off the pipe handler. */
2931         if (IS_IPC(conn)) {
2932                 reply_pipe_read_and_X(req);
2933                 END_PROFILE(SMBreadX);
2934                 return;
2935         }
2936
2937         if (!check_fsp(conn, req, fsp, &current_user)) {
2938                 END_PROFILE(SMBreadX);
2939                 return;
2940         }
2941
2942         if (!CHECK_READ(fsp,req->inbuf)) {
2943                 reply_doserror(req, ERRDOS,ERRbadaccess);
2944                 END_PROFILE(SMBreadX);
2945                 return;
2946         }
2947
2948         if (global_client_caps & CAP_LARGE_READX) {
2949                 size_t upper_size = SVAL(req->inbuf,smb_vwv7);
2950                 smb_maxcnt |= (upper_size<<16);
2951                 if (upper_size > 1) {
2952                         /* Can't do this on a chained packet. */
2953                         if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
2954                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
2955                                 END_PROFILE(SMBreadX);
2956                                 return;
2957                         }
2958                         /* We currently don't do this on signed or sealed data. */
2959                         if (srv_is_signing_active() || srv_encryption_on()) {
2960                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
2961                                 END_PROFILE(SMBreadX);
2962                                 return;
2963                         }
2964                         /* Is there room in the reply for this data ? */
2965                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
2966                                 reply_nterror(req,
2967                                               NT_STATUS_INVALID_PARAMETER);
2968                                 END_PROFILE(SMBreadX);
2969                                 return;
2970                         }
2971                         big_readX = True;
2972                 }
2973         }
2974
2975         if (req->wct == 12) {
2976 #ifdef LARGE_SMB_OFF_T
2977                 /*
2978                  * This is a large offset (64 bit) read.
2979                  */
2980                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
2981
2982 #else /* !LARGE_SMB_OFF_T */
2983
2984                 /*
2985                  * Ensure we haven't been sent a >32 bit offset.
2986                  */
2987
2988                 if(IVAL(req->inbuf,smb_vwv10) != 0) {
2989                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
2990                                  "used and we don't support 64 bit offsets.\n",
2991                                  (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
2992                         END_PROFILE(SMBreadX);
2993                         reply_doserror(req, ERRDOS, ERRbadaccess);
2994                         return;
2995                 }
2996
2997 #endif /* LARGE_SMB_OFF_T */
2998
2999         }
3000
3001         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
3002                       (SMB_BIG_UINT)startpos, READ_LOCK)) {
3003                 END_PROFILE(SMBreadX);
3004                 reply_doserror(req, ERRDOS, ERRlock);
3005                 return;
3006         }
3007
3008         if (!big_readX
3009             && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3010                 END_PROFILE(SMBreadX);
3011                 reply_post_legacy(req, -1);
3012                 return;
3013         }
3014
3015         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3016
3017         END_PROFILE(SMBreadX);
3018         return;
3019 }
3020
3021 /****************************************************************************
3022  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3023 ****************************************************************************/
3024
3025 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3026 {
3027         ssize_t nwritten=0;
3028         ssize_t total_written=0;
3029         size_t numtowrite=0;
3030         size_t tcount;
3031         SMB_OFF_T startpos;
3032         char *data=NULL;
3033         BOOL write_through;
3034         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3035         int outsize = 0;
3036         NTSTATUS status;
3037         START_PROFILE(SMBwritebraw);
3038
3039         if (srv_is_signing_active()) {
3040                 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
3041         }
3042
3043         CHECK_FSP(fsp,conn);
3044         if (!CHECK_WRITE(fsp)) {
3045                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3046         }
3047   
3048         tcount = IVAL(inbuf,smb_vwv1);
3049         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3050         write_through = BITSETW(inbuf+smb_vwv7,0);
3051
3052         /* We have to deal with slightly different formats depending
3053                 on whether we are using the core+ or lanman1.0 protocol */
3054
3055         if(Protocol <= PROTOCOL_COREPLUS) {
3056                 numtowrite = SVAL(smb_buf(inbuf),-2);
3057                 data = smb_buf(inbuf);
3058         } else {
3059                 numtowrite = SVAL(inbuf,smb_vwv10);
3060                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
3061         }
3062
3063         /* force the error type */
3064         SCVAL(inbuf,smb_com,SMBwritec);
3065         SCVAL(outbuf,smb_com,SMBwritec);
3066
3067         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3068                 END_PROFILE(SMBwritebraw);
3069                 return(ERROR_DOS(ERRDOS,ERRlock));
3070         }
3071
3072         if (numtowrite>0)
3073                 nwritten = write_file(fsp,data,startpos,numtowrite);
3074   
3075         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
3076                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
3077
3078         if (nwritten < (ssize_t)numtowrite)  {
3079                 END_PROFILE(SMBwritebraw);
3080                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3081         }
3082
3083         total_written = nwritten;
3084
3085         /* Return a message to the redirector to tell it to send more bytes */
3086         SCVAL(outbuf,smb_com,SMBwritebraw);
3087         SSVALS(outbuf,smb_vwv0,-1);
3088         outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3089         show_msg(outbuf);
3090         if (!send_smb(smbd_server_fd(),outbuf))
3091                 exit_server_cleanly("reply_writebraw: send_smb failed.");
3092   
3093         /* Now read the raw data into the buffer and write it */
3094         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
3095                 exit_server_cleanly("secondary writebraw failed");
3096         }
3097   
3098         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
3099         numtowrite = smb_len(inbuf);
3100
3101         /* Set up outbuf to return the correct return */
3102         outsize = set_message(inbuf,outbuf,1,0,True);
3103         SCVAL(outbuf,smb_com,SMBwritec);
3104
3105         if (numtowrite != 0) {
3106
3107                 if (numtowrite > BUFFER_SIZE) {
3108                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
3109                                 (unsigned int)numtowrite ));
3110                         exit_server_cleanly("secondary writebraw failed");
3111                 }
3112
3113                 if (tcount > nwritten+numtowrite) {
3114                         DEBUG(3,("Client overestimated the write %d %d %d\n",
3115                                 (int)tcount,(int)nwritten,(int)numtowrite));
3116                 }
3117
3118                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
3119                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
3120                                 strerror(errno) ));
3121                         exit_server_cleanly("secondary writebraw failed");
3122                 }
3123
3124                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
3125                 if (nwritten == -1) {
3126                         END_PROFILE(SMBwritebraw);
3127                         return(UNIXERROR(ERRHRD,ERRdiskfull));
3128                 }
3129
3130                 if (nwritten < (ssize_t)numtowrite) {
3131                         SCVAL(outbuf,smb_rcls,ERRHRD);
3132                         SSVAL(outbuf,smb_err,ERRdiskfull);      
3133                 }
3134
3135                 if (nwritten > 0)
3136                         total_written += nwritten;
3137         }
3138  
3139         SSVAL(outbuf,smb_vwv0,total_written);
3140
3141         status = sync_file(conn, fsp, write_through);
3142         if (!NT_STATUS_IS_OK(status)) {
3143                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3144                         fsp->fsp_name, nt_errstr(status) ));
3145                 END_PROFILE(SMBwritebraw);
3146                 return ERROR_NT(status);
3147         }
3148
3149         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
3150                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
3151
3152         /* we won't return a status if write through is not selected - this follows what WfWg does */
3153         END_PROFILE(SMBwritebraw);
3154         if (!write_through && total_written==tcount) {
3155
3156 #if RABBIT_PELLET_FIX
3157                 /*
3158                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3159                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
3160                  */
3161                 if (!send_keepalive(smbd_server_fd()))
3162                         exit_server_cleanly("reply_writebraw: send of keepalive failed");
3163 #endif
3164                 return(-1);
3165         }
3166
3167         return(outsize);
3168 }
3169
3170 #undef DBGC_CLASS
3171 #define DBGC_CLASS DBGC_LOCKING
3172
3173 /****************************************************************************
3174  Reply to a writeunlock (core+).
3175 ****************************************************************************/
3176
3177 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
3178                       int size, int dum_buffsize)
3179 {
3180         ssize_t nwritten = -1;
3181         size_t numtowrite;
3182         SMB_OFF_T startpos;
3183         char *data;
3184         NTSTATUS status = NT_STATUS_OK;
3185         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3186         int outsize = 0;
3187         START_PROFILE(SMBwriteunlock);
3188         
3189         CHECK_FSP(fsp,conn);
3190         if (!CHECK_WRITE(fsp)) {
3191                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3192         }
3193
3194         numtowrite = SVAL(inbuf,smb_vwv1);
3195         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3196         data = smb_buf(inbuf) + 3;
3197   
3198         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3199                 END_PROFILE(SMBwriteunlock);
3200                 return ERROR_DOS(ERRDOS,ERRlock);
3201         }
3202
3203         /* The special X/Open SMB protocol handling of
3204            zero length writes is *NOT* done for
3205            this call */
3206         if(numtowrite == 0) {
3207                 nwritten = 0;
3208         } else {
3209                 nwritten = write_file(fsp,data,startpos,numtowrite);
3210         }
3211   
3212         status = sync_file(conn, fsp, False /* write through */);
3213         if (!NT_STATUS_IS_OK(status)) {
3214                 END_PROFILE(SMBwriteunlock);
3215                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3216                         fsp->fsp_name, nt_errstr(status) ));
3217                 return ERROR_NT(status);
3218         }
3219
3220         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3221                 END_PROFILE(SMBwriteunlock);
3222                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3223         }
3224
3225         if (numtowrite) {
3226                 status = do_unlock(smbd_messaging_context(),
3227                                 fsp,
3228                                 (uint32)SVAL(inbuf,smb_pid),
3229                                 (SMB_BIG_UINT)numtowrite, 
3230                                 (SMB_BIG_UINT)startpos,
3231                                 WINDOWS_LOCK);
3232
3233                 if (NT_STATUS_V(status)) {
3234                         END_PROFILE(SMBwriteunlock);
3235                         return ERROR_NT(status);
3236                 }
3237         }
3238         
3239         outsize = set_message(inbuf,outbuf,1,0,True);
3240         
3241         SSVAL(outbuf,smb_vwv0,nwritten);
3242         
3243         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3244                  fsp->fnum, (int)numtowrite, (int)nwritten));
3245         
3246         END_PROFILE(SMBwriteunlock);
3247         return outsize;
3248 }
3249
3250 #undef DBGC_CLASS
3251 #define DBGC_CLASS DBGC_ALL
3252
3253 /****************************************************************************
3254  Reply to a write.
3255 ****************************************************************************/
3256
3257 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
3258 {
3259         size_t numtowrite;
3260         ssize_t nwritten = -1;
3261         SMB_OFF_T startpos;
3262         char *data;
3263         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3264         int outsize = 0;
3265         NTSTATUS status;
3266         START_PROFILE(SMBwrite);
3267
3268         /* If it's an IPC, pass off the pipe handler. */
3269         if (IS_IPC(conn)) {
3270                 END_PROFILE(SMBwrite);
3271                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3272         }
3273
3274         CHECK_FSP(fsp,conn);
3275         if (!CHECK_WRITE(fsp)) {
3276                 END_PROFILE(SMBwrite);
3277                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3278         }
3279
3280         numtowrite = SVAL(inbuf,smb_vwv1);
3281         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3282         data = smb_buf(inbuf) + 3;
3283   
3284         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3285                 END_PROFILE(SMBwrite);
3286                 return ERROR_DOS(ERRDOS,ERRlock);
3287         }
3288
3289         /*
3290          * X/Open SMB protocol says that if smb_vwv1 is
3291          * zero then the file size should be extended or
3292          * truncated to the size given in smb_vwv[2-3].
3293          */
3294
3295         if(numtowrite == 0) {
3296                 /*
3297                  * This is actually an allocate call, and set EOF. JRA.
3298                  */
3299                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3300                 if (nwritten < 0) {
3301                         END_PROFILE(SMBwrite);
3302                         return ERROR_NT(NT_STATUS_DISK_FULL);
3303                 }
3304                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3305                 if (nwritten < 0) {
3306                         END_PROFILE(SMBwrite);
3307                         return ERROR_NT(NT_STATUS_DISK_FULL);
3308                 }
3309         } else
3310                 nwritten = write_file(fsp,data,startpos,numtowrite);
3311   
3312         status = sync_file(conn, fsp, False);
3313         if (!NT_STATUS_IS_OK(status)) {
3314                 END_PROFILE(SMBwrite);
3315                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3316                         fsp->fsp_name, nt_errstr(status) ));
3317                 return ERROR_NT(status);
3318         }
3319
3320         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3321                 END_PROFILE(SMBwrite);
3322                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3323         }
3324
3325         outsize = set_message(inbuf,outbuf,1,0,True);
3326   
3327         SSVAL(outbuf,smb_vwv0,nwritten);
3328
3329         if (nwritten < (ssize_t)numtowrite) {
3330                 SCVAL(outbuf,smb_rcls,ERRHRD);
3331                 SSVAL(outbuf,smb_err,ERRdiskfull);      
3332         }
3333   
3334         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3335
3336         END_PROFILE(SMBwrite);
3337         return(outsize);
3338 }
3339
3340 /****************************************************************************
3341  Reply to a write and X.
3342 ****************************************************************************/
3343
3344 void reply_write_and_X(connection_struct *conn, struct smb_request *req)
3345 {
3346         files_struct *fsp;
3347         SMB_OFF_T startpos;
3348         size_t numtowrite;
3349         BOOL write_through;
3350         ssize_t nwritten;
3351         unsigned int smb_doff;
3352         unsigned int smblen;
3353         char *data;
3354         BOOL large_writeX;
3355         NTSTATUS status;
3356
3357         START_PROFILE(SMBwriteX);
3358
3359         if ((req->wct != 12) && (req->wct != 14)) {
3360                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3361                 END_PROFILE(SMBwriteX);
3362                 return;
3363         }
3364
3365         numtowrite = SVAL(req->inbuf,smb_vwv10);
3366         smb_doff = SVAL(req->inbuf,smb_vwv11);
3367         smblen = smb_len(req->inbuf);
3368         large_writeX = ((req->wct == 14) && (smblen > 0xFFFF));
3369
3370         /* Deal with possible LARGE_WRITEX */
3371         if (large_writeX) {
3372                 numtowrite |= ((((size_t)SVAL(req->inbuf,smb_vwv9)) & 1 )<<16);
3373         }
3374
3375         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3376                 reply_doserror(req, ERRDOS, ERRbadmem);
3377                 END_PROFILE(SMBwriteX);
3378                 return;
3379         }
3380
3381         /* If it's an IPC, pass off the pipe handler. */
3382         if (IS_IPC(conn)) {
3383                 reply_pipe_write_and_X(req);
3384                 END_PROFILE(SMBwriteX);
3385                 return;
3386         }
3387
3388         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3389         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3390         write_through = BITSETW(req->inbuf+smb_vwv7,0);
3391
3392         if (!check_fsp(conn, req, fsp, &current_user)) {
3393                 END_PROFILE(SMBwriteX);
3394                 return;
3395         }
3396
3397         if (!CHECK_WRITE(fsp)) {
3398                 reply_doserror(req, ERRDOS, ERRbadaccess);
3399                 END_PROFILE(SMBwriteX);
3400                 return;
3401         }
3402
3403         data = smb_base(req->inbuf) + smb_doff;
3404
3405         if(req->wct == 14) {
3406 #ifdef LARGE_SMB_OFF_T
3407                 /*
3408                  * This is a large offset (64 bit) write.
3409                  */
3410                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
3411
3412 #else /* !LARGE_SMB_OFF_T */
3413
3414                 /*
3415                  * Ensure we haven't been sent a >32 bit offset.
3416                  */
3417
3418                 if(IVAL(req->inbuf,smb_vwv12) != 0) {
3419                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
3420                                  "used and we don't support 64 bit offsets.\n",
3421                                  (unsigned int)IVAL(inbuf,smb_vwv12) ));
3422                         reply_doserror(req, ERRDOS, ERRbadaccess);
3423                         END_PROFILE(SMBwriteX);
3424                         return;
3425                 }
3426
3427 #endif /* LARGE_SMB_OFF_T */
3428         }
3429
3430         if (is_locked(fsp,(uint32)req->smbpid,
3431                       (SMB_BIG_UINT)numtowrite,
3432                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3433                 reply_doserror(req, ERRDOS, ERRlock);
3434                 END_PROFILE(SMBwriteX);
3435                 return;
3436         }
3437
3438         /* X/Open SMB protocol says that, unlike SMBwrite
3439         if the length is zero then NO truncation is
3440         done, just a write of zero. To truncate a file,
3441         use SMBwrite. */
3442
3443         if(numtowrite == 0) {
3444                 nwritten = 0;
3445         } else {
3446
3447                 if (schedule_aio_write_and_X(conn, req, fsp, data, startpos,
3448                                              numtowrite)) {
3449                         END_PROFILE(SMBwriteX);
3450                         return;
3451                 }
3452
3453                 nwritten = write_file(fsp,data,startpos,numtowrite);
3454         }
3455   
3456         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3457                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3458                 END_PROFILE(SMBwriteX);
3459                 return;
3460         }
3461
3462         reply_outbuf(req, 6, 0);
3463         SSVAL(req->outbuf,smb_vwv2,nwritten);
3464         if (large_writeX)
3465                 SSVAL(req->outbuf,smb_vwv4,(nwritten>>16)&1);
3466
3467         if (nwritten < (ssize_t)numtowrite) {
3468                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3469                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3470         }
3471
3472         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3473                 fsp->fnum, (int)numtowrite, (int)nwritten));
3474
3475         status = sync_file(conn, fsp, write_through);
3476         if (!NT_STATUS_IS_OK(status)) {
3477                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3478                         fsp->fsp_name, nt_errstr(status) ));
3479                 reply_nterror(req, status);
3480                 END_PROFILE(SMBwriteX);
3481                 return;
3482         }
3483
3484         END_PROFILE(SMBwriteX);
3485         chain_reply_new(req);
3486         return;
3487 }
3488
3489 /****************************************************************************
3490  Reply to a lseek.
3491 ****************************************************************************/
3492
3493 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3494 {
3495         SMB_OFF_T startpos;
3496         SMB_OFF_T res= -1;
3497         int mode,umode;
3498         int outsize = 0;
3499         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3500         START_PROFILE(SMBlseek);
3501
3502         CHECK_FSP(fsp,conn);
3503
3504         flush_write_cache(fsp, SEEK_FLUSH);
3505
3506         mode = SVAL(inbuf,smb_vwv1) & 3;
3507         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3508         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3509
3510         switch (mode) {
3511                 case 0:
3512                         umode = SEEK_SET;
3513                         res = startpos;
3514                         break;
3515                 case 1:
3516                         umode = SEEK_CUR;
3517                         res = fsp->fh->pos + startpos;
3518                         break;
3519                 case 2:
3520                         umode = SEEK_END;
3521                         break;
3522                 default:
3523                         umode = SEEK_SET;
3524                         res = startpos;
3525                         break;
3526         }
3527
3528         if (umode == SEEK_END) {
3529                 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3530                         if(errno == EINVAL) {
3531                                 SMB_OFF_T current_pos = startpos;
3532                                 SMB_STRUCT_STAT sbuf;
3533
3534                                 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3535                                         END_PROFILE(SMBlseek);
3536                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3537                                 }
3538
3539                                 current_pos += sbuf.st_size;
3540                                 if(current_pos < 0)
3541                                         res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3542                         }
3543                 }
3544
3545                 if(res == -1) {
3546                         END_PROFILE(SMBlseek);
3547                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3548                 }
3549         }
3550
3551         fsp->fh->pos = res;
3552   
3553         outsize = set_message(inbuf,outbuf,2,0,True);
3554         SIVAL(outbuf,smb_vwv0,res);
3555   
3556         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3557                 fsp->fnum, (double)startpos, (double)res, mode));
3558
3559         END_PROFILE(SMBlseek);
3560         return(outsize);
3561 }
3562
3563 /****************************************************************************
3564  Reply to a flush.
3565 ****************************************************************************/
3566
3567 void reply_flush(connection_struct *conn, struct smb_request *req)
3568 {
3569         uint16 fnum;
3570         files_struct *fsp;
3571
3572         START_PROFILE(SMBflush);
3573
3574         if (req->wct < 1) {
3575                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3576                 return;
3577         }
3578
3579         fnum = SVAL(req->inbuf,smb_vwv0);
3580         fsp = file_fsp(fnum);
3581
3582         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, &current_user)) {
3583                 return;
3584         }
3585         
3586         if (!fsp) {
3587                 file_sync_all(conn);
3588         } else {
3589                 NTSTATUS status = sync_file(conn, fsp, True);
3590                 if (!NT_STATUS_IS_OK(status)) {
3591                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3592                                 fsp->fsp_name, nt_errstr(status) ));
3593                         reply_nterror(req, status);
3594                         END_PROFILE(SMBflush);
3595                         return;
3596                 }
3597         }
3598         
3599         reply_outbuf(req, 0, 0);
3600
3601         DEBUG(3,("flush\n"));
3602         END_PROFILE(SMBflush);
3603         return;
3604 }
3605
3606 /****************************************************************************
3607  Reply to a exit.
3608  conn POINTER CAN BE NULL HERE !
3609 ****************************************************************************/
3610
3611 void reply_exit(connection_struct *conn, struct smb_request *req)
3612 {
3613         START_PROFILE(SMBexit);
3614
3615         file_close_pid(req->smbpid, req->vuid);
3616
3617         reply_outbuf(req, 0, 0);
3618
3619         DEBUG(3,("exit\n"));
3620
3621         END_PROFILE(SMBexit);
3622         return;
3623 }
3624
3625 /****************************************************************************
3626  Reply to a close - has to deal with closing a directory opened by NT SMB's.
3627 ****************************************************************************/
3628
3629 void reply_close(connection_struct *conn, struct smb_request *req)
3630 {
3631         NTSTATUS status = NT_STATUS_OK;
3632         files_struct *fsp = NULL;
3633         START_PROFILE(SMBclose);
3634
3635         if (req->wct < 3) {
3636                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3637                 END_PROFILE(SMBclose);
3638                 return;
3639         }
3640
3641         /* If it's an IPC, pass off to the pipe handler. */
3642         if (IS_IPC(conn)) {
3643                 reply_pipe_close(conn, req);
3644                 END_PROFILE(SMBclose);
3645                 return;
3646         }
3647
3648         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3649
3650         /*
3651          * We can only use CHECK_FSP if we know it's not a directory.
3652          */
3653
3654         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3655                 reply_doserror(req, ERRDOS, ERRbadfid);
3656                 END_PROFILE(SMBclose);
3657                 return;
3658         }
3659
3660         if(fsp->is_directory) {
3661                 /*
3662                  * Special case - close NT SMB directory handle.
3663                  */
3664                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3665                 status = close_file(fsp,NORMAL_CLOSE);
3666         } else {
3667                 /*
3668                  * Close ordinary file.
3669                  */
3670
3671                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3672                          fsp->fh->fd, fsp->fnum,
3673                          conn->num_files_open));
3674  
3675                 /*
3676                  * Take care of any time sent in the close.
3677                  */
3678
3679                 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
3680                                                 srv_make_unix_date3(
3681                                                         req->inbuf+smb_vwv1)));
3682
3683                 /*
3684                  * close_file() returns the unix errno if an error
3685                  * was detected on close - normally this is due to
3686                  * a disk full error. If not then it was probably an I/O error.
3687                  */
3688  
3689                 status = close_file(fsp,NORMAL_CLOSE);
3690         }  
3691
3692         if (!NT_STATUS_IS_OK(status)) {
3693                 reply_nterror(req, status);
3694                 END_PROFILE(SMBclose);
3695                 return;
3696         }
3697
3698         reply_outbuf(req, 0, 0);
3699         END_PROFILE(SMBclose);
3700         return;
3701 }
3702
3703 /****************************************************************************
3704  Reply to a writeclose (Core+ protocol).
3705 ****************************************************************************/
3706
3707 int reply_writeclose(connection_struct *conn,
3708                      char *inbuf,char *outbuf, int size, int dum_buffsize)
3709 {
3710         size_t numtowrite;
3711         ssize_t nwritten = -1;
3712         int outsize = 0;
3713         NTSTATUS close_status = NT_STATUS_OK;
3714         SMB_OFF_T startpos;
3715         char *data;
3716         struct timespec mtime;
3717         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3718         START_PROFILE(SMBwriteclose);
3719
3720         CHECK_FSP(fsp,conn);
3721         if (!CHECK_WRITE(fsp)) {
3722                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3723         }
3724
3725         numtowrite = SVAL(inbuf,smb_vwv1);
3726         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3727         mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3728         data = smb_buf(inbuf) + 1;
3729   
3730         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3731                 END_PROFILE(SMBwriteclose);
3732                 return ERROR_DOS(ERRDOS,ERRlock);
3733         }
3734   
3735         nwritten = write_file(fsp,data,startpos,numtowrite);
3736
3737         set_filetime(conn, fsp->fsp_name, mtime);
3738   
3739         /*
3740          * More insanity. W2K only closes the file if writelen > 0.
3741          * JRA.
3742          */
3743
3744         if (numtowrite) {
3745                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3746                         fsp->fsp_name ));
3747                 close_status = close_file(fsp,NORMAL_CLOSE);
3748         }
3749
3750         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3751                  fsp->fnum, (int)numtowrite, (int)nwritten,
3752                  conn->num_files_open));
3753   
3754         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3755                 END_PROFILE(SMBwriteclose);
3756                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3757         }
3758  
3759         if(!NT_STATUS_IS_OK(close_status)) {
3760                 END_PROFILE(SMBwriteclose);
3761                 return ERROR_NT(close_status);
3762         }
3763  
3764         outsize = set_message(inbuf,outbuf,1,0,True);
3765   
3766         SSVAL(outbuf,smb_vwv0,nwritten);
3767         END_PROFILE(SMBwriteclose);
3768         return(outsize);
3769 }
3770
3771 #undef DBGC_CLASS
3772 #define DBGC_CLASS DBGC_LOCKING
3773
3774 /****************************************************************************
3775  Reply to a lock.
3776 ****************************************************************************/
3777
3778 int reply_lock(connection_struct *conn,
3779                char *inbuf,char *outbuf, int length, int dum_buffsize)
3780 {
3781         int outsize = set_message(inbuf,outbuf,0,0,False);
3782         SMB_BIG_UINT count,offset;
3783         NTSTATUS status;
3784         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3785         struct byte_range_lock *br_lck = NULL;
3786
3787         START_PROFILE(SMBlock);
3788
3789         CHECK_FSP(fsp,conn);
3790
3791         release_level_2_oplocks_on_change(fsp);
3792
3793         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3794         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3795
3796         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3797                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3798
3799         br_lck = do_lock(smbd_messaging_context(),
3800                         fsp,
3801                         (uint32)SVAL(inbuf,smb_pid),
3802                         count,
3803                         offset,
3804                         WRITE_LOCK,
3805                         WINDOWS_LOCK,
3806                         False, /* Non-blocking lock. */
3807                         &status,
3808                         NULL);
3809
3810         TALLOC_FREE(br_lck);
3811
3812         if (NT_STATUS_V(status)) {
3813                 END_PROFILE(SMBlock);
3814                 return ERROR_NT(status);
3815         }
3816
3817         END_PROFILE(SMBlock);
3818         return(outsize);
3819 }
3820
3821 /****************************************************************************
3822  Reply to a unlock.
3823 ****************************************************************************/
3824
3825 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
3826                  int dum_buffsize)
3827 {
3828         int outsize = set_message(inbuf,outbuf,0,0,False);
3829         SMB_BIG_UINT count,offset;
3830         NTSTATUS status;
3831         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3832         START_PROFILE(SMBunlock);
3833
3834         CHECK_FSP(fsp,conn);
3835         
3836         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3837         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3838         
3839         status = do_unlock(smbd_messaging_context(),
3840                         fsp,
3841                         (uint32)SVAL(inbuf,smb_pid),
3842                         count,
3843                         offset,
3844                         WINDOWS_LOCK);
3845
3846         if (NT_STATUS_V(status)) {
3847                 END_PROFILE(SMBunlock);
3848                 return ERROR_NT(status);
3849         }
3850
3851         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3852                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3853         
3854         END_PROFILE(SMBunlock);
3855         return(outsize);
3856 }
3857
3858 #undef DBGC_CLASS
3859 #define DBGC_CLASS DBGC_ALL
3860
3861 /****************************************************************************
3862  Reply to a tdis.
3863  conn POINTER CAN BE NULL HERE !
3864 ****************************************************************************/
3865
3866 void reply_tdis(connection_struct *conn, struct smb_request *req)
3867 {
3868         START_PROFILE(SMBtdis);
3869
3870         if (!conn) {
3871                 DEBUG(4,("Invalid connection in tdis\n"));
3872                 reply_doserror(req, ERRSRV, ERRinvnid);
3873                 END_PROFILE(SMBtdis);
3874                 return;
3875         }
3876
3877         conn->used = False;
3878
3879         close_cnum(conn,req->vuid);
3880
3881         reply_outbuf(req, 0, 0);
3882         END_PROFILE(SMBtdis);
3883         return;
3884 }
3885
3886 /****************************************************************************
3887  Reply to a echo.
3888  conn POINTER CAN BE NULL HERE !
3889 ****************************************************************************/
3890
3891 void reply_echo(connection_struct *conn, struct smb_request *req)
3892 {
3893         int smb_reverb;
3894         int seq_num;
3895         unsigned int data_len = smb_buflen(req->inbuf);
3896
3897         START_PROFILE(SMBecho);
3898
3899         if (req->wct < 1) {
3900                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3901                 END_PROFILE(SMBecho);
3902                 return;
3903         }
3904
3905         if (data_len > BUFFER_SIZE) {
3906                 DEBUG(0,("reply_echo: data_len too large.\n"));
3907                 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
3908                 END_PROFILE(SMBecho);
3909                 return;
3910         }
3911
3912         smb_reverb = SVAL(req->inbuf,smb_vwv0);
3913
3914         reply_outbuf(req, 1, data_len);
3915
3916         /* copy any incoming data back out */
3917         if (data_len > 0) {
3918                 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
3919         }
3920
3921         if (smb_reverb > 100) {
3922                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3923                 smb_reverb = 100;
3924         }
3925
3926         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3927                 SSVAL(req->outbuf,smb_vwv0,seq_num);
3928
3929                 show_msg((char *)req->outbuf);
3930                 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
3931                         exit_server_cleanly("reply_echo: send_smb failed.");
3932         }
3933
3934         DEBUG(3,("echo %d times\n", smb_reverb));
3935
3936         TALLOC_FREE(req->outbuf);
3937
3938         smb_echo_count++;
3939
3940         END_PROFILE(SMBecho);
3941         return;
3942 }
3943
3944 /****************************************************************************
3945  Reply to a printopen.
3946 ****************************************************************************/
3947
3948 int reply_printopen(connection_struct *conn, 
3949                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3950 {
3951         int outsize = 0;
3952         files_struct *fsp;
3953         NTSTATUS status;
3954         
3955         START_PROFILE(SMBsplopen);
3956         
3957         if (!CAN_PRINT(conn)) {
3958                 END_PROFILE(SMBsplopen);
3959                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3960         }
3961
3962         /* Open for exclusive use, write only. */
3963         status = print_fsp_open(conn, NULL, &fsp);
3964
3965         if (!NT_STATUS_IS_OK(status)) {
3966                 END_PROFILE(SMBsplopen);
3967                 return(ERROR_NT(status));
3968         }
3969
3970         outsize = set_message(inbuf,outbuf,1,0,True);
3971         SSVAL(outbuf,smb_vwv0,fsp->fnum);
3972   
3973         DEBUG(3,("openprint fd=%d fnum=%d\n",
3974                  fsp->fh->fd, fsp->fnum));
3975
3976         END_PROFILE(SMBsplopen);
3977         return(outsize);
3978 }
3979
3980 /****************************************************************************
3981  Reply to a printclose.
3982 ****************************************************************************/
3983
3984 int reply_printclose(connection_struct *conn,
3985                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3986 {
3987         int outsize = set_message(inbuf,outbuf,0,0,False);
3988         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3989         NTSTATUS status;
3990         START_PROFILE(SMBsplclose);
3991
3992         CHECK_FSP(fsp,conn);
3993
3994         if (!CAN_PRINT(conn)) {
3995                 END_PROFILE(SMBsplclose);
3996                 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3997         }
3998   
3999         DEBUG(3,("printclose fd=%d fnum=%d\n",
4000                  fsp->fh->fd,fsp->fnum));
4001   
4002         status = close_file(fsp,NORMAL_CLOSE);
4003
4004         if(!NT_STATUS_IS_OK(status)) {
4005                 END_PROFILE(SMBsplclose);
4006                 return ERROR_NT(status);
4007         }
4008
4009         END_PROFILE(SMBsplclose);
4010         return(outsize);
4011 }
4012
4013 /****************************************************************************
4014  Reply to a printqueue.
4015 ****************************************************************************/
4016
4017 int reply_printqueue(connection_struct *conn,
4018                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4019 {
4020         int outsize = set_message(inbuf,outbuf,2,3,True);
4021         int max_count = SVAL(inbuf,smb_vwv0);
4022         int start_index = SVAL(inbuf,smb_vwv1);
4023         START_PROFILE(SMBsplretq);
4024
4025         /* we used to allow the client to get the cnum wrong, but that
4026            is really quite gross and only worked when there was only
4027            one printer - I think we should now only accept it if they
4028            get it right (tridge) */
4029         if (!CAN_PRINT(conn)) {
4030                 END_PROFILE(SMBsplretq);
4031                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4032         }
4033
4034         SSVAL(outbuf,smb_vwv0,0);
4035         SSVAL(outbuf,smb_vwv1,0);
4036         SCVAL(smb_buf(outbuf),0,1);
4037         SSVAL(smb_buf(outbuf),1,0);
4038   
4039         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4040                  start_index, max_count));
4041
4042         {
4043                 print_queue_struct *queue = NULL;
4044                 print_status_struct status;
4045                 char *p = smb_buf(outbuf) + 3;
4046                 int count = print_queue_status(SNUM(conn), &queue, &status);
4047                 int num_to_get = ABS(max_count);
4048                 int first = (max_count>0?start_index:start_index+max_count+1);
4049                 int i;
4050
4051                 if (first >= count)
4052                         num_to_get = 0;
4053                 else
4054                         num_to_get = MIN(num_to_get,count-first);
4055     
4056
4057                 for (i=first;i<first+num_to_get;i++) {
4058                         srv_put_dos_date2(p,0,queue[i].time);
4059                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4060                         SSVAL(p,5, queue[i].job);
4061                         SIVAL(p,7,queue[i].size);
4062                         SCVAL(p,11,0);
4063                         srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+12,
4064                                     queue[i].fs_user, 16, STR_ASCII);
4065                         p += 28;
4066                 }
4067
4068                 if (count > 0) {
4069                         outsize = set_message(inbuf,outbuf,2,28*count+3,False); 
4070                         SSVAL(outbuf,smb_vwv0,count);
4071                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
4072                         SCVAL(smb_buf(outbuf),0,1);
4073                         SSVAL(smb_buf(outbuf),1,28*count);
4074                 }
4075
4076                 SAFE_FREE(queue);
4077           
4078                 DEBUG(3,("%d entries returned in queue\n",count));
4079         }
4080   
4081         END_PROFILE(SMBsplretq);
4082         return(outsize);
4083 }
4084
4085 /****************************************************************************
4086  Reply to a printwrite.
4087 ****************************************************************************/
4088
4089 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4090 {
4091         int numtowrite;
4092         int outsize = set_message(inbuf,outbuf,0,0,False);
4093         char *data;
4094         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
4095
4096         START_PROFILE(SMBsplwr);
4097   
4098         if (!CAN_PRINT(conn)) {
4099                 END_PROFILE(SMBsplwr);
4100                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4101         }
4102
4103         CHECK_FSP(fsp,conn);
4104         if (!CHECK_WRITE(fsp)) {
4105                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
4106         }
4107
4108         numtowrite = SVAL(smb_buf(inbuf),1);
4109         data = smb_buf(inbuf) + 3;
4110   
4111         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
4112                 END_PROFILE(SMBsplwr);
4113                 return(UNIXERROR(ERRHRD,ERRdiskfull));
4114         }
4115
4116         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4117   
4118         END_PROFILE(SMBsplwr);
4119         return(outsize);
4120 }
4121
4122 /****************************************************************************
4123  Reply to a mkdir.
4124 ****************************************************************************/
4125
4126 void reply_mkdir(connection_struct *conn, struct smb_request *req)
4127 {
4128         pstring directory;
4129         NTSTATUS status;
4130         SMB_STRUCT_STAT sbuf;
4131
4132         START_PROFILE(SMBmkdir);
4133  
4134         srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4135                         smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4136                         STR_TERMINATE, &status);
4137         if (!NT_STATUS_IS_OK(status)) {
4138                 reply_nterror(req, status);
4139                 END_PROFILE(SMBmkdir);
4140                 return;
4141         }
4142
4143         status = resolve_dfspath(conn,
4144                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4145                                  directory);
4146         if (!NT_STATUS_IS_OK(status)) {
4147                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4148                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4149                                         ERRSRV, ERRbadpath);
4150                         END_PROFILE(SMBmkdir);
4151                         return;
4152                 }
4153                 reply_nterror(req, status);
4154                 END_PROFILE(SMBmkdir);
4155                 return;
4156         }
4157
4158         status = unix_convert(conn, directory, False, NULL, &sbuf);
4159         if (!NT_STATUS_IS_OK(status)) {
4160                 reply_nterror(req, status);
4161                 END_PROFILE(SMBmkdir);
4162                 return;
4163         }
4164
4165         status = check_name(conn, directory);
4166         if (!NT_STATUS_IS_OK(status)) {
4167                 reply_nterror(req, status);
4168                 END_PROFILE(SMBmkdir);
4169                 return;
4170         }
4171   
4172         status = create_directory(conn, directory);
4173
4174         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4175
4176         if (!NT_STATUS_IS_OK(status)) {
4177
4178                 if (!use_nt_status()
4179                     && NT_STATUS_EQUAL(status,
4180                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
4181                         /*
4182                          * Yes, in the DOS error code case we get a
4183                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4184                          * samba4 torture test.
4185                          */
4186                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4187                 }
4188
4189                 reply_nterror(req, status);
4190                 END_PROFILE(SMBmkdir);
4191                 return;
4192         }
4193
4194         reply_outbuf(req, 0, 0);
4195
4196         DEBUG( 3, ( "mkdir %s\n", directory ) );
4197
4198         END_PROFILE(SMBmkdir);
4199         return;
4200 }
4201
4202 /****************************************************************************
4203  Static function used by reply_rmdir to delete an entire directory
4204  tree recursively. Return True on ok, False on fail.
4205 ****************************************************************************/
4206
4207 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
4208 {
4209         const char *dname = NULL;
4210         BOOL ret = True;
4211         long offset = 0;
4212         struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4213
4214         if(dir_hnd == NULL)
4215                 return False;
4216
4217         while((dname = ReadDirName(dir_hnd, &offset))) {
4218                 pstring fullname;
4219                 SMB_STRUCT_STAT st;
4220
4221                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4222                         continue;
4223
4224                 if (!is_visible_file(conn, directory, dname, &st, False))
4225                         continue;
4226
4227                 /* Construct the full name. */
4228                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4229                         errno = ENOMEM;
4230                         ret = False;
4231                         break;
4232                 }
4233
4234                 pstrcpy(fullname, directory);
4235                 pstrcat(fullname, "/");
4236                 pstrcat(fullname, dname);
4237
4238                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4239                         ret = False;
4240                         break;
4241                 }
4242
4243                 if(st.st_mode & S_IFDIR) {
4244                         if(!recursive_rmdir(conn, fullname)) {
4245                                 ret = False;
4246                                 break;
4247                         }
4248                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4249                                 ret = False;
4250                                 break;
4251                         }
4252                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4253                         ret = False;
4254                         break;
4255                 }
4256         }
4257         CloseDir(dir_hnd);
4258         return ret;
4259 }
4260
4261 /****************************************************************************
4262  The internals of the rmdir code - called elsewhere.
4263 ****************************************************************************/
4264
4265 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4266 {
4267         int ret;
4268         SMB_STRUCT_STAT st;
4269
4270         /* Might be a symlink. */
4271         if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4272                 return map_nt_error_from_unix(errno);
4273         }
4274
4275         if (S_ISLNK(st.st_mode)) {
4276                 /* Is what it points to a directory ? */
4277                 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4278                         return map_nt_error_from_unix(errno);
4279                 }
4280                 if (!(S_ISDIR(st.st_mode))) {
4281                         return NT_STATUS_NOT_A_DIRECTORY;
4282                 }
4283                 ret = SMB_VFS_UNLINK(conn,directory);
4284         } else {
4285                 ret = SMB_VFS_RMDIR(conn,directory);
4286         }
4287         if (ret == 0) {
4288                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4289                              FILE_NOTIFY_CHANGE_DIR_NAME,
4290                              directory);
4291                 return NT_STATUS_OK;
4292         }
4293
4294         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4295                 /* 
4296                  * Check to see if the only thing in this directory are
4297                  * vetoed files/directories. If so then delete them and
4298                  * retry. If we fail to delete any of them (and we *don't*
4299                  * do a recursive delete) then fail the rmdir.
4300                  */
4301                 const char *dname;
4302                 long dirpos = 0;
4303                 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4304
4305                 if(dir_hnd == NULL) {
4306                         errno = ENOTEMPTY;
4307                         goto err;
4308                 }
4309
4310                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4311                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4312                                 continue;
4313                         if (!is_visible_file(conn, directory, dname, &st, False))
4314                                 continue;
4315                         if(!IS_VETO_PATH(conn, dname)) {
4316                                 CloseDir(dir_hnd);
4317                                 errno = ENOTEMPTY;
4318                                 goto err;
4319                         }
4320                 }
4321
4322                 /* We only have veto files/directories. Recursive delete. */
4323
4324                 RewindDir(dir_hnd,&dirpos);
4325                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4326                         pstring fullname;
4327
4328                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4329                                 continue;
4330                         if (!is_visible_file(conn, directory, dname, &st, False))
4331                                 continue;
4332
4333                         /* Construct the full name. */
4334                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4335                                 errno = ENOMEM;
4336                                 break;
4337                         }
4338
4339                         pstrcpy(fullname, directory);
4340                         pstrcat(fullname, "/");
4341                         pstrcat(fullname, dname);
4342                    
4343                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4344                                 break;
4345                         if(st.st_mode & S_IFDIR) {
4346                                 if(lp_recursive_veto_delete(SNUM(conn))) {
4347                                         if(!recursive_rmdir(conn, fullname))
4348                                                 break;
4349                                 }
4350                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4351                                         break;
4352                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4353                                 break;
4354                 }
4355                 CloseDir(dir_hnd);
4356                 /* Retry the rmdir */
4357                 ret = SMB_VFS_RMDIR(conn,directory);
4358         }
4359
4360   err:
4361
4362         if (ret != 0) {
4363                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4364                          "%s\n", directory,strerror(errno)));
4365                 return map_nt_error_from_unix(errno);
4366         }
4367
4368         notify_fname(conn, NOTIFY_ACTION_REMOVED,
4369                      FILE_NOTIFY_CHANGE_DIR_NAME,
4370                      directory);
4371
4372         return NT_STATUS_OK;
4373 }
4374
4375 /****************************************************************************
4376  Reply to a rmdir.
4377 ****************************************************************************/
4378
4379 void reply_rmdir(connection_struct *conn, struct smb_request *req)
4380 {
4381         pstring directory;
4382         SMB_STRUCT_STAT sbuf;
4383         NTSTATUS status;
4384         START_PROFILE(SMBrmdir);
4385
4386         srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4387                         smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4388                         STR_TERMINATE, &status);
4389         if (!NT_STATUS_IS_OK(status)) {
4390                 reply_nterror(req, status);
4391                 END_PROFILE(SMBrmdir);
4392                 return;
4393         }
4394
4395         status = resolve_dfspath(conn,
4396                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4397                                  directory);
4398         if (!NT_STATUS_IS_OK(status)) {
4399                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4400                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4401                                         ERRSRV, ERRbadpath);
4402                         END_PROFILE(SMBrmdir);
4403                         return;
4404                 }
4405                 reply_nterror(req, status);
4406                 END_PROFILE(SMBrmdir);
4407                 return;
4408         }
4409
4410         status = unix_convert(conn, directory, False, NULL, &sbuf);
4411         if (!NT_STATUS_IS_OK(status)) {
4412                 reply_nterror(req, status);
4413                 END_PROFILE(SMBrmdir);
4414                 return;
4415         }
4416   
4417         status = check_name(conn, directory);
4418         if (!NT_STATUS_IS_OK(status)) {
4419                 reply_nterror(req, status);
4420                 END_PROFILE(SMBrmdir);
4421                 return;
4422         }
4423
4424         dptr_closepath(directory, req->smbpid);
4425         status = rmdir_internals(conn, directory);
4426         if (!NT_STATUS_IS_OK(status)) {
4427                 reply_nterror(req, status);
4428                 END_PROFILE(SMBrmdir);
4429                 return;
4430         }
4431  
4432         reply_outbuf(req, 0, 0);
4433   
4434         DEBUG( 3, ( "rmdir %s\n", directory ) );
4435   
4436         END_PROFILE(SMBrmdir);
4437         return;
4438 }
4439
4440 /*******************************************************************
4441  Resolve wildcards in a filename rename.
4442  Note that name is in UNIX charset and thus potentially can be more
4443  than fstring buffer (255 bytes) especially in default UTF-8 case.
4444  Therefore, we use pstring inside and all calls should ensure that
4445  name2 is at least pstring-long (they do already)
4446 ********************************************************************/
4447
4448 static BOOL resolve_wildcards(const char *name1, char *name2)
4449 {
4450         pstring root1,root2;
4451         pstring ext1,ext2;
4452         char *p,*p2, *pname1, *pname2;
4453         int available_space, actual_space;
4454         
4455         pname1 = strrchr_m(name1,'/');
4456         pname2 = strrchr_m(name2,'/');
4457
4458         if (!pname1 || !pname2)
4459                 return(False);
4460   
4461         pstrcpy(root1,pname1);
4462         pstrcpy(root2,pname2);
4463         p = strrchr_m(root1,'.');
4464         if (p) {
4465                 *p = 0;
4466                 pstrcpy(ext1,p+1);
4467         } else {
4468                 pstrcpy(ext1,"");    
4469         }
4470         p = strrchr_m(root2,'.');
4471         if (p) {
4472                 *p = 0;
4473                 pstrcpy(ext2,p+1);
4474         } else {
4475                 pstrcpy(ext2,"");    
4476         }
4477
4478         p = root1;
4479         p2 = root2;
4480         while (*p2) {
4481                 if (*p2 == '?') {
4482                         *p2 = *p;
4483                         p2++;
4484                 } else if (*p2 == '*') {
4485                         pstrcpy(p2, p);
4486                         break;
4487                 } else {
4488                         p2++;
4489                 }
4490                 if (*p)
4491                         p++;
4492         }
4493
4494         p = ext1;
4495         p2 = ext2;
4496         while (*p2) {
4497                 if (*p2 == '?') {
4498                         *p2 = *p;
4499                         p2++;
4500                 } else if (*p2 == '*') {
4501                         pstrcpy(p2, p);
4502                         break;
4503                 } else {
4504                         p2++;
4505                 }
4506                 if (*p)
4507                         p++;
4508         }
4509
4510         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4511         
4512         if (ext2[0]) {
4513                 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4514                 if (actual_space >= available_space - 1) {
4515                         DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4516                                 actual_space - available_space));
4517                 }
4518         } else {
4519                 pstrcpy_base(pname2, root2, name2);
4520         }
4521
4522         return(True);
4523 }
4524
4525 /****************************************************************************
4526  Ensure open files have their names updated. Updated to notify other smbd's
4527  asynchronously.
4528 ****************************************************************************/
4529
4530 static void rename_open_files(connection_struct *conn,
4531                               struct share_mode_lock *lck,
4532                               const char *newname)
4533 {
4534         files_struct *fsp;
4535         BOOL did_rename = False;
4536
4537         for(fsp = file_find_di_first(lck->id); fsp;
4538             fsp = file_find_di_next(fsp)) {
4539                 /* fsp_name is a relative path under the fsp. To change this for other
4540                    sharepaths we need to manipulate relative paths. */
4541                 /* TODO - create the absolute path and manipulate the newname
4542                    relative to the sharepath. */
4543                 if (fsp->conn != conn) {
4544                         continue;
4545                 }
4546                 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4547                           fsp->fnum, file_id_static_string(&fsp->file_id),
4548                         fsp->fsp_name, newname ));
4549                 string_set(&fsp->fsp_name, newname);
4550                 did_rename = True;
4551         }
4552
4553         if (!did_rename) {
4554                 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4555                           file_id_static_string(&lck->id), newname ));
4556         }
4557
4558         /* Send messages to all smbd's (not ourself) that the name has changed. */
4559         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4560                               newname);
4561 }
4562
4563 /****************************************************************************
4564  We need to check if the source path is a parent directory of the destination
4565  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4566  refuse the rename with a sharing violation. Under UNIX the above call can
4567  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4568  probably need to check that the client is a Windows one before disallowing
4569  this as a UNIX client (one with UNIX extensions) can know the source is a
4570  symlink and make this decision intelligently. Found by an excellent bug
4571  report from <AndyLiebman@aol.com>.
4572 ****************************************************************************/
4573
4574 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4575 {
4576         const char *psrc = src;
4577         const char *pdst = dest;
4578         size_t slen;
4579
4580         if (psrc[0] == '.' && psrc[1] == '/') {
4581                 psrc += 2;
4582         }
4583         if (pdst[0] == '.' && pdst[1] == '/') {
4584                 pdst += 2;
4585         }
4586         if ((slen = strlen(psrc)) > strlen(pdst)) {
4587                 return False;
4588         }
4589         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4590 }
4591
4592 /*
4593  * Do the notify calls from a rename
4594  */
4595
4596 static void notify_rename(connection_struct *conn, BOOL is_dir,
4597                           const char *oldpath, const char *newpath)
4598 {
4599         char *olddir, *newdir;
4600         const char *oldname, *newname;
4601         uint32 mask;
4602
4603         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4604                 : FILE_NOTIFY_CHANGE_FILE_NAME;
4605
4606         if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4607             || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4608                 TALLOC_FREE(olddir);
4609                 return;
4610         }
4611
4612         if (strcmp(olddir, newdir) == 0) {
4613                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4614                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4615         }
4616         else {
4617                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4618                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4619         }
4620         TALLOC_FREE(olddir);
4621         TALLOC_FREE(newdir);
4622
4623         /* this is a strange one. w2k3 gives an additional event for
4624            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4625            files, but not directories */
4626         if (!is_dir) {
4627                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4628                              FILE_NOTIFY_CHANGE_ATTRIBUTES
4629                              |FILE_NOTIFY_CHANGE_CREATION,
4630                              newpath);
4631         }
4632 }
4633
4634 /****************************************************************************
4635  Rename an open file - given an fsp.
4636 ****************************************************************************/
4637
4638 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4639 {
4640         SMB_STRUCT_STAT sbuf, sbuf1;
4641         pstring newname_last_component;
4642         NTSTATUS status = NT_STATUS_OK;
4643         struct share_mode_lock *lck = NULL;
4644         BOOL dst_exists;
4645
4646         ZERO_STRUCT(sbuf);
4647
4648         status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4649
4650         /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4651
4652         if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4653                 return status;
4654         }
4655
4656         status = check_name(conn, newname);
4657         if (!NT_STATUS_IS_OK(status)) {
4658                 return status;
4659         }
4660   
4661         /* Ensure newname contains a '/' */
4662         if(strrchr_m(newname,'/') == 0) {
4663                 pstring tmpstr;
4664                 
4665                 pstrcpy(tmpstr, "./");
4666                 pstrcat(tmpstr, newname);
4667                 pstrcpy(newname, tmpstr);
4668         }
4669
4670         /*
4671          * Check for special case with case preserving and not
4672          * case sensitive. If the old last component differs from the original
4673          * last component only by case, then we should allow
4674          * the rename (user is trying to change the case of the
4675          * filename).
4676          */
4677
4678         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4679                         strequal(newname, fsp->fsp_name)) {
4680                 char *p;
4681                 pstring newname_modified_last_component;
4682
4683                 /*
4684                  * Get the last component of the modified name.
4685                  * Note that we guarantee that newname contains a '/'
4686                  * character above.
4687                  */
4688                 p = strrchr_m(newname,'/');
4689                 pstrcpy(newname_modified_last_component,p+1);
4690                         
4691                 if(strcsequal(newname_modified_last_component, 
4692                               newname_last_component) == False) {
4693                         /*
4694                          * Replace the modified last component with
4695                          * the original.
4696                          */
4697                         pstrcpy(p+1, newname_last_component);
4698                 }
4699         }
4700
4701         /*
4702          * If the src and dest names are identical - including case,
4703          * don't do the rename, just return success.
4704          */
4705
4706         if (strcsequal(fsp->fsp_name, newname)) {
4707                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4708                         newname));
4709                 return NT_STATUS_OK;
4710         }
4711
4712         /*
4713          * Have vfs_object_exist also fill sbuf1
4714          */
4715         dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4716
4717         if(!replace_if_exists && dst_exists) {
4718                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4719                         fsp->fsp_name,newname));
4720                 return NT_STATUS_OBJECT_NAME_COLLISION;
4721         }
4722
4723         if (dst_exists) {
4724                 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
4725                 files_struct *dst_fsp = file_find_di_first(fileid);
4726                 if (dst_fsp) {
4727                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4728                         return NT_STATUS_ACCESS_DENIED;
4729                 }
4730         }
4731
4732         /* Ensure we have a valid stat struct for the source. */
4733         if (fsp->fh->fd != -1) {
4734                 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4735                         return map_nt_error_from_unix(errno);
4736                 }
4737         } else {
4738                 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4739                         return map_nt_error_from_unix(errno);
4740                 }
4741         }
4742
4743         status = can_rename(conn, fsp, attrs, &sbuf);
4744
4745         if (!NT_STATUS_IS_OK(status)) {
4746                 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4747                         nt_errstr(status), fsp->fsp_name,newname));
4748                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4749                         status = NT_STATUS_ACCESS_DENIED;
4750                 return status;
4751         }
4752
4753         if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4754                 return NT_STATUS_ACCESS_DENIED;
4755         }
4756
4757         lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4758
4759         /*
4760          * We have the file open ourselves, so not being able to get the
4761          * corresponding share mode lock is a fatal error.
4762          */
4763
4764         SMB_ASSERT(lck != NULL);
4765
4766         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4767                 uint32 create_options = fsp->fh->private_options;
4768
4769                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4770                         fsp->fsp_name,newname));
4771
4772                 rename_open_files(conn, lck, newname);
4773
4774                 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4775
4776                 /*
4777                  * A rename acts as a new file create w.r.t. allowing an initial delete
4778                  * on close, probably because in Windows there is a new handle to the
4779                  * new file. If initial delete on close was requested but not
4780                  * originally set, we need to set it here. This is probably not 100% correct,
4781                  * but will work for the CIFSFS client which in non-posix mode
4782                  * depends on these semantics. JRA.
4783                  */
4784
4785                 set_allow_initial_delete_on_close(lck, fsp, True);
4786
4787                 if (create_options & FILE_DELETE_ON_CLOSE) {
4788                         status = can_set_delete_on_close(fsp, True, 0);
4789
4790                         if (NT_STATUS_IS_OK(status)) {
4791                                 /* Note that here we set the *inital* delete on close flag,
4792                                  * not the regular one. The magic gets handled in close. */
4793                                 fsp->initial_delete_on_close = True;
4794                         }
4795                 }
4796                 TALLOC_FREE(lck);
4797                 return NT_STATUS_OK;    
4798         }
4799
4800         TALLOC_FREE(lck);
4801
4802         if (errno == ENOTDIR || errno == EISDIR) {
4803                 status = NT_STATUS_OBJECT_NAME_COLLISION;
4804         } else {
4805                 status = map_nt_error_from_unix(errno);
4806         }
4807                 
4808         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4809                 nt_errstr(status), fsp->fsp_name,newname));
4810
4811         return status;
4812 }
4813
4814 /****************************************************************************
4815  The guts of the rename command, split out so it may be called by the NT SMB
4816  code. 
4817 ****************************************************************************/
4818
4819 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
4820                                 pstring name,
4821                                 pstring newname,
4822                                 uint32 attrs,
4823                                 BOOL replace_if_exists,
4824                                 BOOL src_has_wild,
4825                                 BOOL dest_has_wild)
4826 {
4827         pstring directory;
4828         pstring mask;
4829         pstring last_component_src;
4830         pstring last_component_dest;
4831         char *p;
4832         int count=0;
4833         NTSTATUS status = NT_STATUS_OK;
4834         SMB_STRUCT_STAT sbuf1, sbuf2;
4835         struct smb_Dir *dir_hnd = NULL;
4836         const char *dname;
4837         long offset = 0;
4838         pstring destname;
4839
4840         *directory = *mask = 0;
4841
4842         ZERO_STRUCT(sbuf1);
4843         ZERO_STRUCT(sbuf2);
4844
4845         status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4846         if (!NT_STATUS_IS_OK(status)) {
4847                 return status;
4848         }
4849
4850         status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4851         if (!NT_STATUS_IS_OK(status)) {
4852                 return status;
4853         }
4854
4855         /*
4856          * Split the old name into directory and last component
4857          * strings. Note that unix_convert may have stripped off a 
4858          * leading ./ from both name and newname if the rename is 
4859          * at the root of the share. We need to make sure either both
4860          * name and newname contain a / character or neither of them do
4861          * as this is checked in resolve_wildcards().
4862          */
4863
4864         p = strrchr_m(name,'/');
4865         if (!p) {
4866                 pstrcpy(directory,".");
4867                 pstrcpy(mask,name);
4868         } else {
4869                 *p = 0;
4870                 pstrcpy(directory,name);
4871                 pstrcpy(mask,p+1);
4872                 *p = '/'; /* Replace needed for exceptional test below. */
4873         }
4874
4875         /*
4876          * We should only check the mangled cache
4877          * here if unix_convert failed. This means
4878          * that the path in 'mask' doesn't exist
4879          * on the file system and so we need to look
4880          * for a possible mangle. This patch from
4881          * Tine Smukavec <valentin.smukavec@hermes.si>.
4882          */
4883
4884         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4885                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4886         }
4887
4888         if (!src_has_wild) {
4889                 files_struct *fsp;
4890
4891                 /*
4892                  * No wildcards - just process the one file.
4893                  */
4894                 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4895
4896                 /* Add a terminating '/' to the directory name. */
4897                 pstrcat(directory,"/");
4898                 pstrcat(directory,mask);
4899                 
4900                 /* Ensure newname contains a '/' also */
4901                 if(strrchr_m(newname,'/') == 0) {
4902                         pstring tmpstr;
4903                         
4904                         pstrcpy(tmpstr, "./");
4905                         pstrcat(tmpstr, newname);
4906                         pstrcpy(newname, tmpstr);
4907                 }
4908                 
4909                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4910                           "case_preserve = %d, short case preserve = %d, "
4911                           "directory = %s, newname = %s, "
4912                           "last_component_dest = %s, is_8_3 = %d\n", 
4913                           conn->case_sensitive, conn->case_preserve,
4914                           conn->short_case_preserve, directory, 
4915                           newname, last_component_dest, is_short_name));
4916
4917                 /* The dest name still may have wildcards. */
4918                 if (dest_has_wild) {
4919                         if (!resolve_wildcards(directory,newname)) {
4920                                 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", 
4921                                           directory,newname));
4922                                 return NT_STATUS_NO_MEMORY;
4923                         }
4924                 }
4925                                 
4926                 ZERO_STRUCT(sbuf1);
4927                 SMB_VFS_STAT(conn, directory, &sbuf1);
4928
4929                 status = S_ISDIR(sbuf1.st_mode) ?
4930                         open_directory(conn, req, directory, &sbuf1,
4931                                        DELETE_ACCESS,
4932                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
4933                                        FILE_OPEN, 0, 0, NULL,
4934                                        &fsp)
4935                         : open_file_ntcreate(conn, req, directory, &sbuf1,
4936                                              DELETE_ACCESS,
4937                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
4938                                              FILE_OPEN, 0, 0, 0, NULL,
4939                                              &fsp);
4940
4941                 if (!NT_STATUS_IS_OK(status)) {
4942                         DEBUG(3, ("Could not open rename source %s: %s\n",
4943                                   directory, nt_errstr(status)));
4944                         return status;
4945                 }
4946
4947                 status = rename_internals_fsp(conn, fsp, newname, attrs,
4948                                               replace_if_exists);
4949
4950                 close_file(fsp, NORMAL_CLOSE);
4951
4952                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4953                           nt_errstr(status), directory,newname));
4954
4955                 return status;
4956         }
4957
4958         /*
4959          * Wildcards - process each file that matches.
4960          */
4961         if (strequal(mask,"????????.???")) {
4962                 pstrcpy(mask,"*");
4963         }
4964                         
4965         status = check_name(conn, directory);
4966         if (!NT_STATUS_IS_OK(status)) {
4967                 return status;
4968         }
4969         
4970         dir_hnd = OpenDir(conn, directory, mask, attrs);
4971         if (dir_hnd == NULL) {
4972                 return map_nt_error_from_unix(errno);
4973         }
4974                 
4975         status = NT_STATUS_NO_SUCH_FILE;
4976         /*
4977          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4978          * - gentest fix. JRA
4979          */
4980                         
4981         while ((dname = ReadDirName(dir_hnd, &offset))) {
4982                 files_struct *fsp;
4983                 pstring fname;
4984                 BOOL sysdir_entry = False;
4985
4986                 pstrcpy(fname,dname);
4987                                 
4988                 /* Quick check for "." and ".." */
4989                 if (fname[0] == '.') {
4990                         if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4991                                 if (attrs & aDIR) {
4992                                         sysdir_entry = True;
4993                                 } else {
4994                                         continue;
4995                                 }
4996                         }
4997                 }
4998
4999                 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5000                         continue;
5001                 }
5002
5003                 if(!mask_match(fname, mask, conn->case_sensitive)) {
5004                         continue;
5005                 }
5006                                 
5007                 if (sysdir_entry) {
5008                         status = NT_STATUS_OBJECT_NAME_INVALID;
5009                         break;
5010                 }
5011
5012                 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
5013
5014                 pstrcpy(destname,newname);
5015                         
5016                 if (!resolve_wildcards(fname,destname)) {
5017                         DEBUG(6, ("resolve_wildcards %s %s failed\n", 
5018                                   fname, destname));
5019                         continue;
5020                 }
5021                                 
5022                 ZERO_STRUCT(sbuf1);
5023                 SMB_VFS_STAT(conn, fname, &sbuf1);
5024
5025                 status = S_ISDIR(sbuf1.st_mode) ?
5026                         open_directory(conn, req, fname, &sbuf1,
5027                                        DELETE_ACCESS,
5028                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5029                                        FILE_OPEN, 0, 0, NULL,
5030                                        &fsp)
5031                         : open_file_ntcreate(conn, req, fname, &sbuf1,
5032                                              DELETE_ACCESS,
5033                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5034                                              FILE_OPEN, 0, 0, 0, NULL,
5035                                              &fsp);
5036
5037                 if (!NT_STATUS_IS_OK(status)) {
5038                         DEBUG(3,("rename_internals: open_file_ntcreate "
5039                                  "returned %s rename %s -> %s\n",
5040                                  nt_errstr(status), directory, newname));
5041                         break;
5042                 }
5043
5044                 status = rename_internals_fsp(conn, fsp, destname, attrs,
5045                                               replace_if_exists);
5046
5047                 close_file(fsp, NORMAL_CLOSE);
5048
5049                 if (!NT_STATUS_IS_OK(status)) {
5050                         DEBUG(3, ("rename_internals_fsp returned %s for "
5051                                   "rename %s -> %s\n", nt_errstr(status),
5052                                   directory, newname));
5053                         break;
5054                 }
5055
5056                 count++;
5057
5058                 DEBUG(3,("rename_internals: doing rename on %s -> "
5059                          "%s\n",fname,destname));
5060         }
5061         CloseDir(dir_hnd);
5062
5063         if (count == 0 && NT_STATUS_IS_OK(status)) {
5064                 status = map_nt_error_from_unix(errno);
5065         }
5066         
5067         return status;
5068 }
5069
5070 /****************************************************************************
5071  Reply to a mv.
5072 ****************************************************************************/
5073
5074 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
5075              int dum_buffsize)
5076 {
5077         int outsize = 0;
5078         pstring name;
5079         pstring newname;
5080         char *p;
5081         uint32 attrs = SVAL(inbuf,smb_vwv0);
5082         NTSTATUS status;
5083         BOOL src_has_wcard = False;
5084         BOOL dest_has_wcard = False;
5085         struct smb_request req;
5086
5087         START_PROFILE(SMBmv);
5088
5089         init_smb_request(&req, (uint8 *)inbuf);
5090
5091         p = smb_buf(inbuf) + 1;
5092         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5093                                    sizeof(name), 0, STR_TERMINATE, &status,
5094                                    &src_has_wcard);
5095         if (!NT_STATUS_IS_OK(status)) {
5096                 END_PROFILE(SMBmv);
5097                 return ERROR_NT(status);
5098         }
5099         p++;
5100         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5101                                    sizeof(newname), 0, STR_TERMINATE, &status,
5102                                    &dest_has_wcard);
5103         if (!NT_STATUS_IS_OK(status)) {
5104                 END_PROFILE(SMBmv);
5105                 return ERROR_NT(status);
5106         }
5107         
5108         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
5109         if (!NT_STATUS_IS_OK(status)) {
5110                 END_PROFILE(SMBmv);
5111                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5112                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5113                 }
5114                 return ERROR_NT(status);
5115         }
5116
5117         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
5118         if (!NT_STATUS_IS_OK(status)) {
5119                 END_PROFILE(SMBmv);
5120                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5121                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5122                 }
5123                 return ERROR_NT(status);
5124         }
5125         
5126         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5127         
5128         status = rename_internals(conn, &req, name, newname, attrs, False,
5129                                   src_has_wcard, dest_has_wcard);
5130         if (!NT_STATUS_IS_OK(status)) {
5131                 END_PROFILE(SMBmv);
5132                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5133                         /* We have re-scheduled this call. */
5134                         return -1;
5135                 }
5136                 return ERROR_NT(status);
5137         }
5138
5139         outsize = set_message(inbuf,outbuf,0,0,False);
5140   
5141         END_PROFILE(SMBmv);
5142         return(outsize);
5143 }
5144
5145 /*******************************************************************
5146  Copy a file as part of a reply_copy.
5147 ******************************************************************/
5148
5149 /*
5150  * TODO: check error codes on all callers
5151  */
5152
5153 NTSTATUS copy_file(connection_struct *conn,
5154                         char *src,
5155                         char *dest1,
5156                         int ofun,
5157                         int count,
5158                         BOOL target_is_directory)
5159 {
5160         SMB_STRUCT_STAT src_sbuf, sbuf2;
5161         SMB_OFF_T ret=-1;
5162         files_struct *fsp1,*fsp2;
5163         pstring dest;
5164         uint32 dosattrs;
5165         uint32 new_create_disposition;
5166         NTSTATUS status;
5167  
5168         pstrcpy(dest,dest1);
5169         if (target_is_directory) {
5170                 char *p = strrchr_m(src,'/');
5171                 if (p) {
5172                         p++;
5173                 } else {
5174                         p = src;
5175                 }
5176                 pstrcat(dest,"/");
5177                 pstrcat(dest,p);
5178         }
5179
5180         if (!vfs_file_exist(conn,src,&src_sbuf)) {
5181                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5182         }
5183
5184         if (!target_is_directory && count) {
5185                 new_create_disposition = FILE_OPEN;
5186         } else {
5187                 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5188                                 NULL, NULL, &new_create_disposition, NULL)) {
5189                         return NT_STATUS_INVALID_PARAMETER;
5190                 }
5191         }
5192
5193         status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5194                         FILE_GENERIC_READ,
5195                         FILE_SHARE_READ|FILE_SHARE_WRITE,
5196                         FILE_OPEN,
5197                         0,
5198                         FILE_ATTRIBUTE_NORMAL,
5199                         INTERNAL_OPEN_ONLY,
5200                         NULL, &fsp1);
5201
5202         if (!NT_STATUS_IS_OK(status)) {
5203                 return status;
5204         }
5205
5206         dosattrs = dos_mode(conn, src, &src_sbuf);
5207         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
5208                 ZERO_STRUCTP(&sbuf2);
5209         }
5210
5211         status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
5212                         FILE_GENERIC_WRITE,
5213                         FILE_SHARE_READ|FILE_SHARE_WRITE,
5214                         new_create_disposition,
5215                         0,
5216                         dosattrs,
5217                         INTERNAL_OPEN_ONLY,
5218                         NULL, &fsp2);
5219
5220         if (!NT_STATUS_IS_OK(status)) {
5221                 close_file(fsp1,ERROR_CLOSE);
5222                 return status;
5223         }
5224
5225         if ((ofun&3) == 1) {
5226                 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
5227                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
5228                         /*
5229                          * Stop the copy from occurring.
5230                          */
5231                         ret = -1;
5232                         src_sbuf.st_size = 0;
5233                 }
5234         }
5235   
5236         if (src_sbuf.st_size) {
5237                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
5238         }
5239
5240         close_file(fsp1,NORMAL_CLOSE);
5241
5242         /* Ensure the modtime is set correctly on the destination file. */
5243         fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
5244
5245         /*
5246          * As we are opening fsp1 read-only we only expect
5247          * an error on close on fsp2 if we are out of space.
5248          * Thus we don't look at the error return from the
5249          * close of fsp1.
5250          */
5251         status = close_file(fsp2,NORMAL_CLOSE);
5252
5253         if (!NT_STATUS_IS_OK(status)) {
5254                 return status;
5255         }
5256
5257         if (ret != (SMB_OFF_T)src_sbuf.st_size) {
5258                 return NT_STATUS_DISK_FULL;
5259         }
5260
5261         return NT_STATUS_OK;
5262 }
5263
5264 /****************************************************************************
5265  Reply to a file copy.
5266 ****************************************************************************/
5267
5268 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5269 {
5270         int outsize = 0;
5271         pstring name;
5272         pstring directory;
5273         pstring mask,newname;
5274         char *p;
5275         int count=0;
5276         int error = ERRnoaccess;
5277         int err = 0;
5278         int tid2 = SVAL(inbuf,smb_vwv0);
5279         int ofun = SVAL(inbuf,smb_vwv1);
5280         int flags = SVAL(inbuf,smb_vwv2);
5281         BOOL target_is_directory=False;
5282         BOOL source_has_wild = False;
5283         BOOL dest_has_wild = False;
5284         SMB_STRUCT_STAT sbuf1, sbuf2;
5285         NTSTATUS status;
5286         START_PROFILE(SMBcopy);
5287
5288         *directory = *mask = 0;
5289
5290         p = smb_buf(inbuf);
5291         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5292                                    sizeof(name), 0, STR_TERMINATE, &status,
5293                                    &source_has_wild);
5294         if (!NT_STATUS_IS_OK(status)) {
5295                 END_PROFILE(SMBcopy);
5296                 return ERROR_NT(status);
5297         }
5298         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5299                                    sizeof(newname), 0, STR_TERMINATE, &status,
5300                                    &dest_has_wild);
5301         if (!NT_STATUS_IS_OK(status)) {
5302                 END_PROFILE(SMBcopy);
5303                 return ERROR_NT(status);
5304         }
5305    
5306         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5307    
5308         if (tid2 != conn->cnum) {
5309                 /* can't currently handle inter share copies XXXX */
5310                 DEBUG(3,("Rejecting inter-share copy\n"));
5311                 END_PROFILE(SMBcopy);
5312                 return ERROR_DOS(ERRSRV,ERRinvdevice);
5313         }
5314
5315         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5316         if (!NT_STATUS_IS_OK(status)) {
5317                 END_PROFILE(SMBcopy);
5318                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5319                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5320                 }
5321                 return ERROR_NT(status);
5322         }
5323
5324         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5325         if (!NT_STATUS_IS_OK(status)) {
5326                 END_PROFILE(SMBcopy);
5327                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5328                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5329                 }
5330                 return ERROR_NT(status);
5331         }
5332
5333         status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5334         if (!NT_STATUS_IS_OK(status)) {
5335                 END_PROFILE(SMBcopy);
5336                 return ERROR_NT(status);
5337         }
5338
5339         status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5340         if (!NT_STATUS_IS_OK(status)) {
5341                 END_PROFILE(SMBcopy);
5342                 return ERROR_NT(status);
5343         }
5344
5345         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5346
5347         if ((flags&1) && target_is_directory) {
5348                 END_PROFILE(SMBcopy);
5349                 return ERROR_DOS(ERRDOS,ERRbadfile);
5350         }
5351
5352         if ((flags&2) && !target_is_directory) {
5353                 END_PROFILE(SMBcopy);
5354                 return ERROR_DOS(ERRDOS,ERRbadpath);
5355         }
5356
5357         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5358                 /* wants a tree copy! XXXX */
5359                 DEBUG(3,("Rejecting tree copy\n"));
5360                 END_PROFILE(SMBcopy);
5361                 return ERROR_DOS(ERRSRV,ERRerror);
5362         }
5363
5364         p = strrchr_m(name,'/');
5365         if (!p) {
5366                 pstrcpy(directory,"./");
5367                 pstrcpy(mask,name);
5368         } else {
5369                 *p = 0;
5370                 pstrcpy(directory,name);
5371                 pstrcpy(mask,p+1);
5372         }
5373
5374         /*
5375          * We should only check the mangled cache
5376          * here if unix_convert failed. This means
5377          * that the path in 'mask' doesn't exist
5378          * on the file system and so we need to look
5379          * for a possible mangle. This patch from
5380          * Tine Smukavec <valentin.smukavec@hermes.si>.
5381          */
5382
5383         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5384                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5385         }
5386
5387         if (!source_has_wild) {
5388                 pstrcat(directory,"/");
5389                 pstrcat(directory,mask);
5390                 if (dest_has_wild) {
5391                         if (!resolve_wildcards(directory,newname)) {
5392                                 END_PROFILE(SMBcopy);
5393                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5394                         }
5395                 }
5396
5397                 status = check_name(conn, directory);
5398                 if (!NT_STATUS_IS_OK(status)) {
5399                         return ERROR_NT(status);
5400                 }
5401                 
5402                 status = check_name(conn, newname);
5403                 if (!NT_STATUS_IS_OK(status)) {
5404                         return ERROR_NT(status);
5405                 }
5406                 
5407                 status = copy_file(conn,directory,newname,ofun,
5408                                         count,target_is_directory);
5409
5410                 if(!NT_STATUS_IS_OK(status)) {
5411                         END_PROFILE(SMBcopy);
5412                         return ERROR_NT(status);
5413                 } else {
5414                         count++;
5415                 }
5416         } else {
5417                 struct smb_Dir *dir_hnd = NULL;
5418                 const char *dname;
5419                 long offset = 0;
5420                 pstring destname;
5421
5422                 if (strequal(mask,"????????.???"))
5423                         pstrcpy(mask,"*");
5424
5425                 status = check_name(conn, directory);
5426                 if (!NT_STATUS_IS_OK(status)) {
5427                         return ERROR_NT(status);
5428                 }
5429                 
5430                 dir_hnd = OpenDir(conn, directory, mask, 0);
5431                 if (dir_hnd == NULL) {
5432                         status = map_nt_error_from_unix(errno);
5433                         return ERROR_NT(status);
5434                 }
5435
5436                 error = ERRbadfile;
5437
5438                 while ((dname = ReadDirName(dir_hnd, &offset))) {
5439                         pstring fname;
5440                         pstrcpy(fname,dname);
5441     
5442                         if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5443                                 continue;
5444                         }
5445
5446                         if(!mask_match(fname, mask, conn->case_sensitive)) {
5447                                 continue;
5448                         }
5449
5450                         error = ERRnoaccess;
5451                         slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5452                         pstrcpy(destname,newname);
5453                         if (!resolve_wildcards(fname,destname)) {
5454                                 continue;
5455                         }
5456
5457                         status = check_name(conn, fname);
5458                         if (!NT_STATUS_IS_OK(status)) {
5459                                 return ERROR_NT(status);
5460                         }
5461                 
5462                         status = check_name(conn, destname);
5463                         if (!NT_STATUS_IS_OK(status)) {
5464                                 return ERROR_NT(status);
5465                         }
5466                 
5467                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5468
5469                         status = copy_file(conn,fname,destname,ofun,
5470                                         count,target_is_directory);
5471                         if (NT_STATUS_IS_OK(status)) {
5472                                 count++;
5473                         }
5474                 }
5475                 CloseDir(dir_hnd);
5476         }
5477   
5478         if (count == 0) {
5479                 if(err) {
5480                         /* Error on close... */
5481                         errno = err;
5482                         END_PROFILE(SMBcopy);
5483                         return(UNIXERROR(ERRHRD,ERRgeneral));
5484                 }
5485
5486                 END_PROFILE(SMBcopy);
5487                 return ERROR_DOS(ERRDOS,error);
5488         }
5489   
5490         outsize = set_message(inbuf,outbuf,1,0,True);
5491         SSVAL(outbuf,smb_vwv0,count);
5492
5493         END_PROFILE(SMBcopy);
5494         return(outsize);
5495 }
5496
5497 /****************************************************************************
5498  Reply to a setdir.
5499 ****************************************************************************/
5500
5501 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5502 {
5503         int snum;
5504         int outsize = 0;
5505         pstring newdir;
5506         NTSTATUS status;
5507
5508         START_PROFILE(pathworks_setdir);
5509   
5510         snum = SNUM(conn);
5511         if (!CAN_SETDIR(snum)) {
5512                 END_PROFILE(pathworks_setdir);
5513                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5514         }
5515
5516         srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
5517                         smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
5518                         &status);
5519         if (!NT_STATUS_IS_OK(status)) {
5520                 END_PROFILE(pathworks_setdir);
5521                 return ERROR_NT(status);
5522         }
5523   
5524         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5525         if (!NT_STATUS_IS_OK(status)) {
5526                 END_PROFILE(pathworks_setdir);
5527                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5528                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5529                 }
5530                 return ERROR_NT(status);
5531         }
5532
5533         if (strlen(newdir) != 0) {
5534                 if (!vfs_directory_exist(conn,newdir,NULL)) {
5535                         END_PROFILE(pathworks_setdir);
5536                         return ERROR_DOS(ERRDOS,ERRbadpath);
5537                 }
5538                 set_conn_connectpath(conn,newdir);
5539         }
5540   
5541         outsize = set_message(inbuf,outbuf,0,0,False);
5542         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5543   
5544         DEBUG(3,("setdir %s\n", newdir));
5545
5546         END_PROFILE(pathworks_setdir);
5547         return(outsize);
5548 }
5549
5550 #undef DBGC_CLASS
5551 #define DBGC_CLASS DBGC_LOCKING
5552
5553 /****************************************************************************
5554  Get a lock pid, dealing with large count requests.
5555 ****************************************************************************/
5556
5557 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5558 {
5559         if(!large_file_format)
5560                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5561         else
5562                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5563 }
5564
5565 /****************************************************************************
5566  Get a lock count, dealing with large count requests.
5567 ****************************************************************************/
5568
5569 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5570 {
5571         SMB_BIG_UINT count = 0;
5572
5573         if(!large_file_format) {
5574                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5575         } else {
5576
5577 #if defined(HAVE_LONGLONG)
5578                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5579                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5580 #else /* HAVE_LONGLONG */
5581
5582                 /*
5583                  * NT4.x seems to be broken in that it sends large file (64 bit)
5584                  * lockingX calls even if the CAP_LARGE_FILES was *not*
5585                  * negotiated. For boxes without large unsigned ints truncate the
5586                  * lock count by dropping the top 32 bits.
5587                  */
5588
5589                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5590                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5591                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5592                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5593                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5594                 }
5595
5596                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5597 #endif /* HAVE_LONGLONG */
5598         }
5599
5600         return count;
5601 }
5602
5603 #if !defined(HAVE_LONGLONG)
5604 /****************************************************************************
5605  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5606 ****************************************************************************/
5607
5608 static uint32 map_lock_offset(uint32 high, uint32 low)
5609 {
5610         unsigned int i;
5611         uint32 mask = 0;
5612         uint32 highcopy = high;
5613  
5614         /*
5615          * Try and find out how many significant bits there are in high.
5616          */
5617  
5618         for(i = 0; highcopy; i++)
5619                 highcopy >>= 1;
5620  
5621         /*
5622          * We use 31 bits not 32 here as POSIX
5623          * lock offsets may not be negative.
5624          */
5625  
5626         mask = (~0) << (31 - i);
5627  
5628         if(low & mask)
5629                 return 0; /* Fail. */
5630  
5631         high <<= (31 - i);
5632  
5633         return (high|low);
5634 }
5635 #endif /* !defined(HAVE_LONGLONG) */
5636
5637 /****************************************************************************
5638  Get a lock offset, dealing with large offset requests.
5639 ****************************************************************************/
5640
5641 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5642 {
5643         SMB_BIG_UINT offset = 0;
5644
5645         *err = False;
5646
5647         if(!large_file_format) {
5648                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5649         } else {
5650
5651 #if defined(HAVE_LONGLONG)
5652                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5653                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5654 #else /* HAVE_LONGLONG */
5655
5656                 /*
5657                  * NT4.x seems to be broken in that it sends large file (64 bit)
5658                  * lockingX calls even if the CAP_LARGE_FILES was *not*
5659                  * negotiated. For boxes without large unsigned ints mangle the
5660                  * lock offset by mapping the top 32 bits onto the lower 32.
5661                  */
5662       
5663                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5664                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5665                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5666                         uint32 new_low = 0;
5667
5668                         if((new_low = map_lock_offset(high, low)) == 0) {
5669                                 *err = True;
5670                                 return (SMB_BIG_UINT)-1;
5671                         }
5672
5673                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5674                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5675                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5676                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5677                 }
5678
5679                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5680 #endif /* HAVE_LONGLONG */
5681         }
5682
5683         return offset;
5684 }
5685
5686 /****************************************************************************
5687  Reply to a lockingX request.
5688 ****************************************************************************/
5689
5690 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5691                    int length, int bufsize)
5692 {
5693         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
5694         unsigned char locktype = CVAL(inbuf,smb_vwv3);
5695         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5696         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5697         uint16 num_locks = SVAL(inbuf,smb_vwv7);
5698         SMB_BIG_UINT count = 0, offset = 0;
5699         uint32 lock_pid;
5700         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5701         int i;
5702         char *data;
5703         BOOL large_file_format =
5704                 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5705         BOOL err;
5706         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5707
5708         START_PROFILE(SMBlockingX);
5709         
5710         CHECK_FSP(fsp,conn);
5711         
5712         data = smb_buf(inbuf);
5713
5714         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5715                 /* we don't support these - and CANCEL_LOCK makes w2k
5716                    and XP reboot so I don't really want to be
5717                    compatible! (tridge) */
5718                 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5719         }
5720         
5721         /* Check if this is an oplock break on a file
5722            we have granted an oplock on.
5723         */
5724         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5725                 /* Client can insist on breaking to none. */
5726                 BOOL break_to_none = (oplocklevel == 0);
5727                 BOOL result;
5728
5729                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5730                          "for fnum = %d\n", (unsigned int)oplocklevel,
5731                          fsp->fnum ));
5732
5733                 /*
5734                  * Make sure we have granted an exclusive or batch oplock on
5735                  * this file.
5736                  */
5737                 
5738                 if (fsp->oplock_type == 0) {
5739
5740                         /* The Samba4 nbench simulator doesn't understand
5741                            the difference between break to level2 and break
5742                            to none from level2 - it sends oplock break
5743                            replies in both cases. Don't keep logging an error
5744                            message here - just ignore it. JRA. */
5745
5746                         DEBUG(5,("reply_lockingX: Error : oplock break from "
5747                                  "client for fnum = %d (oplock=%d) and no "
5748                                  "oplock granted on this file (%s).\n",
5749                                  fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5750
5751                         /* if this is a pure oplock break request then don't
5752                          * send a reply */
5753                         if (num_locks == 0 && num_ulocks == 0) {
5754                                 END_PROFILE(SMBlockingX);
5755                                 return -1;
5756                         } else {
5757                                 END_PROFILE(SMBlockingX);
5758                                 return ERROR_DOS(ERRDOS,ERRlock);
5759                         }
5760                 }
5761
5762                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5763                     (break_to_none)) {
5764                         result = remove_oplock(fsp);
5765                 } else {
5766                         result = downgrade_oplock(fsp);
5767                 }
5768                 
5769                 if (!result) {
5770                         DEBUG(0, ("reply_lockingX: error in removing "
5771                                   "oplock on file %s\n", fsp->fsp_name));
5772                         /* Hmmm. Is this panic justified? */
5773                         smb_panic("internal tdb error");
5774                 }
5775
5776                 reply_to_oplock_break_requests(fsp);
5777
5778                 /* if this is a pure oplock break request then don't send a
5779                  * reply */
5780                 if (num_locks == 0 && num_ulocks == 0) {
5781                         /* Sanity check - ensure a pure oplock break is not a
5782                            chained request. */
5783                         if(CVAL(inbuf,smb_vwv0) != 0xff)
5784                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
5785                                          "break is a chained %d request !\n",
5786                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
5787                         END_PROFILE(SMBlockingX);
5788                         return -1;
5789                 }
5790         }
5791
5792         /*
5793          * We do this check *after* we have checked this is not a oplock break
5794          * response message. JRA.
5795          */
5796         
5797         release_level_2_oplocks_on_change(fsp);
5798         
5799         /* Data now points at the beginning of the list
5800            of smb_unlkrng structs */
5801         for(i = 0; i < (int)num_ulocks; i++) {
5802                 lock_pid = get_lock_pid( data, i, large_file_format);
5803                 count = get_lock_count( data, i, large_file_format);
5804                 offset = get_lock_offset( data, i, large_file_format, &err);
5805                 
5806                 /*
5807                  * There is no error code marked "stupid client bug".... :-).
5808                  */
5809                 if(err) {
5810                         END_PROFILE(SMBlockingX);
5811                         return ERROR_DOS(ERRDOS,ERRnoaccess);
5812                 }
5813
5814                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5815                           "pid %u, file %s\n", (double)offset, (double)count,
5816                           (unsigned int)lock_pid, fsp->fsp_name ));
5817                 
5818                 status = do_unlock(smbd_messaging_context(),
5819                                 fsp,
5820                                 lock_pid,
5821                                 count,
5822                                 offset,
5823                                 WINDOWS_LOCK);
5824
5825                 if (NT_STATUS_V(status)) {
5826                         END_PROFILE(SMBlockingX);
5827                         return ERROR_NT(status);
5828                 }
5829         }
5830
5831         /* Setup the timeout in seconds. */
5832
5833         if (!lp_blocking_locks(SNUM(conn))) {
5834                 lock_timeout = 0;
5835         }
5836         
5837         /* Now do any requested locks */
5838         data += ((large_file_format ? 20 : 10)*num_ulocks);
5839         
5840         /* Data now points at the beginning of the list
5841            of smb_lkrng structs */
5842         
5843         for(i = 0; i < (int)num_locks; i++) {
5844                 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5845                                 READ_LOCK:WRITE_LOCK);
5846                 lock_pid = get_lock_pid( data, i, large_file_format);
5847                 count = get_lock_count( data, i, large_file_format);
5848                 offset = get_lock_offset( data, i, large_file_format, &err);
5849                 
5850                 /*
5851                  * There is no error code marked "stupid client bug".... :-).
5852                  */
5853                 if(err) {
5854                         END_PROFILE(SMBlockingX);
5855                         return ERROR_DOS(ERRDOS,ERRnoaccess);
5856                 }
5857                 
5858                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5859                           "%u, file %s timeout = %d\n", (double)offset,
5860                           (double)count, (unsigned int)lock_pid,
5861                           fsp->fsp_name, (int)lock_timeout ));
5862                 
5863                 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5864                         if (lp_blocking_locks(SNUM(conn))) {
5865
5866                                 /* Schedule a message to ourselves to
5867                                    remove the blocking lock record and
5868                                    return the right error. */
5869
5870                                 if (!blocking_lock_cancel(fsp,
5871                                                 lock_pid,
5872                                                 offset,
5873                                                 count,
5874                                                 WINDOWS_LOCK,
5875                                                 locktype,
5876                                                 NT_STATUS_FILE_LOCK_CONFLICT)) {
5877                                         END_PROFILE(SMBlockingX);
5878                                         return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5879                                 }
5880                         }
5881                         /* Remove a matching pending lock. */
5882                         status = do_lock_cancel(fsp,
5883                                                 lock_pid,
5884                                                 count,
5885                                                 offset,
5886                                                 WINDOWS_LOCK);
5887                 } else {
5888                         BOOL blocking_lock = lock_timeout ? True : False;
5889                         BOOL defer_lock = False;
5890                         struct byte_range_lock *br_lck;
5891                         uint32 block_smbpid;
5892
5893                         br_lck = do_lock(smbd_messaging_context(),
5894                                         fsp,
5895                                         lock_pid,
5896                                         count,
5897                                         offset, 
5898                                         lock_type,
5899                                         WINDOWS_LOCK,
5900                                         blocking_lock,
5901                                         &status,
5902                                         &block_smbpid);
5903
5904                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5905                                 /* Windows internal resolution for blocking locks seems
5906                                    to be about 200ms... Don't wait for less than that. JRA. */
5907                                 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5908                                         lock_timeout = lp_lock_spin_time();
5909                                 }
5910                                 defer_lock = True;
5911                         }
5912
5913                         /* This heuristic seems to match W2K3 very well. If a
5914                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5915                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
5916                            far as I can tell. Replacement for do_lock_spin(). JRA. */
5917
5918                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5919                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5920                                 defer_lock = True;
5921                                 lock_timeout = lp_lock_spin_time();
5922                         }
5923
5924                         if (br_lck && defer_lock) {
5925                                 /*
5926                                  * A blocking lock was requested. Package up
5927                                  * this smb into a queued request and push it
5928                                  * onto the blocking lock queue.
5929                                  */
5930                                 if(push_blocking_lock_request(br_lck,
5931                                                         inbuf, length,
5932                                                         fsp,
5933                                                         lock_timeout,
5934                                                         i,
5935                                                         lock_pid,
5936                                                         lock_type,
5937                                                         WINDOWS_LOCK,
5938                                                         offset,
5939                                                         count,
5940                                                         block_smbpid)) {
5941                                         TALLOC_FREE(br_lck);
5942                                         END_PROFILE(SMBlockingX);
5943                                         return -1;
5944                                 }
5945                         }
5946
5947                         TALLOC_FREE(br_lck);
5948                 }
5949
5950                 if (NT_STATUS_V(status)) {
5951                         END_PROFILE(SMBlockingX);
5952                         return ERROR_NT(status);
5953                 }
5954         }
5955         
5956         /* If any of the above locks failed, then we must unlock
5957            all of the previous locks (X/Open spec). */
5958
5959         if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5960                         (i != num_locks) &&
5961                         (num_locks != 0)) {
5962                 /*
5963                  * Ensure we don't do a remove on the lock that just failed,
5964                  * as under POSIX rules, if we have a lock already there, we
5965                  * will delete it (and we shouldn't) .....
5966                  */
5967                 for(i--; i >= 0; i--) {
5968                         lock_pid = get_lock_pid( data, i, large_file_format);
5969                         count = get_lock_count( data, i, large_file_format);
5970                         offset = get_lock_offset( data, i, large_file_format,
5971                                                   &err);
5972                         
5973                         /*
5974                          * There is no error code marked "stupid client
5975                          * bug".... :-).
5976                          */
5977                         if(err) {
5978                                 END_PROFILE(SMBlockingX);
5979                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5980                         }
5981                         
5982                         do_unlock(smbd_messaging_context(),
5983                                 fsp,
5984                                 lock_pid,
5985                                 count,
5986                                 offset,
5987                                 WINDOWS_LOCK);
5988                 }
5989                 END_PROFILE(SMBlockingX);
5990                 return ERROR_NT(status);
5991         }
5992
5993         set_message(inbuf,outbuf,2,0,True);
5994         
5995         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5996                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5997         
5998         END_PROFILE(SMBlockingX);
5999         return chain_reply(inbuf,&outbuf,length,bufsize);
6000 }
6001
6002 #undef DBGC_CLASS
6003 #define DBGC_CLASS DBGC_ALL
6004
6005 /****************************************************************************
6006  Reply to a SMBreadbmpx (read block multiplex) request.
6007 ****************************************************************************/
6008
6009 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
6010 {
6011         ssize_t nread = -1;
6012         ssize_t total_read;
6013         char *data;
6014         SMB_OFF_T startpos;
6015         int outsize;
6016         size_t maxcount;
6017         int max_per_packet;
6018         size_t tcount;
6019         int pad;
6020         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6021         START_PROFILE(SMBreadBmpx);
6022
6023         /* this function doesn't seem to work - disable by default */
6024         if (!lp_readbmpx()) {
6025                 END_PROFILE(SMBreadBmpx);
6026                 return ERROR_DOS(ERRSRV,ERRuseSTD);
6027         }
6028
6029         outsize = set_message(inbuf,outbuf,8,0,True);
6030
6031         CHECK_FSP(fsp,conn);
6032         if (!CHECK_READ(fsp,inbuf)) {
6033                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6034         }
6035
6036         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
6037         maxcount = SVAL(inbuf,smb_vwv3);
6038
6039         data = smb_buf(outbuf);
6040         pad = ((long)data)%4;
6041         if (pad)
6042                 pad = 4 - pad;
6043         data += pad;
6044
6045         max_per_packet = bufsize-(outsize+pad);
6046         tcount = maxcount;
6047         total_read = 0;
6048
6049         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
6050                 END_PROFILE(SMBreadBmpx);
6051                 return ERROR_DOS(ERRDOS,ERRlock);
6052         }
6053
6054         do {
6055                 size_t N = MIN(max_per_packet,tcount-total_read);
6056   
6057                 nread = read_file(fsp,data,startpos,N);
6058
6059                 if (nread <= 0)
6060                         nread = 0;
6061
6062                 if (nread < (ssize_t)N)
6063                         tcount = total_read + nread;
6064
6065                 set_message(inbuf,outbuf,8,nread+pad,False);
6066                 SIVAL(outbuf,smb_vwv0,startpos);
6067                 SSVAL(outbuf,smb_vwv2,tcount);
6068                 SSVAL(outbuf,smb_vwv6,nread);
6069                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
6070
6071                 show_msg(outbuf);
6072                 if (!send_smb(smbd_server_fd(),outbuf))
6073                         exit_server_cleanly("reply_readbmpx: send_smb failed.");
6074
6075                 total_read += nread;
6076                 startpos += nread;
6077         } while (total_read < (ssize_t)tcount);
6078
6079         END_PROFILE(SMBreadBmpx);
6080         return(-1);
6081 }
6082
6083 /****************************************************************************
6084  Reply to a SMBsetattrE.
6085 ****************************************************************************/
6086
6087 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6088 {
6089         struct timespec ts[2];
6090         int outsize = 0;
6091         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6092         START_PROFILE(SMBsetattrE);
6093
6094         outsize = set_message(inbuf,outbuf,0,0,False);
6095
6096         if(!fsp || (fsp->conn != conn)) {
6097                 END_PROFILE(SMBsetattrE);
6098                 return ERROR_DOS(ERRDOS,ERRbadfid);
6099         }
6100
6101         /*
6102          * Convert the DOS times into unix times. Ignore create
6103          * time as UNIX can't set this.
6104          */
6105
6106         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
6107         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
6108   
6109         /* 
6110          * Patch from Ray Frush <frush@engr.colostate.edu>
6111          * Sometimes times are sent as zero - ignore them.
6112          */
6113
6114         if (null_timespec(ts[0]) && null_timespec(ts[1])) {
6115                 /* Ignore request */
6116                 if( DEBUGLVL( 3 ) ) {
6117                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
6118                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
6119                 }
6120                 END_PROFILE(SMBsetattrE);
6121                 return(outsize);
6122         } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
6123                 /* set modify time = to access time if modify time was unset */
6124                 ts[1] = ts[0];
6125         }
6126
6127         /* Set the date on this file */
6128         /* Should we set pending modtime here ? JRA */
6129         if(file_ntimes(conn, fsp->fsp_name, ts)) {
6130                 END_PROFILE(SMBsetattrE);
6131                 return ERROR_DOS(ERRDOS,ERRnoaccess);
6132         }
6133   
6134         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
6135                 fsp->fnum,
6136                 (unsigned int)ts[0].tv_sec,
6137                 (unsigned int)ts[1].tv_sec));
6138
6139         END_PROFILE(SMBsetattrE);
6140         return(outsize);
6141 }
6142
6143
6144 /* Back from the dead for OS/2..... JRA. */
6145
6146 /****************************************************************************
6147  Reply to a SMBwritebmpx (write block multiplex primary) request.
6148 ****************************************************************************/
6149
6150 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6151 {
6152         size_t numtowrite;
6153         ssize_t nwritten = -1;
6154         int outsize = 0;
6155         SMB_OFF_T startpos;
6156         size_t tcount;
6157         BOOL write_through;
6158         int smb_doff;
6159         char *data;
6160         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6161         NTSTATUS status;
6162         START_PROFILE(SMBwriteBmpx);
6163
6164         CHECK_FSP(fsp,conn);
6165         if (!CHECK_WRITE(fsp)) {
6166                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6167         }
6168         if (HAS_CACHED_ERROR(fsp)) {
6169                 return(CACHED_ERROR(fsp));
6170         }
6171
6172         tcount = SVAL(inbuf,smb_vwv1);
6173         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
6174         write_through = BITSETW(inbuf+smb_vwv7,0);
6175         numtowrite = SVAL(inbuf,smb_vwv10);
6176         smb_doff = SVAL(inbuf,smb_vwv11);
6177
6178         data = smb_base(inbuf) + smb_doff;
6179
6180         /* If this fails we need to send an SMBwriteC response,
6181                 not an SMBwritebmpx - set this up now so we don't forget */
6182         SCVAL(outbuf,smb_com,SMBwritec);
6183
6184         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
6185                 END_PROFILE(SMBwriteBmpx);
6186                 return(ERROR_DOS(ERRDOS,ERRlock));
6187         }
6188
6189         nwritten = write_file(fsp,data,startpos,numtowrite);
6190
6191         status = sync_file(conn, fsp, write_through);
6192         if (!NT_STATUS_IS_OK(status)) {
6193                 END_PROFILE(SMBwriteBmpx);
6194                 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
6195                         fsp->fsp_name, nt_errstr(status) ));
6196                 return ERROR_NT(status);
6197         }
6198   
6199         if(nwritten < (ssize_t)numtowrite) {
6200                 END_PROFILE(SMBwriteBmpx);
6201                 return(UNIXERROR(ERRHRD,ERRdiskfull));
6202         }
6203
6204         /* If the maximum to be written to this file
6205                 is greater than what we just wrote then set
6206                 up a secondary struct to be attached to this
6207                 fd, we will use this to cache error messages etc. */
6208
6209         if((ssize_t)tcount > nwritten) {
6210                 write_bmpx_struct *wbms;
6211                 if(fsp->wbmpx_ptr != NULL)
6212                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
6213                 else
6214                         wbms = SMB_MALLOC_P(write_bmpx_struct);
6215                 if(!wbms) {
6216                         DEBUG(0,("Out of memory in reply_readmpx\n"));
6217                         END_PROFILE(SMBwriteBmpx);
6218                         return(ERROR_DOS(ERRSRV,ERRnoresource));
6219                 }
6220                 wbms->wr_mode = write_through;
6221                 wbms->wr_discard = False; /* No errors yet */
6222                 wbms->wr_total_written = nwritten;
6223                 wbms->wr_errclass = 0;
6224                 wbms->wr_error = 0;
6225                 fsp->wbmpx_ptr = wbms;
6226         }
6227
6228         /* We are returning successfully, set the message type back to
6229                 SMBwritebmpx */
6230         SCVAL(outbuf,smb_com,SMBwriteBmpx);
6231   
6232         outsize = set_message(inbuf,outbuf,1,0,True);
6233   
6234         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
6235   
6236         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
6237                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
6238
6239         if (write_through && tcount==nwritten) {
6240                 /* We need to send both a primary and a secondary response */
6241                 smb_setlen(inbuf,outbuf,outsize - 4);
6242                 show_msg(outbuf);
6243                 if (!send_smb(smbd_server_fd(),outbuf))
6244                         exit_server_cleanly("reply_writebmpx: send_smb failed.");
6245
6246                 /* Now the secondary */
6247                 outsize = set_message(inbuf,outbuf,1,0,True);
6248                 SCVAL(outbuf,smb_com,SMBwritec);
6249                 SSVAL(outbuf,smb_vwv0,nwritten);
6250         }
6251
6252         END_PROFILE(SMBwriteBmpx);
6253         return(outsize);
6254 }
6255
6256 /****************************************************************************
6257  Reply to a SMBwritebs (write block multiplex secondary) request.
6258 ****************************************************************************/
6259
6260 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
6261 {
6262         size_t numtowrite;
6263         ssize_t nwritten = -1;
6264         int outsize = 0;
6265         SMB_OFF_T startpos;
6266         size_t tcount;
6267         BOOL write_through;
6268         int smb_doff;
6269         char *data;
6270         write_bmpx_struct *wbms;
6271         BOOL send_response = False; 
6272         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6273         NTSTATUS status;
6274         START_PROFILE(SMBwriteBs);
6275
6276         CHECK_FSP(fsp,conn);
6277         if (!CHECK_WRITE(fsp)) {
6278                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6279         }
6280
6281         tcount = SVAL(inbuf,smb_vwv1);
6282         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6283         numtowrite = SVAL(inbuf,smb_vwv6);
6284         smb_doff = SVAL(inbuf,smb_vwv7);
6285
6286         data = smb_base(inbuf) + smb_doff;
6287
6288         /* We need to send an SMBwriteC response, not an SMBwritebs */
6289         SCVAL(outbuf,smb_com,SMBwritec);
6290
6291         /* This fd should have an auxiliary struct attached,
6292                 check that it does */
6293         wbms = fsp->wbmpx_ptr;
6294         if(!wbms) {
6295                 END_PROFILE(SMBwriteBs);
6296                 return(-1);
6297         }
6298
6299         /* If write through is set we can return errors, else we must cache them */
6300         write_through = wbms->wr_mode;
6301
6302         /* Check for an earlier error */
6303         if(wbms->wr_discard) {
6304                 END_PROFILE(SMBwriteBs);
6305                 return -1; /* Just discard the packet */
6306         }
6307
6308         nwritten = write_file(fsp,data,startpos,numtowrite);
6309
6310         status = sync_file(conn, fsp, write_through);
6311   
6312         if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6313                 if(write_through) {
6314                         /* We are returning an error - we can delete the aux struct */
6315                         if (wbms)
6316                                 free((char *)wbms);
6317                         fsp->wbmpx_ptr = NULL;
6318                         END_PROFILE(SMBwriteBs);
6319                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
6320                 }
6321                 wbms->wr_errclass = ERRHRD;
6322                 wbms->wr_error = ERRdiskfull;
6323                 wbms->wr_status = NT_STATUS_DISK_FULL;
6324                 wbms->wr_discard = True;
6325                 END_PROFILE(SMBwriteBs);
6326                 return -1;
6327         }
6328
6329         /* Increment the total written, if this matches tcount
6330                 we can discard the auxiliary struct (hurrah !) and return a writeC */
6331         wbms->wr_total_written += nwritten;
6332         if(wbms->wr_total_written >= tcount) {
6333                 if (write_through) {
6334                         outsize = set_message(inbuf,outbuf,1,0,True);
6335                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
6336                         send_response = True;
6337                 }
6338
6339                 free((char *)wbms);
6340                 fsp->wbmpx_ptr = NULL;
6341         }
6342
6343         if(send_response) {
6344                 END_PROFILE(SMBwriteBs);
6345                 return(outsize);
6346         }
6347
6348         END_PROFILE(SMBwriteBs);
6349         return(-1);
6350 }
6351
6352 /****************************************************************************
6353  Reply to a SMBgetattrE.
6354 ****************************************************************************/
6355
6356 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6357 {
6358         SMB_STRUCT_STAT sbuf;
6359         int outsize = 0;
6360         int mode;
6361         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6362         START_PROFILE(SMBgetattrE);
6363
6364         outsize = set_message(inbuf,outbuf,11,0,True);
6365
6366         if(!fsp || (fsp->conn != conn)) {
6367                 END_PROFILE(SMBgetattrE);
6368                 return ERROR_DOS(ERRDOS,ERRbadfid);
6369         }
6370
6371         /* Do an fstat on this file */
6372         if(fsp_stat(fsp, &sbuf)) {
6373                 END_PROFILE(SMBgetattrE);
6374                 return(UNIXERROR(ERRDOS,ERRnoaccess));
6375         }
6376   
6377         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6378   
6379         /*
6380          * Convert the times into dos times. Set create
6381          * date to be last modify date as UNIX doesn't save
6382          * this.
6383          */
6384
6385         srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6386         srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6387         /* Should we check pending modtime here ? JRA */
6388         srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6389
6390         if (mode & aDIR) {
6391                 SIVAL(outbuf,smb_vwv6,0);
6392                 SIVAL(outbuf,smb_vwv8,0);
6393         } else {
6394                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6395                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6396                 SIVAL(outbuf,smb_vwv8,allocation_size);
6397         }
6398         SSVAL(outbuf,smb_vwv10, mode);
6399   
6400         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6401   
6402         END_PROFILE(SMBgetattrE);
6403         return(outsize);
6404 }