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