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