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