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