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