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