s3: Add new "is_dos_path" argument to SMB_VFS_CREATE_FILE
[metze/samba/wip.git] / source3 / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28
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                 true,                                   /* is_dos_path */
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                 true,                                   /* is_dos_path */
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                 true,                                   /* is_dos_path */
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 = open_file_ntcreate(conn, req, fname, &sbuf,
2127                                 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
2128                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
2129                                 FILE_OPEN,
2130                                 0,
2131                                 fattr,
2132                                 oplock_request,
2133                                 NULL, &fsp);
2134
2135         /* close fd from smb_mkstemp() */
2136         close(tmpfd);
2137
2138         if (!NT_STATUS_IS_OK(status)) {
2139                 if (open_was_deferred(req->mid)) {
2140                         /* We have re-scheduled this call. */
2141                         END_PROFILE(SMBctemp);
2142                         return;
2143                 }
2144                 reply_openerror(req, status);
2145                 END_PROFILE(SMBctemp);
2146                 return;
2147         }
2148
2149         reply_outbuf(req, 1, 0);
2150         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2151
2152         /* the returned filename is relative to the directory */
2153         s = strrchr_m(fsp->fsp_name, '/');
2154         if (!s) {
2155                 s = fsp->fsp_name;
2156         } else {
2157                 s++;
2158         }
2159
2160 #if 0
2161         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2162            thing in the byte section. JRA */
2163         SSVALS(p, 0, -1); /* what is this? not in spec */
2164 #endif
2165         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2166             == -1) {
2167                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2168                 END_PROFILE(SMBctemp);
2169                 return;
2170         }
2171
2172         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2173                 SCVAL(req->outbuf, smb_flg,
2174                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2175         }
2176
2177         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2178                 SCVAL(req->outbuf, smb_flg,
2179                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2180         }
2181
2182         DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2183         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2184                     fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
2185
2186         END_PROFILE(SMBctemp);
2187         return;
2188 }
2189
2190 /*******************************************************************
2191  Check if a user is allowed to rename a file.
2192 ********************************************************************/
2193
2194 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2195                            uint16 dirtype, SMB_STRUCT_STAT *pst)
2196 {
2197         uint32 fmode;
2198
2199         if (!CAN_WRITE(conn)) {
2200                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2201         }
2202
2203         fmode = dos_mode(conn, fsp->fsp_name, pst);
2204         if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2205                 return NT_STATUS_NO_SUCH_FILE;
2206         }
2207
2208         if (S_ISDIR(pst->st_mode)) {
2209                 return NT_STATUS_OK;
2210         }
2211
2212         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2213                 return NT_STATUS_OK;
2214         }
2215
2216         return NT_STATUS_ACCESS_DENIED;
2217 }
2218
2219 /*******************************************************************
2220  * unlink a file with all relevant access checks
2221  *******************************************************************/
2222
2223 static NTSTATUS do_unlink(connection_struct *conn,
2224                         struct smb_request *req,
2225                         const char *fname,
2226                         uint32 dirtype)
2227 {
2228         SMB_STRUCT_STAT sbuf;
2229         uint32 fattr;
2230         files_struct *fsp;
2231         uint32 dirtype_orig = dirtype;
2232         NTSTATUS status;
2233
2234         DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2235
2236         if (!CAN_WRITE(conn)) {
2237                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2238         }
2239
2240         if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2241                 return map_nt_error_from_unix(errno);
2242         }
2243
2244         fattr = dos_mode(conn,fname,&sbuf);
2245
2246         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2247                 dirtype = aDIR|aARCH|aRONLY;
2248         }
2249
2250         dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2251         if (!dirtype) {
2252                 return NT_STATUS_NO_SUCH_FILE;
2253         }
2254
2255         if (!dir_check_ftype(conn, fattr, dirtype)) {
2256                 if (fattr & aDIR) {
2257                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2258                 }
2259                 return NT_STATUS_NO_SUCH_FILE;
2260         }
2261
2262         if (dirtype_orig & 0x8000) {
2263                 /* These will never be set for POSIX. */
2264                 return NT_STATUS_NO_SUCH_FILE;
2265         }
2266
2267 #if 0
2268         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2269                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2270         }
2271
2272         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2273                 return NT_STATUS_NO_SUCH_FILE;
2274         }
2275
2276         if (dirtype & 0xFF00) {
2277                 /* These will never be set for POSIX. */
2278                 return NT_STATUS_NO_SUCH_FILE;
2279         }
2280
2281         dirtype &= 0xFF;
2282         if (!dirtype) {
2283                 return NT_STATUS_NO_SUCH_FILE;
2284         }
2285
2286         /* Can't delete a directory. */
2287         if (fattr & aDIR) {
2288                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2289         }
2290 #endif
2291
2292 #if 0 /* JRATEST */
2293         else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2294                 return NT_STATUS_OBJECT_NAME_INVALID;
2295 #endif /* JRATEST */
2296
2297         /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2298
2299           On a Windows share, a file with read-only dosmode can be opened with
2300           DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2301           fails with NT_STATUS_CANNOT_DELETE error.
2302
2303           This semantic causes a problem that a user can not
2304           rename a file with read-only dosmode on a Samba share
2305           from a Windows command prompt (i.e. cmd.exe, but can rename
2306           from Windows Explorer).
2307         */
2308
2309         if (!lp_delete_readonly(SNUM(conn))) {
2310                 if (fattr & aRONLY) {
2311                         return NT_STATUS_CANNOT_DELETE;
2312                 }
2313         }
2314
2315         /* On open checks the open itself will check the share mode, so
2316            don't do it here as we'll get it wrong. */
2317
2318         status = create_file_unixpath
2319                 (conn,                  /* conn */
2320                  req,                   /* req */
2321                  fname,                 /* fname */
2322                  DELETE_ACCESS,         /* access_mask */
2323                  FILE_SHARE_NONE,       /* share_access */
2324                  FILE_OPEN,             /* create_disposition*/
2325                  FILE_NON_DIRECTORY_FILE, /* create_options */
2326                  FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2327                  0,                     /* oplock_request */
2328                  0,                     /* allocation_size */
2329                  NULL,                  /* sd */
2330                  NULL,                  /* ea_list */
2331                  &fsp,                  /* result */
2332                  NULL,                  /* pinfo */
2333                  &sbuf);                /* psbuf */
2334
2335         if (!NT_STATUS_IS_OK(status)) {
2336                 DEBUG(10, ("create_file_unixpath failed: %s\n",
2337                            nt_errstr(status)));
2338                 return status;
2339         }
2340
2341         /* The set is across all open files on this dev/inode pair. */
2342         if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2343                 close_file(req, fsp, NORMAL_CLOSE);
2344                 return NT_STATUS_ACCESS_DENIED;
2345         }
2346
2347         return close_file(req, fsp, NORMAL_CLOSE);
2348 }
2349
2350 /****************************************************************************
2351  The guts of the unlink command, split out so it may be called by the NT SMB
2352  code.
2353 ****************************************************************************/
2354
2355 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2356                           uint32 dirtype, const char *name_in, bool has_wild)
2357 {
2358         const char *directory = NULL;
2359         char *mask = NULL;
2360         char *name = NULL;
2361         char *p = NULL;
2362         int count=0;
2363         NTSTATUS status = NT_STATUS_OK;
2364         SMB_STRUCT_STAT sbuf;
2365         TALLOC_CTX *ctx = talloc_tos();
2366
2367         status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2368         if (!NT_STATUS_IS_OK(status)) {
2369                 return status;
2370         }
2371
2372         p = strrchr_m(name,'/');
2373         if (!p) {
2374                 directory = talloc_strdup(ctx, ".");
2375                 if (!directory) {
2376                         return NT_STATUS_NO_MEMORY;
2377                 }
2378                 mask = name;
2379         } else {
2380                 *p = 0;
2381                 directory = name;
2382                 mask = p+1;
2383         }
2384
2385         /*
2386          * We should only check the mangled cache
2387          * here if unix_convert failed. This means
2388          * that the path in 'mask' doesn't exist
2389          * on the file system and so we need to look
2390          * for a possible mangle. This patch from
2391          * Tine Smukavec <valentin.smukavec@hermes.si>.
2392          */
2393
2394         if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2395                 char *new_mask = NULL;
2396                 mangle_lookup_name_from_8_3(ctx,
2397                                 mask,
2398                                 &new_mask,
2399                                 conn->params );
2400                 if (new_mask) {
2401                         mask = new_mask;
2402                 }
2403         }
2404
2405         if (!has_wild) {
2406                 directory = talloc_asprintf(ctx,
2407                                 "%s/%s",
2408                                 directory,
2409                                 mask);
2410                 if (!directory) {
2411                         return NT_STATUS_NO_MEMORY;
2412                 }
2413                 if (dirtype == 0) {
2414                         dirtype = FILE_ATTRIBUTE_NORMAL;
2415                 }
2416
2417                 status = check_name(conn, directory);
2418                 if (!NT_STATUS_IS_OK(status)) {
2419                         return status;
2420                 }
2421
2422                 status = do_unlink(conn, req, directory, dirtype);
2423                 if (!NT_STATUS_IS_OK(status)) {
2424                         return status;
2425                 }
2426
2427                 count++;
2428         } else {
2429                 struct smb_Dir *dir_hnd = NULL;
2430                 long offset = 0;
2431                 const char *dname;
2432
2433                 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2434                         return NT_STATUS_OBJECT_NAME_INVALID;
2435                 }
2436
2437                 if (strequal(mask,"????????.???")) {
2438                         mask[0] = '*';
2439                         mask[1] = '\0';
2440                 }
2441
2442                 status = check_name(conn, directory);
2443                 if (!NT_STATUS_IS_OK(status)) {
2444                         return status;
2445                 }
2446
2447                 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2448                                   dirtype);
2449                 if (dir_hnd == NULL) {
2450                         return map_nt_error_from_unix(errno);
2451                 }
2452
2453                 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2454                    the pattern matches against the long name, otherwise the short name 
2455                    We don't implement this yet XXXX
2456                 */
2457
2458                 status = NT_STATUS_NO_SUCH_FILE;
2459
2460                 while ((dname = ReadDirName(dir_hnd, &offset))) {
2461                         SMB_STRUCT_STAT st;
2462                         char *fname = NULL;
2463
2464                         if (!is_visible_file(conn, directory, dname, &st, True)) {
2465                                 continue;
2466                         }
2467
2468                         /* Quick check for "." and ".." */
2469                         if (ISDOT(dname) || ISDOTDOT(dname)) {
2470                                 continue;
2471                         }
2472
2473                         if(!mask_match(dname, mask, conn->case_sensitive)) {
2474                                 continue;
2475                         }
2476
2477                         fname = talloc_asprintf(ctx, "%s/%s",
2478                                         directory,
2479                                         dname);
2480                         if (!fname) {
2481                                 return NT_STATUS_NO_MEMORY;
2482                         }
2483
2484                         status = check_name(conn, fname);
2485                         if (!NT_STATUS_IS_OK(status)) {
2486                                 TALLOC_FREE(dir_hnd);
2487                                 return status;
2488                         }
2489
2490                         status = do_unlink(conn, req, fname, dirtype);
2491                         if (!NT_STATUS_IS_OK(status)) {
2492                                 TALLOC_FREE(fname);
2493                                 continue;
2494                         }
2495
2496                         count++;
2497                         DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2498                                  fname));
2499
2500                         TALLOC_FREE(fname);
2501                 }
2502                 TALLOC_FREE(dir_hnd);
2503         }
2504
2505         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2506                 status = map_nt_error_from_unix(errno);
2507         }
2508
2509         return status;
2510 }
2511
2512 /****************************************************************************
2513  Reply to a unlink
2514 ****************************************************************************/
2515
2516 void reply_unlink(struct smb_request *req)
2517 {
2518         connection_struct *conn = req->conn;
2519         char *name = NULL;
2520         uint32 dirtype;
2521         NTSTATUS status;
2522         bool path_contains_wcard = False;
2523         TALLOC_CTX *ctx = talloc_tos();
2524
2525         START_PROFILE(SMBunlink);
2526
2527         if (req->wct < 1) {
2528                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2529                 END_PROFILE(SMBunlink);
2530                 return;
2531         }
2532
2533         dirtype = SVAL(req->vwv+0, 0);
2534
2535         srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2536                                   STR_TERMINATE, &status,
2537                                   &path_contains_wcard);
2538         if (!NT_STATUS_IS_OK(status)) {
2539                 reply_nterror(req, status);
2540                 END_PROFILE(SMBunlink);
2541                 return;
2542         }
2543
2544         status = resolve_dfspath_wcard(ctx, conn,
2545                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
2546                                        name,
2547                                        &name,
2548                                        &path_contains_wcard);
2549         if (!NT_STATUS_IS_OK(status)) {
2550                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2551                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2552                                         ERRSRV, ERRbadpath);
2553                         END_PROFILE(SMBunlink);
2554                         return;
2555                 }
2556                 reply_nterror(req, status);
2557                 END_PROFILE(SMBunlink);
2558                 return;
2559         }
2560
2561         DEBUG(3,("reply_unlink : %s\n",name));
2562
2563         status = unlink_internals(conn, req, dirtype, name,
2564                                   path_contains_wcard);
2565         if (!NT_STATUS_IS_OK(status)) {
2566                 if (open_was_deferred(req->mid)) {
2567                         /* We have re-scheduled this call. */
2568                         END_PROFILE(SMBunlink);
2569                         return;
2570                 }
2571                 reply_nterror(req, status);
2572                 END_PROFILE(SMBunlink);
2573                 return;
2574         }
2575
2576         reply_outbuf(req, 0, 0);
2577         END_PROFILE(SMBunlink);
2578
2579         return;
2580 }
2581
2582 /****************************************************************************
2583  Fail for readbraw.
2584 ****************************************************************************/
2585
2586 static void fail_readraw(void)
2587 {
2588         const char *errstr = talloc_asprintf(talloc_tos(),
2589                         "FAIL ! reply_readbraw: socket write fail (%s)",
2590                         strerror(errno));
2591         if (!errstr) {
2592                 errstr = "";
2593         }
2594         exit_server_cleanly(errstr);
2595 }
2596
2597 /****************************************************************************
2598  Fake (read/write) sendfile. Returns -1 on read or write fail.
2599 ****************************************************************************/
2600
2601 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2602                              size_t nread)
2603 {
2604         size_t bufsize;
2605         size_t tosend = nread;
2606         char *buf;
2607
2608         if (nread == 0) {
2609                 return 0;
2610         }
2611
2612         bufsize = MIN(nread, 65536);
2613
2614         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2615                 return -1;
2616         }
2617
2618         while (tosend > 0) {
2619                 ssize_t ret;
2620                 size_t cur_read;
2621
2622                 if (tosend > bufsize) {
2623                         cur_read = bufsize;
2624                 } else {
2625                         cur_read = tosend;
2626                 }
2627                 ret = read_file(fsp,buf,startpos,cur_read);
2628                 if (ret == -1) {
2629                         SAFE_FREE(buf);
2630                         return -1;
2631                 }
2632
2633                 /* If we had a short read, fill with zeros. */
2634                 if (ret < cur_read) {
2635                         memset(buf, '\0', cur_read - ret);
2636                 }
2637
2638                 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2639                         SAFE_FREE(buf);
2640                         return -1;
2641                 }
2642                 tosend -= cur_read;
2643                 startpos += cur_read;
2644         }
2645
2646         SAFE_FREE(buf);
2647         return (ssize_t)nread;
2648 }
2649
2650 /****************************************************************************
2651  Return a readbraw error (4 bytes of zero).
2652 ****************************************************************************/
2653
2654 static void reply_readbraw_error(void)
2655 {
2656         char header[4];
2657         SIVAL(header,0,0);
2658         if (write_data(smbd_server_fd(),header,4) != 4) {
2659                 fail_readraw();
2660         }
2661 }
2662
2663 /****************************************************************************
2664  Use sendfile in readbraw.
2665 ****************************************************************************/
2666
2667 void send_file_readbraw(connection_struct *conn,
2668                         files_struct *fsp,
2669                         SMB_OFF_T startpos,
2670                         size_t nread,
2671                         ssize_t mincount)
2672 {
2673         char *outbuf = NULL;
2674         ssize_t ret=0;
2675
2676 #if defined(WITH_SENDFILE)
2677         /*
2678          * We can only use sendfile on a non-chained packet 
2679          * but we can use on a non-oplocked file. tridge proved this
2680          * on a train in Germany :-). JRA.
2681          * reply_readbraw has already checked the length.
2682          */
2683
2684         if ( (chain_size == 0) && (nread > 0) && (fsp->base_fsp == NULL) &&
2685             (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2686                 char header[4];
2687                 DATA_BLOB header_blob;
2688
2689                 _smb_setlen(header,nread);
2690                 header_blob = data_blob_const(header, 4);
2691
2692                 if (SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2693                                 &header_blob, startpos, nread) == -1) {
2694                         /* Returning ENOSYS means no data at all was sent.
2695                          * Do this as a normal read. */
2696                         if (errno == ENOSYS) {
2697                                 goto normal_readbraw;
2698                         }
2699
2700                         /*
2701                          * Special hack for broken Linux with no working sendfile. If we
2702                          * return EINTR we sent the header but not the rest of the data.
2703                          * Fake this up by doing read/write calls.
2704                          */
2705                         if (errno == EINTR) {
2706                                 /* Ensure we don't do this again. */
2707                                 set_use_sendfile(SNUM(conn), False);
2708                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2709
2710                                 if (fake_sendfile(fsp, startpos, nread) == -1) {
2711                                         DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2712                                                 fsp->fsp_name, strerror(errno) ));
2713                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2714                                 }
2715                                 return;
2716                         }
2717
2718                         DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2719                                 fsp->fsp_name, strerror(errno) ));
2720                         exit_server_cleanly("send_file_readbraw sendfile failed");
2721                 }
2722
2723                 return;
2724         }
2725 #endif
2726
2727 normal_readbraw:
2728
2729         outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2730         if (!outbuf) {
2731                 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2732                         (unsigned)(nread+4)));
2733                 reply_readbraw_error();
2734                 return;
2735         }
2736
2737         if (nread > 0) {
2738                 ret = read_file(fsp,outbuf+4,startpos,nread);
2739 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2740                 if (ret < mincount)
2741                         ret = 0;
2742 #else
2743                 if (ret < nread)
2744                         ret = 0;
2745 #endif
2746         }
2747
2748         _smb_setlen(outbuf,ret);
2749         if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2750                 fail_readraw();
2751
2752         TALLOC_FREE(outbuf);
2753 }
2754
2755 /****************************************************************************
2756  Reply to a readbraw (core+ protocol).
2757 ****************************************************************************/
2758
2759 void reply_readbraw(struct smb_request *req)
2760 {
2761         connection_struct *conn = req->conn;
2762         ssize_t maxcount,mincount;
2763         size_t nread = 0;
2764         SMB_OFF_T startpos;
2765         files_struct *fsp;
2766         SMB_STRUCT_STAT st;
2767         SMB_OFF_T size = 0;
2768
2769         START_PROFILE(SMBreadbraw);
2770
2771         if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2772                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2773                         "raw reads/writes are disallowed.");
2774         }
2775
2776         if (req->wct < 8) {
2777                 reply_readbraw_error();
2778                 END_PROFILE(SMBreadbraw);
2779                 return;
2780         }
2781
2782         /*
2783          * Special check if an oplock break has been issued
2784          * and the readraw request croses on the wire, we must
2785          * return a zero length response here.
2786          */
2787
2788         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2789
2790         /*
2791          * We have to do a check_fsp by hand here, as
2792          * we must always return 4 zero bytes on error,
2793          * not a NTSTATUS.
2794          */
2795
2796         if (!fsp || !conn || conn != fsp->conn ||
2797                         req->vuid != fsp->vuid ||
2798                         fsp->is_directory || fsp->fh->fd == -1) {
2799                 /*
2800                  * fsp could be NULL here so use the value from the packet. JRA.
2801                  */
2802                 DEBUG(3,("reply_readbraw: fnum %d not valid "
2803                         "- cache prime?\n",
2804                         (int)SVAL(req->vwv+0, 0)));
2805                 reply_readbraw_error();
2806                 END_PROFILE(SMBreadbraw);
2807                 return;
2808         }
2809
2810         /* Do a "by hand" version of CHECK_READ. */
2811         if (!(fsp->can_read ||
2812                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2813                                 (fsp->access_mask & FILE_EXECUTE)))) {
2814                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2815                                 (int)SVAL(req->vwv+0, 0)));
2816                 reply_readbraw_error();
2817                 END_PROFILE(SMBreadbraw);
2818                 return;
2819         }
2820
2821         flush_write_cache(fsp, READRAW_FLUSH);
2822
2823         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2824         if(req->wct == 10) {
2825                 /*
2826                  * This is a large offset (64 bit) read.
2827                  */
2828 #ifdef LARGE_SMB_OFF_T
2829
2830                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
2831
2832 #else /* !LARGE_SMB_OFF_T */
2833
2834                 /*
2835                  * Ensure we haven't been sent a >32 bit offset.
2836                  */
2837
2838                 if(IVAL(req->vwv+8, 0) != 0) {
2839                         DEBUG(0,("reply_readbraw: large offset "
2840                                 "(%x << 32) used and we don't support "
2841                                 "64 bit offsets.\n",
2842                         (unsigned int)IVAL(req->vwv+8, 0) ));
2843                         reply_readbraw_error();
2844                         END_PROFILE(SMBreadbraw);
2845                         return;
2846                 }
2847
2848 #endif /* LARGE_SMB_OFF_T */
2849
2850                 if(startpos < 0) {
2851                         DEBUG(0,("reply_readbraw: negative 64 bit "
2852                                 "readraw offset (%.0f) !\n",
2853                                 (double)startpos ));
2854                         reply_readbraw_error();
2855                         END_PROFILE(SMBreadbraw);
2856                         return;
2857                 }      
2858         }
2859
2860         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
2861         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
2862
2863         /* ensure we don't overrun the packet size */
2864         maxcount = MIN(65535,maxcount);
2865
2866         if (is_locked(fsp,(uint32)req->smbpid,
2867                         (uint64_t)maxcount,
2868                         (uint64_t)startpos,
2869                         READ_LOCK)) {
2870                 reply_readbraw_error();
2871                 END_PROFILE(SMBreadbraw);
2872                 return;
2873         }
2874
2875         if (SMB_VFS_FSTAT(fsp, &st) == 0) {
2876                 size = st.st_size;
2877         }
2878
2879         if (startpos >= size) {
2880                 nread = 0;
2881         } else {
2882                 nread = MIN(maxcount,(size - startpos));
2883         }
2884
2885 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2886         if (nread < mincount)
2887                 nread = 0;
2888 #endif
2889
2890         DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2891                 "min=%lu nread=%lu\n",
2892                 fsp->fnum, (double)startpos,
2893                 (unsigned long)maxcount,
2894                 (unsigned long)mincount,
2895                 (unsigned long)nread ) );
2896
2897         send_file_readbraw(conn, fsp, startpos, nread, mincount);
2898
2899         DEBUG(5,("reply_readbraw finished\n"));
2900         END_PROFILE(SMBreadbraw);
2901 }
2902
2903 #undef DBGC_CLASS
2904 #define DBGC_CLASS DBGC_LOCKING
2905
2906 /****************************************************************************
2907  Reply to a lockread (core+ protocol).
2908 ****************************************************************************/
2909
2910 void reply_lockread(struct smb_request *req)
2911 {
2912         connection_struct *conn = req->conn;
2913         ssize_t nread = -1;
2914         char *data;
2915         SMB_OFF_T startpos;
2916         size_t numtoread;
2917         NTSTATUS status;
2918         files_struct *fsp;
2919         struct byte_range_lock *br_lck = NULL;
2920         char *p = NULL;
2921
2922         START_PROFILE(SMBlockread);
2923
2924         if (req->wct < 5) {
2925                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2926                 END_PROFILE(SMBlockread);
2927                 return;
2928         }
2929
2930         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2931
2932         if (!check_fsp(conn, req, fsp)) {
2933                 END_PROFILE(SMBlockread);
2934                 return;
2935         }
2936
2937         if (!CHECK_READ(fsp,req)) {
2938                 reply_doserror(req, ERRDOS, ERRbadaccess);
2939                 END_PROFILE(SMBlockread);
2940                 return;
2941         }
2942
2943         release_level_2_oplocks_on_change(fsp);
2944
2945         numtoread = SVAL(req->vwv+1, 0);
2946         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
2947
2948         numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
2949
2950         reply_outbuf(req, 5, numtoread + 3);
2951
2952         data = smb_buf(req->outbuf) + 3;
2953
2954         /*
2955          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2956          * protocol request that predates the read/write lock concept. 
2957          * Thus instead of asking for a read lock here we need to ask
2958          * for a write lock. JRA.
2959          * Note that the requested lock size is unaffected by max_recv.
2960          */
2961
2962         br_lck = do_lock(smbd_messaging_context(),
2963                         fsp,
2964                         req->smbpid,
2965                         (uint64_t)numtoread,
2966                         (uint64_t)startpos,
2967                         WRITE_LOCK,
2968                         WINDOWS_LOCK,
2969                         False, /* Non-blocking lock. */
2970                         &status,
2971                         NULL);
2972         TALLOC_FREE(br_lck);
2973
2974         if (NT_STATUS_V(status)) {
2975                 reply_nterror(req, status);
2976                 END_PROFILE(SMBlockread);
2977                 return;
2978         }
2979
2980         /*
2981          * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2982          */
2983
2984         if (numtoread > max_recv) {
2985                 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2986 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2987                         (unsigned int)numtoread, (unsigned int)max_recv ));
2988                 numtoread = MIN(numtoread,max_recv);
2989         }
2990         nread = read_file(fsp,data,startpos,numtoread);
2991
2992         if (nread < 0) {
2993                 reply_unixerror(req, ERRDOS, ERRnoaccess);
2994                 END_PROFILE(SMBlockread);
2995                 return;
2996         }
2997
2998         srv_set_message((char *)req->outbuf, 5, nread+3, False);
2999
3000         SSVAL(req->outbuf,smb_vwv0,nread);
3001         SSVAL(req->outbuf,smb_vwv5,nread+3);
3002         p = smb_buf(req->outbuf);
3003         SCVAL(p,0,0); /* pad byte. */
3004         SSVAL(p,1,nread);
3005
3006         DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3007                  fsp->fnum, (int)numtoread, (int)nread));
3008
3009         END_PROFILE(SMBlockread);
3010         return;
3011 }
3012
3013 #undef DBGC_CLASS
3014 #define DBGC_CLASS DBGC_ALL
3015
3016 /****************************************************************************
3017  Reply to a read.
3018 ****************************************************************************/
3019
3020 void reply_read(struct smb_request *req)
3021 {
3022         connection_struct *conn = req->conn;
3023         size_t numtoread;
3024         ssize_t nread = 0;
3025         char *data;
3026         SMB_OFF_T startpos;
3027         int outsize = 0;
3028         files_struct *fsp;
3029
3030         START_PROFILE(SMBread);
3031
3032         if (req->wct < 3) {
3033                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3034                 END_PROFILE(SMBread);
3035                 return;
3036         }
3037
3038         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3039
3040         if (!check_fsp(conn, req, fsp)) {
3041                 END_PROFILE(SMBread);
3042                 return;
3043         }
3044
3045         if (!CHECK_READ(fsp,req)) {
3046                 reply_doserror(req, ERRDOS, ERRbadaccess);
3047                 END_PROFILE(SMBread);
3048                 return;
3049         }
3050
3051         numtoread = SVAL(req->vwv+1, 0);
3052         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3053
3054         numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3055
3056         /*
3057          * The requested read size cannot be greater than max_recv. JRA.
3058          */
3059         if (numtoread > max_recv) {
3060                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3061 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3062                         (unsigned int)numtoread, (unsigned int)max_recv ));
3063                 numtoread = MIN(numtoread,max_recv);
3064         }
3065
3066         reply_outbuf(req, 5, numtoread+3);
3067
3068         data = smb_buf(req->outbuf) + 3;
3069
3070         if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtoread,
3071                       (uint64_t)startpos, READ_LOCK)) {
3072                 reply_doserror(req, ERRDOS,ERRlock);
3073                 END_PROFILE(SMBread);
3074                 return;
3075         }
3076
3077         if (numtoread > 0)
3078                 nread = read_file(fsp,data,startpos,numtoread);
3079
3080         if (nread < 0) {
3081                 reply_unixerror(req, ERRDOS,ERRnoaccess);
3082                 END_PROFILE(SMBread);
3083                 return;
3084         }
3085
3086         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3087
3088         SSVAL(req->outbuf,smb_vwv0,nread);
3089         SSVAL(req->outbuf,smb_vwv5,nread+3);
3090         SCVAL(smb_buf(req->outbuf),0,1);
3091         SSVAL(smb_buf(req->outbuf),1,nread);
3092
3093         DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3094                 fsp->fnum, (int)numtoread, (int)nread ) );
3095
3096         END_PROFILE(SMBread);
3097         return;
3098 }
3099
3100 /****************************************************************************
3101  Setup readX header.
3102 ****************************************************************************/
3103
3104 static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3105 {
3106         int outsize;
3107         char *data;
3108
3109         outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3110         data = smb_buf(outbuf);
3111
3112         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3113
3114         SCVAL(outbuf,smb_vwv0,0xFF);
3115         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3116         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3117         SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
3118         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3119         SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
3120         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3121         _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3122         return outsize;
3123 }
3124
3125 /****************************************************************************
3126  Reply to a read and X - possibly using sendfile.
3127 ****************************************************************************/
3128
3129 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3130                             files_struct *fsp, SMB_OFF_T startpos,
3131                             size_t smb_maxcnt)
3132 {
3133         SMB_STRUCT_STAT sbuf;
3134         ssize_t nread = -1;
3135
3136         if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3137                 reply_unixerror(req, ERRDOS, ERRnoaccess);
3138                 return;
3139         }
3140
3141         if (startpos > sbuf.st_size) {
3142                 smb_maxcnt = 0;
3143         } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3144                 smb_maxcnt = (sbuf.st_size - startpos);
3145         }
3146
3147         if (smb_maxcnt == 0) {
3148                 goto normal_read;
3149         }
3150
3151 #if defined(WITH_SENDFILE)
3152         /*
3153          * We can only use sendfile on a non-chained packet
3154          * but we can use on a non-oplocked file. tridge proved this
3155          * on a train in Germany :-). JRA.
3156          */
3157
3158         if ((chain_size == 0) && (CVAL(req->vwv+0, 0) == 0xFF) &&
3159             !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3160             lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3161                 uint8 headerbuf[smb_size + 12 * 2];
3162                 DATA_BLOB header;
3163
3164                 /*
3165                  * Set up the packet header before send. We
3166                  * assume here the sendfile will work (get the
3167                  * correct amount of data).
3168                  */
3169
3170                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3171
3172                 construct_reply_common_req(req, (char *)headerbuf);
3173                 setup_readX_header((char *)headerbuf, smb_maxcnt);
3174
3175                 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3176                         /* Returning ENOSYS or EINVAL means no data at all was sent. 
3177                            Do this as a normal read. */
3178                         if (errno == ENOSYS || errno == EINVAL) {
3179                                 goto normal_read;
3180                         }
3181
3182                         /*
3183                          * Special hack for broken Linux with no working sendfile. If we
3184                          * return EINTR we sent the header but not the rest of the data.
3185                          * Fake this up by doing read/write calls.
3186                          */
3187
3188                         if (errno == EINTR) {
3189                                 /* Ensure we don't do this again. */
3190                                 set_use_sendfile(SNUM(conn), False);
3191                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3192                                 nread = fake_sendfile(fsp, startpos,
3193                                                       smb_maxcnt);
3194                                 if (nread == -1) {
3195                                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3196                                                 fsp->fsp_name, strerror(errno) ));
3197                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3198                                 }
3199                                 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3200                                         fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3201                                 /* No outbuf here means successful sendfile. */
3202                                 TALLOC_FREE(req->outbuf);
3203                                 return;
3204                         }
3205
3206                         DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3207                                 fsp->fsp_name, strerror(errno) ));
3208                         exit_server_cleanly("send_file_readX sendfile failed");
3209                 }
3210
3211                 DEBUG( 3, ( "send_file_readX: 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 #endif
3218
3219 normal_read:
3220
3221         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3222                 uint8 headerbuf[smb_size + 2*12];
3223
3224                 construct_reply_common_req(req, (char *)headerbuf);
3225                 setup_readX_header((char *)headerbuf, smb_maxcnt);
3226
3227                 /* Send out the header. */
3228                 if (write_data(smbd_server_fd(), (char *)headerbuf,
3229                                sizeof(headerbuf)) != sizeof(headerbuf)) {
3230                         DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3231                                 fsp->fsp_name, strerror(errno) ));
3232                         exit_server_cleanly("send_file_readX sendfile failed");
3233                 }
3234                 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3235                 if (nread == -1) {
3236                         DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3237                                 fsp->fsp_name, strerror(errno) ));
3238                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3239                 }
3240                 TALLOC_FREE(req->outbuf);
3241                 return;
3242         }
3243
3244         reply_outbuf(req, 12, smb_maxcnt);
3245
3246         nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3247         if (nread < 0) {
3248                 reply_unixerror(req, ERRDOS, ERRnoaccess);
3249                 return;
3250         }
3251
3252         setup_readX_header((char *)req->outbuf, nread);
3253
3254         DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3255                     fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3256
3257         chain_reply(req);
3258 }
3259
3260 /****************************************************************************
3261  Reply to a read and X.
3262 ****************************************************************************/
3263
3264 void reply_read_and_X(struct smb_request *req)
3265 {
3266         connection_struct *conn = req->conn;
3267         files_struct *fsp;
3268         SMB_OFF_T startpos;
3269         size_t smb_maxcnt;
3270         bool big_readX = False;
3271 #if 0
3272         size_t smb_mincnt = SVAL(req->vwv+6, 0);
3273 #endif
3274
3275         START_PROFILE(SMBreadX);
3276
3277         if ((req->wct != 10) && (req->wct != 12)) {
3278                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3279                 return;
3280         }
3281
3282         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3283         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3284         smb_maxcnt = SVAL(req->vwv+5, 0);
3285
3286         /* If it's an IPC, pass off the pipe handler. */
3287         if (IS_IPC(conn)) {
3288                 reply_pipe_read_and_X(req);
3289                 END_PROFILE(SMBreadX);
3290                 return;
3291         }
3292
3293         if (!check_fsp(conn, req, fsp)) {
3294                 END_PROFILE(SMBreadX);
3295                 return;
3296         }
3297
3298         if (!CHECK_READ(fsp,req)) {
3299                 reply_doserror(req, ERRDOS,ERRbadaccess);
3300                 END_PROFILE(SMBreadX);
3301                 return;
3302         }
3303
3304         if (global_client_caps & CAP_LARGE_READX) {
3305                 size_t upper_size = SVAL(req->vwv+7, 0);
3306                 smb_maxcnt |= (upper_size<<16);
3307                 if (upper_size > 1) {
3308                         /* Can't do this on a chained packet. */
3309                         if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3310                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3311                                 END_PROFILE(SMBreadX);
3312                                 return;
3313                         }
3314                         /* We currently don't do this on signed or sealed data. */
3315                         if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3316                                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3317                                 END_PROFILE(SMBreadX);
3318                                 return;
3319                         }
3320                         /* Is there room in the reply for this data ? */
3321                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
3322                                 reply_nterror(req,
3323                                               NT_STATUS_INVALID_PARAMETER);
3324                                 END_PROFILE(SMBreadX);
3325                                 return;
3326                         }
3327                         big_readX = True;
3328                 }
3329         }
3330
3331         if (req->wct == 12) {
3332 #ifdef LARGE_SMB_OFF_T
3333                 /*
3334                  * This is a large offset (64 bit) read.
3335                  */
3336                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3337
3338 #else /* !LARGE_SMB_OFF_T */
3339
3340                 /*
3341                  * Ensure we haven't been sent a >32 bit offset.
3342                  */
3343
3344                 if(IVAL(req->vwv+10, 0) != 0) {
3345                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3346                                  "used and we don't support 64 bit offsets.\n",
3347                                  (unsigned int)IVAL(req->vwv+10, 0) ));
3348                         END_PROFILE(SMBreadX);
3349                         reply_doserror(req, ERRDOS, ERRbadaccess);
3350                         return;
3351                 }
3352
3353 #endif /* LARGE_SMB_OFF_T */
3354
3355         }
3356
3357         if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)smb_maxcnt,
3358                       (uint64_t)startpos, READ_LOCK)) {
3359                 END_PROFILE(SMBreadX);
3360                 reply_doserror(req, ERRDOS, ERRlock);
3361                 return;
3362         }
3363
3364         if (!big_readX &&
3365             schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3366                 END_PROFILE(SMBreadX);
3367                 return;
3368         }
3369
3370         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3371
3372         END_PROFILE(SMBreadX);
3373         return;
3374 }
3375
3376 /****************************************************************************
3377  Error replies to writebraw must have smb_wct == 1. Fix this up.
3378 ****************************************************************************/
3379
3380 void error_to_writebrawerr(struct smb_request *req)
3381 {
3382         uint8 *old_outbuf = req->outbuf;
3383
3384         reply_outbuf(req, 1, 0);
3385
3386         memcpy(req->outbuf, old_outbuf, smb_size);
3387         TALLOC_FREE(old_outbuf);
3388 }
3389
3390 /****************************************************************************
3391  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3392 ****************************************************************************/
3393
3394 void reply_writebraw(struct smb_request *req)
3395 {
3396         connection_struct *conn = req->conn;
3397         char *buf = NULL;
3398         ssize_t nwritten=0;
3399         ssize_t total_written=0;
3400         size_t numtowrite=0;
3401         size_t tcount;
3402         SMB_OFF_T startpos;
3403         char *data=NULL;
3404         bool write_through;
3405         files_struct *fsp;
3406         NTSTATUS status;
3407
3408         START_PROFILE(SMBwritebraw);
3409
3410         /*
3411          * If we ever reply with an error, it must have the SMB command
3412          * type of SMBwritec, not SMBwriteBraw, as this tells the client
3413          * we're finished.
3414          */
3415         SCVAL(req->inbuf,smb_com,SMBwritec);
3416
3417         if (srv_is_signing_active()) {
3418                 END_PROFILE(SMBwritebraw);
3419                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3420                                 "raw reads/writes are disallowed.");
3421         }
3422
3423         if (req->wct < 12) {
3424                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3425                 error_to_writebrawerr(req);
3426                 END_PROFILE(SMBwritebraw);
3427                 return;
3428         }
3429
3430         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3431         if (!check_fsp(conn, req, fsp)) {
3432                 error_to_writebrawerr(req);
3433                 END_PROFILE(SMBwritebraw);
3434                 return;
3435         }
3436
3437         if (!CHECK_WRITE(fsp)) {
3438                 reply_doserror(req, ERRDOS, ERRbadaccess);
3439                 error_to_writebrawerr(req);
3440                 END_PROFILE(SMBwritebraw);
3441                 return;
3442         }
3443
3444         tcount = IVAL(req->vwv+1, 0);
3445         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3446         write_through = BITSETW(req->vwv+7,0);
3447
3448         /* We have to deal with slightly different formats depending
3449                 on whether we are using the core+ or lanman1.0 protocol */
3450
3451         if(Protocol <= PROTOCOL_COREPLUS) {
3452                 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3453                 data = smb_buf(req->inbuf);
3454         } else {
3455                 numtowrite = SVAL(req->vwv+10, 0);
3456                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3457         }
3458
3459         /* Ensure we don't write bytes past the end of this packet. */
3460         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3461                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3462                 error_to_writebrawerr(req);
3463                 END_PROFILE(SMBwritebraw);
3464                 return;
3465         }
3466
3467         if (is_locked(fsp,(uint32)req->smbpid,(uint64_t)tcount,
3468                                 (uint64_t)startpos, WRITE_LOCK)) {
3469                 reply_doserror(req, ERRDOS, ERRlock);
3470                 error_to_writebrawerr(req);
3471                 END_PROFILE(SMBwritebraw);
3472                 return;
3473         }
3474
3475         if (numtowrite>0) {
3476                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3477         }
3478
3479         DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3480                         "wrote=%d sync=%d\n",
3481                 fsp->fnum, (double)startpos, (int)numtowrite,
3482                 (int)nwritten, (int)write_through));
3483
3484         if (nwritten < (ssize_t)numtowrite)  {
3485                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3486                 error_to_writebrawerr(req);
3487                 END_PROFILE(SMBwritebraw);
3488                 return;
3489         }
3490
3491         total_written = nwritten;
3492
3493         /* Allocate a buffer of 64k + length. */
3494         buf = TALLOC_ARRAY(NULL, char, 65540);
3495         if (!buf) {
3496                 reply_doserror(req, ERRDOS, ERRnomem);
3497                 error_to_writebrawerr(req);
3498                 END_PROFILE(SMBwritebraw);
3499                 return;
3500         }
3501
3502         /* Return a SMBwritebraw message to the redirector to tell
3503          * it to send more bytes */
3504
3505         memcpy(buf, req->inbuf, smb_size);
3506         srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3507         SCVAL(buf,smb_com,SMBwritebraw);
3508         SSVALS(buf,smb_vwv0,0xFFFF);
3509         show_msg(buf);
3510         if (!srv_send_smb(smbd_server_fd(),
3511                         buf,
3512                         IS_CONN_ENCRYPTED(conn))) {
3513                 exit_server_cleanly("reply_writebraw: srv_send_smb "
3514                         "failed.");
3515         }
3516
3517         /* Now read the raw data into the buffer and write it */
3518         status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3519                                  &numtowrite);
3520         if (!NT_STATUS_IS_OK(status)) {
3521                 exit_server_cleanly("secondary writebraw failed");
3522         }
3523
3524         /* Set up outbuf to return the correct size */
3525         reply_outbuf(req, 1, 0);
3526
3527         if (numtowrite != 0) {
3528
3529                 if (numtowrite > 0xFFFF) {
3530                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3531                                 "raw requested (%u). Terminating\n",
3532                                 (unsigned int)numtowrite ));
3533                         exit_server_cleanly("secondary writebraw failed");
3534                 }
3535
3536                 if (tcount > nwritten+numtowrite) {
3537                         DEBUG(3,("reply_writebraw: Client overestimated the "
3538                                 "write %d %d %d\n",
3539                                 (int)tcount,(int)nwritten,(int)numtowrite));
3540                 }
3541
3542                 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3543
3544                 if (!NT_STATUS_IS_OK(status)) {
3545                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3546                                  "raw read failed (%s). Terminating\n",
3547                                  nt_errstr(status)));
3548                         exit_server_cleanly("secondary writebraw failed");
3549                 }
3550
3551                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3552                 if (nwritten == -1) {
3553                         TALLOC_FREE(buf);
3554                         reply_unixerror(req, ERRHRD, ERRdiskfull);
3555                         error_to_writebrawerr(req);
3556                         END_PROFILE(SMBwritebraw);
3557                         return;
3558                 }
3559
3560                 if (nwritten < (ssize_t)numtowrite) {
3561                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
3562                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
3563                 }
3564
3565                 if (nwritten > 0) {
3566                         total_written += nwritten;
3567                 }
3568         }
3569
3570         TALLOC_FREE(buf);
3571         SSVAL(req->outbuf,smb_vwv0,total_written);
3572
3573         status = sync_file(conn, fsp, write_through);
3574         if (!NT_STATUS_IS_OK(status)) {
3575                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3576                         fsp->fsp_name, nt_errstr(status) ));
3577                 reply_nterror(req, status);
3578                 error_to_writebrawerr(req);
3579                 END_PROFILE(SMBwritebraw);
3580                 return;
3581         }
3582
3583         DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3584                 "wrote=%d\n",
3585                 fsp->fnum, (double)startpos, (int)numtowrite,
3586                 (int)total_written));
3587
3588         /* We won't return a status if write through is not selected - this
3589          * follows what WfWg does */
3590         END_PROFILE(SMBwritebraw);
3591
3592         if (!write_through && total_written==tcount) {
3593
3594 #if RABBIT_PELLET_FIX
3595                 /*
3596                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3597                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3598                  * JRA.
3599                  */
3600                 if (!send_keepalive(smbd_server_fd())) {
3601                         exit_server_cleanly("reply_writebraw: send of "
3602                                 "keepalive failed");
3603                 }
3604 #endif
3605                 TALLOC_FREE(req->outbuf);
3606         }
3607         return;
3608 }
3609
3610 #undef DBGC_CLASS
3611 #define DBGC_CLASS DBGC_LOCKING
3612
3613 /****************************************************************************
3614  Reply to a writeunlock (core+).
3615 ****************************************************************************/
3616
3617 void reply_writeunlock(struct smb_request *req)
3618 {
3619         connection_struct *conn = req->conn;
3620         ssize_t nwritten = -1;
3621         size_t numtowrite;
3622         SMB_OFF_T startpos;
3623         const char *data;
3624         NTSTATUS status = NT_STATUS_OK;
3625         files_struct *fsp;
3626
3627         START_PROFILE(SMBwriteunlock);
3628
3629         if (req->wct < 5) {
3630                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3631                 END_PROFILE(SMBwriteunlock);
3632                 return;
3633         }
3634
3635         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3636
3637         if (!check_fsp(conn, req, fsp)) {
3638                 END_PROFILE(SMBwriteunlock);
3639                 return;
3640         }
3641
3642         if (!CHECK_WRITE(fsp)) {
3643                 reply_doserror(req, ERRDOS,ERRbadaccess);
3644                 END_PROFILE(SMBwriteunlock);
3645                 return;
3646         }
3647
3648         numtowrite = SVAL(req->vwv+1, 0);
3649         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3650         data = (const char *)req->buf + 3;
3651
3652         if (numtowrite
3653             && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
3654                          (uint64_t)startpos, WRITE_LOCK)) {
3655                 reply_doserror(req, ERRDOS, ERRlock);
3656                 END_PROFILE(SMBwriteunlock);
3657                 return;
3658         }
3659
3660         /* The special X/Open SMB protocol handling of
3661            zero length writes is *NOT* done for
3662            this call */
3663         if(numtowrite == 0) {
3664                 nwritten = 0;
3665         } else {
3666                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3667         }
3668
3669         status = sync_file(conn, fsp, False /* write through */);
3670         if (!NT_STATUS_IS_OK(status)) {
3671                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3672                         fsp->fsp_name, nt_errstr(status) ));
3673                 reply_nterror(req, status);
3674                 END_PROFILE(SMBwriteunlock);
3675                 return;
3676         }
3677
3678         if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3679                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3680                 END_PROFILE(SMBwriteunlock);
3681                 return;
3682         }
3683
3684         if (numtowrite) {
3685                 status = do_unlock(smbd_messaging_context(),
3686                                 fsp,
3687                                 req->smbpid,
3688                                 (uint64_t)numtowrite, 
3689                                 (uint64_t)startpos,
3690                                 WINDOWS_LOCK);
3691
3692                 if (NT_STATUS_V(status)) {
3693                         reply_nterror(req, status);
3694                         END_PROFILE(SMBwriteunlock);
3695                         return;
3696                 }
3697         }
3698
3699         reply_outbuf(req, 1, 0);
3700
3701         SSVAL(req->outbuf,smb_vwv0,nwritten);
3702
3703         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3704                  fsp->fnum, (int)numtowrite, (int)nwritten));
3705
3706         END_PROFILE(SMBwriteunlock);
3707         return;
3708 }
3709
3710 #undef DBGC_CLASS
3711 #define DBGC_CLASS DBGC_ALL
3712
3713 /****************************************************************************
3714  Reply to a write.
3715 ****************************************************************************/
3716
3717 void reply_write(struct smb_request *req)
3718 {
3719         connection_struct *conn = req->conn;
3720         size_t numtowrite;
3721         ssize_t nwritten = -1;
3722         SMB_OFF_T startpos;
3723         const char *data;
3724         files_struct *fsp;
3725         NTSTATUS status;
3726
3727         START_PROFILE(SMBwrite);
3728
3729         if (req->wct < 5) {
3730                 END_PROFILE(SMBwrite);
3731                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3732                 return;
3733         }
3734
3735         /* If it's an IPC, pass off the pipe handler. */
3736         if (IS_IPC(conn)) {
3737                 reply_pipe_write(req);
3738                 END_PROFILE(SMBwrite);
3739                 return;
3740         }
3741
3742         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3743
3744         if (!check_fsp(conn, req, fsp)) {
3745                 END_PROFILE(SMBwrite);
3746                 return;
3747         }
3748
3749         if (!CHECK_WRITE(fsp)) {
3750                 reply_doserror(req, ERRDOS, ERRbadaccess);
3751                 END_PROFILE(SMBwrite);
3752                 return;
3753         }
3754
3755         numtowrite = SVAL(req->vwv+1, 0);
3756         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3757         data = (const char *)req->buf + 3;
3758
3759         if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
3760                       (uint64_t)startpos, WRITE_LOCK)) {
3761                 reply_doserror(req, ERRDOS, ERRlock);
3762                 END_PROFILE(SMBwrite);
3763                 return;
3764         }
3765
3766         /*
3767          * X/Open SMB protocol says that if smb_vwv1 is
3768          * zero then the file size should be extended or
3769          * truncated to the size given in smb_vwv[2-3].
3770          */
3771
3772         if(numtowrite == 0) {
3773                 /*
3774                  * This is actually an allocate call, and set EOF. JRA.
3775                  */
3776                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3777                 if (nwritten < 0) {
3778                         reply_nterror(req, NT_STATUS_DISK_FULL);
3779                         END_PROFILE(SMBwrite);
3780                         return;
3781                 }
3782                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3783                 if (nwritten < 0) {
3784                         reply_nterror(req, NT_STATUS_DISK_FULL);
3785                         END_PROFILE(SMBwrite);
3786                         return;
3787                 }
3788                 trigger_write_time_update_immediate(fsp);
3789         } else {
3790                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3791         }
3792
3793         status = sync_file(conn, fsp, False);
3794         if (!NT_STATUS_IS_OK(status)) {
3795                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3796                         fsp->fsp_name, nt_errstr(status) ));
3797                 reply_nterror(req, status);
3798                 END_PROFILE(SMBwrite);
3799                 return;
3800         }
3801
3802         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3803                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3804                 END_PROFILE(SMBwrite);
3805                 return;
3806         }
3807
3808         reply_outbuf(req, 1, 0);
3809
3810         SSVAL(req->outbuf,smb_vwv0,nwritten);
3811
3812         if (nwritten < (ssize_t)numtowrite) {
3813                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3814                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3815         }
3816
3817         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3818
3819         END_PROFILE(SMBwrite);
3820         return;
3821 }
3822
3823 /****************************************************************************
3824  Ensure a buffer is a valid writeX for recvfile purposes.
3825 ****************************************************************************/
3826
3827 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3828                                                 (2*14) + /* word count (including bcc) */ \
3829                                                 1 /* pad byte */)
3830
3831 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3832 {
3833         size_t numtowrite;
3834         connection_struct *conn = NULL;
3835         unsigned int doff = 0;
3836         size_t len = smb_len_large(inbuf);
3837
3838         if (is_encrypted_packet(inbuf)) {
3839                 /* Can't do this on encrypted
3840                  * connections. */
3841                 return false;
3842         }
3843
3844         if (CVAL(inbuf,smb_com) != SMBwriteX) {
3845                 return false;
3846         }
3847
3848         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3849                         CVAL(inbuf,smb_wct) != 14) {
3850                 DEBUG(10,("is_valid_writeX_buffer: chained or "
3851                         "invalid word length.\n"));
3852                 return false;
3853         }
3854
3855         conn = conn_find(SVAL(inbuf, smb_tid));
3856         if (conn == NULL) {
3857                 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3858                 return false;
3859         }
3860         if (IS_IPC(conn)) {
3861                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3862                 return false;
3863         }
3864         doff = SVAL(inbuf,smb_vwv11);
3865
3866         numtowrite = SVAL(inbuf,smb_vwv10);
3867
3868         if (len > doff && len - doff > 0xFFFF) {
3869                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3870         }
3871
3872         if (numtowrite == 0) {
3873                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3874                 return false;
3875         }
3876
3877         /* Ensure the sizes match up. */
3878         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3879                 /* no pad byte...old smbclient :-( */
3880                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3881                         (unsigned int)doff,
3882                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
3883                 return false;
3884         }
3885
3886         if (len - doff != numtowrite) {
3887                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3888                         "len = %u, doff = %u, numtowrite = %u\n",
3889                         (unsigned int)len,
3890                         (unsigned int)doff,
3891                         (unsigned int)numtowrite ));
3892                 return false;
3893         }
3894
3895         DEBUG(10,("is_valid_writeX_buffer: true "
3896                 "len = %u, doff = %u, numtowrite = %u\n",
3897                 (unsigned int)len,
3898                 (unsigned int)doff,
3899                 (unsigned int)numtowrite ));
3900
3901         return true;
3902 }
3903
3904 /****************************************************************************
3905  Reply to a write and X.
3906 ****************************************************************************/
3907
3908 void reply_write_and_X(struct smb_request *req)
3909 {
3910         connection_struct *conn = req->conn;
3911         files_struct *fsp;
3912         SMB_OFF_T startpos;
3913         size_t numtowrite;
3914         bool write_through;
3915         ssize_t nwritten;
3916         unsigned int smb_doff;
3917         unsigned int smblen;
3918         char *data;
3919         NTSTATUS status;
3920
3921         START_PROFILE(SMBwriteX);
3922
3923         if ((req->wct != 12) && (req->wct != 14)) {
3924                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3925                 END_PROFILE(SMBwriteX);
3926                 return;
3927         }
3928
3929         numtowrite = SVAL(req->vwv+10, 0);
3930         smb_doff = SVAL(req->vwv+11, 0);
3931         smblen = smb_len(req->inbuf);
3932
3933         if (req->unread_bytes > 0xFFFF ||
3934                         (smblen > smb_doff &&
3935                                 smblen - smb_doff > 0xFFFF)) {
3936                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
3937         }
3938
3939         if (req->unread_bytes) {
3940                 /* Can't do a recvfile write on IPC$ */
3941                 if (IS_IPC(conn)) {
3942                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3943                         END_PROFILE(SMBwriteX);
3944                         return;
3945                 }
3946                 if (numtowrite != req->unread_bytes) {
3947                         reply_doserror(req, ERRDOS, ERRbadmem);
3948                         END_PROFILE(SMBwriteX);
3949                         return;
3950                 }
3951         } else {
3952                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
3953                                 smb_doff + numtowrite > smblen) {
3954                         reply_doserror(req, ERRDOS, ERRbadmem);
3955                         END_PROFILE(SMBwriteX);
3956                         return;
3957                 }
3958         }
3959
3960         /* If it's an IPC, pass off the pipe handler. */
3961         if (IS_IPC(conn)) {
3962                 if (req->unread_bytes) {
3963                         reply_doserror(req, ERRDOS, ERRbadmem);
3964                         END_PROFILE(SMBwriteX);
3965                         return;
3966                 }
3967                 reply_pipe_write_and_X(req);
3968                 END_PROFILE(SMBwriteX);
3969                 return;
3970         }
3971
3972         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3973         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3974         write_through = BITSETW(req->vwv+7,0);
3975
3976         if (!check_fsp(conn, req, fsp)) {
3977                 END_PROFILE(SMBwriteX);
3978                 return;
3979         }
3980
3981         if (!CHECK_WRITE(fsp)) {
3982                 reply_doserror(req, ERRDOS, ERRbadaccess);
3983                 END_PROFILE(SMBwriteX);
3984                 return;
3985         }
3986
3987         data = smb_base(req->inbuf) + smb_doff;
3988
3989         if(req->wct == 14) {
3990 #ifdef LARGE_SMB_OFF_T
3991                 /*
3992                  * This is a large offset (64 bit) write.
3993                  */
3994                 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
3995
3996 #else /* !LARGE_SMB_OFF_T */
3997
3998                 /*
3999                  * Ensure we haven't been sent a >32 bit offset.
4000                  */
4001
4002                 if(IVAL(req->vwv+12, 0) != 0) {
4003                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4004                                  "used and we don't support 64 bit offsets.\n",
4005                                  (unsigned int)IVAL(req->vwv+12, 0) ));
4006                         reply_doserror(req, ERRDOS, ERRbadaccess);
4007                         END_PROFILE(SMBwriteX);
4008                         return;
4009                 }
4010
4011 #endif /* LARGE_SMB_OFF_T */
4012         }
4013
4014         if (is_locked(fsp,(uint32)req->smbpid,
4015                       (uint64_t)numtowrite,
4016                       (uint64_t)startpos, WRITE_LOCK)) {
4017                 reply_doserror(req, ERRDOS, ERRlock);
4018                 END_PROFILE(SMBwriteX);
4019                 return;
4020         }
4021
4022         /* X/Open SMB protocol says that, unlike SMBwrite
4023         if the length is zero then NO truncation is
4024         done, just a write of zero. To truncate a file,
4025         use SMBwrite. */
4026
4027         if(numtowrite == 0) {
4028                 nwritten = 0;
4029         } else {
4030
4031                 if ((req->unread_bytes == 0) &&
4032                     schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4033                                              numtowrite)) {
4034                         END_PROFILE(SMBwriteX);
4035                         return;
4036                 }
4037
4038                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4039         }
4040
4041         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4042                 reply_unixerror(req, ERRHRD, ERRdiskfull);
4043                 END_PROFILE(SMBwriteX);
4044                 return;
4045         }
4046
4047         reply_outbuf(req, 6, 0);
4048         SSVAL(req->outbuf,smb_vwv2,nwritten);
4049         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4050
4051         if (nwritten < (ssize_t)numtowrite) {
4052                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4053                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4054         }
4055
4056         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4057                 fsp->fnum, (int)numtowrite, (int)nwritten));
4058
4059         status = sync_file(conn, fsp, write_through);
4060         if (!NT_STATUS_IS_OK(status)) {
4061                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4062                         fsp->fsp_name, nt_errstr(status) ));
4063                 reply_nterror(req, status);
4064                 END_PROFILE(SMBwriteX);
4065                 return;
4066         }
4067
4068         END_PROFILE(SMBwriteX);
4069         chain_reply(req);
4070         return;
4071 }
4072
4073 /****************************************************************************
4074  Reply to a lseek.
4075 ****************************************************************************/
4076
4077 void reply_lseek(struct smb_request *req)
4078 {
4079         connection_struct *conn = req->conn;
4080         SMB_OFF_T startpos;
4081         SMB_OFF_T res= -1;
4082         int mode,umode;
4083         files_struct *fsp;
4084
4085         START_PROFILE(SMBlseek);
4086
4087         if (req->wct < 4) {
4088                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4089                 END_PROFILE(SMBlseek);
4090                 return;
4091         }
4092
4093         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4094
4095         if (!check_fsp(conn, req, fsp)) {
4096                 return;
4097         }
4098
4099         flush_write_cache(fsp, SEEK_FLUSH);
4100
4101         mode = SVAL(req->vwv+1, 0) & 3;
4102         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4103         startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4104
4105         switch (mode) {
4106                 case 0:
4107                         umode = SEEK_SET;
4108                         res = startpos;
4109                         break;
4110                 case 1:
4111                         umode = SEEK_CUR;
4112                         res = fsp->fh->pos + startpos;
4113                         break;
4114                 case 2:
4115                         umode = SEEK_END;
4116                         break;
4117                 default:
4118                         umode = SEEK_SET;
4119                         res = startpos;
4120                         break;
4121         }
4122
4123         if (umode == SEEK_END) {
4124                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4125                         if(errno == EINVAL) {
4126                                 SMB_OFF_T current_pos = startpos;
4127                                 SMB_STRUCT_STAT sbuf;
4128
4129                                 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4130                                         reply_unixerror(req, ERRDOS,
4131                                                         ERRnoaccess);
4132                                         END_PROFILE(SMBlseek);
4133                                         return;
4134                                 }
4135
4136                                 current_pos += sbuf.st_size;
4137                                 if(current_pos < 0)
4138                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4139                         }
4140                 }
4141
4142                 if(res == -1) {
4143                         reply_unixerror(req, ERRDOS, ERRnoaccess);
4144                         END_PROFILE(SMBlseek);
4145                         return;
4146                 }
4147         }
4148
4149         fsp->fh->pos = res;
4150
4151         reply_outbuf(req, 2, 0);
4152         SIVAL(req->outbuf,smb_vwv0,res);
4153
4154         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4155                 fsp->fnum, (double)startpos, (double)res, mode));
4156
4157         END_PROFILE(SMBlseek);
4158         return;
4159 }
4160
4161 /****************************************************************************
4162  Reply to a flush.
4163 ****************************************************************************/
4164
4165 void reply_flush(struct smb_request *req)
4166 {
4167         connection_struct *conn = req->conn;
4168         uint16 fnum;
4169         files_struct *fsp;
4170
4171         START_PROFILE(SMBflush);
4172
4173         if (req->wct < 1) {
4174                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4175                 return;
4176         }
4177
4178         fnum = SVAL(req->vwv+0, 0);
4179         fsp = file_fsp(req, fnum);
4180
4181         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4182                 return;
4183         }
4184
4185         if (!fsp) {
4186                 file_sync_all(conn);
4187         } else {
4188                 NTSTATUS status = sync_file(conn, fsp, True);
4189                 if (!NT_STATUS_IS_OK(status)) {
4190                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4191                                 fsp->fsp_name, nt_errstr(status) ));
4192                         reply_nterror(req, status);
4193                         END_PROFILE(SMBflush);
4194                         return;
4195                 }
4196         }
4197
4198         reply_outbuf(req, 0, 0);
4199
4200         DEBUG(3,("flush\n"));
4201         END_PROFILE(SMBflush);
4202         return;
4203 }
4204
4205 /****************************************************************************
4206  Reply to a exit.
4207  conn POINTER CAN BE NULL HERE !
4208 ****************************************************************************/
4209
4210 void reply_exit(struct smb_request *req)
4211 {
4212         START_PROFILE(SMBexit);
4213
4214         file_close_pid(req->smbpid, req->vuid);
4215
4216         reply_outbuf(req, 0, 0);
4217
4218         DEBUG(3,("exit\n"));
4219
4220         END_PROFILE(SMBexit);
4221         return;
4222 }
4223
4224 /****************************************************************************
4225  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4226 ****************************************************************************/
4227
4228 void reply_close(struct smb_request *req)
4229 {
4230         connection_struct *conn = req->conn;
4231         NTSTATUS status = NT_STATUS_OK;
4232         files_struct *fsp = NULL;
4233         START_PROFILE(SMBclose);
4234
4235         if (req->wct < 3) {
4236                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4237                 END_PROFILE(SMBclose);
4238                 return;
4239         }
4240
4241         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4242
4243         /*
4244          * We can only use check_fsp if we know it's not a directory.
4245          */
4246
4247         if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4248                 reply_doserror(req, ERRDOS, ERRbadfid);
4249                 END_PROFILE(SMBclose);
4250                 return;
4251         }
4252
4253         if(fsp->is_directory) {
4254                 /*
4255                  * Special case - close NT SMB directory handle.
4256                  */
4257                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4258                 status = close_file(req, fsp, NORMAL_CLOSE);
4259         } else {
4260                 time_t t;
4261                 /*
4262                  * Close ordinary file.
4263                  */
4264
4265                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4266                          fsp->fh->fd, fsp->fnum,
4267                          conn->num_files_open));
4268
4269                 /*
4270                  * Take care of any time sent in the close.
4271                  */
4272
4273                 t = srv_make_unix_date3(req->vwv+1);
4274                 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4275
4276                 /*
4277                  * close_file() returns the unix errno if an error
4278                  * was detected on close - normally this is due to
4279                  * a disk full error. If not then it was probably an I/O error.
4280                  */
4281
4282                 status = close_file(req, fsp, NORMAL_CLOSE);
4283         }  
4284
4285         if (!NT_STATUS_IS_OK(status)) {
4286                 reply_nterror(req, status);
4287                 END_PROFILE(SMBclose);
4288                 return;
4289         }
4290
4291         reply_outbuf(req, 0, 0);
4292         END_PROFILE(SMBclose);
4293         return;
4294 }
4295
4296 /****************************************************************************
4297  Reply to a writeclose (Core+ protocol).
4298 ****************************************************************************/
4299
4300 void reply_writeclose(struct smb_request *req)
4301 {
4302         connection_struct *conn = req->conn;
4303         size_t numtowrite;
4304         ssize_t nwritten = -1;
4305         NTSTATUS close_status = NT_STATUS_OK;
4306         SMB_OFF_T startpos;
4307         const char *data;
4308         struct timespec mtime;
4309         files_struct *fsp;
4310
4311         START_PROFILE(SMBwriteclose);
4312
4313         if (req->wct < 6) {
4314                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4315                 END_PROFILE(SMBwriteclose);
4316                 return;
4317         }
4318
4319         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4320
4321         if (!check_fsp(conn, req, fsp)) {
4322                 END_PROFILE(SMBwriteclose);
4323                 return;
4324         }
4325         if (!CHECK_WRITE(fsp)) {
4326                 reply_doserror(req, ERRDOS,ERRbadaccess);
4327                 END_PROFILE(SMBwriteclose);
4328                 return;
4329         }
4330
4331         numtowrite = SVAL(req->vwv+1, 0);
4332         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4333         mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4334         data = (const char *)req->buf + 1;
4335
4336         if (numtowrite
4337             && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
4338                          (uint64_t)startpos, WRITE_LOCK)) {
4339                 reply_doserror(req, ERRDOS,ERRlock);
4340                 END_PROFILE(SMBwriteclose);
4341                 return;
4342         }
4343
4344         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4345
4346         set_close_write_time(fsp, mtime);
4347
4348         /*
4349          * More insanity. W2K only closes the file if writelen > 0.
4350          * JRA.
4351          */
4352
4353         if (numtowrite) {
4354                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4355                         fsp->fsp_name ));
4356                 close_status = close_file(req, fsp, NORMAL_CLOSE);
4357         }
4358
4359         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4360                  fsp->fnum, (int)numtowrite, (int)nwritten,
4361                  conn->num_files_open));
4362
4363         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4364                 reply_doserror(req, ERRHRD, ERRdiskfull);
4365                 END_PROFILE(SMBwriteclose);
4366                 return;
4367         }
4368
4369         if(!NT_STATUS_IS_OK(close_status)) {
4370                 reply_nterror(req, close_status);
4371                 END_PROFILE(SMBwriteclose);
4372                 return;
4373         }
4374
4375         reply_outbuf(req, 1, 0);
4376
4377         SSVAL(req->outbuf,smb_vwv0,nwritten);
4378         END_PROFILE(SMBwriteclose);
4379         return;
4380 }
4381
4382 #undef DBGC_CLASS
4383 #define DBGC_CLASS DBGC_LOCKING
4384
4385 /****************************************************************************
4386  Reply to a lock.
4387 ****************************************************************************/
4388
4389 void reply_lock(struct smb_request *req)
4390 {
4391         connection_struct *conn = req->conn;
4392         uint64_t count,offset;
4393         NTSTATUS status;
4394         files_struct *fsp;
4395         struct byte_range_lock *br_lck = NULL;
4396
4397         START_PROFILE(SMBlock);
4398
4399         if (req->wct < 5) {
4400                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4401                 END_PROFILE(SMBlock);
4402                 return;
4403         }
4404
4405         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4406
4407         if (!check_fsp(conn, req, fsp)) {
4408                 END_PROFILE(SMBlock);
4409                 return;
4410         }
4411
4412         release_level_2_oplocks_on_change(fsp);
4413
4414         count = (uint64_t)IVAL(req->vwv+1, 0);
4415         offset = (uint64_t)IVAL(req->vwv+3, 0);
4416
4417         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4418                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4419
4420         br_lck = do_lock(smbd_messaging_context(),
4421                         fsp,
4422                         req->smbpid,
4423                         count,
4424                         offset,
4425                         WRITE_LOCK,
4426                         WINDOWS_LOCK,
4427                         False, /* Non-blocking lock. */
4428                         &status,
4429                         NULL);
4430
4431         TALLOC_FREE(br_lck);
4432
4433         if (NT_STATUS_V(status)) {
4434                 reply_nterror(req, status);
4435                 END_PROFILE(SMBlock);
4436                 return;
4437         }
4438
4439         reply_outbuf(req, 0, 0);
4440
4441         END_PROFILE(SMBlock);
4442         return;
4443 }
4444
4445 /****************************************************************************
4446  Reply to a unlock.
4447 ****************************************************************************/
4448
4449 void reply_unlock(struct smb_request *req)
4450 {
4451         connection_struct *conn = req->conn;
4452         uint64_t count,offset;
4453         NTSTATUS status;
4454         files_struct *fsp;
4455
4456         START_PROFILE(SMBunlock);
4457
4458         if (req->wct < 5) {
4459                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4460                 END_PROFILE(SMBunlock);
4461                 return;
4462         }
4463
4464         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4465
4466         if (!check_fsp(conn, req, fsp)) {
4467                 END_PROFILE(SMBunlock);
4468                 return;
4469         }
4470
4471         count = (uint64_t)IVAL(req->vwv+1, 0);
4472         offset = (uint64_t)IVAL(req->vwv+3, 0);
4473
4474         status = do_unlock(smbd_messaging_context(),
4475                         fsp,
4476                         req->smbpid,
4477                         count,
4478                         offset,
4479                         WINDOWS_LOCK);
4480
4481         if (NT_STATUS_V(status)) {
4482                 reply_nterror(req, status);
4483                 END_PROFILE(SMBunlock);
4484                 return;
4485         }
4486
4487         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4488                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4489
4490         reply_outbuf(req, 0, 0);
4491
4492         END_PROFILE(SMBunlock);
4493         return;
4494 }
4495
4496 #undef DBGC_CLASS
4497 #define DBGC_CLASS DBGC_ALL
4498
4499 /****************************************************************************
4500  Reply to a tdis.
4501  conn POINTER CAN BE NULL HERE !
4502 ****************************************************************************/
4503
4504 void reply_tdis(struct smb_request *req)
4505 {
4506         connection_struct *conn = req->conn;
4507         START_PROFILE(SMBtdis);
4508
4509         if (!conn) {
4510                 DEBUG(4,("Invalid connection in tdis\n"));
4511                 reply_doserror(req, ERRSRV, ERRinvnid);
4512                 END_PROFILE(SMBtdis);
4513                 return;
4514         }
4515
4516         conn->used = False;
4517
4518         close_cnum(conn,req->vuid);
4519         req->conn = NULL;
4520
4521         reply_outbuf(req, 0, 0);
4522         END_PROFILE(SMBtdis);
4523         return;
4524 }
4525
4526 /****************************************************************************
4527  Reply to a echo.
4528  conn POINTER CAN BE NULL HERE !
4529 ****************************************************************************/
4530
4531 void reply_echo(struct smb_request *req)
4532 {
4533         connection_struct *conn = req->conn;
4534         int smb_reverb;
4535         int seq_num;
4536
4537         START_PROFILE(SMBecho);
4538
4539         if (req->wct < 1) {
4540                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4541                 END_PROFILE(SMBecho);
4542                 return;
4543         }
4544
4545         smb_reverb = SVAL(req->vwv+0, 0);
4546
4547         reply_outbuf(req, 1, req->buflen);
4548
4549         /* copy any incoming data back out */
4550         if (req->buflen > 0) {
4551                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4552         }
4553
4554         if (smb_reverb > 100) {
4555                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4556                 smb_reverb = 100;
4557         }
4558
4559         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4560                 SSVAL(req->outbuf,smb_vwv0,seq_num);
4561
4562                 show_msg((char *)req->outbuf);
4563                 if (!srv_send_smb(smbd_server_fd(),
4564                                 (char *)req->outbuf,
4565                                 IS_CONN_ENCRYPTED(conn)||req->encrypted))
4566                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
4567         }
4568
4569         DEBUG(3,("echo %d times\n", smb_reverb));
4570
4571         TALLOC_FREE(req->outbuf);
4572
4573         END_PROFILE(SMBecho);
4574         return;
4575 }
4576
4577 /****************************************************************************
4578  Reply to a printopen.
4579 ****************************************************************************/
4580
4581 void reply_printopen(struct smb_request *req)
4582 {
4583         connection_struct *conn = req->conn;
4584         files_struct *fsp;
4585         NTSTATUS status;
4586
4587         START_PROFILE(SMBsplopen);
4588
4589         if (req->wct < 2) {
4590                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4591                 END_PROFILE(SMBsplopen);
4592                 return;
4593         }
4594
4595         if (!CAN_PRINT(conn)) {
4596                 reply_doserror(req, ERRDOS, ERRnoaccess);
4597                 END_PROFILE(SMBsplopen);
4598                 return;
4599         }
4600
4601         status = file_new(req, conn, &fsp);
4602         if(!NT_STATUS_IS_OK(status)) {
4603                 reply_nterror(req, status);
4604                 END_PROFILE(SMBsplopen);
4605                 return;
4606         }
4607
4608         /* Open for exclusive use, write only. */
4609         status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
4610
4611         if (!NT_STATUS_IS_OK(status)) {
4612                 reply_nterror(req, status);
4613                 END_PROFILE(SMBsplopen);
4614                 return;
4615         }
4616
4617         reply_outbuf(req, 1, 0);
4618         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4619
4620         DEBUG(3,("openprint fd=%d fnum=%d\n",
4621                  fsp->fh->fd, fsp->fnum));
4622
4623         END_PROFILE(SMBsplopen);
4624         return;
4625 }
4626
4627 /****************************************************************************
4628  Reply to a printclose.
4629 ****************************************************************************/
4630
4631 void reply_printclose(struct smb_request *req)
4632 {
4633         connection_struct *conn = req->conn;
4634         files_struct *fsp;
4635         NTSTATUS status;
4636
4637         START_PROFILE(SMBsplclose);
4638
4639         if (req->wct < 1) {
4640                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4641                 END_PROFILE(SMBsplclose);
4642                 return;
4643         }
4644
4645         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4646
4647         if (!check_fsp(conn, req, fsp)) {
4648                 END_PROFILE(SMBsplclose);
4649                 return;
4650         }
4651
4652         if (!CAN_PRINT(conn)) {
4653                 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4654                 END_PROFILE(SMBsplclose);
4655                 return;
4656         }
4657
4658         DEBUG(3,("printclose fd=%d fnum=%d\n",
4659                  fsp->fh->fd,fsp->fnum));
4660
4661         status = close_file(req, fsp, NORMAL_CLOSE);
4662
4663         if(!NT_STATUS_IS_OK(status)) {
4664                 reply_nterror(req, status);
4665                 END_PROFILE(SMBsplclose);
4666                 return;
4667         }
4668
4669         reply_outbuf(req, 0, 0);
4670
4671         END_PROFILE(SMBsplclose);
4672         return;
4673 }
4674
4675 /****************************************************************************
4676  Reply to a printqueue.
4677 ****************************************************************************/
4678
4679 void reply_printqueue(struct smb_request *req)
4680 {
4681         connection_struct *conn = req->conn;
4682         int max_count;
4683         int start_index;
4684
4685         START_PROFILE(SMBsplretq);
4686
4687         if (req->wct < 2) {
4688                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4689                 END_PROFILE(SMBsplretq);
4690                 return;
4691         }
4692
4693         max_count = SVAL(req->vwv+0, 0);
4694         start_index = SVAL(req->vwv+1, 0);
4695
4696         /* we used to allow the client to get the cnum wrong, but that
4697            is really quite gross and only worked when there was only
4698            one printer - I think we should now only accept it if they
4699            get it right (tridge) */
4700         if (!CAN_PRINT(conn)) {
4701                 reply_doserror(req, ERRDOS, ERRnoaccess);
4702                 END_PROFILE(SMBsplretq);
4703                 return;
4704         }
4705
4706         reply_outbuf(req, 2, 3);
4707         SSVAL(req->outbuf,smb_vwv0,0);
4708         SSVAL(req->outbuf,smb_vwv1,0);
4709         SCVAL(smb_buf(req->outbuf),0,1);
4710         SSVAL(smb_buf(req->outbuf),1,0);
4711
4712         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4713                  start_index, max_count));
4714
4715         {
4716                 print_queue_struct *queue = NULL;
4717                 print_status_struct status;
4718                 int count = print_queue_status(SNUM(conn), &queue, &status);
4719                 int num_to_get = ABS(max_count);
4720                 int first = (max_count>0?start_index:start_index+max_count+1);
4721                 int i;
4722
4723                 if (first >= count)
4724                         num_to_get = 0;
4725                 else
4726                         num_to_get = MIN(num_to_get,count-first);
4727
4728
4729                 for (i=first;i<first+num_to_get;i++) {
4730                         char blob[28];
4731                         char *p = blob;
4732
4733                         srv_put_dos_date2(p,0,queue[i].time);
4734                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4735                         SSVAL(p,5, queue[i].job);
4736                         SIVAL(p,7,queue[i].size);
4737                         SCVAL(p,11,0);
4738                         srvstr_push(blob, req->flags2, p+12,
4739                                     queue[i].fs_user, 16, STR_ASCII);
4740
4741                         if (message_push_blob(
4742                                     &req->outbuf,
4743                                     data_blob_const(
4744                                             blob, sizeof(blob))) == -1) {
4745                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4746                                 END_PROFILE(SMBsplretq);
4747                                 return;
4748                         }
4749                 }
4750
4751                 if (count > 0) {
4752                         SSVAL(req->outbuf,smb_vwv0,count);
4753                         SSVAL(req->outbuf,smb_vwv1,
4754                               (max_count>0?first+count:first-1));
4755                         SCVAL(smb_buf(req->outbuf),0,1);
4756                         SSVAL(smb_buf(req->outbuf),1,28*count);
4757                 }
4758
4759                 SAFE_FREE(queue);
4760
4761                 DEBUG(3,("%d entries returned in queue\n",count));
4762         }
4763
4764         END_PROFILE(SMBsplretq);
4765         return;
4766 }
4767
4768 /****************************************************************************
4769  Reply to a printwrite.
4770 ****************************************************************************/
4771
4772 void reply_printwrite(struct smb_request *req)
4773 {
4774         connection_struct *conn = req->conn;
4775         int numtowrite;
4776         const char *data;
4777         files_struct *fsp;
4778
4779         START_PROFILE(SMBsplwr);
4780
4781         if (req->wct < 1) {
4782                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4783                 END_PROFILE(SMBsplwr);
4784                 return;
4785         }
4786
4787         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4788
4789         if (!check_fsp(conn, req, fsp)) {
4790                 END_PROFILE(SMBsplwr);
4791                 return;
4792         }
4793
4794         if (!CAN_PRINT(conn)) {
4795                 reply_doserror(req, ERRDOS, ERRnoaccess);
4796                 END_PROFILE(SMBsplwr);
4797                 return;
4798         }
4799
4800         if (!CHECK_WRITE(fsp)) {
4801                 reply_doserror(req, ERRDOS, ERRbadaccess);
4802                 END_PROFILE(SMBsplwr);
4803                 return;
4804         }
4805
4806         numtowrite = SVAL(req->buf, 1);
4807
4808         if (req->buflen < numtowrite + 3) {
4809                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4810                 END_PROFILE(SMBsplwr);
4811                 return;
4812         }
4813
4814         data = (const char *)req->buf + 3;
4815
4816         if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4817                 reply_unixerror(req, ERRHRD, ERRdiskfull);
4818                 END_PROFILE(SMBsplwr);
4819                 return;
4820         }
4821
4822         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4823
4824         END_PROFILE(SMBsplwr);
4825         return;
4826 }
4827
4828 /****************************************************************************
4829  Reply to a mkdir.
4830 ****************************************************************************/
4831
4832 void reply_mkdir(struct smb_request *req)
4833 {
4834         connection_struct *conn = req->conn;
4835         char *directory = NULL;
4836         NTSTATUS status;
4837         SMB_STRUCT_STAT sbuf;
4838         TALLOC_CTX *ctx = talloc_tos();
4839
4840         START_PROFILE(SMBmkdir);
4841
4842         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
4843                             STR_TERMINATE, &status);
4844         if (!NT_STATUS_IS_OK(status)) {
4845                 reply_nterror(req, status);
4846                 END_PROFILE(SMBmkdir);
4847                 return;
4848         }
4849
4850         status = resolve_dfspath(ctx, conn,
4851                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4852                                  directory,
4853                                  &directory);
4854         if (!NT_STATUS_IS_OK(status)) {
4855                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4856                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4857                                         ERRSRV, ERRbadpath);
4858                         END_PROFILE(SMBmkdir);
4859                         return;
4860                 }
4861                 reply_nterror(req, status);
4862                 END_PROFILE(SMBmkdir);
4863                 return;
4864         }
4865
4866         status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4867         if (!NT_STATUS_IS_OK(status)) {
4868                 reply_nterror(req, status);
4869                 END_PROFILE(SMBmkdir);
4870                 return;
4871         }
4872
4873         status = check_name(conn, directory);
4874         if (!NT_STATUS_IS_OK(status)) {
4875                 reply_nterror(req, status);
4876                 END_PROFILE(SMBmkdir);
4877                 return;
4878         }
4879
4880         status = create_directory(conn, req, directory);
4881
4882         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4883
4884         if (!NT_STATUS_IS_OK(status)) {
4885
4886                 if (!use_nt_status()
4887                     && NT_STATUS_EQUAL(status,
4888                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
4889                         /*
4890                          * Yes, in the DOS error code case we get a
4891                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4892                          * samba4 torture test.
4893                          */
4894                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4895                 }
4896
4897                 reply_nterror(req, status);
4898                 END_PROFILE(SMBmkdir);
4899                 return;
4900         }
4901
4902         reply_outbuf(req, 0, 0);
4903
4904         DEBUG( 3, ( "mkdir %s\n", directory ) );
4905
4906         END_PROFILE(SMBmkdir);
4907         return;
4908 }
4909
4910 /****************************************************************************
4911  Static function used by reply_rmdir to delete an entire directory
4912  tree recursively. Return True on ok, False on fail.
4913 ****************************************************************************/
4914
4915 static bool recursive_rmdir(TALLOC_CTX *ctx,
4916                         connection_struct *conn,
4917                         char *directory)
4918 {
4919         const char *dname = NULL;
4920         bool ret = True;
4921         long offset = 0;
4922         struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
4923                                           NULL, 0);
4924
4925         if(dir_hnd == NULL)
4926                 return False;
4927
4928         while((dname = ReadDirName(dir_hnd, &offset))) {
4929                 char *fullname = NULL;
4930                 SMB_STRUCT_STAT st;
4931
4932                 if (ISDOT(dname) || ISDOTDOT(dname)) {
4933                         continue;
4934                 }
4935
4936                 if (!is_visible_file(conn, directory, dname, &st, False)) {
4937                         continue;
4938                 }
4939
4940                 /* Construct the full name. */
4941                 fullname = talloc_asprintf(ctx,
4942                                 "%s/%s",
4943                                 directory,
4944                                 dname);
4945                 if (!fullname) {
4946                         errno = ENOMEM;
4947                         ret = False;
4948                         break;
4949                 }
4950
4951                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4952                         ret = False;
4953                         break;
4954                 }
4955
4956                 if(st.st_mode & S_IFDIR) {
4957                         if(!recursive_rmdir(ctx, conn, fullname)) {
4958                                 ret = False;
4959                                 break;
4960                         }
4961                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4962                                 ret = False;
4963                                 break;
4964                         }
4965                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4966                         ret = False;
4967                         break;
4968                 }
4969                 TALLOC_FREE(fullname);
4970         }
4971         TALLOC_FREE(dir_hnd);
4972         return ret;
4973 }
4974
4975 /****************************************************************************
4976  The internals of the rmdir code - called elsewhere.
4977 ****************************************************************************/
4978
4979 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
4980                         connection_struct *conn,
4981                         const char *directory)
4982 {
4983         int ret;
4984         SMB_STRUCT_STAT st;
4985
4986         /* Might be a symlink. */
4987         if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4988                 return map_nt_error_from_unix(errno);
4989         }
4990
4991         if (S_ISLNK(st.st_mode)) {
4992                 /* Is what it points to a directory ? */
4993                 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4994                         return map_nt_error_from_unix(errno);
4995                 }
4996                 if (!(S_ISDIR(st.st_mode))) {
4997                         return NT_STATUS_NOT_A_DIRECTORY;
4998                 }
4999                 ret = SMB_VFS_UNLINK(conn,directory);
5000         } else {
5001                 ret = SMB_VFS_RMDIR(conn,directory);
5002         }
5003         if (ret == 0) {
5004                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5005                              FILE_NOTIFY_CHANGE_DIR_NAME,
5006                              directory);
5007                 return NT_STATUS_OK;
5008         }
5009
5010         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5011                 /*
5012                  * Check to see if the only thing in this directory are
5013                  * vetoed files/directories. If so then delete them and
5014                  * retry. If we fail to delete any of them (and we *don't*
5015                  * do a recursive delete) then fail the rmdir.
5016                  */
5017                 const char *dname;
5018                 long dirpos = 0;
5019                 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5020                                                   directory, NULL, 0);
5021
5022                 if(dir_hnd == NULL) {
5023                         errno = ENOTEMPTY;
5024                         goto err;
5025                 }
5026
5027                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5028                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5029                                 continue;
5030                         if (!is_visible_file(conn, directory, dname, &st, False))
5031                                 continue;
5032                         if(!IS_VETO_PATH(conn, dname)) {
5033                                 TALLOC_FREE(dir_hnd);
5034                                 errno = ENOTEMPTY;
5035                                 goto err;
5036                         }
5037                 }
5038
5039                 /* We only have veto files/directories.
5040                  * Are we allowed to delete them ? */
5041
5042                 if(!lp_recursive_veto_delete(SNUM(conn))) {
5043                         TALLOC_FREE(dir_hnd);
5044                         errno = ENOTEMPTY;
5045                         goto err;
5046                 }
5047
5048                 /* Do a recursive delete. */
5049                 RewindDir(dir_hnd,&dirpos);
5050                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5051                         char *fullname = NULL;
5052
5053                         if (ISDOT(dname) || ISDOTDOT(dname)) {
5054                                 continue;
5055                         }
5056                         if (!is_visible_file(conn, directory, dname, &st, False)) {
5057                                 continue;
5058                         }
5059
5060                         fullname = talloc_asprintf(ctx,
5061                                         "%s/%s",
5062                                         directory,
5063                                         dname);
5064
5065                         if(!fullname) {
5066                                 errno = ENOMEM;
5067                                 break;
5068                         }
5069
5070                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5071                                 break;
5072                         }
5073                         if(st.st_mode & S_IFDIR) {
5074                                 if(!recursive_rmdir(ctx, conn, fullname)) {
5075                                         break;
5076                                 }
5077                                 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5078                                         break;
5079                                 }
5080                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5081                                 break;
5082                         }
5083                         TALLOC_FREE(fullname);
5084                 }
5085                 TALLOC_FREE(dir_hnd);
5086                 /* Retry the rmdir */
5087                 ret = SMB_VFS_RMDIR(conn,directory);
5088         }
5089
5090   err:
5091
5092         if (ret != 0) {
5093                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5094                          "%s\n", directory,strerror(errno)));
5095                 return map_nt_error_from_unix(errno);
5096         }
5097
5098         notify_fname(conn, NOTIFY_ACTION_REMOVED,
5099                      FILE_NOTIFY_CHANGE_DIR_NAME,
5100                      directory);
5101
5102         return NT_STATUS_OK;
5103 }
5104
5105 /****************************************************************************
5106  Reply to a rmdir.
5107 ****************************************************************************/
5108
5109 void reply_rmdir(struct smb_request *req)
5110 {
5111         connection_struct *conn = req->conn;
5112         char *directory = NULL;
5113         SMB_STRUCT_STAT sbuf;
5114         NTSTATUS status;
5115         TALLOC_CTX *ctx = talloc_tos();
5116
5117         START_PROFILE(SMBrmdir);
5118
5119         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5120                             STR_TERMINATE, &status);
5121         if (!NT_STATUS_IS_OK(status)) {
5122                 reply_nterror(req, status);
5123                 END_PROFILE(SMBrmdir);
5124                 return;
5125         }
5126
5127         status = resolve_dfspath(ctx, conn,
5128                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5129                                  directory,
5130                                  &directory);
5131         if (!NT_STATUS_IS_OK(status)) {
5132                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5133                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5134                                         ERRSRV, ERRbadpath);
5135                         END_PROFILE(SMBrmdir);
5136                         return;
5137                 }
5138                 reply_nterror(req, status);
5139                 END_PROFILE(SMBrmdir);
5140                 return;
5141         }
5142
5143         status = unix_convert(ctx, conn, directory, False, &directory,
5144                         NULL, &sbuf);
5145         if (!NT_STATUS_IS_OK(status)) {
5146                 reply_nterror(req, status);
5147                 END_PROFILE(SMBrmdir);
5148                 return;
5149         }
5150
5151         status = check_name(conn, directory);
5152         if (!NT_STATUS_IS_OK(status)) {
5153                 reply_nterror(req, status);
5154                 END_PROFILE(SMBrmdir);
5155                 return;
5156         }
5157
5158         dptr_closepath(directory, req->smbpid);
5159         status = rmdir_internals(ctx, conn, directory);
5160         if (!NT_STATUS_IS_OK(status)) {
5161                 reply_nterror(req, status);
5162                 END_PROFILE(SMBrmdir);
5163                 return;
5164         }
5165
5166         reply_outbuf(req, 0, 0);
5167
5168         DEBUG( 3, ( "rmdir %s\n", directory ) );
5169
5170         END_PROFILE(SMBrmdir);
5171         return;
5172 }
5173
5174 /*******************************************************************
5175  Resolve wildcards in a filename rename.
5176 ********************************************************************/
5177
5178 static bool resolve_wildcards(TALLOC_CTX *ctx,
5179                                 const char *name1,
5180                                 const char *name2,
5181                                 char **pp_newname)
5182 {
5183         char *name2_copy = NULL;
5184         char *root1 = NULL;
5185         char *root2 = NULL;
5186         char *ext1 = NULL;
5187         char *ext2 = NULL;
5188         char *p,*p2, *pname1, *pname2;
5189
5190         name2_copy = talloc_strdup(ctx, name2);
5191         if (!name2_copy) {
5192                 return False;
5193         }
5194
5195         pname1 = strrchr_m(name1,'/');
5196         pname2 = strrchr_m(name2_copy,'/');
5197
5198         if (!pname1 || !pname2) {
5199                 return False;
5200         }
5201
5202         /* Truncate the copy of name2 at the last '/' */
5203         *pname2 = '\0';
5204
5205         /* Now go past the '/' */
5206         pname1++;
5207         pname2++;
5208
5209         root1 = talloc_strdup(ctx, pname1);
5210         root2 = talloc_strdup(ctx, pname2);
5211
5212         if (!root1 || !root2) {
5213                 return False;
5214         }
5215
5216         p = strrchr_m(root1,'.');
5217         if (p) {
5218                 *p = 0;
5219                 ext1 = talloc_strdup(ctx, p+1);
5220         } else {
5221                 ext1 = talloc_strdup(ctx, "");
5222         }
5223         p = strrchr_m(root2,'.');
5224         if (p) {
5225                 *p = 0;
5226                 ext2 = talloc_strdup(ctx, p+1);
5227         } else {
5228                 ext2 = talloc_strdup(ctx, "");
5229         }
5230
5231         if (!ext1 || !ext2) {
5232                 return False;
5233         }
5234
5235         p = root1;
5236         p2 = root2;
5237         while (*p2) {
5238                 if (*p2 == '?') {
5239                         /* Hmmm. Should this be mb-aware ? */
5240                         *p2 = *p;
5241                         p2++;
5242                 } else if (*p2 == '*') {
5243                         *p2 = '\0';
5244                         root2 = talloc_asprintf(ctx, "%s%s",
5245                                                 root2,
5246                                                 p);
5247                         if (!root2) {
5248                                 return False;
5249                         }
5250                         break;
5251                 } else {
5252                         p2++;
5253                 }
5254                 if (*p) {
5255                         p++;
5256                 }
5257         }
5258
5259         p = ext1;
5260         p2 = ext2;
5261         while (*p2) {
5262                 if (*p2 == '?') {
5263                         /* Hmmm. Should this be mb-aware ? */
5264                         *p2 = *p;
5265                         p2++;
5266                 } else if (*p2 == '*') {
5267                         *p2 = '\0';
5268                         ext2 = talloc_asprintf(ctx, "%s%s",
5269                                                 ext2,
5270                                                 p);
5271                         if (!ext2) {
5272                                 return False;
5273                         }
5274                         break;
5275                 } else {
5276                         p2++;
5277                 }
5278                 if (*p) {
5279                         p++;
5280                 }
5281         }
5282
5283         if (*ext2) {
5284                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5285                                 name2_copy,
5286                                 root2,
5287                                 ext2);
5288         } else {
5289                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5290                                 name2_copy,
5291                                 root2);
5292         }
5293
5294         if (!*pp_newname) {
5295                 return False;
5296         }
5297
5298         return True;
5299 }
5300
5301 /****************************************************************************
5302  Ensure open files have their names updated. Updated to notify other smbd's
5303  asynchronously.
5304 ****************************************************************************/
5305
5306 static void rename_open_files(connection_struct *conn,
5307                               struct share_mode_lock *lck,
5308                               const char *newname)
5309 {
5310         files_struct *fsp;
5311         bool did_rename = False;
5312
5313         for(fsp = file_find_di_first(lck->id); fsp;
5314             fsp = file_find_di_next(fsp)) {
5315                 /* fsp_name is a relative path under the fsp. To change this for other
5316                    sharepaths we need to manipulate relative paths. */
5317                 /* TODO - create the absolute path and manipulate the newname
5318                    relative to the sharepath. */
5319                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5320                         continue;
5321                 }
5322                 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5323                           fsp->fnum, file_id_string_tos(&fsp->file_id),
5324                         fsp->fsp_name, newname ));
5325                 string_set(&fsp->fsp_name, newname);
5326                 did_rename = True;
5327         }
5328
5329         if (!did_rename) {
5330                 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5331                           file_id_string_tos(&lck->id), newname ));
5332         }
5333
5334         /* Send messages to all smbd's (not ourself) that the name has changed. */
5335         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5336                               newname);
5337 }
5338
5339 /****************************************************************************
5340  We need to check if the source path is a parent directory of the destination
5341  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5342  refuse the rename with a sharing violation. Under UNIX the above call can
5343  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5344  probably need to check that the client is a Windows one before disallowing
5345  this as a UNIX client (one with UNIX extensions) can know the source is a
5346  symlink and make this decision intelligently. Found by an excellent bug
5347  report from <AndyLiebman@aol.com>.
5348 ****************************************************************************/
5349
5350 static bool rename_path_prefix_equal(const char *src, const char *dest)
5351 {
5352         const char *psrc = src;
5353         const char *pdst = dest;
5354         size_t slen;
5355
5356         if (psrc[0] == '.' && psrc[1] == '/') {
5357                 psrc += 2;
5358         }
5359         if (pdst[0] == '.' && pdst[1] == '/') {
5360                 pdst += 2;
5361         }
5362         if ((slen = strlen(psrc)) > strlen(pdst)) {
5363                 return False;
5364         }
5365         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5366 }
5367
5368 /*
5369  * Do the notify calls from a rename
5370  */
5371
5372 static void notify_rename(connection_struct *conn, bool is_dir,
5373                           const char *oldpath, const char *newpath)
5374 {
5375         char *olddir, *newdir;
5376         const char *oldname, *newname;
5377         uint32 mask;
5378
5379         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5380                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5381
5382         if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
5383             || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
5384                 TALLOC_FREE(olddir);
5385                 return;
5386         }
5387
5388         if (strcmp(olddir, newdir) == 0) {
5389                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5390                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5391         }
5392         else {
5393                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5394                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5395         }
5396         TALLOC_FREE(olddir);
5397         TALLOC_FREE(newdir);
5398
5399         /* this is a strange one. w2k3 gives an additional event for
5400            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5401            files, but not directories */
5402         if (!is_dir) {
5403                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5404                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5405                              |FILE_NOTIFY_CHANGE_CREATION,
5406                              newpath);
5407         }
5408 }
5409
5410 /****************************************************************************
5411  Rename an open file - given an fsp.
5412 ****************************************************************************/
5413
5414 NTSTATUS rename_internals_fsp(connection_struct *conn,
5415                         files_struct *fsp,
5416                         char *newname,
5417                         const char *newname_last_component,
5418                         uint32 attrs,
5419                         bool replace_if_exists)
5420 {
5421         TALLOC_CTX *ctx = talloc_tos();
5422         SMB_STRUCT_STAT sbuf, sbuf1;
5423         NTSTATUS status = NT_STATUS_OK;
5424         struct share_mode_lock *lck = NULL;
5425         bool dst_exists;
5426
5427         ZERO_STRUCT(sbuf);
5428
5429         status = check_name(conn, newname);
5430         if (!NT_STATUS_IS_OK(status)) {
5431                 return status;
5432         }
5433
5434         /* Ensure newname contains a '/' */
5435         if(strrchr_m(newname,'/') == 0) {
5436                 newname = talloc_asprintf(ctx,
5437                                         "./%s",
5438                                         newname);
5439                 if (!newname) {
5440                         return NT_STATUS_NO_MEMORY;
5441                 }
5442         }
5443
5444         /*
5445          * Check for special case with case preserving and not
5446          * case sensitive. If the old last component differs from the original
5447          * last component only by case, then we should allow
5448          * the rename (user is trying to change the case of the
5449          * filename).
5450          */
5451
5452         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5453                         strequal(newname, fsp->fsp_name)) {
5454                 char *p;
5455                 char *newname_modified_last_component = NULL;
5456
5457                 /*
5458                  * Get the last component of the modified name.
5459                  * Note that we guarantee that newname contains a '/'
5460                  * character above.
5461                  */
5462                 p = strrchr_m(newname,'/');
5463                 newname_modified_last_component = talloc_strdup(ctx,
5464                                                 p+1);
5465                 if (!newname_modified_last_component) {
5466                         return NT_STATUS_NO_MEMORY;
5467                 }
5468
5469                 if(strcsequal(newname_modified_last_component,
5470                               newname_last_component) == False) {
5471                         /*
5472                          * Replace the modified last component with
5473                          * the original.
5474                          */
5475                         *p = '\0'; /* Truncate at the '/' */
5476                         newname = talloc_asprintf(ctx,
5477                                         "%s/%s",
5478                                         newname,
5479                                         newname_last_component);
5480                 }
5481         }
5482
5483         /*
5484          * If the src and dest names are identical - including case,
5485          * don't do the rename, just return success.
5486          */
5487
5488         if (strcsequal(fsp->fsp_name, newname)) {
5489                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5490                         newname));
5491                 return NT_STATUS_OK;
5492         }
5493
5494         /*
5495          * Have vfs_object_exist also fill sbuf1
5496          */
5497         dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5498
5499         if(!replace_if_exists && dst_exists) {
5500                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5501                         fsp->fsp_name,newname));
5502                 return NT_STATUS_OBJECT_NAME_COLLISION;
5503         }
5504
5505         if(replace_if_exists && dst_exists) {
5506                 if (is_ntfs_stream_name(newname)) {
5507                         return NT_STATUS_INVALID_PARAMETER;
5508                 }
5509         }
5510
5511         if (dst_exists) {
5512                 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5513                 files_struct *dst_fsp = file_find_di_first(fileid);
5514                 if (dst_fsp) {
5515                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5516                         return NT_STATUS_ACCESS_DENIED;
5517                 }
5518         }
5519
5520         /* Ensure we have a valid stat struct for the source. */
5521         if (fsp->fh->fd != -1) {
5522                 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5523                         return map_nt_error_from_unix(errno);
5524                 }
5525         } else {
5526                 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5527                         return map_nt_error_from_unix(errno);
5528                 }
5529         }
5530
5531         status = can_rename(conn, fsp, attrs, &sbuf);
5532
5533         if (!NT_STATUS_IS_OK(status)) {
5534                 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5535                         nt_errstr(status), fsp->fsp_name,newname));
5536                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5537                         status = NT_STATUS_ACCESS_DENIED;
5538                 return status;
5539         }
5540
5541         if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5542                 return NT_STATUS_ACCESS_DENIED;
5543         }
5544
5545         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5546                                   NULL);
5547
5548         /*
5549          * We have the file open ourselves, so not being able to get the
5550          * corresponding share mode lock is a fatal error.
5551          */
5552
5553         SMB_ASSERT(lck != NULL);
5554
5555         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5556                 uint32 create_options = fsp->fh->private_options;
5557
5558                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5559                         fsp->fsp_name,newname));
5560
5561                 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5562
5563                 rename_open_files(conn, lck, newname);
5564
5565                 /*
5566                  * A rename acts as a new file create w.r.t. allowing an initial delete
5567                  * on close, probably because in Windows there is a new handle to the
5568                  * new file. If initial delete on close was requested but not
5569                  * originally set, we need to set it here. This is probably not 100% correct,
5570                  * but will work for the CIFSFS client which in non-posix mode
5571                  * depends on these semantics. JRA.
5572                  */
5573
5574                 set_allow_initial_delete_on_close(lck, fsp, True);
5575
5576                 if (create_options & FILE_DELETE_ON_CLOSE) {
5577                         status = can_set_delete_on_close(fsp, True, 0);
5578
5579                         if (NT_STATUS_IS_OK(status)) {
5580                                 /* Note that here we set the *inital* delete on close flag,
5581                                  * not the regular one. The magic gets handled in close. */
5582                                 fsp->initial_delete_on_close = True;
5583                         }
5584                 }
5585                 TALLOC_FREE(lck);
5586                 return NT_STATUS_OK;
5587         }
5588
5589         TALLOC_FREE(lck);
5590
5591         if (errno == ENOTDIR || errno == EISDIR) {
5592                 status = NT_STATUS_OBJECT_NAME_COLLISION;
5593         } else {
5594                 status = map_nt_error_from_unix(errno);
5595         }
5596
5597         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5598                 nt_errstr(status), fsp->fsp_name,newname));
5599
5600         return status;
5601 }
5602
5603 /****************************************************************************
5604  The guts of the rename command, split out so it may be called by the NT SMB
5605  code.
5606 ****************************************************************************/
5607
5608 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5609                         connection_struct *conn,
5610                         struct smb_request *req,
5611                         const char *name_in,
5612                         const char *newname_in,
5613                         uint32 attrs,
5614                         bool replace_if_exists,
5615                         bool src_has_wild,
5616                         bool dest_has_wild,
5617                         uint32_t access_mask)
5618 {
5619         char *directory = NULL;
5620         char *mask = NULL;
5621         char *last_component_src = NULL;
5622         char *last_component_dest = NULL;
5623         char *name = NULL;
5624         char *newname = NULL;
5625         char *p;
5626         int count=0;
5627         NTSTATUS status = NT_STATUS_OK;
5628         SMB_STRUCT_STAT sbuf1, sbuf2;
5629         struct smb_Dir *dir_hnd = NULL;
5630         const char *dname;
5631         long offset = 0;
5632
5633         ZERO_STRUCT(sbuf1);
5634         ZERO_STRUCT(sbuf2);
5635
5636         status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5637                         &last_component_src, &sbuf1);
5638         if (!NT_STATUS_IS_OK(status)) {
5639                 return status;
5640         }
5641
5642         status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5643                         &last_component_dest, &sbuf2);
5644         if (!NT_STATUS_IS_OK(status)) {
5645                 return status;
5646         }
5647
5648         /*
5649          * Split the old name into directory and last component
5650          * strings. Note that unix_convert may have stripped off a
5651          * leading ./ from both name and newname if the rename is
5652          * at the root of the share. We need to make sure either both
5653          * name and newname contain a / character or neither of them do
5654          * as this is checked in resolve_wildcards().
5655          */
5656
5657         p = strrchr_m(name,'/');
5658         if (!p) {
5659                 directory = talloc_strdup(ctx, ".");
5660                 if (!directory) {
5661                         return NT_STATUS_NO_MEMORY;
5662                 }
5663                 mask = name;
5664         } else {
5665                 *p = 0;
5666                 directory = talloc_strdup(ctx, name);
5667                 if (!directory) {
5668                         return NT_STATUS_NO_MEMORY;
5669                 }
5670                 mask = p+1;
5671                 *p = '/'; /* Replace needed for exceptional test below. */
5672         }
5673
5674         /*
5675          * We should only check the mangled cache
5676          * here if unix_convert failed. This means
5677          * that the path in 'mask' doesn't exist
5678          * on the file system and so we need to look
5679          * for a possible mangle. This patch from
5680          * Tine Smukavec <valentin.smukavec@hermes.si>.
5681          */
5682
5683         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5684                 char *new_mask = NULL;
5685                 mangle_lookup_name_from_8_3(ctx,
5686                                         mask,
5687                                         &new_mask,
5688                                         conn->params );
5689                 if (new_mask) {
5690                         mask = new_mask;
5691                 }
5692         }
5693
5694         if (!src_has_wild) {
5695                 files_struct *fsp;
5696
5697                 /*
5698                  * No wildcards - just process the one file.
5699                  */
5700                 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5701
5702                 /* Add a terminating '/' to the directory name. */
5703                 directory = talloc_asprintf_append(directory,
5704                                 "/%s",
5705                                 mask);
5706                 if (!directory) {
5707                         return NT_STATUS_NO_MEMORY;
5708                 }
5709
5710                 /* Ensure newname contains a '/' also */
5711                 if(strrchr_m(newname,'/') == 0) {
5712                         newname = talloc_asprintf(ctx,
5713                                                 "./%s",
5714                                                 newname);
5715                         if (!newname) {
5716                                 return NT_STATUS_NO_MEMORY;
5717                         }
5718                 }
5719
5720                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5721                           "case_preserve = %d, short case preserve = %d, "
5722                           "directory = %s, newname = %s, "
5723                           "last_component_dest = %s, is_8_3 = %d\n",
5724                           conn->case_sensitive, conn->case_preserve,
5725                           conn->short_case_preserve, directory,
5726                           newname, last_component_dest, is_short_name));
5727
5728                 /* The dest name still may have wildcards. */
5729                 if (dest_has_wild) {
5730                         char *mod_newname = NULL;
5731                         if (!resolve_wildcards(ctx,
5732                                         directory,newname,&mod_newname)) {
5733                                 DEBUG(6, ("rename_internals: resolve_wildcards "
5734                                         "%s %s failed\n",
5735                                         directory,
5736                                         newname));
5737                                 return NT_STATUS_NO_MEMORY;
5738                         }
5739                         newname = mod_newname;
5740                 }
5741
5742                 ZERO_STRUCT(sbuf1);
5743                 SMB_VFS_STAT(conn, directory, &sbuf1);
5744
5745                 status = S_ISDIR(sbuf1.st_mode) ?
5746                         open_directory(conn, req, directory, &sbuf1,
5747                                        access_mask,
5748                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5749                                        FILE_OPEN, 0, 0, NULL,
5750                                        &fsp)
5751                         : open_file_ntcreate(conn, req, directory, &sbuf1,
5752                                              access_mask,
5753                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5754                                              FILE_OPEN, 0, 0, 0, NULL,
5755                                              &fsp);
5756
5757                 if (!NT_STATUS_IS_OK(status)) {
5758                         DEBUG(3, ("Could not open rename source %s: %s\n",
5759                                   directory, nt_errstr(status)));
5760                         return status;
5761                 }
5762
5763                 status = rename_internals_fsp(conn, fsp, newname,
5764                                               last_component_dest,
5765                                               attrs, replace_if_exists);
5766
5767                 close_file(req, fsp, NORMAL_CLOSE);
5768
5769                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5770                           nt_errstr(status), directory,newname));
5771
5772                 return status;
5773         }
5774
5775         /*
5776          * Wildcards - process each file that matches.
5777          */
5778         if (strequal(mask,"????????.???")) {
5779                 mask[0] = '*';
5780                 mask[1] = '\0';
5781         }
5782
5783         status = check_name(conn, directory);
5784         if (!NT_STATUS_IS_OK(status)) {
5785                 return status;
5786         }
5787
5788         dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
5789         if (dir_hnd == NULL) {
5790                 return map_nt_error_from_unix(errno);
5791         }
5792
5793         status = NT_STATUS_NO_SUCH_FILE;
5794         /*
5795          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5796          * - gentest fix. JRA
5797          */
5798
5799         while ((dname = ReadDirName(dir_hnd, &offset))) {
5800                 files_struct *fsp = NULL;
5801                 char *fname = NULL;
5802                 char *destname = NULL;
5803                 bool sysdir_entry = False;
5804
5805                 /* Quick check for "." and ".." */
5806                 if (ISDOT(dname) || ISDOTDOT(dname)) {
5807                         if (attrs & aDIR) {
5808                                 sysdir_entry = True;
5809                         } else {
5810                                 continue;
5811                         }
5812                 }
5813
5814                 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5815                         continue;
5816                 }
5817
5818                 if(!mask_match(dname, mask, conn->case_sensitive)) {
5819                         continue;
5820                 }
5821
5822                 if (sysdir_entry) {
5823                         status = NT_STATUS_OBJECT_NAME_INVALID;
5824                         break;
5825                 }
5826
5827                 fname = talloc_asprintf(ctx,
5828                                 "%s/%s",
5829                                 directory,
5830                                 dname);
5831                 if (!fname) {
5832                         return NT_STATUS_NO_MEMORY;
5833                 }
5834
5835                 if (!resolve_wildcards(ctx,
5836                                 fname,newname,&destname)) {
5837                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
5838                                   fname, destname));
5839                         TALLOC_FREE(fname);
5840                         continue;
5841                 }
5842                 if (!destname) {
5843                         return NT_STATUS_NO_MEMORY;
5844                 }
5845
5846                 ZERO_STRUCT(sbuf1);
5847                 SMB_VFS_STAT(conn, fname, &sbuf1);
5848
5849                 status = S_ISDIR(sbuf1.st_mode) ?
5850                         open_directory(conn, req, fname, &sbuf1,
5851                                        access_mask,
5852                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5853                                        FILE_OPEN, 0, 0, NULL,
5854                                        &fsp)
5855                         : open_file_ntcreate(conn, req, fname, &sbuf1,
5856                                              access_mask,
5857                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5858                                              FILE_OPEN, 0, 0, 0, NULL,
5859                                              &fsp);
5860
5861                 if (!NT_STATUS_IS_OK(status)) {
5862                         DEBUG(3,("rename_internals: open_file_ntcreate "
5863                                  "returned %s rename %s -> %s\n",
5864                                  nt_errstr(status), directory, newname));
5865                         break;
5866                 }
5867
5868                 status = rename_internals_fsp(conn, fsp, destname, dname,
5869                                               attrs, replace_if_exists);
5870
5871                 close_file(req, fsp, NORMAL_CLOSE);
5872
5873                 if (!NT_STATUS_IS_OK(status)) {
5874                         DEBUG(3, ("rename_internals_fsp returned %s for "
5875                                   "rename %s -> %s\n", nt_errstr(status),
5876                                   directory, newname));
5877                         break;
5878                 }
5879
5880                 count++;
5881
5882                 DEBUG(3,("rename_internals: doing rename on %s -> "
5883                          "%s\n",fname,destname));
5884
5885                 TALLOC_FREE(fname);
5886                 TALLOC_FREE(destname);
5887         }
5888         TALLOC_FREE(dir_hnd);
5889
5890         if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
5891                 status = map_nt_error_from_unix(errno);
5892         }
5893
5894         return status;
5895 }
5896
5897 /****************************************************************************
5898  Reply to a mv.
5899 ****************************************************************************/
5900
5901 void reply_mv(struct smb_request *req)
5902 {
5903         connection_struct *conn = req->conn;
5904         char *name = NULL;
5905         char *newname = NULL;
5906         const char *p;
5907         uint32 attrs;
5908         NTSTATUS status;
5909         bool src_has_wcard = False;
5910         bool dest_has_wcard = False;
5911         TALLOC_CTX *ctx = talloc_tos();
5912
5913         START_PROFILE(SMBmv);
5914
5915         if (req->wct < 1) {
5916                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5917                 END_PROFILE(SMBmv);
5918                 return;
5919         }
5920
5921         attrs = SVAL(req->vwv+0, 0);
5922
5923         p = (const char *)req->buf + 1;
5924         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
5925                                        &status, &src_has_wcard);
5926         if (!NT_STATUS_IS_OK(status)) {
5927                 reply_nterror(req, status);
5928                 END_PROFILE(SMBmv);
5929                 return;
5930         }
5931         p++;
5932         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
5933                                        &status, &dest_has_wcard);
5934         if (!NT_STATUS_IS_OK(status)) {
5935                 reply_nterror(req, status);
5936                 END_PROFILE(SMBmv);
5937                 return;
5938         }
5939
5940         status = resolve_dfspath_wcard(ctx, conn,
5941                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5942                                        name,
5943                                        &name,
5944                                        &src_has_wcard);
5945         if (!NT_STATUS_IS_OK(status)) {
5946                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5947                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5948                                         ERRSRV, ERRbadpath);
5949                         END_PROFILE(SMBmv);
5950                         return;
5951                 }
5952                 reply_nterror(req, status);
5953                 END_PROFILE(SMBmv);
5954                 return;
5955         }
5956
5957         status = resolve_dfspath_wcard(ctx, conn,
5958                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5959                                        newname,
5960                                        &newname,
5961                                        &dest_has_wcard);
5962         if (!NT_STATUS_IS_OK(status)) {
5963                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5964                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5965                                         ERRSRV, ERRbadpath);
5966                         END_PROFILE(SMBmv);
5967                         return;
5968                 }
5969                 reply_nterror(req, status);
5970                 END_PROFILE(SMBmv);
5971                 return;
5972         }
5973
5974         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5975
5976         status = rename_internals(ctx, conn, req, name, newname, attrs, False,
5977                                   src_has_wcard, dest_has_wcard, DELETE_ACCESS);
5978         if (!NT_STATUS_IS_OK(status)) {
5979                 if (open_was_deferred(req->mid)) {
5980                         /* We have re-scheduled this call. */
5981                         END_PROFILE(SMBmv);
5982                         return;
5983                 }
5984                 reply_nterror(req, status);
5985                 END_PROFILE(SMBmv);
5986                 return;
5987         }
5988
5989         reply_outbuf(req, 0, 0);
5990
5991         END_PROFILE(SMBmv);
5992         return;
5993 }
5994
5995 /*******************************************************************
5996  Copy a file as part of a reply_copy.
5997 ******************************************************************/
5998
5999 /*
6000  * TODO: check error codes on all callers
6001  */
6002
6003 NTSTATUS copy_file(TALLOC_CTX *ctx,
6004                         connection_struct *conn,
6005                         const char *src,
6006                         const char *dest1,
6007                         int ofun,
6008                         int count,
6009                         bool target_is_directory)
6010 {
6011         SMB_STRUCT_STAT src_sbuf, sbuf2;
6012         SMB_OFF_T ret=-1;
6013         files_struct *fsp1,*fsp2;
6014         char *dest = NULL;
6015         uint32 dosattrs;
6016         uint32 new_create_disposition;
6017         NTSTATUS status;
6018
6019         dest = talloc_strdup(ctx, dest1);
6020         if (!dest) {
6021                 return NT_STATUS_NO_MEMORY;
6022         }
6023         if (target_is_directory) {
6024                 const char *p = strrchr_m(src,'/');
6025                 if (p) {
6026                         p++;
6027                 } else {
6028                         p = src;
6029                 }
6030                 dest = talloc_asprintf_append(dest,
6031                                 "/%s",
6032                                 p);
6033                 if (!dest) {
6034                         return NT_STATUS_NO_MEMORY;
6035                 }
6036         }
6037
6038         if (!vfs_file_exist(conn,src,&src_sbuf)) {
6039                 TALLOC_FREE(dest);
6040                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6041         }
6042
6043         if (!target_is_directory && count) {
6044                 new_create_disposition = FILE_OPEN;
6045         } else {
6046                 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6047                                 NULL, NULL, &new_create_disposition, NULL)) {
6048                         TALLOC_FREE(dest);
6049                         return NT_STATUS_INVALID_PARAMETER;
6050                 }
6051         }
6052
6053         status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
6054                         FILE_GENERIC_READ,
6055                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6056                         FILE_OPEN,
6057                         0,
6058                         FILE_ATTRIBUTE_NORMAL,
6059                         INTERNAL_OPEN_ONLY,
6060                         NULL, &fsp1);
6061
6062         if (!NT_STATUS_IS_OK(status)) {
6063                 TALLOC_FREE(dest);
6064                 return status;
6065         }
6066
6067         dosattrs = dos_mode(conn, src, &src_sbuf);
6068         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6069                 ZERO_STRUCTP(&sbuf2);
6070         }
6071
6072         status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
6073                         FILE_GENERIC_WRITE,
6074                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6075                         new_create_disposition,
6076                         0,
6077                         dosattrs,
6078                         INTERNAL_OPEN_ONLY,
6079                         NULL, &fsp2);
6080
6081         TALLOC_FREE(dest);
6082
6083         if (!NT_STATUS_IS_OK(status)) {
6084                 close_file(NULL, fsp1, ERROR_CLOSE);
6085                 return status;
6086         }
6087
6088         if ((ofun&3) == 1) {
6089                 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6090                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6091                         /*
6092                          * Stop the copy from occurring.
6093                          */
6094                         ret = -1;
6095                         src_sbuf.st_size = 0;
6096                 }
6097         }
6098
6099         if (src_sbuf.st_size) {
6100                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6101         }
6102
6103         close_file(NULL, fsp1, NORMAL_CLOSE);
6104
6105         /* Ensure the modtime is set correctly on the destination file. */
6106         set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6107
6108         /*
6109          * As we are opening fsp1 read-only we only expect
6110          * an error on close on fsp2 if we are out of space.
6111          * Thus we don't look at the error return from the
6112          * close of fsp1.
6113          */
6114         status = close_file(NULL, fsp2, NORMAL_CLOSE);
6115
6116         if (!NT_STATUS_IS_OK(status)) {
6117                 return status;
6118         }
6119
6120         if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6121                 return NT_STATUS_DISK_FULL;
6122         }
6123
6124         return NT_STATUS_OK;
6125 }
6126
6127 /****************************************************************************
6128  Reply to a file copy.
6129 ****************************************************************************/
6130
6131 void reply_copy(struct smb_request *req)
6132 {
6133         connection_struct *conn = req->conn;
6134         char *name = NULL;
6135         char *newname = NULL;
6136         char *directory = NULL;
6137         const char *mask = NULL;
6138         const char mask_star[] = "*";
6139         const char *p;
6140         int count=0;
6141         int error = ERRnoaccess;
6142         int err = 0;
6143         int tid2;
6144         int ofun;
6145         int flags;
6146         bool target_is_directory=False;
6147         bool source_has_wild = False;
6148         bool dest_has_wild = False;
6149         SMB_STRUCT_STAT sbuf1, sbuf2;
6150         NTSTATUS status;
6151         TALLOC_CTX *ctx = talloc_tos();
6152
6153         START_PROFILE(SMBcopy);
6154
6155         if (req->wct < 3) {
6156                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6157                 END_PROFILE(SMBcopy);
6158                 return;
6159         }
6160
6161         tid2 = SVAL(req->vwv+0, 0);
6162         ofun = SVAL(req->vwv+1, 0);
6163         flags = SVAL(req->vwv+2, 0);
6164
6165         p = (const char *)req->buf;
6166         p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6167                                        &status, &source_has_wild);
6168         if (!NT_STATUS_IS_OK(status)) {
6169                 reply_nterror(req, status);
6170                 END_PROFILE(SMBcopy);
6171                 return;
6172         }
6173         p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6174                                        &status, &dest_has_wild);
6175         if (!NT_STATUS_IS_OK(status)) {
6176                 reply_nterror(req, status);
6177                 END_PROFILE(SMBcopy);
6178                 return;
6179         }
6180
6181         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6182
6183         if (tid2 != conn->cnum) {
6184                 /* can't currently handle inter share copies XXXX */
6185                 DEBUG(3,("Rejecting inter-share copy\n"));
6186                 reply_doserror(req, ERRSRV, ERRinvdevice);
6187                 END_PROFILE(SMBcopy);
6188                 return;
6189         }
6190
6191         status = resolve_dfspath_wcard(ctx, conn,
6192                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6193                                        name,
6194                                        &name,
6195                                        &source_has_wild);
6196         if (!NT_STATUS_IS_OK(status)) {
6197                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6198                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6199                                         ERRSRV, ERRbadpath);
6200                         END_PROFILE(SMBcopy);
6201                         return;
6202                 }
6203                 reply_nterror(req, status);
6204                 END_PROFILE(SMBcopy);
6205                 return;
6206         }
6207
6208         status = resolve_dfspath_wcard(ctx, conn,
6209                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6210                                        newname,
6211                                        &newname,
6212                                        &dest_has_wild);
6213         if (!NT_STATUS_IS_OK(status)) {
6214                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6215                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6216                                         ERRSRV, ERRbadpath);
6217                         END_PROFILE(SMBcopy);
6218                         return;
6219                 }
6220                 reply_nterror(req, status);
6221                 END_PROFILE(SMBcopy);
6222                 return;
6223         }
6224
6225         status = unix_convert(ctx, conn, name, source_has_wild,
6226                         &name, NULL, &sbuf1);
6227         if (!NT_STATUS_IS_OK(status)) {
6228                 reply_nterror(req, status);
6229                 END_PROFILE(SMBcopy);
6230                 return;
6231         }
6232
6233         status = unix_convert(ctx, conn, newname, dest_has_wild,
6234                         &newname, NULL, &sbuf2);
6235         if (!NT_STATUS_IS_OK(status)) {
6236                 reply_nterror(req, status);
6237                 END_PROFILE(SMBcopy);
6238                 return;
6239         }
6240
6241         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6242
6243         if ((flags&1) && target_is_directory) {
6244                 reply_doserror(req, ERRDOS, ERRbadfile);
6245                 END_PROFILE(SMBcopy);
6246                 return;
6247         }
6248
6249         if ((flags&2) && !target_is_directory) {
6250                 reply_doserror(req, ERRDOS, ERRbadpath);
6251                 END_PROFILE(SMBcopy);
6252                 return;
6253         }
6254
6255         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6256                 /* wants a tree copy! XXXX */
6257                 DEBUG(3,("Rejecting tree copy\n"));
6258                 reply_doserror(req, ERRSRV, ERRerror);
6259                 END_PROFILE(SMBcopy);
6260                 return;
6261         }
6262
6263         p = strrchr_m(name,'/');
6264         if (p != NULL) {
6265                 directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
6266                 mask = p+1;
6267         } else {
6268                 directory = talloc_strdup(ctx, "./");
6269                 mask = name;
6270         }
6271
6272         if (!directory) {
6273                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6274                 END_PROFILE(SMBcopy);
6275                 return;
6276         }
6277
6278         /*
6279          * We should only check the mangled cache
6280          * here if unix_convert failed. This means
6281          * that the path in 'mask' doesn't exist
6282          * on the file system and so we need to look
6283          * for a possible mangle. This patch from
6284          * Tine Smukavec <valentin.smukavec@hermes.si>.
6285          */
6286
6287         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6288                 char *new_mask = NULL;
6289                 mangle_lookup_name_from_8_3(ctx,
6290                                         mask,
6291                                         &new_mask,
6292                                         conn->params );
6293                 if (new_mask) {
6294                         mask = new_mask;
6295                 }
6296         }
6297
6298         if (!source_has_wild) {
6299                 directory = talloc_asprintf_append(directory,
6300                                 "/%s",
6301                                 mask);
6302                 if (dest_has_wild) {
6303                         char *mod_newname = NULL;
6304                         if (!resolve_wildcards(ctx,
6305                                         directory,newname,&mod_newname)) {
6306                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6307                                 END_PROFILE(SMBcopy);
6308                                 return;
6309                         }
6310                         newname = mod_newname;
6311                 }
6312
6313                 status = check_name(conn, directory);
6314                 if (!NT_STATUS_IS_OK(status)) {
6315                         reply_nterror(req, status);
6316                         END_PROFILE(SMBcopy);
6317                         return;
6318                 }
6319
6320                 status = check_name(conn, newname);
6321                 if (!NT_STATUS_IS_OK(status)) {
6322                         reply_nterror(req, status);
6323                         END_PROFILE(SMBcopy);
6324                         return;
6325                 }
6326
6327                 status = copy_file(ctx,conn,directory,newname,ofun,
6328                                 count,target_is_directory);
6329
6330                 if(!NT_STATUS_IS_OK(status)) {
6331                         reply_nterror(req, status);
6332                         END_PROFILE(SMBcopy);
6333                         return;
6334                 } else {
6335                         count++;
6336                 }
6337         } else {
6338                 struct smb_Dir *dir_hnd = NULL;
6339                 const char *dname = NULL;
6340                 long offset = 0;
6341
6342                 if (strequal(mask,"????????.???")) {
6343                         mask = mask_star;
6344                 }
6345
6346                 status = check_name(conn, directory);
6347                 if (!NT_STATUS_IS_OK(status)) {
6348                         reply_nterror(req, status);
6349                         END_PROFILE(SMBcopy);
6350                         return;
6351                 }
6352
6353                 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6354                 if (dir_hnd == NULL) {
6355                         status = map_nt_error_from_unix(errno);
6356                         reply_nterror(req, status);
6357                         END_PROFILE(SMBcopy);
6358                         return;
6359                 }
6360
6361                 error = ERRbadfile;
6362
6363                 while ((dname = ReadDirName(dir_hnd, &offset))) {
6364                         char *destname = NULL;
6365                         char *fname = NULL;
6366
6367                         if (ISDOT(dname) || ISDOTDOT(dname)) {
6368                                 continue;
6369                         }
6370
6371                         if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6372                                 continue;
6373                         }
6374
6375                         if(!mask_match(dname, mask, conn->case_sensitive)) {
6376                                 continue;
6377                         }
6378
6379                         error = ERRnoaccess;
6380                         fname = talloc_asprintf(ctx,
6381                                         "%s/%s",
6382                                         directory,
6383                                         dname);
6384                         if (!fname) {
6385                                 TALLOC_FREE(dir_hnd);
6386                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6387                                 END_PROFILE(SMBcopy);
6388                                 return;
6389                         }
6390
6391                         if (!resolve_wildcards(ctx,
6392                                         fname,newname,&destname)) {
6393                                 continue;
6394                         }
6395                         if (!destname) {
6396                                 TALLOC_FREE(dir_hnd);
6397                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6398                                 END_PROFILE(SMBcopy);
6399                                 return;
6400                         }
6401
6402                         status = check_name(conn, fname);
6403                         if (!NT_STATUS_IS_OK(status)) {
6404                                 TALLOC_FREE(dir_hnd);
6405                                 reply_nterror(req, status);
6406                                 END_PROFILE(SMBcopy);
6407                                 return;
6408                         }
6409
6410                         status = check_name(conn, destname);
6411                         if (!NT_STATUS_IS_OK(status)) {
6412                                 TALLOC_FREE(dir_hnd);
6413                                 reply_nterror(req, status);
6414                                 END_PROFILE(SMBcopy);
6415                                 return;
6416                         }
6417
6418                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6419
6420                         status = copy_file(ctx,conn,fname,destname,ofun,
6421                                         count,target_is_directory);
6422                         if (NT_STATUS_IS_OK(status)) {
6423                                 count++;
6424                         }
6425                         TALLOC_FREE(fname);
6426                         TALLOC_FREE(destname);
6427                 }
6428                 TALLOC_FREE(dir_hnd);
6429         }
6430
6431         if (count == 0) {
6432                 if(err) {
6433                         /* Error on close... */
6434                         errno = err;
6435                         reply_unixerror(req, ERRHRD, ERRgeneral);
6436                         END_PROFILE(SMBcopy);
6437                         return;
6438                 }
6439
6440                 reply_doserror(req, ERRDOS, error);
6441                 END_PROFILE(SMBcopy);
6442                 return;
6443         }
6444
6445         reply_outbuf(req, 1, 0);
6446         SSVAL(req->outbuf,smb_vwv0,count);
6447
6448         END_PROFILE(SMBcopy);
6449         return;
6450 }
6451
6452 #undef DBGC_CLASS
6453 #define DBGC_CLASS DBGC_LOCKING
6454
6455 /****************************************************************************
6456  Get a lock pid, dealing with large count requests.
6457 ****************************************************************************/
6458
6459 uint32 get_lock_pid(const uint8_t *data, int data_offset,
6460                     bool large_file_format)
6461 {
6462         if(!large_file_format)
6463                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6464         else
6465                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6466 }
6467
6468 /****************************************************************************
6469  Get a lock count, dealing with large count requests.
6470 ****************************************************************************/
6471
6472 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6473                         bool large_file_format)
6474 {
6475         uint64_t count = 0;
6476
6477         if(!large_file_format) {
6478                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6479         } else {
6480
6481 #if defined(HAVE_LONGLONG)
6482                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6483                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6484 #else /* HAVE_LONGLONG */
6485
6486                 /*
6487                  * NT4.x seems to be broken in that it sends large file (64 bit)
6488                  * lockingX calls even if the CAP_LARGE_FILES was *not*
6489                  * negotiated. For boxes without large unsigned ints truncate the
6490                  * lock count by dropping the top 32 bits.
6491                  */
6492
6493                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6494                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6495                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6496                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6497                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6498                 }
6499
6500                 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6501 #endif /* HAVE_LONGLONG */
6502         }
6503
6504         return count;
6505 }
6506
6507 #if !defined(HAVE_LONGLONG)
6508 /****************************************************************************
6509  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6510 ****************************************************************************/
6511
6512 static uint32 map_lock_offset(uint32 high, uint32 low)
6513 {
6514         unsigned int i;
6515         uint32 mask = 0;
6516         uint32 highcopy = high;
6517
6518         /*
6519          * Try and find out how many significant bits there are in high.
6520          */
6521
6522         for(i = 0; highcopy; i++)
6523                 highcopy >>= 1;
6524
6525         /*
6526          * We use 31 bits not 32 here as POSIX
6527          * lock offsets may not be negative.
6528          */
6529
6530         mask = (~0) << (31 - i);
6531
6532         if(low & mask)
6533                 return 0; /* Fail. */
6534
6535         high <<= (31 - i);
6536
6537         return (high|low);
6538 }
6539 #endif /* !defined(HAVE_LONGLONG) */
6540
6541 /****************************************************************************
6542  Get a lock offset, dealing with large offset requests.
6543 ****************************************************************************/
6544
6545 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6546                          bool large_file_format, bool *err)
6547 {
6548         uint64_t offset = 0;
6549
6550         *err = False;
6551
6552         if(!large_file_format) {
6553                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6554         } else {
6555
6556 #if defined(HAVE_LONGLONG)
6557                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6558                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6559 #else /* HAVE_LONGLONG */
6560
6561                 /*
6562                  * NT4.x seems to be broken in that it sends large file (64 bit)
6563                  * lockingX calls even if the CAP_LARGE_FILES was *not*
6564                  * negotiated. For boxes without large unsigned ints mangle the
6565                  * lock offset by mapping the top 32 bits onto the lower 32.
6566                  */
6567
6568                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6569                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6570                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6571                         uint32 new_low = 0;
6572
6573                         if((new_low = map_lock_offset(high, low)) == 0) {
6574                                 *err = True;
6575                                 return (uint64_t)-1;
6576                         }
6577
6578                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6579                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6580                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6581                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6582                 }
6583
6584                 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6585 #endif /* HAVE_LONGLONG */
6586         }
6587
6588         return offset;
6589 }
6590
6591 /****************************************************************************
6592  Reply to a lockingX request.
6593 ****************************************************************************/
6594
6595 void reply_lockingX(struct smb_request *req)
6596 {
6597         connection_struct *conn = req->conn;
6598         files_struct *fsp;
6599         unsigned char locktype;
6600         unsigned char oplocklevel;
6601         uint16 num_ulocks;
6602         uint16 num_locks;
6603         uint64_t count = 0, offset = 0;
6604         uint32 lock_pid;
6605         int32 lock_timeout;
6606         int i;
6607         const uint8_t *data;
6608         bool large_file_format;
6609         bool err;
6610         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6611
6612         START_PROFILE(SMBlockingX);
6613
6614         if (req->wct < 8) {
6615                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6616                 END_PROFILE(SMBlockingX);
6617                 return;
6618         }
6619
6620         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6621         locktype = CVAL(req->vwv+3, 0);
6622         oplocklevel = CVAL(req->vwv+3, 1);
6623         num_ulocks = SVAL(req->vwv+6, 0);
6624         num_locks = SVAL(req->vwv+7, 0);
6625         lock_timeout = IVAL(req->vwv+4, 0);
6626         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6627
6628         if (!check_fsp(conn, req, fsp)) {
6629                 END_PROFILE(SMBlockingX);
6630                 return;
6631         }
6632
6633         data = req->buf;
6634
6635         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6636                 /* we don't support these - and CANCEL_LOCK makes w2k
6637                    and XP reboot so I don't really want to be
6638                    compatible! (tridge) */
6639                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6640                 END_PROFILE(SMBlockingX);
6641                 return;
6642         }
6643
6644         /* Check if this is an oplock break on a file
6645            we have granted an oplock on.
6646         */
6647         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6648                 /* Client can insist on breaking to none. */
6649                 bool break_to_none = (oplocklevel == 0);
6650                 bool result;
6651
6652                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6653                          "for fnum = %d\n", (unsigned int)oplocklevel,
6654                          fsp->fnum ));
6655
6656                 /*
6657                  * Make sure we have granted an exclusive or batch oplock on
6658                  * this file.
6659                  */
6660
6661                 if (fsp->oplock_type == 0) {
6662
6663                         /* The Samba4 nbench simulator doesn't understand
6664                            the difference between break to level2 and break
6665                            to none from level2 - it sends oplock break
6666                            replies in both cases. Don't keep logging an error
6667                            message here - just ignore it. JRA. */
6668
6669                         DEBUG(5,("reply_lockingX: Error : oplock break from "
6670                                  "client for fnum = %d (oplock=%d) and no "
6671                                  "oplock granted on this file (%s).\n",
6672                                  fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6673
6674                         /* if this is a pure oplock break request then don't
6675                          * send a reply */
6676                         if (num_locks == 0 && num_ulocks == 0) {
6677                                 END_PROFILE(SMBlockingX);
6678                                 return;
6679                         } else {
6680                                 END_PROFILE(SMBlockingX);
6681                                 reply_doserror(req, ERRDOS, ERRlock);
6682                                 return;
6683                         }
6684                 }
6685
6686                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6687                     (break_to_none)) {
6688                         result = remove_oplock(fsp);
6689                 } else {
6690                         result = downgrade_oplock(fsp);
6691                 }
6692
6693                 if (!result) {
6694                         DEBUG(0, ("reply_lockingX: error in removing "
6695                                   "oplock on file %s\n", fsp->fsp_name));
6696                         /* Hmmm. Is this panic justified? */
6697                         smb_panic("internal tdb error");
6698                 }
6699
6700                 reply_to_oplock_break_requests(fsp);
6701
6702                 /* if this is a pure oplock break request then don't send a
6703                  * reply */
6704                 if (num_locks == 0 && num_ulocks == 0) {
6705                         /* Sanity check - ensure a pure oplock break is not a
6706                            chained request. */
6707                         if(CVAL(req->vwv+0, 0) != 0xff)
6708                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
6709                                          "break is a chained %d request !\n",
6710                                          (unsigned int)CVAL(req->vwv+0, 0)));
6711                         END_PROFILE(SMBlockingX);
6712                         return;
6713                 }
6714         }
6715
6716         /*
6717          * We do this check *after* we have checked this is not a oplock break
6718          * response message. JRA.
6719          */
6720
6721         release_level_2_oplocks_on_change(fsp);
6722
6723         if (req->buflen <
6724             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6725                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6726                 END_PROFILE(SMBlockingX);
6727                 return;
6728         }
6729
6730         /* Data now points at the beginning of the list
6731            of smb_unlkrng structs */
6732         for(i = 0; i < (int)num_ulocks; i++) {
6733                 lock_pid = get_lock_pid( data, i, large_file_format);
6734                 count = get_lock_count( data, i, large_file_format);
6735                 offset = get_lock_offset( data, i, large_file_format, &err);
6736
6737                 /*
6738                  * There is no error code marked "stupid client bug".... :-).
6739                  */
6740                 if(err) {
6741                         END_PROFILE(SMBlockingX);
6742                         reply_doserror(req, ERRDOS, ERRnoaccess);
6743                         return;
6744                 }
6745
6746                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6747                           "pid %u, file %s\n", (double)offset, (double)count,
6748                           (unsigned int)lock_pid, fsp->fsp_name ));
6749
6750                 status = do_unlock(smbd_messaging_context(),
6751                                 fsp,
6752                                 lock_pid,
6753                                 count,
6754                                 offset,
6755                                 WINDOWS_LOCK);
6756
6757                 if (NT_STATUS_V(status)) {
6758                         END_PROFILE(SMBlockingX);
6759                         reply_nterror(req, status);
6760                         return;
6761                 }
6762         }
6763
6764         /* Setup the timeout in seconds. */
6765
6766         if (!lp_blocking_locks(SNUM(conn))) {
6767                 lock_timeout = 0;
6768         }
6769
6770         /* Now do any requested locks */
6771         data += ((large_file_format ? 20 : 10)*num_ulocks);
6772
6773         /* Data now points at the beginning of the list
6774            of smb_lkrng structs */
6775
6776         for(i = 0; i < (int)num_locks; i++) {
6777                 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6778                                 READ_LOCK:WRITE_LOCK);
6779                 lock_pid = get_lock_pid( data, i, large_file_format);
6780                 count = get_lock_count( data, i, large_file_format);
6781                 offset = get_lock_offset( data, i, large_file_format, &err);
6782
6783                 /*
6784                  * There is no error code marked "stupid client bug".... :-).
6785                  */
6786                 if(err) {
6787                         END_PROFILE(SMBlockingX);
6788                         reply_doserror(req, ERRDOS, ERRnoaccess);
6789                         return;
6790                 }
6791
6792                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6793                           "%u, file %s timeout = %d\n", (double)offset,
6794                           (double)count, (unsigned int)lock_pid,
6795                           fsp->fsp_name, (int)lock_timeout ));
6796
6797                 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6798                         if (lp_blocking_locks(SNUM(conn))) {
6799
6800                                 /* Schedule a message to ourselves to
6801                                    remove the blocking lock record and
6802                                    return the right error. */
6803
6804                                 if (!blocking_lock_cancel(fsp,
6805                                                 lock_pid,
6806                                                 offset,
6807                                                 count,
6808                                                 WINDOWS_LOCK,
6809                                                 locktype,
6810                                                 NT_STATUS_FILE_LOCK_CONFLICT)) {
6811                                         END_PROFILE(SMBlockingX);
6812                                         reply_nterror(
6813                                                 req,
6814                                                 NT_STATUS_DOS(
6815                                                         ERRDOS,
6816                                                         ERRcancelviolation));
6817                                         return;
6818                                 }
6819                         }
6820                         /* Remove a matching pending lock. */
6821                         status = do_lock_cancel(fsp,
6822                                                 lock_pid,
6823                                                 count,
6824                                                 offset,
6825                                                 WINDOWS_LOCK);
6826                 } else {
6827                         bool blocking_lock = lock_timeout ? True : False;
6828                         bool defer_lock = False;
6829                         struct byte_range_lock *br_lck;
6830                         uint32 block_smbpid;
6831
6832                         br_lck = do_lock(smbd_messaging_context(),
6833                                         fsp,
6834                                         lock_pid,
6835                                         count,
6836                                         offset, 
6837                                         lock_type,
6838                                         WINDOWS_LOCK,
6839                                         blocking_lock,
6840                                         &status,
6841                                         &block_smbpid);
6842
6843                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6844                                 /* Windows internal resolution for blocking locks seems
6845                                    to be about 200ms... Don't wait for less than that. JRA. */
6846                                 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6847                                         lock_timeout = lp_lock_spin_time();
6848                                 }
6849                                 defer_lock = True;
6850                         }
6851
6852                         /* This heuristic seems to match W2K3 very well. If a
6853                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6854                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
6855                            far as I can tell. Replacement for do_lock_spin(). JRA. */
6856
6857                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6858                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6859                                 defer_lock = True;
6860                                 lock_timeout = lp_lock_spin_time();
6861                         }
6862
6863                         if (br_lck && defer_lock) {
6864                                 /*
6865                                  * A blocking lock was requested. Package up
6866                                  * this smb into a queued request and push it
6867                                  * onto the blocking lock queue.
6868                                  */
6869                                 if(push_blocking_lock_request(br_lck,
6870                                                         req,
6871                                                         fsp,
6872                                                         lock_timeout,
6873                                                         i,
6874                                                         lock_pid,
6875                                                         lock_type,
6876                                                         WINDOWS_LOCK,
6877                                                         offset,
6878                                                         count,
6879                                                         block_smbpid)) {
6880                                         TALLOC_FREE(br_lck);
6881                                         END_PROFILE(SMBlockingX);
6882                                         return;
6883                                 }
6884                         }
6885
6886                         TALLOC_FREE(br_lck);
6887                 }
6888
6889                 if (NT_STATUS_V(status)) {
6890                         END_PROFILE(SMBlockingX);
6891                         reply_nterror(req, status);
6892                         return;
6893                 }
6894         }
6895
6896         /* If any of the above locks failed, then we must unlock
6897            all of the previous locks (X/Open spec). */
6898
6899         if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6900                         (i != num_locks) &&
6901                         (num_locks != 0)) {
6902                 /*
6903                  * Ensure we don't do a remove on the lock that just failed,
6904                  * as under POSIX rules, if we have a lock already there, we
6905                  * will delete it (and we shouldn't) .....
6906                  */
6907                 for(i--; i >= 0; i--) {
6908                         lock_pid = get_lock_pid( data, i, large_file_format);
6909                         count = get_lock_count( data, i, large_file_format);
6910                         offset = get_lock_offset( data, i, large_file_format,
6911                                                   &err);
6912
6913                         /*
6914                          * There is no error code marked "stupid client
6915                          * bug".... :-).
6916                          */
6917                         if(err) {
6918                                 END_PROFILE(SMBlockingX);
6919                                 reply_doserror(req, ERRDOS, ERRnoaccess);
6920                                 return;
6921                         }
6922
6923                         do_unlock(smbd_messaging_context(),
6924                                 fsp,
6925                                 lock_pid,
6926                                 count,
6927                                 offset,
6928                                 WINDOWS_LOCK);
6929                 }
6930                 END_PROFILE(SMBlockingX);
6931                 reply_nterror(req, status);
6932                 return;
6933         }
6934
6935         reply_outbuf(req, 2, 0);
6936
6937         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
6938                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
6939
6940         END_PROFILE(SMBlockingX);
6941         chain_reply(req);
6942 }
6943
6944 #undef DBGC_CLASS
6945 #define DBGC_CLASS DBGC_ALL
6946
6947 /****************************************************************************
6948  Reply to a SMBreadbmpx (read block multiplex) request.
6949  Always reply with an error, if someone has a platform really needs this,
6950  please contact vl@samba.org
6951 ****************************************************************************/
6952
6953 void reply_readbmpx(struct smb_request *req)
6954 {
6955         START_PROFILE(SMBreadBmpx);
6956         reply_doserror(req, ERRSRV, ERRuseSTD);
6957         END_PROFILE(SMBreadBmpx);
6958         return;
6959 }
6960
6961 /****************************************************************************
6962  Reply to a SMBreadbs (read block multiplex secondary) request.
6963  Always reply with an error, if someone has a platform really needs this,
6964  please contact vl@samba.org
6965 ****************************************************************************/
6966
6967 void reply_readbs(struct smb_request *req)
6968 {
6969         START_PROFILE(SMBreadBs);
6970         reply_doserror(req, ERRSRV, ERRuseSTD);
6971         END_PROFILE(SMBreadBs);
6972         return;
6973 }
6974
6975 /****************************************************************************
6976  Reply to a SMBsetattrE.
6977 ****************************************************************************/
6978
6979 void reply_setattrE(struct smb_request *req)
6980 {
6981         connection_struct *conn = req->conn;
6982         struct timespec ts[2];
6983         files_struct *fsp;
6984         SMB_STRUCT_STAT sbuf;
6985         NTSTATUS status;
6986
6987         START_PROFILE(SMBsetattrE);
6988
6989         if (req->wct < 7) {
6990                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6991                 END_PROFILE(SMBsetattrE);
6992                 return;
6993         }
6994
6995         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6996
6997         if(!fsp || (fsp->conn != conn)) {
6998                 reply_doserror(req, ERRDOS, ERRbadfid);
6999                 END_PROFILE(SMBsetattrE);
7000                 return;
7001         }
7002
7003
7004         /*
7005          * Convert the DOS times into unix times. Ignore create
7006          * time as UNIX can't set this.
7007          */
7008
7009         ts[0] = convert_time_t_to_timespec(
7010                 srv_make_unix_date2(req->vwv+3)); /* atime. */
7011         ts[1] = convert_time_t_to_timespec(
7012                 srv_make_unix_date2(req->vwv+5)); /* mtime. */
7013
7014         reply_outbuf(req, 0, 0);
7015
7016         /* 
7017          * Patch from Ray Frush <frush@engr.colostate.edu>
7018          * Sometimes times are sent as zero - ignore them.
7019          */
7020
7021         /* Ensure we have a valid stat struct for the source. */
7022         if (fsp->fh->fd != -1) {
7023                 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7024                         status = map_nt_error_from_unix(errno);
7025                         reply_nterror(req, status);
7026                         END_PROFILE(SMBsetattrE);
7027                         return;
7028                 }
7029         } else {
7030                 if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) {
7031                         status = map_nt_error_from_unix(errno);
7032                         reply_nterror(req, status);
7033                         END_PROFILE(SMBsetattrE);
7034                         return;
7035                 }
7036         }
7037
7038         status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7039                                    &sbuf, ts, true);
7040         if (!NT_STATUS_IS_OK(status)) {
7041                 reply_doserror(req, ERRDOS, ERRnoaccess);
7042                 END_PROFILE(SMBsetattrE);
7043                 return;
7044         }
7045
7046         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7047                 fsp->fnum,
7048                 (unsigned int)ts[0].tv_sec,
7049                 (unsigned int)ts[1].tv_sec));
7050
7051         END_PROFILE(SMBsetattrE);
7052         return;
7053 }
7054
7055
7056 /* Back from the dead for OS/2..... JRA. */
7057
7058 /****************************************************************************
7059  Reply to a SMBwritebmpx (write block multiplex primary) request.
7060  Always reply with an error, if someone has a platform really needs this,
7061  please contact vl@samba.org
7062 ****************************************************************************/
7063
7064 void reply_writebmpx(struct smb_request *req)
7065 {
7066         START_PROFILE(SMBwriteBmpx);
7067         reply_doserror(req, ERRSRV, ERRuseSTD);
7068         END_PROFILE(SMBwriteBmpx);
7069         return;
7070 }
7071
7072 /****************************************************************************
7073  Reply to a SMBwritebs (write block multiplex secondary) request.
7074  Always reply with an error, if someone has a platform really needs this,
7075  please contact vl@samba.org
7076 ****************************************************************************/
7077
7078 void reply_writebs(struct smb_request *req)
7079 {
7080         START_PROFILE(SMBwriteBs);
7081         reply_doserror(req, ERRSRV, ERRuseSTD);
7082         END_PROFILE(SMBwriteBs);
7083         return;
7084 }
7085
7086 /****************************************************************************
7087  Reply to a SMBgetattrE.
7088 ****************************************************************************/
7089
7090 void reply_getattrE(struct smb_request *req)
7091 {
7092         connection_struct *conn = req->conn;
7093         SMB_STRUCT_STAT sbuf;
7094         int mode;
7095         files_struct *fsp;
7096         struct timespec create_ts;
7097
7098         START_PROFILE(SMBgetattrE);
7099
7100         if (req->wct < 1) {
7101                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7102                 END_PROFILE(SMBgetattrE);
7103                 return;
7104         }
7105
7106         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7107
7108         if(!fsp || (fsp->conn != conn)) {
7109                 reply_doserror(req, ERRDOS, ERRbadfid);
7110                 END_PROFILE(SMBgetattrE);
7111                 return;
7112         }
7113
7114         /* Do an fstat on this file */
7115         if(fsp_stat(fsp, &sbuf)) {
7116                 reply_unixerror(req, ERRDOS, ERRnoaccess);
7117                 END_PROFILE(SMBgetattrE);
7118                 return;
7119         }
7120
7121         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7122
7123         /*
7124          * Convert the times into dos times. Set create
7125          * date to be last modify date as UNIX doesn't save
7126          * this.
7127          */
7128
7129         reply_outbuf(req, 11, 0);
7130
7131         create_ts = get_create_timespec(&sbuf,
7132                                   lp_fake_dir_create_times(SNUM(conn)));
7133         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7134         srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7135         /* Should we check pending modtime here ? JRA */
7136         srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7137
7138         if (mode & aDIR) {
7139                 SIVAL(req->outbuf, smb_vwv6, 0);
7140                 SIVAL(req->outbuf, smb_vwv8, 0);
7141         } else {
7142                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
7143                 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7144                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7145         }
7146         SSVAL(req->outbuf,smb_vwv10, mode);
7147
7148         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7149
7150         END_PROFILE(SMBgetattrE);
7151         return;
7152 }