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