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