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