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