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