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