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