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