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