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