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