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