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