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