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