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