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