locking: store the write time in the locking.tdb
[tprouty/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 (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
1114                 reply_unixerror(req, ERRDOS, ERRnoaccess);
1115                 END_PROFILE(SMBsetatr);
1116                 return;
1117         }
1118
1119         if (mode != FILE_ATTRIBUTE_NORMAL) {
1120                 if (VALID_STAT_OF_DIR(sbuf))
1121                         mode |= aDIR;
1122                 else
1123                         mode &= ~aDIR;
1124
1125                 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1126                         reply_unixerror(req, ERRDOS, ERRnoaccess);
1127                         END_PROFILE(SMBsetatr);
1128                         return;
1129                 }
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,fsp->fsp_name,&sbuf);
1643         mtime = sbuf.st_mtime;
1644
1645         if (fattr & aDIR) {
1646                 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
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,fsp->fsp_name,&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, fsp->fsp_name, 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", fsp->fsp_name ) );
2004         DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2005                     fsp->fsp_name, 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(fsp->fsp_name, '/');
2129         if (!s) {
2130                 s = fsp->fsp_name;
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", fsp->fsp_name ) );
2158         DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2159                     fsp->fh->fd, (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|FILE_WRITE_ATTRIBUTES)) {
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: successful 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) && (fsp->base_fsp == NULL) &&
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) && (fsp->base_fsp == NULL) &&
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                 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3520
3521                 if (!NT_STATUS_IS_OK(status)) {
3522                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3523                                  "raw read failed (%s). Terminating\n",
3524                                  nt_errstr(status)));
3525                         exit_server_cleanly("secondary writebraw failed");
3526                 }
3527
3528                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3529                 if (nwritten == -1) {
3530                         TALLOC_FREE(buf);
3531                         reply_unixerror(req, ERRHRD, ERRdiskfull);
3532                         error_to_writebrawerr(req);
3533                         END_PROFILE(SMBwritebraw);
3534                         return;
3535                 }
3536
3537                 if (nwritten < (ssize_t)numtowrite) {
3538                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
3539                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
3540                 }
3541
3542                 if (nwritten > 0) {
3543                         total_written += nwritten;
3544                 }
3545         }
3546
3547         TALLOC_FREE(buf);
3548         SSVAL(req->outbuf,smb_vwv0,total_written);
3549
3550         status = sync_file(conn, fsp, write_through);
3551         if (!NT_STATUS_IS_OK(status)) {
3552                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3553                         fsp->fsp_name, nt_errstr(status) ));
3554                 reply_nterror(req, status);
3555                 error_to_writebrawerr(req);
3556                 END_PROFILE(SMBwritebraw);
3557                 return;
3558         }
3559
3560         DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3561                 "wrote=%d\n",
3562                 fsp->fnum, (double)startpos, (int)numtowrite,
3563                 (int)total_written));
3564
3565         /* We won't return a status if write through is not selected - this
3566          * follows what WfWg does */
3567         END_PROFILE(SMBwritebraw);
3568
3569         if (!write_through && total_written==tcount) {
3570
3571 #if RABBIT_PELLET_FIX
3572                 /*
3573                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3574                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3575                  * JRA.
3576                  */
3577                 if (!send_keepalive(smbd_server_fd())) {
3578                         exit_server_cleanly("reply_writebraw: send of "
3579                                 "keepalive failed");
3580                 }
3581 #endif
3582                 TALLOC_FREE(req->outbuf);
3583         }
3584         return;
3585 }
3586
3587 #undef DBGC_CLASS
3588 #define DBGC_CLASS DBGC_LOCKING
3589
3590 /****************************************************************************
3591  Reply to a writeunlock (core+).
3592 ****************************************************************************/
3593
3594 void reply_writeunlock(struct smb_request *req)
3595 {
3596         connection_struct *conn = req->conn;
3597         ssize_t nwritten = -1;
3598         size_t numtowrite;
3599         SMB_OFF_T startpos;
3600         char *data;
3601         NTSTATUS status = NT_STATUS_OK;
3602         files_struct *fsp;
3603
3604         START_PROFILE(SMBwriteunlock);
3605
3606         if (req->wct < 5) {
3607                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3608                 END_PROFILE(SMBwriteunlock);
3609                 return;
3610         }
3611         
3612         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3613
3614         if (!check_fsp(conn, req, fsp, &current_user)) {
3615                 END_PROFILE(SMBwriteunlock);
3616                 return;
3617         }
3618
3619         if (!CHECK_WRITE(fsp)) {
3620                 reply_doserror(req, ERRDOS,ERRbadaccess);
3621                 END_PROFILE(SMBwriteunlock);
3622                 return;
3623         }
3624
3625         numtowrite = SVAL(req->inbuf,smb_vwv1);
3626         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3627         data = smb_buf(req->inbuf) + 3;
3628   
3629         if (numtowrite
3630             && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3631                          (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3632                 reply_doserror(req, ERRDOS, ERRlock);
3633                 END_PROFILE(SMBwriteunlock);
3634                 return;
3635         }
3636
3637         /* The special X/Open SMB protocol handling of
3638            zero length writes is *NOT* done for
3639            this call */
3640         if(numtowrite == 0) {
3641                 nwritten = 0;
3642         } else {
3643                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3644         }
3645   
3646         status = sync_file(conn, fsp, False /* write through */);
3647         if (!NT_STATUS_IS_OK(status)) {
3648                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3649                         fsp->fsp_name, nt_errstr(status) ));
3650                 reply_nterror(req, status);
3651                 END_PROFILE(SMBwriteunlock);
3652                 return;
3653         }
3654
3655         if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3656                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3657                 END_PROFILE(SMBwriteunlock);
3658                 return;
3659         }
3660
3661         if (numtowrite) {
3662                 status = do_unlock(smbd_messaging_context(),
3663                                 fsp,
3664                                 req->smbpid,
3665                                 (SMB_BIG_UINT)numtowrite, 
3666                                 (SMB_BIG_UINT)startpos,
3667                                 WINDOWS_LOCK);
3668
3669                 if (NT_STATUS_V(status)) {
3670                         reply_nterror(req, status);
3671                         END_PROFILE(SMBwriteunlock);
3672                         return;
3673                 }
3674         }
3675
3676         reply_outbuf(req, 1, 0);
3677         
3678         SSVAL(req->outbuf,smb_vwv0,nwritten);
3679         
3680         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3681                  fsp->fnum, (int)numtowrite, (int)nwritten));
3682         
3683         END_PROFILE(SMBwriteunlock);
3684         return;
3685 }
3686
3687 #undef DBGC_CLASS
3688 #define DBGC_CLASS DBGC_ALL
3689
3690 /****************************************************************************
3691  Reply to a write.
3692 ****************************************************************************/
3693
3694 void reply_write(struct smb_request *req)
3695 {
3696         connection_struct *conn = req->conn;
3697         size_t numtowrite;
3698         ssize_t nwritten = -1;
3699         SMB_OFF_T startpos;
3700         char *data;
3701         files_struct *fsp;
3702         NTSTATUS status;
3703
3704         START_PROFILE(SMBwrite);
3705
3706         if (req->wct < 5) {
3707                 END_PROFILE(SMBwrite);
3708                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3709                 return;
3710         }
3711
3712         /* If it's an IPC, pass off the pipe handler. */
3713         if (IS_IPC(conn)) {
3714                 reply_pipe_write(req);
3715                 END_PROFILE(SMBwrite);
3716                 return;
3717         }
3718
3719         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3720
3721         if (!check_fsp(conn, req, fsp, &current_user)) {
3722                 END_PROFILE(SMBwrite);
3723                 return;
3724         }
3725
3726         if (!CHECK_WRITE(fsp)) {
3727                 reply_doserror(req, ERRDOS, ERRbadaccess);
3728                 END_PROFILE(SMBwrite);
3729                 return;
3730         }
3731
3732         numtowrite = SVAL(req->inbuf,smb_vwv1);
3733         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3734         data = smb_buf(req->inbuf) + 3;
3735   
3736         if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3737                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3738                 reply_doserror(req, ERRDOS, ERRlock);
3739                 END_PROFILE(SMBwrite);
3740                 return;
3741         }
3742
3743         /*
3744          * X/Open SMB protocol says that if smb_vwv1 is
3745          * zero then the file size should be extended or
3746          * truncated to the size given in smb_vwv[2-3].
3747          */
3748
3749         if(numtowrite == 0) {
3750                 /*
3751                  * This is actually an allocate call, and set EOF. JRA.
3752                  */
3753                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3754                 if (nwritten < 0) {
3755                         reply_nterror(req, NT_STATUS_DISK_FULL);
3756                         END_PROFILE(SMBwrite);
3757                         return;
3758                 }
3759                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3760                 if (nwritten < 0) {
3761                         reply_nterror(req, NT_STATUS_DISK_FULL);
3762                         END_PROFILE(SMBwrite);
3763                         return;
3764                 }
3765         } else
3766                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3767   
3768         status = sync_file(conn, fsp, False);
3769         if (!NT_STATUS_IS_OK(status)) {
3770                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3771                         fsp->fsp_name, nt_errstr(status) ));
3772                 reply_nterror(req, status);
3773                 END_PROFILE(SMBwrite);
3774                 return;
3775         }
3776
3777         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3778                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3779                 END_PROFILE(SMBwrite);
3780                 return;
3781         }
3782
3783         reply_outbuf(req, 1, 0);
3784   
3785         SSVAL(req->outbuf,smb_vwv0,nwritten);
3786
3787         if (nwritten < (ssize_t)numtowrite) {
3788                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3789                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3790         }
3791   
3792         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3793
3794         END_PROFILE(SMBwrite);
3795         return;
3796 }
3797
3798 /****************************************************************************
3799  Ensure a buffer is a valid writeX for recvfile purposes.
3800 ****************************************************************************/
3801
3802 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3803                                                 (2*14) + /* word count (including bcc) */ \
3804                                                 1 /* pad byte */)
3805
3806 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3807 {
3808         size_t numtowrite;
3809         connection_struct *conn = NULL;
3810         unsigned int doff = 0;
3811         size_t len = smb_len_large(inbuf);
3812
3813         if (is_encrypted_packet(inbuf)) {
3814                 /* Can't do this on encrypted
3815                  * connections. */
3816                 return false;
3817         }
3818
3819         if (CVAL(inbuf,smb_com) != SMBwriteX) {
3820                 return false;
3821         }
3822
3823         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3824                         CVAL(inbuf,smb_wct) != 14) {
3825                 DEBUG(10,("is_valid_writeX_buffer: chained or "
3826                         "invalid word length.\n"));
3827                 return false;
3828         }
3829
3830         conn = conn_find(SVAL(inbuf, smb_tid));
3831         if (conn == NULL) {
3832                 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3833                 return false;
3834         }
3835         if (IS_IPC(conn)) {
3836                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3837                 return false;
3838         }
3839         doff = SVAL(inbuf,smb_vwv11);
3840
3841         numtowrite = SVAL(inbuf,smb_vwv10);
3842
3843         if (len > doff && len - doff > 0xFFFF) {
3844                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3845         }
3846
3847         if (numtowrite == 0) {
3848                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3849                 return false;
3850         }
3851
3852         /* Ensure the sizes match up. */
3853         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3854                 /* no pad byte...old smbclient :-( */
3855                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3856                         (unsigned int)doff,
3857                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
3858                 return false;
3859         }
3860
3861         if (len - doff != numtowrite) {
3862                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3863                         "len = %u, doff = %u, numtowrite = %u\n",
3864                         (unsigned int)len,
3865                         (unsigned int)doff,
3866                         (unsigned int)numtowrite ));
3867                 return false;
3868         }
3869
3870         DEBUG(10,("is_valid_writeX_buffer: true "
3871                 "len = %u, doff = %u, numtowrite = %u\n",
3872                 (unsigned int)len,
3873                 (unsigned int)doff,
3874                 (unsigned int)numtowrite ));
3875
3876         return true;
3877 }
3878
3879 /****************************************************************************
3880  Reply to a write and X.
3881 ****************************************************************************/
3882
3883 void reply_write_and_X(struct smb_request *req)
3884 {
3885         connection_struct *conn = req->conn;
3886         files_struct *fsp;
3887         SMB_OFF_T startpos;
3888         size_t numtowrite;
3889         bool write_through;
3890         ssize_t nwritten;
3891         unsigned int smb_doff;
3892         unsigned int smblen;
3893         char *data;
3894         NTSTATUS status;
3895
3896         START_PROFILE(SMBwriteX);
3897
3898         if ((req->wct != 12) && (req->wct != 14)) {
3899                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3900                 END_PROFILE(SMBwriteX);
3901                 return;
3902         }
3903
3904         numtowrite = SVAL(req->inbuf,smb_vwv10);
3905         smb_doff = SVAL(req->inbuf,smb_vwv11);
3906         smblen = smb_len(req->inbuf);
3907
3908         if (req->unread_bytes > 0xFFFF ||
3909                         (smblen > smb_doff &&
3910                                 smblen - smb_doff > 0xFFFF)) {
3911                 numtowrite |= (((size_t)SVAL(req->inbuf,smb_vwv9))<<16);
3912         }
3913
3914         if (req->unread_bytes) {
3915                 /* Can't do a recvfile write on IPC$ */
3916                 if (IS_IPC(conn)) {
3917                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3918                         END_PROFILE(SMBwriteX);
3919                         return;
3920                 }
3921                 if (numtowrite != req->unread_bytes) {
3922                         reply_doserror(req, ERRDOS, ERRbadmem);
3923                         END_PROFILE(SMBwriteX);
3924                         return;
3925                 }
3926         } else {
3927                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
3928                                 smb_doff + numtowrite > smblen) {
3929                         reply_doserror(req, ERRDOS, ERRbadmem);
3930                         END_PROFILE(SMBwriteX);
3931                         return;
3932                 }
3933         }
3934
3935         /* If it's an IPC, pass off the pipe handler. */
3936         if (IS_IPC(conn)) {
3937                 if (req->unread_bytes) {
3938                         reply_doserror(req, ERRDOS, ERRbadmem);
3939                         END_PROFILE(SMBwriteX);
3940                         return;
3941                 }
3942                 reply_pipe_write_and_X(req);
3943                 END_PROFILE(SMBwriteX);
3944                 return;
3945         }
3946
3947         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3948         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3949         write_through = BITSETW(req->inbuf+smb_vwv7,0);
3950
3951         if (!check_fsp(conn, req, fsp, &current_user)) {
3952                 END_PROFILE(SMBwriteX);
3953                 return;
3954         }
3955
3956         if (!CHECK_WRITE(fsp)) {
3957                 reply_doserror(req, ERRDOS, ERRbadaccess);
3958                 END_PROFILE(SMBwriteX);
3959                 return;
3960         }
3961
3962         data = smb_base(req->inbuf) + smb_doff;
3963
3964         if(req->wct == 14) {
3965 #ifdef LARGE_SMB_OFF_T
3966                 /*
3967                  * This is a large offset (64 bit) write.
3968                  */
3969                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
3970
3971 #else /* !LARGE_SMB_OFF_T */
3972
3973                 /*
3974                  * Ensure we haven't been sent a >32 bit offset.
3975                  */
3976
3977                 if(IVAL(req->inbuf,smb_vwv12) != 0) {
3978                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
3979                                  "used and we don't support 64 bit offsets.\n",
3980                                  (unsigned int)IVAL(req->inbuf,smb_vwv12) ));
3981                         reply_doserror(req, ERRDOS, ERRbadaccess);
3982                         END_PROFILE(SMBwriteX);
3983                         return;
3984                 }
3985
3986 #endif /* LARGE_SMB_OFF_T */
3987         }
3988
3989         if (is_locked(fsp,(uint32)req->smbpid,
3990                       (SMB_BIG_UINT)numtowrite,
3991                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3992                 reply_doserror(req, ERRDOS, ERRlock);
3993                 END_PROFILE(SMBwriteX);
3994                 return;
3995         }
3996
3997         /* X/Open SMB protocol says that, unlike SMBwrite
3998         if the length is zero then NO truncation is
3999         done, just a write of zero. To truncate a file,
4000         use SMBwrite. */
4001
4002         if(numtowrite == 0) {
4003                 nwritten = 0;
4004         } else {
4005
4006                 if ((req->unread_bytes == 0) &&
4007                     schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4008                                              numtowrite)) {
4009                         END_PROFILE(SMBwriteX);
4010                         return;
4011                 }
4012                 
4013                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4014         }
4015
4016         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4017                 reply_unixerror(req, ERRHRD, ERRdiskfull);
4018                 END_PROFILE(SMBwriteX);
4019                 return;
4020         }
4021
4022         reply_outbuf(req, 6, 0);
4023         SSVAL(req->outbuf,smb_vwv2,nwritten);
4024         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4025
4026         if (nwritten < (ssize_t)numtowrite) {
4027                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4028                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4029         }
4030
4031         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4032                 fsp->fnum, (int)numtowrite, (int)nwritten));
4033
4034         status = sync_file(conn, fsp, write_through);
4035         if (!NT_STATUS_IS_OK(status)) {
4036                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4037                         fsp->fsp_name, nt_errstr(status) ));
4038                 reply_nterror(req, status);
4039                 END_PROFILE(SMBwriteX);
4040                 return;
4041         }
4042
4043         END_PROFILE(SMBwriteX);
4044         chain_reply(req);
4045         return;
4046 }
4047
4048 /****************************************************************************
4049  Reply to a lseek.
4050 ****************************************************************************/
4051
4052 void reply_lseek(struct smb_request *req)
4053 {
4054         connection_struct *conn = req->conn;
4055         SMB_OFF_T startpos;
4056         SMB_OFF_T res= -1;
4057         int mode,umode;
4058         files_struct *fsp;
4059
4060         START_PROFILE(SMBlseek);
4061
4062         if (req->wct < 4) {
4063                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4064                 END_PROFILE(SMBlseek);
4065                 return;
4066         }
4067
4068         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4069
4070         if (!check_fsp(conn, req, fsp, &current_user)) {
4071                 return;
4072         }
4073
4074         flush_write_cache(fsp, SEEK_FLUSH);
4075
4076         mode = SVAL(req->inbuf,smb_vwv1) & 3;
4077         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4078         startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2);
4079
4080         switch (mode) {
4081                 case 0:
4082                         umode = SEEK_SET;
4083                         res = startpos;
4084                         break;
4085                 case 1:
4086                         umode = SEEK_CUR;
4087                         res = fsp->fh->pos + startpos;
4088                         break;
4089                 case 2:
4090                         umode = SEEK_END;
4091                         break;
4092                 default:
4093                         umode = SEEK_SET;
4094                         res = startpos;
4095                         break;
4096         }
4097
4098         if (umode == SEEK_END) {
4099                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4100                         if(errno == EINVAL) {
4101                                 SMB_OFF_T current_pos = startpos;
4102                                 SMB_STRUCT_STAT sbuf;
4103
4104                                 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4105                                         reply_unixerror(req, ERRDOS,
4106                                                         ERRnoaccess);
4107                                         END_PROFILE(SMBlseek);
4108                                         return;
4109                                 }
4110
4111                                 current_pos += sbuf.st_size;
4112                                 if(current_pos < 0)
4113                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4114                         }
4115                 }
4116
4117                 if(res == -1) {
4118                         reply_unixerror(req, ERRDOS, ERRnoaccess);
4119                         END_PROFILE(SMBlseek);
4120                         return;
4121                 }
4122         }
4123
4124         fsp->fh->pos = res;
4125
4126         reply_outbuf(req, 2, 0);
4127         SIVAL(req->outbuf,smb_vwv0,res);
4128   
4129         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4130                 fsp->fnum, (double)startpos, (double)res, mode));
4131
4132         END_PROFILE(SMBlseek);
4133         return;
4134 }
4135
4136 /****************************************************************************
4137  Reply to a flush.
4138 ****************************************************************************/
4139
4140 void reply_flush(struct smb_request *req)
4141 {
4142         connection_struct *conn = req->conn;
4143         uint16 fnum;
4144         files_struct *fsp;
4145
4146         START_PROFILE(SMBflush);
4147
4148         if (req->wct < 1) {
4149                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4150                 return;
4151         }
4152
4153         fnum = SVAL(req->inbuf,smb_vwv0);
4154         fsp = file_fsp(fnum);
4155
4156         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, &current_user)) {
4157                 return;
4158         }
4159         
4160         if (!fsp) {
4161                 file_sync_all(conn);
4162         } else {
4163                 NTSTATUS status = sync_file(conn, fsp, True);
4164                 if (!NT_STATUS_IS_OK(status)) {
4165                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4166                                 fsp->fsp_name, nt_errstr(status) ));
4167                         reply_nterror(req, status);
4168                         END_PROFILE(SMBflush);
4169                         return;
4170                 }
4171         }
4172         
4173         reply_outbuf(req, 0, 0);
4174
4175         DEBUG(3,("flush\n"));
4176         END_PROFILE(SMBflush);
4177         return;
4178 }
4179
4180 /****************************************************************************
4181  Reply to a exit.
4182  conn POINTER CAN BE NULL HERE !
4183 ****************************************************************************/
4184
4185 void reply_exit(struct smb_request *req)
4186 {
4187         START_PROFILE(SMBexit);
4188
4189         file_close_pid(req->smbpid, req->vuid);
4190
4191         reply_outbuf(req, 0, 0);
4192
4193         DEBUG(3,("exit\n"));
4194
4195         END_PROFILE(SMBexit);
4196         return;
4197 }
4198
4199 /****************************************************************************
4200  Reply to a close - has to deal with closing a directory opened by NT SMB's.
4201 ****************************************************************************/
4202
4203 void reply_close(struct smb_request *req)
4204 {
4205         connection_struct *conn = req->conn;
4206         NTSTATUS status = NT_STATUS_OK;
4207         files_struct *fsp = NULL;
4208         START_PROFILE(SMBclose);
4209
4210         if (req->wct < 3) {
4211                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4212                 END_PROFILE(SMBclose);
4213                 return;
4214         }
4215
4216         /* If it's an IPC, pass off to the pipe handler. */
4217         if (IS_IPC(conn)) {
4218                 reply_pipe_close(conn, req);
4219                 END_PROFILE(SMBclose);
4220                 return;
4221         }
4222
4223         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4224
4225         /*
4226          * We can only use CHECK_FSP if we know it's not a directory.
4227          */
4228
4229         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
4230                 reply_doserror(req, ERRDOS, ERRbadfid);
4231                 END_PROFILE(SMBclose);
4232                 return;
4233         }
4234
4235         if(fsp->is_directory) {
4236                 /*
4237                  * Special case - close NT SMB directory handle.
4238                  */
4239                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4240                 status = close_file(fsp,NORMAL_CLOSE);
4241         } else {
4242                 /*
4243                  * Close ordinary file.
4244                  */
4245
4246                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4247                          fsp->fh->fd, fsp->fnum,
4248                          conn->num_files_open));
4249  
4250                 /*
4251                  * Take care of any time sent in the close.
4252                  */
4253
4254                 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
4255                                                 srv_make_unix_date3(
4256                                                         req->inbuf+smb_vwv1)));
4257
4258                 /*
4259                  * close_file() returns the unix errno if an error
4260                  * was detected on close - normally this is due to
4261                  * a disk full error. If not then it was probably an I/O error.
4262                  */
4263  
4264                 status = close_file(fsp,NORMAL_CLOSE);
4265         }  
4266
4267         if (!NT_STATUS_IS_OK(status)) {
4268                 reply_nterror(req, status);
4269                 END_PROFILE(SMBclose);
4270                 return;
4271         }
4272
4273         reply_outbuf(req, 0, 0);
4274         END_PROFILE(SMBclose);
4275         return;
4276 }
4277
4278 /****************************************************************************
4279  Reply to a writeclose (Core+ protocol).
4280 ****************************************************************************/
4281
4282 void reply_writeclose(struct smb_request *req)
4283 {
4284         connection_struct *conn = req->conn;
4285         size_t numtowrite;
4286         ssize_t nwritten = -1;
4287         NTSTATUS close_status = NT_STATUS_OK;
4288         SMB_OFF_T startpos;
4289         char *data;
4290         struct timespec mtime;
4291         files_struct *fsp;
4292
4293         START_PROFILE(SMBwriteclose);
4294
4295         if (req->wct < 6) {
4296                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4297                 END_PROFILE(SMBwriteclose);
4298                 return;
4299         }
4300
4301         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4302
4303         if (!check_fsp(conn, req, fsp, &current_user)) {
4304                 END_PROFILE(SMBwriteclose);
4305                 return;
4306         }
4307         if (!CHECK_WRITE(fsp)) {
4308                 reply_doserror(req, ERRDOS,ERRbadaccess);
4309                 END_PROFILE(SMBwriteclose);
4310                 return;
4311         }
4312
4313         numtowrite = SVAL(req->inbuf,smb_vwv1);
4314         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
4315         mtime = convert_time_t_to_timespec(srv_make_unix_date3(
4316                                                    req->inbuf+smb_vwv4));
4317         data = smb_buf(req->inbuf) + 1;
4318   
4319         if (numtowrite
4320             && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
4321                          (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
4322                 reply_doserror(req, ERRDOS,ERRlock);
4323                 END_PROFILE(SMBwriteclose);
4324                 return;
4325         }
4326   
4327         nwritten = write_file(req,fsp,data,startpos,numtowrite);
4328
4329         set_filetime(conn, fsp->fsp_name, mtime);
4330   
4331         /*
4332          * More insanity. W2K only closes the file if writelen > 0.
4333          * JRA.
4334          */
4335
4336         if (numtowrite) {
4337                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4338                         fsp->fsp_name ));
4339                 close_status = close_file(fsp,NORMAL_CLOSE);
4340         }
4341
4342         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4343                  fsp->fnum, (int)numtowrite, (int)nwritten,
4344                  conn->num_files_open));
4345   
4346         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4347                 reply_doserror(req, ERRHRD, ERRdiskfull);
4348                 END_PROFILE(SMBwriteclose);
4349                 return;
4350         }
4351  
4352         if(!NT_STATUS_IS_OK(close_status)) {
4353                 reply_nterror(req, close_status);
4354                 END_PROFILE(SMBwriteclose);
4355                 return;
4356         }
4357
4358         reply_outbuf(req, 1, 0);
4359   
4360         SSVAL(req->outbuf,smb_vwv0,nwritten);
4361         END_PROFILE(SMBwriteclose);
4362         return;
4363 }
4364
4365 #undef DBGC_CLASS
4366 #define DBGC_CLASS DBGC_LOCKING
4367
4368 /****************************************************************************
4369  Reply to a lock.
4370 ****************************************************************************/
4371
4372 void reply_lock(struct smb_request *req)
4373 {
4374         connection_struct *conn = req->conn;
4375         SMB_BIG_UINT count,offset;
4376         NTSTATUS status;
4377         files_struct *fsp;
4378         struct byte_range_lock *br_lck = NULL;
4379
4380         START_PROFILE(SMBlock);
4381
4382         if (req->wct < 5) {
4383                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4384                 END_PROFILE(SMBlock);
4385                 return;
4386         }
4387
4388         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4389
4390         if (!check_fsp(conn, req, fsp, &current_user)) {
4391                 END_PROFILE(SMBlock);
4392                 return;
4393         }
4394
4395         release_level_2_oplocks_on_change(fsp);
4396
4397         count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4398         offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4399
4400         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4401                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4402
4403         br_lck = do_lock(smbd_messaging_context(),
4404                         fsp,
4405                         req->smbpid,
4406                         count,
4407                         offset,
4408                         WRITE_LOCK,
4409                         WINDOWS_LOCK,
4410                         False, /* Non-blocking lock. */
4411                         &status,
4412                         NULL);
4413
4414         TALLOC_FREE(br_lck);
4415
4416         if (NT_STATUS_V(status)) {
4417                 reply_nterror(req, status);
4418                 END_PROFILE(SMBlock);
4419                 return;
4420         }
4421
4422         reply_outbuf(req, 0, 0);
4423
4424         END_PROFILE(SMBlock);
4425         return;
4426 }
4427
4428 /****************************************************************************
4429  Reply to a unlock.
4430 ****************************************************************************/
4431
4432 void reply_unlock(struct smb_request *req)
4433 {
4434         connection_struct *conn = req->conn;
4435         SMB_BIG_UINT count,offset;
4436         NTSTATUS status;
4437         files_struct *fsp;
4438
4439         START_PROFILE(SMBunlock);
4440
4441         if (req->wct < 5) {
4442                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4443                 END_PROFILE(SMBunlock);
4444                 return;
4445         }
4446
4447         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4448
4449         if (!check_fsp(conn, req, fsp, &current_user)) {
4450                 END_PROFILE(SMBunlock);
4451                 return;
4452         }
4453         
4454         count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4455         offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4456         
4457         status = do_unlock(smbd_messaging_context(),
4458                         fsp,
4459                         req->smbpid,
4460                         count,
4461                         offset,
4462                         WINDOWS_LOCK);
4463
4464         if (NT_STATUS_V(status)) {
4465                 reply_nterror(req, status);
4466                 END_PROFILE(SMBunlock);
4467                 return;
4468         }
4469
4470         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4471                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4472
4473         reply_outbuf(req, 0, 0);
4474
4475         END_PROFILE(SMBunlock);
4476         return;
4477 }
4478
4479 #undef DBGC_CLASS
4480 #define DBGC_CLASS DBGC_ALL
4481
4482 /****************************************************************************
4483  Reply to a tdis.
4484  conn POINTER CAN BE NULL HERE !
4485 ****************************************************************************/
4486
4487 void reply_tdis(struct smb_request *req)
4488 {
4489         connection_struct *conn = req->conn;
4490         START_PROFILE(SMBtdis);
4491
4492         if (!conn) {
4493                 DEBUG(4,("Invalid connection in tdis\n"));
4494                 reply_doserror(req, ERRSRV, ERRinvnid);
4495                 END_PROFILE(SMBtdis);
4496                 return;
4497         }
4498
4499         conn->used = False;
4500
4501         close_cnum(conn,req->vuid);
4502         req->conn = NULL;
4503
4504         reply_outbuf(req, 0, 0);
4505         END_PROFILE(SMBtdis);
4506         return;
4507 }
4508
4509 /****************************************************************************
4510  Reply to a echo.
4511  conn POINTER CAN BE NULL HERE !
4512 ****************************************************************************/
4513
4514 void reply_echo(struct smb_request *req)
4515 {
4516         connection_struct *conn = req->conn;
4517         int smb_reverb;
4518         int seq_num;
4519         unsigned int data_len = smb_buflen(req->inbuf);
4520
4521         START_PROFILE(SMBecho);
4522
4523         if (req->wct < 1) {
4524                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4525                 END_PROFILE(SMBecho);
4526                 return;
4527         }
4528
4529         if (data_len > BUFFER_SIZE) {
4530                 DEBUG(0,("reply_echo: data_len too large.\n"));
4531                 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
4532                 END_PROFILE(SMBecho);
4533                 return;
4534         }
4535
4536         smb_reverb = SVAL(req->inbuf,smb_vwv0);
4537
4538         reply_outbuf(req, 1, data_len);
4539
4540         /* copy any incoming data back out */
4541         if (data_len > 0) {
4542                 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
4543         }
4544
4545         if (smb_reverb > 100) {
4546                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4547                 smb_reverb = 100;
4548         }
4549
4550         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4551                 SSVAL(req->outbuf,smb_vwv0,seq_num);
4552
4553                 show_msg((char *)req->outbuf);
4554                 if (!srv_send_smb(smbd_server_fd(),
4555                                 (char *)req->outbuf,
4556                                 IS_CONN_ENCRYPTED(conn)||req->encrypted))
4557                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
4558         }
4559
4560         DEBUG(3,("echo %d times\n", smb_reverb));
4561
4562         TALLOC_FREE(req->outbuf);
4563
4564         smb_echo_count++;
4565
4566         END_PROFILE(SMBecho);
4567         return;
4568 }
4569
4570 /****************************************************************************
4571  Reply to a printopen.
4572 ****************************************************************************/
4573
4574 void reply_printopen(struct smb_request *req)
4575 {
4576         connection_struct *conn = req->conn;
4577         files_struct *fsp;
4578         NTSTATUS status;
4579         
4580         START_PROFILE(SMBsplopen);
4581
4582         if (req->wct < 2) {
4583                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4584                 END_PROFILE(SMBsplopen);
4585                 return;
4586         }
4587
4588         if (!CAN_PRINT(conn)) {
4589                 reply_doserror(req, ERRDOS, ERRnoaccess);
4590                 END_PROFILE(SMBsplopen);
4591                 return;
4592         }
4593
4594         /* Open for exclusive use, write only. */
4595         status = print_fsp_open(conn, NULL, &fsp);
4596
4597         if (!NT_STATUS_IS_OK(status)) {
4598                 reply_nterror(req, status);
4599                 END_PROFILE(SMBsplopen);
4600                 return;
4601         }
4602
4603         reply_outbuf(req, 1, 0);
4604         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4605   
4606         DEBUG(3,("openprint fd=%d fnum=%d\n",
4607                  fsp->fh->fd, fsp->fnum));
4608
4609         END_PROFILE(SMBsplopen);
4610         return;
4611 }
4612
4613 /****************************************************************************
4614  Reply to a printclose.
4615 ****************************************************************************/
4616
4617 void reply_printclose(struct smb_request *req)
4618 {
4619         connection_struct *conn = req->conn;
4620         files_struct *fsp;
4621         NTSTATUS status;
4622
4623         START_PROFILE(SMBsplclose);
4624
4625         if (req->wct < 1) {
4626                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4627                 END_PROFILE(SMBsplclose);
4628                 return;
4629         }
4630
4631         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4632
4633         if (!check_fsp(conn, req, fsp, &current_user)) {
4634                 END_PROFILE(SMBsplclose);
4635                 return;
4636         }
4637
4638         if (!CAN_PRINT(conn)) {
4639                 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4640                 END_PROFILE(SMBsplclose);
4641                 return;
4642         }
4643   
4644         DEBUG(3,("printclose fd=%d fnum=%d\n",
4645                  fsp->fh->fd,fsp->fnum));
4646   
4647         status = close_file(fsp,NORMAL_CLOSE);
4648
4649         if(!NT_STATUS_IS_OK(status)) {
4650                 reply_nterror(req, status);
4651                 END_PROFILE(SMBsplclose);
4652                 return;
4653         }
4654
4655         END_PROFILE(SMBsplclose);
4656         return;
4657 }
4658
4659 /****************************************************************************
4660  Reply to a printqueue.
4661 ****************************************************************************/
4662
4663 void reply_printqueue(struct smb_request *req)
4664 {
4665         connection_struct *conn = req->conn;
4666         int max_count;
4667         int start_index;
4668
4669         START_PROFILE(SMBsplretq);
4670
4671         if (req->wct < 2) {
4672                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4673                 END_PROFILE(SMBsplretq);
4674                 return;
4675         }
4676
4677         max_count = SVAL(req->inbuf,smb_vwv0);
4678         start_index = SVAL(req->inbuf,smb_vwv1);
4679
4680         /* we used to allow the client to get the cnum wrong, but that
4681            is really quite gross and only worked when there was only
4682            one printer - I think we should now only accept it if they
4683            get it right (tridge) */
4684         if (!CAN_PRINT(conn)) {
4685                 reply_doserror(req, ERRDOS, ERRnoaccess);
4686                 END_PROFILE(SMBsplretq);
4687                 return;
4688         }
4689
4690         reply_outbuf(req, 2, 3);
4691         SSVAL(req->outbuf,smb_vwv0,0);
4692         SSVAL(req->outbuf,smb_vwv1,0);
4693         SCVAL(smb_buf(req->outbuf),0,1);
4694         SSVAL(smb_buf(req->outbuf),1,0);
4695   
4696         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4697                  start_index, max_count));
4698
4699         {
4700                 print_queue_struct *queue = NULL;
4701                 print_status_struct status;
4702                 int count = print_queue_status(SNUM(conn), &queue, &status);
4703                 int num_to_get = ABS(max_count);
4704                 int first = (max_count>0?start_index:start_index+max_count+1);
4705                 int i;
4706
4707                 if (first >= count)
4708                         num_to_get = 0;
4709                 else
4710                         num_to_get = MIN(num_to_get,count-first);
4711     
4712
4713                 for (i=first;i<first+num_to_get;i++) {
4714                         char blob[28];
4715                         char *p = blob;
4716
4717                         srv_put_dos_date2(p,0,queue[i].time);
4718                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4719                         SSVAL(p,5, queue[i].job);
4720                         SIVAL(p,7,queue[i].size);
4721                         SCVAL(p,11,0);
4722                         srvstr_push(blob, req->flags2, p+12,
4723                                     queue[i].fs_user, 16, STR_ASCII);
4724
4725                         if (message_push_blob(
4726                                     &req->outbuf,
4727                                     data_blob_const(
4728                                             blob, sizeof(blob))) == -1) {
4729                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
4730                                 END_PROFILE(SMBsplretq);
4731                                 return;
4732                         }
4733                 }
4734
4735                 if (count > 0) {
4736                         SSVAL(req->outbuf,smb_vwv0,count);
4737                         SSVAL(req->outbuf,smb_vwv1,
4738                               (max_count>0?first+count:first-1));
4739                         SCVAL(smb_buf(req->outbuf),0,1);
4740                         SSVAL(smb_buf(req->outbuf),1,28*count);
4741                 }
4742
4743                 SAFE_FREE(queue);
4744           
4745                 DEBUG(3,("%d entries returned in queue\n",count));
4746         }
4747   
4748         END_PROFILE(SMBsplretq);
4749         return;
4750 }
4751
4752 /****************************************************************************
4753  Reply to a printwrite.
4754 ****************************************************************************/
4755
4756 void reply_printwrite(struct smb_request *req)
4757 {
4758         connection_struct *conn = req->conn;
4759         int numtowrite;
4760         char *data;
4761         files_struct *fsp;
4762
4763         START_PROFILE(SMBsplwr);
4764
4765         if (req->wct < 1) {
4766                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4767                 END_PROFILE(SMBsplwr);
4768                 return;
4769         }
4770   
4771         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4772
4773         if (!check_fsp(conn, req, fsp, &current_user)) {
4774                 END_PROFILE(SMBsplwr);
4775                 return;
4776         }
4777
4778         if (!CAN_PRINT(conn)) {
4779                 reply_doserror(req, ERRDOS, ERRnoaccess);
4780                 END_PROFILE(SMBsplwr);
4781                 return;
4782         }
4783
4784         if (!CHECK_WRITE(fsp)) {
4785                 reply_doserror(req, ERRDOS, ERRbadaccess);
4786                 END_PROFILE(SMBsplwr);
4787                 return;
4788         }
4789
4790         numtowrite = SVAL(smb_buf(req->inbuf),1);
4791
4792         if (smb_buflen(req->inbuf) < numtowrite + 3) {
4793                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4794                 END_PROFILE(SMBsplwr);
4795                 return;
4796         }
4797
4798         data = smb_buf(req->inbuf) + 3;
4799
4800         if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4801                 reply_unixerror(req, ERRHRD, ERRdiskfull);
4802                 END_PROFILE(SMBsplwr);
4803                 return;
4804         }
4805
4806         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4807
4808         END_PROFILE(SMBsplwr);
4809         return;
4810 }
4811
4812 /****************************************************************************
4813  Reply to a mkdir.
4814 ****************************************************************************/
4815
4816 void reply_mkdir(struct smb_request *req)
4817 {
4818         connection_struct *conn = req->conn;
4819         char *directory = NULL;
4820         NTSTATUS status;
4821         SMB_STRUCT_STAT sbuf;
4822         TALLOC_CTX *ctx = talloc_tos();
4823
4824         START_PROFILE(SMBmkdir);
4825
4826         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
4827                         smb_buf(req->inbuf) + 1, 0,
4828                         STR_TERMINATE, &status);
4829         if (!NT_STATUS_IS_OK(status)) {
4830                 reply_nterror(req, status);
4831                 END_PROFILE(SMBmkdir);
4832                 return;
4833         }
4834
4835         status = resolve_dfspath(ctx, conn,
4836                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4837                                  directory,
4838                                  &directory);
4839         if (!NT_STATUS_IS_OK(status)) {
4840                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4841                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4842                                         ERRSRV, ERRbadpath);
4843                         END_PROFILE(SMBmkdir);
4844                         return;
4845                 }
4846                 reply_nterror(req, status);
4847                 END_PROFILE(SMBmkdir);
4848                 return;
4849         }
4850
4851         status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4852         if (!NT_STATUS_IS_OK(status)) {
4853                 reply_nterror(req, status);
4854                 END_PROFILE(SMBmkdir);
4855                 return;
4856         }
4857
4858         status = check_name(conn, directory);
4859         if (!NT_STATUS_IS_OK(status)) {
4860                 reply_nterror(req, status);
4861                 END_PROFILE(SMBmkdir);
4862                 return;
4863         }
4864
4865         status = create_directory(conn, req, directory);
4866
4867         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4868
4869         if (!NT_STATUS_IS_OK(status)) {
4870
4871                 if (!use_nt_status()
4872                     && NT_STATUS_EQUAL(status,
4873                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
4874                         /*
4875                          * Yes, in the DOS error code case we get a
4876                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4877                          * samba4 torture test.
4878                          */
4879                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4880                 }
4881
4882                 reply_nterror(req, status);
4883                 END_PROFILE(SMBmkdir);
4884                 return;
4885         }
4886
4887         reply_outbuf(req, 0, 0);
4888
4889         DEBUG( 3, ( "mkdir %s\n", directory ) );
4890
4891         END_PROFILE(SMBmkdir);
4892         return;
4893 }
4894
4895 /****************************************************************************
4896  Static function used by reply_rmdir to delete an entire directory
4897  tree recursively. Return True on ok, False on fail.
4898 ****************************************************************************/
4899
4900 static bool recursive_rmdir(TALLOC_CTX *ctx,
4901                         connection_struct *conn,
4902                         char *directory)
4903 {
4904         const char *dname = NULL;
4905         bool ret = True;
4906         long offset = 0;
4907         struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
4908                                           NULL, 0);
4909
4910         if(dir_hnd == NULL)
4911                 return False;
4912
4913         while((dname = ReadDirName(dir_hnd, &offset))) {
4914                 char *fullname = NULL;
4915                 SMB_STRUCT_STAT st;
4916
4917                 if (ISDOT(dname) || ISDOTDOT(dname)) {
4918                         continue;
4919                 }
4920
4921                 if (!is_visible_file(conn, directory, dname, &st, False)) {
4922                         continue;
4923                 }
4924
4925                 /* Construct the full name. */
4926                 fullname = talloc_asprintf(ctx,
4927                                 "%s/%s",
4928                                 directory,
4929                                 dname);
4930                 if (!fullname) {
4931                         errno = ENOMEM;
4932                         ret = False;
4933                         break;
4934                 }
4935
4936                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4937                         ret = False;
4938                         break;
4939                 }
4940
4941                 if(st.st_mode & S_IFDIR) {
4942                         if(!recursive_rmdir(ctx, conn, fullname)) {
4943                                 ret = False;
4944                                 break;
4945                         }
4946                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4947                                 ret = False;
4948                                 break;
4949                         }
4950                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4951                         ret = False;
4952                         break;
4953                 }
4954                 TALLOC_FREE(fullname);
4955         }
4956         TALLOC_FREE(dir_hnd);
4957         return ret;
4958 }
4959
4960 /****************************************************************************
4961  The internals of the rmdir code - called elsewhere.
4962 ****************************************************************************/
4963
4964 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
4965                         connection_struct *conn,
4966                         const char *directory)
4967 {
4968         int ret;
4969         SMB_STRUCT_STAT st;
4970
4971         /* Might be a symlink. */
4972         if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4973                 return map_nt_error_from_unix(errno);
4974         }
4975
4976         if (S_ISLNK(st.st_mode)) {
4977                 /* Is what it points to a directory ? */
4978                 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4979                         return map_nt_error_from_unix(errno);
4980                 }
4981                 if (!(S_ISDIR(st.st_mode))) {
4982                         return NT_STATUS_NOT_A_DIRECTORY;
4983                 }
4984                 ret = SMB_VFS_UNLINK(conn,directory);
4985         } else {
4986                 ret = SMB_VFS_RMDIR(conn,directory);
4987         }
4988         if (ret == 0) {
4989                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4990                              FILE_NOTIFY_CHANGE_DIR_NAME,
4991                              directory);
4992                 return NT_STATUS_OK;
4993         }
4994
4995         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4996                 /*
4997                  * Check to see if the only thing in this directory are
4998                  * vetoed files/directories. If so then delete them and
4999                  * retry. If we fail to delete any of them (and we *don't*
5000                  * do a recursive delete) then fail the rmdir.
5001                  */
5002                 const char *dname;
5003                 long dirpos = 0;
5004                 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5005                                                   directory, NULL, 0);
5006
5007                 if(dir_hnd == NULL) {
5008                         errno = ENOTEMPTY;
5009                         goto err;
5010                 }
5011
5012                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5013                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5014                                 continue;
5015                         if (!is_visible_file(conn, directory, dname, &st, False))
5016                                 continue;
5017                         if(!IS_VETO_PATH(conn, dname)) {
5018                                 TALLOC_FREE(dir_hnd);
5019                                 errno = ENOTEMPTY;
5020                                 goto err;
5021                         }
5022                 }
5023
5024                 /* We only have veto files/directories. Recursive delete. */
5025
5026                 RewindDir(dir_hnd,&dirpos);
5027                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
5028                         char *fullname = NULL;
5029
5030                         if (ISDOT(dname) || ISDOTDOT(dname)) {
5031                                 continue;
5032                         }
5033                         if (!is_visible_file(conn, directory, dname, &st, False)) {
5034                                 continue;
5035                         }
5036
5037                         fullname = talloc_asprintf(ctx,
5038                                         "%s/%s",
5039                                         directory,
5040                                         dname);
5041
5042                         if(!fullname) {
5043                                 errno = ENOMEM;
5044                                 break;
5045                         }
5046
5047                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5048                                 break;
5049                         }
5050                         if(st.st_mode & S_IFDIR) {
5051                                 if(lp_recursive_veto_delete(SNUM(conn))) {
5052                                         if(!recursive_rmdir(ctx, conn, fullname))
5053                                                 break;
5054                                 }
5055                                 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5056                                         break;
5057                                 }
5058                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5059                                 break;
5060                         }
5061                         TALLOC_FREE(fullname);
5062                 }
5063                 TALLOC_FREE(dir_hnd);
5064                 /* Retry the rmdir */
5065                 ret = SMB_VFS_RMDIR(conn,directory);
5066         }
5067
5068   err:
5069
5070         if (ret != 0) {
5071                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5072                          "%s\n", directory,strerror(errno)));
5073                 return map_nt_error_from_unix(errno);
5074         }
5075
5076         notify_fname(conn, NOTIFY_ACTION_REMOVED,
5077                      FILE_NOTIFY_CHANGE_DIR_NAME,
5078                      directory);
5079
5080         return NT_STATUS_OK;
5081 }
5082
5083 /****************************************************************************
5084  Reply to a rmdir.
5085 ****************************************************************************/
5086
5087 void reply_rmdir(struct smb_request *req)
5088 {
5089         connection_struct *conn = req->conn;
5090         char *directory = NULL;
5091         SMB_STRUCT_STAT sbuf;
5092         NTSTATUS status;
5093         TALLOC_CTX *ctx = talloc_tos();
5094
5095         START_PROFILE(SMBrmdir);
5096
5097         srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
5098                         smb_buf(req->inbuf) + 1, 0,
5099                         STR_TERMINATE, &status);
5100         if (!NT_STATUS_IS_OK(status)) {
5101                 reply_nterror(req, status);
5102                 END_PROFILE(SMBrmdir);
5103                 return;
5104         }
5105
5106         status = resolve_dfspath(ctx, conn,
5107                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
5108                                  directory,
5109                                  &directory);
5110         if (!NT_STATUS_IS_OK(status)) {
5111                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5112                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5113                                         ERRSRV, ERRbadpath);
5114                         END_PROFILE(SMBrmdir);
5115                         return;
5116                 }
5117                 reply_nterror(req, status);
5118                 END_PROFILE(SMBrmdir);
5119                 return;
5120         }
5121
5122         status = unix_convert(ctx, conn, directory, False, &directory,
5123                         NULL, &sbuf);
5124         if (!NT_STATUS_IS_OK(status)) {
5125                 reply_nterror(req, status);
5126                 END_PROFILE(SMBrmdir);
5127                 return;
5128         }
5129
5130         status = check_name(conn, directory);
5131         if (!NT_STATUS_IS_OK(status)) {
5132                 reply_nterror(req, status);
5133                 END_PROFILE(SMBrmdir);
5134                 return;
5135         }
5136
5137         dptr_closepath(directory, req->smbpid);
5138         status = rmdir_internals(ctx, conn, directory);
5139         if (!NT_STATUS_IS_OK(status)) {
5140                 reply_nterror(req, status);
5141                 END_PROFILE(SMBrmdir);
5142                 return;
5143         }
5144
5145         reply_outbuf(req, 0, 0);
5146
5147         DEBUG( 3, ( "rmdir %s\n", directory ) );
5148
5149         END_PROFILE(SMBrmdir);
5150         return;
5151 }
5152
5153 /*******************************************************************
5154  Resolve wildcards in a filename rename.
5155 ********************************************************************/
5156
5157 static bool resolve_wildcards(TALLOC_CTX *ctx,
5158                                 const char *name1,
5159                                 const char *name2,
5160                                 char **pp_newname)
5161 {
5162         char *name2_copy = NULL;
5163         char *root1 = NULL;
5164         char *root2 = NULL;
5165         char *ext1 = NULL;
5166         char *ext2 = NULL;
5167         char *p,*p2, *pname1, *pname2;
5168         
5169         name2_copy = talloc_strdup(ctx, name2);
5170         if (!name2_copy) {
5171                 return False;
5172         }
5173
5174         pname1 = strrchr_m(name1,'/');
5175         pname2 = strrchr_m(name2_copy,'/');
5176
5177         if (!pname1 || !pname2) {
5178                 return False;
5179         }
5180   
5181         /* Truncate the copy of name2 at the last '/' */
5182         *pname2 = '\0';
5183
5184         /* Now go past the '/' */
5185         pname1++;
5186         pname2++;
5187
5188         root1 = talloc_strdup(ctx, pname1);
5189         root2 = talloc_strdup(ctx, pname2);
5190
5191         if (!root1 || !root2) {
5192                 return False;
5193         }
5194
5195         p = strrchr_m(root1,'.');
5196         if (p) {
5197                 *p = 0;
5198                 ext1 = talloc_strdup(ctx, p+1);
5199         } else {
5200                 ext1 = talloc_strdup(ctx, "");
5201         }
5202         p = strrchr_m(root2,'.');
5203         if (p) {
5204                 *p = 0;
5205                 ext2 = talloc_strdup(ctx, p+1);
5206         } else {
5207                 ext2 = talloc_strdup(ctx, "");
5208         }
5209
5210         if (!ext1 || !ext2) {
5211                 return False;
5212         }
5213
5214         p = root1;
5215         p2 = root2;
5216         while (*p2) {
5217                 if (*p2 == '?') {
5218                         /* Hmmm. Should this be mb-aware ? */
5219                         *p2 = *p;
5220                         p2++;
5221                 } else if (*p2 == '*') {
5222                         *p2 = '\0';
5223                         root2 = talloc_asprintf(ctx, "%s%s",
5224                                                 root2,
5225                                                 p);
5226                         if (!root2) {
5227                                 return False;
5228                         }
5229                         break;
5230                 } else {
5231                         p2++;
5232                 }
5233                 if (*p) {
5234                         p++;
5235                 }
5236         }
5237
5238         p = ext1;
5239         p2 = ext2;
5240         while (*p2) {
5241                 if (*p2 == '?') {
5242                         /* Hmmm. Should this be mb-aware ? */
5243                         *p2 = *p;
5244                         p2++;
5245                 } else if (*p2 == '*') {
5246                         *p2 = '\0';
5247                         ext2 = talloc_asprintf(ctx, "%s%s",
5248                                                 ext2,
5249                                                 p);
5250                         if (!ext2) {
5251                                 return False;
5252                         }
5253                         break;
5254                 } else {
5255                         p2++;
5256                 }
5257                 if (*p) {
5258                         p++;
5259                 }
5260         }
5261
5262         if (*ext2) {
5263                 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5264                                 name2_copy,
5265                                 root2,
5266                                 ext2);
5267         } else {
5268                 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5269                                 name2_copy,
5270                                 root2);
5271         }
5272
5273         if (!*pp_newname) {
5274                 return False;
5275         }
5276
5277         return True;
5278 }
5279
5280 /****************************************************************************
5281  Ensure open files have their names updated. Updated to notify other smbd's
5282  asynchronously.
5283 ****************************************************************************/
5284
5285 static void rename_open_files(connection_struct *conn,
5286                               struct share_mode_lock *lck,
5287                               const char *newname)
5288 {
5289         files_struct *fsp;
5290         bool did_rename = False;
5291
5292         for(fsp = file_find_di_first(lck->id); fsp;
5293             fsp = file_find_di_next(fsp)) {
5294                 /* fsp_name is a relative path under the fsp. To change this for other
5295                    sharepaths we need to manipulate relative paths. */
5296                 /* TODO - create the absolute path and manipulate the newname
5297                    relative to the sharepath. */
5298                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5299                         continue;
5300                 }
5301                 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5302                           fsp->fnum, file_id_string_tos(&fsp->file_id),
5303                         fsp->fsp_name, newname ));
5304                 string_set(&fsp->fsp_name, newname);
5305                 did_rename = True;
5306         }
5307
5308         if (!did_rename) {
5309                 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5310                           file_id_string_tos(&lck->id), newname ));
5311         }
5312
5313         /* Send messages to all smbd's (not ourself) that the name has changed. */
5314         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5315                               newname);
5316 }
5317
5318 /****************************************************************************
5319  We need to check if the source path is a parent directory of the destination
5320  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5321  refuse the rename with a sharing violation. Under UNIX the above call can
5322  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5323  probably need to check that the client is a Windows one before disallowing
5324  this as a UNIX client (one with UNIX extensions) can know the source is a
5325  symlink and make this decision intelligently. Found by an excellent bug
5326  report from <AndyLiebman@aol.com>.
5327 ****************************************************************************/
5328
5329 static bool rename_path_prefix_equal(const char *src, const char *dest)
5330 {
5331         const char *psrc = src;
5332         const char *pdst = dest;
5333         size_t slen;
5334
5335         if (psrc[0] == '.' && psrc[1] == '/') {
5336                 psrc += 2;
5337         }
5338         if (pdst[0] == '.' && pdst[1] == '/') {
5339                 pdst += 2;
5340         }
5341         if ((slen = strlen(psrc)) > strlen(pdst)) {
5342                 return False;
5343         }
5344         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5345 }
5346
5347 /*
5348  * Do the notify calls from a rename
5349  */
5350
5351 static void notify_rename(connection_struct *conn, bool is_dir,
5352                           const char *oldpath, const char *newpath)
5353 {
5354         char *olddir, *newdir;
5355         const char *oldname, *newname;
5356         uint32 mask;
5357
5358         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5359                 : FILE_NOTIFY_CHANGE_FILE_NAME;
5360
5361         if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
5362             || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
5363                 TALLOC_FREE(olddir);
5364                 return;
5365         }
5366
5367         if (strcmp(olddir, newdir) == 0) {
5368                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5369                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5370         }
5371         else {
5372                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5373                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5374         }
5375         TALLOC_FREE(olddir);
5376         TALLOC_FREE(newdir);
5377
5378         /* this is a strange one. w2k3 gives an additional event for
5379            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5380            files, but not directories */
5381         if (!is_dir) {
5382                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5383                              FILE_NOTIFY_CHANGE_ATTRIBUTES
5384                              |FILE_NOTIFY_CHANGE_CREATION,
5385                              newpath);
5386         }
5387 }
5388
5389 /****************************************************************************
5390  Rename an open file - given an fsp.
5391 ****************************************************************************/
5392
5393 NTSTATUS rename_internals_fsp(connection_struct *conn,
5394                         files_struct *fsp,
5395                         char *newname,
5396                         const char *newname_last_component,
5397                         uint32 attrs,
5398                         bool replace_if_exists)
5399 {
5400         TALLOC_CTX *ctx = talloc_tos();
5401         SMB_STRUCT_STAT sbuf, sbuf1;
5402         NTSTATUS status = NT_STATUS_OK;
5403         struct share_mode_lock *lck = NULL;
5404         bool dst_exists;
5405
5406         ZERO_STRUCT(sbuf);
5407
5408         status = check_name(conn, newname);
5409         if (!NT_STATUS_IS_OK(status)) {
5410                 return status;
5411         }
5412
5413         /* Ensure newname contains a '/' */
5414         if(strrchr_m(newname,'/') == 0) {
5415                 newname = talloc_asprintf(ctx,
5416                                         "./%s",
5417                                         newname);
5418                 if (!newname) {
5419                         return NT_STATUS_NO_MEMORY;
5420                 }
5421         }
5422
5423         /*
5424          * Check for special case with case preserving and not
5425          * case sensitive. If the old last component differs from the original
5426          * last component only by case, then we should allow
5427          * the rename (user is trying to change the case of the
5428          * filename).
5429          */
5430
5431         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5432                         strequal(newname, fsp->fsp_name)) {
5433                 char *p;
5434                 char *newname_modified_last_component = NULL;
5435
5436                 /*
5437                  * Get the last component of the modified name.
5438                  * Note that we guarantee that newname contains a '/'
5439                  * character above.
5440                  */
5441                 p = strrchr_m(newname,'/');
5442                 newname_modified_last_component = talloc_strdup(ctx,
5443                                                 p+1);
5444                 if (!newname_modified_last_component) {
5445                         return NT_STATUS_NO_MEMORY;
5446                 }
5447
5448                 if(strcsequal(newname_modified_last_component,
5449                               newname_last_component) == False) {
5450                         /*
5451                          * Replace the modified last component with
5452                          * the original.
5453                          */
5454                         *p = '\0'; /* Truncate at the '/' */
5455                         newname = talloc_asprintf(ctx,
5456                                         "%s/%s",
5457                                         newname,
5458                                         newname_last_component);
5459                 }
5460         }
5461
5462         /*
5463          * If the src and dest names are identical - including case,
5464          * don't do the rename, just return success.
5465          */
5466
5467         if (strcsequal(fsp->fsp_name, newname)) {
5468                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5469                         newname));
5470                 return NT_STATUS_OK;
5471         }
5472
5473         /*
5474          * Have vfs_object_exist also fill sbuf1
5475          */
5476         dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5477
5478         if(!replace_if_exists && dst_exists) {
5479                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5480                         fsp->fsp_name,newname));
5481                 return NT_STATUS_OBJECT_NAME_COLLISION;
5482         }
5483
5484         if (dst_exists) {
5485                 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5486                 files_struct *dst_fsp = file_find_di_first(fileid);
5487                 if (dst_fsp) {
5488                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5489                         return NT_STATUS_ACCESS_DENIED;
5490                 }
5491         }
5492
5493         /* Ensure we have a valid stat struct for the source. */
5494         if (fsp->fh->fd != -1) {
5495                 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5496                         return map_nt_error_from_unix(errno);
5497                 }
5498         } else {
5499                 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5500                         return map_nt_error_from_unix(errno);
5501                 }
5502         }
5503
5504         status = can_rename(conn, fsp, attrs, &sbuf);
5505
5506         if (!NT_STATUS_IS_OK(status)) {
5507                 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5508                         nt_errstr(status), fsp->fsp_name,newname));
5509                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5510                         status = NT_STATUS_ACCESS_DENIED;
5511                 return status;
5512         }
5513
5514         if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5515                 return NT_STATUS_ACCESS_DENIED;
5516         }
5517
5518         lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5519                                   NULL);
5520
5521         /*
5522          * We have the file open ourselves, so not being able to get the
5523          * corresponding share mode lock is a fatal error.
5524          */
5525
5526         SMB_ASSERT(lck != NULL);
5527
5528         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5529                 uint32 create_options = fsp->fh->private_options;
5530
5531                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5532                         fsp->fsp_name,newname));
5533
5534                 rename_open_files(conn, lck, newname);
5535
5536                 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5537
5538                 /*
5539                  * A rename acts as a new file create w.r.t. allowing an initial delete
5540                  * on close, probably because in Windows there is a new handle to the
5541                  * new file. If initial delete on close was requested but not
5542                  * originally set, we need to set it here. This is probably not 100% correct,
5543                  * but will work for the CIFSFS client which in non-posix mode
5544                  * depends on these semantics. JRA.
5545                  */
5546
5547                 set_allow_initial_delete_on_close(lck, fsp, True);
5548
5549                 if (create_options & FILE_DELETE_ON_CLOSE) {
5550                         status = can_set_delete_on_close(fsp, True, 0);
5551
5552                         if (NT_STATUS_IS_OK(status)) {
5553                                 /* Note that here we set the *inital* delete on close flag,
5554                                  * not the regular one. The magic gets handled in close. */
5555                                 fsp->initial_delete_on_close = True;
5556                         }
5557                 }
5558                 TALLOC_FREE(lck);
5559                 return NT_STATUS_OK;
5560         }
5561
5562         TALLOC_FREE(lck);
5563
5564         if (errno == ENOTDIR || errno == EISDIR) {
5565                 status = NT_STATUS_OBJECT_NAME_COLLISION;
5566         } else {
5567                 status = map_nt_error_from_unix(errno);
5568         }
5569
5570         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5571                 nt_errstr(status), fsp->fsp_name,newname));
5572
5573         return status;
5574 }
5575
5576 /****************************************************************************
5577  The guts of the rename command, split out so it may be called by the NT SMB
5578  code.
5579 ****************************************************************************/
5580
5581 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5582                         connection_struct *conn,
5583                         struct smb_request *req,
5584                         const char *name_in,
5585                         const char *newname_in,
5586                         uint32 attrs,
5587                         bool replace_if_exists,
5588                         bool src_has_wild,
5589                         bool dest_has_wild,
5590                         uint32_t access_mask)
5591 {
5592         char *directory = NULL;
5593         char *mask = NULL;
5594         char *last_component_src = NULL;
5595         char *last_component_dest = NULL;
5596         char *name = NULL;
5597         char *newname = NULL;
5598         char *p;
5599         int count=0;
5600         NTSTATUS status = NT_STATUS_OK;
5601         SMB_STRUCT_STAT sbuf1, sbuf2;
5602         struct smb_Dir *dir_hnd = NULL;
5603         const char *dname;
5604         long offset = 0;
5605
5606         ZERO_STRUCT(sbuf1);
5607         ZERO_STRUCT(sbuf2);
5608
5609         status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5610                         &last_component_src, &sbuf1);
5611         if (!NT_STATUS_IS_OK(status)) {
5612                 return status;
5613         }
5614
5615         status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5616                         &last_component_dest, &sbuf2);
5617         if (!NT_STATUS_IS_OK(status)) {
5618                 return status;
5619         }
5620
5621         /*
5622          * Split the old name into directory and last component
5623          * strings. Note that unix_convert may have stripped off a
5624          * leading ./ from both name and newname if the rename is
5625          * at the root of the share. We need to make sure either both
5626          * name and newname contain a / character or neither of them do
5627          * as this is checked in resolve_wildcards().
5628          */
5629
5630         p = strrchr_m(name,'/');
5631         if (!p) {
5632                 directory = talloc_strdup(ctx, ".");
5633                 if (!directory) {
5634                         return NT_STATUS_NO_MEMORY;
5635                 }
5636                 mask = name;
5637         } else {
5638                 *p = 0;
5639                 directory = talloc_strdup(ctx, name);
5640                 if (!directory) {
5641                         return NT_STATUS_NO_MEMORY;
5642                 }
5643                 mask = p+1;
5644                 *p = '/'; /* Replace needed for exceptional test below. */
5645         }
5646
5647         /*
5648          * We should only check the mangled cache
5649          * here if unix_convert failed. This means
5650          * that the path in 'mask' doesn't exist
5651          * on the file system and so we need to look
5652          * for a possible mangle. This patch from
5653          * Tine Smukavec <valentin.smukavec@hermes.si>.
5654          */
5655
5656         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5657                 char *new_mask = NULL;
5658                 mangle_lookup_name_from_8_3(ctx,
5659                                         mask,
5660                                         &new_mask,
5661                                         conn->params );
5662                 if (new_mask) {
5663                         mask = new_mask;
5664                 }
5665         }
5666
5667         if (!src_has_wild) {
5668                 files_struct *fsp;
5669
5670                 /*
5671                  * No wildcards - just process the one file.
5672                  */
5673                 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5674
5675                 /* Add a terminating '/' to the directory name. */
5676                 directory = talloc_asprintf_append(directory,
5677                                 "/%s",
5678                                 mask);
5679                 if (!directory) {
5680                         return NT_STATUS_NO_MEMORY;
5681                 }
5682
5683                 /* Ensure newname contains a '/' also */
5684                 if(strrchr_m(newname,'/') == 0) {
5685                         newname = talloc_asprintf(ctx,
5686                                                 "./%s",
5687                                                 newname);
5688                         if (!newname) {
5689                                 return NT_STATUS_NO_MEMORY;
5690                         }
5691                 }
5692
5693                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5694                           "case_preserve = %d, short case preserve = %d, "
5695                           "directory = %s, newname = %s, "
5696                           "last_component_dest = %s, is_8_3 = %d\n",
5697                           conn->case_sensitive, conn->case_preserve,
5698                           conn->short_case_preserve, directory,
5699                           newname, last_component_dest, is_short_name));
5700
5701                 /* The dest name still may have wildcards. */
5702                 if (dest_has_wild) {
5703                         char *mod_newname = NULL;
5704                         if (!resolve_wildcards(ctx,
5705                                         directory,newname,&mod_newname)) {
5706                                 DEBUG(6, ("rename_internals: resolve_wildcards "
5707                                         "%s %s failed\n",
5708                                         directory,
5709                                         newname));
5710                                 return NT_STATUS_NO_MEMORY;
5711                         }
5712                         newname = mod_newname;
5713                 }
5714
5715                 ZERO_STRUCT(sbuf1);
5716                 SMB_VFS_STAT(conn, directory, &sbuf1);
5717
5718                 status = S_ISDIR(sbuf1.st_mode) ?
5719                         open_directory(conn, req, directory, &sbuf1,
5720                                        access_mask,
5721                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5722                                        FILE_OPEN, 0, 0, NULL,
5723                                        &fsp)
5724                         : open_file_ntcreate(conn, req, directory, &sbuf1,
5725                                              access_mask,
5726                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5727                                              FILE_OPEN, 0, 0, 0, NULL,
5728                                              &fsp);
5729
5730                 if (!NT_STATUS_IS_OK(status)) {
5731                         DEBUG(3, ("Could not open rename source %s: %s\n",
5732                                   directory, nt_errstr(status)));
5733                         return status;
5734                 }
5735
5736                 status = rename_internals_fsp(conn, fsp, newname,
5737                                               last_component_dest,
5738                                               attrs, replace_if_exists);
5739
5740                 close_file(fsp, NORMAL_CLOSE);
5741
5742                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5743                           nt_errstr(status), directory,newname));
5744
5745                 return status;
5746         }
5747
5748         /*
5749          * Wildcards - process each file that matches.
5750          */
5751         if (strequal(mask,"????????.???")) {
5752                 mask[0] = '*';
5753                 mask[1] = '\0';
5754         }
5755
5756         status = check_name(conn, directory);
5757         if (!NT_STATUS_IS_OK(status)) {
5758                 return status;
5759         }
5760
5761         dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
5762         if (dir_hnd == NULL) {
5763                 return map_nt_error_from_unix(errno);
5764         }
5765
5766         status = NT_STATUS_NO_SUCH_FILE;
5767         /*
5768          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5769          * - gentest fix. JRA
5770          */
5771
5772         while ((dname = ReadDirName(dir_hnd, &offset))) {
5773                 files_struct *fsp = NULL;
5774                 char *fname = NULL;
5775                 char *destname = NULL;
5776                 bool sysdir_entry = False;
5777
5778                 /* Quick check for "." and ".." */
5779                 if (ISDOT(dname) || ISDOTDOT(dname)) {
5780                         if (attrs & aDIR) {
5781                                 sysdir_entry = True;
5782                         } else {
5783                                 continue;
5784                         }
5785                 }
5786
5787                 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5788                         continue;
5789                 }
5790
5791                 if(!mask_match(dname, mask, conn->case_sensitive)) {
5792                         continue;
5793                 }
5794
5795                 if (sysdir_entry) {
5796                         status = NT_STATUS_OBJECT_NAME_INVALID;
5797                         break;
5798                 }
5799
5800                 fname = talloc_asprintf(ctx,
5801                                 "%s/%s",
5802                                 directory,
5803                                 dname);
5804                 if (!fname) {
5805                         return NT_STATUS_NO_MEMORY;
5806                 }
5807
5808                 if (!resolve_wildcards(ctx,
5809                                 fname,newname,&destname)) {
5810                         DEBUG(6, ("resolve_wildcards %s %s failed\n",
5811                                   fname, destname));
5812                         TALLOC_FREE(fname);
5813                         continue;
5814                 }
5815                 if (!destname) {
5816                         return NT_STATUS_NO_MEMORY;
5817                 }
5818
5819                 ZERO_STRUCT(sbuf1);
5820                 SMB_VFS_STAT(conn, fname, &sbuf1);
5821
5822                 status = S_ISDIR(sbuf1.st_mode) ?
5823                         open_directory(conn, req, fname, &sbuf1,
5824                                        access_mask,
5825                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
5826                                        FILE_OPEN, 0, 0, NULL,
5827                                        &fsp)
5828                         : open_file_ntcreate(conn, req, fname, &sbuf1,
5829                                              access_mask,
5830                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
5831                                              FILE_OPEN, 0, 0, 0, NULL,
5832                                              &fsp);
5833
5834                 if (!NT_STATUS_IS_OK(status)) {
5835                         DEBUG(3,("rename_internals: open_file_ntcreate "
5836                                  "returned %s rename %s -> %s\n",
5837                                  nt_errstr(status), directory, newname));
5838                         break;
5839                 }
5840
5841                 status = rename_internals_fsp(conn, fsp, destname, dname,
5842                                               attrs, replace_if_exists);
5843
5844                 close_file(fsp, NORMAL_CLOSE);
5845
5846                 if (!NT_STATUS_IS_OK(status)) {
5847                         DEBUG(3, ("rename_internals_fsp returned %s for "
5848                                   "rename %s -> %s\n", nt_errstr(status),
5849                                   directory, newname));
5850                         break;
5851                 }
5852
5853                 count++;
5854
5855                 DEBUG(3,("rename_internals: doing rename on %s -> "
5856                          "%s\n",fname,destname));
5857
5858                 TALLOC_FREE(fname);
5859                 TALLOC_FREE(destname);
5860         }
5861         TALLOC_FREE(dir_hnd);
5862
5863         if (count == 0 && NT_STATUS_IS_OK(status)) {
5864                 status = map_nt_error_from_unix(errno);
5865         }
5866
5867         return status;
5868 }
5869
5870 /****************************************************************************
5871  Reply to a mv.
5872 ****************************************************************************/
5873
5874 void reply_mv(struct smb_request *req)
5875 {
5876         connection_struct *conn = req->conn;
5877         char *name = NULL;
5878         char *newname = NULL;
5879         char *p;
5880         uint32 attrs;
5881         NTSTATUS status;
5882         bool src_has_wcard = False;
5883         bool dest_has_wcard = False;
5884         TALLOC_CTX *ctx = talloc_tos();
5885
5886         START_PROFILE(SMBmv);
5887
5888         if (req->wct < 1) {
5889                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5890                 END_PROFILE(SMBmv);
5891                 return;
5892         }
5893
5894         attrs = SVAL(req->inbuf,smb_vwv0);
5895
5896         p = smb_buf(req->inbuf) + 1;
5897         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
5898                                    0, STR_TERMINATE, &status,
5899                                    &src_has_wcard);
5900         if (!NT_STATUS_IS_OK(status)) {
5901                 reply_nterror(req, status);
5902                 END_PROFILE(SMBmv);
5903                 return;
5904         }
5905         p++;
5906         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
5907                                    0, STR_TERMINATE, &status,
5908                                    &dest_has_wcard);
5909         if (!NT_STATUS_IS_OK(status)) {
5910                 reply_nterror(req, status);
5911                 END_PROFILE(SMBmv);
5912                 return;
5913         }
5914
5915         status = resolve_dfspath_wcard(ctx, conn,
5916                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5917                                        name,
5918                                        &name,
5919                                        &src_has_wcard);
5920         if (!NT_STATUS_IS_OK(status)) {
5921                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5922                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5923                                         ERRSRV, ERRbadpath);
5924                         END_PROFILE(SMBmv);
5925                         return;
5926                 }
5927                 reply_nterror(req, status);
5928                 END_PROFILE(SMBmv);
5929                 return;
5930         }
5931
5932         status = resolve_dfspath_wcard(ctx, conn,
5933                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
5934                                        newname,
5935                                        &newname,
5936                                        &dest_has_wcard);
5937         if (!NT_STATUS_IS_OK(status)) {
5938                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5939                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5940                                         ERRSRV, ERRbadpath);
5941                         END_PROFILE(SMBmv);
5942                         return;
5943                 }
5944                 reply_nterror(req, status);
5945                 END_PROFILE(SMBmv);
5946                 return;
5947         }
5948
5949         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5950
5951         status = rename_internals(ctx, conn, req, name, newname, attrs, False,
5952                                   src_has_wcard, dest_has_wcard, DELETE_ACCESS);
5953         if (!NT_STATUS_IS_OK(status)) {
5954                 if (open_was_deferred(req->mid)) {
5955                         /* We have re-scheduled this call. */
5956                         END_PROFILE(SMBmv);
5957                         return;
5958                 }
5959                 reply_nterror(req, status);
5960                 END_PROFILE(SMBmv);
5961                 return;
5962         }
5963
5964         reply_outbuf(req, 0, 0);
5965
5966         END_PROFILE(SMBmv);
5967         return;
5968 }
5969
5970 /*******************************************************************
5971  Copy a file as part of a reply_copy.
5972 ******************************************************************/
5973
5974 /*
5975  * TODO: check error codes on all callers
5976  */
5977
5978 NTSTATUS copy_file(TALLOC_CTX *ctx,
5979                         connection_struct *conn,
5980                         const char *src,
5981                         const char *dest1,
5982                         int ofun,
5983                         int count,
5984                         bool target_is_directory)
5985 {
5986         SMB_STRUCT_STAT src_sbuf, sbuf2;
5987         SMB_OFF_T ret=-1;
5988         files_struct *fsp1,*fsp2;
5989         char *dest = NULL;
5990         uint32 dosattrs;
5991         uint32 new_create_disposition;
5992         NTSTATUS status;
5993
5994         dest = talloc_strdup(ctx, dest1);
5995         if (!dest) {
5996                 return NT_STATUS_NO_MEMORY;
5997         }
5998         if (target_is_directory) {
5999                 const char *p = strrchr_m(src,'/');
6000                 if (p) {
6001                         p++;
6002                 } else {
6003                         p = src;
6004                 }
6005                 dest = talloc_asprintf_append(dest,
6006                                 "/%s",
6007                                 p);
6008                 if (!dest) {
6009                         return NT_STATUS_NO_MEMORY;
6010                 }
6011         }
6012
6013         if (!vfs_file_exist(conn,src,&src_sbuf)) {
6014                 TALLOC_FREE(dest);
6015                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6016         }
6017
6018         if (!target_is_directory && count) {
6019                 new_create_disposition = FILE_OPEN;
6020         } else {
6021                 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6022                                 NULL, NULL, &new_create_disposition, NULL)) {
6023                         TALLOC_FREE(dest);
6024                         return NT_STATUS_INVALID_PARAMETER;
6025                 }
6026         }
6027
6028         status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
6029                         FILE_GENERIC_READ,
6030                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6031                         FILE_OPEN,
6032                         0,
6033                         FILE_ATTRIBUTE_NORMAL,
6034                         INTERNAL_OPEN_ONLY,
6035                         NULL, &fsp1);
6036
6037         if (!NT_STATUS_IS_OK(status)) {
6038                 TALLOC_FREE(dest);
6039                 return status;
6040         }
6041
6042         dosattrs = dos_mode(conn, src, &src_sbuf);
6043         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6044                 ZERO_STRUCTP(&sbuf2);
6045         }
6046
6047         status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
6048                         FILE_GENERIC_WRITE,
6049                         FILE_SHARE_READ|FILE_SHARE_WRITE,
6050                         new_create_disposition,
6051                         0,
6052                         dosattrs,
6053                         INTERNAL_OPEN_ONLY,
6054                         NULL, &fsp2);
6055
6056         TALLOC_FREE(dest);
6057
6058         if (!NT_STATUS_IS_OK(status)) {
6059                 close_file(fsp1,ERROR_CLOSE);
6060                 return status;
6061         }
6062
6063         if ((ofun&3) == 1) {
6064                 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6065                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6066                         /*
6067                          * Stop the copy from occurring.
6068                          */
6069                         ret = -1;
6070                         src_sbuf.st_size = 0;
6071                 }
6072         }
6073
6074         if (src_sbuf.st_size) {
6075                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6076         }
6077
6078         close_file(fsp1,NORMAL_CLOSE);
6079
6080         /* Ensure the modtime is set correctly on the destination file. */
6081         fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
6082
6083         /*
6084          * As we are opening fsp1 read-only we only expect
6085          * an error on close on fsp2 if we are out of space.
6086          * Thus we don't look at the error return from the
6087          * close of fsp1.
6088          */
6089         status = close_file(fsp2,NORMAL_CLOSE);
6090
6091         if (!NT_STATUS_IS_OK(status)) {
6092                 return status;
6093         }
6094
6095         if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6096                 return NT_STATUS_DISK_FULL;
6097         }
6098
6099         return NT_STATUS_OK;
6100 }
6101
6102 /****************************************************************************
6103  Reply to a file copy.
6104 ****************************************************************************/
6105
6106 void reply_copy(struct smb_request *req)
6107 {
6108         connection_struct *conn = req->conn;
6109         char *name = NULL;
6110         char *newname = NULL;
6111         char *directory = NULL;
6112         char *mask = NULL;
6113         char *p;
6114         int count=0;
6115         int error = ERRnoaccess;
6116         int err = 0;
6117         int tid2;
6118         int ofun;
6119         int flags;
6120         bool target_is_directory=False;
6121         bool source_has_wild = False;
6122         bool dest_has_wild = False;
6123         SMB_STRUCT_STAT sbuf1, sbuf2;
6124         NTSTATUS status;
6125         TALLOC_CTX *ctx = talloc_tos();
6126
6127         START_PROFILE(SMBcopy);
6128
6129         if (req->wct < 3) {
6130                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6131                 END_PROFILE(SMBcopy);
6132                 return;
6133         }
6134
6135         tid2 = SVAL(req->inbuf,smb_vwv0);
6136         ofun = SVAL(req->inbuf,smb_vwv1);
6137         flags = SVAL(req->inbuf,smb_vwv2);
6138
6139         p = smb_buf(req->inbuf);
6140         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
6141                                    0, STR_TERMINATE, &status,
6142                                    &source_has_wild);
6143         if (!NT_STATUS_IS_OK(status)) {
6144                 reply_nterror(req, status);
6145                 END_PROFILE(SMBcopy);
6146                 return;
6147         }
6148         p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
6149                                    0, STR_TERMINATE, &status,
6150                                    &dest_has_wild);
6151         if (!NT_STATUS_IS_OK(status)) {
6152                 reply_nterror(req, status);
6153                 END_PROFILE(SMBcopy);
6154                 return;
6155         }
6156
6157         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6158
6159         if (tid2 != conn->cnum) {
6160                 /* can't currently handle inter share copies XXXX */
6161                 DEBUG(3,("Rejecting inter-share copy\n"));
6162                 reply_doserror(req, ERRSRV, ERRinvdevice);
6163                 END_PROFILE(SMBcopy);
6164                 return;
6165         }
6166
6167         status = resolve_dfspath_wcard(ctx, conn,
6168                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6169                                        name,
6170                                        &name,
6171                                        &source_has_wild);
6172         if (!NT_STATUS_IS_OK(status)) {
6173                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6174                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6175                                         ERRSRV, ERRbadpath);
6176                         END_PROFILE(SMBcopy);
6177                         return;
6178                 }
6179                 reply_nterror(req, status);
6180                 END_PROFILE(SMBcopy);
6181                 return;
6182         }
6183
6184         status = resolve_dfspath_wcard(ctx, conn,
6185                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
6186                                        newname,
6187                                        &newname,
6188                                        &dest_has_wild);
6189         if (!NT_STATUS_IS_OK(status)) {
6190                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6191                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6192                                         ERRSRV, ERRbadpath);
6193                         END_PROFILE(SMBcopy);
6194                         return;
6195                 }
6196                 reply_nterror(req, status);
6197                 END_PROFILE(SMBcopy);
6198                 return;
6199         }
6200
6201         status = unix_convert(ctx, conn, name, source_has_wild,
6202                         &name, NULL, &sbuf1);
6203         if (!NT_STATUS_IS_OK(status)) {
6204                 reply_nterror(req, status);
6205                 END_PROFILE(SMBcopy);
6206                 return;
6207         }
6208
6209         status = unix_convert(ctx, conn, newname, dest_has_wild,
6210                         &newname, NULL, &sbuf2);
6211         if (!NT_STATUS_IS_OK(status)) {
6212                 reply_nterror(req, status);
6213                 END_PROFILE(SMBcopy);
6214                 return;
6215         }
6216
6217         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6218
6219         if ((flags&1) && target_is_directory) {
6220                 reply_doserror(req, ERRDOS, ERRbadfile);
6221                 END_PROFILE(SMBcopy);
6222                 return;
6223         }
6224
6225         if ((flags&2) && !target_is_directory) {
6226                 reply_doserror(req, ERRDOS, ERRbadpath);
6227                 END_PROFILE(SMBcopy);
6228                 return;
6229         }
6230
6231         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6232                 /* wants a tree copy! XXXX */
6233                 DEBUG(3,("Rejecting tree copy\n"));
6234                 reply_doserror(req, ERRSRV, ERRerror);
6235                 END_PROFILE(SMBcopy);
6236                 return;
6237         }
6238
6239         p = strrchr_m(name,'/');
6240         if (!p) {
6241                 directory = talloc_strdup(ctx, "./");
6242                 if (!directory) {
6243                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6244                         END_PROFILE(SMBcopy);
6245                         return;
6246                 }
6247                 mask = name;
6248         } else {
6249                 *p = 0;
6250                 directory = talloc_strdup(ctx, name);
6251                 if (!directory) {
6252                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6253                         END_PROFILE(SMBcopy);
6254                         return;
6255                 }
6256                 mask = p+1;
6257         }
6258
6259         /*
6260          * We should only check the mangled cache
6261          * here if unix_convert failed. This means
6262          * that the path in 'mask' doesn't exist
6263          * on the file system and so we need to look
6264          * for a possible mangle. This patch from
6265          * Tine Smukavec <valentin.smukavec@hermes.si>.
6266          */
6267
6268         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6269                 char *new_mask = NULL;
6270                 mangle_lookup_name_from_8_3(ctx,
6271                                         mask,
6272                                         &new_mask,
6273                                         conn->params );
6274                 if (new_mask) {
6275                         mask = new_mask;
6276                 }
6277         }
6278
6279         if (!source_has_wild) {
6280                 directory = talloc_asprintf_append(directory,
6281                                 "/%s",
6282                                 mask);
6283                 if (dest_has_wild) {
6284                         char *mod_newname = NULL;
6285                         if (!resolve_wildcards(ctx,
6286                                         directory,newname,&mod_newname)) {
6287                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6288                                 END_PROFILE(SMBcopy);
6289                                 return;
6290                         }
6291                         newname = mod_newname;
6292                 }
6293
6294                 status = check_name(conn, directory);
6295                 if (!NT_STATUS_IS_OK(status)) {
6296                         reply_nterror(req, status);
6297                         END_PROFILE(SMBcopy);
6298                         return;
6299                 }
6300
6301                 status = check_name(conn, newname);
6302                 if (!NT_STATUS_IS_OK(status)) {
6303                         reply_nterror(req, status);
6304                         END_PROFILE(SMBcopy);
6305                         return;
6306                 }
6307
6308                 status = copy_file(ctx,conn,directory,newname,ofun,
6309                                 count,target_is_directory);
6310
6311                 if(!NT_STATUS_IS_OK(status)) {
6312                         reply_nterror(req, status);
6313                         END_PROFILE(SMBcopy);
6314                         return;
6315                 } else {
6316                         count++;
6317                 }
6318         } else {
6319                 struct smb_Dir *dir_hnd = NULL;
6320                 const char *dname = NULL;
6321                 long offset = 0;
6322
6323                 if (strequal(mask,"????????.???")) {
6324                         mask[0] = '*';
6325                         mask[1] = '\0';
6326                 }
6327
6328                 status = check_name(conn, directory);
6329                 if (!NT_STATUS_IS_OK(status)) {
6330                         reply_nterror(req, status);
6331                         END_PROFILE(SMBcopy);
6332                         return;
6333                 }
6334
6335                 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6336                 if (dir_hnd == NULL) {
6337                         status = map_nt_error_from_unix(errno);
6338                         reply_nterror(req, status);
6339                         END_PROFILE(SMBcopy);
6340                         return;
6341                 }
6342
6343                 error = ERRbadfile;
6344
6345                 while ((dname = ReadDirName(dir_hnd, &offset))) {
6346                         char *destname = NULL;
6347                         char *fname = NULL;
6348
6349                         if (ISDOT(dname) || ISDOTDOT(dname)) {
6350                                 continue;
6351                         }
6352
6353                         if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6354                                 continue;
6355                         }
6356
6357                         if(!mask_match(dname, mask, conn->case_sensitive)) {
6358                                 continue;
6359                         }
6360
6361                         error = ERRnoaccess;
6362                         fname = talloc_asprintf(ctx,
6363                                         "%s/%s",
6364                                         directory,
6365                                         dname);
6366                         if (!fname) {
6367                                 TALLOC_FREE(dir_hnd);
6368                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6369                                 END_PROFILE(SMBcopy);
6370                                 return;
6371                         }
6372
6373                         if (!resolve_wildcards(ctx,
6374                                         fname,newname,&destname)) {
6375                                 continue;
6376                         }
6377                         if (!destname) {
6378                                 TALLOC_FREE(dir_hnd);
6379                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6380                                 END_PROFILE(SMBcopy);
6381                                 return;
6382                         }
6383
6384                         status = check_name(conn, fname);
6385                         if (!NT_STATUS_IS_OK(status)) {
6386                                 TALLOC_FREE(dir_hnd);
6387                                 reply_nterror(req, status);
6388                                 END_PROFILE(SMBcopy);
6389                                 return;
6390                         }
6391
6392                         status = check_name(conn, destname);
6393                         if (!NT_STATUS_IS_OK(status)) {
6394                                 TALLOC_FREE(dir_hnd);
6395                                 reply_nterror(req, status);
6396                                 END_PROFILE(SMBcopy);
6397                                 return;
6398                         }
6399
6400                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6401
6402                         status = copy_file(ctx,conn,fname,destname,ofun,
6403                                         count,target_is_directory);
6404                         if (NT_STATUS_IS_OK(status)) {
6405                                 count++;
6406                         }
6407                         TALLOC_FREE(fname);
6408                         TALLOC_FREE(destname);
6409                 }
6410                 TALLOC_FREE(dir_hnd);
6411         }
6412
6413         if (count == 0) {
6414                 if(err) {
6415                         /* Error on close... */
6416                         errno = err;
6417                         reply_unixerror(req, ERRHRD, ERRgeneral);
6418                         END_PROFILE(SMBcopy);
6419                         return;
6420                 }
6421
6422                 reply_doserror(req, ERRDOS, error);
6423                 END_PROFILE(SMBcopy);
6424                 return;
6425         }
6426
6427         reply_outbuf(req, 1, 0);
6428         SSVAL(req->outbuf,smb_vwv0,count);
6429
6430         END_PROFILE(SMBcopy);
6431         return;
6432 }
6433
6434 #undef DBGC_CLASS
6435 #define DBGC_CLASS DBGC_LOCKING
6436
6437 /****************************************************************************
6438  Get a lock pid, dealing with large count requests.
6439 ****************************************************************************/
6440
6441 uint32 get_lock_pid( char *data, int data_offset, bool large_file_format)
6442 {
6443         if(!large_file_format)
6444                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6445         else
6446                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6447 }
6448
6449 /****************************************************************************
6450  Get a lock count, dealing with large count requests.
6451 ****************************************************************************/
6452
6453 SMB_BIG_UINT get_lock_count( char *data, int data_offset, bool large_file_format)
6454 {
6455         SMB_BIG_UINT count = 0;
6456
6457         if(!large_file_format) {
6458                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6459         } else {
6460
6461 #if defined(HAVE_LONGLONG)
6462                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6463                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6464 #else /* HAVE_LONGLONG */
6465
6466                 /*
6467                  * NT4.x seems to be broken in that it sends large file (64 bit)
6468                  * lockingX calls even if the CAP_LARGE_FILES was *not*
6469                  * negotiated. For boxes without large unsigned ints truncate the
6470                  * lock count by dropping the top 32 bits.
6471                  */
6472
6473                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6474                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6475                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6476                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6477                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6478                 }
6479
6480                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6481 #endif /* HAVE_LONGLONG */
6482         }
6483
6484         return count;
6485 }
6486
6487 #if !defined(HAVE_LONGLONG)
6488 /****************************************************************************
6489  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6490 ****************************************************************************/
6491
6492 static uint32 map_lock_offset(uint32 high, uint32 low)
6493 {
6494         unsigned int i;
6495         uint32 mask = 0;
6496         uint32 highcopy = high;
6497  
6498         /*
6499          * Try and find out how many significant bits there are in high.
6500          */
6501  
6502         for(i = 0; highcopy; i++)
6503                 highcopy >>= 1;
6504  
6505         /*
6506          * We use 31 bits not 32 here as POSIX
6507          * lock offsets may not be negative.
6508          */
6509  
6510         mask = (~0) << (31 - i);
6511  
6512         if(low & mask)
6513                 return 0; /* Fail. */
6514  
6515         high <<= (31 - i);
6516  
6517         return (high|low);
6518 }
6519 #endif /* !defined(HAVE_LONGLONG) */
6520
6521 /****************************************************************************
6522  Get a lock offset, dealing with large offset requests.
6523 ****************************************************************************/
6524
6525 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_format, bool *err)
6526 {
6527         SMB_BIG_UINT offset = 0;
6528
6529         *err = False;
6530
6531         if(!large_file_format) {
6532                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6533         } else {
6534
6535 #if defined(HAVE_LONGLONG)
6536                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6537                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6538 #else /* HAVE_LONGLONG */
6539
6540                 /*
6541                  * NT4.x seems to be broken in that it sends large file (64 bit)
6542                  * lockingX calls even if the CAP_LARGE_FILES was *not*
6543                  * negotiated. For boxes without large unsigned ints mangle the
6544                  * lock offset by mapping the top 32 bits onto the lower 32.
6545                  */
6546       
6547                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6548                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6549                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6550                         uint32 new_low = 0;
6551
6552                         if((new_low = map_lock_offset(high, low)) == 0) {
6553                                 *err = True;
6554                                 return (SMB_BIG_UINT)-1;
6555                         }
6556
6557                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6558                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6559                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6560                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6561                 }
6562
6563                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6564 #endif /* HAVE_LONGLONG */
6565         }
6566
6567         return offset;
6568 }
6569
6570 /****************************************************************************
6571  Reply to a lockingX request.
6572 ****************************************************************************/
6573
6574 void reply_lockingX(struct smb_request *req)
6575 {
6576         connection_struct *conn = req->conn;
6577         files_struct *fsp;
6578         unsigned char locktype;
6579         unsigned char oplocklevel;
6580         uint16 num_ulocks;
6581         uint16 num_locks;
6582         SMB_BIG_UINT count = 0, offset = 0;
6583         uint32 lock_pid;
6584         int32 lock_timeout;
6585         int i;
6586         char *data;
6587         bool large_file_format;
6588         bool err;
6589         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6590
6591         START_PROFILE(SMBlockingX);
6592
6593         if (req->wct < 8) {
6594                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6595                 END_PROFILE(SMBlockingX);
6596                 return;
6597         }
6598         
6599         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
6600         locktype = CVAL(req->inbuf,smb_vwv3);
6601         oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
6602         num_ulocks = SVAL(req->inbuf,smb_vwv6);
6603         num_locks = SVAL(req->inbuf,smb_vwv7);
6604         lock_timeout = IVAL(req->inbuf,smb_vwv4);
6605         large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6606
6607         if (!check_fsp(conn, req, fsp, &current_user)) {
6608                 END_PROFILE(SMBlockingX);
6609                 return;
6610         }
6611         
6612         data = smb_buf(req->inbuf);
6613
6614         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6615                 /* we don't support these - and CANCEL_LOCK makes w2k
6616                    and XP reboot so I don't really want to be
6617                    compatible! (tridge) */
6618                 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6619                 END_PROFILE(SMBlockingX);
6620                 return;
6621         }
6622         
6623         /* Check if this is an oplock break on a file
6624            we have granted an oplock on.
6625         */
6626         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6627                 /* Client can insist on breaking to none. */
6628                 bool break_to_none = (oplocklevel == 0);
6629                 bool result;
6630
6631                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6632                          "for fnum = %d\n", (unsigned int)oplocklevel,
6633                          fsp->fnum ));
6634
6635                 /*
6636                  * Make sure we have granted an exclusive or batch oplock on
6637                  * this file.
6638                  */
6639                 
6640                 if (fsp->oplock_type == 0) {
6641
6642                         /* The Samba4 nbench simulator doesn't understand
6643                            the difference between break to level2 and break
6644                            to none from level2 - it sends oplock break
6645                            replies in both cases. Don't keep logging an error
6646                            message here - just ignore it. JRA. */
6647
6648                         DEBUG(5,("reply_lockingX: Error : oplock break from "
6649                                  "client for fnum = %d (oplock=%d) and no "
6650                                  "oplock granted on this file (%s).\n",
6651                                  fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6652
6653                         /* if this is a pure oplock break request then don't
6654                          * send a reply */
6655                         if (num_locks == 0 && num_ulocks == 0) {
6656                                 END_PROFILE(SMBlockingX);
6657                                 return;
6658                         } else {
6659                                 END_PROFILE(SMBlockingX);
6660                                 reply_doserror(req, ERRDOS, ERRlock);
6661                                 return;
6662                         }
6663                 }
6664
6665                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6666                     (break_to_none)) {
6667                         result = remove_oplock(fsp);
6668                 } else {
6669                         result = downgrade_oplock(fsp);
6670                 }
6671                 
6672                 if (!result) {
6673                         DEBUG(0, ("reply_lockingX: error in removing "
6674                                   "oplock on file %s\n", fsp->fsp_name));
6675                         /* Hmmm. Is this panic justified? */
6676                         smb_panic("internal tdb error");
6677                 }
6678
6679                 reply_to_oplock_break_requests(fsp);
6680
6681                 /* if this is a pure oplock break request then don't send a
6682                  * reply */
6683                 if (num_locks == 0 && num_ulocks == 0) {
6684                         /* Sanity check - ensure a pure oplock break is not a
6685                            chained request. */
6686                         if(CVAL(req->inbuf,smb_vwv0) != 0xff)
6687                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
6688                                          "break is a chained %d request !\n",
6689                                          (unsigned int)CVAL(req->inbuf,
6690                                                             smb_vwv0) ));
6691                         END_PROFILE(SMBlockingX);
6692                         return;
6693                 }
6694         }
6695
6696         /*
6697          * We do this check *after* we have checked this is not a oplock break
6698          * response message. JRA.
6699          */
6700         
6701         release_level_2_oplocks_on_change(fsp);
6702
6703         if (smb_buflen(req->inbuf) <
6704             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6705                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6706                 END_PROFILE(SMBlockingX);
6707                 return;
6708         }
6709         
6710         /* Data now points at the beginning of the list
6711            of smb_unlkrng structs */
6712         for(i = 0; i < (int)num_ulocks; i++) {
6713                 lock_pid = get_lock_pid( data, i, large_file_format);
6714                 count = get_lock_count( data, i, large_file_format);
6715                 offset = get_lock_offset( data, i, large_file_format, &err);
6716                 
6717                 /*
6718                  * There is no error code marked "stupid client bug".... :-).
6719                  */
6720                 if(err) {
6721                         END_PROFILE(SMBlockingX);
6722                         reply_doserror(req, ERRDOS, ERRnoaccess);
6723                         return;
6724                 }
6725
6726                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6727                           "pid %u, file %s\n", (double)offset, (double)count,
6728                           (unsigned int)lock_pid, fsp->fsp_name ));
6729                 
6730                 status = do_unlock(smbd_messaging_context(),
6731                                 fsp,
6732                                 lock_pid,
6733                                 count,
6734                                 offset,
6735                                 WINDOWS_LOCK);
6736
6737                 if (NT_STATUS_V(status)) {
6738                         END_PROFILE(SMBlockingX);
6739                         reply_nterror(req, status);
6740                         return;
6741                 }
6742         }
6743
6744         /* Setup the timeout in seconds. */
6745
6746         if (!lp_blocking_locks(SNUM(conn))) {
6747                 lock_timeout = 0;
6748         }
6749         
6750         /* Now do any requested locks */
6751         data += ((large_file_format ? 20 : 10)*num_ulocks);
6752         
6753         /* Data now points at the beginning of the list
6754            of smb_lkrng structs */
6755         
6756         for(i = 0; i < (int)num_locks; i++) {
6757                 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6758                                 READ_LOCK:WRITE_LOCK);
6759                 lock_pid = get_lock_pid( data, i, large_file_format);
6760                 count = get_lock_count( data, i, large_file_format);
6761                 offset = get_lock_offset( data, i, large_file_format, &err);
6762                 
6763                 /*
6764                  * There is no error code marked "stupid client bug".... :-).
6765                  */
6766                 if(err) {
6767                         END_PROFILE(SMBlockingX);
6768                         reply_doserror(req, ERRDOS, ERRnoaccess);
6769                         return;
6770                 }
6771                 
6772                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6773                           "%u, file %s timeout = %d\n", (double)offset,
6774                           (double)count, (unsigned int)lock_pid,
6775                           fsp->fsp_name, (int)lock_timeout ));
6776                 
6777                 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6778                         if (lp_blocking_locks(SNUM(conn))) {
6779
6780                                 /* Schedule a message to ourselves to
6781                                    remove the blocking lock record and
6782                                    return the right error. */
6783
6784                                 if (!blocking_lock_cancel(fsp,
6785                                                 lock_pid,
6786                                                 offset,
6787                                                 count,
6788                                                 WINDOWS_LOCK,
6789                                                 locktype,
6790                                                 NT_STATUS_FILE_LOCK_CONFLICT)) {
6791                                         END_PROFILE(SMBlockingX);
6792                                         reply_nterror(
6793                                                 req,
6794                                                 NT_STATUS_DOS(
6795                                                         ERRDOS,
6796                                                         ERRcancelviolation));
6797                                         return;
6798                                 }
6799                         }
6800                         /* Remove a matching pending lock. */
6801                         status = do_lock_cancel(fsp,
6802                                                 lock_pid,
6803                                                 count,
6804                                                 offset,
6805                                                 WINDOWS_LOCK);
6806                 } else {
6807                         bool blocking_lock = lock_timeout ? True : False;
6808                         bool defer_lock = False;
6809                         struct byte_range_lock *br_lck;
6810                         uint32 block_smbpid;
6811
6812                         br_lck = do_lock(smbd_messaging_context(),
6813                                         fsp,
6814                                         lock_pid,
6815                                         count,
6816                                         offset, 
6817                                         lock_type,
6818                                         WINDOWS_LOCK,
6819                                         blocking_lock,
6820                                         &status,
6821                                         &block_smbpid);
6822
6823                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6824                                 /* Windows internal resolution for blocking locks seems
6825                                    to be about 200ms... Don't wait for less than that. JRA. */
6826                                 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6827                                         lock_timeout = lp_lock_spin_time();
6828                                 }
6829                                 defer_lock = True;
6830                         }
6831
6832                         /* This heuristic seems to match W2K3 very well. If a
6833                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6834                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
6835                            far as I can tell. Replacement for do_lock_spin(). JRA. */
6836
6837                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6838                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6839                                 defer_lock = True;
6840                                 lock_timeout = lp_lock_spin_time();
6841                         }
6842
6843                         if (br_lck && defer_lock) {
6844                                 /*
6845                                  * A blocking lock was requested. Package up
6846                                  * this smb into a queued request and push it
6847                                  * onto the blocking lock queue.
6848                                  */
6849                                 if(push_blocking_lock_request(br_lck,
6850                                                         req,
6851                                                         fsp,
6852                                                         lock_timeout,
6853                                                         i,
6854                                                         lock_pid,
6855                                                         lock_type,
6856                                                         WINDOWS_LOCK,
6857                                                         offset,
6858                                                         count,
6859                                                         block_smbpid)) {
6860                                         TALLOC_FREE(br_lck);
6861                                         END_PROFILE(SMBlockingX);
6862                                         return;
6863                                 }
6864                         }
6865
6866                         TALLOC_FREE(br_lck);
6867                 }
6868
6869                 if (NT_STATUS_V(status)) {
6870                         END_PROFILE(SMBlockingX);
6871                         reply_nterror(req, status);
6872                         return;
6873                 }
6874         }
6875         
6876         /* If any of the above locks failed, then we must unlock
6877            all of the previous locks (X/Open spec). */
6878
6879         if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6880                         (i != num_locks) &&
6881                         (num_locks != 0)) {
6882                 /*
6883                  * Ensure we don't do a remove on the lock that just failed,
6884                  * as under POSIX rules, if we have a lock already there, we
6885                  * will delete it (and we shouldn't) .....
6886                  */
6887                 for(i--; i >= 0; i--) {
6888                         lock_pid = get_lock_pid( data, i, large_file_format);
6889                         count = get_lock_count( data, i, large_file_format);
6890                         offset = get_lock_offset( data, i, large_file_format,
6891                                                   &err);
6892                         
6893                         /*
6894                          * There is no error code marked "stupid client
6895                          * bug".... :-).
6896                          */
6897                         if(err) {
6898                                 END_PROFILE(SMBlockingX);
6899                                 reply_doserror(req, ERRDOS, ERRnoaccess);
6900                                 return;
6901                         }
6902                         
6903                         do_unlock(smbd_messaging_context(),
6904                                 fsp,
6905                                 lock_pid,
6906                                 count,
6907                                 offset,
6908                                 WINDOWS_LOCK);
6909                 }
6910                 END_PROFILE(SMBlockingX);
6911                 reply_nterror(req, status);
6912                 return;
6913         }
6914
6915         reply_outbuf(req, 2, 0);
6916         
6917         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
6918                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
6919         
6920         END_PROFILE(SMBlockingX);
6921         chain_reply(req);
6922 }
6923
6924 #undef DBGC_CLASS
6925 #define DBGC_CLASS DBGC_ALL
6926
6927 /****************************************************************************
6928  Reply to a SMBreadbmpx (read block multiplex) request.
6929  Always reply with an error, if someone has a platform really needs this,
6930  please contact vl@samba.org
6931 ****************************************************************************/
6932
6933 void reply_readbmpx(struct smb_request *req)
6934 {
6935         START_PROFILE(SMBreadBmpx);
6936         reply_doserror(req, ERRSRV, ERRuseSTD);
6937         END_PROFILE(SMBreadBmpx);
6938         return;
6939 }
6940
6941 /****************************************************************************
6942  Reply to a SMBreadbs (read block multiplex secondary) request.
6943  Always reply with an error, if someone has a platform really needs this,
6944  please contact vl@samba.org
6945 ****************************************************************************/
6946
6947 void reply_readbs(struct smb_request *req)
6948 {
6949         START_PROFILE(SMBreadBs);
6950         reply_doserror(req, ERRSRV, ERRuseSTD);
6951         END_PROFILE(SMBreadBs);
6952         return;
6953 }
6954
6955 /****************************************************************************
6956  Reply to a SMBsetattrE.
6957 ****************************************************************************/
6958
6959 void reply_setattrE(struct smb_request *req)
6960 {
6961         connection_struct *conn = req->conn;
6962         struct timespec ts[2];
6963         files_struct *fsp;
6964
6965         START_PROFILE(SMBsetattrE);
6966
6967         if (req->wct < 7) {
6968                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6969                 END_PROFILE(SMBsetattrE);
6970                 return;
6971         }
6972
6973         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
6974
6975         if(!fsp || (fsp->conn != conn)) {
6976                 reply_doserror(req, ERRDOS, ERRbadfid);
6977                 END_PROFILE(SMBsetattrE);
6978                 return;
6979         }
6980
6981
6982         /*
6983          * Convert the DOS times into unix times. Ignore create
6984          * time as UNIX can't set this.
6985          */
6986
6987         ts[0] = convert_time_t_to_timespec(
6988                 srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */
6989         ts[1] = convert_time_t_to_timespec(
6990                 srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */
6991   
6992         reply_outbuf(req, 0, 0);
6993
6994         /* 
6995          * Patch from Ray Frush <frush@engr.colostate.edu>
6996          * Sometimes times are sent as zero - ignore them.
6997          */
6998
6999         if (null_timespec(ts[0]) && null_timespec(ts[1])) {
7000                 /* Ignore request */
7001                 if( DEBUGLVL( 3 ) ) {
7002                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
7003                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
7004                 }
7005                 END_PROFILE(SMBsetattrE);
7006                 return;
7007         } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
7008                 /* set modify time = to access time if modify time was unset */
7009                 ts[1] = ts[0];
7010         }
7011
7012         /* Set the date on this file */
7013         /* Should we set pending modtime here ? JRA */
7014         if(file_ntimes(conn, fsp->fsp_name, ts)) {
7015                 reply_doserror(req, ERRDOS, ERRnoaccess);
7016                 END_PROFILE(SMBsetattrE);
7017                 return;
7018         }
7019   
7020         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7021                 fsp->fnum,
7022                 (unsigned int)ts[0].tv_sec,
7023                 (unsigned int)ts[1].tv_sec));
7024
7025         END_PROFILE(SMBsetattrE);
7026         return;
7027 }
7028
7029
7030 /* Back from the dead for OS/2..... JRA. */
7031
7032 /****************************************************************************
7033  Reply to a SMBwritebmpx (write block multiplex primary) request.
7034  Always reply with an error, if someone has a platform really needs this,
7035  please contact vl@samba.org
7036 ****************************************************************************/
7037
7038 void reply_writebmpx(struct smb_request *req)
7039 {
7040         START_PROFILE(SMBwriteBmpx);
7041         reply_doserror(req, ERRSRV, ERRuseSTD);
7042         END_PROFILE(SMBwriteBmpx);
7043         return;
7044 }
7045
7046 /****************************************************************************
7047  Reply to a SMBwritebs (write block multiplex secondary) request.
7048  Always reply with an error, if someone has a platform really needs this,
7049  please contact vl@samba.org
7050 ****************************************************************************/
7051
7052 void reply_writebs(struct smb_request *req)
7053 {
7054         START_PROFILE(SMBwriteBs);
7055         reply_doserror(req, ERRSRV, ERRuseSTD);
7056         END_PROFILE(SMBwriteBs);
7057         return;
7058 }
7059
7060 /****************************************************************************
7061  Reply to a SMBgetattrE.
7062 ****************************************************************************/
7063
7064 void reply_getattrE(struct smb_request *req)
7065 {
7066         connection_struct *conn = req->conn;
7067         SMB_STRUCT_STAT sbuf;
7068         int mode;
7069         files_struct *fsp;
7070
7071         START_PROFILE(SMBgetattrE);
7072
7073         if (req->wct < 1) {
7074                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7075                 END_PROFILE(SMBgetattrE);
7076                 return;
7077         }
7078
7079         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
7080
7081         if(!fsp || (fsp->conn != conn)) {
7082                 reply_doserror(req, ERRDOS, ERRbadfid);
7083                 END_PROFILE(SMBgetattrE);
7084                 return;
7085         }
7086
7087         /* Do an fstat on this file */
7088         if(fsp_stat(fsp, &sbuf)) {
7089                 reply_unixerror(req, ERRDOS, ERRnoaccess);
7090                 END_PROFILE(SMBgetattrE);
7091                 return;
7092         }
7093   
7094         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7095   
7096         /*
7097          * Convert the times into dos times. Set create
7098          * date to be last modify date as UNIX doesn't save
7099          * this.
7100          */
7101
7102         reply_outbuf(req, 11, 0);
7103
7104         srv_put_dos_date2((char *)req->outbuf, smb_vwv0,
7105                           get_create_time(&sbuf,
7106                                           lp_fake_dir_create_times(SNUM(conn))));
7107         srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7108         /* Should we check pending modtime here ? JRA */
7109         srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7110
7111         if (mode & aDIR) {
7112                 SIVAL(req->outbuf, smb_vwv6, 0);
7113                 SIVAL(req->outbuf, smb_vwv8, 0);
7114         } else {
7115                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
7116                 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7117                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7118         }
7119         SSVAL(req->outbuf,smb_vwv10, mode);
7120   
7121         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7122   
7123         END_PROFILE(SMBgetattrE);
7124         return;
7125 }