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