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