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