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