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