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