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