Re-enable async I/O for non-TSM systems
[samba.git] / source / smbd / reply.c
1 /*
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_recv;
32 unsigned int smb_echo_count = 0;
33 extern uint32 global_client_caps;
34
35 extern struct current_user current_user;
36 extern bool global_encrypted_passwords_negotiated;
37
38 /****************************************************************************
39  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
40  path or anything including wildcards.
41  We're assuming here that '/' is not the second byte in any multibyte char
42  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
43  set.
44 ****************************************************************************/
45
46 /* Custom version for processing POSIX paths. */
47 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
48
49 static NTSTATUS check_path_syntax_internal(char *path,
50                                            bool posix_path,
51                                            bool *p_last_component_contains_wcard)
52 {
53         char *d = path;
54         const char *s = path;
55         NTSTATUS ret = NT_STATUS_OK;
56         bool start_of_name_component = True;
57
58         *p_last_component_contains_wcard = False;
59
60         while (*s) {
61                 if (IS_PATH_SEP(*s,posix_path)) {
62                         /*
63                          * Safe to assume is not the second part of a mb char
64                          * as this is handled below.
65                          */
66                         /* Eat multiple '/' or '\\' */
67                         while (IS_PATH_SEP(*s,posix_path)) {
68                                 s++;
69                         }
70                         if ((d != path) && (*s != '\0')) {
71                                 /* We only care about non-leading or trailing '/' or '\\' */
72                                 *d++ = '/';
73                         }
74
75                         start_of_name_component = True;
76                         /* New component. */
77                         *p_last_component_contains_wcard = False;
78                         continue;
79                 }
80
81                 if (start_of_name_component) {
82                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
83                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
84
85                                 /*
86                                  * No mb char starts with '.' so we're safe checking the directory separator here.
87                                  */
88
89                                 /* If  we just added a '/' - delete it */
90                                 if ((d > path) && (*(d-1) == '/')) {
91                                         *(d-1) = '\0';
92                                         d--;
93                                 }
94
95                                 /* Are we at the start ? Can't go back further if so. */
96                                 if (d <= path) {
97                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
98                                         break;
99                                 }
100                                 /* Go back one level... */
101                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
102                                 /* NOTE - if this assumption is invalid we are not in good shape... */
103                                 /* Decrement d first as d points to the *next* char to write into. */
104                                 for (d--; d > path; d--) {
105                                         if (*d == '/')
106                                                 break;
107                                 }
108                                 s += 2; /* Else go past the .. */
109                                 /* We're still at the start of a name component, just the previous one. */
110                                 continue;
111
112                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
113                                 if (posix_path) {
114                                         /* Eat the '.' */
115                                         s++;
116                                         continue;
117                                 }
118                         }
119
120                 }
121
122                 if (!(*s & 0x80)) {
123                         if (!posix_path) {
124                                 if (*s <= 0x1f) {
125                                         return NT_STATUS_OBJECT_NAME_INVALID;
126                                 }
127                                 switch (*s) {
128                                         case '*':
129                                         case '?':
130                                         case '<':
131                                         case '>':
132                                         case '"':
133                                                 *p_last_component_contains_wcard = True;
134                                                 break;
135                                         default:
136                                                 break;
137                                 }
138                         }
139                         *d++ = *s++;
140                 } else {
141                         size_t siz;
142                         /* Get the size of the next MB character. */
143                         next_codepoint(s,&siz);
144                         switch(siz) {
145                                 case 5:
146                                         *d++ = *s++;
147                                         /*fall through*/
148                                 case 4:
149                                         *d++ = *s++;
150                                         /*fall through*/
151                                 case 3:
152                                         *d++ = *s++;
153                                         /*fall through*/
154                                 case 2:
155                                         *d++ = *s++;
156                                         /*fall through*/
157                                 case 1:
158                                         *d++ = *s++;
159                                         break;
160                                 default:
161                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
162                                         *d = '\0';
163                                         return NT_STATUS_INVALID_PARAMETER;
164                         }
165                 }
166                 start_of_name_component = False;
167         }
168
169         *d = '\0';
170
171         return ret;
172 }
173
174 /****************************************************************************
175  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
176  No wildcards allowed.
177 ****************************************************************************/
178
179 NTSTATUS check_path_syntax(char *path)
180 {
181         bool ignore;
182         return check_path_syntax_internal(path, False, &ignore);
183 }
184
185 /****************************************************************************
186  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
187  Wildcards allowed - p_contains_wcard returns true if the last component contained
188  a wildcard.
189 ****************************************************************************/
190
191 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
192 {
193         return check_path_syntax_internal(path, False, p_contains_wcard);
194 }
195
196 /****************************************************************************
197  Check the path for a POSIX client.
198  We're assuming here that '/' is not the second byte in any multibyte char
199  set (a safe assumption).
200 ****************************************************************************/
201
202 NTSTATUS check_path_syntax_posix(char *path)
203 {
204         bool ignore;
205         return check_path_syntax_internal(path, True, &ignore);
206 }
207
208 /****************************************************************************
209  Pull a string and check the path allowing a wilcard - provide for error return.
210 ****************************************************************************/
211
212 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
213                         const char *inbuf,
214                         uint16 smb_flags2,
215                         char **pp_dest,
216                         const char *src,
217                         size_t src_len,
218                         int flags,
219                         NTSTATUS *err,
220                         bool *contains_wcard)
221 {
222         size_t ret;
223
224         *pp_dest = NULL;
225
226         if (src_len == 0) {
227                 ret = srvstr_pull_buf_talloc(ctx,
228                                 inbuf,
229                                 smb_flags2,
230                                 pp_dest,
231                                 src,
232                                 flags);
233         } else {
234                 ret = srvstr_pull_talloc(ctx,
235                                 inbuf,
236                                 smb_flags2,
237                                 pp_dest,
238                                 src,
239                                 src_len,
240                                 flags);
241         }
242
243         if (!*pp_dest) {
244                 *err = NT_STATUS_INVALID_PARAMETER;
245                 return ret;
246         }
247
248         *contains_wcard = False;
249
250         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
251                 /*
252                  * For a DFS path the function parse_dfs_path()
253                  * will do the path processing, just make a copy.
254                  */
255                 *err = NT_STATUS_OK;
256                 return ret;
257         }
258
259         if (lp_posix_pathnames()) {
260                 *err = check_path_syntax_posix(*pp_dest);
261         } else {
262                 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
263         }
264
265         return ret;
266 }
267
268 /****************************************************************************
269  Pull a string and check the path - provide for error return.
270 ****************************************************************************/
271
272 size_t srvstr_get_path(TALLOC_CTX *ctx,
273                         const char *inbuf,
274                         uint16 smb_flags2,
275                         char **pp_dest,
276                         const char *src,
277                         size_t src_len,
278                         int flags,
279                         NTSTATUS *err)
280 {
281         size_t ret;
282
283         *pp_dest = NULL;
284
285         if (src_len == 0) {
286                 ret = srvstr_pull_buf_talloc(ctx,
287                                         inbuf,
288                                         smb_flags2,
289                                         pp_dest,
290                                         src,
291                                         flags);
292         } else {
293                 ret = srvstr_pull_talloc(ctx,
294                                 inbuf,
295                                 smb_flags2,
296                                 pp_dest,
297                                 src,
298                                 src_len,
299                                 flags);
300         }
301
302         if (!*pp_dest) {
303                 *err = NT_STATUS_INVALID_PARAMETER;
304                 return ret;
305         }
306
307         if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
308                 /*
309                  * For a DFS path the function parse_dfs_path()
310                  * will do the path processing, just make a copy.
311                  */
312                 *err = NT_STATUS_OK;
313                 return ret;
314         }
315
316         if (lp_posix_pathnames()) {
317                 *err = check_path_syntax_posix(*pp_dest);
318         } else {
319                 *err = check_path_syntax(*pp_dest);
320         }
321
322         return ret;
323 }
324
325 /****************************************************************************
326  Check if we have a correct fsp pointing to a file. Basic check for open fsp.
327 ****************************************************************************/
328
329 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
330                files_struct *fsp, struct current_user *user)
331 {
332         if (!(fsp) || !(conn)) {
333                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
334                 return False;
335         }
336         if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) {
337                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
338                 return False;
339         }
340         return True;
341 }
342
343 /****************************************************************************
344  Check if we have a correct fsp pointing to a file. Replacement for the
345  CHECK_FSP macro.
346 ****************************************************************************/
347
348 bool check_fsp(connection_struct *conn, struct smb_request *req,
349                files_struct *fsp, struct current_user *user)
350 {
351         if (!check_fsp_open(conn, req, fsp, user)) {
352                 return False;
353         }
354         if ((fsp)->is_directory) {
355                 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
356                 return False;
357         }
358         if ((fsp)->fh->fd == -1) {
359                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
360                 return False;
361         }
362         (fsp)->num_smb_operations++;
363         return True;
364 }
365
366 /****************************************************************************
367  Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
368 ****************************************************************************/
369
370 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
371                       files_struct *fsp, struct current_user *user)
372 {
373         if ((fsp) && (conn) && ((conn)==(fsp)->conn)
374             && (current_user.vuid==(fsp)->vuid)) {
375                 return True;
376         }
377
378         reply_nterror(req, NT_STATUS_INVALID_HANDLE);
379         return False;
380 }
381
382 /****************************************************************************
383  Reply to a (netbios-level) special message.
384 ****************************************************************************/
385
386 void reply_special(char *inbuf)
387 {
388         int msg_type = CVAL(inbuf,0);
389         int msg_flags = CVAL(inbuf,1);
390         fstring name1,name2;
391         char name_type = 0;
392
393         /*
394          * We only really use 4 bytes of the outbuf, but for the smb_setlen
395          * calculation & friends (srv_send_smb uses that) we need the full smb
396          * header.
397          */
398         char outbuf[smb_size];
399         
400         static bool already_got_session = False;
401
402         *name1 = *name2 = 0;
403         
404         memset(outbuf, '\0', sizeof(outbuf));
405
406         smb_setlen(outbuf,0);
407         
408         switch (msg_type) {
409         case 0x81: /* session request */
410                 
411                 if (already_got_session) {
412                         exit_server_cleanly("multiple session request not permitted");
413                 }
414                 
415                 SCVAL(outbuf,0,0x82);
416                 SCVAL(outbuf,3,0);
417                 if (name_len(inbuf+4) > 50 || 
418                     name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
419                         DEBUG(0,("Invalid name length in session request\n"));
420                         return;
421                 }
422                 name_extract(inbuf,4,name1);
423                 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
424                 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
425                          name1,name2));      
426
427                 set_local_machine_name(name1, True);
428                 set_remote_machine_name(name2, True);
429
430                 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
431                          get_local_machine_name(), get_remote_machine_name(),
432                          name_type));
433
434                 if (name_type == 'R') {
435                         /* We are being asked for a pathworks session --- 
436                            no thanks! */
437                         SCVAL(outbuf, 0,0x83);
438                         break;
439                 }
440
441                 /* only add the client's machine name to the list
442                    of possibly valid usernames if we are operating
443                    in share mode security */
444                 if (lp_security() == SEC_SHARE) {
445                         add_session_user(get_remote_machine_name());
446                 }
447
448                 reload_services(True);
449                 reopen_logs();
450
451                 already_got_session = True;
452                 break;
453                 
454         case 0x89: /* session keepalive request 
455                       (some old clients produce this?) */
456                 SCVAL(outbuf,0,SMBkeepalive);
457                 SCVAL(outbuf,3,0);
458                 break;
459                 
460         case 0x82: /* positive session response */
461         case 0x83: /* negative session response */
462         case 0x84: /* retarget session response */
463                 DEBUG(0,("Unexpected session response\n"));
464                 break;
465                 
466         case SMBkeepalive: /* session keepalive */
467         default:
468                 return;
469         }
470         
471         DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
472                     msg_type, msg_flags));
473
474         srv_send_smb(smbd_server_fd(), outbuf, false);
475         return;
476 }
477
478 /****************************************************************************
479  Reply to a tcon.
480  conn POINTER CAN BE NULL HERE !
481 ****************************************************************************/
482
483 void reply_tcon(struct smb_request *req)
484 {
485         connection_struct *conn = req->conn;
486         const char *service;
487         char *service_buf = NULL;
488         char *password = NULL;
489         char *dev = NULL;
490         int pwlen=0;
491         NTSTATUS nt_status;
492         char *p;
493         DATA_BLOB password_blob;
494         TALLOC_CTX *ctx = talloc_tos();
495
496         START_PROFILE(SMBtcon);
497
498         if (smb_buflen(req->inbuf) < 4) {
499                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
500                 END_PROFILE(SMBtcon);
501                 return;
502         }
503
504         p = smb_buf(req->inbuf)+1;
505         p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
506                                     &service_buf, p, STR_TERMINATE) + 1;
507         pwlen = srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
508                                        &password, p, STR_TERMINATE) + 1;
509         p += pwlen;
510         p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
511                                     &dev, p, STR_TERMINATE) + 1;
512
513         if (service_buf == NULL || password == NULL || dev == NULL) {
514                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
515                 END_PROFILE(SMBtcon);
516                 return;
517         }
518         p = strrchr_m(service_buf,'\\');
519         if (p) {
520                 service = p+1;
521         } else {
522                 service = service_buf;
523         }
524
525         password_blob = data_blob(password, pwlen+1);
526
527         conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
528         req->conn = conn;
529
530         data_blob_clear_free(&password_blob);
531
532         if (!conn) {
533                 reply_nterror(req, nt_status);
534                 END_PROFILE(SMBtcon);
535                 return;
536         }
537
538         reply_outbuf(req, 2, 0);
539         SSVAL(req->outbuf,smb_vwv0,max_recv);
540         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
541         SSVAL(req->outbuf,smb_tid,conn->cnum);
542
543         DEBUG(3,("tcon service=%s cnum=%d\n",
544                  service, conn->cnum));
545
546         END_PROFILE(SMBtcon);
547         return;
548 }
549
550 /****************************************************************************
551  Reply to a tcon and X.
552  conn POINTER CAN BE NULL HERE !
553 ****************************************************************************/
554
555 void reply_tcon_and_X(struct smb_request *req)
556 {
557         connection_struct *conn = req->conn;
558         char *service = NULL;
559         DATA_BLOB password;
560         TALLOC_CTX *ctx = talloc_tos();
561         /* what the cleint thinks the device is */
562         char *client_devicetype = NULL;
563         /* what the server tells the client the share represents */
564         const char *server_devicetype;
565         NTSTATUS nt_status;
566         int passlen;
567         char *path = NULL;
568         char *p, *q;
569         uint16 tcon_flags;
570
571         START_PROFILE(SMBtconX);
572
573         if (req->wct < 4) {
574                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
575                 END_PROFILE(SMBtconX);
576                 return;
577         }
578
579         passlen = SVAL(req->inbuf,smb_vwv3);
580         tcon_flags = SVAL(req->inbuf,smb_vwv2);
581
582         /* we might have to close an old one */
583         if ((tcon_flags & 0x1) && conn) {
584                 close_cnum(conn,req->vuid);
585                 req->conn = NULL;
586                 conn = NULL;
587         }
588
589         if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
590                 reply_doserror(req, ERRDOS, ERRbuftoosmall);
591                 END_PROFILE(SMBtconX);
592                 return;
593         }
594
595         if (global_encrypted_passwords_negotiated) {
596                 password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf),
597                                             passlen);
598                 if (lp_security() == SEC_SHARE) {
599                         /*
600                          * Security = share always has a pad byte
601                          * after the password.
602                          */
603                         p = smb_buf(req->inbuf) + passlen + 1;
604                 } else {
605                         p = smb_buf(req->inbuf) + passlen;
606                 }
607         } else {
608                 password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf),
609                                             passlen+1);
610                 /* Ensure correct termination */
611                 password.data[passlen]=0;
612                 p = smb_buf(req->inbuf) + passlen + 1;
613         }
614
615         p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
616                              STR_TERMINATE);
617
618         if (path == NULL) {
619                 data_blob_clear_free(&password);
620                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
621                 END_PROFILE(SMBtconX);
622                 return;
623         }
624
625         /*
626          * the service name can be either: \\server\share
627          * or share directly like on the DELL PowerVault 705
628          */
629         if (*path=='\\') {
630                 q = strchr_m(path+2,'\\');
631                 if (!q) {
632                         data_blob_clear_free(&password);
633                         reply_doserror(req, ERRDOS, ERRnosuchshare);
634                         END_PROFILE(SMBtconX);
635                         return;
636                 }
637                 service = q+1;
638         } else {
639                 service = path;
640         }
641
642         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
643                                 &client_devicetype, p,
644                                 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
645
646         if (client_devicetype == NULL) {
647                 data_blob_clear_free(&password);
648                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
649                 END_PROFILE(SMBtconX);
650                 return;
651         }
652
653         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
654
655         conn = make_connection(service, password, client_devicetype,
656                                req->vuid, &nt_status);
657         req->conn =conn;
658
659         data_blob_clear_free(&password);
660
661         if (!conn) {
662                 reply_nterror(req, nt_status);
663                 END_PROFILE(SMBtconX);
664                 return;
665         }
666
667         if ( IS_IPC(conn) )
668                 server_devicetype = "IPC";
669         else if ( IS_PRINT(conn) )
670                 server_devicetype = "LPT1:";
671         else
672                 server_devicetype = "A:";
673
674         if (Protocol < PROTOCOL_NT1) {
675                 reply_outbuf(req, 2, 0);
676                 if (message_push_string(&req->outbuf, server_devicetype,
677                                         STR_TERMINATE|STR_ASCII) == -1) {
678                         reply_nterror(req, NT_STATUS_NO_MEMORY);
679                         END_PROFILE(SMBtconX);
680                         return;
681                 }
682         } else {
683                 /* NT sets the fstype of IPC$ to the null string */
684                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
685
686                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
687                         /* Return permissions. */
688                         uint32 perm1 = 0;
689                         uint32 perm2 = 0;
690
691                         reply_outbuf(req, 7, 0);
692
693                         if (IS_IPC(conn)) {
694                                 perm1 = FILE_ALL_ACCESS;
695                                 perm2 = FILE_ALL_ACCESS;
696                         } else {
697                                 perm1 = CAN_WRITE(conn) ?
698                                                 SHARE_ALL_ACCESS :
699                                                 SHARE_READ_ONLY;
700                         }
701
702                         SIVAL(req->outbuf, smb_vwv3, perm1);
703                         SIVAL(req->outbuf, smb_vwv5, perm2);
704                 } else {
705                         reply_outbuf(req, 3, 0);
706                 }
707
708                 if ((message_push_string(&req->outbuf, server_devicetype,
709                                          STR_TERMINATE|STR_ASCII) == -1)
710                     || (message_push_string(&req->outbuf, fstype,
711                                             STR_TERMINATE) == -1)) {
712                         reply_nterror(req, NT_STATUS_NO_MEMORY);
713                         END_PROFILE(SMBtconX);
714                         return;
715                 }
716
717                 /* what does setting this bit do? It is set by NT4 and
718                    may affect the ability to autorun mounted cdroms */
719                 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
720                       (lp_csc_policy(SNUM(conn)) << 2));
721
722                 init_dfsroot(conn, req->inbuf, req->outbuf);
723         }
724
725
726         DEBUG(3,("tconX service=%s \n",
727                  service));
728
729         /* set the incoming and outgoing tid to the just created one */
730         SSVAL(req->inbuf,smb_tid,conn->cnum);
731         SSVAL(req->outbuf,smb_tid,conn->cnum);
732
733         END_PROFILE(SMBtconX);
734
735         chain_reply(req);
736         return;
737 }
738
739 /****************************************************************************
740  Reply to an unknown type.
741 ****************************************************************************/
742
743 void reply_unknown_new(struct smb_request *req, uint8 type)
744 {
745         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
746                   smb_fn_name(type), type, type));
747         reply_doserror(req, ERRSRV, ERRunknownsmb);
748         return;
749 }
750
751 /****************************************************************************
752  Reply to an ioctl.
753  conn POINTER CAN BE NULL HERE !
754 ****************************************************************************/
755
756 void reply_ioctl(struct smb_request *req)
757 {
758         connection_struct *conn = req->conn;
759         uint16 device;
760         uint16 function;
761         uint32 ioctl_code;
762         int replysize;
763         char *p;
764
765         START_PROFILE(SMBioctl);
766
767         if (req->wct < 3) {
768                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
769                 END_PROFILE(SMBioctl);
770                 return;
771         }
772
773         device     = SVAL(req->inbuf,smb_vwv1);
774         function   = SVAL(req->inbuf,smb_vwv2);
775         ioctl_code = (device << 16) + function;
776
777         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
778
779         switch (ioctl_code) {
780             case IOCTL_QUERY_JOB_INFO:
781                     replysize = 32;
782                     break;
783             default:
784                     reply_doserror(req, ERRSRV, ERRnosupport);
785                     END_PROFILE(SMBioctl);
786                     return;
787         }
788
789         reply_outbuf(req, 8, replysize+1);
790         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
791         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
792         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
793         p = smb_buf(req->outbuf);
794         memset(p, '\0', replysize+1); /* valgrind-safe. */
795         p += 1;          /* Allow for alignment */
796
797         switch (ioctl_code) {
798                 case IOCTL_QUERY_JOB_INFO:                  
799                 {
800                         files_struct *fsp = file_fsp(SVAL(req->inbuf,
801                                                           smb_vwv0));
802                         if (!fsp) {
803                                 reply_doserror(req, ERRDOS, ERRbadfid);
804                                 END_PROFILE(SMBioctl);
805                                 return;
806                         }
807                         SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
808                         srvstr_push((char *)req->outbuf, req->flags2, p+2,
809                                     global_myname(), 15,
810                                     STR_TERMINATE|STR_ASCII);
811                         if (conn) {
812                                 srvstr_push((char *)req->outbuf, req->flags2,
813                                             p+18, lp_servicename(SNUM(conn)),
814                                             13, STR_TERMINATE|STR_ASCII);
815                         } else {
816                                 memset(p+18, 0, 13);
817                         }
818                         break;
819                 }
820         }
821
822         END_PROFILE(SMBioctl);
823         return;
824 }
825
826 /****************************************************************************
827  Strange checkpath NTSTATUS mapping.
828 ****************************************************************************/
829
830 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
831 {
832         /* Strange DOS error code semantics only for checkpath... */
833         if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
834                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
835                         /* We need to map to ERRbadpath */
836                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
837                 }
838         }
839         return status;
840 }
841
842 /****************************************************************************
843  Reply to a checkpath.
844 ****************************************************************************/
845
846 void reply_checkpath(struct smb_request *req)
847 {
848         connection_struct *conn = req->conn;
849         char *name = NULL;
850         SMB_STRUCT_STAT sbuf;
851         NTSTATUS status;
852         TALLOC_CTX *ctx = talloc_tos();
853
854         START_PROFILE(SMBcheckpath);
855
856         srvstr_get_path(ctx,(char *)req->inbuf, req->flags2, &name,
857                         smb_buf(req->inbuf) + 1, 0,
858                         STR_TERMINATE, &status);
859         if (!NT_STATUS_IS_OK(status)) {
860                 status = map_checkpath_error((char *)req->inbuf, status);
861                 reply_nterror(req, status);
862                 END_PROFILE(SMBcheckpath);
863                 return;
864         }
865
866         status = resolve_dfspath(ctx, conn,
867                         req->flags2 & FLAGS2_DFS_PATHNAMES,
868                         name,
869                         &name);
870         if (!NT_STATUS_IS_OK(status)) {
871                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
872                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
873                                         ERRSRV, ERRbadpath);
874                         END_PROFILE(SMBcheckpath);
875                         return;
876                 }
877                 goto path_err;
878         }
879
880         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
881
882         status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
883         if (!NT_STATUS_IS_OK(status)) {
884                 goto path_err;
885         }
886
887         status = check_name(conn, name);
888         if (!NT_STATUS_IS_OK(status)) {
889                 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
890                 goto path_err;
891         }
892
893         if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
894                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
895                 status = map_nt_error_from_unix(errno);
896                 goto path_err;
897         }
898
899         if (!S_ISDIR(sbuf.st_mode)) {
900                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
901                                 ERRDOS, ERRbadpath);
902                 END_PROFILE(SMBcheckpath);
903                 return;
904         }
905
906         reply_outbuf(req, 0, 0);
907
908         END_PROFILE(SMBcheckpath);
909         return;
910
911   path_err:
912
913         END_PROFILE(SMBcheckpath);
914
915         /* We special case this - as when a Windows machine
916                 is parsing a path is steps through the components
917                 one at a time - if a component fails it expects
918                 ERRbadpath, not ERRbadfile.
919         */
920         status = map_checkpath_error((char *)req->inbuf, status);
921         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
922                 /*
923                  * Windows returns different error codes if
924                  * the parent directory is valid but not the
925                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
926                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
927                  * if the path is invalid.
928                  */
929                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
930                                 ERRDOS, ERRbadpath);
931                 return;
932         }
933
934         reply_nterror(req, status);
935 }
936
937 /****************************************************************************
938  Reply to a getatr.
939 ****************************************************************************/
940
941 void reply_getatr(struct smb_request *req)
942 {
943         connection_struct *conn = req->conn;
944         char *fname = NULL;
945         SMB_STRUCT_STAT sbuf;
946         int mode=0;
947         SMB_OFF_T size=0;
948         time_t mtime=0;
949         char *p;
950         NTSTATUS status;
951         TALLOC_CTX *ctx = talloc_tos();
952
953         START_PROFILE(SMBgetatr);
954
955         p = smb_buf(req->inbuf) + 1;
956         p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
957                              0, STR_TERMINATE, &status);
958         if (!NT_STATUS_IS_OK(status)) {
959                 reply_nterror(req, status);
960                 END_PROFILE(SMBgetatr);
961                 return;
962         }
963
964         status = resolve_dfspath(ctx, conn,
965                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
966                                 fname,
967                                 &fname);
968         if (!NT_STATUS_IS_OK(status)) {
969                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
970                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
971                                         ERRSRV, ERRbadpath);
972                         END_PROFILE(SMBgetatr);
973                         return;
974                 }
975                 reply_nterror(req, status);
976                 END_PROFILE(SMBgetatr);
977                 return;
978         }
979
980         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
981                 under WfWg - weird! */
982         if (*fname == '\0') {
983                 mode = aHIDDEN | aDIR;
984                 if (!CAN_WRITE(conn)) {
985                         mode |= aRONLY;
986                 }
987                 size = 0;
988                 mtime = 0;
989         } else {
990                 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
991                 if (!NT_STATUS_IS_OK(status)) {
992                         reply_nterror(req, status);
993                         END_PROFILE(SMBgetatr);
994                         return;
995                 }
996                 status = check_name(conn, fname);
997                 if (!NT_STATUS_IS_OK(status)) {
998                         DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
999                         reply_nterror(req, status);
1000                         END_PROFILE(SMBgetatr);
1001                         return;
1002                 }
1003                 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
1004                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1005                         reply_unixerror(req, ERRDOS,ERRbadfile);
1006                         END_PROFILE(SMBgetatr);
1007                         return;
1008                 }
1009
1010                 mode = dos_mode(conn,fname,&sbuf);
1011                 size = sbuf.st_size;
1012                 mtime = sbuf.st_mtime;
1013                 if (mode & aDIR) {
1014                         size = 0;
1015                 }
1016         }
1017
1018         reply_outbuf(req, 10, 0);
1019
1020         SSVAL(req->outbuf,smb_vwv0,mode);
1021         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1022                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1023         } else {
1024                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1025         }
1026         SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1027
1028         if (Protocol >= PROTOCOL_NT1) {
1029                 SSVAL(req->outbuf, smb_flg2,
1030                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1031         }
1032   
1033         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1034
1035         END_PROFILE(SMBgetatr);
1036         return;
1037 }
1038
1039 /****************************************************************************
1040  Reply to a setatr.
1041 ****************************************************************************/
1042
1043 void reply_setatr(struct smb_request *req)
1044 {
1045         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 (mode != FILE_ATTRIBUTE_NORMAL) {
1114                 if (VALID_STAT_OF_DIR(sbuf))
1115                         mode |= aDIR;
1116                 else
1117                         mode &= ~aDIR;
1118
1119                 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1120                         reply_unixerror(req, ERRDOS, ERRnoaccess);
1121                         END_PROFILE(SMBsetatr);
1122                         return;
1123                 }
1124         }
1125
1126         if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
1127                 reply_unixerror(req, ERRDOS, ERRnoaccess);
1128                 END_PROFILE(SMBsetatr);
1129                 return;
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         if (read_smb_length(smbd_server_fd(),buf,
3496                         SMB_SECONDARY_WAIT, get_srv_read_error()) == -1) {
3497                 exit_server_cleanly("secondary writebraw failed");
3498         }
3499
3500         /*
3501          * Even though this is not an smb message,
3502          * smb_len returns the generic length of a packet.
3503          */
3504
3505         numtowrite = smb_len(buf);
3506
3507         /* Set up outbuf to return the correct size */
3508         reply_outbuf(req, 1, 0);
3509
3510         if (numtowrite != 0) {
3511
3512                 if (numtowrite > 0xFFFF) {
3513                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3514                                 "raw requested (%u). Terminating\n",
3515                                 (unsigned int)numtowrite ));
3516                         exit_server_cleanly("secondary writebraw failed");
3517                 }
3518
3519                 if (tcount > nwritten+numtowrite) {
3520                         DEBUG(3,("reply_writebraw: Client overestimated the "
3521                                 "write %d %d %d\n",
3522                                 (int)tcount,(int)nwritten,(int)numtowrite));
3523                 }
3524
3525                 if (read_data(smbd_server_fd(), buf+4, numtowrite,get_srv_read_error())
3526                                         != numtowrite ) {
3527                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3528                                 "raw read failed (%s). Terminating\n",
3529                                 strerror(errno) ));
3530                         exit_server_cleanly("secondary writebraw failed");
3531                 }
3532
3533                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3534                 if (nwritten == -1) {
3535                         TALLOC_FREE(buf);
3536                         reply_unixerror(req, ERRHRD, ERRdiskfull);
3537                         error_to_writebrawerr(req);
3538                         END_PROFILE(SMBwritebraw);
3539                         return;
3540                 }
3541
3542                 if (nwritten < (ssize_t)numtowrite) {
3543                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
3544                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
3545                 }
3546
3547                 if (nwritten > 0) {
3548                         total_written += nwritten;
3549                 }
3550         }
3551
3552         TALLOC_FREE(buf);
3553         SSVAL(req->outbuf,smb_vwv0,total_written);
3554
3555         status = sync_file(conn, fsp, write_through);
3556         if (!NT_STATUS_IS_OK(status)) {
3557                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3558                         fsp->fsp_name, nt_errstr(status) ));
3559                 reply_nterror(req, status);
3560                 error_to_writebrawerr(req);
3561                 END_PROFILE(SMBwritebraw);
3562                 return;
3563         }
3564
3565         DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3566                 "wrote=%d\n",
3567                 fsp->fnum, (double)startpos, (int)numtowrite,
3568                 (int)total_written));
3569
3570         /* We won't return a status if write through is not selected - this
3571          * follows what WfWg does */
3572         END_PROFILE(SMBwritebraw);
3573
3574         if (!write_through && total_written==tcount) {
3575
3576 #if RABBIT_PELLET_FIX
3577                 /*
3578                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3579                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3580                  * JRA.
3581                  */
3582                 if (!send_keepalive(smbd_server_fd())) {
3583                         exit_server_cleanly("reply_writebraw: send of "
3584                                 "keepalive failed");
3585                 }
3586 #endif
3587                 TALLOC_FREE(req->outbuf);
3588         }
3589         return;
3590 }
3591
3592 #undef DBGC_CLASS
3593 #define DBGC_CLASS DBGC_LOCKING
3594
3595 /****************************************************************************
3596  Reply to a writeunlock (core+).
3597 ****************************************************************************/
3598
3599 void reply_writeunlock(struct smb_request *req)
3600 {
3601         connection_struct *conn = req->conn;
3602         ssize_t nwritten = -1;
3603         size_t numtowrite;
3604         SMB_OFF_T startpos;
3605         char *data;
3606         NTSTATUS status = NT_STATUS_OK;
3607         files_struct *fsp;
3608
3609         START_PROFILE(SMBwriteunlock);
3610
3611         if (req->wct < 5) {
3612                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3613                 END_PROFILE(SMBwriteunlock);
3614                 return;
3615         }
3616         
3617         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3618
3619         if (!check_fsp(conn, req, fsp, &current_user)) {
3620                 END_PROFILE(SMBwriteunlock);
3621                 return;
3622         }
3623
3624         if (!CHECK_WRITE(fsp)) {
3625                 reply_doserror(req, ERRDOS,ERRbadaccess);
3626                 END_PROFILE(SMBwriteunlock);
3627                 return;
3628         }
3629
3630         numtowrite = SVAL(req->inbuf,smb_vwv1);
3631         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3632         data = smb_buf(req->inbuf) + 3;
3633   
3634         if (numtowrite
3635             && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3636                          (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3637                 reply_doserror(req, ERRDOS, ERRlock);
3638                 END_PROFILE(SMBwriteunlock);
3639                 return;
3640         }
3641
3642         /* The special X/Open SMB protocol handling of
3643            zero length writes is *NOT* done for
3644            this call */
3645         if(numtowrite == 0) {
3646                 nwritten = 0;
3647         } else {
3648                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3649         }
3650   
3651         status = sync_file(conn, fsp, False /* write through */);
3652         if (!NT_STATUS_IS_OK(status)) {
3653                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3654                         fsp->fsp_name, nt_errstr(status) ));
3655                 reply_nterror(req, status);
3656                 END_PROFILE(SMBwriteunlock);
3657                 return;
3658         }
3659
3660         if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3661                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3662                 END_PROFILE(SMBwriteunlock);
3663                 return;
3664         }
3665
3666         if (numtowrite) {
3667                 status = do_unlock(smbd_messaging_context(),
3668                                 fsp,
3669                                 req->smbpid,
3670                                 (SMB_BIG_UINT)numtowrite, 
3671                                 (SMB_BIG_UINT)startpos,
3672                                 WINDOWS_LOCK);
3673
3674                 if (NT_STATUS_V(status)) {
3675                         reply_nterror(req, status);
3676                         END_PROFILE(SMBwriteunlock);
3677                         return;
3678                 }
3679         }
3680
3681         reply_outbuf(req, 1, 0);
3682         
3683         SSVAL(req->outbuf,smb_vwv0,nwritten);
3684         
3685         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3686                  fsp->fnum, (int)numtowrite, (int)nwritten));
3687         
3688         END_PROFILE(SMBwriteunlock);
3689         return;
3690 }
3691
3692 #undef DBGC_CLASS
3693 #define DBGC_CLASS DBGC_ALL
3694
3695 /****************************************************************************
3696  Reply to a write.
3697 ****************************************************************************/
3698
3699 void reply_write(struct smb_request *req)
3700 {
3701         connection_struct *conn = req->conn;
3702         size_t numtowrite;
3703         ssize_t nwritten = -1;
3704         SMB_OFF_T startpos;
3705         char *data;
3706         files_struct *fsp;
3707         NTSTATUS status;
3708
3709         START_PROFILE(SMBwrite);
3710
3711         if (req->wct < 5) {
3712                 END_PROFILE(SMBwrite);
3713                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3714                 return;
3715         }
3716
3717         /* If it's an IPC, pass off the pipe handler. */
3718         if (IS_IPC(conn)) {
3719                 reply_pipe_write(req);
3720                 END_PROFILE(SMBwrite);
3721                 return;
3722         }
3723
3724         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3725
3726         if (!check_fsp(conn, req, fsp, &current_user)) {
3727                 END_PROFILE(SMBwrite);
3728                 return;
3729         }
3730
3731         if (!CHECK_WRITE(fsp)) {
3732                 reply_doserror(req, ERRDOS, ERRbadaccess);
3733                 END_PROFILE(SMBwrite);
3734                 return;
3735         }
3736
3737         numtowrite = SVAL(req->inbuf,smb_vwv1);
3738         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3739         data = smb_buf(req->inbuf) + 3;
3740   
3741         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3742                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3743                 reply_doserror(req, ERRDOS, ERRlock);
3744                 END_PROFILE(SMBwrite);
3745                 return;
3746         }
3747
3748         /*
3749          * X/Open SMB protocol says that if smb_vwv1 is
3750          * zero then the file size should be extended or
3751          * truncated to the size given in smb_vwv[2-3].
3752          */
3753
3754         if(numtowrite == 0) {
3755                 /*
3756                  * This is actually an allocate call, and set EOF. JRA.
3757                  */
3758                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3759                 if (nwritten < 0) {
3760                         reply_nterror(req, NT_STATUS_DISK_FULL);
3761                         END_PROFILE(SMBwrite);
3762                         return;
3763                 }
3764                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3765                 if (nwritten < 0) {
3766                         reply_nterror(req, NT_STATUS_DISK_FULL);
3767                         END_PROFILE(SMBwrite);
3768                         return;
3769                 }
3770         } else
3771                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3772   
3773         status = sync_file(conn, fsp, False);
3774         if (!NT_STATUS_IS_OK(status)) {
3775                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3776                         fsp->fsp_name, nt_errstr(status) ));
3777                 reply_nterror(req, status);
3778                 END_PROFILE(SMBwrite);
3779                 return;
3780         }
3781
3782         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3783                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3784                 END_PROFILE(SMBwrite);
3785                 return;
3786         }
3787
3788         reply_outbuf(req, 1, 0);
3789   
3790         SSVAL(req->outbuf,smb_vwv0,nwritten);
3791
3792         if (nwritten < (ssize_t)numtowrite) {
3793                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3794                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3795         }
3796   
3797         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3798
3799         END_PROFILE(SMBwrite);
3800         return;
3801 }
3802
3803 /****************************************************************************
3804  Ensure a buffer is a valid writeX for recvfile purposes.
3805 ****************************************************************************/
3806
3807 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3808                                                 (2*14) + /* word count (including bcc) */ \
3809                                                 1 /* pad byte */)
3810
3811 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3812 {
3813         size_t numtowrite;
3814         connection_struct *conn = NULL;
3815         unsigned int doff = 0;
3816         size_t len = smb_len_large(inbuf);
3817
3818         if (is_encrypted_packet(inbuf)) {
3819                 /* Can't do this on encrypted
3820                  * connections. */
3821                 return false;
3822         }
3823
3824         if (CVAL(inbuf,smb_com) != SMBwriteX) {
3825                 return false;
3826         }
3827
3828         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3829                         CVAL(inbuf,smb_wct) != 14) {
3830                 DEBUG(10,("is_valid_writeX_buffer: chained or "
3831                         "invalid word length.\n"));
3832                 return false;
3833         }
3834
3835         conn = conn_find(SVAL(inbuf, smb_tid));
3836         if (conn == NULL) {
3837                 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3838                 return false;
3839         }
3840         if (IS_IPC(conn)) {
3841                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3842                 return false;
3843         }
3844         doff = SVAL(inbuf,smb_vwv11);
3845
3846         numtowrite = SVAL(inbuf,smb_vwv10);
3847
3848         if (len > doff && len - doff > 0xFFFF) {
3849                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3850         }
3851
3852         if (numtowrite == 0) {
3853                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3854                 return false;
3855         }
3856
3857         /* Ensure the sizes match up. */
3858         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3859                 /* no pad byte...old smbclient :-( */
3860                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3861                         (unsigned int)doff,
3862                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
3863                 return false;
3864         }
3865
3866         if (len - doff != numtowrite) {
3867                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3868                         "len = %u, doff = %u, numtowrite = %u\n",
3869                         (unsigned int)len,
3870                         (unsigned int)doff,
3871                         (unsigned int)numtowrite ));
3872                 return false;
3873         }
3874
3875         DEBUG(10,("is_valid_writeX_buffer: true "
3876                 "len = %u, doff = %u, numtowrite = %u\n",
3877                 (unsigned int)len,
3878                 (unsigned int)doff,
3879                 (unsigned int)numtowrite ));
3880
3881         return true;
3882 }
3883
3884 /****************************************************************************
3885  Reply to a write and X.
3886 ****************************************************************************/
3887
3888 void reply_write_and_X(struct smb_request *req)
3889 {
3890         connection_struct *conn = req->conn;
3891         files_struct *fsp;
3892         SMB_OFF_T startpos;
3893         size_t numtowrite;
3894         bool write_through;
3895         ssize_t nwritten;
3896         unsigned int smb_doff;
3897         unsigned int smblen;
3898         char *data;
3899         NTSTATUS status;
3900
3901         START_PROFILE(SMBwriteX);
3902
3903         if ((req->wct != 12) && (req->wct != 14)) {
3904                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3905                 END_PROFILE(SMBwriteX);
3906                 return;
3907         }
3908
3909         numtowrite = SVAL(req->inbuf,smb_vwv10);
3910         smb_doff = SVAL(req->inbuf,smb_vwv11);
3911         smblen = smb_len(req->inbuf);
3912
3913         if (req->unread_bytes > 0xFFFF ||
3914                         (smblen > smb_doff &&
3915                                 smblen - smb_doff > 0xFFFF)) {
3916                 numtowrite |= (((size_t)SVAL(req->inbuf,smb_vwv9))<<16);
3917         }
3918
3919         if (req->unread_bytes) {
3920                 /* Can't do a recvfile write on IPC$ */
3921                 if (IS_IPC(conn)) {
3922                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3923                         END_PROFILE(SMBwriteX);
3924                         return;
3925                 }
3926                 if (numtowrite != req->unread_bytes) {
3927                         reply_doserror(req, ERRDOS, ERRbadmem);
3928                         END_PROFILE(SMBwriteX);
3929                         return;
3930                 }
3931         } else {
3932                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
3933                                 smb_doff + numtowrite > smblen) {
3934                         reply_doserror(req, ERRDOS, ERRbadmem);
3935                         END_PROFILE(SMBwriteX);
3936                         return;
3937                 }
3938         }
3939
3940         /* If it's an IPC, pass off the pipe handler. */
3941         if (IS_IPC(conn)) {
3942                 if (req->unread_bytes) {
3943                         reply_doserror(req, ERRDOS, ERRbadmem);
3944                         END_PROFILE(SMBwriteX);
3945                         return;
3946                 }
3947                 reply_pipe_write_and_X(req);
3948                 END_PROFILE(SMBwriteX);
3949                 return;
3950         }
3951
3952         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3953         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3954         write_through = BITSETW(req->inbuf+smb_vwv7,0);
3955
3956         if (!check_fsp(conn, req, fsp, &current_user)) {
3957                 END_PROFILE(SMBwriteX);
3958                 return;
3959         }
3960
3961         if (!CHECK_WRITE(fsp)) {
3962                 reply_doserror(req, ERRDOS, ERRbadaccess);
3963                 END_PROFILE(SMBwriteX);
3964                 return;
3965         }
3966
3967         data = smb_base(req->inbuf) + smb_doff;
3968
3969         if(req->wct == 14) {
3970 #ifdef LARGE_SMB_OFF_T
3971                 /*
3972                  * This is a large offset (64 bit) write.
3973                  */
3974                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
3975
3976 #else /* !LARGE_SMB_OFF_T */
3977
3978                 /*
3979                  * Ensure we haven't been sent a >32 bit offset.
3980                  */
3981
3982                 if(IVAL(req->inbuf,smb_vwv12) != 0) {
3983                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
3984                                  "used and we don't support 64 bit offsets.\n",
3985                                  (unsigned int)IVAL(req->inbuf,smb_vwv12) ));
3986                         reply_doserror(req, ERRDOS, ERRbadaccess);
3987                         END_PROFILE(SMBwriteX);
3988                         return;
3989                 }
3990
3991 #endif /* LARGE_SMB_OFF_T */
3992         }
3993
3994         if (is_locked(fsp,(uint32)req->smbpid,
3995                       (SMB_BIG_UINT)numtowrite,
3996                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3997                 reply_doserror(req, ERRDOS, ERRlock);
3998                 END_PROFILE(SMBwriteX);
3999                 return;
4000         }
4001
4002         /* X/Open SMB protocol says that, unlike SMBwrite
4003         if the length is zero then NO truncation is
4004         done, just a write of zero. To truncate a file,
4005         use SMBwrite. */
4006
4007         if(numtowrite == 0) {
4008                 nwritten = 0;
4009         } else {
4010
4011                 if ((req->unread_bytes == 0) &&
4012                     schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4013                                              numtowrite)) {
4014                         END_PROFILE(SMBwriteX);
4015                         return;
4016                 }
4017                 
4018                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4019         }
4020
4021         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4022                 reply_unixerror(req, ERRHRD, ERRdiskfull);
4023                 END_PROFILE(SMBwriteX);
4024                 return;
4025         }
4026
4027         reply_outbuf(req, 6, 0);
4028         SSVAL(req->outbuf,smb_vwv2,nwritten);
4029         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4030
4031         if (nwritten < (ssize_t)numtowrite) {
4032                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4033                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4034         }
4035
4036         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4037                 fsp->fnum, (int)numtowrite, (int)nwritten));
4038
4039         status = sync_file(conn, fsp, write_through);
4040         if (!NT_STATUS_IS_OK(status)) {
4041                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4042                         fsp->fsp_name, nt_errstr(status) ));
4043                 reply_nterror(req, status);
4044                 END_PROFILE(SMBwriteX);
4045                 return;
4046         }
4047
4048         END_PROFILE(SMBwriteX);
4049         chain_reply(req);
4050         return;
4051 }
4052
4053 /****************************************************************************
4054  Reply to a lseek.
4055 ****************************************************************************/
4056
4057 void reply_lseek(struct smb_request *req)
4058 {
4059         connection_struct *conn = req->conn;
4060         SMB_OFF_T startpos;
4061         SMB_OFF_T res= -1;
4062         int mode,umode;
4063         files_struct *fsp;
4064
4065         START_PROFILE(SMBlseek);
4066
4067         if (req->wct < 4) {
4068                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4069                 END_PROFILE(SMBlseek);
4070                 return;
4071         }
4072
4073         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4074
4075         if (!check_fsp(conn, req, fsp, &current_user)) {
4076                 return;
4077         }
4078
4079         flush_write_cache(fsp, SEEK_FLUSH);
4080
4081         mode = SVAL(req->inbuf,smb_vwv1) & 3;
4082         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4083         startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2);
4084
4085         switch (mode) {
4086                 case 0:
4087                         umode = SEEK_SET;
4088                         res = startpos;
4089                         break;
4090                 case 1:
4091                         umode = SEEK_CUR;
4092                         res = fsp->fh->pos + startpos;
4093                         break;
4094                 case 2:
4095                         umode = SEEK_END;
4096                         break;
4097                 default:
4098                         umode = SEEK_SET;
4099                         res = startpos;
4100                         break;
4101         }
4102
4103         if (umode == SEEK_END) {
4104                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4105                         if(errno == EINVAL) {
4106                                 SMB_OFF_T current_pos = startpos;
4107                                 SMB_STRUCT_STAT sbuf;
4108
4109                                 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4110                                         reply_unixerror(req, ERRDOS,
4111                                                         ERRnoaccess);
4112                                         END_PROFILE(SMBlseek);
4113                                         return;
4114                                 }
4115
4116                                 current_pos += sbuf.st_size;
4117                                 if(current_pos < 0)
4118                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4119                         }
4120                 }
4121
4122                 if(res == -1) {
4123                         reply_unixerror(req, ERRDOS, ERRnoaccess);
4124                         END_PROFILE(SMBlseek);
4125                         return;
4126                 }
4127         }
4128
4129         fsp->fh->pos = res;
4130
4131         reply_outbuf(req, 2, 0);
4132         SIVAL(req->outbuf,smb_vwv0,res);
4133   
4134         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4135                 fsp->fnum, (double)startpos, (double)res, mode));
4136
4137         END_PROFILE(SMBlseek);
4138         return;
4139 }
4140
4141 /****************************************************************************
4142  Reply to a flush.
4143 ****************************************************************************/
4144
4145 void reply_flush(struct smb_request *req)
4146 {
4147         connection_struct *conn = req->conn;
4148         uint16 fnum;
4149         files_struct *fsp;
4150
4151         START_PROFILE(SMBflush);
4152
4153         if (req->wct < 1) {
4154                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4155                 return;
4156         }
4157
4158         fnum = SVAL(req->inbuf,smb_vwv0);
4159         fsp = file_fsp(fnum);
4160
4161         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, &current_user)) {
4162                 return;
4163         }
4164         
4165         if (!fsp) {
4166                 file_sync_all(conn);
4167         } else {
4168                 NTSTATUS status = sync_file(conn, fsp, True);
4169                 if (!NT_STATUS_IS_OK(status)) {
4170                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4171                                 fsp->fsp_name, nt_errstr(status) ));
4172                         reply_nterror(req, status);
4173                         END_PROFILE(SMBflush);
4174                         return;
4175                 }
4176         }
4177         
4178         reply_outbuf(req, 0, 0);
4179
4180         DEBUG(3,("flush\n"));
4181         END_PROFILE(SMBflush);
4182         return;
4183 }
4184
4185 /****************************************************************************
4186  Reply to a exit.
4187  conn POINTER CAN BE NULL HERE !
4188 ****************************************************************************/
4189
4190 void reply_exit(struct smb_request *req)
4191 {
4192         START_PROFILE(SMBexit);
4193
4194         file_close_pid(req->smbpid, req->vuid);
4195
4196         reply_outbuf(req, 0, 0);
4197
4198         DEBUG(3,("exit\n"));
4199
4200         END_PROFILE(SMBexit);
4201         return;
4202 }
4203
4204 /****************************************************************************
4205  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4206 ****************************************************************************/
4207
4208 void reply_close(struct smb_request *req)
4209 {
4210         connection_struct *conn = req->conn;
4211         NTSTATUS status = NT_STATUS_OK;
4212         files_struct *fsp = NULL;
4213         START_PROFILE(SMBclose);
4214
4215         if (req->wct < 3) {
4216                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4217                 END_PROFILE(SMBclose);
4218                 return;
4219         }
4220
4221         /* If it's an IPC, pass off to the pipe handler. */
4222         if (IS_IPC(conn)) {
4223                 reply_pipe_close(conn, req);
4224                 END_PROFILE(SMBclose);
4225                 return;
4226         }
4227
4228         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4229
4230         /*
4231          * We can only use CHECK_FSP if we know it's not a directory.
4232          */
4233
4234         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
4235                 reply_doserror(req, ERRDOS, ERRbadfid);
4236                 END_PROFILE(SMBclose);
4237                 return;
4238         }
4239
4240         if(fsp->is_directory) {
4241                 /*
4242                  * Special case - close NT SMB directory handle.
4243                  */
4244                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4245                 status = close_file(fsp,NORMAL_CLOSE);
4246         } else {
4247                 /*
4248                  * Close ordinary file.
4249                  */
4250
4251                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4252                          fsp->fh->fd, fsp->fnum,
4253                          conn->num_files_open));
4254  
4255                 /*
4256                  * Take care of any time sent in the close.
4257                  */
4258
4259                 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
4260                                                 srv_make_unix_date3(
4261                                                         req->inbuf+smb_vwv1)));
4262
4263                 /*
4264                  * close_file() returns the unix errno if an error
4265                  * was detected on close - normally this is due to
4266                  * a disk full error. If not then it was probably an I/O error.
4267                  */
4268  
4269                 status = close_file(fsp,NORMAL_CLOSE);
4270         }  
4271
4272         if (!NT_STATUS_IS_OK(status)) {
4273                 reply_nterror(req, status);
4274                 END_PROFILE(SMBclose);
4275                 return;
4276         }
4277
4278         reply_outbuf(req, 0, 0);
4279         END_PROFILE(SMBclose);
4280         return;
4281 }
4282
4283 /****************************************************************************
4284  Reply to a writeclose (Core+ protocol).
4285 ****************************************************************************/
4286
4287 void reply_writeclose(struct smb_request *req)
4288 {
4289         connection_struct *conn = req->conn;
4290         size_t numtowrite;
4291         ssize_t nwritten = -1;
4292         NTSTATUS close_status = NT_STATUS_OK;
4293         SMB_OFF_T startpos;
4294         char *data;
4295         struct timespec mtime;
4296         files_struct *fsp;
4297
4298         START_PROFILE(SMBwriteclose);
4299
4300         if (req->wct < 6) {
4301                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4302                 END_PROFILE(SMBwriteclose);
4303                 return;
4304         }
4305
4306         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4307
4308         if (!check_fsp(conn, req, fsp, &current_user)) {
4309                 END_PROFILE(SMBwriteclose);
4310                 return;
4311         }
4312         if (!CHECK_WRITE(fsp)) {
4313                 reply_doserror(req, ERRDOS,ERRbadaccess);
4314                 END_PROFILE(SMBwriteclose);
4315                 return;
4316         }
4317
4318         numtowrite = SVAL(req->inbuf,smb_vwv1);
4319         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
4320         mtime = convert_time_t_to_timespec(srv_make_unix_date3(
4321                                                    req->inbuf+smb_vwv4));
4322         data = smb_buf(req->inbuf) + 1;
4323   
4324         if (numtowrite
4325             && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
4326                          (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
4327                 reply_doserror(req, ERRDOS,ERRlock);
4328                 END_PROFILE(SMBwriteclose);
4329                 return;
4330         }
4331   
4332         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4333
4334         set_filetime(conn, fsp->fsp_name, mtime);
4335   
4336         /*
4337          * More insanity. W2K only closes the file if writelen > 0.
4338          * JRA.
4339          */
4340
4341         if (numtowrite) {
4342                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4343                         fsp->fsp_name ));
4344                 close_status = close_file(fsp,NORMAL_CLOSE);
4345         }
4346
4347         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4348                  fsp->fnum, (int)numtowrite, (int)nwritten,
4349                  conn->num_files_open));
4350   
4351         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4352                 reply_doserror(req, ERRHRD, ERRdiskfull);
4353                 END_PROFILE(SMBwriteclose);
4354                 return;
4355         }
4356  
4357         if(!NT_STATUS_IS_OK(close_status)) {
4358                 reply_nterror(req, close_status);
4359                 END_PROFILE(SMBwriteclose);
4360                 return;
4361         }
4362
4363         reply_outbuf(req, 1, 0);
4364   
4365         SSVAL(req->outbuf,smb_vwv0,nwritten);
4366         END_PROFILE(SMBwriteclose);
4367         return;
4368 }
4369
4370 #undef DBGC_CLASS
4371 #define DBGC_CLASS DBGC_LOCKING
4372
4373 /****************************************************************************
4374  Reply to a lock.
4375 ****************************************************************************/
4376
4377 void reply_lock(struct smb_request *req)
4378 {
4379         connection_struct *conn = req->conn;
4380         SMB_BIG_UINT count,offset;
4381         NTSTATUS status;
4382         files_struct *fsp;
4383         struct byte_range_lock *br_lck = NULL;
4384
4385         START_PROFILE(SMBlock);
4386
4387         if (req->wct < 5) {
4388                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4389                 END_PROFILE(SMBlock);
4390                 return;
4391         }
4392
4393         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4394
4395         if (!check_fsp(conn, req, fsp, &current_user)) {
4396                 END_PROFILE(SMBlock);
4397                 return;
4398         }
4399
4400         release_level_2_oplocks_on_change(fsp);
4401
4402         count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4403         offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4404
4405         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4406                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4407
4408         br_lck = do_lock(smbd_messaging_context(),
4409                         fsp,
4410                         req->smbpid,
4411                         count,
4412                         offset,
4413                         WRITE_LOCK,
4414                         WINDOWS_LOCK,
4415                         False, /* Non-blocking lock. */
4416                         &status,
4417                         NULL);
4418
4419         TALLOC_FREE(br_lck);
4420
4421         if (NT_STATUS_V(status)) {
4422                 reply_nterror(req, status);
4423                 END_PROFILE(SMBlock);
4424                 return;
4425         }
4426
4427         reply_outbuf(req, 0, 0);
4428
4429         END_PROFILE(SMBlock);
4430         return;
4431 }
4432
4433 /****************************************************************************
4434  Reply to a unlock.
4435 ****************************************************************************/
4436
4437 void reply_unlock(struct smb_request *req)
4438 {
4439         connection_struct *conn = req->conn;
4440         SMB_BIG_UINT count,offset;
4441         NTSTATUS status;
4442         files_struct *fsp;
4443
4444         START_PROFILE(SMBunlock);
4445
4446         if (req->wct < 5) {
4447                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4448                 END_PROFILE(SMBunlock);
4449                 return;
4450         }
4451
4452         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4453
4454         if (!check_fsp(conn, req, fsp, &current_user)) {
4455                 END_PROFILE(SMBunlock);
4456                 return;
4457         }
4458         
4459         count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4460         offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4461         
4462         status = do_unlock(smbd_messaging_context(),
4463                         fsp,
4464                         req->smbpid,
4465                         count,
4466                         offset,
4467                         WINDOWS_LOCK);
4468
4469         if (NT_STATUS_V(status)) {
4470                 reply_nterror(req, status);
4471                 END_PROFILE(SMBunlock);
4472                 return;
4473         }
4474
4475         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4476                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4477
4478         reply_outbuf(req, 0, 0);
4479
4480         END_PROFILE(SMBunlock);
4481         return;
4482 }
4483
4484 #undef DBGC_CLASS
4485 #define DBGC_CLASS DBGC_ALL
4486
4487 /****************************************************************************
4488  Reply to a tdis.
4489  conn POINTER CAN BE NULL HERE !
4490 ****************************************************************************/
4491
4492 void reply_tdis(struct smb_request *req)
4493 {
4494         connection_struct *conn = req->conn;
4495         START_PROFILE(SMBtdis);
4496
4497         if (!conn) {
4498                 DEBUG(4,("Invalid connection in tdis\n"));
4499                 reply_doserror(req, ERRSRV, ERRinvnid);
4500                 END_PROFILE(SMBtdis);
4501                 return;
4502         }
4503
4504         conn->used = False;
4505
4506         close_cnum(conn,req->vuid);
4507         req->conn = NULL;
4508
4509         reply_outbuf(req, 0, 0);
4510         END_PROFILE(SMBtdis);
4511         return;
4512 }
4513
4514 /****************************************************************************
4515  Reply to a echo.
4516  conn POINTER CAN BE NULL HERE !
4517 ****************************************************************************/
4518
4519 void reply_echo(struct smb_request *req)
4520 {
4521         connection_struct *conn = req->conn;
4522         int smb_reverb;
4523         int seq_num;
4524         unsigned int data_len = smb_buflen(req->inbuf);
4525
4526         START_PROFILE(SMBecho);
4527
4528         if (req->wct < 1) {
4529                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4530                 END_PROFILE(SMBecho);
4531                 return;
4532         }
4533
4534         if (data_len > BUFFER_SIZE) {
4535                 DEBUG(0,("reply_echo: data_len too large.\n"));
4536                 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
4537                 END_PROFILE(SMBecho);
4538                 return;
4539         }
4540
4541         smb_reverb = SVAL(req->inbuf,smb_vwv0);
4542
4543         reply_outbuf(req, 1, data_len);
4544
4545         /* copy any incoming data back out */
4546         if (data_len > 0) {
4547                 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
4548         }
4549
4550         if (smb_reverb > 100) {
4551                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4552                 smb_reverb = 100;
4553         }
4554
4555         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4556                 SSVAL(req->outbuf,smb_vwv0,seq_num);
4557
4558                 show_msg((char *)req->outbuf);
4559                 if (!srv_send_smb(smbd_server_fd(),
4560                                 (char *)req->outbuf,
4561                                 IS_CONN_ENCRYPTED(conn)||req->encrypted))
4562                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
4563         }
4564
4565         DEBUG(3,("echo %d times\n", smb_reverb));
4566
4567         TALLOC_FREE(req->outbuf);
4568
4569         smb_echo_count++;
4570
4571         END_PROFILE(SMBecho);
4572         return;
4573 }
4574
4575 /****************************************************************************
4576  Reply to a printopen.
4577 ****************************************************************************/
4578
4579 void reply_printopen(struct smb_request *req)
4580 {
4581         connection_struct *conn = req->conn;
4582         files_struct *fsp;
4583         NTSTATUS status;
4584         
4585         START_PROFILE(SMBsplopen);
4586
4587         if (req->wct < 2) {
4588                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4589                 END_PROFILE(SMBsplopen);
4590                 return;
4591         }
4592
4593         if (!CAN_PRINT(conn)) {
4594                 reply_doserror(req, ERRDOS, ERRnoaccess);
4595                 END_PROFILE(SMBsplopen);
4596                 return;
4597         }
4598
4599         /* Open for exclusive use, write only. */
4600         status = print_fsp_open(conn, NULL, &fsp);
4601
4602         if (!NT_STATUS_IS_OK(status)) {
4603                 reply_nterror(req, status);
4604                 END_PROFILE(SMBsplopen);
4605                 return;
4606         }
4607
4608         reply_outbuf(req, 1, 0);
4609         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4610   
4611         DEBUG(3,("openprint fd=%d fnum=%d\n",
4612                  fsp->fh->fd, fsp->fnum));
4613
4614         END_PROFILE(SMBsplopen);
4615         return;
4616 }
4617
4618 /****************************************************************************
4619  Reply to a printclose.
4620 ****************************************************************************/
4621
4622 void reply_printclose(struct smb_request *req)
4623 {
4624         connection_struct *conn = req->conn;
4625         files_struct *fsp;
4626         NTSTATUS status;
4627
4628         START_PROFILE(SMBsplclose);
4629
4630         if (req->wct < 3) {
4631                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4632                 END_PROFILE(SMBsplclose);
4633                 return;
4634         }
4635
4636         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4637
4638         if (!check_fsp(conn, req, fsp, &current_user)) {
4639                 END_PROFILE(SMBsplclose);
4640                 return;
4641         }
4642
4643         if (!CAN_PRINT(conn)) {
4644                 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4645                 END_PROFILE(SMBsplclose);
4646                 return;
4647         }
4648   
4649         DEBUG(3,("printclose fd=%d fnum=%d\n",
4650                  fsp->fh->fd,fsp->fnum));
4651   
4652         status = close_file(fsp,NORMAL_CLOSE);
4653
4654         if(!NT_STATUS_IS_OK(status)) {
4655                 reply_nterror(req, status);
4656                 END_PROFILE(SMBsplclose);
4657                 return;
4658         }
4659
4660         END_PROFILE(SMBsplclose);
4661         return;
4662 }
4663
4664 /****************************************************************************
4665  Reply to a printqueue.
4666 ****************************************************************************/
4667
4668 void reply_printqueue(struct smb_request *req)
4669 {
4670         connection_struct *conn = req->conn;
4671         int max_count;
4672         int start_index;
4673
4674         START_PROFILE(SMBsplretq);
4675
4676         if (req->wct < 2) {
4677                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4678                 END_PROFILE(SMBsplretq);
4679                 return;
4680         }
4681
4682         max_count = SVAL(req->inbuf,smb_vwv0);
4683         start_index = SVAL(req->inbuf,smb_vwv1);
4684
4685         /* we used to allow the client to get the cnum wrong, but that
4686            is really quite gross and only worked when there was only
4687            one printer - I think we should now only accept it if they
4688            get it right (tridge) */
4689         if (!CAN_PRINT(conn)) {
4690                 reply_doserror(req, ERRDOS, ERRnoaccess);
4691                 END_PROFILE(SMBsplretq);
4692                 return;
4693         }
4694
4695         reply_outbuf(req, 2, 3);
4696         SSVAL(req->outbuf,smb_vwv0,0);
4697         SSVAL(req->outbuf,smb_vwv1,0);
4698         SCVAL(smb_buf(req->outbuf),0,1);
4699         SSVAL(smb_buf(req->outbuf),1,0);
4700   
4701         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4702                  start_index, max_count));
4703
4704         {
4705                 print_queue_struct *queue = NULL;
4706                 print_status_struct status;
4707                 int count = print_queue_status(SNUM(conn), &queue, &status);
4708                 int num_to_get = ABS(max_count);
4709                 int first = (max_count>0?start_index:start_index+max_count+1);
4710                 int i;
4711
4712                 if (first >= count)
4713                         num_to_get = 0;
4714                 else
4715                         num_to_get = MIN(num_to_get,count-first);
4716     
4717
4718                 for (i=first;i<first+num_to_get;i++) {
4719                         char blob[28];
4720                         char *p = blob;
4721
4722                         srv_put_dos_date2(p,0,queue[i].time);
4723                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4724                         SSVAL(p,5, queue[i].job);
4725                         SIVAL(p,7,queue[i].size);
4726                         SCVAL(p,11,0);
4727                         srvstr_push(blob, req->flags2, p+12,
4728                                     queue[i].fs_user, 16, STR_ASCII);
4729
4730                         if (message_push_blob(
4731                                     &req->outbuf,
4732                                     data_blob_const(
4733                                             blob, sizeof(blob))) == -1) {
4734                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4735                                 END_PROFILE(SMBsplretq);
4736                                 return;
4737                         }
4738                 }
4739
4740                 if (count > 0) {
4741                         SSVAL(req->outbuf,smb_vwv0,count);
4742                         SSVAL(req->outbuf,smb_vwv1,
4743                               (max_count>0?first+count:first-1));
4744                         SCVAL(smb_buf(req->outbuf),0,1);
4745                         SSVAL(smb_buf(req->outbuf),1,28*count);
4746                 }
4747
4748                 SAFE_FREE(queue);
4749           
4750                 DEBUG(3,("%d entries returned in queue\n",count));
4751         }
4752   
4753         END_PROFILE(SMBsplretq);
4754         return;
4755 }
4756
4757 /****************************************************************************
4758  Reply to a printwrite.
4759 ****************************************************************************/
4760
4761 void reply_printwrite(struct smb_request *req)
4762 {
4763         connection_struct *conn = req->conn;
4764         int numtowrite;
4765         char *data;
4766         files_struct *fsp;
4767
4768         START_PROFILE(SMBsplwr);
4769
4770         if (req->wct < 1) {
4771                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4772                 END_PROFILE(SMBsplwr);
4773                 return;
4774         }
4775   
4776         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4777
4778         if (!check_fsp(conn, req, fsp, &current_user)) {
4779                 END_PROFILE(SMBsplwr);
4780                 return;
4781         }
4782
4783         if (!CAN_PRINT(conn)) {
4784                 reply_doserror(req, ERRDOS, ERRnoaccess);
4785                 END_PROFILE(SMBsplwr);
4786                 return;
4787         }
4788
4789         if (!CHECK_WRITE(fsp)) {
4790                 reply_doserror(req, ERRDOS, ERRbadaccess);
4791                 END_PROFILE(SMBsplwr);
4792                 return;
4793         }
4794
4795         numtowrite = SVAL(smb_buf(req->inbuf),1);
4796
4797         if (smb_buflen(req->inbuf) < numtowrite + 3) {
4798                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4799                 END_PROFILE(SMBsplwr);
4800                 return;
4801         }
4802
4803         data = smb_buf(req->inbuf) + 3;
4804
4805         if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4806                 reply_unixerror(req, ERRHRD, ERRdiskfull);
4807                 END_PROFILE(SMBsplwr);
4808                 return;
4809         }
4810
4811         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4812
4813         END_PROFILE(SMBsplwr);
4814         return;
4815 }
4816
4817 /****************************************************************************
4818  Reply to a mkdir.
4819 ****************************************************************************/
4820
4821 void reply_mkdir(struct smb_request *req)
4822 {
4823         connection_struct *conn = req->conn;
4824         char *directory = NULL;
4825         NTSTATUS status;
4826         SMB_STRUCT_STAT sbuf;
4827         TALLOC_CTX *ctx = talloc_tos();
4828
4829         START_PROFILE(SMBmkdir);
4830
4831         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
4832                         smb_buf(req->inbuf) + 1, 0,
4833                         STR_TERMINATE, &status);
4834         if (!NT_STATUS_IS_OK(status)) {
4835                 reply_nterror(req, status);
4836                 END_PROFILE(SMBmkdir);
4837                 return;
4838         }
4839
4840         status = resolve_dfspath(ctx, conn,
4841                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4842                                  directory,
4843                                  &directory);
4844         if (!NT_STATUS_IS_OK(status)) {
4845                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4846                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4847                                         ERRSRV, ERRbadpath);
4848                         END_PROFILE(SMBmkdir);
4849                         return;
4850                 }
4851                 reply_nterror(req, status);
4852                 END_PROFILE(SMBmkdir);
4853                 return;
4854         }
4855
4856         status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4857         if (!NT_STATUS_IS_OK(status)) {
4858                 reply_nterror(req, status);
4859                 END_PROFILE(SMBmkdir);
4860                 return;
4861         }
4862
4863         status = check_name(conn, directory);
4864         if (!NT_STATUS_IS_OK(status)) {
4865                 reply_nterror(req, status);
4866                 END_PROFILE(SMBmkdir);
4867                 return;
4868         }
4869
4870         status = create_directory(conn, req, directory);
4871
4872         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4873
4874         if (!NT_STATUS_IS_OK(status)) {
4875
4876                 if (!use_nt_status()
4877                     && NT_STATUS_EQUAL(status,
4878                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
4879                         /*
4880                          * Yes, in the DOS error code case we get a
4881                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4882                          * samba4 torture test.
4883                          */
4884                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4885                 }
4886
4887                 reply_nterror(req, status);
4888                 END_PROFILE(SMBmkdir);
4889                 return;
4890         }
4891
4892         reply_outbuf(req, 0, 0);
4893
4894         DEBUG( 3, ( "mkdir %s\n", directory ) );
4895
4896         END_PROFILE(SMBmkdir);
4897         return;
4898 }
4899
4900 /****************************************************************************
4901  Static function used by reply_rmdir to delete an entire directory
4902  tree recursively. Return True on ok, False on fail.
4903 ****************************************************************************/
4904
4905 static bool recursive_rmdir(TALLOC_CTX *ctx,
4906                         connection_struct *conn,
4907                         char *directory)
4908 {
4909         const char *dname = NULL;
4910         bool ret = True;
4911         long offset = 0;
4912         struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
4913                                           NULL, 0);
4914
4915         if(dir_hnd == NULL)
4916                 return False;
4917
4918         while((dname = ReadDirName(dir_hnd, &offset))) {
4919                 char *fullname = NULL;
4920                 SMB_STRUCT_STAT st;
4921
4922                 if (ISDOT(dname) || ISDOTDOT(dname)) {
4923                         continue;
4924                 }
4925
4926                 if (!is_visible_file(conn, directory, dname, &st, False)) {
4927                         continue;
4928                 }
4929
4930                 /* Construct the full name. */
4931                 fullname = talloc_asprintf(ctx,
4932                                 "%s/%s",
4933                                 directory,
4934                                 dname);
4935                 if (!fullname) {
4936                         errno = ENOMEM;
4937                         ret = False;
4938                         break;
4939                 }
4940
4941                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4942                         ret = False;
4943                         break;
4944                 }
4945
4946                 if(st.st_mode & S_IFDIR) {
4947                         if(!recursive_rmdir(ctx, conn, fullname)) {
4948                                 ret = False;
4949                                 break;
4950                         }
4951                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4952                                 ret = False;
4953                                 break;
4954                         }
4955                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4956                         ret = False;
4957                         break;
4958                 }
4959                 TALLOC_FREE(fullname);
4960         }
4961         TALLOC_FREE(dir_hnd);
4962         return ret;
4963 }
4964
4965 /****************************************************************************
4966  The internals of the rmdir code - called elsewhere.
4967 ****************************************************************************/
4968
4969 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
4970                         connection_struct *conn,
4971                         const char *directory)
4972 {
4973         int ret;
4974         SMB_STRUCT_STAT st;
4975
4976         /* Might be a symlink. */
4977         if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4978                 return map_nt_error_from_unix(errno);
4979         }
4980
4981         if (S_ISLNK(st.st_mode)) {
4982                 /* Is what it points to a directory ? */
4983                 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4984                         return map_nt_error_from_unix(errno);
4985                 }
4986                 if (!(S_ISDIR(st.st_mode))) {
4987                         return NT_STATUS_NOT_A_DIRECTORY;
4988                 }
4989                 ret = SMB_VFS_UNLINK(conn,directory);
4990         } else {
4991                 ret = SMB_VFS_RMDIR(conn,directory);
4992         }
4993         if (ret == 0) {
4994                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4995                              FILE_NOTIFY_CHANGE_DIR_NAME,
4996                              directory);
4997                 return NT_STATUS_OK;
4998         }
4999
5000         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5001                 /*
5002                  * Check to see if the only thing in this directory are
5003                  * vetoed files/directories. If so then delete them and
5004                  * retry. If we fail to delete any of them (and we *don't*
5005                  * do a recursive delete) then fail the rmdir.
5006                  */
5007                 const char *dname;
5008                 long dirpos = 0;
5009                 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5010                                                   directory, NULL, 0);
5011
5012                 if(dir_hnd == NULL) {
5013                         errno = ENOTEMPTY;
5014                         goto err;
5015                 }
5016
5017                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5018                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5019                                 continue;
5020                         if (!is_visible_file(conn, directory, dname, &st, False))
5021                                 continue;
5022                         if(!IS_VETO_PATH(conn, dname)) {
5023                                 TALLOC_FREE(dir_hnd);
5024                                 errno = ENOTEMPTY;
5025                                 goto err;
5026                         }
5027                 }
5028
5029                 /* We only have veto files/directories. Recursive delete. */
5030
5031                 RewindDir(dir_hnd,&dirpos);
5032                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5033                         char *fullname = NULL;
5034
5035                         if (ISDOT(dname) || ISDOTDOT(dname)) {
5036                                 continue;
5037                         }
5038                         if (!is_visible_file(conn, directory, dname, &st, False)) {
5039                                 continue;
5040                         }
5041
5042                         fullname = talloc_asprintf(ctx,
5043                                         "%s/%s",
5044                                         directory,
5045                                         dname);
5046
5047                         if(!fullname) {
5048                                 errno = ENOMEM;
5049                                 break;
5050                         }
5051
5052                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5053                                 break;
5054                         }
5055                         if(st.st_mode & S_IFDIR) {
5056                                 if(lp_recursive_veto_delete(SNUM(conn))) {
5057                                         if(!recursive_rmdir(ctx, conn, fullname))
5058                                                 break;
5059                                 }
5060                                 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5061                                         break;
5062                                 }
5063                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5064                                 break;
5065                         }
5066                         TALLOC_FREE(fullname);
5067                 }
5068                 TALLOC_FREE(dir_hnd);
5069                 /* Retry the rmdir */
5070                 ret = SMB_VFS_RMDIR(conn,directory);
5071         }
5072
5073   err:
5074
5075         if (ret != 0) {
5076                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5077                          "%s\n", directory,strerror(errno)));
5078                 return map_nt_error_from_unix(errno);
5079         }
5080
5081         notify_fname(conn, NOTIFY_ACTION_REMOVED,
5082                      FILE_NOTIFY_CHANGE_DIR_NAME,
5083                      directory);
5084
5085         return NT_STATUS_OK;
5086 }
5087
5088 /****************************************************************************
5089  Reply to a rmdir.
5090 ****************************************************************************/
5091
5092 void reply_rmdir(struct smb_request *req)
5093 {
5094         connection_struct *conn = req->conn;
5095         char *directory = NULL;
5096         SMB_STRUCT_STAT sbuf;
5097         NTSTATUS status;
5098         TALLOC_CTX *ctx = talloc_tos();
5099
5100         START_PROFILE(SMBrmdir);
5101
5102         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
5103                         smb_buf(req->inbuf) + 1, 0,
5104                         STR_TERMINATE, &status);
5105         if (!NT_STATUS_IS_OK(status)) {
5106                 reply_nterror(req, status);
5107                 END_PROFILE(SMBrmdir);
5108                 return;
5109         }
5110
5111         status = resolve_dfspath(ctx, conn,
5112                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5113                                  directory,
5114                                  &directory);
5115         if (!NT_STATUS_IS_OK(status)) {
5116                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5117                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5118                                         ERRSRV, ERRbadpath);
5119                         END_PROFILE(SMBrmdir);
5120                         return;
5121                 }
5122                 reply_nterror(req, status);
5123                 END_PROFILE(SMBrmdir);
5124                 return;
5125         }
5126
5127         status = unix_convert(ctx, conn, directory, False, &directory,
5128                         NULL, &sbuf);
5129         if (!NT_STATUS_IS_OK(status)) {
5130                 reply_nterror(req, status);
5131                 END_PROFILE(SMBrmdir);
5132                 return;
5133         }
5134
5135         status = check_name(conn, directory);
5136         if (!NT_STATUS_IS_OK(status)) {
5137                 reply_nterror(req, status);
5138                 END_PROFILE(SMBrmdir);
5139                 return;
5140         }
5141
5142         dptr_closepath(directory, req->smbpid);
5143         status = rmdir_internals(ctx, conn, directory);
5144         if (!NT_STATUS_IS_OK(status)) {
5145                 reply_nterror(req, status);
5146                 END_PROFILE(SMBrmdir);
5147                 return;
5148         }
5149
5150         reply_outbuf(req, 0, 0);
5151
5152         DEBUG( 3, ( "rmdir %s\n", directory ) );
5153
5154         END_PROFILE(SMBrmdir);
5155         return;
5156 }
5157
5158 /*******************************************************************
5159  Resolve wildcards in a filename rename.
5160 ********************************************************************/
5161
5162 static bool resolve_wildcards(TALLOC_CTX *ctx,
5163                                 const char *name1,
5164                                 const char *name2,
5165                                 char **pp_newname)
5166 {
5167         char *name2_copy = NULL;
5168         char *root1 = NULL;
5169         char *root2 = NULL;
5170         char *ext1 = NULL;
5171         char *ext2 = NULL;
5172         char *p,*p2, *pname1, *pname2;
5173         
5174         name2_copy = talloc_strdup(ctx, name2);
5175         if (!name2_copy) {
5176                 return False;
5177         }
5178
5179         pname1 = strrchr_m(name1,'/');
5180         pname2 = strrchr_m(name2_copy,'/');
5181
5182         if (!pname1 || !pname2) {
5183                 return False;
5184         }
5185   
5186         /* Truncate the copy of name2 at the last '/' */
5187         *pname2 = '\0';
5188
5189         /* Now go past the '/' */
5190         pname1++;
5191         pname2++;
5192
5193         root1 = talloc_strdup(ctx, pname1);
5194         root2 = talloc_strdup(ctx, pname2);
5195
5196         if (!root1 || !root2) {
5197                 return False;
5198         }
5199
5200         p = strrchr_m(root1,'.');
5201         if (p) {
5202                 *p = 0;
5203                 ext1 = talloc_strdup(ctx, p+1);
5204         } else {
5205                 ext1 = talloc_strdup(ctx, "");
5206         }
5207         p = strrchr_m(root2,'.');
5208         if (p) {
5209                 *p = 0;
5210                 ext2 = talloc_strdup(ctx, p+1);
5211         } else {
5212                 ext2 = talloc_strdup(ctx, "");
5213         }
5214
5215         if (!ext1 || !ext2) {
5216                 return False;
5217         }
5218
5219         p = root1;
5220         p2 = root2;
5221         while (*p2) {
5222                 if (*p2 == '?') {
5223                         /* Hmmm. Should this be mb-aware ? */
5224                         *p2 = *p;
5225                         p2++;
5226                 } else if (*p2 == '*') {
5227                         *p2 = '\0';
5228                         root2 = talloc_asprintf(ctx, "%s%s",
5229                                                 root2,
5230                                                 p);
5231                         if (!root2) {
5232                                 return False;
5233                         }
5234                         break;
5235                 } else {
5236                         p2++;
5237                 }
5238                 if (*p) {
5239                         p++;
5240                 }
5241         }
5242
5243         p = ext1;
5244         p2 = ext2;
5245         while (*p2) {
5246                 if (*p2 == '?') {
5247                         /* Hmmm. Should this be mb-aware ? */
5248                         *p2 = *p;
5249                         p2++;
5250                 } else if (*p2 == '*') {
5251                         *p2 = '\0';
5252                         ext2 = talloc_asprintf(ctx, "%s%s",
5253                                                 ext2,
5254                                                 p);
5255                         if (!ext2) {
5256                                 return False;
5257                         }
5258                         break;
5259                 } else {
5260                         p2++;
5261                 }
5262                 if (*p) {
5263                         p++;
5264                 }
5265         }
5266
5267         if (*ext2) {
5268                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5269                                 name2_copy,
5270                                 root2,
5271                                 ext2);
5272         } else {
5273                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5274                                 name2_copy,
5275                                 root2);
5276         }
5277
5278         if (!*pp_newname) {
5279                 return False;
5280         }
5281
5282         return True;
5283 }
5284
5285 /****************************************************************************
5286  Ensure open files have their names updated. Updated to notify other smbd's
5287  asynchronously.
5288 ****************************************************************************/
5289
5290 static void rename_open_files(connection_struct *conn,
5291                               struct share_mode_lock *lck,
5292                               const char *newname)
5293 {
5294         files_struct *fsp;
5295         bool did_rename = False;
5296
5297         for(fsp = file_find_di_first(lck->id); fsp;
5298             fsp = file_find_di_next(fsp)) {
5299                 /* fsp_name is a relative path under the fsp. To change this for other
5300                    sharepaths we need to manipulate relative paths. */
5301                 /* TODO - create the absolute path and manipulate the newname
5302                    relative to the sharepath. */
5303                 if (fsp->conn != conn) {
5304                         continue;
5305                 }
5306                 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5307                           fsp->fnum, file_id_string_tos(&fsp->file_id),
5308                         fsp->fsp_name, newname ));
5309                 string_set(&fsp->fsp_name, newname);
5310                 did_rename = True;
5311         }
5312
5313         if (!did_rename) {
5314                 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5315                           file_id_string_tos(&lck->id), newname ));
5316         }
5317
5318         /* Send messages to all smbd's (not ourself) that the name has changed. */
5319         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5320                               newname);
5321 }
5322
5323 /****************************************************************************
5324  We need to check if the source path is a parent directory of the destination
5325  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5326  refuse the rename with a sharing violation. Under UNIX the above call can
5327  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5328  probably need to check that the client is a Windows one before disallowing
5329  this as a UNIX client (one with UNIX extensions) can know the source is a
5330  symlink and make this decision intelligently. Found by an excellent bug
5331  report from <AndyLiebman@aol.com>.
5332 ****************************************************************************/
5333
5334 static bool rename_path_prefix_equal(const char *src, const char *dest)
5335 {
5336         const char *psrc = src;
5337         const char *pdst = dest;
5338         size_t slen;
5339
5340         if (psrc[0] == '.' && psrc[1] == '/') {
5341                 psrc += 2;
5342         }
5343         if (pdst[0] == '.' && pdst[1] == '/') {
5344                 pdst += 2;
5345         }
5346         if ((slen = strlen(psrc)) > strlen(pdst)) {
5347                 return False;
5348         }
5349         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5350 }
5351
5352 /*
5353  * Do the notify calls from a rename
5354  */
5355
5356 static void notify_rename(connection_struct *conn, bool is_dir,
5357                           const char *oldpath, const char *newpath)
5358 {
5359         char *olddir, *newdir;
5360         const char *oldname, *newname;
5361         uint32 mask;
5362
5363         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5364                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5365
5366         if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
5367             || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
5368                 TALLOC_FREE(olddir);
5369                 return;
5370         }
5371
5372         if (strcmp(olddir, newdir) == 0) {
5373                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5374                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5375         }
5376         else {
5377                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5378                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5379         }
5380         TALLOC_FREE(olddir);
5381         TALLOC_FREE(newdir);
5382
5383         /* this is a strange one. w2k3 gives an additional event for
5384            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5385            files, but not directories */
5386         if (!is_dir) {
5387                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5388                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5389                              |FILE_NOTIFY_CHANGE_CREATION,
5390                              newpath);
5391         }
5392 }
5393
5394 /****************************************************************************
5395  Rename an open file - given an fsp.
5396 ****************************************************************************/
5397
5398 NTSTATUS rename_internals_fsp(connection_struct *conn,
5399                         files_struct *fsp,
5400                         char *newname,
5401                         const char *newname_last_component,
5402                         uint32 attrs,
5403                         bool replace_if_exists)
5404 {
5405         TALLOC_CTX *ctx = talloc_tos();
5406         SMB_STRUCT_STAT sbuf, sbuf1;
5407         NTSTATUS status = NT_STATUS_OK;
5408         struct share_mode_lock *lck = NULL;
5409         bool dst_exists;
5410
5411         ZERO_STRUCT(sbuf);
5412
5413         status = check_name(conn, newname);
5414         if (!NT_STATUS_IS_OK(status)) {
5415                 return status;
5416         }
5417
5418         /* Ensure newname contains a '/' */
5419         if(strrchr_m(newname,'/') == 0) {
5420                 newname = talloc_asprintf(ctx,
5421                                         "./%s",
5422                                         newname);
5423                 if (!newname) {
5424                         return NT_STATUS_NO_MEMORY;
5425                 }
5426         }
5427
5428         /*
5429          * Check for special case with case preserving and not
5430          * case sensitive. If the old last component differs from the original
5431          * last component only by case, then we should allow
5432          * the rename (user is trying to change the case of the
5433          * filename).
5434          */
5435
5436         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5437                         strequal(newname, fsp->fsp_name)) {
5438                 char *p;
5439                 char *newname_modified_last_component = NULL;
5440
5441                 /*
5442                  * Get the last component of the modified name.
5443                  * Note that we guarantee that newname contains a '/'
5444                  * character above.
5445                  */
5446                 p = strrchr_m(newname,'/');
5447                 newname_modified_last_component = talloc_strdup(ctx,
5448                                                 p+1);
5449                 if (!newname_modified_last_component) {
5450                         return NT_STATUS_NO_MEMORY;
5451                 }
5452
5453                 if(strcsequal(newname_modified_last_component,
5454                               newname_last_component) == False) {
5455                         /*
5456                          * Replace the modified last component with
5457                          * the original.
5458                          */
5459                         *p = '\0'; /* Truncate at the '/' */
5460                         newname = talloc_asprintf(ctx,
5461                                         "%s/%s",
5462                                         newname,
5463                                         newname_last_component);
5464                 }
5465         }
5466
5467         /*
5468          * If the src and dest names are identical - including case,
5469          * don't do the rename, just return success.
5470          */
5471
5472         if (strcsequal(fsp->fsp_name, newname)) {
5473                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5474                         newname));
5475                 return NT_STATUS_OK;
5476         }
5477
5478         /*
5479          * Have vfs_object_exist also fill sbuf1
5480          */
5481         dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5482
5483         if(!replace_if_exists && dst_exists) {
5484                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5485                         fsp->fsp_name,newname));
5486                 return NT_STATUS_OBJECT_NAME_COLLISION;
5487         }
5488
5489         if (dst_exists) {
5490                 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5491                 files_struct *dst_fsp = file_find_di_first(fileid);
5492                 if (dst_fsp) {
5493                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5494                         return NT_STATUS_ACCESS_DENIED;
5495                 }
5496         }
5497
5498         /* Ensure we have a valid stat struct for the source. */
5499         if (fsp->fh->fd != -1) {
5500                 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5501                         return map_nt_error_from_unix(errno);
5502                 }
5503         } else {
5504                 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5505                         return map_nt_error_from_unix(errno);
5506                 }
5507         }
5508
5509         status = can_rename(conn, fsp, attrs, &sbuf);
5510
5511         if (!NT_STATUS_IS_OK(status)) {
5512                 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5513                         nt_errstr(status), fsp->fsp_name,newname));
5514                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5515                         status = NT_STATUS_ACCESS_DENIED;
5516                 return status;
5517         }
5518
5519         if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5520                 return NT_STATUS_ACCESS_DENIED;
5521         }
5522
5523         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
5524
5525         /*
5526          * We have the file open ourselves, so not being able to get the
5527          * corresponding share mode lock is a fatal error.
5528          */
5529
5530         SMB_ASSERT(lck != NULL);
5531
5532         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5533                 uint32 create_options = fsp->fh->private_options;
5534
5535                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5536                         fsp->fsp_name,newname));
5537
5538                 rename_open_files(conn, lck, newname);
5539
5540                 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5541
5542                 /*
5543                  * A rename acts as a new file create w.r.t. allowing an initial delete
5544                  * on close, probably because in Windows there is a new handle to the
5545                  * new file. If initial delete on close was requested but not
5546                  * originally set, we need to set it here. This is probably not 100% correct,
5547                  * but will work for the CIFSFS client which in non-posix mode
5548                  * depends on these semantics. JRA.
5549                  */
5550
5551                 set_allow_initial_delete_on_close(lck, fsp, True);
5552
5553                 if (create_options & FILE_DELETE_ON_CLOSE) {
5554                         status = can_set_delete_on_close(fsp, True, 0);
5555
5556                         if (NT_STATUS_IS_OK(status)) {
5557                                 /* Note that here we set the *inital* delete on close flag,
5558                                  * not the regular one. The magic gets handled in close. */
5559                                 fsp->initial_delete_on_close = True;
5560                         }
5561                 }
5562                 TALLOC_FREE(lck);
5563                 return NT_STATUS_OK;
5564         }
5565
5566         TALLOC_FREE(lck);
5567
5568         if (errno == ENOTDIR || errno == EISDIR) {
5569                 status = NT_STATUS_OBJECT_NAME_COLLISION;
5570         } else {
5571                 status = map_nt_error_from_unix(errno);
5572         }
5573
5574         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5575                 nt_errstr(status), fsp->fsp_name,newname));
5576
5577         return status;
5578 }
5579
5580 /****************************************************************************
5581  The guts of the rename command, split out so it may be called by the NT SMB
5582  code.
5583 ****************************************************************************/
5584
5585 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5586                         connection_struct *conn,
5587                         struct smb_request *req,
5588                         const char *name_in,
5589                         const char *newname_in,
5590                         uint32 attrs,
5591                         bool replace_if_exists,
5592                         bool src_has_wild,
5593                         bool dest_has_wild)
5594 {
5595         char *directory = NULL;
5596         char *mask = NULL;
5597         char *last_component_src = NULL;
5598         char *last_component_dest = NULL;
5599         char *name = NULL;
5600         char *newname = NULL;
5601         char *p;
5602         int count=0;
5603         NTSTATUS status = NT_STATUS_OK;
5604         SMB_STRUCT_STAT sbuf1, sbuf2;
5605         struct smb_Dir *dir_hnd = NULL;
5606         const char *dname;
5607         long offset = 0;
5608
5609         ZERO_STRUCT(sbuf1);
5610         ZERO_STRUCT(sbuf2);
5611
5612         status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5613                         &last_component_src, &sbuf1);
5614         if (!NT_STATUS_IS_OK(status)) {
5615                 return status;
5616         }
5617
5618         status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5619                         &last_component_dest, &sbuf2);
5620         if (!NT_STATUS_IS_OK(status)) {
5621                 return status;
5622         }
5623
5624         /*
5625          * Split the old name into directory and last component
5626          * strings. Note that unix_convert may have stripped off a
5627          * leading ./ from both name and newname if the rename is
5628          * at the root of the share. We need to make sure either both
5629          * name and newname contain a / character or neither of them do
5630          * as this is checked in resolve_wildcards().
5631          */
5632
5633         p = strrchr_m(name,'/');
5634         if (!p) {
5635                 directory = talloc_strdup(ctx, ".");
5636                 if (!directory) {
5637                         return NT_STATUS_NO_MEMORY;
5638                 }
5639                 mask = name;
5640         } else {
5641                 *p = 0;
5642                 directory = talloc_strdup(ctx, name);
5643                 if (!directory) {
5644                         return NT_STATUS_NO_MEMORY;
5645                 }
5646                 mask = p+1;
5647                 *p = '/'; /* Replace needed for exceptional test below. */
5648         }
5649
5650         /*
5651          * We should only check the mangled cache
5652          * here if unix_convert failed. This means
5653          * that the path in 'mask' doesn't exist
5654          * on the file system and so we need to look
5655          * for a possible mangle. This patch from
5656          * Tine Smukavec <valentin.smukavec@hermes.si>.
5657          */
5658
5659         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5660                 char *new_mask = NULL;
5661                 mangle_lookup_name_from_8_3(ctx,
5662                                         mask,
5663                                         &new_mask,
5664                                         conn->params );
5665                 if (new_mask) {
5666                         mask = new_mask;
5667                 }
5668         }
5669
5670         if (!src_has_wild) {
5671                 files_struct *fsp;
5672
5673                 /*
5674                  * No wildcards - just process the one file.
5675                  */
5676                 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5677
5678                 /* Add a terminating '/' to the directory name. */
5679                 directory = talloc_asprintf_append(directory,
5680                                 "/%s",
5681                                 mask);
5682                 if (!directory) {
5683                         return NT_STATUS_NO_MEMORY;
5684                 }
5685
5686                 /* Ensure newname contains a '/' also */
5687                 if(strrchr_m(newname,'/') == 0) {
5688                         newname = talloc_asprintf(ctx,
5689                                                 "./%s",
5690                                                 newname);
5691                         if (!newname) {
5692                                 return NT_STATUS_NO_MEMORY;
5693                         }
5694                 }
5695
5696                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5697                           "case_preserve = %d, short case preserve = %d, "
5698                           "directory = %s, newname = %s, "
5699                           "last_component_dest = %s, is_8_3 = %d\n",
5700                           conn->case_sensitive, conn->case_preserve,
5701                           conn->short_case_preserve, directory,
5702                           newname, last_component_dest, is_short_name));
5703
5704                 /* The dest name still may have wildcards. */
5705                 if (dest_has_wild) {
5706                         char *mod_newname = NULL;
5707                         if (!resolve_wildcards(ctx,
5708                                         directory,newname,&mod_newname)) {
5709                                 DEBUG(6, ("rename_internals: resolve_wildcards "
5710                                         "%s %s failed\n",
5711                                         directory,
5712                                         newname));
5713                                 return NT_STATUS_NO_MEMORY;
5714                         }
5715                         newname = mod_newname;
5716                 }
5717
5718                 ZERO_STRUCT(sbuf1);
5719                 SMB_VFS_STAT(conn, directory, &sbuf1);
5720
5721                 status = S_ISDIR(sbuf1.st_mode) ?
5722                         open_directory(conn, req, directory, &sbuf1,
5723                                        DELETE_ACCESS,
5724                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5725                                        FILE_OPEN, 0, 0, NULL,
5726                                        &fsp)
5727                         : open_file_ntcreate(conn, req, directory, &sbuf1,
5728                                              DELETE_ACCESS,
5729                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5730                                              FILE_OPEN, 0, 0, 0, NULL,
5731                                              &fsp);
5732
5733                 if (!NT_STATUS_IS_OK(status)) {
5734                         DEBUG(3, ("Could not open rename source %s: %s\n",
5735                                   directory, nt_errstr(status)));
5736                         return status;
5737                 }
5738
5739                 status = rename_internals_fsp(conn, fsp, newname,
5740                                               last_component_dest,
5741                                               attrs, replace_if_exists);
5742
5743                 close_file(fsp, NORMAL_CLOSE);
5744
5745                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5746                           nt_errstr(status), directory,newname));
5747
5748                 return status;
5749         }
5750
5751         /*
5752          * Wildcards - process each file that matches.
5753          */
5754         if (strequal(mask,"????????.???")) {
5755                 mask[0] = '*';
5756                 mask[1] = '\0';
5757         }
5758
5759         status = check_name(conn, directory);
5760         if (!NT_STATUS_IS_OK(status)) {
5761                 return status;
5762         }
5763
5764         dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
5765         if (dir_hnd == NULL) {
5766                 return map_nt_error_from_unix(errno);
5767         }
5768
5769         status = NT_STATUS_NO_SUCH_FILE;
5770         /*
5771          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5772          * - gentest fix. JRA
5773          */
5774
5775         while ((dname = ReadDirName(dir_hnd, &offset))) {
5776                 files_struct *fsp = NULL;
5777                 char *fname = NULL;
5778                 char *destname = NULL;
5779                 bool sysdir_entry = False;
5780
5781                 /* Quick check for "." and ".." */
5782                 if (ISDOT(dname) || ISDOTDOT(dname)) {
5783                         if (attrs & aDIR) {
5784                                 sysdir_entry = True;
5785                         } else {
5786                                 continue;
5787                         }
5788                 }
5789
5790                 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5791                         continue;
5792                 }
5793
5794                 if(!mask_match(dname, mask, conn->case_sensitive)) {
5795                         continue;
5796                 }
5797
5798                 if (sysdir_entry) {
5799                         status = NT_STATUS_OBJECT_NAME_INVALID;
5800                         break;
5801                 }
5802
5803                 fname = talloc_asprintf(ctx,
5804                                 "%s/%s",
5805                                 directory,
5806                                 dname);
5807                 if (!fname) {
5808                         return NT_STATUS_NO_MEMORY;
5809                 }
5810
5811                 if (!resolve_wildcards(ctx,
5812                                 fname,newname,&destname)) {
5813                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
5814                                   fname, destname));
5815                         TALLOC_FREE(fname);
5816                         continue;
5817                 }
5818                 if (!destname) {
5819                         return NT_STATUS_NO_MEMORY;
5820                 }
5821
5822                 ZERO_STRUCT(sbuf1);
5823                 SMB_VFS_STAT(conn, fname, &sbuf1);
5824
5825                 status = S_ISDIR(sbuf1.st_mode) ?
5826                         open_directory(conn, req, fname, &sbuf1,
5827                                        DELETE_ACCESS,
5828                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5829                                        FILE_OPEN, 0, 0, NULL,
5830                                        &fsp)
5831                         : open_file_ntcreate(conn, req, fname, &sbuf1,
5832                                              DELETE_ACCESS,
5833                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5834                                              FILE_OPEN, 0, 0, 0, NULL,
5835                                              &fsp);
5836
5837                 if (!NT_STATUS_IS_OK(status)) {
5838                         DEBUG(3,("rename_internals: open_file_ntcreate "
5839                                  "returned %s rename %s -> %s\n",
5840                                  nt_errstr(status), directory, newname));
5841                         break;
5842                 }
5843
5844                 status = rename_internals_fsp(conn, fsp, destname, dname,
5845                                               attrs, replace_if_exists);
5846
5847                 close_file(fsp, NORMAL_CLOSE);
5848
5849                 if (!NT_STATUS_IS_OK(status)) {
5850                         DEBUG(3, ("rename_internals_fsp returned %s for "
5851                                   "rename %s -> %s\n", nt_errstr(status),
5852                                   directory, newname));
5853                         break;
5854                 }
5855
5856                 count++;
5857
5858                 DEBUG(3,("rename_internals: doing rename on %s -> "
5859                          "%s\n",fname,destname));
5860
5861                 TALLOC_FREE(fname);
5862                 TALLOC_FREE(destname);
5863         }
5864         TALLOC_FREE(dir_hnd);
5865
5866         if (count == 0 && NT_STATUS_IS_OK(status)) {
5867                 status = map_nt_error_from_unix(errno);
5868         }
5869
5870         return status;
5871 }
5872
5873 /****************************************************************************
5874  Reply to a mv.
5875 ****************************************************************************/
5876
5877 void reply_mv(struct smb_request *req)
5878 {
5879         connection_struct *conn = req->conn;
5880         char *name = NULL;
5881         char *newname = NULL;
5882         char *p;
5883         uint32 attrs;
5884         NTSTATUS status;
5885         bool src_has_wcard = False;
5886         bool dest_has_wcard = False;
5887         TALLOC_CTX *ctx = talloc_tos();
5888
5889         START_PROFILE(SMBmv);
5890
5891         if (req->wct < 1) {
5892                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5893                 END_PROFILE(SMBmv);
5894                 return;
5895         }
5896
5897         attrs = SVAL(req->inbuf,smb_vwv0);
5898
5899         p = smb_buf(req->inbuf) + 1;
5900         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
5901                                    0, STR_TERMINATE, &status,
5902                                    &src_has_wcard);
5903         if (!NT_STATUS_IS_OK(status)) {
5904                 reply_nterror(req, status);
5905                 END_PROFILE(SMBmv);
5906                 return;
5907         }
5908         p++;
5909         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
5910                                    0, STR_TERMINATE, &status,
5911                                    &dest_has_wcard);
5912         if (!NT_STATUS_IS_OK(status)) {
5913                 reply_nterror(req, status);
5914                 END_PROFILE(SMBmv);
5915                 return;
5916         }
5917
5918         status = resolve_dfspath_wcard(ctx, conn,
5919                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5920                                        name,
5921                                        &name,
5922                                        &src_has_wcard);
5923         if (!NT_STATUS_IS_OK(status)) {
5924                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5925                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5926                                         ERRSRV, ERRbadpath);
5927                         END_PROFILE(SMBmv);
5928                         return;
5929                 }
5930                 reply_nterror(req, status);
5931                 END_PROFILE(SMBmv);
5932                 return;
5933         }
5934
5935         status = resolve_dfspath_wcard(ctx, conn,
5936                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5937                                        newname,
5938                                        &newname,
5939                                        &dest_has_wcard);
5940         if (!NT_STATUS_IS_OK(status)) {
5941                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5942                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5943                                         ERRSRV, ERRbadpath);
5944                         END_PROFILE(SMBmv);
5945                         return;
5946                 }
5947                 reply_nterror(req, status);
5948                 END_PROFILE(SMBmv);
5949                 return;
5950         }
5951
5952         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5953
5954         status = rename_internals(ctx, conn, req, name, newname, attrs, False,
5955                                   src_has_wcard, dest_has_wcard);
5956         if (!NT_STATUS_IS_OK(status)) {
5957                 if (open_was_deferred(req->mid)) {
5958                         /* We have re-scheduled this call. */
5959                         END_PROFILE(SMBmv);
5960                         return;
5961                 }
5962                 reply_nterror(req, status);
5963                 END_PROFILE(SMBmv);
5964                 return;
5965         }
5966
5967         reply_outbuf(req, 0, 0);
5968
5969         END_PROFILE(SMBmv);
5970         return;
5971 }
5972
5973 /*******************************************************************
5974  Copy a file as part of a reply_copy.
5975 ******************************************************************/
5976
5977 /*
5978  * TODO: check error codes on all callers
5979  */
5980
5981 NTSTATUS copy_file(TALLOC_CTX *ctx,
5982                         connection_struct *conn,
5983                         const char *src,
5984                         const char *dest1,
5985                         int ofun,
5986                         int count,
5987                         bool target_is_directory)
5988 {
5989         SMB_STRUCT_STAT src_sbuf, sbuf2;
5990         SMB_OFF_T ret=-1;
5991         files_struct *fsp1,*fsp2;
5992         char *dest = NULL;
5993         uint32 dosattrs;
5994         uint32 new_create_disposition;
5995         NTSTATUS status;
5996
5997         dest = talloc_strdup(ctx, dest1);
5998         if (!dest) {
5999                 return NT_STATUS_NO_MEMORY;
6000         }
6001         if (target_is_directory) {
6002                 const char *p = strrchr_m(src,'/');
6003                 if (p) {
6004                         p++;
6005                 } else {
6006                         p = src;
6007                 }
6008                 dest = talloc_asprintf_append(dest,
6009                                 "/%s",
6010                                 p);
6011                 if (!dest) {
6012                         return NT_STATUS_NO_MEMORY;
6013                 }
6014         }
6015
6016         if (!vfs_file_exist(conn,src,&src_sbuf)) {
6017                 TALLOC_FREE(dest);
6018                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6019         }
6020
6021         if (!target_is_directory && count) {
6022                 new_create_disposition = FILE_OPEN;
6023         } else {
6024                 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6025                                 NULL, NULL, &new_create_disposition, NULL)) {
6026                         TALLOC_FREE(dest);
6027                         return NT_STATUS_INVALID_PARAMETER;
6028                 }
6029         }
6030
6031         status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
6032                         FILE_GENERIC_READ,
6033                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6034                         FILE_OPEN,
6035                         0,
6036                         FILE_ATTRIBUTE_NORMAL,
6037                         INTERNAL_OPEN_ONLY,
6038                         NULL, &fsp1);
6039
6040         if (!NT_STATUS_IS_OK(status)) {
6041                 TALLOC_FREE(dest);
6042                 return status;
6043         }
6044
6045         dosattrs = dos_mode(conn, src, &src_sbuf);
6046         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6047                 ZERO_STRUCTP(&sbuf2);
6048         }
6049
6050         status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
6051                         FILE_GENERIC_WRITE,
6052                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6053                         new_create_disposition,
6054                         0,
6055                         dosattrs,
6056                         INTERNAL_OPEN_ONLY,
6057                         NULL, &fsp2);
6058
6059         TALLOC_FREE(dest);
6060
6061         if (!NT_STATUS_IS_OK(status)) {
6062                 close_file(fsp1,ERROR_CLOSE);
6063                 return status;
6064         }
6065
6066         if ((ofun&3) == 1) {
6067                 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6068                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6069                         /*
6070                          * Stop the copy from occurring.
6071                          */
6072                         ret = -1;
6073                         src_sbuf.st_size = 0;
6074                 }
6075         }
6076
6077         if (src_sbuf.st_size) {
6078                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6079         }
6080
6081         close_file(fsp1,NORMAL_CLOSE);
6082
6083         /* Ensure the modtime is set correctly on the destination file. */
6084         fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
6085
6086         /*
6087          * As we are opening fsp1 read-only we only expect
6088          * an error on close on fsp2 if we are out of space.
6089          * Thus we don't look at the error return from the
6090          * close of fsp1.
6091          */
6092         status = close_file(fsp2,NORMAL_CLOSE);
6093
6094         if (!NT_STATUS_IS_OK(status)) {
6095                 return status;
6096         }
6097
6098         if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6099                 return NT_STATUS_DISK_FULL;
6100         }
6101
6102         return NT_STATUS_OK;
6103 }
6104
6105 /****************************************************************************
6106  Reply to a file copy.
6107 ****************************************************************************/
6108
6109 void reply_copy(struct smb_request *req)
6110 {
6111         connection_struct *conn = req->conn;
6112         char *name = NULL;
6113         char *newname = NULL;
6114         char *directory = NULL;
6115         char *mask = NULL;
6116         char *p;
6117         int count=0;
6118         int error = ERRnoaccess;
6119         int err = 0;
6120         int tid2;
6121         int ofun;
6122         int flags;
6123         bool target_is_directory=False;
6124         bool source_has_wild = False;
6125         bool dest_has_wild = False;
6126         SMB_STRUCT_STAT sbuf1, sbuf2;
6127         NTSTATUS status;
6128         TALLOC_CTX *ctx = talloc_tos();
6129
6130         START_PROFILE(SMBcopy);
6131
6132         if (req->wct < 3) {
6133                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6134                 END_PROFILE(SMBcopy);
6135                 return;
6136         }
6137
6138         tid2 = SVAL(req->inbuf,smb_vwv0);
6139         ofun = SVAL(req->inbuf,smb_vwv1);
6140         flags = SVAL(req->inbuf,smb_vwv2);
6141
6142         p = smb_buf(req->inbuf);
6143         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
6144                                    0, STR_TERMINATE, &status,
6145                                    &source_has_wild);
6146         if (!NT_STATUS_IS_OK(status)) {
6147                 reply_nterror(req, status);
6148                 END_PROFILE(SMBcopy);
6149                 return;
6150         }
6151         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
6152                                    0, STR_TERMINATE, &status,
6153                                    &dest_has_wild);
6154         if (!NT_STATUS_IS_OK(status)) {
6155                 reply_nterror(req, status);
6156                 END_PROFILE(SMBcopy);
6157                 return;
6158         }
6159
6160         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6161
6162         if (tid2 != conn->cnum) {
6163                 /* can't currently handle inter share copies XXXX */
6164                 DEBUG(3,("Rejecting inter-share copy\n"));
6165                 reply_doserror(req, ERRSRV, ERRinvdevice);
6166                 END_PROFILE(SMBcopy);
6167                 return;
6168         }
6169
6170         status = resolve_dfspath_wcard(ctx, conn,
6171                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6172                                        name,
6173                                        &name,
6174                                        &source_has_wild);
6175         if (!NT_STATUS_IS_OK(status)) {
6176                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6177                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6178                                         ERRSRV, ERRbadpath);
6179                         END_PROFILE(SMBcopy);
6180                         return;
6181                 }
6182                 reply_nterror(req, status);
6183                 END_PROFILE(SMBcopy);
6184                 return;
6185         }
6186
6187         status = resolve_dfspath_wcard(ctx, conn,
6188                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6189                                        newname,
6190                                        &newname,
6191                                        &dest_has_wild);
6192         if (!NT_STATUS_IS_OK(status)) {
6193                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6194                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6195                                         ERRSRV, ERRbadpath);
6196                         END_PROFILE(SMBcopy);
6197                         return;
6198                 }
6199                 reply_nterror(req, status);
6200                 END_PROFILE(SMBcopy);
6201                 return;
6202         }
6203
6204         status = unix_convert(ctx, conn, name, source_has_wild,
6205                         &name, NULL, &sbuf1);
6206         if (!NT_STATUS_IS_OK(status)) {
6207                 reply_nterror(req, status);
6208                 END_PROFILE(SMBcopy);
6209                 return;
6210         }
6211
6212         status = unix_convert(ctx, conn, newname, dest_has_wild,
6213                         &newname, NULL, &sbuf2);
6214         if (!NT_STATUS_IS_OK(status)) {
6215                 reply_nterror(req, status);
6216                 END_PROFILE(SMBcopy);
6217                 return;
6218         }
6219
6220         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6221
6222         if ((flags&1) && target_is_directory) {
6223                 reply_doserror(req, ERRDOS, ERRbadfile);
6224                 END_PROFILE(SMBcopy);
6225                 return;
6226         }
6227
6228         if ((flags&2) && !target_is_directory) {
6229                 reply_doserror(req, ERRDOS, ERRbadpath);
6230                 END_PROFILE(SMBcopy);
6231                 return;
6232         }
6233
6234         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6235                 /* wants a tree copy! XXXX */
6236                 DEBUG(3,("Rejecting tree copy\n"));
6237                 reply_doserror(req, ERRSRV, ERRerror);
6238                 END_PROFILE(SMBcopy);
6239                 return;
6240         }
6241
6242         p = strrchr_m(name,'/');
6243         if (!p) {
6244                 directory = talloc_strdup(ctx, "./");
6245                 if (!directory) {
6246                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6247                         END_PROFILE(SMBcopy);
6248                         return;
6249                 }
6250                 mask = name;
6251         } else {
6252                 *p = 0;
6253                 directory = talloc_strdup(ctx, name);
6254                 if (!directory) {
6255                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6256                         END_PROFILE(SMBcopy);
6257                         return;
6258                 }
6259                 mask = p+1;
6260         }
6261
6262         /*
6263          * We should only check the mangled cache
6264          * here if unix_convert failed. This means
6265          * that the path in 'mask' doesn't exist
6266          * on the file system and so we need to look
6267          * for a possible mangle. This patch from
6268          * Tine Smukavec <valentin.smukavec@hermes.si>.
6269          */
6270
6271         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6272                 char *new_mask = NULL;
6273                 mangle_lookup_name_from_8_3(ctx,
6274                                         mask,
6275                                         &new_mask,
6276                                         conn->params );
6277                 if (new_mask) {
6278                         mask = new_mask;
6279                 }
6280         }
6281
6282         if (!source_has_wild) {
6283                 directory = talloc_asprintf_append(directory,
6284                                 "/%s",
6285                                 mask);
6286                 if (dest_has_wild) {
6287                         char *mod_newname = NULL;
6288                         if (!resolve_wildcards(ctx,
6289                                         directory,newname,&mod_newname)) {
6290                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6291                                 END_PROFILE(SMBcopy);
6292                                 return;
6293                         }
6294                         newname = mod_newname;
6295                 }
6296
6297                 status = check_name(conn, directory);
6298                 if (!NT_STATUS_IS_OK(status)) {
6299                         reply_nterror(req, status);
6300                         END_PROFILE(SMBcopy);
6301                         return;
6302                 }
6303
6304                 status = check_name(conn, newname);
6305                 if (!NT_STATUS_IS_OK(status)) {
6306                         reply_nterror(req, status);
6307                         END_PROFILE(SMBcopy);
6308                         return;
6309                 }
6310
6311                 status = copy_file(ctx,conn,directory,newname,ofun,
6312                                 count,target_is_directory);
6313
6314                 if(!NT_STATUS_IS_OK(status)) {
6315                         reply_nterror(req, status);
6316                         END_PROFILE(SMBcopy);
6317                         return;
6318                 } else {
6319                         count++;
6320                 }
6321         } else {
6322                 struct smb_Dir *dir_hnd = NULL;
6323                 const char *dname = NULL;
6324                 long offset = 0;
6325
6326                 if (strequal(mask,"????????.???")) {
6327                         mask[0] = '*';
6328                         mask[1] = '\0';
6329                 }
6330
6331                 status = check_name(conn, directory);
6332                 if (!NT_STATUS_IS_OK(status)) {
6333                         reply_nterror(req, status);
6334                         END_PROFILE(SMBcopy);
6335                         return;
6336                 }
6337
6338                 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6339                 if (dir_hnd == NULL) {
6340                         status = map_nt_error_from_unix(errno);
6341                         reply_nterror(req, status);
6342                         END_PROFILE(SMBcopy);
6343                         return;
6344                 }
6345
6346                 error = ERRbadfile;
6347
6348                 while ((dname = ReadDirName(dir_hnd, &offset))) {
6349                         char *destname = NULL;
6350                         char *fname = NULL;
6351
6352                         if (ISDOT(dname) || ISDOTDOT(dname)) {
6353                                 continue;
6354                         }
6355
6356                         if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6357                                 continue;
6358                         }
6359
6360                         if(!mask_match(dname, mask, conn->case_sensitive)) {
6361                                 continue;
6362                         }
6363
6364                         error = ERRnoaccess;
6365                         fname = talloc_asprintf(ctx,
6366                                         "%s/%s",
6367                                         directory,
6368                                         dname);
6369                         if (!fname) {
6370                                 TALLOC_FREE(dir_hnd);
6371                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6372                                 END_PROFILE(SMBcopy);
6373                                 return;
6374                         }
6375
6376                         if (!resolve_wildcards(ctx,
6377                                         fname,newname,&destname)) {
6378                                 continue;
6379                         }
6380                         if (!destname) {
6381                                 TALLOC_FREE(dir_hnd);
6382                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6383                                 END_PROFILE(SMBcopy);
6384                                 return;
6385                         }
6386
6387                         status = check_name(conn, fname);
6388                         if (!NT_STATUS_IS_OK(status)) {
6389                                 TALLOC_FREE(dir_hnd);
6390                                 reply_nterror(req, status);
6391                                 END_PROFILE(SMBcopy);
6392                                 return;
6393                         }
6394
6395                         status = check_name(conn, destname);
6396                         if (!NT_STATUS_IS_OK(status)) {
6397                                 TALLOC_FREE(dir_hnd);
6398                                 reply_nterror(req, status);
6399                                 END_PROFILE(SMBcopy);
6400                                 return;
6401                         }
6402
6403                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6404
6405                         status = copy_file(ctx,conn,fname,destname,ofun,
6406                                         count,target_is_directory);
6407                         if (NT_STATUS_IS_OK(status)) {
6408                                 count++;
6409                         }
6410                         TALLOC_FREE(fname);
6411                         TALLOC_FREE(destname);
6412                 }
6413                 TALLOC_FREE(dir_hnd);
6414         }
6415
6416         if (count == 0) {
6417                 if(err) {
6418                         /* Error on close... */
6419                         errno = err;
6420                         reply_unixerror(req, ERRHRD, ERRgeneral);
6421                         END_PROFILE(SMBcopy);
6422                         return;
6423                 }
6424
6425                 reply_doserror(req, ERRDOS, error);
6426                 END_PROFILE(SMBcopy);
6427                 return;
6428         }
6429
6430         reply_outbuf(req, 1, 0);
6431         SSVAL(req->outbuf,smb_vwv0,count);
6432
6433         END_PROFILE(SMBcopy);
6434         return;
6435 }
6436
6437 #undef DBGC_CLASS
6438 #define DBGC_CLASS DBGC_LOCKING
6439
6440 /****************************************************************************
6441  Get a lock pid, dealing with large count requests.
6442 ****************************************************************************/
6443
6444 uint32 get_lock_pid( char *data, int data_offset, bool large_file_format)
6445 {
6446         if(!large_file_format)
6447                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6448         else
6449                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6450 }
6451
6452 /****************************************************************************
6453  Get a lock count, dealing with large count requests.
6454 ****************************************************************************/
6455
6456 SMB_BIG_UINT get_lock_count( char *data, int data_offset, bool large_file_format)
6457 {
6458         SMB_BIG_UINT count = 0;
6459
6460         if(!large_file_format) {
6461                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6462         } else {
6463
6464 #if defined(HAVE_LONGLONG)
6465                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6466                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6467 #else /* HAVE_LONGLONG */
6468
6469                 /*
6470                  * NT4.x seems to be broken in that it sends large file (64 bit)
6471                  * lockingX calls even if the CAP_LARGE_FILES was *not*
6472                  * negotiated. For boxes without large unsigned ints truncate the
6473                  * lock count by dropping the top 32 bits.
6474                  */
6475
6476                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6477                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6478                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6479                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6480                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6481                 }
6482
6483                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6484 #endif /* HAVE_LONGLONG */
6485         }
6486
6487         return count;
6488 }
6489
6490 #if !defined(HAVE_LONGLONG)
6491 /****************************************************************************
6492  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6493 ****************************************************************************/
6494
6495 static uint32 map_lock_offset(uint32 high, uint32 low)
6496 {
6497         unsigned int i;
6498         uint32 mask = 0;
6499         uint32 highcopy = high;
6500  
6501         /*
6502          * Try and find out how many significant bits there are in high.
6503          */
6504  
6505         for(i = 0; highcopy; i++)
6506                 highcopy >>= 1;
6507  
6508         /*
6509          * We use 31 bits not 32 here as POSIX
6510          * lock offsets may not be negative.
6511          */
6512  
6513         mask = (~0) << (31 - i);
6514  
6515         if(low & mask)
6516                 return 0; /* Fail. */
6517  
6518         high <<= (31 - i);
6519  
6520         return (high|low);
6521 }
6522 #endif /* !defined(HAVE_LONGLONG) */
6523
6524 /****************************************************************************
6525  Get a lock offset, dealing with large offset requests.
6526 ****************************************************************************/
6527
6528 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_format, bool *err)
6529 {
6530         SMB_BIG_UINT offset = 0;
6531
6532         *err = False;
6533
6534         if(!large_file_format) {
6535                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6536         } else {
6537
6538 #if defined(HAVE_LONGLONG)
6539                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6540                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6541 #else /* HAVE_LONGLONG */
6542
6543                 /*
6544                  * NT4.x seems to be broken in that it sends large file (64 bit)
6545                  * lockingX calls even if the CAP_LARGE_FILES was *not*
6546                  * negotiated. For boxes without large unsigned ints mangle the
6547                  * lock offset by mapping the top 32 bits onto the lower 32.
6548                  */
6549       
6550                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6551                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6552                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6553                         uint32 new_low = 0;
6554
6555                         if((new_low = map_lock_offset(high, low)) == 0) {
6556                                 *err = True;
6557                                 return (SMB_BIG_UINT)-1;
6558                         }
6559
6560                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6561                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6562                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6563                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6564                 }
6565
6566                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6567 #endif /* HAVE_LONGLONG */
6568         }
6569
6570         return offset;
6571 }
6572
6573 /****************************************************************************
6574  Reply to a lockingX request.
6575 ****************************************************************************/
6576
6577 void reply_lockingX(struct smb_request *req)
6578 {
6579         connection_struct *conn = req->conn;
6580         files_struct *fsp;
6581         unsigned char locktype;
6582         unsigned char oplocklevel;
6583         uint16 num_ulocks;
6584         uint16 num_locks;
6585         SMB_BIG_UINT count = 0, offset = 0;
6586         uint32 lock_pid;
6587         int32 lock_timeout;
6588         int i;
6589         char *data;
6590         bool large_file_format;
6591         bool err;
6592         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6593
6594         START_PROFILE(SMBlockingX);
6595
6596         if (req->wct < 8) {
6597                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6598                 END_PROFILE(SMBlockingX);
6599                 return;
6600         }
6601         
6602         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
6603         locktype = CVAL(req->inbuf,smb_vwv3);
6604         oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
6605         num_ulocks = SVAL(req->inbuf,smb_vwv6);
6606         num_locks = SVAL(req->inbuf,smb_vwv7);
6607         lock_timeout = IVAL(req->inbuf,smb_vwv4);
6608         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6609
6610         if (!check_fsp(conn, req, fsp, &current_user)) {
6611                 END_PROFILE(SMBlockingX);
6612                 return;
6613         }
6614         
6615         data = smb_buf(req->inbuf);
6616
6617         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6618                 /* we don't support these - and CANCEL_LOCK makes w2k
6619                    and XP reboot so I don't really want to be
6620                    compatible! (tridge) */
6621                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6622                 END_PROFILE(SMBlockingX);
6623                 return;
6624         }
6625         
6626         /* Check if this is an oplock break on a file
6627            we have granted an oplock on.
6628         */
6629         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6630                 /* Client can insist on breaking to none. */
6631                 bool break_to_none = (oplocklevel == 0);
6632                 bool result;
6633
6634                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6635                          "for fnum = %d\n", (unsigned int)oplocklevel,
6636                          fsp->fnum ));
6637
6638                 /*
6639                  * Make sure we have granted an exclusive or batch oplock on
6640                  * this file.
6641                  */
6642                 
6643                 if (fsp->oplock_type == 0) {
6644
6645                         /* The Samba4 nbench simulator doesn't understand
6646                            the difference between break to level2 and break
6647                            to none from level2 - it sends oplock break
6648                            replies in both cases. Don't keep logging an error
6649                            message here - just ignore it. JRA. */
6650
6651                         DEBUG(5,("reply_lockingX: Error : oplock break from "
6652                                  "client for fnum = %d (oplock=%d) and no "
6653                                  "oplock granted on this file (%s).\n",
6654                                  fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6655
6656                         /* if this is a pure oplock break request then don't
6657                          * send a reply */
6658                         if (num_locks == 0 && num_ulocks == 0) {
6659                                 END_PROFILE(SMBlockingX);
6660                                 return;
6661                         } else {
6662                                 END_PROFILE(SMBlockingX);
6663                                 reply_doserror(req, ERRDOS, ERRlock);
6664                                 return;
6665                         }
6666                 }
6667
6668                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6669                     (break_to_none)) {
6670                         result = remove_oplock(fsp);
6671                 } else {
6672                         result = downgrade_oplock(fsp);
6673                 }
6674                 
6675                 if (!result) {
6676                         DEBUG(0, ("reply_lockingX: error in removing "
6677                                   "oplock on file %s\n", fsp->fsp_name));
6678                         /* Hmmm. Is this panic justified? */
6679                         smb_panic("internal tdb error");
6680                 }
6681
6682                 reply_to_oplock_break_requests(fsp);
6683
6684                 /* if this is a pure oplock break request then don't send a
6685                  * reply */
6686                 if (num_locks == 0 && num_ulocks == 0) {
6687                         /* Sanity check - ensure a pure oplock break is not a
6688                            chained request. */
6689                         if(CVAL(req->inbuf,smb_vwv0) != 0xff)
6690                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
6691                                          "break is a chained %d request !\n",
6692                                          (unsigned int)CVAL(req->inbuf,
6693                                                             smb_vwv0) ));
6694                         END_PROFILE(SMBlockingX);
6695                         return;
6696                 }
6697         }
6698
6699         /*
6700          * We do this check *after* we have checked this is not a oplock break
6701          * response message. JRA.
6702          */
6703         
6704         release_level_2_oplocks_on_change(fsp);
6705
6706         if (smb_buflen(req->inbuf) <
6707             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6708                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6709                 END_PROFILE(SMBlockingX);
6710                 return;
6711         }
6712         
6713         /* Data now points at the beginning of the list
6714            of smb_unlkrng structs */
6715         for(i = 0; i < (int)num_ulocks; i++) {
6716                 lock_pid = get_lock_pid( data, i, large_file_format);
6717                 count = get_lock_count( data, i, large_file_format);
6718                 offset = get_lock_offset( data, i, large_file_format, &err);
6719                 
6720                 /*
6721                  * There is no error code marked "stupid client bug".... :-).
6722                  */
6723                 if(err) {
6724                         END_PROFILE(SMBlockingX);
6725                         reply_doserror(req, ERRDOS, ERRnoaccess);
6726                         return;
6727                 }
6728
6729                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6730                           "pid %u, file %s\n", (double)offset, (double)count,
6731                           (unsigned int)lock_pid, fsp->fsp_name ));
6732                 
6733                 status = do_unlock(smbd_messaging_context(),
6734                                 fsp,
6735                                 lock_pid,
6736                                 count,
6737                                 offset,
6738                                 WINDOWS_LOCK);
6739
6740                 if (NT_STATUS_V(status)) {
6741                         END_PROFILE(SMBlockingX);
6742                         reply_nterror(req, status);
6743                         return;
6744                 }
6745         }
6746
6747         /* Setup the timeout in seconds. */
6748
6749         if (!lp_blocking_locks(SNUM(conn))) {
6750                 lock_timeout = 0;
6751         }
6752         
6753         /* Now do any requested locks */
6754         data += ((large_file_format ? 20 : 10)*num_ulocks);
6755         
6756         /* Data now points at the beginning of the list
6757            of smb_lkrng structs */
6758         
6759         for(i = 0; i < (int)num_locks; i++) {
6760                 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6761                                 READ_LOCK:WRITE_LOCK);
6762                 lock_pid = get_lock_pid( data, i, large_file_format);
6763                 count = get_lock_count( data, i, large_file_format);
6764                 offset = get_lock_offset( data, i, large_file_format, &err);
6765                 
6766                 /*
6767                  * There is no error code marked "stupid client bug".... :-).
6768                  */
6769                 if(err) {
6770                         END_PROFILE(SMBlockingX);
6771                         reply_doserror(req, ERRDOS, ERRnoaccess);
6772                         return;
6773                 }
6774                 
6775                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6776                           "%u, file %s timeout = %d\n", (double)offset,
6777                           (double)count, (unsigned int)lock_pid,
6778                           fsp->fsp_name, (int)lock_timeout ));
6779                 
6780                 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6781                         if (lp_blocking_locks(SNUM(conn))) {
6782
6783                                 /* Schedule a message to ourselves to
6784                                    remove the blocking lock record and
6785                                    return the right error. */
6786
6787                                 if (!blocking_lock_cancel(fsp,
6788                                                 lock_pid,
6789                                                 offset,
6790                                                 count,
6791                                                 WINDOWS_LOCK,
6792                                                 locktype,
6793                                                 NT_STATUS_FILE_LOCK_CONFLICT)) {
6794                                         END_PROFILE(SMBlockingX);
6795                                         reply_nterror(
6796                                                 req,
6797                                                 NT_STATUS_DOS(
6798                                                         ERRDOS,
6799                                                         ERRcancelviolation));
6800                                         return;
6801                                 }
6802                         }
6803                         /* Remove a matching pending lock. */
6804                         status = do_lock_cancel(fsp,
6805                                                 lock_pid,
6806                                                 count,
6807                                                 offset,
6808                                                 WINDOWS_LOCK);
6809                 } else {
6810                         bool blocking_lock = lock_timeout ? True : False;
6811                         bool defer_lock = False;
6812                         struct byte_range_lock *br_lck;
6813                         uint32 block_smbpid;
6814
6815                         br_lck = do_lock(smbd_messaging_context(),
6816                                         fsp,
6817                                         lock_pid,
6818                                         count,
6819                                         offset, 
6820                                         lock_type,
6821                                         WINDOWS_LOCK,
6822                                         blocking_lock,
6823                                         &status,
6824                                         &block_smbpid);
6825
6826                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6827                                 /* Windows internal resolution for blocking locks seems
6828                                    to be about 200ms... Don't wait for less than that. JRA. */
6829                                 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6830                                         lock_timeout = lp_lock_spin_time();
6831                                 }
6832                                 defer_lock = True;
6833                         }
6834
6835                         /* This heuristic seems to match W2K3 very well. If a
6836                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6837                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
6838                            far as I can tell. Replacement for do_lock_spin(). JRA. */
6839
6840                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6841                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6842                                 defer_lock = True;
6843                                 lock_timeout = lp_lock_spin_time();
6844                         }
6845
6846                         if (br_lck && defer_lock) {
6847                                 /*
6848                                  * A blocking lock was requested. Package up
6849                                  * this smb into a queued request and push it
6850                                  * onto the blocking lock queue.
6851                                  */
6852                                 if(push_blocking_lock_request(br_lck,
6853                                                         req,
6854                                                         fsp,
6855                                                         lock_timeout,
6856                                                         i,
6857                                                         lock_pid,
6858                                                         lock_type,
6859                                                         WINDOWS_LOCK,
6860                                                         offset,
6861                                                         count,
6862                                                         block_smbpid)) {
6863                                         TALLOC_FREE(br_lck);
6864                                         END_PROFILE(SMBlockingX);
6865                                         return;
6866                                 }
6867                         }
6868
6869                         TALLOC_FREE(br_lck);
6870                 }
6871
6872                 if (NT_STATUS_V(status)) {
6873                         END_PROFILE(SMBlockingX);
6874                         reply_nterror(req, status);
6875                         return;
6876                 }
6877         }
6878         
6879         /* If any of the above locks failed, then we must unlock
6880            all of the previous locks (X/Open spec). */
6881
6882         if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6883                         (i != num_locks) &&
6884                         (num_locks != 0)) {
6885                 /*
6886                  * Ensure we don't do a remove on the lock that just failed,
6887                  * as under POSIX rules, if we have a lock already there, we
6888                  * will delete it (and we shouldn't) .....
6889                  */
6890                 for(i--; i >= 0; i--) {
6891                         lock_pid = get_lock_pid( data, i, large_file_format);
6892                         count = get_lock_count( data, i, large_file_format);
6893                         offset = get_lock_offset( data, i, large_file_format,
6894                                                   &err);
6895                         
6896                         /*
6897                          * There is no error code marked "stupid client
6898                          * bug".... :-).
6899                          */
6900                         if(err) {
6901                                 END_PROFILE(SMBlockingX);
6902                                 reply_doserror(req, ERRDOS, ERRnoaccess);
6903                                 return;
6904                         }
6905                         
6906                         do_unlock(smbd_messaging_context(),
6907                                 fsp,
6908                                 lock_pid,
6909                                 count,
6910                                 offset,
6911                                 WINDOWS_LOCK);
6912                 }
6913                 END_PROFILE(SMBlockingX);
6914                 reply_nterror(req, status);
6915                 return;
6916         }
6917
6918         reply_outbuf(req, 2, 0);
6919         
6920         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
6921                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
6922         
6923         END_PROFILE(SMBlockingX);
6924         chain_reply(req);
6925 }
6926
6927 #undef DBGC_CLASS
6928 #define DBGC_CLASS DBGC_ALL
6929
6930 /****************************************************************************
6931  Reply to a SMBreadbmpx (read block multiplex) request.
6932  Always reply with an error, if someone has a platform really needs this,
6933  please contact vl@samba.org
6934 ****************************************************************************/
6935
6936 void reply_readbmpx(struct smb_request *req)
6937 {
6938         START_PROFILE(SMBreadBmpx);
6939         reply_doserror(req, ERRSRV, ERRuseSTD);
6940         END_PROFILE(SMBreadBmpx);
6941         return;
6942 }
6943
6944 /****************************************************************************
6945  Reply to a SMBreadbs (read block multiplex secondary) request.
6946  Always reply with an error, if someone has a platform really needs this,
6947  please contact vl@samba.org
6948 ****************************************************************************/
6949
6950 void reply_readbs(struct smb_request *req)
6951 {
6952         START_PROFILE(SMBreadBs);
6953         reply_doserror(req, ERRSRV, ERRuseSTD);
6954         END_PROFILE(SMBreadBs);
6955         return;
6956 }
6957
6958 /****************************************************************************
6959  Reply to a SMBsetattrE.
6960 ****************************************************************************/
6961
6962 void reply_setattrE(struct smb_request *req)
6963 {
6964         connection_struct *conn = req->conn;
6965         struct timespec ts[2];
6966         files_struct *fsp;
6967
6968         START_PROFILE(SMBsetattrE);
6969
6970         if (req->wct < 7) {
6971                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6972                 END_PROFILE(SMBsetattrE);
6973                 return;
6974         }
6975
6976         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
6977
6978         if(!fsp || (fsp->conn != conn)) {
6979                 reply_doserror(req, ERRDOS, ERRbadfid);
6980                 END_PROFILE(SMBsetattrE);
6981                 return;
6982         }
6983
6984
6985         /*
6986          * Convert the DOS times into unix times. Ignore create
6987          * time as UNIX can't set this.
6988          */
6989
6990         ts[0] = convert_time_t_to_timespec(
6991                 srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */
6992         ts[1] = convert_time_t_to_timespec(
6993                 srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */
6994   
6995         reply_outbuf(req, 0, 0);
6996
6997         /* 
6998          * Patch from Ray Frush <frush@engr.colostate.edu>
6999          * Sometimes times are sent as zero - ignore them.
7000          */
7001
7002         if (null_timespec(ts[0]) && null_timespec(ts[1])) {
7003                 /* Ignore request */
7004                 if( DEBUGLVL( 3 ) ) {
7005                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
7006                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
7007                 }
7008                 END_PROFILE(SMBsetattrE);
7009                 return;
7010         } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
7011                 /* set modify time = to access time if modify time was unset */
7012                 ts[1] = ts[0];
7013         }
7014
7015         /* Set the date on this file */
7016         /* Should we set pending modtime here ? JRA */
7017         if(file_ntimes(conn, fsp->fsp_name, ts)) {
7018                 reply_doserror(req, ERRDOS, ERRnoaccess);
7019                 END_PROFILE(SMBsetattrE);
7020                 return;
7021         }
7022   
7023         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7024                 fsp->fnum,
7025                 (unsigned int)ts[0].tv_sec,
7026                 (unsigned int)ts[1].tv_sec));
7027
7028         END_PROFILE(SMBsetattrE);
7029         return;
7030 }
7031
7032
7033 /* Back from the dead for OS/2..... JRA. */
7034
7035 /****************************************************************************
7036  Reply to a SMBwritebmpx (write block multiplex primary) request.
7037  Always reply with an error, if someone has a platform really needs this,
7038  please contact vl@samba.org
7039 ****************************************************************************/
7040
7041 void reply_writebmpx(struct smb_request *req)
7042 {
7043         START_PROFILE(SMBwriteBmpx);
7044         reply_doserror(req, ERRSRV, ERRuseSTD);
7045         END_PROFILE(SMBwriteBmpx);
7046         return;
7047 }
7048
7049 /****************************************************************************
7050  Reply to a SMBwritebs (write block multiplex secondary) request.
7051  Always reply with an error, if someone has a platform really needs this,
7052  please contact vl@samba.org
7053 ****************************************************************************/
7054
7055 void reply_writebs(struct smb_request *req)
7056 {
7057         START_PROFILE(SMBwriteBs);
7058         reply_doserror(req, ERRSRV, ERRuseSTD);
7059         END_PROFILE(SMBwriteBs);
7060         return;
7061 }
7062
7063 /****************************************************************************
7064  Reply to a SMBgetattrE.
7065 ****************************************************************************/
7066
7067 void reply_getattrE(struct smb_request *req)
7068 {
7069         connection_struct *conn = req->conn;
7070         SMB_STRUCT_STAT sbuf;
7071         int mode;
7072         files_struct *fsp;
7073
7074         START_PROFILE(SMBgetattrE);
7075
7076         if (req->wct < 1) {
7077                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7078                 END_PROFILE(SMBgetattrE);
7079                 return;
7080         }
7081
7082         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
7083
7084         if(!fsp || (fsp->conn != conn)) {
7085                 reply_doserror(req, ERRDOS, ERRbadfid);
7086                 END_PROFILE(SMBgetattrE);
7087                 return;
7088         }
7089
7090         /* Do an fstat on this file */
7091         if(fsp_stat(fsp, &sbuf)) {
7092                 reply_unixerror(req, ERRDOS, ERRnoaccess);
7093                 END_PROFILE(SMBgetattrE);
7094                 return;
7095         }
7096   
7097         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7098   
7099         /*
7100          * Convert the times into dos times. Set create
7101          * date to be last modify date as UNIX doesn't save
7102          * this.
7103          */
7104
7105         reply_outbuf(req, 11, 0);
7106
7107         srv_put_dos_date2((char *)req->outbuf, smb_vwv0,
7108                           get_create_time(&sbuf,
7109                                           lp_fake_dir_create_times(SNUM(conn))));
7110         srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7111         /* Should we check pending modtime here ? JRA */
7112         srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7113
7114         if (mode & aDIR) {
7115                 SIVAL(req->outbuf, smb_vwv6, 0);
7116                 SIVAL(req->outbuf, smb_vwv8, 0);
7117         } else {
7118                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
7119                 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7120                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7121         }
7122         SSVAL(req->outbuf,smb_vwv10, mode);
7123   
7124         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7125   
7126         END_PROFILE(SMBgetattrE);
7127         return;
7128 }