s3: Lift smbd_server_fd() from read_data()
[nivanova/samba-autobuild/.git] / source3 / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28 #include "printing.h"
29 #include "smbd/globals.h"
30 #include "../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->sock, (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, 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->sock, 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  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3801 ****************************************************************************/
3802
3803 void reply_writebraw(struct smb_request *req)
3804 {
3805         connection_struct *conn = req->conn;
3806         char *buf = NULL;
3807         ssize_t nwritten=0;
3808         ssize_t total_written=0;
3809         size_t numtowrite=0;
3810         size_t tcount;
3811         SMB_OFF_T startpos;
3812         char *data=NULL;
3813         bool write_through;
3814         files_struct *fsp;
3815         struct lock_struct lock;
3816         NTSTATUS status;
3817
3818         START_PROFILE(SMBwritebraw);
3819
3820         /*
3821          * If we ever reply with an error, it must have the SMB command
3822          * type of SMBwritec, not SMBwriteBraw, as this tells the client
3823          * we're finished.
3824          */
3825         SCVAL(req->inbuf,smb_com,SMBwritec);
3826
3827         if (srv_is_signing_active(req->sconn)) {
3828                 END_PROFILE(SMBwritebraw);
3829                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3830                                 "raw reads/writes are disallowed.");
3831         }
3832
3833         if (req->wct < 12) {
3834                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3835                 error_to_writebrawerr(req);
3836                 END_PROFILE(SMBwritebraw);
3837                 return;
3838         }
3839
3840         if (req->sconn->smb1.echo_handler.trusted_fde) {
3841                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3842                          "'async smb echo handler = yes'\n"));
3843                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3844                 error_to_writebrawerr(req);
3845                 END_PROFILE(SMBwritebraw);
3846                 return;
3847         }
3848
3849         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3850         if (!check_fsp(conn, req, fsp)) {
3851                 error_to_writebrawerr(req);
3852                 END_PROFILE(SMBwritebraw);
3853                 return;
3854         }
3855
3856         if (!CHECK_WRITE(fsp)) {
3857                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3858                 error_to_writebrawerr(req);
3859                 END_PROFILE(SMBwritebraw);
3860                 return;
3861         }
3862
3863         tcount = IVAL(req->vwv+1, 0);
3864         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3865         write_through = BITSETW(req->vwv+7,0);
3866
3867         /* We have to deal with slightly different formats depending
3868                 on whether we are using the core+ or lanman1.0 protocol */
3869
3870         if(get_Protocol() <= PROTOCOL_COREPLUS) {
3871                 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3872                 data = smb_buf(req->inbuf);
3873         } else {
3874                 numtowrite = SVAL(req->vwv+10, 0);
3875                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3876         }
3877
3878         /* Ensure we don't write bytes past the end of this packet. */
3879         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3880                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3881                 error_to_writebrawerr(req);
3882                 END_PROFILE(SMBwritebraw);
3883                 return;
3884         }
3885
3886         if (!fsp->print_file) {
3887                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3888                     (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3889                     &lock);
3890
3891                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3892                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3893                         error_to_writebrawerr(req);
3894                         END_PROFILE(SMBwritebraw);
3895                         return;
3896                 }
3897         }
3898
3899         if (numtowrite>0) {
3900                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3901         }
3902
3903         DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3904                         "wrote=%d sync=%d\n",
3905                 fsp->fnum, (double)startpos, (int)numtowrite,
3906                 (int)nwritten, (int)write_through));
3907
3908         if (nwritten < (ssize_t)numtowrite)  {
3909                 reply_nterror(req, NT_STATUS_DISK_FULL);
3910                 error_to_writebrawerr(req);
3911                 goto strict_unlock;
3912         }
3913
3914         total_written = nwritten;
3915
3916         /* Allocate a buffer of 64k + length. */
3917         buf = TALLOC_ARRAY(NULL, char, 65540);
3918         if (!buf) {
3919                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3920                 error_to_writebrawerr(req);
3921                 goto strict_unlock;
3922         }
3923
3924         /* Return a SMBwritebraw message to the redirector to tell
3925          * it to send more bytes */
3926
3927         memcpy(buf, req->inbuf, smb_size);
3928         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3929         SCVAL(buf,smb_com,SMBwritebraw);
3930         SSVALS(buf,smb_vwv0,0xFFFF);
3931         show_msg(buf);
3932         if (!srv_send_smb(req->sconn->sock,
3933                           buf,
3934                           false, 0, /* no signing */
3935                           IS_CONN_ENCRYPTED(conn),
3936                           &req->pcd)) {
3937                 exit_server_cleanly("reply_writebraw: srv_send_smb "
3938                         "failed.");
3939         }
3940
3941         /* Now read the raw data into the buffer and write it */
3942         status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
3943                                  &numtowrite);
3944         if (!NT_STATUS_IS_OK(status)) {
3945                 exit_server_cleanly("secondary writebraw failed");
3946         }
3947
3948         /* Set up outbuf to return the correct size */
3949         reply_outbuf(req, 1, 0);
3950
3951         if (numtowrite != 0) {
3952
3953                 if (numtowrite > 0xFFFF) {
3954                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3955                                 "raw requested (%u). Terminating\n",
3956                                 (unsigned int)numtowrite ));
3957                         exit_server_cleanly("secondary writebraw failed");
3958                 }
3959
3960                 if (tcount > nwritten+numtowrite) {
3961                         DEBUG(3,("reply_writebraw: Client overestimated the "
3962                                 "write %d %d %d\n",
3963                                 (int)tcount,(int)nwritten,(int)numtowrite));
3964                 }
3965
3966                 status = read_data(req->sconn->sock, buf+4, numtowrite);
3967
3968                 if (!NT_STATUS_IS_OK(status)) {
3969                         char addr[INET6_ADDRSTRLEN];
3970                         /* Try and give an error message
3971                          * saying what client failed. */
3972                         DEBUG(0, ("reply_writebraw: Oversize secondary write "
3973                                   "raw read failed (%s) for client %s. "
3974                                   "Terminating\n", nt_errstr(status),
3975                                   get_peer_addr(req->sconn->sock, addr,
3976                                                 sizeof(addr))));
3977                         exit_server_cleanly("secondary writebraw failed");
3978                 }
3979
3980                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3981                 if (nwritten == -1) {
3982                         TALLOC_FREE(buf);
3983                         reply_nterror(req, map_nt_error_from_unix(errno));
3984                         error_to_writebrawerr(req);
3985                         goto strict_unlock;
3986                 }
3987
3988                 if (nwritten < (ssize_t)numtowrite) {
3989                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
3990                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
3991                 }
3992
3993                 if (nwritten > 0) {
3994                         total_written += nwritten;
3995                 }
3996         }
3997
3998         TALLOC_FREE(buf);
3999         SSVAL(req->outbuf,smb_vwv0,total_written);
4000
4001         status = sync_file(conn, fsp, write_through);
4002         if (!NT_STATUS_IS_OK(status)) {
4003                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4004                          fsp_str_dbg(fsp), nt_errstr(status)));
4005                 reply_nterror(req, status);
4006                 error_to_writebrawerr(req);
4007                 goto strict_unlock;
4008         }
4009
4010         DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4011                 "wrote=%d\n",
4012                 fsp->fnum, (double)startpos, (int)numtowrite,
4013                 (int)total_written));
4014
4015         if (!fsp->print_file) {
4016                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4017         }
4018
4019         /* We won't return a status if write through is not selected - this
4020          * follows what WfWg does */
4021         END_PROFILE(SMBwritebraw);
4022
4023         if (!write_through && total_written==tcount) {
4024
4025 #if RABBIT_PELLET_FIX
4026                 /*
4027                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4028                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4029                  * JRA.
4030                  */
4031                 if (!send_keepalive(req->sconn->sock)) {
4032                         exit_server_cleanly("reply_writebraw: send of "
4033                                 "keepalive failed");
4034                 }
4035 #endif
4036                 TALLOC_FREE(req->outbuf);
4037         }
4038         return;
4039
4040 strict_unlock:
4041         if (!fsp->print_file) {
4042                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4043         }
4044
4045         END_PROFILE(SMBwritebraw);
4046         return;
4047 }
4048
4049 #undef DBGC_CLASS
4050 #define DBGC_CLASS DBGC_LOCKING
4051
4052 /****************************************************************************
4053  Reply to a writeunlock (core+).
4054 ****************************************************************************/
4055
4056 void reply_writeunlock(struct smb_request *req)
4057 {
4058         connection_struct *conn = req->conn;
4059         ssize_t nwritten = -1;
4060         size_t numtowrite;
4061         SMB_OFF_T startpos;
4062         const char *data;
4063         NTSTATUS status = NT_STATUS_OK;
4064         files_struct *fsp;
4065         struct lock_struct lock;
4066         int saved_errno = 0;
4067
4068         START_PROFILE(SMBwriteunlock);
4069
4070         if (req->wct < 5) {
4071                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4072                 END_PROFILE(SMBwriteunlock);
4073                 return;
4074         }
4075
4076         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4077
4078         if (!check_fsp(conn, req, fsp)) {
4079                 END_PROFILE(SMBwriteunlock);
4080                 return;
4081         }
4082
4083         if (!CHECK_WRITE(fsp)) {
4084                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4085                 END_PROFILE(SMBwriteunlock);
4086                 return;
4087         }
4088
4089         numtowrite = SVAL(req->vwv+1, 0);
4090         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4091         data = (const char *)req->buf + 3;
4092
4093         if (!fsp->print_file && numtowrite > 0) {
4094                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4095                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4096                     &lock);
4097
4098                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4099                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4100                         END_PROFILE(SMBwriteunlock);
4101                         return;
4102                 }
4103         }
4104
4105         /* The special X/Open SMB protocol handling of
4106            zero length writes is *NOT* done for
4107            this call */
4108         if(numtowrite == 0) {
4109                 nwritten = 0;
4110         } else {
4111                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4112                 saved_errno = errno;
4113         }
4114
4115         status = sync_file(conn, fsp, False /* write through */);
4116         if (!NT_STATUS_IS_OK(status)) {
4117                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4118                          fsp_str_dbg(fsp), nt_errstr(status)));
4119                 reply_nterror(req, status);
4120                 goto strict_unlock;
4121         }
4122
4123         if(nwritten < 0) {
4124                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4125                 goto strict_unlock;
4126         }
4127
4128         if((nwritten < numtowrite) && (numtowrite != 0)) {
4129                 reply_nterror(req, NT_STATUS_DISK_FULL);
4130                 goto strict_unlock;
4131         }
4132
4133         if (numtowrite && !fsp->print_file) {
4134                 status = do_unlock(req->sconn->msg_ctx,
4135                                 fsp,
4136                                 (uint64_t)req->smbpid,
4137                                 (uint64_t)numtowrite, 
4138                                 (uint64_t)startpos,
4139                                 WINDOWS_LOCK);
4140
4141                 if (NT_STATUS_V(status)) {
4142                         reply_nterror(req, status);
4143                         goto strict_unlock;
4144                 }
4145         }
4146
4147         reply_outbuf(req, 1, 0);
4148
4149         SSVAL(req->outbuf,smb_vwv0,nwritten);
4150
4151         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4152                  fsp->fnum, (int)numtowrite, (int)nwritten));
4153
4154 strict_unlock:
4155         if (numtowrite && !fsp->print_file) {
4156                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4157         }
4158
4159         END_PROFILE(SMBwriteunlock);
4160         return;
4161 }
4162
4163 #undef DBGC_CLASS
4164 #define DBGC_CLASS DBGC_ALL
4165
4166 /****************************************************************************
4167  Reply to a write.
4168 ****************************************************************************/
4169
4170 void reply_write(struct smb_request *req)
4171 {
4172         connection_struct *conn = req->conn;
4173         size_t numtowrite;
4174         ssize_t nwritten = -1;
4175         SMB_OFF_T startpos;
4176         const char *data;
4177         files_struct *fsp;
4178         struct lock_struct lock;
4179         NTSTATUS status;
4180         int saved_errno = 0;
4181
4182         START_PROFILE(SMBwrite);
4183
4184         if (req->wct < 5) {
4185                 END_PROFILE(SMBwrite);
4186                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4187                 return;
4188         }
4189
4190         /* If it's an IPC, pass off the pipe handler. */
4191         if (IS_IPC(conn)) {
4192                 reply_pipe_write(req);
4193                 END_PROFILE(SMBwrite);
4194                 return;
4195         }
4196
4197         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4198
4199         if (!check_fsp(conn, req, fsp)) {
4200                 END_PROFILE(SMBwrite);
4201                 return;
4202         }
4203
4204         if (!CHECK_WRITE(fsp)) {
4205                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4206                 END_PROFILE(SMBwrite);
4207                 return;
4208         }
4209
4210         numtowrite = SVAL(req->vwv+1, 0);
4211         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4212         data = (const char *)req->buf + 3;
4213
4214         if (!fsp->print_file) {
4215                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4216                         (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4217                         &lock);
4218
4219                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4220                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4221                         END_PROFILE(SMBwrite);
4222                         return;
4223                 }
4224         }
4225
4226         /*
4227          * X/Open SMB protocol says that if smb_vwv1 is
4228          * zero then the file size should be extended or
4229          * truncated to the size given in smb_vwv[2-3].
4230          */
4231
4232         if(numtowrite == 0) {
4233                 /*
4234                  * This is actually an allocate call, and set EOF. JRA.
4235                  */
4236                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4237                 if (nwritten < 0) {
4238                         reply_nterror(req, NT_STATUS_DISK_FULL);
4239                         goto strict_unlock;
4240                 }
4241                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4242                 if (nwritten < 0) {
4243                         reply_nterror(req, NT_STATUS_DISK_FULL);
4244                         goto strict_unlock;
4245                 }
4246                 trigger_write_time_update_immediate(fsp);
4247         } else {
4248                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4249         }
4250
4251         status = sync_file(conn, fsp, False);
4252         if (!NT_STATUS_IS_OK(status)) {
4253                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4254                          fsp_str_dbg(fsp), nt_errstr(status)));
4255                 reply_nterror(req, status);
4256                 goto strict_unlock;
4257         }
4258
4259         if(nwritten < 0) {
4260                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4261                 goto strict_unlock;
4262         }
4263
4264         if((nwritten == 0) && (numtowrite != 0)) {
4265                 reply_nterror(req, NT_STATUS_DISK_FULL);
4266                 goto strict_unlock;
4267         }
4268
4269         reply_outbuf(req, 1, 0);
4270
4271         SSVAL(req->outbuf,smb_vwv0,nwritten);
4272
4273         if (nwritten < (ssize_t)numtowrite) {
4274                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4275                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4276         }
4277
4278         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4279
4280 strict_unlock:
4281         if (!fsp->print_file) {
4282                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4283         }
4284
4285         END_PROFILE(SMBwrite);
4286         return;
4287 }
4288
4289 /****************************************************************************
4290  Ensure a buffer is a valid writeX for recvfile purposes.
4291 ****************************************************************************/
4292
4293 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4294                                                 (2*14) + /* word count (including bcc) */ \
4295                                                 1 /* pad byte */)
4296
4297 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4298                             const uint8_t *inbuf)
4299 {
4300         size_t numtowrite;
4301         connection_struct *conn = NULL;
4302         unsigned int doff = 0;
4303         size_t len = smb_len_large(inbuf);
4304
4305         if (is_encrypted_packet(inbuf)) {
4306                 /* Can't do this on encrypted
4307                  * connections. */
4308                 return false;
4309         }
4310
4311         if (CVAL(inbuf,smb_com) != SMBwriteX) {
4312                 return false;
4313         }
4314
4315         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4316                         CVAL(inbuf,smb_wct) != 14) {
4317                 DEBUG(10,("is_valid_writeX_buffer: chained or "
4318                         "invalid word length.\n"));
4319                 return false;
4320         }
4321
4322         conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4323         if (conn == NULL) {
4324                 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4325                 return false;
4326         }
4327         if (IS_IPC(conn)) {
4328                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4329                 return false;
4330         }
4331         if (IS_PRINT(conn)) {
4332                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4333                 return false;
4334         }
4335         doff = SVAL(inbuf,smb_vwv11);
4336
4337         numtowrite = SVAL(inbuf,smb_vwv10);
4338
4339         if (len > doff && len - doff > 0xFFFF) {
4340                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4341         }
4342
4343         if (numtowrite == 0) {
4344                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4345                 return false;
4346         }
4347
4348         /* Ensure the sizes match up. */
4349         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4350                 /* no pad byte...old smbclient :-( */
4351                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4352                         (unsigned int)doff,
4353                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4354                 return false;
4355         }
4356
4357         if (len - doff != numtowrite) {
4358                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4359                         "len = %u, doff = %u, numtowrite = %u\n",
4360                         (unsigned int)len,
4361                         (unsigned int)doff,
4362                         (unsigned int)numtowrite ));
4363                 return false;
4364         }
4365
4366         DEBUG(10,("is_valid_writeX_buffer: true "
4367                 "len = %u, doff = %u, numtowrite = %u\n",
4368                 (unsigned int)len,
4369                 (unsigned int)doff,
4370                 (unsigned int)numtowrite ));
4371
4372         return true;
4373 }
4374
4375 /****************************************************************************
4376  Reply to a write and X.
4377 ****************************************************************************/
4378
4379 void reply_write_and_X(struct smb_request *req)
4380 {
4381         connection_struct *conn = req->conn;
4382         files_struct *fsp;
4383         struct lock_struct lock;
4384         SMB_OFF_T startpos;
4385         size_t numtowrite;
4386         bool write_through;
4387         ssize_t nwritten;
4388         unsigned int smb_doff;
4389         unsigned int smblen;
4390         char *data;
4391         NTSTATUS status;
4392         int saved_errno = 0;
4393
4394         START_PROFILE(SMBwriteX);
4395
4396         if ((req->wct != 12) && (req->wct != 14)) {
4397                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4398                 END_PROFILE(SMBwriteX);
4399                 return;
4400         }
4401
4402         numtowrite = SVAL(req->vwv+10, 0);
4403         smb_doff = SVAL(req->vwv+11, 0);
4404         smblen = smb_len(req->inbuf);
4405
4406         if (req->unread_bytes > 0xFFFF ||
4407                         (smblen > smb_doff &&
4408                                 smblen - smb_doff > 0xFFFF)) {
4409                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4410         }
4411
4412         if (req->unread_bytes) {
4413                 /* Can't do a recvfile write on IPC$ */
4414                 if (IS_IPC(conn)) {
4415                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4416                         END_PROFILE(SMBwriteX);
4417                         return;
4418                 }
4419                 if (numtowrite != req->unread_bytes) {
4420                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4421                         END_PROFILE(SMBwriteX);
4422                         return;
4423                 }
4424         } else {
4425                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4426                                 smb_doff + numtowrite > smblen) {
4427                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4428                         END_PROFILE(SMBwriteX);
4429                         return;
4430                 }
4431         }
4432
4433         /* If it's an IPC, pass off the pipe handler. */
4434         if (IS_IPC(conn)) {
4435                 if (req->unread_bytes) {
4436                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4437                         END_PROFILE(SMBwriteX);
4438                         return;
4439                 }
4440                 reply_pipe_write_and_X(req);
4441                 END_PROFILE(SMBwriteX);
4442                 return;
4443         }
4444
4445         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4446         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4447         write_through = BITSETW(req->vwv+7,0);
4448
4449         if (!check_fsp(conn, req, fsp)) {
4450                 END_PROFILE(SMBwriteX);
4451                 return;
4452         }
4453
4454         if (!CHECK_WRITE(fsp)) {
4455                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4456                 END_PROFILE(SMBwriteX);
4457                 return;
4458         }
4459
4460         data = smb_base(req->inbuf) + smb_doff;
4461
4462         if(req->wct == 14) {
4463 #ifdef LARGE_SMB_OFF_T
4464                 /*
4465                  * This is a large offset (64 bit) write.
4466                  */
4467                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4468
4469 #else /* !LARGE_SMB_OFF_T */
4470
4471                 /*
4472                  * Ensure we haven't been sent a >32 bit offset.
4473                  */
4474
4475                 if(IVAL(req->vwv+12, 0) != 0) {
4476                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4477                                  "used and we don't support 64 bit offsets.\n",
4478                                  (unsigned int)IVAL(req->vwv+12, 0) ));
4479                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4480                         END_PROFILE(SMBwriteX);
4481                         return;
4482                 }
4483
4484 #endif /* LARGE_SMB_OFF_T */
4485         }
4486
4487         /* X/Open SMB protocol says that, unlike SMBwrite
4488         if the length is zero then NO truncation is
4489         done, just a write of zero. To truncate a file,
4490         use SMBwrite. */
4491
4492         if(numtowrite == 0) {
4493                 nwritten = 0;
4494         } else {
4495                 if (req->unread_bytes == 0) {
4496                         status = schedule_aio_write_and_X(conn,
4497                                                 req,
4498                                                 fsp,
4499                                                 data,
4500                                                 startpos,
4501                                                 numtowrite);
4502
4503                         if (NT_STATUS_IS_OK(status)) {
4504                                 /* write scheduled - we're done. */
4505                                 goto out;
4506                         }
4507                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4508                                 /* Real error - report to client. */
4509                                 reply_nterror(req, status);
4510                                 goto out;
4511                         }
4512                         /* NT_STATUS_RETRY - fall through to sync write. */
4513                 }
4514
4515                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4516                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4517                     &lock);
4518
4519                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4520                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4521                         goto out;
4522                 }
4523
4524                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4525                 saved_errno = errno;
4526
4527                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4528         }
4529
4530         if(nwritten < 0) {
4531                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4532                 goto out;
4533         }
4534
4535         if((nwritten == 0) && (numtowrite != 0)) {
4536                 reply_nterror(req, NT_STATUS_DISK_FULL);
4537                 goto out;
4538         }
4539
4540         reply_outbuf(req, 6, 0);
4541         SSVAL(req->outbuf,smb_vwv2,nwritten);
4542         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4543
4544         if (nwritten < (ssize_t)numtowrite) {
4545                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4546                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4547         }
4548
4549         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4550                 fsp->fnum, (int)numtowrite, (int)nwritten));
4551
4552         status = sync_file(conn, fsp, write_through);
4553         if (!NT_STATUS_IS_OK(status)) {
4554                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4555                          fsp_str_dbg(fsp), nt_errstr(status)));
4556                 reply_nterror(req, status);
4557                 goto out;
4558         }
4559
4560         END_PROFILE(SMBwriteX);
4561         chain_reply(req);
4562         return;
4563
4564 out:
4565         END_PROFILE(SMBwriteX);
4566         return;
4567 }
4568
4569 /****************************************************************************
4570  Reply to a lseek.
4571 ****************************************************************************/
4572
4573 void reply_lseek(struct smb_request *req)
4574 {
4575         connection_struct *conn = req->conn;
4576         SMB_OFF_T startpos;
4577         SMB_OFF_T res= -1;
4578         int mode,umode;
4579         files_struct *fsp;
4580
4581         START_PROFILE(SMBlseek);
4582
4583         if (req->wct < 4) {
4584                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4585                 END_PROFILE(SMBlseek);
4586                 return;
4587         }
4588
4589         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4590
4591         if (!check_fsp(conn, req, fsp)) {
4592                 return;
4593         }
4594
4595         flush_write_cache(fsp, SEEK_FLUSH);
4596
4597         mode = SVAL(req->vwv+1, 0) & 3;
4598         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4599         startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4600
4601         switch (mode) {
4602                 case 0:
4603                         umode = SEEK_SET;
4604                         res = startpos;
4605                         break;
4606                 case 1:
4607                         umode = SEEK_CUR;
4608                         res = fsp->fh->pos + startpos;
4609                         break;
4610                 case 2:
4611                         umode = SEEK_END;
4612                         break;
4613                 default:
4614                         umode = SEEK_SET;
4615                         res = startpos;
4616                         break;
4617         }
4618
4619         if (umode == SEEK_END) {
4620                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4621                         if(errno == EINVAL) {
4622                                 SMB_OFF_T current_pos = startpos;
4623
4624                                 if(fsp_stat(fsp) == -1) {
4625                                         reply_nterror(req,
4626                                                 map_nt_error_from_unix(errno));
4627                                         END_PROFILE(SMBlseek);
4628                                         return;
4629                                 }
4630
4631                                 current_pos += fsp->fsp_name->st.st_ex_size;
4632                                 if(current_pos < 0)
4633                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4634                         }
4635                 }
4636
4637                 if(res == -1) {
4638                         reply_nterror(req, map_nt_error_from_unix(errno));
4639                         END_PROFILE(SMBlseek);
4640                         return;
4641                 }
4642         }
4643
4644         fsp->fh->pos = res;
4645
4646         reply_outbuf(req, 2, 0);
4647         SIVAL(req->outbuf,smb_vwv0,res);
4648
4649         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4650                 fsp->fnum, (double)startpos, (double)res, mode));
4651
4652         END_PROFILE(SMBlseek);
4653         return;
4654 }
4655
4656 /****************************************************************************
4657  Reply to a flush.
4658 ****************************************************************************/
4659
4660 void reply_flush(struct smb_request *req)
4661 {
4662         connection_struct *conn = req->conn;
4663         uint16 fnum;
4664         files_struct *fsp;
4665
4666         START_PROFILE(SMBflush);
4667
4668         if (req->wct < 1) {
4669                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4670                 return;
4671         }
4672
4673         fnum = SVAL(req->vwv+0, 0);
4674         fsp = file_fsp(req, fnum);
4675
4676         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4677                 return;
4678         }
4679
4680         if (!fsp) {
4681                 file_sync_all(conn);
4682         } else {
4683                 NTSTATUS status = sync_file(conn, fsp, True);
4684                 if (!NT_STATUS_IS_OK(status)) {
4685                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4686                                 fsp_str_dbg(fsp), nt_errstr(status)));
4687                         reply_nterror(req, status);
4688                         END_PROFILE(SMBflush);
4689                         return;
4690                 }
4691         }
4692
4693         reply_outbuf(req, 0, 0);
4694
4695         DEBUG(3,("flush\n"));
4696         END_PROFILE(SMBflush);
4697         return;
4698 }
4699
4700 /****************************************************************************
4701  Reply to a exit.
4702  conn POINTER CAN BE NULL HERE !
4703 ****************************************************************************/
4704
4705 void reply_exit(struct smb_request *req)
4706 {
4707         START_PROFILE(SMBexit);
4708
4709         file_close_pid(req->smbpid, req->vuid);
4710
4711         reply_outbuf(req, 0, 0);
4712
4713         DEBUG(3,("exit\n"));
4714
4715         END_PROFILE(SMBexit);
4716         return;
4717 }
4718
4719 /****************************************************************************
4720  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4721 ****************************************************************************/
4722
4723 void reply_close(struct smb_request *req)
4724 {
4725         connection_struct *conn = req->conn;
4726         NTSTATUS status = NT_STATUS_OK;
4727         files_struct *fsp = NULL;
4728         START_PROFILE(SMBclose);
4729
4730         if (req->wct < 3) {
4731                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4732                 END_PROFILE(SMBclose);
4733                 return;
4734         }
4735
4736         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4737
4738         /*
4739          * We can only use check_fsp if we know it's not a directory.
4740          */
4741
4742         if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4743                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4744                 END_PROFILE(SMBclose);
4745                 return;
4746         }
4747
4748         if(fsp->is_directory) {
4749                 /*
4750                  * Special case - close NT SMB directory handle.
4751                  */
4752                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4753                 status = close_file(req, fsp, NORMAL_CLOSE);
4754         } else {
4755                 time_t t;
4756                 /*
4757                  * Close ordinary file.
4758                  */
4759
4760                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4761                          fsp->fh->fd, fsp->fnum,
4762                          conn->num_files_open));
4763
4764                 /*
4765                  * Take care of any time sent in the close.
4766                  */
4767
4768                 t = srv_make_unix_date3(req->vwv+1);
4769                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4770
4771                 /*
4772                  * close_file() returns the unix errno if an error
4773                  * was detected on close - normally this is due to
4774                  * a disk full error. If not then it was probably an I/O error.
4775                  */
4776
4777                 status = close_file(req, fsp, NORMAL_CLOSE);
4778         }  
4779
4780         if (!NT_STATUS_IS_OK(status)) {
4781                 reply_nterror(req, status);
4782                 END_PROFILE(SMBclose);
4783                 return;
4784         }
4785
4786         reply_outbuf(req, 0, 0);
4787         END_PROFILE(SMBclose);
4788         return;
4789 }
4790
4791 /****************************************************************************
4792  Reply to a writeclose (Core+ protocol).
4793 ****************************************************************************/
4794
4795 void reply_writeclose(struct smb_request *req)
4796 {
4797         connection_struct *conn = req->conn;
4798         size_t numtowrite;
4799         ssize_t nwritten = -1;
4800         NTSTATUS close_status = NT_STATUS_OK;
4801         SMB_OFF_T startpos;
4802         const char *data;
4803         struct timespec mtime;
4804         files_struct *fsp;
4805         struct lock_struct lock;
4806
4807         START_PROFILE(SMBwriteclose);
4808
4809         if (req->wct < 6) {
4810                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4811                 END_PROFILE(SMBwriteclose);
4812                 return;
4813         }
4814
4815         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4816
4817         if (!check_fsp(conn, req, fsp)) {
4818                 END_PROFILE(SMBwriteclose);
4819                 return;
4820         }
4821         if (!CHECK_WRITE(fsp)) {
4822                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4823                 END_PROFILE(SMBwriteclose);
4824                 return;
4825         }
4826
4827         numtowrite = SVAL(req->vwv+1, 0);
4828         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4829         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4830         data = (const char *)req->buf + 1;
4831
4832         if (!fsp->print_file) {
4833                 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4834                     (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4835                     &lock);
4836
4837                 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4838                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4839                         END_PROFILE(SMBwriteclose);
4840                         return;
4841                 }
4842         }
4843
4844         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4845
4846         set_close_write_time(fsp, mtime);
4847
4848         /*
4849          * More insanity. W2K only closes the file if writelen > 0.
4850          * JRA.
4851          */
4852
4853         if (numtowrite) {
4854                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4855                          "file %s\n", fsp_str_dbg(fsp)));
4856                 close_status = close_file(req, fsp, NORMAL_CLOSE);
4857         }
4858
4859         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4860                  fsp->fnum, (int)numtowrite, (int)nwritten,
4861                  conn->num_files_open));
4862
4863         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4864                 reply_nterror(req, NT_STATUS_DISK_FULL);
4865                 goto strict_unlock;
4866         }
4867
4868         if(!NT_STATUS_IS_OK(close_status)) {
4869                 reply_nterror(req, close_status);
4870                 goto strict_unlock;
4871         }
4872
4873         reply_outbuf(req, 1, 0);
4874
4875         SSVAL(req->outbuf,smb_vwv0,nwritten);
4876
4877 strict_unlock:
4878         if (numtowrite && !fsp->print_file) {
4879                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4880         }
4881
4882         END_PROFILE(SMBwriteclose);
4883         return;
4884 }
4885
4886 #undef DBGC_CLASS
4887 #define DBGC_CLASS DBGC_LOCKING
4888
4889 /****************************************************************************
4890  Reply to a lock.
4891 ****************************************************************************/
4892
4893 void reply_lock(struct smb_request *req)
4894 {
4895         connection_struct *conn = req->conn;
4896         uint64_t count,offset;
4897         NTSTATUS status;
4898         files_struct *fsp;
4899         struct byte_range_lock *br_lck = NULL;
4900
4901         START_PROFILE(SMBlock);
4902
4903         if (req->wct < 5) {
4904                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4905                 END_PROFILE(SMBlock);
4906                 return;
4907         }
4908
4909         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4910
4911         if (!check_fsp(conn, req, fsp)) {
4912                 END_PROFILE(SMBlock);
4913                 return;
4914         }
4915
4916         count = (uint64_t)IVAL(req->vwv+1, 0);
4917         offset = (uint64_t)IVAL(req->vwv+3, 0);
4918
4919         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4920                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4921
4922         br_lck = do_lock(req->sconn->msg_ctx,
4923                         fsp,
4924                         (uint64_t)req->smbpid,
4925                         count,
4926                         offset,
4927                         WRITE_LOCK,
4928                         WINDOWS_LOCK,
4929                         False, /* Non-blocking lock. */
4930                         &status,
4931                         NULL,
4932                         NULL);
4933
4934         TALLOC_FREE(br_lck);
4935
4936         if (NT_STATUS_V(status)) {
4937                 reply_nterror(req, status);
4938                 END_PROFILE(SMBlock);
4939                 return;
4940         }
4941
4942         reply_outbuf(req, 0, 0);
4943
4944         END_PROFILE(SMBlock);
4945         return;
4946 }
4947
4948 /****************************************************************************
4949  Reply to a unlock.
4950 ****************************************************************************/
4951
4952 void reply_unlock(struct smb_request *req)
4953 {
4954         connection_struct *conn = req->conn;
4955         uint64_t count,offset;
4956         NTSTATUS status;
4957         files_struct *fsp;
4958
4959         START_PROFILE(SMBunlock);
4960
4961         if (req->wct < 5) {
4962                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4963                 END_PROFILE(SMBunlock);
4964                 return;
4965         }
4966
4967         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4968
4969         if (!check_fsp(conn, req, fsp)) {
4970                 END_PROFILE(SMBunlock);
4971                 return;
4972         }
4973
4974         count = (uint64_t)IVAL(req->vwv+1, 0);
4975         offset = (uint64_t)IVAL(req->vwv+3, 0);
4976
4977         status = do_unlock(req->sconn->msg_ctx,
4978                         fsp,
4979                         (uint64_t)req->smbpid,
4980                         count,
4981                         offset,
4982                         WINDOWS_LOCK);
4983
4984         if (NT_STATUS_V(status)) {
4985                 reply_nterror(req, status);
4986                 END_PROFILE(SMBunlock);
4987                 return;
4988         }
4989
4990         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4991                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4992
4993         reply_outbuf(req, 0, 0);
4994
4995         END_PROFILE(SMBunlock);
4996         return;
4997 }
4998
4999 #undef DBGC_CLASS
5000 #define DBGC_CLASS DBGC_ALL
5001
5002 /****************************************************************************
5003  Reply to a tdis.
5004  conn POINTER CAN BE NULL HERE !
5005 ****************************************************************************/
5006
5007 void reply_tdis(struct smb_request *req)
5008 {
5009         connection_struct *conn = req->conn;
5010         START_PROFILE(SMBtdis);
5011
5012         if (!conn) {
5013                 DEBUG(4,("Invalid connection in tdis\n"));
5014                 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5015                 END_PROFILE(SMBtdis);
5016                 return;
5017         }
5018
5019         conn->used = False;
5020
5021         close_cnum(conn,req->vuid);
5022         req->conn = NULL;
5023
5024         reply_outbuf(req, 0, 0);
5025         END_PROFILE(SMBtdis);
5026         return;
5027 }
5028
5029 /****************************************************************************
5030  Reply to a echo.
5031  conn POINTER CAN BE NULL HERE !
5032 ****************************************************************************/
5033
5034 void reply_echo(struct smb_request *req)
5035 {
5036         connection_struct *conn = req->conn;
5037         struct smb_perfcount_data local_pcd;
5038         struct smb_perfcount_data *cur_pcd;
5039         int smb_reverb;
5040         int seq_num;
5041
5042         START_PROFILE(SMBecho);
5043
5044         smb_init_perfcount_data(&local_pcd);
5045
5046         if (req->wct < 1) {
5047                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5048                 END_PROFILE(SMBecho);
5049                 return;
5050         }
5051
5052         smb_reverb = SVAL(req->vwv+0, 0);
5053
5054         reply_outbuf(req, 1, req->buflen);
5055
5056         /* copy any incoming data back out */
5057         if (req->buflen > 0) {
5058                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5059         }
5060
5061         if (smb_reverb > 100) {
5062                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5063                 smb_reverb = 100;
5064         }
5065
5066         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5067
5068                 /* this makes sure we catch the request pcd */
5069                 if (seq_num == smb_reverb) {
5070                         cur_pcd = &req->pcd;
5071                 } else {
5072                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5073                         cur_pcd = &local_pcd;
5074                 }
5075
5076                 SSVAL(req->outbuf,smb_vwv0,seq_num);
5077
5078                 show_msg((char *)req->outbuf);
5079                 if (!srv_send_smb(req->sconn->sock,
5080                                 (char *)req->outbuf,
5081                                 true, req->seqnum+1,
5082                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5083                                 cur_pcd))
5084                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
5085         }
5086
5087         DEBUG(3,("echo %d times\n", smb_reverb));
5088
5089         TALLOC_FREE(req->outbuf);
5090
5091         END_PROFILE(SMBecho);
5092         return;
5093 }
5094
5095 /****************************************************************************
5096  Reply to a printopen.
5097 ****************************************************************************/
5098
5099 void reply_printopen(struct smb_request *req)
5100 {
5101         connection_struct *conn = req->conn;
5102         files_struct *fsp;
5103         NTSTATUS status;
5104
5105         START_PROFILE(SMBsplopen);
5106
5107         if (req->wct < 2) {
5108                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5109                 END_PROFILE(SMBsplopen);
5110                 return;
5111         }
5112
5113         if (!CAN_PRINT(conn)) {
5114                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5115                 END_PROFILE(SMBsplopen);
5116                 return;
5117         }
5118
5119         status = file_new(req, conn, &fsp);
5120         if(!NT_STATUS_IS_OK(status)) {
5121                 reply_nterror(req, status);
5122                 END_PROFILE(SMBsplopen);
5123                 return;
5124         }
5125
5126         /* Open for exclusive use, write only. */
5127         status = print_spool_open(fsp, NULL, req->vuid);
5128
5129         if (!NT_STATUS_IS_OK(status)) {
5130                 file_free(req, fsp);
5131                 reply_nterror(req, status);
5132                 END_PROFILE(SMBsplopen);
5133                 return;
5134         }
5135
5136         reply_outbuf(req, 1, 0);
5137         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5138
5139         DEBUG(3,("openprint fd=%d fnum=%d\n",
5140                  fsp->fh->fd, fsp->fnum));
5141
5142         END_PROFILE(SMBsplopen);
5143         return;
5144 }
5145
5146 /****************************************************************************
5147  Reply to a printclose.
5148 ****************************************************************************/
5149
5150 void reply_printclose(struct smb_request *req)
5151 {
5152         connection_struct *conn = req->conn;
5153         files_struct *fsp;
5154         NTSTATUS status;
5155
5156         START_PROFILE(SMBsplclose);
5157
5158         if (req->wct < 1) {
5159                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5160                 END_PROFILE(SMBsplclose);
5161                 return;
5162         }
5163
5164         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5165
5166         if (!check_fsp(conn, req, fsp)) {
5167                 END_PROFILE(SMBsplclose);
5168                 return;
5169         }
5170
5171         if (!CAN_PRINT(conn)) {
5172                 reply_force_doserror(req, ERRSRV, ERRerror);
5173                 END_PROFILE(SMBsplclose);
5174                 return;
5175         }
5176
5177         DEBUG(3,("printclose fd=%d fnum=%d\n",
5178                  fsp->fh->fd,fsp->fnum));
5179
5180         status = close_file(req, fsp, NORMAL_CLOSE);
5181
5182         if(!NT_STATUS_IS_OK(status)) {
5183                 reply_nterror(req, status);
5184                 END_PROFILE(SMBsplclose);
5185                 return;
5186         }
5187
5188         reply_outbuf(req, 0, 0);
5189
5190         END_PROFILE(SMBsplclose);
5191         return;
5192 }
5193
5194 /****************************************************************************
5195  Reply to a printqueue.
5196 ****************************************************************************/
5197
5198 void reply_printqueue(struct smb_request *req)
5199 {
5200         connection_struct *conn = req->conn;
5201         int max_count;
5202         int start_index;
5203
5204         START_PROFILE(SMBsplretq);
5205
5206         if (req->wct < 2) {
5207                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5208                 END_PROFILE(SMBsplretq);
5209                 return;
5210         }
5211
5212         max_count = SVAL(req->vwv+0, 0);
5213         start_index = SVAL(req->vwv+1, 0);
5214
5215         /* we used to allow the client to get the cnum wrong, but that
5216            is really quite gross and only worked when there was only
5217            one printer - I think we should now only accept it if they
5218            get it right (tridge) */
5219         if (!CAN_PRINT(conn)) {
5220                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5221                 END_PROFILE(SMBsplretq);
5222                 return;
5223         }
5224
5225         reply_outbuf(req, 2, 3);
5226         SSVAL(req->outbuf,smb_vwv0,0);
5227         SSVAL(req->outbuf,smb_vwv1,0);
5228         SCVAL(smb_buf(req->outbuf),0,1);
5229         SSVAL(smb_buf(req->outbuf),1,0);
5230
5231         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5232                  start_index, max_count));
5233
5234         {
5235                 TALLOC_CTX *mem_ctx = talloc_tos();
5236                 NTSTATUS status;
5237                 WERROR werr;
5238                 const char *sharename = lp_servicename(SNUM(conn));
5239                 struct rpc_pipe_client *cli = NULL;
5240                 struct policy_handle handle;
5241                 struct spoolss_DevmodeContainer devmode_ctr;
5242                 union spoolss_JobInfo *info;
5243                 uint32_t count;
5244                 uint32_t num_to_get;
5245                 uint32_t first;
5246                 uint32_t i;
5247
5248                 ZERO_STRUCT(handle);
5249
5250                 status = rpc_connect_spoolss_pipe(conn, &cli);
5251                 if (!NT_STATUS_IS_OK(status)) {
5252                         DEBUG(0, ("reply_printqueue: "
5253                                   "could not connect to spoolss: %s\n",
5254                                   nt_errstr(status)));
5255                         reply_nterror(req, status);
5256                         goto out;
5257                 }
5258
5259                 ZERO_STRUCT(devmode_ctr);
5260
5261                 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5262                                                 sharename,
5263                                                 NULL, devmode_ctr,
5264                                                 SEC_FLAG_MAXIMUM_ALLOWED,
5265                                                 &handle,
5266                                                 &werr);
5267                 if (!NT_STATUS_IS_OK(status)) {
5268                         reply_nterror(req, status);
5269                         goto out;
5270                 }
5271                 if (!W_ERROR_IS_OK(werr)) {
5272                         reply_nterror(req, werror_to_ntstatus(werr));
5273                         goto out;
5274                 }
5275
5276                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5277                                                &handle,
5278                                                0, /* firstjob */
5279                                                0xff, /* numjobs */
5280                                                2, /* level */
5281                                                0, /* offered */
5282                                                &count,
5283                                                &info);
5284                 if (!W_ERROR_IS_OK(werr)) {
5285                         reply_nterror(req, werror_to_ntstatus(werr));
5286                         goto out;
5287                 }
5288
5289                 if (max_count > 0) {
5290                         first = start_index;
5291                 } else {
5292                         first = start_index + max_count + 1;
5293                 }
5294
5295                 if (first >= count) {
5296                         num_to_get = first;
5297                 } else {
5298                         num_to_get = first + MIN(ABS(max_count), count - first);
5299                 }
5300
5301                 for (i = first; i < num_to_get; i++) {
5302                         char blob[28];
5303                         char *p = blob;
5304                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5305                         int qstatus;
5306                         uint16_t qrapjobid = pjobid_to_rap(sharename,
5307                                                         info[i].info2.job_id);
5308
5309                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
5310                                 qstatus = 2;
5311                         } else {
5312                                 qstatus = 3;
5313                         }
5314
5315                         srv_put_dos_date2(p, 0, qtime);
5316                         SCVAL(p, 4, qstatus);
5317                         SSVAL(p, 5, qrapjobid);
5318                         SIVAL(p, 7, info[i].info2.size);
5319                         SCVAL(p, 11, 0);
5320                         srvstr_push(blob, req->flags2, p+12,
5321                                     info[i].info2.notify_name, 16, STR_ASCII);
5322
5323                         if (message_push_blob(
5324                                     &req->outbuf,
5325                                     data_blob_const(
5326                                             blob, sizeof(blob))) == -1) {
5327                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5328                                 goto out;
5329                         }
5330                 }
5331
5332                 if (count > 0) {
5333                         SSVAL(req->outbuf,smb_vwv0,count);
5334                         SSVAL(req->outbuf,smb_vwv1,
5335                               (max_count>0?first+count:first-1));
5336                         SCVAL(smb_buf(req->outbuf),0,1);
5337                         SSVAL(smb_buf(req->outbuf),1,28*count);
5338                 }
5339
5340
5341                 DEBUG(3, ("%u entries returned in queue\n",
5342                           (unsigned)count));
5343
5344 out:
5345                 if (cli && is_valid_policy_hnd(&handle)) {
5346                         rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5347                 }
5348
5349         }
5350
5351         END_PROFILE(SMBsplretq);
5352         return;
5353 }
5354
5355 /****************************************************************************
5356  Reply to a printwrite.
5357 ****************************************************************************/
5358
5359 void reply_printwrite(struct smb_request *req)
5360 {
5361         connection_struct *conn = req->conn;
5362         int numtowrite;
5363         const char *data;
5364         files_struct *fsp;
5365
5366         START_PROFILE(SMBsplwr);
5367
5368         if (req->wct < 1) {
5369                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5370                 END_PROFILE(SMBsplwr);
5371                 return;
5372         }
5373
5374         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5375
5376         if (!check_fsp(conn, req, fsp)) {
5377                 END_PROFILE(SMBsplwr);
5378                 return;
5379         }
5380
5381         if (!fsp->print_file) {
5382                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5383                 END_PROFILE(SMBsplwr);
5384                 return;
5385         }
5386
5387         if (!CHECK_WRITE(fsp)) {
5388                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5389                 END_PROFILE(SMBsplwr);
5390                 return;
5391         }
5392
5393         numtowrite = SVAL(req->buf, 1);
5394
5395         if (req->buflen < numtowrite + 3) {
5396                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5397                 END_PROFILE(SMBsplwr);
5398                 return;
5399         }
5400
5401         data = (const char *)req->buf + 3;
5402
5403         if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5404                 reply_nterror(req, map_nt_error_from_unix(errno));
5405                 END_PROFILE(SMBsplwr);
5406                 return;
5407         }
5408
5409         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5410
5411         END_PROFILE(SMBsplwr);
5412         return;
5413 }
5414
5415 /****************************************************************************
5416  Reply to a mkdir.
5417 ****************************************************************************/
5418
5419 void reply_mkdir(struct smb_request *req)
5420 {
5421         connection_struct *conn = req->conn;
5422         struct smb_filename *smb_dname = NULL;
5423         char *directory = NULL;
5424         NTSTATUS status;
5425         TALLOC_CTX *ctx = talloc_tos();
5426
5427         START_PROFILE(SMBmkdir);
5428
5429         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5430                             STR_TERMINATE, &status);
5431         if (!NT_STATUS_IS_OK(status)) {
5432                 reply_nterror(req, status);
5433                 goto out;
5434         }
5435
5436         status = filename_convert(ctx, conn,
5437                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5438                                  directory,
5439                                  0,
5440                                  NULL,
5441                                  &smb_dname);
5442         if (!NT_STATUS_IS_OK(status)) {
5443                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5444                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5445                                         ERRSRV, ERRbadpath);
5446                         goto out;
5447                 }
5448                 reply_nterror(req, status);
5449                 goto out;
5450         }
5451
5452         status = create_directory(conn, req, smb_dname);
5453
5454         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5455
5456         if (!NT_STATUS_IS_OK(status)) {
5457
5458                 if (!use_nt_status()
5459                     && NT_STATUS_EQUAL(status,
5460                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
5461                         /*
5462                          * Yes, in the DOS error code case we get a
5463                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5464                          * samba4 torture test.
5465                          */
5466                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5467                 }
5468
5469                 reply_nterror(req, status);
5470                 goto out;
5471         }
5472
5473         reply_outbuf(req, 0, 0);
5474
5475         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5476  out:
5477         TALLOC_FREE(smb_dname);
5478         END_PROFILE(SMBmkdir);
5479         return;
5480 }
5481
5482 /****************************************************************************
5483  Reply to a rmdir.
5484 ****************************************************************************/
5485
5486 void reply_rmdir(struct smb_request *req)
5487 {
5488         connection_struct *conn = req->conn;
5489         struct smb_filename *smb_dname = NULL;
5490         char *directory = NULL;
5491         NTSTATUS status;
5492         TALLOC_CTX *ctx = talloc_tos();
5493         files_struct *fsp = NULL;
5494         int info = 0;
5495         struct smbd_server_connection *sconn = req->sconn;
5496
5497         START_PROFILE(SMBrmdir);
5498
5499         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5500                             STR_TERMINATE, &status);
5501         if (!NT_STATUS_IS_OK(status)) {
5502                 reply_nterror(req, status);
5503                 goto out;
5504         }
5505
5506         status = filename_convert(ctx, conn,
5507                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5508                                  directory,
5509                                  0,
5510                                  NULL,
5511                                  &smb_dname);
5512         if (!NT_STATUS_IS_OK(status)) {
5513                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5514                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5515                                         ERRSRV, ERRbadpath);
5516                         goto out;
5517                 }
5518                 reply_nterror(req, status);
5519                 goto out;
5520         }
5521
5522         if (is_ntfs_stream_smb_fname(smb_dname)) {
5523                 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5524                 goto out;
5525         }
5526
5527         status = SMB_VFS_CREATE_FILE(
5528                 conn,                                   /* conn */
5529                 req,                                    /* req */
5530                 0,                                      /* root_dir_fid */
5531                 smb_dname,                              /* fname */
5532                 DELETE_ACCESS,                          /* access_mask */
5533                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5534                         FILE_SHARE_DELETE),
5535                 FILE_OPEN,                              /* create_disposition*/
5536                 FILE_DIRECTORY_FILE,                    /* create_options */
5537                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
5538                 0,                                      /* oplock_request */
5539                 0,                                      /* allocation_size */
5540                 0,                                      /* private_flags */
5541                 NULL,                                   /* sd */
5542                 NULL,                                   /* ea_list */
5543                 &fsp,                                   /* result */
5544                 &info);                                 /* pinfo */
5545
5546         if (!NT_STATUS_IS_OK(status)) {
5547                 if (open_was_deferred(req->mid)) {
5548                         /* We have re-scheduled this call. */
5549                         goto out;
5550                 }
5551                 reply_nterror(req, status);
5552                 goto out;
5553         }
5554
5555         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5556         if (!NT_STATUS_IS_OK(status)) {
5557                 close_file(req, fsp, ERROR_CLOSE);
5558                 reply_nterror(req, status);
5559                 goto out;
5560         }
5561
5562         if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5563                 close_file(req, fsp, ERROR_CLOSE);
5564                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5565                 goto out;
5566         }
5567
5568         status = close_file(req, fsp, NORMAL_CLOSE);
5569         if (!NT_STATUS_IS_OK(status)) {
5570                 reply_nterror(req, status);
5571         } else {
5572                 reply_outbuf(req, 0, 0);
5573         }
5574
5575         dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5576
5577         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5578  out:
5579         TALLOC_FREE(smb_dname);
5580         END_PROFILE(SMBrmdir);
5581         return;
5582 }
5583
5584 /*******************************************************************
5585  Resolve wildcards in a filename rename.
5586 ********************************************************************/
5587
5588 static bool resolve_wildcards(TALLOC_CTX *ctx,
5589                                 const char *name1,
5590                                 const char *name2,
5591                                 char **pp_newname)
5592 {
5593         char *name2_copy = NULL;
5594         char *root1 = NULL;
5595         char *root2 = NULL;
5596         char *ext1 = NULL;
5597         char *ext2 = NULL;
5598         char *p,*p2, *pname1, *pname2;
5599
5600         name2_copy = talloc_strdup(ctx, name2);
5601         if (!name2_copy) {
5602                 return False;
5603         }
5604
5605         pname1 = strrchr_m(name1,'/');
5606         pname2 = strrchr_m(name2_copy,'/');
5607
5608         if (!pname1 || !pname2) {
5609                 return False;
5610         }
5611
5612         /* Truncate the copy of name2 at the last '/' */
5613         *pname2 = '\0';
5614
5615         /* Now go past the '/' */
5616         pname1++;
5617         pname2++;
5618
5619         root1 = talloc_strdup(ctx, pname1);
5620         root2 = talloc_strdup(ctx, pname2);
5621
5622         if (!root1 || !root2) {
5623                 return False;
5624         }
5625
5626         p = strrchr_m(root1,'.');
5627         if (p) {
5628                 *p = 0;
5629                 ext1 = talloc_strdup(ctx, p+1);
5630         } else {
5631                 ext1 = talloc_strdup(ctx, "");
5632         }
5633         p = strrchr_m(root2,'.');
5634         if (p) {
5635                 *p = 0;
5636                 ext2 = talloc_strdup(ctx, p+1);
5637         } else {
5638                 ext2 = talloc_strdup(ctx, "");
5639         }
5640
5641         if (!ext1 || !ext2) {
5642                 return False;
5643         }
5644
5645         p = root1;
5646         p2 = root2;
5647         while (*p2) {
5648                 if (*p2 == '?') {
5649                         /* Hmmm. Should this be mb-aware ? */
5650                         *p2 = *p;
5651                         p2++;
5652                 } else if (*p2 == '*') {
5653                         *p2 = '\0';
5654                         root2 = talloc_asprintf(ctx, "%s%s",
5655                                                 root2,
5656                                                 p);
5657                         if (!root2) {
5658                                 return False;
5659                         }
5660                         break;
5661                 } else {
5662                         p2++;
5663                 }
5664                 if (*p) {
5665                         p++;
5666                 }
5667         }
5668
5669         p = ext1;
5670         p2 = ext2;
5671         while (*p2) {
5672                 if (*p2 == '?') {
5673                         /* Hmmm. Should this be mb-aware ? */
5674                         *p2 = *p;
5675                         p2++;
5676                 } else if (*p2 == '*') {
5677                         *p2 = '\0';
5678                         ext2 = talloc_asprintf(ctx, "%s%s",
5679                                                 ext2,
5680                                                 p);
5681                         if (!ext2) {
5682                                 return False;
5683                         }
5684                         break;
5685                 } else {
5686                         p2++;
5687                 }
5688                 if (*p) {
5689                         p++;
5690                 }
5691         }
5692
5693         if (*ext2) {
5694                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5695                                 name2_copy,
5696                                 root2,
5697                                 ext2);
5698         } else {
5699                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5700                                 name2_copy,
5701                                 root2);
5702         }
5703
5704         if (!*pp_newname) {
5705                 return False;
5706         }
5707
5708         return True;
5709 }
5710
5711 /****************************************************************************
5712  Ensure open files have their names updated. Updated to notify other smbd's
5713  asynchronously.
5714 ****************************************************************************/
5715
5716 static void rename_open_files(connection_struct *conn,
5717                               struct share_mode_lock *lck,
5718                               const struct smb_filename *smb_fname_dst)
5719 {
5720         files_struct *fsp;
5721         bool did_rename = False;
5722         NTSTATUS status;
5723
5724         for(fsp = file_find_di_first(lck->id); fsp;
5725             fsp = file_find_di_next(fsp)) {
5726                 /* fsp_name is a relative path under the fsp. To change this for other
5727                    sharepaths we need to manipulate relative paths. */
5728                 /* TODO - create the absolute path and manipulate the newname
5729                    relative to the sharepath. */
5730                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5731                         continue;
5732                 }
5733                 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5734                            "(file_id %s) from %s -> %s\n", fsp->fnum,
5735                            file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5736                            smb_fname_str_dbg(smb_fname_dst)));
5737
5738                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5739                 if (NT_STATUS_IS_OK(status)) {
5740                         did_rename = True;
5741                 }
5742         }
5743
5744         if (!did_rename) {
5745                 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5746                            "for %s\n", file_id_string_tos(&lck->id),
5747                            smb_fname_str_dbg(smb_fname_dst)));
5748         }
5749
5750         /* Send messages to all smbd's (not ourself) that the name has changed. */
5751         rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5752                               smb_fname_dst);
5753
5754 }
5755
5756 /****************************************************************************
5757  We need to check if the source path is a parent directory of the destination
5758  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5759  refuse the rename with a sharing violation. Under UNIX the above call can
5760  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5761  probably need to check that the client is a Windows one before disallowing
5762  this as a UNIX client (one with UNIX extensions) can know the source is a
5763  symlink and make this decision intelligently. Found by an excellent bug
5764  report from <AndyLiebman@aol.com>.
5765 ****************************************************************************/
5766
5767 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5768                                      const struct smb_filename *smb_fname_dst)
5769 {
5770         const char *psrc = smb_fname_src->base_name;
5771         const char *pdst = smb_fname_dst->base_name;
5772         size_t slen;
5773
5774         if (psrc[0] == '.' && psrc[1] == '/') {
5775                 psrc += 2;
5776         }
5777         if (pdst[0] == '.' && pdst[1] == '/') {
5778                 pdst += 2;
5779         }
5780         if ((slen = strlen(psrc)) > strlen(pdst)) {
5781                 return False;
5782         }
5783         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5784 }
5785
5786 /*
5787  * Do the notify calls from a rename
5788  */
5789
5790 static void notify_rename(connection_struct *conn, bool is_dir,
5791                           const struct smb_filename *smb_fname_src,
5792                           const struct smb_filename *smb_fname_dst)
5793 {
5794         char *parent_dir_src = NULL;
5795         char *parent_dir_dst = NULL;
5796         uint32 mask;
5797
5798         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5799                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5800
5801         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5802                             &parent_dir_src, NULL) ||
5803             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5804                             &parent_dir_dst, NULL)) {
5805                 goto out;
5806         }
5807
5808         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5809                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5810                              smb_fname_src->base_name);
5811                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5812                              smb_fname_dst->base_name);
5813         }
5814         else {
5815                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5816                              smb_fname_src->base_name);
5817                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5818                              smb_fname_dst->base_name);
5819         }
5820
5821         /* this is a strange one. w2k3 gives an additional event for
5822            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5823            files, but not directories */
5824         if (!is_dir) {
5825                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5826                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5827                              |FILE_NOTIFY_CHANGE_CREATION,
5828                              smb_fname_dst->base_name);
5829         }
5830  out:
5831         TALLOC_FREE(parent_dir_src);
5832         TALLOC_FREE(parent_dir_dst);
5833 }
5834
5835 /****************************************************************************
5836  Rename an open file - given an fsp.
5837 ****************************************************************************/
5838
5839 NTSTATUS rename_internals_fsp(connection_struct *conn,
5840                         files_struct *fsp,
5841                         const struct smb_filename *smb_fname_dst_in,
5842                         uint32 attrs,
5843                         bool replace_if_exists)
5844 {
5845         TALLOC_CTX *ctx = talloc_tos();
5846         struct smb_filename *smb_fname_dst = NULL;
5847         NTSTATUS status = NT_STATUS_OK;
5848         struct share_mode_lock *lck = NULL;
5849         bool dst_exists, old_is_stream, new_is_stream;
5850
5851         status = check_name(conn, smb_fname_dst_in->base_name);
5852         if (!NT_STATUS_IS_OK(status)) {
5853                 return status;
5854         }
5855
5856         /* Make a copy of the dst smb_fname structs */
5857
5858         status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5859         if (!NT_STATUS_IS_OK(status)) {
5860                 goto out;
5861         }
5862
5863         /* Ensure the dst smb_fname contains a '/' */
5864         if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5865                 char * tmp;
5866                 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5867                                       smb_fname_dst->base_name);
5868                 if (!tmp) {
5869                         status = NT_STATUS_NO_MEMORY;
5870                         goto out;
5871                 }
5872                 TALLOC_FREE(smb_fname_dst->base_name);
5873                 smb_fname_dst->base_name = tmp;
5874         }
5875
5876         /*
5877          * Check for special case with case preserving and not
5878          * case sensitive. If the old last component differs from the original
5879          * last component only by case, then we should allow
5880          * the rename (user is trying to change the case of the
5881          * filename).
5882          */
5883         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5884             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5885             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5886                 char *last_slash;
5887                 char *fname_dst_lcomp_base_mod = NULL;
5888                 struct smb_filename *smb_fname_orig_lcomp = NULL;
5889
5890                 /*
5891                  * Get the last component of the destination name.  Note that
5892                  * we guarantee that destination name contains a '/' character
5893                  * above.
5894                  */
5895                 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5896                 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5897                 if (!fname_dst_lcomp_base_mod) {
5898                         status = NT_STATUS_NO_MEMORY;
5899                         goto out;
5900                 }
5901
5902                 /*
5903                  * Create an smb_filename struct using the original last
5904                  * component of the destination.
5905                  */
5906                 status = create_synthetic_smb_fname_split(ctx,
5907                     smb_fname_dst->original_lcomp, NULL,
5908                     &smb_fname_orig_lcomp);
5909                 if (!NT_STATUS_IS_OK(status)) {
5910                         TALLOC_FREE(fname_dst_lcomp_base_mod);
5911                         goto out;
5912                 }
5913
5914                 /* If the base names only differ by case, use original. */
5915                 if(!strcsequal(fname_dst_lcomp_base_mod,
5916                                smb_fname_orig_lcomp->base_name)) {
5917                         char *tmp;
5918                         /*
5919                          * Replace the modified last component with the
5920                          * original.
5921                          */
5922                         *last_slash = '\0'; /* Truncate at the '/' */
5923                         tmp = talloc_asprintf(smb_fname_dst,
5924                                         "%s/%s",
5925                                         smb_fname_dst->base_name,
5926                                         smb_fname_orig_lcomp->base_name);
5927                         if (tmp == NULL) {
5928                                 status = NT_STATUS_NO_MEMORY;
5929                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
5930                                 TALLOC_FREE(smb_fname_orig_lcomp);
5931                                 goto out;
5932                         }
5933                         TALLOC_FREE(smb_fname_dst->base_name);
5934                         smb_fname_dst->base_name = tmp;
5935                 }
5936
5937                 /* If the stream_names only differ by case, use original. */
5938                 if(!strcsequal(smb_fname_dst->stream_name,
5939                                smb_fname_orig_lcomp->stream_name)) {
5940                         char *tmp = NULL;
5941                         /* Use the original stream. */
5942                         tmp = talloc_strdup(smb_fname_dst,
5943                                             smb_fname_orig_lcomp->stream_name);
5944                         if (tmp == NULL) {
5945                                 status = NT_STATUS_NO_MEMORY;
5946                                 TALLOC_FREE(fname_dst_lcomp_base_mod);
5947                                 TALLOC_FREE(smb_fname_orig_lcomp);
5948                                 goto out;
5949                         }
5950                         TALLOC_FREE(smb_fname_dst->stream_name);
5951                         smb_fname_dst->stream_name = tmp;
5952                 }
5953                 TALLOC_FREE(fname_dst_lcomp_base_mod);
5954                 TALLOC_FREE(smb_fname_orig_lcomp);
5955         }
5956
5957         /*
5958          * If the src and dest names are identical - including case,
5959          * don't do the rename, just return success.
5960          */
5961
5962         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5963             strcsequal(fsp->fsp_name->stream_name,
5964                        smb_fname_dst->stream_name)) {
5965                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5966                           "- returning success\n",
5967                           smb_fname_str_dbg(smb_fname_dst)));
5968                 status = NT_STATUS_OK;
5969                 goto out;
5970         }
5971
5972         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5973         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5974
5975         /* Return the correct error code if both names aren't streams. */
5976         if (!old_is_stream && new_is_stream) {
5977                 status = NT_STATUS_OBJECT_NAME_INVALID;
5978                 goto out;
5979         }
5980
5981         if (old_is_stream && !new_is_stream) {
5982                 status = NT_STATUS_INVALID_PARAMETER;
5983                 goto out;
5984         }
5985
5986         dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5987
5988         if(!replace_if_exists && dst_exists) {
5989                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5990                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5991                           smb_fname_str_dbg(smb_fname_dst)));
5992                 status = NT_STATUS_OBJECT_NAME_COLLISION;
5993                 goto out;
5994         }
5995
5996         if (dst_exists) {
5997                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
5998                     &smb_fname_dst->st);
5999                 files_struct *dst_fsp = file_find_di_first(fileid);
6000                 /* The file can be open when renaming a stream */
6001                 if (dst_fsp && !new_is_stream) {
6002                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6003                         status = NT_STATUS_ACCESS_DENIED;
6004                         goto out;
6005                 }
6006         }
6007
6008         /* Ensure we have a valid stat struct for the source. */
6009         status = vfs_stat_fsp(fsp);
6010         if (!NT_STATUS_IS_OK(status)) {
6011                 goto out;
6012         }
6013
6014         status = can_rename(conn, fsp, attrs);
6015
6016         if (!NT_STATUS_IS_OK(status)) {
6017                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6018                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6019                           smb_fname_str_dbg(smb_fname_dst)));
6020                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6021                         status = NT_STATUS_ACCESS_DENIED;
6022                 goto out;
6023         }
6024
6025         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6026                 status = NT_STATUS_ACCESS_DENIED;
6027         }
6028
6029         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6030                                   NULL);
6031
6032         /*
6033          * We have the file open ourselves, so not being able to get the
6034          * corresponding share mode lock is a fatal error.
6035          */
6036
6037         SMB_ASSERT(lck != NULL);
6038
6039         if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6040                 uint32 create_options = fsp->fh->private_options;
6041
6042                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6043                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6044                           smb_fname_str_dbg(smb_fname_dst)));
6045
6046                 if (lp_map_archive(SNUM(conn)) ||
6047                     lp_store_dos_attributes(SNUM(conn))) {
6048                         /* We must set the archive bit on the newly
6049                            renamed file. */
6050                         if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6051                                 uint32_t old_dosmode = dos_mode(conn,
6052                                                         smb_fname_dst);
6053                                 file_set_dosmode(conn,
6054                                         smb_fname_dst,
6055                                         old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6056                                         NULL,
6057                                         true);
6058                         }
6059                 }
6060
6061                 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6062                               smb_fname_dst);
6063
6064                 rename_open_files(conn, lck, smb_fname_dst);
6065
6066                 /*
6067                  * A rename acts as a new file create w.r.t. allowing an initial delete
6068                  * on close, probably because in Windows there is a new handle to the
6069                  * new file. If initial delete on close was requested but not
6070                  * originally set, we need to set it here. This is probably not 100% correct,
6071                  * but will work for the CIFSFS client which in non-posix mode
6072                  * depends on these semantics. JRA.
6073                  */
6074
6075                 if (create_options & FILE_DELETE_ON_CLOSE) {
6076                         status = can_set_delete_on_close(fsp, 0);
6077
6078                         if (NT_STATUS_IS_OK(status)) {
6079                                 /* Note that here we set the *inital* delete on close flag,
6080                                  * not the regular one. The magic gets handled in close. */
6081                                 fsp->initial_delete_on_close = True;
6082                         }
6083                 }
6084                 TALLOC_FREE(lck);
6085                 status = NT_STATUS_OK;
6086                 goto out;
6087         }
6088
6089         TALLOC_FREE(lck);
6090
6091         if (errno == ENOTDIR || errno == EISDIR) {
6092                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6093         } else {
6094                 status = map_nt_error_from_unix(errno);
6095         }
6096
6097         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6098                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6099                   smb_fname_str_dbg(smb_fname_dst)));
6100
6101  out:
6102         TALLOC_FREE(smb_fname_dst);
6103
6104         return status;
6105 }
6106
6107 /****************************************************************************
6108  The guts of the rename command, split out so it may be called by the NT SMB
6109  code.
6110 ****************************************************************************/
6111
6112 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6113                         connection_struct *conn,
6114                         struct smb_request *req,
6115                         struct smb_filename *smb_fname_src,
6116                         struct smb_filename *smb_fname_dst,
6117                         uint32 attrs,
6118                         bool replace_if_exists,
6119                         bool src_has_wild,
6120                         bool dest_has_wild,
6121                         uint32_t access_mask)
6122 {
6123         char *fname_src_dir = NULL;
6124         char *fname_src_mask = NULL;
6125         int count=0;
6126         NTSTATUS status = NT_STATUS_OK;
6127         struct smb_Dir *dir_hnd = NULL;
6128         const char *dname = NULL;
6129         char *talloced = NULL;
6130         long offset = 0;
6131         int create_options = 0;
6132         bool posix_pathnames = lp_posix_pathnames();
6133
6134         /*
6135          * Split the old name into directory and last component
6136          * strings. Note that unix_convert may have stripped off a
6137          * leading ./ from both name and newname if the rename is
6138          * at the root of the share. We need to make sure either both
6139          * name and newname contain a / character or neither of them do
6140          * as this is checked in resolve_wildcards().
6141          */
6142
6143         /* Split up the directory from the filename/mask. */
6144         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6145                                       &fname_src_dir, &fname_src_mask);
6146         if (!NT_STATUS_IS_OK(status)) {
6147                 status = NT_STATUS_NO_MEMORY;
6148                 goto out;
6149         }
6150
6151         /*
6152          * We should only check the mangled cache
6153          * here if unix_convert failed. This means
6154          * that the path in 'mask' doesn't exist
6155          * on the file system and so we need to look
6156          * for a possible mangle. This patch from
6157          * Tine Smukavec <valentin.smukavec@hermes.si>.
6158          */
6159
6160         if (!VALID_STAT(smb_fname_src->st) &&
6161             mangle_is_mangled(fname_src_mask, conn->params)) {
6162                 char *new_mask = NULL;
6163                 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6164                                             conn->params);
6165                 if (new_mask) {
6166                         TALLOC_FREE(fname_src_mask);
6167                         fname_src_mask = new_mask;
6168                 }
6169         }
6170
6171         if (!src_has_wild) {
6172                 files_struct *fsp;
6173
6174                 /*
6175                  * Only one file needs to be renamed. Append the mask back
6176                  * onto the directory.
6177                  */
6178                 TALLOC_FREE(smb_fname_src->base_name);
6179                 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6180                                                            "%s/%s",
6181                                                            fname_src_dir,
6182                                                            fname_src_mask);
6183                 if (!smb_fname_src->base_name) {
6184                         status = NT_STATUS_NO_MEMORY;
6185                         goto out;
6186                 }
6187
6188                 /* Ensure dst fname contains a '/' also */
6189                 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6190                         char *tmp;
6191                         tmp = talloc_asprintf(smb_fname_dst, "./%s",
6192                                               smb_fname_dst->base_name);
6193                         if (!tmp) {
6194                                 status = NT_STATUS_NO_MEMORY;
6195                                 goto out;
6196                         }
6197                         TALLOC_FREE(smb_fname_dst->base_name);
6198                         smb_fname_dst->base_name = tmp;
6199                 }
6200
6201                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6202                           "case_preserve = %d, short case preserve = %d, "
6203                           "directory = %s, newname = %s, "
6204                           "last_component_dest = %s\n",
6205                           conn->case_sensitive, conn->case_preserve,
6206                           conn->short_case_preserve,
6207                           smb_fname_str_dbg(smb_fname_src),
6208                           smb_fname_str_dbg(smb_fname_dst),
6209                           smb_fname_dst->original_lcomp));
6210
6211                 /* The dest name still may have wildcards. */
6212                 if (dest_has_wild) {
6213                         char *fname_dst_mod = NULL;
6214                         if (!resolve_wildcards(smb_fname_dst,
6215                                                smb_fname_src->base_name,
6216                                                smb_fname_dst->base_name,
6217                                                &fname_dst_mod)) {
6218                                 DEBUG(6, ("rename_internals: resolve_wildcards "
6219                                           "%s %s failed\n",
6220                                           smb_fname_src->base_name,
6221                                           smb_fname_dst->base_name));
6222                                 status = NT_STATUS_NO_MEMORY;
6223                                 goto out;
6224                         }
6225                         TALLOC_FREE(smb_fname_dst->base_name);
6226                         smb_fname_dst->base_name = fname_dst_mod;
6227                 }
6228
6229                 ZERO_STRUCT(smb_fname_src->st);
6230                 if (posix_pathnames) {
6231                         SMB_VFS_LSTAT(conn, smb_fname_src);
6232                 } else {
6233                         SMB_VFS_STAT(conn, smb_fname_src);
6234                 }
6235
6236                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6237                         create_options |= FILE_DIRECTORY_FILE;
6238                 }
6239
6240                 status = SMB_VFS_CREATE_FILE(
6241                         conn,                           /* conn */
6242                         req,                            /* req */
6243                         0,                              /* root_dir_fid */
6244                         smb_fname_src,                  /* fname */
6245                         access_mask,                    /* access_mask */
6246                         (FILE_SHARE_READ |              /* share_access */
6247                             FILE_SHARE_WRITE),
6248                         FILE_OPEN,                      /* create_disposition*/
6249                         create_options,                 /* create_options */
6250                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6251                         0,                              /* oplock_request */
6252                         0,                              /* allocation_size */
6253                         0,                              /* private_flags */
6254                         NULL,                           /* sd */
6255                         NULL,                           /* ea_list */
6256                         &fsp,                           /* result */
6257                         NULL);                          /* pinfo */
6258
6259                 if (!NT_STATUS_IS_OK(status)) {
6260                         DEBUG(3, ("Could not open rename source %s: %s\n",
6261                                   smb_fname_str_dbg(smb_fname_src),
6262                                   nt_errstr(status)));
6263                         goto out;
6264                 }
6265
6266                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6267                                               attrs, replace_if_exists);
6268
6269                 close_file(req, fsp, NORMAL_CLOSE);
6270
6271                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6272                           nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6273                           smb_fname_str_dbg(smb_fname_dst)));
6274
6275                 goto out;
6276         }
6277
6278         /*
6279          * Wildcards - process each file that matches.
6280          */
6281         if (strequal(fname_src_mask, "????????.???")) {
6282                 TALLOC_FREE(fname_src_mask);
6283                 fname_src_mask = talloc_strdup(ctx, "*");
6284                 if (!fname_src_mask) {
6285                         status = NT_STATUS_NO_MEMORY;
6286                         goto out;
6287                 }
6288         }
6289
6290         status = check_name(conn, fname_src_dir);
6291         if (!NT_STATUS_IS_OK(status)) {
6292                 goto out;
6293         }
6294
6295         dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6296                           attrs);
6297         if (dir_hnd == NULL) {
6298                 status = map_nt_error_from_unix(errno);
6299                 goto out;
6300         }
6301
6302         status = NT_STATUS_NO_SUCH_FILE;
6303         /*
6304          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6305          * - gentest fix. JRA
6306          */
6307
6308         while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6309                                     &talloced))) {
6310                 files_struct *fsp = NULL;
6311                 char *destname = NULL;
6312                 bool sysdir_entry = False;
6313
6314                 /* Quick check for "." and ".." */
6315                 if (ISDOT(dname) || ISDOTDOT(dname)) {
6316                         if (attrs & aDIR) {
6317                                 sysdir_entry = True;
6318                         } else {
6319                                 TALLOC_FREE(talloced);
6320                                 continue;
6321                         }
6322                 }
6323
6324                 if (!is_visible_file(conn, fname_src_dir, dname,
6325                                      &smb_fname_src->st, false)) {
6326                         TALLOC_FREE(talloced);
6327                         continue;
6328                 }
6329
6330                 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6331                         TALLOC_FREE(talloced);
6332                         continue;
6333                 }
6334
6335                 if (sysdir_entry) {
6336                         status = NT_STATUS_OBJECT_NAME_INVALID;
6337                         break;
6338                 }
6339
6340                 TALLOC_FREE(smb_fname_src->base_name);
6341                 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6342                                                            "%s/%s",
6343                                                            fname_src_dir,
6344                                                            dname);
6345                 if (!smb_fname_src->base_name) {
6346                         status = NT_STATUS_NO_MEMORY;
6347                         goto out;
6348                 }
6349
6350                 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6351                                        smb_fname_dst->base_name,
6352                                        &destname)) {
6353                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
6354                                   smb_fname_src->base_name, destname));
6355                         TALLOC_FREE(talloced);
6356                         continue;
6357                 }
6358                 if (!destname) {
6359                         status = NT_STATUS_NO_MEMORY;
6360                         goto out;
6361                 }
6362
6363                 TALLOC_FREE(smb_fname_dst->base_name);
6364                 smb_fname_dst->base_name = destname;
6365
6366                 ZERO_STRUCT(smb_fname_src->st);
6367                 if (posix_pathnames) {
6368                         SMB_VFS_LSTAT(conn, smb_fname_src);
6369                 } else {
6370                         SMB_VFS_STAT(conn, smb_fname_src);
6371                 }
6372
6373                 create_options = 0;
6374
6375                 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6376                         create_options |= FILE_DIRECTORY_FILE;
6377                 }
6378
6379                 status = SMB_VFS_CREATE_FILE(
6380                         conn,                           /* conn */
6381                         req,                            /* req */
6382                         0,                              /* root_dir_fid */
6383                         smb_fname_src,                  /* fname */
6384                         access_mask,                    /* access_mask */
6385                         (FILE_SHARE_READ |              /* share_access */
6386                             FILE_SHARE_WRITE),
6387                         FILE_OPEN,                      /* create_disposition*/
6388                         create_options,                 /* create_options */
6389                         posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6390                         0,                              /* oplock_request */
6391                         0,                              /* allocation_size */
6392                         0,                              /* private_flags */
6393                         NULL,                           /* sd */
6394                         NULL,                           /* ea_list */
6395                         &fsp,                           /* result */
6396                         NULL);                          /* pinfo */
6397
6398                 if (!NT_STATUS_IS_OK(status)) {
6399                         DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6400                                  "returned %s rename %s -> %s\n",
6401                                  nt_errstr(status),
6402                                  smb_fname_str_dbg(smb_fname_src),
6403                                  smb_fname_str_dbg(smb_fname_dst)));
6404                         break;
6405                 }
6406
6407                 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6408                                                               dname);
6409                 if (!smb_fname_dst->original_lcomp) {
6410                         status = NT_STATUS_NO_MEMORY;
6411                         goto out;
6412                 }
6413
6414                 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6415                                               attrs, replace_if_exists);
6416
6417                 close_file(req, fsp, NORMAL_CLOSE);
6418
6419                 if (!NT_STATUS_IS_OK(status)) {
6420                         DEBUG(3, ("rename_internals_fsp returned %s for "
6421                                   "rename %s -> %s\n", nt_errstr(status),
6422                                   smb_fname_str_dbg(smb_fname_src),
6423                                   smb_fname_str_dbg(smb_fname_dst)));
6424                         break;
6425                 }
6426
6427                 count++;
6428
6429                 DEBUG(3,("rename_internals: doing rename on %s -> "
6430                          "%s\n", smb_fname_str_dbg(smb_fname_src),
6431                          smb_fname_str_dbg(smb_fname_src)));
6432                 TALLOC_FREE(talloced);
6433         }
6434         TALLOC_FREE(dir_hnd);
6435
6436         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6437                 status = map_nt_error_from_unix(errno);
6438         }
6439
6440  out:
6441         TALLOC_FREE(talloced);
6442         TALLOC_FREE(fname_src_dir);
6443         TALLOC_FREE(fname_src_mask);
6444         return status;
6445 }
6446
6447 /****************************************************************************
6448  Reply to a mv.
6449 ****************************************************************************/
6450
6451 void reply_mv(struct smb_request *req)
6452 {
6453         connection_struct *conn = req->conn;
6454         char *name = NULL;
6455         char *newname = NULL;
6456         const char *p;
6457         uint32 attrs;
6458         NTSTATUS status;
6459         bool src_has_wcard = False;
6460         bool dest_has_wcard = False;
6461         TALLOC_CTX *ctx = talloc_tos();
6462         struct smb_filename *smb_fname_src = NULL;
6463         struct smb_filename *smb_fname_dst = NULL;
6464
6465         START_PROFILE(SMBmv);
6466
6467         if (req->wct < 1) {
6468                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6469                 goto out;
6470         }
6471
6472         attrs = SVAL(req->vwv+0, 0);
6473
6474         p = (const char *)req->buf + 1;
6475         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6476                                        &status, &src_has_wcard);
6477         if (!NT_STATUS_IS_OK(status)) {
6478                 reply_nterror(req, status);
6479                 goto out;
6480         }
6481         p++;
6482         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6483                                        &status, &dest_has_wcard);
6484         if (!NT_STATUS_IS_OK(status)) {
6485                 reply_nterror(req, status);
6486                 goto out;
6487         }
6488
6489         status = filename_convert(ctx,
6490                                   conn,
6491                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6492                                   name,
6493                                   UCF_COND_ALLOW_WCARD_LCOMP,
6494                                   &src_has_wcard,
6495                                   &smb_fname_src);
6496
6497         if (!NT_STATUS_IS_OK(status)) {
6498                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6499                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6500                                         ERRSRV, ERRbadpath);
6501                         goto out;
6502                 }
6503                 reply_nterror(req, status);
6504                 goto out;
6505         }
6506
6507         status = filename_convert(ctx,
6508                                   conn,
6509                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6510                                   newname,
6511                                   UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6512                                   &dest_has_wcard,
6513                                   &smb_fname_dst);
6514
6515         if (!NT_STATUS_IS_OK(status)) {
6516                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6517                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6518                                         ERRSRV, ERRbadpath);
6519                         goto out;
6520                 }
6521                 reply_nterror(req, status);
6522                 goto out;
6523         }
6524
6525         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6526                  smb_fname_str_dbg(smb_fname_dst)));
6527
6528         status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6529                                   attrs, False, src_has_wcard, dest_has_wcard,
6530                                   DELETE_ACCESS);
6531         if (!NT_STATUS_IS_OK(status)) {
6532                 if (open_was_deferred(req->mid)) {
6533                         /* We have re-scheduled this call. */
6534                         goto out;
6535                 }
6536                 reply_nterror(req, status);
6537                 goto out;
6538         }
6539
6540         reply_outbuf(req, 0, 0);
6541  out:
6542         TALLOC_FREE(smb_fname_src);
6543         TALLOC_FREE(smb_fname_dst);
6544         END_PROFILE(SMBmv);
6545         return;
6546 }
6547
6548 /*******************************************************************
6549  Copy a file as part of a reply_copy.
6550 ******************************************************************/
6551
6552 /*
6553  * TODO: check error codes on all callers
6554  */
6555
6556 NTSTATUS copy_file(TALLOC_CTX *ctx,
6557                         connection_struct *conn,
6558                         struct smb_filename *smb_fname_src,
6559                         struct smb_filename *smb_fname_dst,
6560                         int ofun,
6561                         int count,
6562                         bool target_is_directory)
6563 {
6564         struct smb_filename *smb_fname_dst_tmp = NULL;
6565         SMB_OFF_T ret=-1;
6566         files_struct *fsp1,*fsp2;
6567         uint32 dosattrs;
6568         uint32 new_create_disposition;
6569         NTSTATUS status;
6570
6571
6572         status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6573         if (!NT_STATUS_IS_OK(status)) {
6574                 return status;
6575         }
6576
6577         /*
6578          * If the target is a directory, extract the last component from the
6579          * src filename and append it to the dst filename
6580          */
6581         if (target_is_directory) {
6582                 const char *p;
6583
6584                 /* dest/target can't be a stream if it's a directory. */
6585                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6586
6587                 p = strrchr_m(smb_fname_src->base_name,'/');
6588                 if (p) {
6589                         p++;
6590                 } else {
6591                         p = smb_fname_src->base_name;
6592                 }
6593                 smb_fname_dst_tmp->base_name =
6594                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6595                                            p);
6596                 if (!smb_fname_dst_tmp->base_name) {
6597                         status = NT_STATUS_NO_MEMORY;
6598                         goto out;
6599                 }
6600         }
6601
6602         status = vfs_file_exist(conn, smb_fname_src);
6603         if (!NT_STATUS_IS_OK(status)) {
6604                 goto out;
6605         }
6606
6607         if (!target_is_directory && count) {
6608                 new_create_disposition = FILE_OPEN;
6609         } else {
6610                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6611                                                  NULL, NULL,
6612                                                  &new_create_disposition,
6613                                                  NULL,
6614                                                  NULL)) {
6615                         status = NT_STATUS_INVALID_PARAMETER;
6616                         goto out;
6617                 }
6618         }
6619
6620         /* Open the src file for reading. */
6621         status = SMB_VFS_CREATE_FILE(
6622                 conn,                                   /* conn */
6623                 NULL,                                   /* req */
6624                 0,                                      /* root_dir_fid */
6625                 smb_fname_src,                          /* fname */
6626                 FILE_GENERIC_READ,                      /* access_mask */
6627                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6628                 FILE_OPEN,                              /* create_disposition*/
6629                 0,                                      /* create_options */
6630                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
6631                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6632                 0,                                      /* allocation_size */
6633                 0,                                      /* private_flags */
6634                 NULL,                                   /* sd */
6635                 NULL,                                   /* ea_list */
6636                 &fsp1,                                  /* result */
6637                 NULL);                                  /* psbuf */
6638
6639         if (!NT_STATUS_IS_OK(status)) {
6640                 goto out;
6641         }
6642
6643         dosattrs = dos_mode(conn, smb_fname_src);
6644
6645         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6646                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6647         }
6648
6649         /* Open the dst file for writing. */
6650         status = SMB_VFS_CREATE_FILE(
6651                 conn,                                   /* conn */
6652                 NULL,                                   /* req */
6653                 0,                                      /* root_dir_fid */
6654                 smb_fname_dst,                          /* fname */
6655                 FILE_GENERIC_WRITE,                     /* access_mask */
6656                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
6657                 new_create_disposition,                 /* create_disposition*/
6658                 0,                                      /* create_options */
6659                 dosattrs,                               /* file_attributes */
6660                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
6661                 0,                                      /* allocation_size */
6662                 0,                                      /* private_flags */
6663                 NULL,                                   /* sd */
6664                 NULL,                                   /* ea_list */
6665                 &fsp2,                                  /* result */
6666                 NULL);                                  /* psbuf */
6667
6668         if (!NT_STATUS_IS_OK(status)) {
6669                 close_file(NULL, fsp1, ERROR_CLOSE);
6670                 goto out;
6671         }
6672
6673         if ((ofun&3) == 1) {
6674                 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6675                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6676                         /*
6677                          * Stop the copy from occurring.
6678                          */
6679                         ret = -1;
6680                         smb_fname_src->st.st_ex_size = 0;
6681                 }
6682         }
6683
6684         /* Do the actual copy. */
6685         if (smb_fname_src->st.st_ex_size) {
6686                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6687         }
6688
6689         close_file(NULL, fsp1, NORMAL_CLOSE);
6690
6691         /* Ensure the modtime is set correctly on the destination file. */
6692         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6693
6694         /*
6695          * As we are opening fsp1 read-only we only expect
6696          * an error on close on fsp2 if we are out of space.
6697          * Thus we don't look at the error return from the
6698          * close of fsp1.
6699          */
6700         status = close_file(NULL, fsp2, NORMAL_CLOSE);
6701
6702         if (!NT_STATUS_IS_OK(status)) {
6703                 goto out;
6704         }
6705
6706         if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6707                 status = NT_STATUS_DISK_FULL;
6708                 goto out;
6709         }
6710
6711         status = NT_STATUS_OK;
6712
6713  out:
6714         TALLOC_FREE(smb_fname_dst_tmp);
6715         return status;
6716 }
6717
6718 /****************************************************************************
6719  Reply to a file copy.
6720 ****************************************************************************/
6721
6722 void reply_copy(struct smb_request *req)
6723 {
6724         connection_struct *conn = req->conn;
6725         struct smb_filename *smb_fname_src = NULL;
6726         struct smb_filename *smb_fname_dst = NULL;
6727         char *fname_src = NULL;
6728         char *fname_dst = NULL;
6729         char *fname_src_mask = NULL;
6730         char *fname_src_dir = NULL;
6731         const char *p;
6732         int count=0;
6733         int error = ERRnoaccess;
6734         int tid2;
6735         int ofun;
6736         int flags;
6737         bool target_is_directory=False;
6738         bool source_has_wild = False;
6739         bool dest_has_wild = False;
6740         NTSTATUS status;
6741         TALLOC_CTX *ctx = talloc_tos();
6742
6743         START_PROFILE(SMBcopy);
6744
6745         if (req->wct < 3) {
6746                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6747                 goto out;
6748         }
6749
6750         tid2 = SVAL(req->vwv+0, 0);
6751         ofun = SVAL(req->vwv+1, 0);
6752         flags = SVAL(req->vwv+2, 0);
6753
6754         p = (const char *)req->buf;
6755         p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6756                                        &status, &source_has_wild);
6757         if (!NT_STATUS_IS_OK(status)) {
6758                 reply_nterror(req, status);
6759                 goto out;
6760         }
6761         p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6762                                        &status, &dest_has_wild);
6763         if (!NT_STATUS_IS_OK(status)) {
6764                 reply_nterror(req, status);
6765                 goto out;
6766         }
6767
6768         DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6769
6770         if (tid2 != conn->cnum) {
6771                 /* can't currently handle inter share copies XXXX */
6772                 DEBUG(3,("Rejecting inter-share copy\n"));
6773                 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6774                 goto out;
6775         }
6776
6777         status = filename_convert(ctx, conn,
6778                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6779                                   fname_src,
6780                                   UCF_COND_ALLOW_WCARD_LCOMP,
6781                                   &source_has_wild,
6782                                   &smb_fname_src);
6783         if (!NT_STATUS_IS_OK(status)) {
6784                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6785                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6786                                         ERRSRV, ERRbadpath);
6787                         goto out;
6788                 }
6789                 reply_nterror(req, status);
6790                 goto out;
6791         }
6792
6793         status = filename_convert(ctx, conn,
6794                                   req->flags2 & FLAGS2_DFS_PATHNAMES,
6795                                   fname_dst,
6796                                   UCF_COND_ALLOW_WCARD_LCOMP,
6797                                   &dest_has_wild,
6798                                   &smb_fname_dst);
6799         if (!NT_STATUS_IS_OK(status)) {
6800                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6801                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6802                                         ERRSRV, ERRbadpath);
6803                         goto out;
6804                 }
6805                 reply_nterror(req, status);
6806                 goto out;
6807         }
6808
6809         target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6810
6811         if ((flags&1) && target_is_directory) {
6812                 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6813                 goto out;
6814         }
6815
6816         if ((flags&2) && !target_is_directory) {
6817                 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6818                 goto out;
6819         }
6820
6821         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6822                 /* wants a tree copy! XXXX */
6823                 DEBUG(3,("Rejecting tree copy\n"));
6824                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6825                 goto out;
6826         }
6827
6828         /* Split up the directory from the filename/mask. */
6829         status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6830                                       &fname_src_dir, &fname_src_mask);
6831         if (!NT_STATUS_IS_OK(status)) {
6832                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6833                 goto out;
6834         }
6835
6836         /*
6837          * We should only check the mangled cache
6838          * here if unix_convert failed. This means
6839          * that the path in 'mask' doesn't exist
6840          * on the file system and so we need to look
6841          * for a possible mangle. This patch from
6842          * Tine Smukavec <valentin.smukavec@hermes.si>.
6843          */
6844         if (!VALID_STAT(smb_fname_src->st) &&
6845             mangle_is_mangled(fname_src_mask, conn->params)) {
6846                 char *new_mask = NULL;
6847                 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6848                                             &new_mask, conn->params);
6849
6850                 /* Use demangled name if one was successfully found. */
6851                 if (new_mask) {
6852                         TALLOC_FREE(fname_src_mask);
6853                         fname_src_mask = new_mask;
6854                 }
6855         }
6856
6857         if (!source_has_wild) {
6858
6859                 /*
6860                  * Only one file needs to be copied. Append the mask back onto
6861                  * the directory.
6862                  */
6863                 TALLOC_FREE(smb_fname_src->base_name);
6864                 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6865                                                            "%s/%s",
6866                                                            fname_src_dir,
6867                                                            fname_src_mask);
6868                 if (!smb_fname_src->base_name) {
6869                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6870                         goto out;
6871                 }
6872
6873                 if (dest_has_wild) {
6874                         char *fname_dst_mod = NULL;
6875                         if (!resolve_wildcards(smb_fname_dst,
6876                                                smb_fname_src->base_name,
6877                                                smb_fname_dst->base_name,
6878                                                &fname_dst_mod)) {
6879                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6880                                 goto out;
6881                         }
6882                         TALLOC_FREE(smb_fname_dst->base_name);
6883                         smb_fname_dst->base_name = fname_dst_mod;
6884                 }
6885
6886                 status = check_name(conn, smb_fname_src->base_name);
6887                 if (!NT_STATUS_IS_OK(status)) {
6888                         reply_nterror(req, status);
6889                         goto out;
6890                 }
6891
6892                 status = check_name(conn, smb_fname_dst->base_name);
6893                 if (!NT_STATUS_IS_OK(status)) {
6894                         reply_nterror(req, status);
6895                         goto out;
6896                 }
6897
6898                 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6899                                    ofun, count, target_is_directory);
6900
6901                 if(!NT_STATUS_IS_OK(status)) {
6902                         reply_nterror(req, status);
6903                         goto out;
6904                 } else {
6905                         count++;
6906                 }
6907         } else {
6908                 struct smb_Dir *dir_hnd = NULL;
6909                 const char *dname = NULL;
6910                 char *talloced = NULL;
6911                 long offset = 0;
6912
6913                 /*
6914                  * There is a wildcard that requires us to actually read the
6915                  * src dir and copy each file matching the mask to the dst.
6916                  * Right now streams won't be copied, but this could
6917                  * presumably be added with a nested loop for reach dir entry.
6918                  */
6919                 SMB_ASSERT(!smb_fname_src->stream_name);
6920                 SMB_ASSERT(!smb_fname_dst->stream_name);
6921
6922                 smb_fname_src->stream_name = NULL;
6923                 smb_fname_dst->stream_name = NULL;
6924
6925                 if (strequal(fname_src_mask,"????????.???")) {
6926                         TALLOC_FREE(fname_src_mask);
6927                         fname_src_mask = talloc_strdup(ctx, "*");
6928                         if (!fname_src_mask) {
6929                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6930                                 goto out;
6931                         }
6932                 }
6933
6934                 status = check_name(conn, fname_src_dir);
6935                 if (!NT_STATUS_IS_OK(status)) {
6936                         reply_nterror(req, status);
6937                         goto out;
6938                 }
6939
6940                 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6941                 if (dir_hnd == NULL) {
6942                         status = map_nt_error_from_unix(errno);
6943                         reply_nterror(req, status);
6944                         goto out;
6945                 }
6946
6947                 error = ERRbadfile;
6948
6949                 /* Iterate over the src dir copying each entry to the dst. */
6950                 while ((dname = ReadDirName(dir_hnd, &offset,
6951                                             &smb_fname_src->st, &talloced))) {
6952                         char *destname = NULL;
6953
6954                         if (ISDOT(dname) || ISDOTDOT(dname)) {
6955                                 TALLOC_FREE(talloced);
6956                                 continue;
6957                         }
6958
6959                         if (!is_visible_file(conn, fname_src_dir, dname,
6960                                              &smb_fname_src->st, false)) {
6961                                 TALLOC_FREE(talloced);
6962                                 continue;
6963                         }
6964
6965                         if(!mask_match(dname, fname_src_mask,
6966                                        conn->case_sensitive)) {
6967                                 TALLOC_FREE(talloced);
6968                                 continue;
6969                         }
6970
6971                         error = ERRnoaccess;
6972
6973                         /* Get the src smb_fname struct setup. */
6974                         TALLOC_FREE(smb_fname_src->base_name);
6975                         smb_fname_src->base_name =
6976                             talloc_asprintf(smb_fname_src, "%s/%s",
6977                                             fname_src_dir, dname);
6978
6979                         if (!smb_fname_src->base_name) {
6980                                 TALLOC_FREE(dir_hnd);
6981                                 TALLOC_FREE(talloced);
6982                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6983                                 goto out;
6984                         }
6985
6986                         if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6987                                                smb_fname_dst->base_name,
6988                                                &destname)) {
6989                                 TALLOC_FREE(talloced);
6990                                 continue;
6991                         }
6992                         if (!destname) {
6993                                 TALLOC_FREE(dir_hnd);
6994                                 TALLOC_FREE(talloced);
6995                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6996                                 goto out;
6997                         }
6998
6999                         TALLOC_FREE(smb_fname_dst->base_name);
7000                         smb_fname_dst->base_name = destname;
7001
7002                         status = check_name(conn, smb_fname_src->base_name);
7003                         if (!NT_STATUS_IS_OK(status)) {
7004                                 TALLOC_FREE(dir_hnd);
7005                                 TALLOC_FREE(talloced);
7006                                 reply_nterror(req, status);
7007                                 goto out;
7008                         }
7009
7010                         status = check_name(conn, smb_fname_dst->base_name);
7011                         if (!NT_STATUS_IS_OK(status)) {
7012                                 TALLOC_FREE(dir_hnd);
7013                                 TALLOC_FREE(talloced);
7014                                 reply_nterror(req, status);
7015                                 goto out;
7016                         }
7017
7018                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7019                                 smb_fname_src->base_name,
7020                                 smb_fname_dst->base_name));
7021
7022                         status = copy_file(ctx, conn, smb_fname_src,
7023                                            smb_fname_dst, ofun, count,
7024                                            target_is_directory);
7025                         if (NT_STATUS_IS_OK(status)) {
7026                                 count++;
7027                         }
7028
7029                         TALLOC_FREE(talloced);
7030                 }
7031                 TALLOC_FREE(dir_hnd);
7032         }
7033
7034         if (count == 0) {
7035                 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7036                 goto out;
7037         }
7038
7039         reply_outbuf(req, 1, 0);
7040         SSVAL(req->outbuf,smb_vwv0,count);
7041  out:
7042         TALLOC_FREE(smb_fname_src);
7043         TALLOC_FREE(smb_fname_dst);
7044         TALLOC_FREE(fname_src);
7045         TALLOC_FREE(fname_dst);
7046         TALLOC_FREE(fname_src_mask);
7047         TALLOC_FREE(fname_src_dir);
7048
7049         END_PROFILE(SMBcopy);
7050         return;
7051 }
7052
7053 #undef DBGC_CLASS
7054 #define DBGC_CLASS DBGC_LOCKING
7055
7056 /****************************************************************************
7057  Get a lock pid, dealing with large count requests.
7058 ****************************************************************************/
7059
7060 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7061                     bool large_file_format)
7062 {
7063         if(!large_file_format)
7064                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7065         else
7066                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7067 }
7068
7069 /****************************************************************************
7070  Get a lock count, dealing with large count requests.
7071 ****************************************************************************/
7072
7073 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7074                         bool large_file_format)
7075 {
7076         uint64_t count = 0;
7077
7078         if(!large_file_format) {
7079                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7080         } else {
7081
7082 #if defined(HAVE_LONGLONG)
7083                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7084                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7085 #else /* HAVE_LONGLONG */
7086
7087                 /*
7088                  * NT4.x seems to be broken in that it sends large file (64 bit)
7089                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7090                  * negotiated. For boxes without large unsigned ints truncate the
7091                  * lock count by dropping the top 32 bits.
7092                  */
7093
7094                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7095                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7096                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7097                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7098                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7099                 }
7100
7101                 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7102 #endif /* HAVE_LONGLONG */
7103         }
7104
7105         return count;
7106 }
7107
7108 #if !defined(HAVE_LONGLONG)
7109 /****************************************************************************
7110  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7111 ****************************************************************************/
7112
7113 static uint32 map_lock_offset(uint32 high, uint32 low)
7114 {
7115         unsigned int i;
7116         uint32 mask = 0;
7117         uint32 highcopy = high;
7118
7119         /*
7120          * Try and find out how many significant bits there are in high.
7121          */
7122
7123         for(i = 0; highcopy; i++)
7124                 highcopy >>= 1;
7125
7126         /*
7127          * We use 31 bits not 32 here as POSIX
7128          * lock offsets may not be negative.
7129          */
7130
7131         mask = (~0) << (31 - i);
7132
7133         if(low & mask)
7134                 return 0; /* Fail. */
7135
7136         high <<= (31 - i);
7137
7138         return (high|low);
7139 }
7140 #endif /* !defined(HAVE_LONGLONG) */
7141
7142 /****************************************************************************
7143  Get a lock offset, dealing with large offset requests.
7144 ****************************************************************************/
7145
7146 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7147                          bool large_file_format, bool *err)
7148 {
7149         uint64_t offset = 0;
7150
7151         *err = False;
7152
7153         if(!large_file_format) {
7154                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7155         } else {
7156
7157 #if defined(HAVE_LONGLONG)
7158                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7159                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7160 #else /* HAVE_LONGLONG */
7161
7162                 /*
7163                  * NT4.x seems to be broken in that it sends large file (64 bit)
7164                  * lockingX calls even if the CAP_LARGE_FILES was *not*
7165                  * negotiated. For boxes without large unsigned ints mangle the
7166                  * lock offset by mapping the top 32 bits onto the lower 32.
7167                  */
7168
7169                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7170                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7171                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7172                         uint32 new_low = 0;
7173
7174                         if((new_low = map_lock_offset(high, low)) == 0) {
7175                                 *err = True;
7176                                 return (uint64_t)-1;
7177                         }
7178
7179                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7180                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7181                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7182                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7183                 }
7184
7185                 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7186 #endif /* HAVE_LONGLONG */
7187         }
7188
7189         return offset;
7190 }
7191
7192 NTSTATUS smbd_do_locking(struct smb_request *req,
7193                          files_struct *fsp,
7194                          uint8_t type,
7195                          int32_t timeout,
7196                          uint16_t num_ulocks,
7197                          struct smbd_lock_element *ulocks,
7198                          uint16_t num_locks,
7199                          struct smbd_lock_element *locks,
7200                          bool *async)
7201 {
7202         connection_struct *conn = req->conn;
7203         int i;
7204         NTSTATUS status = NT_STATUS_OK;
7205
7206         *async = false;
7207
7208         /* Data now points at the beginning of the list
7209            of smb_unlkrng structs */
7210         for(i = 0; i < (int)num_ulocks; i++) {
7211                 struct smbd_lock_element *e = &ulocks[i];
7212
7213                 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7214                           "pid %u, file %s\n",
7215                           (double)e->offset,
7216                           (double)e->count,
7217                           (unsigned int)e->smblctx,
7218                           fsp_str_dbg(fsp)));
7219
7220                 if (e->brltype != UNLOCK_LOCK) {
7221                         /* this can only happen with SMB2 */
7222                         return NT_STATUS_INVALID_PARAMETER;
7223                 }
7224
7225                 status = do_unlock(req->sconn->msg_ctx,
7226                                 fsp,
7227                                 e->smblctx,
7228                                 e->count,
7229                                 e->offset,
7230                                 WINDOWS_LOCK);
7231
7232                 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7233                     nt_errstr(status)));
7234
7235                 if (!NT_STATUS_IS_OK(status)) {
7236                         return status;
7237                 }
7238         }
7239
7240         /* Setup the timeout in seconds. */
7241
7242         if (!lp_blocking_locks(SNUM(conn))) {
7243                 timeout = 0;
7244         }
7245
7246         /* Data now points at the beginning of the list
7247            of smb_lkrng structs */
7248
7249         for(i = 0; i < (int)num_locks; i++) {
7250                 struct smbd_lock_element *e = &locks[i];
7251
7252                 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7253                           "%llu, file %s timeout = %d\n",
7254                           (double)e->offset,
7255                           (double)e->count,
7256                           (unsigned long long)e->smblctx,
7257                           fsp_str_dbg(fsp),
7258                           (int)timeout));
7259
7260                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7261                         struct blocking_lock_record *blr = NULL;
7262
7263                         if (num_locks > 1) {
7264                                 /*
7265                                  * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7266                                  * if the lock vector contains one entry. When given mutliple cancel
7267                                  * requests in a single PDU we expect the server to return an
7268                                  * error. Windows servers seem to accept the request but only
7269                                  * cancel the first lock.
7270                                  * JRA - Do what Windows does (tm) :-).
7271                                  */
7272
7273 #if 0
7274                                 /* MS-CIFS (2.2.4.32.1) behavior. */
7275                                 return NT_STATUS_DOS(ERRDOS,
7276                                                 ERRcancelviolation);
7277 #else
7278                                 /* Windows behavior. */
7279                                 if (i != 0) {
7280                                         DEBUG(10,("smbd_do_locking: ignoring subsequent "
7281                                                 "cancel request\n"));
7282                                         continue;
7283                                 }
7284 #endif
7285                         }
7286
7287                         if (lp_blocking_locks(SNUM(conn))) {
7288
7289                                 /* Schedule a message to ourselves to
7290                                    remove the blocking lock record and
7291                                    return the right error. */
7292
7293                                 blr = blocking_lock_cancel_smb1(fsp,
7294                                                 e->smblctx,
7295                                                 e->offset,
7296                                                 e->count,
7297                                                 WINDOWS_LOCK,
7298                                                 type,
7299                                                 NT_STATUS_FILE_LOCK_CONFLICT);
7300                                 if (blr == NULL) {
7301                                         return NT_STATUS_DOS(
7302                                                         ERRDOS,
7303                                                         ERRcancelviolation);
7304                                 }
7305                         }
7306                         /* Remove a matching pending lock. */
7307                         status = do_lock_cancel(fsp,
7308                                                 e->smblctx,
7309                                                 e->count,
7310                                                 e->offset,
7311                                                 WINDOWS_LOCK,
7312                                                 blr);
7313                 } else {
7314                         bool blocking_lock = timeout ? true : false;
7315                         bool defer_lock = false;
7316                         struct byte_range_lock *br_lck;
7317                         uint64_t block_smblctx;
7318
7319                         br_lck = do_lock(req->sconn->msg_ctx,
7320                                         fsp,
7321                                         e->smblctx,
7322                                         e->count,
7323                                         e->offset, 
7324                                         e->brltype,
7325                                         WINDOWS_LOCK,
7326                                         blocking_lock,
7327                                         &status,
7328                                         &block_smblctx,
7329                                         NULL);
7330
7331                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7332                                 /* Windows internal resolution for blocking locks seems
7333                                    to be about 200ms... Don't wait for less than that. JRA. */
7334                                 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7335                                         timeout = lp_lock_spin_time();
7336                                 }
7337                                 defer_lock = true;
7338                         }
7339
7340                         /* If a lock sent with timeout of zero would fail, and
7341                          * this lock has been requested multiple times,
7342                          * according to brl_lock_failed() we convert this
7343                          * request to a blocking lock with a timeout of between
7344                          * 150 - 300 milliseconds.
7345                          *
7346                          * If lp_lock_spin_time() has been set to 0, we skip
7347                          * this blocking retry and fail immediately.
7348                          *
7349                          * Replacement for do_lock_spin(). JRA. */
7350
7351                         if (!req->sconn->using_smb2 &&
7352                             br_lck && lp_blocking_locks(SNUM(conn)) &&
7353                             lp_lock_spin_time() && !blocking_lock &&
7354                             NT_STATUS_EQUAL((status),
7355                                 NT_STATUS_FILE_LOCK_CONFLICT))
7356                         {
7357                                 defer_lock = true;
7358                                 timeout = lp_lock_spin_time();
7359                         }
7360
7361                         if (br_lck && defer_lock) {
7362                                 /*
7363                                  * A blocking lock was requested. Package up
7364                                  * this smb into a queued request and push it
7365                                  * onto the blocking lock queue.
7366                                  */
7367                                 if(push_blocking_lock_request(br_lck,
7368                                                         req,
7369                                                         fsp,
7370                                                         timeout,
7371                                                         i,
7372                                                         e->smblctx,
7373                                                         e->brltype,
7374                                                         WINDOWS_LOCK,
7375                                                         e->offset,
7376                                                         e->count,
7377                                                         block_smblctx)) {
7378                                         TALLOC_FREE(br_lck);
7379                                         *async = true;
7380                                         return NT_STATUS_OK;
7381                                 }
7382                         }
7383
7384                         TALLOC_FREE(br_lck);
7385                 }
7386
7387                 if (!NT_STATUS_IS_OK(status)) {
7388                         break;
7389                 }
7390         }
7391
7392         /* If any of the above locks failed, then we must unlock
7393            all of the previous locks (X/Open spec). */
7394
7395         if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7396
7397                 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7398                         i = -1; /* we want to skip the for loop */
7399                 }
7400
7401                 /*
7402                  * Ensure we don't do a remove on the lock that just failed,
7403                  * as under POSIX rules, if we have a lock already there, we
7404                  * will delete it (and we shouldn't) .....
7405                  */
7406                 for(i--; i >= 0; i--) {
7407                         struct smbd_lock_element *e = &locks[i];
7408
7409                         do_unlock(req->sconn->msg_ctx,
7410                                 fsp,
7411                                 e->smblctx,
7412                                 e->count,
7413                                 e->offset,
7414                                 WINDOWS_LOCK);
7415                 }
7416                 return status;
7417         }
7418
7419         DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7420                   fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7421
7422         return NT_STATUS_OK;
7423 }
7424
7425 /****************************************************************************
7426  Reply to a lockingX request.
7427 ****************************************************************************/
7428
7429 void reply_lockingX(struct smb_request *req)
7430 {
7431         connection_struct *conn = req->conn;
7432         files_struct *fsp;
7433         unsigned char locktype;
7434         unsigned char oplocklevel;
7435         uint16 num_ulocks;
7436         uint16 num_locks;
7437         int32 lock_timeout;
7438         int i;
7439         const uint8_t *data;
7440         bool large_file_format;
7441         bool err;
7442         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7443         struct smbd_lock_element *ulocks;
7444         struct smbd_lock_element *locks;
7445         bool async = false;
7446
7447         START_PROFILE(SMBlockingX);
7448
7449         if (req->wct < 8) {
7450                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7451                 END_PROFILE(SMBlockingX);
7452                 return;
7453         }
7454
7455         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7456         locktype = CVAL(req->vwv+3, 0);
7457         oplocklevel = CVAL(req->vwv+3, 1);
7458         num_ulocks = SVAL(req->vwv+6, 0);
7459         num_locks = SVAL(req->vwv+7, 0);
7460         lock_timeout = IVAL(req->vwv+4, 0);
7461         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7462
7463         if (!check_fsp(conn, req, fsp)) {
7464                 END_PROFILE(SMBlockingX);
7465                 return;
7466         }
7467
7468         data = req->buf;
7469
7470         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7471                 /* we don't support these - and CANCEL_LOCK makes w2k
7472                    and XP reboot so I don't really want to be
7473                    compatible! (tridge) */
7474                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7475                 END_PROFILE(SMBlockingX);
7476                 return;
7477         }
7478
7479         /* Check if this is an oplock break on a file
7480            we have granted an oplock on.
7481         */
7482         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7483                 /* Client can insist on breaking to none. */
7484                 bool break_to_none = (oplocklevel == 0);
7485                 bool result;
7486
7487                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7488                          "for fnum = %d\n", (unsigned int)oplocklevel,
7489                          fsp->fnum ));
7490
7491                 /*
7492                  * Make sure we have granted an exclusive or batch oplock on
7493                  * this file.
7494                  */
7495
7496                 if (fsp->oplock_type == 0) {
7497
7498                         /* The Samba4 nbench simulator doesn't understand
7499                            the difference between break to level2 and break
7500                            to none from level2 - it sends oplock break
7501                            replies in both cases. Don't keep logging an error
7502                            message here - just ignore it. JRA. */
7503
7504                         DEBUG(5,("reply_lockingX: Error : oplock break from "
7505                                  "client for fnum = %d (oplock=%d) and no "
7506                                  "oplock granted on this file (%s).\n",
7507                                  fsp->fnum, fsp->oplock_type,
7508                                  fsp_str_dbg(fsp)));
7509
7510                         /* if this is a pure oplock break request then don't
7511                          * send a reply */
7512                         if (num_locks == 0 && num_ulocks == 0) {
7513                                 END_PROFILE(SMBlockingX);
7514                                 return;
7515                         } else {
7516                                 END_PROFILE(SMBlockingX);
7517                                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7518                                 return;
7519                         }
7520                 }
7521
7522                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7523                     (break_to_none)) {
7524                         result = remove_oplock(fsp);
7525                 } else {
7526                         result = downgrade_oplock(fsp);
7527                 }
7528
7529                 if (!result) {
7530                         DEBUG(0, ("reply_lockingX: error in removing "
7531                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
7532                         /* Hmmm. Is this panic justified? */
7533                         smb_panic("internal tdb error");
7534                 }
7535
7536                 reply_to_oplock_break_requests(fsp);
7537
7538                 /* if this is a pure oplock break request then don't send a
7539                  * reply */
7540                 if (num_locks == 0 && num_ulocks == 0) {
7541                         /* Sanity check - ensure a pure oplock break is not a
7542                            chained request. */
7543                         if(CVAL(req->vwv+0, 0) != 0xff)
7544                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
7545                                          "break is a chained %d request !\n",
7546                                          (unsigned int)CVAL(req->vwv+0, 0)));
7547                         END_PROFILE(SMBlockingX);
7548                         return;
7549                 }
7550         }
7551
7552         if (req->buflen <
7553             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7554                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7555                 END_PROFILE(SMBlockingX);
7556                 return;
7557         }
7558
7559         ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7560         if (ulocks == NULL) {
7561                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7562                 END_PROFILE(SMBlockingX);
7563                 return;
7564         }
7565
7566         locks = talloc_array(req, struct smbd_lock_element, num_locks);
7567         if (locks == NULL) {
7568                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7569                 END_PROFILE(SMBlockingX);
7570                 return;
7571         }
7572
7573         /* Data now points at the beginning of the list
7574            of smb_unlkrng structs */
7575         for(i = 0; i < (int)num_ulocks; i++) {
7576                 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7577                 ulocks[i].count = get_lock_count(data, i, large_file_format);
7578                 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7579                 ulocks[i].brltype = UNLOCK_LOCK;
7580
7581                 /*
7582                  * There is no error code marked "stupid client bug".... :-).
7583                  */
7584                 if(err) {
7585                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7586                         END_PROFILE(SMBlockingX);
7587                         return;
7588                 }
7589         }
7590
7591         /* Now do any requested locks */
7592         data += ((large_file_format ? 20 : 10)*num_ulocks);
7593
7594         /* Data now points at the beginning of the list
7595            of smb_lkrng structs */
7596
7597         for(i = 0; i < (int)num_locks; i++) {
7598                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7599                 locks[i].count = get_lock_count(data, i, large_file_format);
7600                 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7601
7602                 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7603                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7604                                 locks[i].brltype = PENDING_READ_LOCK;
7605                         } else {
7606                                 locks[i].brltype = READ_LOCK;
7607                         }
7608                 } else {
7609                         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7610                                 locks[i].brltype = PENDING_WRITE_LOCK;
7611                         } else {
7612                                 locks[i].brltype = WRITE_LOCK;
7613                         }
7614                 }
7615
7616                 /*
7617                  * There is no error code marked "stupid client bug".... :-).
7618                  */
7619                 if(err) {
7620                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7621                         END_PROFILE(SMBlockingX);
7622                         return;
7623                 }
7624         }
7625
7626         status = smbd_do_locking(req, fsp,
7627                                  locktype, lock_timeout,
7628                                  num_ulocks, ulocks,
7629                                  num_locks, locks,
7630                                  &async);
7631         if (!NT_STATUS_IS_OK(status)) {
7632                 END_PROFILE(SMBlockingX);
7633                 reply_nterror(req, status);
7634                 return;
7635         }
7636         if (async) {
7637                 END_PROFILE(SMBlockingX);
7638                 return;
7639         }
7640
7641         reply_outbuf(req, 2, 0);
7642
7643         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7644                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7645
7646         END_PROFILE(SMBlockingX);
7647         chain_reply(req);
7648 }
7649
7650 #undef DBGC_CLASS
7651 #define DBGC_CLASS DBGC_ALL
7652
7653 /****************************************************************************
7654  Reply to a SMBreadbmpx (read block multiplex) request.
7655  Always reply with an error, if someone has a platform really needs this,
7656  please contact vl@samba.org
7657 ****************************************************************************/
7658
7659 void reply_readbmpx(struct smb_request *req)
7660 {
7661         START_PROFILE(SMBreadBmpx);
7662         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7663         END_PROFILE(SMBreadBmpx);
7664         return;
7665 }
7666
7667 /****************************************************************************
7668  Reply to a SMBreadbs (read block multiplex secondary) request.
7669  Always reply with an error, if someone has a platform really needs this,
7670  please contact vl@samba.org
7671 ****************************************************************************/
7672
7673 void reply_readbs(struct smb_request *req)
7674 {
7675         START_PROFILE(SMBreadBs);
7676         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7677         END_PROFILE(SMBreadBs);
7678         return;
7679 }
7680
7681 /****************************************************************************
7682  Reply to a SMBsetattrE.
7683 ****************************************************************************/
7684
7685 void reply_setattrE(struct smb_request *req)
7686 {
7687         connection_struct *conn = req->conn;
7688         struct smb_file_time ft;
7689         files_struct *fsp;
7690         NTSTATUS status;
7691
7692         START_PROFILE(SMBsetattrE);
7693         ZERO_STRUCT(ft);
7694
7695         if (req->wct < 7) {
7696                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7697                 goto out;
7698         }
7699
7700         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7701
7702         if(!fsp || (fsp->conn != conn)) {
7703                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7704                 goto out;
7705         }
7706
7707         /*
7708          * Convert the DOS times into unix times.
7709          */
7710
7711         ft.atime = convert_time_t_to_timespec(
7712             srv_make_unix_date2(req->vwv+3));
7713         ft.mtime = convert_time_t_to_timespec(
7714             srv_make_unix_date2(req->vwv+5));
7715         ft.create_time = convert_time_t_to_timespec(
7716             srv_make_unix_date2(req->vwv+1));
7717
7718         reply_outbuf(req, 0, 0);
7719
7720         /* 
7721          * Patch from Ray Frush <frush@engr.colostate.edu>
7722          * Sometimes times are sent as zero - ignore them.
7723          */
7724
7725         /* Ensure we have a valid stat struct for the source. */
7726         status = vfs_stat_fsp(fsp);
7727         if (!NT_STATUS_IS_OK(status)) {
7728                 reply_nterror(req, status);
7729                 goto out;
7730         }
7731
7732         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7733         if (!NT_STATUS_IS_OK(status)) {
7734                 reply_nterror(req, status);
7735                 goto out;
7736         }
7737
7738         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7739                " createtime=%u\n",
7740                 fsp->fnum,
7741                 (unsigned int)ft.atime.tv_sec,
7742                 (unsigned int)ft.mtime.tv_sec,
7743                 (unsigned int)ft.create_time.tv_sec
7744                 ));
7745  out:
7746         END_PROFILE(SMBsetattrE);
7747         return;
7748 }
7749
7750
7751 /* Back from the dead for OS/2..... JRA. */
7752
7753 /****************************************************************************
7754  Reply to a SMBwritebmpx (write block multiplex primary) request.
7755  Always reply with an error, if someone has a platform really needs this,
7756  please contact vl@samba.org
7757 ****************************************************************************/
7758
7759 void reply_writebmpx(struct smb_request *req)
7760 {
7761         START_PROFILE(SMBwriteBmpx);
7762         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7763         END_PROFILE(SMBwriteBmpx);
7764         return;
7765 }
7766
7767 /****************************************************************************
7768  Reply to a SMBwritebs (write block multiplex secondary) request.
7769  Always reply with an error, if someone has a platform really needs this,
7770  please contact vl@samba.org
7771 ****************************************************************************/
7772
7773 void reply_writebs(struct smb_request *req)
7774 {
7775         START_PROFILE(SMBwriteBs);
7776         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7777         END_PROFILE(SMBwriteBs);
7778         return;
7779 }
7780
7781 /****************************************************************************
7782  Reply to a SMBgetattrE.
7783 ****************************************************************************/
7784
7785 void reply_getattrE(struct smb_request *req)
7786 {
7787         connection_struct *conn = req->conn;
7788         int mode;
7789         files_struct *fsp;
7790         struct timespec create_ts;
7791
7792         START_PROFILE(SMBgetattrE);
7793
7794         if (req->wct < 1) {
7795                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7796                 END_PROFILE(SMBgetattrE);
7797                 return;
7798         }
7799
7800         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7801
7802         if(!fsp || (fsp->conn != conn)) {
7803                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7804                 END_PROFILE(SMBgetattrE);
7805                 return;
7806         }
7807
7808         /* Do an fstat on this file */
7809         if(fsp_stat(fsp)) {
7810                 reply_nterror(req, map_nt_error_from_unix(errno));
7811                 END_PROFILE(SMBgetattrE);
7812                 return;
7813         }
7814
7815         mode = dos_mode(conn, fsp->fsp_name);
7816
7817         /*
7818          * Convert the times into dos times. Set create
7819          * date to be last modify date as UNIX doesn't save
7820          * this.
7821          */
7822
7823         reply_outbuf(req, 11, 0);
7824
7825         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7826         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7827         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7828                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7829         /* Should we check pending modtime here ? JRA */
7830         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7831                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7832
7833         if (mode & aDIR) {
7834                 SIVAL(req->outbuf, smb_vwv6, 0);
7835                 SIVAL(req->outbuf, smb_vwv8, 0);
7836         } else {
7837                 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7838                 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7839                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7840         }
7841         SSVAL(req->outbuf,smb_vwv10, mode);
7842
7843         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7844
7845         END_PROFILE(SMBgetattrE);
7846         return;
7847 }