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