r24306: the check_fsp() function has an explicit user argument
[nivanova/samba-autobuild/.git] / source3 / smbd / reply.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jeremy Allison 1992-2007.
7    Copyright (C) Volker Lendecke 2007
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
27 #include "includes.h"
28
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_recv;
32 unsigned int smb_echo_count = 0;
33 extern uint32 global_client_caps;
34
35 extern struct current_user current_user;
36 extern BOOL global_encrypted_passwords_negotiated;
37
38 /****************************************************************************
39  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
40  path or anything including wildcards.
41  We're assuming here that '/' is not the second byte in any multibyte char
42  set (a safe assumption). '\\' *may* be the second byte in a multibyte char
43  set.
44 ****************************************************************************/
45
46 /* Custom version for processing POSIX paths. */
47 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
48
49 static NTSTATUS check_path_syntax_internal(char *path,
50                                            BOOL posix_path,
51                                            BOOL *p_last_component_contains_wcard)
52 {
53         char *d = path;
54         const char *s = path;
55         NTSTATUS ret = NT_STATUS_OK;
56         BOOL start_of_name_component = True;
57
58         *p_last_component_contains_wcard = False;
59
60         while (*s) {
61                 if (IS_PATH_SEP(*s,posix_path)) {
62                         /*
63                          * Safe to assume is not the second part of a mb char
64                          * as this is handled below.
65                          */
66                         /* Eat multiple '/' or '\\' */
67                         while (IS_PATH_SEP(*s,posix_path)) {
68                                 s++;
69                         }
70                         if ((d != path) && (*s != '\0')) {
71                                 /* We only care about non-leading or trailing '/' or '\\' */
72                                 *d++ = '/';
73                         }
74
75                         start_of_name_component = True;
76                         /* New component. */
77                         *p_last_component_contains_wcard = False;
78                         continue;
79                 }
80
81                 if (start_of_name_component) {
82                         if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
83                                 /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
84
85                                 /*
86                                  * No mb char starts with '.' so we're safe checking the directory separator here.
87                                  */
88
89                                 /* If  we just added a '/' - delete it */
90                                 if ((d > path) && (*(d-1) == '/')) {
91                                         *(d-1) = '\0';
92                                         d--;
93                                 }
94
95                                 /* Are we at the start ? Can't go back further if so. */
96                                 if (d <= path) {
97                                         ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
98                                         break;
99                                 }
100                                 /* Go back one level... */
101                                 /* We know this is safe as '/' cannot be part of a mb sequence. */
102                                 /* NOTE - if this assumption is invalid we are not in good shape... */
103                                 /* Decrement d first as d points to the *next* char to write into. */
104                                 for (d--; d > path; d--) {
105                                         if (*d == '/')
106                                                 break;
107                                 }
108                                 s += 2; /* Else go past the .. */
109                                 /* We're still at the start of a name component, just the previous one. */
110                                 continue;
111
112                         } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
113                                 if (posix_path) {
114                                         /* Eat the '.' */
115                                         s++;
116                                         continue;
117                                 }
118                         }
119
120                 }
121
122                 if (!(*s & 0x80)) {
123                         if (!posix_path) {
124                                 if (*s <= 0x1f) {
125                                         return NT_STATUS_OBJECT_NAME_INVALID;
126                                 }
127                                 switch (*s) {
128                                         case '*':
129                                         case '?':
130                                         case '<':
131                                         case '>':
132                                         case '"':
133                                                 *p_last_component_contains_wcard = True;
134                                                 break;
135                                         default:
136                                                 break;
137                                 }
138                         }
139                         *d++ = *s++;
140                 } else {
141                         size_t siz;
142                         /* Get the size of the next MB character. */
143                         next_codepoint(s,&siz);
144                         switch(siz) {
145                                 case 5:
146                                         *d++ = *s++;
147                                         /*fall through*/
148                                 case 4:
149                                         *d++ = *s++;
150                                         /*fall through*/
151                                 case 3:
152                                         *d++ = *s++;
153                                         /*fall through*/
154                                 case 2:
155                                         *d++ = *s++;
156                                         /*fall through*/
157                                 case 1:
158                                         *d++ = *s++;
159                                         break;
160                                 default:
161                                         DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
162                                         *d = '\0';
163                                         return NT_STATUS_INVALID_PARAMETER;
164                         }
165                 }
166                 start_of_name_component = False;
167         }
168
169         *d = '\0';
170         return ret;
171 }
172
173 /****************************************************************************
174  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
175  No wildcards allowed.
176 ****************************************************************************/
177
178 NTSTATUS check_path_syntax(char *path)
179 {
180         BOOL ignore;
181         return check_path_syntax_internal(path, False, &ignore);
182 }
183
184 /****************************************************************************
185  Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
186  Wildcards allowed - p_contains_wcard returns true if the last component contained
187  a wildcard.
188 ****************************************************************************/
189
190 NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
191 {
192         return check_path_syntax_internal(path, False, p_contains_wcard);
193 }
194
195 /****************************************************************************
196  Check the path for a POSIX client.
197  We're assuming here that '/' is not the second byte in any multibyte char
198  set (a safe assumption).
199 ****************************************************************************/
200
201 NTSTATUS check_path_syntax_posix(char *path)
202 {
203         BOOL ignore;
204         return check_path_syntax_internal(path, True, &ignore);
205 }
206
207 /****************************************************************************
208  Pull a string and check the path allowing a wilcard - provide for error return.
209 ****************************************************************************/
210
211 size_t srvstr_get_path_wcard(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 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2862 {
2863         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
2864         SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2865         ssize_t nread = -1;
2866         size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2867         BOOL big_readX = False;
2868 #if 0
2869         size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2870 #endif
2871
2872         START_PROFILE(SMBreadX);
2873
2874         /* If it's an IPC, pass off the pipe handler. */
2875         if (IS_IPC(conn)) {
2876                 END_PROFILE(SMBreadX);
2877                 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2878         }
2879
2880         CHECK_FSP(fsp,conn);
2881         if (!CHECK_READ(fsp,inbuf)) {
2882                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2883         }
2884
2885         set_message(inbuf,outbuf,12,0,True);
2886
2887         if (global_client_caps & CAP_LARGE_READX) {
2888                 size_t upper_size = SVAL(inbuf,smb_vwv7);
2889                 smb_maxcnt |= (upper_size<<16);
2890                 if (upper_size > 1) {
2891                         /* Can't do this on a chained packet. */
2892                         if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
2893                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2894                         }
2895                         /* We currently don't do this on signed or sealed data. */
2896                         if (srv_is_signing_active() || srv_encryption_on()) {
2897                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2898                         }
2899                         /* Is there room in the reply for this data ? */
2900                         if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
2901                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2902                         }
2903                         big_readX = True;
2904                 }
2905         }
2906
2907         if(CVAL(inbuf,smb_wct) == 12) {
2908 #ifdef LARGE_SMB_OFF_T
2909                 /*
2910                  * This is a large offset (64 bit) read.
2911                  */
2912                 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2913
2914 #else /* !LARGE_SMB_OFF_T */
2915
2916                 /*
2917                  * Ensure we haven't been sent a >32 bit offset.
2918                  */
2919
2920                 if(IVAL(inbuf,smb_vwv10) != 0) {
2921                         DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2922 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2923                         END_PROFILE(SMBreadX);
2924                         return ERROR_DOS(ERRDOS,ERRbadaccess);
2925                 }
2926
2927 #endif /* LARGE_SMB_OFF_T */
2928
2929         }
2930
2931         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2932                 END_PROFILE(SMBreadX);
2933                 return ERROR_DOS(ERRDOS,ERRlock);
2934         }
2935
2936         if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2937                 END_PROFILE(SMBreadX);
2938                 return -1;
2939         }
2940
2941         nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2942         /* Only call chain_reply if not an error. */
2943         if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2944                 nread = chain_reply(inbuf,&outbuf,length,bufsize);
2945         }
2946
2947         END_PROFILE(SMBreadX);
2948         return nread;
2949 }
2950
2951 /****************************************************************************
2952  Reply to a writebraw (core+ or LANMAN1.0 protocol).
2953 ****************************************************************************/
2954
2955 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2956 {
2957         ssize_t nwritten=0;
2958         ssize_t total_written=0;
2959         size_t numtowrite=0;
2960         size_t tcount;
2961         SMB_OFF_T startpos;
2962         char *data=NULL;
2963         BOOL write_through;
2964         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2965         int outsize = 0;
2966         NTSTATUS status;
2967         START_PROFILE(SMBwritebraw);
2968
2969         if (srv_is_signing_active()) {
2970                 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2971         }
2972
2973         CHECK_FSP(fsp,conn);
2974         if (!CHECK_WRITE(fsp)) {
2975                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2976         }
2977   
2978         tcount = IVAL(inbuf,smb_vwv1);
2979         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2980         write_through = BITSETW(inbuf+smb_vwv7,0);
2981
2982         /* We have to deal with slightly different formats depending
2983                 on whether we are using the core+ or lanman1.0 protocol */
2984
2985         if(Protocol <= PROTOCOL_COREPLUS) {
2986                 numtowrite = SVAL(smb_buf(inbuf),-2);
2987                 data = smb_buf(inbuf);
2988         } else {
2989                 numtowrite = SVAL(inbuf,smb_vwv10);
2990                 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2991         }
2992
2993         /* force the error type */
2994         SCVAL(inbuf,smb_com,SMBwritec);
2995         SCVAL(outbuf,smb_com,SMBwritec);
2996
2997         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2998                 END_PROFILE(SMBwritebraw);
2999                 return(ERROR_DOS(ERRDOS,ERRlock));
3000         }
3001
3002         if (numtowrite>0)
3003                 nwritten = write_file(fsp,data,startpos,numtowrite);
3004   
3005         DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
3006                 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
3007
3008         if (nwritten < (ssize_t)numtowrite)  {
3009                 END_PROFILE(SMBwritebraw);
3010                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3011         }
3012
3013         total_written = nwritten;
3014
3015         /* Return a message to the redirector to tell it to send more bytes */
3016         SCVAL(outbuf,smb_com,SMBwritebraw);
3017         SSVALS(outbuf,smb_vwv0,-1);
3018         outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3019         show_msg(outbuf);
3020         if (!send_smb(smbd_server_fd(),outbuf))
3021                 exit_server_cleanly("reply_writebraw: send_smb failed.");
3022   
3023         /* Now read the raw data into the buffer and write it */
3024         if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
3025                 exit_server_cleanly("secondary writebraw failed");
3026         }
3027   
3028         /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
3029         numtowrite = smb_len(inbuf);
3030
3031         /* Set up outbuf to return the correct return */
3032         outsize = set_message(inbuf,outbuf,1,0,True);
3033         SCVAL(outbuf,smb_com,SMBwritec);
3034
3035         if (numtowrite != 0) {
3036
3037                 if (numtowrite > BUFFER_SIZE) {
3038                         DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
3039                                 (unsigned int)numtowrite ));
3040                         exit_server_cleanly("secondary writebraw failed");
3041                 }
3042
3043                 if (tcount > nwritten+numtowrite) {
3044                         DEBUG(3,("Client overestimated the write %d %d %d\n",
3045                                 (int)tcount,(int)nwritten,(int)numtowrite));
3046                 }
3047
3048                 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
3049                         DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
3050                                 strerror(errno) ));
3051                         exit_server_cleanly("secondary writebraw failed");
3052                 }
3053
3054                 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
3055                 if (nwritten == -1) {
3056                         END_PROFILE(SMBwritebraw);
3057                         return(UNIXERROR(ERRHRD,ERRdiskfull));
3058                 }
3059
3060                 if (nwritten < (ssize_t)numtowrite) {
3061                         SCVAL(outbuf,smb_rcls,ERRHRD);
3062                         SSVAL(outbuf,smb_err,ERRdiskfull);      
3063                 }
3064
3065                 if (nwritten > 0)
3066                         total_written += nwritten;
3067         }
3068  
3069         SSVAL(outbuf,smb_vwv0,total_written);
3070
3071         status = sync_file(conn, fsp, write_through);
3072         if (!NT_STATUS_IS_OK(status)) {
3073                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3074                         fsp->fsp_name, nt_errstr(status) ));
3075                 END_PROFILE(SMBwritebraw);
3076                 return ERROR_NT(status);
3077         }
3078
3079         DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
3080                 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
3081
3082         /* we won't return a status if write through is not selected - this follows what WfWg does */
3083         END_PROFILE(SMBwritebraw);
3084         if (!write_through && total_written==tcount) {
3085
3086 #if RABBIT_PELLET_FIX
3087                 /*
3088                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3089                  * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
3090                  */
3091                 if (!send_keepalive(smbd_server_fd()))
3092                         exit_server_cleanly("reply_writebraw: send of keepalive failed");
3093 #endif
3094                 return(-1);
3095         }
3096
3097         return(outsize);
3098 }
3099
3100 #undef DBGC_CLASS
3101 #define DBGC_CLASS DBGC_LOCKING
3102
3103 /****************************************************************************
3104  Reply to a writeunlock (core+).
3105 ****************************************************************************/
3106
3107 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
3108                       int size, int dum_buffsize)
3109 {
3110         ssize_t nwritten = -1;
3111         size_t numtowrite;
3112         SMB_OFF_T startpos;
3113         char *data;
3114         NTSTATUS status = NT_STATUS_OK;
3115         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3116         int outsize = 0;
3117         START_PROFILE(SMBwriteunlock);
3118         
3119         CHECK_FSP(fsp,conn);
3120         if (!CHECK_WRITE(fsp)) {
3121                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3122         }
3123
3124         numtowrite = SVAL(inbuf,smb_vwv1);
3125         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3126         data = smb_buf(inbuf) + 3;
3127   
3128         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3129                 END_PROFILE(SMBwriteunlock);
3130                 return ERROR_DOS(ERRDOS,ERRlock);
3131         }
3132
3133         /* The special X/Open SMB protocol handling of
3134            zero length writes is *NOT* done for
3135            this call */
3136         if(numtowrite == 0) {
3137                 nwritten = 0;
3138         } else {
3139                 nwritten = write_file(fsp,data,startpos,numtowrite);
3140         }
3141   
3142         status = sync_file(conn, fsp, False /* write through */);
3143         if (!NT_STATUS_IS_OK(status)) {
3144                 END_PROFILE(SMBwriteunlock);
3145                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3146                         fsp->fsp_name, nt_errstr(status) ));
3147                 return ERROR_NT(status);
3148         }
3149
3150         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3151                 END_PROFILE(SMBwriteunlock);
3152                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3153         }
3154
3155         if (numtowrite) {
3156                 status = do_unlock(smbd_messaging_context(),
3157                                 fsp,
3158                                 (uint32)SVAL(inbuf,smb_pid),
3159                                 (SMB_BIG_UINT)numtowrite, 
3160                                 (SMB_BIG_UINT)startpos,
3161                                 WINDOWS_LOCK);
3162
3163                 if (NT_STATUS_V(status)) {
3164                         END_PROFILE(SMBwriteunlock);
3165                         return ERROR_NT(status);
3166                 }
3167         }
3168         
3169         outsize = set_message(inbuf,outbuf,1,0,True);
3170         
3171         SSVAL(outbuf,smb_vwv0,nwritten);
3172         
3173         DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3174                  fsp->fnum, (int)numtowrite, (int)nwritten));
3175         
3176         END_PROFILE(SMBwriteunlock);
3177         return outsize;
3178 }
3179
3180 #undef DBGC_CLASS
3181 #define DBGC_CLASS DBGC_ALL
3182
3183 /****************************************************************************
3184  Reply to a write.
3185 ****************************************************************************/
3186
3187 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
3188 {
3189         size_t numtowrite;
3190         ssize_t nwritten = -1;
3191         SMB_OFF_T startpos;
3192         char *data;
3193         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3194         int outsize = 0;
3195         NTSTATUS status;
3196         START_PROFILE(SMBwrite);
3197
3198         /* If it's an IPC, pass off the pipe handler. */
3199         if (IS_IPC(conn)) {
3200                 END_PROFILE(SMBwrite);
3201                 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3202         }
3203
3204         CHECK_FSP(fsp,conn);
3205         if (!CHECK_WRITE(fsp)) {
3206                 END_PROFILE(SMBwrite);
3207                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3208         }
3209
3210         numtowrite = SVAL(inbuf,smb_vwv1);
3211         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3212         data = smb_buf(inbuf) + 3;
3213   
3214         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3215                 END_PROFILE(SMBwrite);
3216                 return ERROR_DOS(ERRDOS,ERRlock);
3217         }
3218
3219         /*
3220          * X/Open SMB protocol says that if smb_vwv1 is
3221          * zero then the file size should be extended or
3222          * truncated to the size given in smb_vwv[2-3].
3223          */
3224
3225         if(numtowrite == 0) {
3226                 /*
3227                  * This is actually an allocate call, and set EOF. JRA.
3228                  */
3229                 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3230                 if (nwritten < 0) {
3231                         END_PROFILE(SMBwrite);
3232                         return ERROR_NT(NT_STATUS_DISK_FULL);
3233                 }
3234                 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3235                 if (nwritten < 0) {
3236                         END_PROFILE(SMBwrite);
3237                         return ERROR_NT(NT_STATUS_DISK_FULL);
3238                 }
3239         } else
3240                 nwritten = write_file(fsp,data,startpos,numtowrite);
3241   
3242         status = sync_file(conn, fsp, False);
3243         if (!NT_STATUS_IS_OK(status)) {
3244                 END_PROFILE(SMBwrite);
3245                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3246                         fsp->fsp_name, nt_errstr(status) ));
3247                 return ERROR_NT(status);
3248         }
3249
3250         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3251                 END_PROFILE(SMBwrite);
3252                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3253         }
3254
3255         outsize = set_message(inbuf,outbuf,1,0,True);
3256   
3257         SSVAL(outbuf,smb_vwv0,nwritten);
3258
3259         if (nwritten < (ssize_t)numtowrite) {
3260                 SCVAL(outbuf,smb_rcls,ERRHRD);
3261                 SSVAL(outbuf,smb_err,ERRdiskfull);      
3262         }
3263   
3264         DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3265
3266         END_PROFILE(SMBwrite);
3267         return(outsize);
3268 }
3269
3270 /****************************************************************************
3271  Reply to a write and X.
3272 ****************************************************************************/
3273
3274 void reply_write_and_X(connection_struct *conn, struct smb_request *req)
3275 {
3276         files_struct *fsp;
3277         SMB_OFF_T startpos;
3278         size_t numtowrite;
3279         BOOL write_through;
3280         ssize_t nwritten;
3281         unsigned int smb_doff;
3282         unsigned int smblen;
3283         char *data;
3284         BOOL large_writeX;
3285         NTSTATUS status;
3286
3287         START_PROFILE(SMBwriteX);
3288
3289         if ((req->wct != 12) && (req->wct != 14)) {
3290                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3291                 END_PROFILE(SMBwriteX);
3292                 return;
3293         }
3294
3295         numtowrite = SVAL(req->inbuf,smb_vwv10);
3296         smb_doff = SVAL(req->inbuf,smb_vwv11);
3297         smblen = smb_len(req->inbuf);
3298         large_writeX = ((req->wct == 14) && (smblen > 0xFFFF));
3299
3300         /* Deal with possible LARGE_WRITEX */
3301         if (large_writeX) {
3302                 numtowrite |= ((((size_t)SVAL(req->inbuf,smb_vwv9)) & 1 )<<16);
3303         }
3304
3305         if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3306                 reply_doserror(req, ERRDOS, ERRbadmem);
3307                 END_PROFILE(SMBwriteX);
3308                 return;
3309         }
3310
3311         /* If it's an IPC, pass off the pipe handler. */
3312         if (IS_IPC(conn)) {
3313                 reply_pipe_write_and_X(req);
3314                 END_PROFILE(SMBwriteX);
3315                 return;
3316         }
3317
3318         fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3319         startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3320         write_through = BITSETW(req->inbuf+smb_vwv7,0);
3321
3322         if (!check_fsp(conn, req, fsp, &current_user)) {
3323                 END_PROFILE(SMBwriteX);
3324                 return;
3325         }
3326
3327         if (!CHECK_WRITE(fsp)) {
3328                 reply_doserror(req, ERRDOS, ERRbadaccess);
3329                 END_PROFILE(SMBwriteX);
3330                 return;
3331         }
3332
3333         data = smb_base(req->inbuf) + smb_doff;
3334
3335         if(req->wct == 14) {
3336 #ifdef LARGE_SMB_OFF_T
3337                 /*
3338                  * This is a large offset (64 bit) write.
3339                  */
3340                 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
3341
3342 #else /* !LARGE_SMB_OFF_T */
3343
3344                 /*
3345                  * Ensure we haven't been sent a >32 bit offset.
3346                  */
3347
3348                 if(IVAL(req->inbuf,smb_vwv12) != 0) {
3349                         DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
3350                                  "used and we don't support 64 bit offsets.\n",
3351                                  (unsigned int)IVAL(inbuf,smb_vwv12) ));
3352                         reply_doserror(req, ERRDOS, ERRbadaccess);
3353                         END_PROFILE(SMBwriteX);
3354                         return;
3355                 }
3356
3357 #endif /* LARGE_SMB_OFF_T */
3358         }
3359
3360         if (is_locked(fsp,(uint32)req->smbpid,
3361                       (SMB_BIG_UINT)numtowrite,
3362                       (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3363                 reply_doserror(req, ERRDOS, ERRlock);
3364                 END_PROFILE(SMBwriteX);
3365                 return;
3366         }
3367
3368         /* X/Open SMB protocol says that, unlike SMBwrite
3369         if the length is zero then NO truncation is
3370         done, just a write of zero. To truncate a file,
3371         use SMBwrite. */
3372
3373         if(numtowrite == 0) {
3374                 nwritten = 0;
3375         } else {
3376
3377                 if (schedule_aio_write_and_X(conn, req, fsp, data, startpos,
3378                                              numtowrite)) {
3379                         END_PROFILE(SMBwriteX);
3380                         return;
3381                 }
3382
3383                 nwritten = write_file(fsp,data,startpos,numtowrite);
3384                 reply_outbuf(req, 6, 0);
3385         }
3386   
3387         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3388                 reply_unixerror(req, ERRHRD, ERRdiskfull);
3389                 END_PROFILE(SMBwriteX);
3390                 return;
3391         }
3392
3393         SSVAL(req->outbuf,smb_vwv2,nwritten);
3394         if (large_writeX)
3395                 SSVAL(req->outbuf,smb_vwv4,(nwritten>>16)&1);
3396
3397         if (nwritten < (ssize_t)numtowrite) {
3398                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3399                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3400         }
3401
3402         DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3403                 fsp->fnum, (int)numtowrite, (int)nwritten));
3404
3405         status = sync_file(conn, fsp, write_through);
3406         if (!NT_STATUS_IS_OK(status)) {
3407                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3408                         fsp->fsp_name, nt_errstr(status) ));
3409                 reply_nterror(req, status);
3410                 END_PROFILE(SMBwriteX);
3411                 return;
3412         }
3413
3414         END_PROFILE(SMBwriteX);
3415         chain_reply_new(req);
3416         return;
3417 }
3418
3419 /****************************************************************************
3420  Reply to a lseek.
3421 ****************************************************************************/
3422
3423 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3424 {
3425         SMB_OFF_T startpos;
3426         SMB_OFF_T res= -1;
3427         int mode,umode;
3428         int outsize = 0;
3429         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3430         START_PROFILE(SMBlseek);
3431
3432         CHECK_FSP(fsp,conn);
3433
3434         flush_write_cache(fsp, SEEK_FLUSH);
3435
3436         mode = SVAL(inbuf,smb_vwv1) & 3;
3437         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3438         startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3439
3440         switch (mode) {
3441                 case 0:
3442                         umode = SEEK_SET;
3443                         res = startpos;
3444                         break;
3445                 case 1:
3446                         umode = SEEK_CUR;
3447                         res = fsp->fh->pos + startpos;
3448                         break;
3449                 case 2:
3450                         umode = SEEK_END;
3451                         break;
3452                 default:
3453                         umode = SEEK_SET;
3454                         res = startpos;
3455                         break;
3456         }
3457
3458         if (umode == SEEK_END) {
3459                 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3460                         if(errno == EINVAL) {
3461                                 SMB_OFF_T current_pos = startpos;
3462                                 SMB_STRUCT_STAT sbuf;
3463
3464                                 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3465                                         END_PROFILE(SMBlseek);
3466                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3467                                 }
3468
3469                                 current_pos += sbuf.st_size;
3470                                 if(current_pos < 0)
3471                                         res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3472                         }
3473                 }
3474
3475                 if(res == -1) {
3476                         END_PROFILE(SMBlseek);
3477                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3478                 }
3479         }
3480
3481         fsp->fh->pos = res;
3482   
3483         outsize = set_message(inbuf,outbuf,2,0,True);
3484         SIVAL(outbuf,smb_vwv0,res);
3485   
3486         DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3487                 fsp->fnum, (double)startpos, (double)res, mode));
3488
3489         END_PROFILE(SMBlseek);
3490         return(outsize);
3491 }
3492
3493 /****************************************************************************
3494  Reply to a flush.
3495 ****************************************************************************/
3496
3497 void reply_flush(connection_struct *conn, struct smb_request *req)
3498 {
3499         uint16 fnum;
3500         files_struct *fsp;
3501
3502         START_PROFILE(SMBflush);
3503
3504         if (req->wct < 1) {
3505                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3506                 return;
3507         }
3508
3509         fnum = SVAL(req->inbuf,smb_vwv0);
3510         fsp = file_fsp(fnum);
3511
3512         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, &current_user)) {
3513                 return;
3514         }
3515         
3516         if (!fsp) {
3517                 file_sync_all(conn);
3518         } else {
3519                 NTSTATUS status = sync_file(conn, fsp, True);
3520                 if (!NT_STATUS_IS_OK(status)) {
3521                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3522                                 fsp->fsp_name, nt_errstr(status) ));
3523                         reply_nterror(req, status);
3524                         END_PROFILE(SMBflush);
3525                         return;
3526                 }
3527         }
3528         
3529         reply_outbuf(req, 0, 0);
3530
3531         DEBUG(3,("flush\n"));
3532         END_PROFILE(SMBflush);
3533         return;
3534 }
3535
3536 /****************************************************************************
3537  Reply to a exit.
3538  conn POINTER CAN BE NULL HERE !
3539 ****************************************************************************/
3540
3541 void reply_exit(connection_struct *conn, struct smb_request *req)
3542 {
3543         START_PROFILE(SMBexit);
3544
3545         file_close_pid(req->smbpid, req->vuid);
3546
3547         reply_outbuf(req, 0, 0);
3548
3549         DEBUG(3,("exit\n"));
3550
3551         END_PROFILE(SMBexit);
3552         return;
3553 }
3554
3555 /****************************************************************************
3556  Reply to a close - has to deal with closing a directory opened by NT SMB's.
3557 ****************************************************************************/
3558
3559 void reply_close(connection_struct *conn, struct smb_request *req)
3560 {
3561         NTSTATUS status = NT_STATUS_OK;
3562         files_struct *fsp = NULL;
3563         START_PROFILE(SMBclose);
3564
3565         if (req->wct < 3) {
3566                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3567                 END_PROFILE(SMBclose);
3568                 return;
3569         }
3570
3571         /* If it's an IPC, pass off to the pipe handler. */
3572         if (IS_IPC(conn)) {
3573                 reply_pipe_close(conn, req);
3574                 END_PROFILE(SMBclose);
3575                 return;
3576         }
3577
3578         fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3579
3580         /*
3581          * We can only use CHECK_FSP if we know it's not a directory.
3582          */
3583
3584         if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3585                 reply_doserror(req, ERRDOS, ERRbadfid);
3586                 END_PROFILE(SMBclose);
3587                 return;
3588         }
3589
3590         if(fsp->is_directory) {
3591                 /*
3592                  * Special case - close NT SMB directory handle.
3593                  */
3594                 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3595                 status = close_file(fsp,NORMAL_CLOSE);
3596         } else {
3597                 /*
3598                  * Close ordinary file.
3599                  */
3600
3601                 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3602                          fsp->fh->fd, fsp->fnum,
3603                          conn->num_files_open));
3604  
3605                 /*
3606                  * Take care of any time sent in the close.
3607                  */
3608
3609                 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
3610                                                 srv_make_unix_date3(
3611                                                         req->inbuf+smb_vwv1)));
3612
3613                 /*
3614                  * close_file() returns the unix errno if an error
3615                  * was detected on close - normally this is due to
3616                  * a disk full error. If not then it was probably an I/O error.
3617                  */
3618  
3619                 status = close_file(fsp,NORMAL_CLOSE);
3620         }  
3621
3622         if (!NT_STATUS_IS_OK(status)) {
3623                 reply_nterror(req, status);
3624                 END_PROFILE(SMBclose);
3625                 return;
3626         }
3627
3628         reply_outbuf(req, 0, 0);
3629         END_PROFILE(SMBclose);
3630         return;
3631 }
3632
3633 /****************************************************************************
3634  Reply to a writeclose (Core+ protocol).
3635 ****************************************************************************/
3636
3637 int reply_writeclose(connection_struct *conn,
3638                      char *inbuf,char *outbuf, int size, int dum_buffsize)
3639 {
3640         size_t numtowrite;
3641         ssize_t nwritten = -1;
3642         int outsize = 0;
3643         NTSTATUS close_status = NT_STATUS_OK;
3644         SMB_OFF_T startpos;
3645         char *data;
3646         struct timespec mtime;
3647         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3648         START_PROFILE(SMBwriteclose);
3649
3650         CHECK_FSP(fsp,conn);
3651         if (!CHECK_WRITE(fsp)) {
3652                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3653         }
3654
3655         numtowrite = SVAL(inbuf,smb_vwv1);
3656         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3657         mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3658         data = smb_buf(inbuf) + 1;
3659   
3660         if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3661                 END_PROFILE(SMBwriteclose);
3662                 return ERROR_DOS(ERRDOS,ERRlock);
3663         }
3664   
3665         nwritten = write_file(fsp,data,startpos,numtowrite);
3666
3667         set_filetime(conn, fsp->fsp_name, mtime);
3668   
3669         /*
3670          * More insanity. W2K only closes the file if writelen > 0.
3671          * JRA.
3672          */
3673
3674         if (numtowrite) {
3675                 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3676                         fsp->fsp_name ));
3677                 close_status = close_file(fsp,NORMAL_CLOSE);
3678         }
3679
3680         DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3681                  fsp->fnum, (int)numtowrite, (int)nwritten,
3682                  conn->num_files_open));
3683   
3684         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3685                 END_PROFILE(SMBwriteclose);
3686                 return(UNIXERROR(ERRHRD,ERRdiskfull));
3687         }
3688  
3689         if(!NT_STATUS_IS_OK(close_status)) {
3690                 END_PROFILE(SMBwriteclose);
3691                 return ERROR_NT(close_status);
3692         }
3693  
3694         outsize = set_message(inbuf,outbuf,1,0,True);
3695   
3696         SSVAL(outbuf,smb_vwv0,nwritten);
3697         END_PROFILE(SMBwriteclose);
3698         return(outsize);
3699 }
3700
3701 #undef DBGC_CLASS
3702 #define DBGC_CLASS DBGC_LOCKING
3703
3704 /****************************************************************************
3705  Reply to a lock.
3706 ****************************************************************************/
3707
3708 int reply_lock(connection_struct *conn,
3709                char *inbuf,char *outbuf, int length, int dum_buffsize)
3710 {
3711         int outsize = set_message(inbuf,outbuf,0,0,False);
3712         SMB_BIG_UINT count,offset;
3713         NTSTATUS status;
3714         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3715         struct byte_range_lock *br_lck = NULL;
3716
3717         START_PROFILE(SMBlock);
3718
3719         CHECK_FSP(fsp,conn);
3720
3721         release_level_2_oplocks_on_change(fsp);
3722
3723         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3724         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3725
3726         DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3727                  fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3728
3729         br_lck = do_lock(smbd_messaging_context(),
3730                         fsp,
3731                         (uint32)SVAL(inbuf,smb_pid),
3732                         count,
3733                         offset,
3734                         WRITE_LOCK,
3735                         WINDOWS_LOCK,
3736                         False, /* Non-blocking lock. */
3737                         &status,
3738                         NULL);
3739
3740         TALLOC_FREE(br_lck);
3741
3742         if (NT_STATUS_V(status)) {
3743                 END_PROFILE(SMBlock);
3744                 return ERROR_NT(status);
3745         }
3746
3747         END_PROFILE(SMBlock);
3748         return(outsize);
3749 }
3750
3751 /****************************************************************************
3752  Reply to a unlock.
3753 ****************************************************************************/
3754
3755 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
3756                  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         START_PROFILE(SMBunlock);
3763
3764         CHECK_FSP(fsp,conn);
3765         
3766         count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3767         offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3768         
3769         status = do_unlock(smbd_messaging_context(),
3770                         fsp,
3771                         (uint32)SVAL(inbuf,smb_pid),
3772                         count,
3773                         offset,
3774                         WINDOWS_LOCK);
3775
3776         if (NT_STATUS_V(status)) {
3777                 END_PROFILE(SMBunlock);
3778                 return ERROR_NT(status);
3779         }
3780
3781         DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3782                     fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3783         
3784         END_PROFILE(SMBunlock);
3785         return(outsize);
3786 }
3787
3788 #undef DBGC_CLASS
3789 #define DBGC_CLASS DBGC_ALL
3790
3791 /****************************************************************************
3792  Reply to a tdis.
3793  conn POINTER CAN BE NULL HERE !
3794 ****************************************************************************/
3795
3796 void reply_tdis(connection_struct *conn, struct smb_request *req)
3797 {
3798         START_PROFILE(SMBtdis);
3799
3800         if (!conn) {
3801                 DEBUG(4,("Invalid connection in tdis\n"));
3802                 reply_doserror(req, ERRSRV, ERRinvnid);
3803                 END_PROFILE(SMBtdis);
3804                 return;
3805         }
3806
3807         conn->used = False;
3808
3809         close_cnum(conn,req->vuid);
3810
3811         reply_outbuf(req, 0, 0);
3812         END_PROFILE(SMBtdis);
3813         return;
3814 }
3815
3816 /****************************************************************************
3817  Reply to a echo.
3818  conn POINTER CAN BE NULL HERE !
3819 ****************************************************************************/
3820
3821 void reply_echo(connection_struct *conn, struct smb_request *req)
3822 {
3823         int smb_reverb;
3824         int seq_num;
3825         unsigned int data_len = smb_buflen(req->inbuf);
3826
3827         START_PROFILE(SMBecho);
3828
3829         if (req->wct < 1) {
3830                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3831                 END_PROFILE(SMBecho);
3832                 return;
3833         }
3834
3835         if (data_len > BUFFER_SIZE) {
3836                 DEBUG(0,("reply_echo: data_len too large.\n"));
3837                 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
3838                 END_PROFILE(SMBecho);
3839                 return;
3840         }
3841
3842         smb_reverb = SVAL(req->inbuf,smb_vwv0);
3843
3844         reply_outbuf(req, 1, data_len);
3845
3846         /* copy any incoming data back out */
3847         if (data_len > 0) {
3848                 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
3849         }
3850
3851         if (smb_reverb > 100) {
3852                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3853                 smb_reverb = 100;
3854         }
3855
3856         for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3857                 SSVAL(req->outbuf,smb_vwv0,seq_num);
3858
3859                 show_msg((char *)req->outbuf);
3860                 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
3861                         exit_server_cleanly("reply_echo: send_smb failed.");
3862         }
3863
3864         DEBUG(3,("echo %d times\n", smb_reverb));
3865
3866         TALLOC_FREE(req->outbuf);
3867
3868         smb_echo_count++;
3869
3870         END_PROFILE(SMBecho);
3871         return;
3872 }
3873
3874 /****************************************************************************
3875  Reply to a printopen.
3876 ****************************************************************************/
3877
3878 int reply_printopen(connection_struct *conn, 
3879                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3880 {
3881         int outsize = 0;
3882         files_struct *fsp;
3883         NTSTATUS status;
3884         
3885         START_PROFILE(SMBsplopen);
3886         
3887         if (!CAN_PRINT(conn)) {
3888                 END_PROFILE(SMBsplopen);
3889                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3890         }
3891
3892         /* Open for exclusive use, write only. */
3893         status = print_fsp_open(conn, NULL, &fsp);
3894
3895         if (!NT_STATUS_IS_OK(status)) {
3896                 END_PROFILE(SMBsplopen);
3897                 return(ERROR_NT(status));
3898         }
3899
3900         outsize = set_message(inbuf,outbuf,1,0,True);
3901         SSVAL(outbuf,smb_vwv0,fsp->fnum);
3902   
3903         DEBUG(3,("openprint fd=%d fnum=%d\n",
3904                  fsp->fh->fd, fsp->fnum));
3905
3906         END_PROFILE(SMBsplopen);
3907         return(outsize);
3908 }
3909
3910 /****************************************************************************
3911  Reply to a printclose.
3912 ****************************************************************************/
3913
3914 int reply_printclose(connection_struct *conn,
3915                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3916 {
3917         int outsize = set_message(inbuf,outbuf,0,0,False);
3918         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3919         NTSTATUS status;
3920         START_PROFILE(SMBsplclose);
3921
3922         CHECK_FSP(fsp,conn);
3923
3924         if (!CAN_PRINT(conn)) {
3925                 END_PROFILE(SMBsplclose);
3926                 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3927         }
3928   
3929         DEBUG(3,("printclose fd=%d fnum=%d\n",
3930                  fsp->fh->fd,fsp->fnum));
3931   
3932         status = close_file(fsp,NORMAL_CLOSE);
3933
3934         if(!NT_STATUS_IS_OK(status)) {
3935                 END_PROFILE(SMBsplclose);
3936                 return ERROR_NT(status);
3937         }
3938
3939         END_PROFILE(SMBsplclose);
3940         return(outsize);
3941 }
3942
3943 /****************************************************************************
3944  Reply to a printqueue.
3945 ****************************************************************************/
3946
3947 int reply_printqueue(connection_struct *conn,
3948                      char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3949 {
3950         int outsize = set_message(inbuf,outbuf,2,3,True);
3951         int max_count = SVAL(inbuf,smb_vwv0);
3952         int start_index = SVAL(inbuf,smb_vwv1);
3953         START_PROFILE(SMBsplretq);
3954
3955         /* we used to allow the client to get the cnum wrong, but that
3956            is really quite gross and only worked when there was only
3957            one printer - I think we should now only accept it if they
3958            get it right (tridge) */
3959         if (!CAN_PRINT(conn)) {
3960                 END_PROFILE(SMBsplretq);
3961                 return ERROR_DOS(ERRDOS,ERRnoaccess);
3962         }
3963
3964         SSVAL(outbuf,smb_vwv0,0);
3965         SSVAL(outbuf,smb_vwv1,0);
3966         SCVAL(smb_buf(outbuf),0,1);
3967         SSVAL(smb_buf(outbuf),1,0);
3968   
3969         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3970                  start_index, max_count));
3971
3972         {
3973                 print_queue_struct *queue = NULL;
3974                 print_status_struct status;
3975                 char *p = smb_buf(outbuf) + 3;
3976                 int count = print_queue_status(SNUM(conn), &queue, &status);
3977                 int num_to_get = ABS(max_count);
3978                 int first = (max_count>0?start_index:start_index+max_count+1);
3979                 int i;
3980
3981                 if (first >= count)
3982                         num_to_get = 0;
3983                 else
3984                         num_to_get = MIN(num_to_get,count-first);
3985     
3986
3987                 for (i=first;i<first+num_to_get;i++) {
3988                         srv_put_dos_date2(p,0,queue[i].time);
3989                         SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3990                         SSVAL(p,5, queue[i].job);
3991                         SIVAL(p,7,queue[i].size);
3992                         SCVAL(p,11,0);
3993                         srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+12,
3994                                     queue[i].fs_user, 16, STR_ASCII);
3995                         p += 28;
3996                 }
3997
3998                 if (count > 0) {
3999                         outsize = set_message(inbuf,outbuf,2,28*count+3,False); 
4000                         SSVAL(outbuf,smb_vwv0,count);
4001                         SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
4002                         SCVAL(smb_buf(outbuf),0,1);
4003                         SSVAL(smb_buf(outbuf),1,28*count);
4004                 }
4005
4006                 SAFE_FREE(queue);
4007           
4008                 DEBUG(3,("%d entries returned in queue\n",count));
4009         }
4010   
4011         END_PROFILE(SMBsplretq);
4012         return(outsize);
4013 }
4014
4015 /****************************************************************************
4016  Reply to a printwrite.
4017 ****************************************************************************/
4018
4019 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4020 {
4021         int numtowrite;
4022         int outsize = set_message(inbuf,outbuf,0,0,False);
4023         char *data;
4024         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
4025
4026         START_PROFILE(SMBsplwr);
4027   
4028         if (!CAN_PRINT(conn)) {
4029                 END_PROFILE(SMBsplwr);
4030                 return ERROR_DOS(ERRDOS,ERRnoaccess);
4031         }
4032
4033         CHECK_FSP(fsp,conn);
4034         if (!CHECK_WRITE(fsp)) {
4035                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
4036         }
4037
4038         numtowrite = SVAL(smb_buf(inbuf),1);
4039         data = smb_buf(inbuf) + 3;
4040   
4041         if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
4042                 END_PROFILE(SMBsplwr);
4043                 return(UNIXERROR(ERRHRD,ERRdiskfull));
4044         }
4045
4046         DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4047   
4048         END_PROFILE(SMBsplwr);
4049         return(outsize);
4050 }
4051
4052 /****************************************************************************
4053  Reply to a mkdir.
4054 ****************************************************************************/
4055
4056 void reply_mkdir(connection_struct *conn, struct smb_request *req)
4057 {
4058         pstring directory;
4059         NTSTATUS status;
4060         SMB_STRUCT_STAT sbuf;
4061
4062         START_PROFILE(SMBmkdir);
4063  
4064         srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4065                         smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4066                         STR_TERMINATE, &status);
4067         if (!NT_STATUS_IS_OK(status)) {
4068                 reply_nterror(req, status);
4069                 END_PROFILE(SMBmkdir);
4070                 return;
4071         }
4072
4073         status = resolve_dfspath(conn,
4074                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4075                                  directory);
4076         if (!NT_STATUS_IS_OK(status)) {
4077                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4078                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4079                                         ERRSRV, ERRbadpath);
4080                         END_PROFILE(SMBmkdir);
4081                         return;
4082                 }
4083                 reply_nterror(req, status);
4084                 END_PROFILE(SMBmkdir);
4085                 return;
4086         }
4087
4088         status = unix_convert(conn, directory, False, NULL, &sbuf);
4089         if (!NT_STATUS_IS_OK(status)) {
4090                 reply_nterror(req, status);
4091                 END_PROFILE(SMBmkdir);
4092                 return;
4093         }
4094
4095         status = check_name(conn, directory);
4096         if (!NT_STATUS_IS_OK(status)) {
4097                 reply_nterror(req, status);
4098                 END_PROFILE(SMBmkdir);
4099                 return;
4100         }
4101   
4102         status = create_directory(conn, directory);
4103
4104         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4105
4106         if (!NT_STATUS_IS_OK(status)) {
4107
4108                 if (!use_nt_status()
4109                     && NT_STATUS_EQUAL(status,
4110                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
4111                         /*
4112                          * Yes, in the DOS error code case we get a
4113                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4114                          * samba4 torture test.
4115                          */
4116                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4117                 }
4118
4119                 reply_nterror(req, status);
4120                 END_PROFILE(SMBmkdir);
4121                 return;
4122         }
4123
4124         reply_outbuf(req, 0, 0);
4125
4126         DEBUG( 3, ( "mkdir %s\n", directory ) );
4127
4128         END_PROFILE(SMBmkdir);
4129         return;
4130 }
4131
4132 /****************************************************************************
4133  Static function used by reply_rmdir to delete an entire directory
4134  tree recursively. Return True on ok, False on fail.
4135 ****************************************************************************/
4136
4137 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
4138 {
4139         const char *dname = NULL;
4140         BOOL ret = True;
4141         long offset = 0;
4142         struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4143
4144         if(dir_hnd == NULL)
4145                 return False;
4146
4147         while((dname = ReadDirName(dir_hnd, &offset))) {
4148                 pstring fullname;
4149                 SMB_STRUCT_STAT st;
4150
4151                 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4152                         continue;
4153
4154                 if (!is_visible_file(conn, directory, dname, &st, False))
4155                         continue;
4156
4157                 /* Construct the full name. */
4158                 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4159                         errno = ENOMEM;
4160                         ret = False;
4161                         break;
4162                 }
4163
4164                 pstrcpy(fullname, directory);
4165                 pstrcat(fullname, "/");
4166                 pstrcat(fullname, dname);
4167
4168                 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4169                         ret = False;
4170                         break;
4171                 }
4172
4173                 if(st.st_mode & S_IFDIR) {
4174                         if(!recursive_rmdir(conn, fullname)) {
4175                                 ret = False;
4176                                 break;
4177                         }
4178                         if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4179                                 ret = False;
4180                                 break;
4181                         }
4182                 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4183                         ret = False;
4184                         break;
4185                 }
4186         }
4187         CloseDir(dir_hnd);
4188         return ret;
4189 }
4190
4191 /****************************************************************************
4192  The internals of the rmdir code - called elsewhere.
4193 ****************************************************************************/
4194
4195 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4196 {
4197         int ret;
4198         SMB_STRUCT_STAT st;
4199
4200         /* Might be a symlink. */
4201         if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4202                 return map_nt_error_from_unix(errno);
4203         }
4204
4205         if (S_ISLNK(st.st_mode)) {
4206                 /* Is what it points to a directory ? */
4207                 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4208                         return map_nt_error_from_unix(errno);
4209                 }
4210                 if (!(S_ISDIR(st.st_mode))) {
4211                         return NT_STATUS_NOT_A_DIRECTORY;
4212                 }
4213                 ret = SMB_VFS_UNLINK(conn,directory);
4214         } else {
4215                 ret = SMB_VFS_RMDIR(conn,directory);
4216         }
4217         if (ret == 0) {
4218                 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4219                              FILE_NOTIFY_CHANGE_DIR_NAME,
4220                              directory);
4221                 return NT_STATUS_OK;
4222         }
4223
4224         if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4225                 /* 
4226                  * Check to see if the only thing in this directory are
4227                  * vetoed files/directories. If so then delete them and
4228                  * retry. If we fail to delete any of them (and we *don't*
4229                  * do a recursive delete) then fail the rmdir.
4230                  */
4231                 const char *dname;
4232                 long dirpos = 0;
4233                 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4234
4235                 if(dir_hnd == NULL) {
4236                         errno = ENOTEMPTY;
4237                         goto err;
4238                 }
4239
4240                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4241                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4242                                 continue;
4243                         if (!is_visible_file(conn, directory, dname, &st, False))
4244                                 continue;
4245                         if(!IS_VETO_PATH(conn, dname)) {
4246                                 CloseDir(dir_hnd);
4247                                 errno = ENOTEMPTY;
4248                                 goto err;
4249                         }
4250                 }
4251
4252                 /* We only have veto files/directories. Recursive delete. */
4253
4254                 RewindDir(dir_hnd,&dirpos);
4255                 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4256                         pstring fullname;
4257
4258                         if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4259                                 continue;
4260                         if (!is_visible_file(conn, directory, dname, &st, False))
4261                                 continue;
4262
4263                         /* Construct the full name. */
4264                         if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4265                                 errno = ENOMEM;
4266                                 break;
4267                         }
4268
4269                         pstrcpy(fullname, directory);
4270                         pstrcat(fullname, "/");
4271                         pstrcat(fullname, dname);
4272                    
4273                         if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4274                                 break;
4275                         if(st.st_mode & S_IFDIR) {
4276                                 if(lp_recursive_veto_delete(SNUM(conn))) {
4277                                         if(!recursive_rmdir(conn, fullname))
4278                                                 break;
4279                                 }
4280                                 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4281                                         break;
4282                         } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4283                                 break;
4284                 }
4285                 CloseDir(dir_hnd);
4286                 /* Retry the rmdir */
4287                 ret = SMB_VFS_RMDIR(conn,directory);
4288         }
4289
4290   err:
4291
4292         if (ret != 0) {
4293                 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4294                          "%s\n", directory,strerror(errno)));
4295                 return map_nt_error_from_unix(errno);
4296         }
4297
4298         notify_fname(conn, NOTIFY_ACTION_REMOVED,
4299                      FILE_NOTIFY_CHANGE_DIR_NAME,
4300                      directory);
4301
4302         return NT_STATUS_OK;
4303 }
4304
4305 /****************************************************************************
4306  Reply to a rmdir.
4307 ****************************************************************************/
4308
4309 void reply_rmdir(connection_struct *conn, struct smb_request *req)
4310 {
4311         pstring directory;
4312         SMB_STRUCT_STAT sbuf;
4313         NTSTATUS status;
4314         START_PROFILE(SMBrmdir);
4315
4316         srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4317                         smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4318                         STR_TERMINATE, &status);
4319         if (!NT_STATUS_IS_OK(status)) {
4320                 reply_nterror(req, status);
4321                 END_PROFILE(SMBrmdir);
4322                 return;
4323         }
4324
4325         status = resolve_dfspath(conn,
4326                                  req->flags2 & FLAGS2_DFS_PATHNAMES,
4327                                  directory);
4328         if (!NT_STATUS_IS_OK(status)) {
4329                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4330                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4331                                         ERRSRV, ERRbadpath);
4332                         END_PROFILE(SMBrmdir);
4333                         return;
4334                 }
4335                 reply_nterror(req, status);
4336                 END_PROFILE(SMBrmdir);
4337                 return;
4338         }
4339
4340         status = unix_convert(conn, directory, False, NULL, &sbuf);
4341         if (!NT_STATUS_IS_OK(status)) {
4342                 reply_nterror(req, status);
4343                 END_PROFILE(SMBrmdir);
4344                 return;
4345         }
4346   
4347         status = check_name(conn, directory);
4348         if (!NT_STATUS_IS_OK(status)) {
4349                 reply_nterror(req, status);
4350                 END_PROFILE(SMBrmdir);
4351                 return;
4352         }
4353
4354         dptr_closepath(directory, req->smbpid);
4355         status = rmdir_internals(conn, directory);
4356         if (!NT_STATUS_IS_OK(status)) {
4357                 reply_nterror(req, status);
4358                 END_PROFILE(SMBrmdir);
4359                 return;
4360         }
4361  
4362         reply_outbuf(req, 0, 0);
4363   
4364         DEBUG( 3, ( "rmdir %s\n", directory ) );
4365   
4366         END_PROFILE(SMBrmdir);
4367         return;
4368 }
4369
4370 /*******************************************************************
4371  Resolve wildcards in a filename rename.
4372  Note that name is in UNIX charset and thus potentially can be more
4373  than fstring buffer (255 bytes) especially in default UTF-8 case.
4374  Therefore, we use pstring inside and all calls should ensure that
4375  name2 is at least pstring-long (they do already)
4376 ********************************************************************/
4377
4378 static BOOL resolve_wildcards(const char *name1, char *name2)
4379 {
4380         pstring root1,root2;
4381         pstring ext1,ext2;
4382         char *p,*p2, *pname1, *pname2;
4383         int available_space, actual_space;
4384         
4385         pname1 = strrchr_m(name1,'/');
4386         pname2 = strrchr_m(name2,'/');
4387
4388         if (!pname1 || !pname2)
4389                 return(False);
4390   
4391         pstrcpy(root1,pname1);
4392         pstrcpy(root2,pname2);
4393         p = strrchr_m(root1,'.');
4394         if (p) {
4395                 *p = 0;
4396                 pstrcpy(ext1,p+1);
4397         } else {
4398                 pstrcpy(ext1,"");    
4399         }
4400         p = strrchr_m(root2,'.');
4401         if (p) {
4402                 *p = 0;
4403                 pstrcpy(ext2,p+1);
4404         } else {
4405                 pstrcpy(ext2,"");    
4406         }
4407
4408         p = root1;
4409         p2 = root2;
4410         while (*p2) {
4411                 if (*p2 == '?') {
4412                         *p2 = *p;
4413                         p2++;
4414                 } else if (*p2 == '*') {
4415                         pstrcpy(p2, p);
4416                         break;
4417                 } else {
4418                         p2++;
4419                 }
4420                 if (*p)
4421                         p++;
4422         }
4423
4424         p = ext1;
4425         p2 = ext2;
4426         while (*p2) {
4427                 if (*p2 == '?') {
4428                         *p2 = *p;
4429                         p2++;
4430                 } else if (*p2 == '*') {
4431                         pstrcpy(p2, p);
4432                         break;
4433                 } else {
4434                         p2++;
4435                 }
4436                 if (*p)
4437                         p++;
4438         }
4439
4440         available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4441         
4442         if (ext2[0]) {
4443                 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4444                 if (actual_space >= available_space - 1) {
4445                         DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4446                                 actual_space - available_space));
4447                 }
4448         } else {
4449                 pstrcpy_base(pname2, root2, name2);
4450         }
4451
4452         return(True);
4453 }
4454
4455 /****************************************************************************
4456  Ensure open files have their names updated. Updated to notify other smbd's
4457  asynchronously.
4458 ****************************************************************************/
4459
4460 static void rename_open_files(connection_struct *conn,
4461                               struct share_mode_lock *lck,
4462                               const char *newname)
4463 {
4464         files_struct *fsp;
4465         BOOL did_rename = False;
4466
4467         for(fsp = file_find_di_first(lck->id); fsp;
4468             fsp = file_find_di_next(fsp)) {
4469                 /* fsp_name is a relative path under the fsp. To change this for other
4470                    sharepaths we need to manipulate relative paths. */
4471                 /* TODO - create the absolute path and manipulate the newname
4472                    relative to the sharepath. */
4473                 if (fsp->conn != conn) {
4474                         continue;
4475                 }
4476                 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4477                           fsp->fnum, file_id_static_string(&fsp->file_id),
4478                         fsp->fsp_name, newname ));
4479                 string_set(&fsp->fsp_name, newname);
4480                 did_rename = True;
4481         }
4482
4483         if (!did_rename) {
4484                 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4485                           file_id_static_string(&lck->id), newname ));
4486         }
4487
4488         /* Send messages to all smbd's (not ourself) that the name has changed. */
4489         rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4490                               newname);
4491 }
4492
4493 /****************************************************************************
4494  We need to check if the source path is a parent directory of the destination
4495  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4496  refuse the rename with a sharing violation. Under UNIX the above call can
4497  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4498  probably need to check that the client is a Windows one before disallowing
4499  this as a UNIX client (one with UNIX extensions) can know the source is a
4500  symlink and make this decision intelligently. Found by an excellent bug
4501  report from <AndyLiebman@aol.com>.
4502 ****************************************************************************/
4503
4504 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4505 {
4506         const char *psrc = src;
4507         const char *pdst = dest;
4508         size_t slen;
4509
4510         if (psrc[0] == '.' && psrc[1] == '/') {
4511                 psrc += 2;
4512         }
4513         if (pdst[0] == '.' && pdst[1] == '/') {
4514                 pdst += 2;
4515         }
4516         if ((slen = strlen(psrc)) > strlen(pdst)) {
4517                 return False;
4518         }
4519         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4520 }
4521
4522 /*
4523  * Do the notify calls from a rename
4524  */
4525
4526 static void notify_rename(connection_struct *conn, BOOL is_dir,
4527                           const char *oldpath, const char *newpath)
4528 {
4529         char *olddir, *newdir;
4530         const char *oldname, *newname;
4531         uint32 mask;
4532
4533         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4534                 : FILE_NOTIFY_CHANGE_FILE_NAME;
4535
4536         if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4537             || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4538                 TALLOC_FREE(olddir);
4539                 return;
4540         }
4541
4542         if (strcmp(olddir, newdir) == 0) {
4543                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4544                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4545         }
4546         else {
4547                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4548                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4549         }
4550         TALLOC_FREE(olddir);
4551         TALLOC_FREE(newdir);
4552
4553         /* this is a strange one. w2k3 gives an additional event for
4554            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4555            files, but not directories */
4556         if (!is_dir) {
4557                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4558                              FILE_NOTIFY_CHANGE_ATTRIBUTES
4559                              |FILE_NOTIFY_CHANGE_CREATION,
4560                              newpath);
4561         }
4562 }
4563
4564 /****************************************************************************
4565  Rename an open file - given an fsp.
4566 ****************************************************************************/
4567
4568 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4569 {
4570         SMB_STRUCT_STAT sbuf, sbuf1;
4571         pstring newname_last_component;
4572         NTSTATUS status = NT_STATUS_OK;
4573         struct share_mode_lock *lck = NULL;
4574         BOOL dst_exists;
4575
4576         ZERO_STRUCT(sbuf);
4577
4578         status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4579
4580         /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4581
4582         if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4583                 return status;
4584         }
4585
4586         status = check_name(conn, newname);
4587         if (!NT_STATUS_IS_OK(status)) {
4588                 return status;
4589         }
4590   
4591         /* Ensure newname contains a '/' */
4592         if(strrchr_m(newname,'/') == 0) {
4593                 pstring tmpstr;
4594                 
4595                 pstrcpy(tmpstr, "./");
4596                 pstrcat(tmpstr, newname);
4597                 pstrcpy(newname, tmpstr);
4598         }
4599
4600         /*
4601          * Check for special case with case preserving and not
4602          * case sensitive. If the old last component differs from the original
4603          * last component only by case, then we should allow
4604          * the rename (user is trying to change the case of the
4605          * filename).
4606          */
4607
4608         if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4609                         strequal(newname, fsp->fsp_name)) {
4610                 char *p;
4611                 pstring newname_modified_last_component;
4612
4613                 /*
4614                  * Get the last component of the modified name.
4615                  * Note that we guarantee that newname contains a '/'
4616                  * character above.
4617                  */
4618                 p = strrchr_m(newname,'/');
4619                 pstrcpy(newname_modified_last_component,p+1);
4620                         
4621                 if(strcsequal(newname_modified_last_component, 
4622                               newname_last_component) == False) {
4623                         /*
4624                          * Replace the modified last component with
4625                          * the original.
4626                          */
4627                         pstrcpy(p+1, newname_last_component);
4628                 }
4629         }
4630
4631         /*
4632          * If the src and dest names are identical - including case,
4633          * don't do the rename, just return success.
4634          */
4635
4636         if (strcsequal(fsp->fsp_name, newname)) {
4637                 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4638                         newname));
4639                 return NT_STATUS_OK;
4640         }
4641
4642         /*
4643          * Have vfs_object_exist also fill sbuf1
4644          */
4645         dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4646
4647         if(!replace_if_exists && dst_exists) {
4648                 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4649                         fsp->fsp_name,newname));
4650                 return NT_STATUS_OBJECT_NAME_COLLISION;
4651         }
4652
4653         if (dst_exists) {
4654                 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
4655                 files_struct *dst_fsp = file_find_di_first(fileid);
4656                 if (dst_fsp) {
4657                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4658                         return NT_STATUS_ACCESS_DENIED;
4659                 }
4660         }
4661
4662         /* Ensure we have a valid stat struct for the source. */
4663         if (fsp->fh->fd != -1) {
4664                 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4665                         return map_nt_error_from_unix(errno);
4666                 }
4667         } else {
4668                 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4669                         return map_nt_error_from_unix(errno);
4670                 }
4671         }
4672
4673         status = can_rename(conn, fsp, attrs, &sbuf);
4674
4675         if (!NT_STATUS_IS_OK(status)) {
4676                 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4677                         nt_errstr(status), fsp->fsp_name,newname));
4678                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4679                         status = NT_STATUS_ACCESS_DENIED;
4680                 return status;
4681         }
4682
4683         if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4684                 return NT_STATUS_ACCESS_DENIED;
4685         }
4686
4687         lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4688
4689         /*
4690          * We have the file open ourselves, so not being able to get the
4691          * corresponding share mode lock is a fatal error.
4692          */
4693
4694         SMB_ASSERT(lck != NULL);
4695
4696         if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4697                 uint32 create_options = fsp->fh->private_options;
4698
4699                 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4700                         fsp->fsp_name,newname));
4701
4702                 rename_open_files(conn, lck, newname);
4703
4704                 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4705
4706                 /*
4707                  * A rename acts as a new file create w.r.t. allowing an initial delete
4708                  * on close, probably because in Windows there is a new handle to the
4709                  * new file. If initial delete on close was requested but not
4710                  * originally set, we need to set it here. This is probably not 100% correct,
4711                  * but will work for the CIFSFS client which in non-posix mode
4712                  * depends on these semantics. JRA.
4713                  */
4714
4715                 set_allow_initial_delete_on_close(lck, fsp, True);
4716
4717                 if (create_options & FILE_DELETE_ON_CLOSE) {
4718                         status = can_set_delete_on_close(fsp, True, 0);
4719
4720                         if (NT_STATUS_IS_OK(status)) {
4721                                 /* Note that here we set the *inital* delete on close flag,
4722                                  * not the regular one. The magic gets handled in close. */
4723                                 fsp->initial_delete_on_close = True;
4724                         }
4725                 }
4726                 TALLOC_FREE(lck);
4727                 return NT_STATUS_OK;    
4728         }
4729
4730         TALLOC_FREE(lck);
4731
4732         if (errno == ENOTDIR || errno == EISDIR) {
4733                 status = NT_STATUS_OBJECT_NAME_COLLISION;
4734         } else {
4735                 status = map_nt_error_from_unix(errno);
4736         }
4737                 
4738         DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4739                 nt_errstr(status), fsp->fsp_name,newname));
4740
4741         return status;
4742 }
4743
4744 /****************************************************************************
4745  The guts of the rename command, split out so it may be called by the NT SMB
4746  code. 
4747 ****************************************************************************/
4748
4749 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
4750                                 pstring name,
4751                                 pstring newname,
4752                                 uint32 attrs,
4753                                 BOOL replace_if_exists,
4754                                 BOOL src_has_wild,
4755                                 BOOL dest_has_wild)
4756 {
4757         pstring directory;
4758         pstring mask;
4759         pstring last_component_src;
4760         pstring last_component_dest;
4761         char *p;
4762         int count=0;
4763         NTSTATUS status = NT_STATUS_OK;
4764         SMB_STRUCT_STAT sbuf1, sbuf2;
4765         struct smb_Dir *dir_hnd = NULL;
4766         const char *dname;
4767         long offset = 0;
4768         pstring destname;
4769
4770         *directory = *mask = 0;
4771
4772         ZERO_STRUCT(sbuf1);
4773         ZERO_STRUCT(sbuf2);
4774
4775         status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4776         if (!NT_STATUS_IS_OK(status)) {
4777                 return status;
4778         }
4779
4780         status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4781         if (!NT_STATUS_IS_OK(status)) {
4782                 return status;
4783         }
4784
4785         /*
4786          * Split the old name into directory and last component
4787          * strings. Note that unix_convert may have stripped off a 
4788          * leading ./ from both name and newname if the rename is 
4789          * at the root of the share. We need to make sure either both
4790          * name and newname contain a / character or neither of them do
4791          * as this is checked in resolve_wildcards().
4792          */
4793
4794         p = strrchr_m(name,'/');
4795         if (!p) {
4796                 pstrcpy(directory,".");
4797                 pstrcpy(mask,name);
4798         } else {
4799                 *p = 0;
4800                 pstrcpy(directory,name);
4801                 pstrcpy(mask,p+1);
4802                 *p = '/'; /* Replace needed for exceptional test below. */
4803         }
4804
4805         /*
4806          * We should only check the mangled cache
4807          * here if unix_convert failed. This means
4808          * that the path in 'mask' doesn't exist
4809          * on the file system and so we need to look
4810          * for a possible mangle. This patch from
4811          * Tine Smukavec <valentin.smukavec@hermes.si>.
4812          */
4813
4814         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4815                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4816         }
4817
4818         if (!src_has_wild) {
4819                 files_struct *fsp;
4820
4821                 /*
4822                  * No wildcards - just process the one file.
4823                  */
4824                 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4825
4826                 /* Add a terminating '/' to the directory name. */
4827                 pstrcat(directory,"/");
4828                 pstrcat(directory,mask);
4829                 
4830                 /* Ensure newname contains a '/' also */
4831                 if(strrchr_m(newname,'/') == 0) {
4832                         pstring tmpstr;
4833                         
4834                         pstrcpy(tmpstr, "./");
4835                         pstrcat(tmpstr, newname);
4836                         pstrcpy(newname, tmpstr);
4837                 }
4838                 
4839                 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4840                           "case_preserve = %d, short case preserve = %d, "
4841                           "directory = %s, newname = %s, "
4842                           "last_component_dest = %s, is_8_3 = %d\n", 
4843                           conn->case_sensitive, conn->case_preserve,
4844                           conn->short_case_preserve, directory, 
4845                           newname, last_component_dest, is_short_name));
4846
4847                 /* The dest name still may have wildcards. */
4848                 if (dest_has_wild) {
4849                         if (!resolve_wildcards(directory,newname)) {
4850                                 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", 
4851                                           directory,newname));
4852                                 return NT_STATUS_NO_MEMORY;
4853                         }
4854                 }
4855                                 
4856                 ZERO_STRUCT(sbuf1);
4857                 SMB_VFS_STAT(conn, directory, &sbuf1);
4858
4859                 status = S_ISDIR(sbuf1.st_mode) ?
4860                         open_directory(conn, req, directory, &sbuf1,
4861                                        DELETE_ACCESS,
4862                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
4863                                        FILE_OPEN, 0, 0, NULL,
4864                                        &fsp)
4865                         : open_file_ntcreate(conn, req, directory, &sbuf1,
4866                                              DELETE_ACCESS,
4867                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
4868                                              FILE_OPEN, 0, 0, 0, NULL,
4869                                              &fsp);
4870
4871                 if (!NT_STATUS_IS_OK(status)) {
4872                         DEBUG(3, ("Could not open rename source %s: %s\n",
4873                                   directory, nt_errstr(status)));
4874                         return status;
4875                 }
4876
4877                 status = rename_internals_fsp(conn, fsp, newname, attrs,
4878                                               replace_if_exists);
4879
4880                 close_file(fsp, NORMAL_CLOSE);
4881
4882                 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4883                           nt_errstr(status), directory,newname));
4884
4885                 return status;
4886         }
4887
4888         /*
4889          * Wildcards - process each file that matches.
4890          */
4891         if (strequal(mask,"????????.???")) {
4892                 pstrcpy(mask,"*");
4893         }
4894                         
4895         status = check_name(conn, directory);
4896         if (!NT_STATUS_IS_OK(status)) {
4897                 return status;
4898         }
4899         
4900         dir_hnd = OpenDir(conn, directory, mask, attrs);
4901         if (dir_hnd == NULL) {
4902                 return map_nt_error_from_unix(errno);
4903         }
4904                 
4905         status = NT_STATUS_NO_SUCH_FILE;
4906         /*
4907          * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4908          * - gentest fix. JRA
4909          */
4910                         
4911         while ((dname = ReadDirName(dir_hnd, &offset))) {
4912                 files_struct *fsp;
4913                 pstring fname;
4914                 BOOL sysdir_entry = False;
4915
4916                 pstrcpy(fname,dname);
4917                                 
4918                 /* Quick check for "." and ".." */
4919                 if (fname[0] == '.') {
4920                         if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4921                                 if (attrs & aDIR) {
4922                                         sysdir_entry = True;
4923                                 } else {
4924                                         continue;
4925                                 }
4926                         }
4927                 }
4928
4929                 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4930                         continue;
4931                 }
4932
4933                 if(!mask_match(fname, mask, conn->case_sensitive)) {
4934                         continue;
4935                 }
4936                                 
4937                 if (sysdir_entry) {
4938                         status = NT_STATUS_OBJECT_NAME_INVALID;
4939                         break;
4940                 }
4941
4942                 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4943
4944                 pstrcpy(destname,newname);
4945                         
4946                 if (!resolve_wildcards(fname,destname)) {
4947                         DEBUG(6, ("resolve_wildcards %s %s failed\n", 
4948                                   fname, destname));
4949                         continue;
4950                 }
4951                                 
4952                 ZERO_STRUCT(sbuf1);
4953                 SMB_VFS_STAT(conn, fname, &sbuf1);
4954
4955                 status = S_ISDIR(sbuf1.st_mode) ?
4956                         open_directory(conn, req, fname, &sbuf1,
4957                                        DELETE_ACCESS,
4958                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
4959                                        FILE_OPEN, 0, 0, NULL,
4960                                        &fsp)
4961                         : open_file_ntcreate(conn, req, fname, &sbuf1,
4962                                              DELETE_ACCESS,
4963                                              FILE_SHARE_READ|FILE_SHARE_WRITE,
4964                                              FILE_OPEN, 0, 0, 0, NULL,
4965                                              &fsp);
4966
4967                 if (!NT_STATUS_IS_OK(status)) {
4968                         DEBUG(3,("rename_internals: open_file_ntcreate "
4969                                  "returned %s rename %s -> %s\n",
4970                                  nt_errstr(status), directory, newname));
4971                         break;
4972                 }
4973
4974                 status = rename_internals_fsp(conn, fsp, destname, attrs,
4975                                               replace_if_exists);
4976
4977                 close_file(fsp, NORMAL_CLOSE);
4978
4979                 if (!NT_STATUS_IS_OK(status)) {
4980                         DEBUG(3, ("rename_internals_fsp returned %s for "
4981                                   "rename %s -> %s\n", nt_errstr(status),
4982                                   directory, newname));
4983                         break;
4984                 }
4985
4986                 count++;
4987
4988                 DEBUG(3,("rename_internals: doing rename on %s -> "
4989                          "%s\n",fname,destname));
4990         }
4991         CloseDir(dir_hnd);
4992
4993         if (count == 0 && NT_STATUS_IS_OK(status)) {
4994                 status = map_nt_error_from_unix(errno);
4995         }
4996         
4997         return status;
4998 }
4999
5000 /****************************************************************************
5001  Reply to a mv.
5002 ****************************************************************************/
5003
5004 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, 
5005              int dum_buffsize)
5006 {
5007         int outsize = 0;
5008         pstring name;
5009         pstring newname;
5010         char *p;
5011         uint32 attrs = SVAL(inbuf,smb_vwv0);
5012         NTSTATUS status;
5013         BOOL src_has_wcard = False;
5014         BOOL dest_has_wcard = False;
5015         struct smb_request req;
5016
5017         START_PROFILE(SMBmv);
5018
5019         init_smb_request(&req, (uint8 *)inbuf);
5020
5021         p = smb_buf(inbuf) + 1;
5022         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5023                                    sizeof(name), 0, STR_TERMINATE, &status,
5024                                    &src_has_wcard);
5025         if (!NT_STATUS_IS_OK(status)) {
5026                 END_PROFILE(SMBmv);
5027                 return ERROR_NT(status);
5028         }
5029         p++;
5030         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5031                                    sizeof(newname), 0, STR_TERMINATE, &status,
5032                                    &dest_has_wcard);
5033         if (!NT_STATUS_IS_OK(status)) {
5034                 END_PROFILE(SMBmv);
5035                 return ERROR_NT(status);
5036         }
5037         
5038         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
5039         if (!NT_STATUS_IS_OK(status)) {
5040                 END_PROFILE(SMBmv);
5041                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5042                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5043                 }
5044                 return ERROR_NT(status);
5045         }
5046
5047         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
5048         if (!NT_STATUS_IS_OK(status)) {
5049                 END_PROFILE(SMBmv);
5050                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5051                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5052                 }
5053                 return ERROR_NT(status);
5054         }
5055         
5056         DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5057         
5058         status = rename_internals(conn, &req, name, newname, attrs, False,
5059                                   src_has_wcard, dest_has_wcard);
5060         if (!NT_STATUS_IS_OK(status)) {
5061                 END_PROFILE(SMBmv);
5062                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5063                         /* We have re-scheduled this call. */
5064                         return -1;
5065                 }
5066                 return ERROR_NT(status);
5067         }
5068
5069         outsize = set_message(inbuf,outbuf,0,0,False);
5070   
5071         END_PROFILE(SMBmv);
5072         return(outsize);
5073 }
5074
5075 /*******************************************************************
5076  Copy a file as part of a reply_copy.
5077 ******************************************************************/
5078
5079 /*
5080  * TODO: check error codes on all callers
5081  */
5082
5083 NTSTATUS copy_file(connection_struct *conn,
5084                         char *src,
5085                         char *dest1,
5086                         int ofun,
5087                         int count,
5088                         BOOL target_is_directory)
5089 {
5090         SMB_STRUCT_STAT src_sbuf, sbuf2;
5091         SMB_OFF_T ret=-1;
5092         files_struct *fsp1,*fsp2;
5093         pstring dest;
5094         uint32 dosattrs;
5095         uint32 new_create_disposition;
5096         NTSTATUS status;
5097  
5098         pstrcpy(dest,dest1);
5099         if (target_is_directory) {
5100                 char *p = strrchr_m(src,'/');
5101                 if (p) {
5102                         p++;
5103                 } else {
5104                         p = src;
5105                 }
5106                 pstrcat(dest,"/");
5107                 pstrcat(dest,p);
5108         }
5109
5110         if (!vfs_file_exist(conn,src,&src_sbuf)) {
5111                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5112         }
5113
5114         if (!target_is_directory && count) {
5115                 new_create_disposition = FILE_OPEN;
5116         } else {
5117                 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5118                                 NULL, NULL, &new_create_disposition, NULL)) {
5119                         return NT_STATUS_INVALID_PARAMETER;
5120                 }
5121         }
5122
5123         status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5124                         FILE_GENERIC_READ,
5125                         FILE_SHARE_READ|FILE_SHARE_WRITE,
5126                         FILE_OPEN,
5127                         0,
5128                         FILE_ATTRIBUTE_NORMAL,
5129                         INTERNAL_OPEN_ONLY,
5130                         NULL, &fsp1);
5131
5132         if (!NT_STATUS_IS_OK(status)) {
5133                 return status;
5134         }
5135
5136         dosattrs = dos_mode(conn, src, &src_sbuf);
5137         if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
5138                 ZERO_STRUCTP(&sbuf2);
5139         }
5140
5141         status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
5142                         FILE_GENERIC_WRITE,
5143                         FILE_SHARE_READ|FILE_SHARE_WRITE,
5144                         new_create_disposition,
5145                         0,
5146                         dosattrs,
5147                         INTERNAL_OPEN_ONLY,
5148                         NULL, &fsp2);
5149
5150         if (!NT_STATUS_IS_OK(status)) {
5151                 close_file(fsp1,ERROR_CLOSE);
5152                 return status;
5153         }
5154
5155         if ((ofun&3) == 1) {
5156                 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
5157                         DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
5158                         /*
5159                          * Stop the copy from occurring.
5160                          */
5161                         ret = -1;
5162                         src_sbuf.st_size = 0;
5163                 }
5164         }
5165   
5166         if (src_sbuf.st_size) {
5167                 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
5168         }
5169
5170         close_file(fsp1,NORMAL_CLOSE);
5171
5172         /* Ensure the modtime is set correctly on the destination file. */
5173         fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
5174
5175         /*
5176          * As we are opening fsp1 read-only we only expect
5177          * an error on close on fsp2 if we are out of space.
5178          * Thus we don't look at the error return from the
5179          * close of fsp1.
5180          */
5181         status = close_file(fsp2,NORMAL_CLOSE);
5182
5183         if (!NT_STATUS_IS_OK(status)) {
5184                 return status;
5185         }
5186
5187         if (ret != (SMB_OFF_T)src_sbuf.st_size) {
5188                 return NT_STATUS_DISK_FULL;
5189         }
5190
5191         return NT_STATUS_OK;
5192 }
5193
5194 /****************************************************************************
5195  Reply to a file copy.
5196 ****************************************************************************/
5197
5198 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5199 {
5200         int outsize = 0;
5201         pstring name;
5202         pstring directory;
5203         pstring mask,newname;
5204         char *p;
5205         int count=0;
5206         int error = ERRnoaccess;
5207         int err = 0;
5208         int tid2 = SVAL(inbuf,smb_vwv0);
5209         int ofun = SVAL(inbuf,smb_vwv1);
5210         int flags = SVAL(inbuf,smb_vwv2);
5211         BOOL target_is_directory=False;
5212         BOOL source_has_wild = False;
5213         BOOL dest_has_wild = False;
5214         SMB_STRUCT_STAT sbuf1, sbuf2;
5215         NTSTATUS status;
5216         START_PROFILE(SMBcopy);
5217
5218         *directory = *mask = 0;
5219
5220         p = smb_buf(inbuf);
5221         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5222                                    sizeof(name), 0, STR_TERMINATE, &status,
5223                                    &source_has_wild);
5224         if (!NT_STATUS_IS_OK(status)) {
5225                 END_PROFILE(SMBcopy);
5226                 return ERROR_NT(status);
5227         }
5228         p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5229                                    sizeof(newname), 0, STR_TERMINATE, &status,
5230                                    &dest_has_wild);
5231         if (!NT_STATUS_IS_OK(status)) {
5232                 END_PROFILE(SMBcopy);
5233                 return ERROR_NT(status);
5234         }
5235    
5236         DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5237    
5238         if (tid2 != conn->cnum) {
5239                 /* can't currently handle inter share copies XXXX */
5240                 DEBUG(3,("Rejecting inter-share copy\n"));
5241                 END_PROFILE(SMBcopy);
5242                 return ERROR_DOS(ERRSRV,ERRinvdevice);
5243         }
5244
5245         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5246         if (!NT_STATUS_IS_OK(status)) {
5247                 END_PROFILE(SMBcopy);
5248                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5249                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5250                 }
5251                 return ERROR_NT(status);
5252         }
5253
5254         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5255         if (!NT_STATUS_IS_OK(status)) {
5256                 END_PROFILE(SMBcopy);
5257                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5258                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5259                 }
5260                 return ERROR_NT(status);
5261         }
5262
5263         status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5264         if (!NT_STATUS_IS_OK(status)) {
5265                 END_PROFILE(SMBcopy);
5266                 return ERROR_NT(status);
5267         }
5268
5269         status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5270         if (!NT_STATUS_IS_OK(status)) {
5271                 END_PROFILE(SMBcopy);
5272                 return ERROR_NT(status);
5273         }
5274
5275         target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5276
5277         if ((flags&1) && target_is_directory) {
5278                 END_PROFILE(SMBcopy);
5279                 return ERROR_DOS(ERRDOS,ERRbadfile);
5280         }
5281
5282         if ((flags&2) && !target_is_directory) {
5283                 END_PROFILE(SMBcopy);
5284                 return ERROR_DOS(ERRDOS,ERRbadpath);
5285         }
5286
5287         if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5288                 /* wants a tree copy! XXXX */
5289                 DEBUG(3,("Rejecting tree copy\n"));
5290                 END_PROFILE(SMBcopy);
5291                 return ERROR_DOS(ERRSRV,ERRerror);
5292         }
5293
5294         p = strrchr_m(name,'/');
5295         if (!p) {
5296                 pstrcpy(directory,"./");
5297                 pstrcpy(mask,name);
5298         } else {
5299                 *p = 0;
5300                 pstrcpy(directory,name);
5301                 pstrcpy(mask,p+1);
5302         }
5303
5304         /*
5305          * We should only check the mangled cache
5306          * here if unix_convert failed. This means
5307          * that the path in 'mask' doesn't exist
5308          * on the file system and so we need to look
5309          * for a possible mangle. This patch from
5310          * Tine Smukavec <valentin.smukavec@hermes.si>.
5311          */
5312
5313         if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5314                 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5315         }
5316
5317         if (!source_has_wild) {
5318                 pstrcat(directory,"/");
5319                 pstrcat(directory,mask);
5320                 if (dest_has_wild) {
5321                         if (!resolve_wildcards(directory,newname)) {
5322                                 END_PROFILE(SMBcopy);
5323                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5324                         }
5325                 }
5326
5327                 status = check_name(conn, directory);
5328                 if (!NT_STATUS_IS_OK(status)) {
5329                         return ERROR_NT(status);
5330                 }
5331                 
5332                 status = check_name(conn, newname);
5333                 if (!NT_STATUS_IS_OK(status)) {
5334                         return ERROR_NT(status);
5335                 }
5336                 
5337                 status = copy_file(conn,directory,newname,ofun,
5338                                         count,target_is_directory);
5339
5340                 if(!NT_STATUS_IS_OK(status)) {
5341                         END_PROFILE(SMBcopy);
5342                         return ERROR_NT(status);
5343                 } else {
5344                         count++;
5345                 }
5346         } else {
5347                 struct smb_Dir *dir_hnd = NULL;
5348                 const char *dname;
5349                 long offset = 0;
5350                 pstring destname;
5351
5352                 if (strequal(mask,"????????.???"))
5353                         pstrcpy(mask,"*");
5354
5355                 status = check_name(conn, directory);
5356                 if (!NT_STATUS_IS_OK(status)) {
5357                         return ERROR_NT(status);
5358                 }
5359                 
5360                 dir_hnd = OpenDir(conn, directory, mask, 0);
5361                 if (dir_hnd == NULL) {
5362                         status = map_nt_error_from_unix(errno);
5363                         return ERROR_NT(status);
5364                 }
5365
5366                 error = ERRbadfile;
5367
5368                 while ((dname = ReadDirName(dir_hnd, &offset))) {
5369                         pstring fname;
5370                         pstrcpy(fname,dname);
5371     
5372                         if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5373                                 continue;
5374                         }
5375
5376                         if(!mask_match(fname, mask, conn->case_sensitive)) {
5377                                 continue;
5378                         }
5379
5380                         error = ERRnoaccess;
5381                         slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5382                         pstrcpy(destname,newname);
5383                         if (!resolve_wildcards(fname,destname)) {
5384                                 continue;
5385                         }
5386
5387                         status = check_name(conn, fname);
5388                         if (!NT_STATUS_IS_OK(status)) {
5389                                 return ERROR_NT(status);
5390                         }
5391                 
5392                         status = check_name(conn, destname);
5393                         if (!NT_STATUS_IS_OK(status)) {
5394                                 return ERROR_NT(status);
5395                         }
5396                 
5397                         DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5398
5399                         status = copy_file(conn,fname,destname,ofun,
5400                                         count,target_is_directory);
5401                         if (NT_STATUS_IS_OK(status)) {
5402                                 count++;
5403                         }
5404                 }
5405                 CloseDir(dir_hnd);
5406         }
5407   
5408         if (count == 0) {
5409                 if(err) {
5410                         /* Error on close... */
5411                         errno = err;
5412                         END_PROFILE(SMBcopy);
5413                         return(UNIXERROR(ERRHRD,ERRgeneral));
5414                 }
5415
5416                 END_PROFILE(SMBcopy);
5417                 return ERROR_DOS(ERRDOS,error);
5418         }
5419   
5420         outsize = set_message(inbuf,outbuf,1,0,True);
5421         SSVAL(outbuf,smb_vwv0,count);
5422
5423         END_PROFILE(SMBcopy);
5424         return(outsize);
5425 }
5426
5427 /****************************************************************************
5428  Reply to a setdir.
5429 ****************************************************************************/
5430
5431 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5432 {
5433         int snum;
5434         int outsize = 0;
5435         pstring newdir;
5436         NTSTATUS status;
5437
5438         START_PROFILE(pathworks_setdir);
5439   
5440         snum = SNUM(conn);
5441         if (!CAN_SETDIR(snum)) {
5442                 END_PROFILE(pathworks_setdir);
5443                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5444         }
5445
5446         srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
5447                         smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
5448                         &status);
5449         if (!NT_STATUS_IS_OK(status)) {
5450                 END_PROFILE(pathworks_setdir);
5451                 return ERROR_NT(status);
5452         }
5453   
5454         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5455         if (!NT_STATUS_IS_OK(status)) {
5456                 END_PROFILE(pathworks_setdir);
5457                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5458                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5459                 }
5460                 return ERROR_NT(status);
5461         }
5462
5463         if (strlen(newdir) != 0) {
5464                 if (!vfs_directory_exist(conn,newdir,NULL)) {
5465                         END_PROFILE(pathworks_setdir);
5466                         return ERROR_DOS(ERRDOS,ERRbadpath);
5467                 }
5468                 set_conn_connectpath(conn,newdir);
5469         }
5470   
5471         outsize = set_message(inbuf,outbuf,0,0,False);
5472         SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5473   
5474         DEBUG(3,("setdir %s\n", newdir));
5475
5476         END_PROFILE(pathworks_setdir);
5477         return(outsize);
5478 }
5479
5480 #undef DBGC_CLASS
5481 #define DBGC_CLASS DBGC_LOCKING
5482
5483 /****************************************************************************
5484  Get a lock pid, dealing with large count requests.
5485 ****************************************************************************/
5486
5487 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5488 {
5489         if(!large_file_format)
5490                 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5491         else
5492                 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5493 }
5494
5495 /****************************************************************************
5496  Get a lock count, dealing with large count requests.
5497 ****************************************************************************/
5498
5499 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5500 {
5501         SMB_BIG_UINT count = 0;
5502
5503         if(!large_file_format) {
5504                 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5505         } else {
5506
5507 #if defined(HAVE_LONGLONG)
5508                 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5509                         ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5510 #else /* HAVE_LONGLONG */
5511
5512                 /*
5513                  * NT4.x seems to be broken in that it sends large file (64 bit)
5514                  * lockingX calls even if the CAP_LARGE_FILES was *not*
5515                  * negotiated. For boxes without large unsigned ints truncate the
5516                  * lock count by dropping the top 32 bits.
5517                  */
5518
5519                 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5520                         DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5521                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5522                                 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5523                                 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5524                 }
5525
5526                 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5527 #endif /* HAVE_LONGLONG */
5528         }
5529
5530         return count;
5531 }
5532
5533 #if !defined(HAVE_LONGLONG)
5534 /****************************************************************************
5535  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5536 ****************************************************************************/
5537
5538 static uint32 map_lock_offset(uint32 high, uint32 low)
5539 {
5540         unsigned int i;
5541         uint32 mask = 0;
5542         uint32 highcopy = high;
5543  
5544         /*
5545          * Try and find out how many significant bits there are in high.
5546          */
5547  
5548         for(i = 0; highcopy; i++)
5549                 highcopy >>= 1;
5550  
5551         /*
5552          * We use 31 bits not 32 here as POSIX
5553          * lock offsets may not be negative.
5554          */
5555  
5556         mask = (~0) << (31 - i);
5557  
5558         if(low & mask)
5559                 return 0; /* Fail. */
5560  
5561         high <<= (31 - i);
5562  
5563         return (high|low);
5564 }
5565 #endif /* !defined(HAVE_LONGLONG) */
5566
5567 /****************************************************************************
5568  Get a lock offset, dealing with large offset requests.
5569 ****************************************************************************/
5570
5571 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5572 {
5573         SMB_BIG_UINT offset = 0;
5574
5575         *err = False;
5576
5577         if(!large_file_format) {
5578                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5579         } else {
5580
5581 #if defined(HAVE_LONGLONG)
5582                 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5583                                 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5584 #else /* HAVE_LONGLONG */
5585
5586                 /*
5587                  * NT4.x seems to be broken in that it sends large file (64 bit)
5588                  * lockingX calls even if the CAP_LARGE_FILES was *not*
5589                  * negotiated. For boxes without large unsigned ints mangle the
5590                  * lock offset by mapping the top 32 bits onto the lower 32.
5591                  */
5592       
5593                 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5594                         uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5595                         uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5596                         uint32 new_low = 0;
5597
5598                         if((new_low = map_lock_offset(high, low)) == 0) {
5599                                 *err = True;
5600                                 return (SMB_BIG_UINT)-1;
5601                         }
5602
5603                         DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5604                                 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5605                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5606                         SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5607                 }
5608
5609                 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5610 #endif /* HAVE_LONGLONG */
5611         }
5612
5613         return offset;
5614 }
5615
5616 /****************************************************************************
5617  Reply to a lockingX request.
5618 ****************************************************************************/
5619
5620 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5621                    int length, int bufsize)
5622 {
5623         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
5624         unsigned char locktype = CVAL(inbuf,smb_vwv3);
5625         unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5626         uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5627         uint16 num_locks = SVAL(inbuf,smb_vwv7);
5628         SMB_BIG_UINT count = 0, offset = 0;
5629         uint32 lock_pid;
5630         int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5631         int i;
5632         char *data;
5633         BOOL large_file_format =
5634                 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5635         BOOL err;
5636         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5637
5638         START_PROFILE(SMBlockingX);
5639         
5640         CHECK_FSP(fsp,conn);
5641         
5642         data = smb_buf(inbuf);
5643
5644         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5645                 /* we don't support these - and CANCEL_LOCK makes w2k
5646                    and XP reboot so I don't really want to be
5647                    compatible! (tridge) */
5648                 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5649         }
5650         
5651         /* Check if this is an oplock break on a file
5652            we have granted an oplock on.
5653         */
5654         if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5655                 /* Client can insist on breaking to none. */
5656                 BOOL break_to_none = (oplocklevel == 0);
5657                 BOOL result;
5658
5659                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5660                          "for fnum = %d\n", (unsigned int)oplocklevel,
5661                          fsp->fnum ));
5662
5663                 /*
5664                  * Make sure we have granted an exclusive or batch oplock on
5665                  * this file.
5666                  */
5667                 
5668                 if (fsp->oplock_type == 0) {
5669
5670                         /* The Samba4 nbench simulator doesn't understand
5671                            the difference between break to level2 and break
5672                            to none from level2 - it sends oplock break
5673                            replies in both cases. Don't keep logging an error
5674                            message here - just ignore it. JRA. */
5675
5676                         DEBUG(5,("reply_lockingX: Error : oplock break from "
5677                                  "client for fnum = %d (oplock=%d) and no "
5678                                  "oplock granted on this file (%s).\n",
5679                                  fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5680
5681                         /* if this is a pure oplock break request then don't
5682                          * send a reply */
5683                         if (num_locks == 0 && num_ulocks == 0) {
5684                                 END_PROFILE(SMBlockingX);
5685                                 return -1;
5686                         } else {
5687                                 END_PROFILE(SMBlockingX);
5688                                 return ERROR_DOS(ERRDOS,ERRlock);
5689                         }
5690                 }
5691
5692                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5693                     (break_to_none)) {
5694                         result = remove_oplock(fsp);
5695                 } else {
5696                         result = downgrade_oplock(fsp);
5697                 }
5698                 
5699                 if (!result) {
5700                         DEBUG(0, ("reply_lockingX: error in removing "
5701                                   "oplock on file %s\n", fsp->fsp_name));
5702                         /* Hmmm. Is this panic justified? */
5703                         smb_panic("internal tdb error");
5704                 }
5705
5706                 reply_to_oplock_break_requests(fsp);
5707
5708                 /* if this is a pure oplock break request then don't send a
5709                  * reply */
5710                 if (num_locks == 0 && num_ulocks == 0) {
5711                         /* Sanity check - ensure a pure oplock break is not a
5712                            chained request. */
5713                         if(CVAL(inbuf,smb_vwv0) != 0xff)
5714                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
5715                                          "break is a chained %d request !\n",
5716                                          (unsigned int)CVAL(inbuf,smb_vwv0) ));
5717                         END_PROFILE(SMBlockingX);
5718                         return -1;
5719                 }
5720         }
5721
5722         /*
5723          * We do this check *after* we have checked this is not a oplock break
5724          * response message. JRA.
5725          */
5726         
5727         release_level_2_oplocks_on_change(fsp);
5728         
5729         /* Data now points at the beginning of the list
5730            of smb_unlkrng structs */
5731         for(i = 0; i < (int)num_ulocks; i++) {
5732                 lock_pid = get_lock_pid( data, i, large_file_format);
5733                 count = get_lock_count( data, i, large_file_format);
5734                 offset = get_lock_offset( data, i, large_file_format, &err);
5735                 
5736                 /*
5737                  * There is no error code marked "stupid client bug".... :-).
5738                  */
5739                 if(err) {
5740                         END_PROFILE(SMBlockingX);
5741                         return ERROR_DOS(ERRDOS,ERRnoaccess);
5742                 }
5743
5744                 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5745                           "pid %u, file %s\n", (double)offset, (double)count,
5746                           (unsigned int)lock_pid, fsp->fsp_name ));
5747                 
5748                 status = do_unlock(smbd_messaging_context(),
5749                                 fsp,
5750                                 lock_pid,
5751                                 count,
5752                                 offset,
5753                                 WINDOWS_LOCK);
5754
5755                 if (NT_STATUS_V(status)) {
5756                         END_PROFILE(SMBlockingX);
5757                         return ERROR_NT(status);
5758                 }
5759         }
5760
5761         /* Setup the timeout in seconds. */
5762
5763         if (!lp_blocking_locks(SNUM(conn))) {
5764                 lock_timeout = 0;
5765         }
5766         
5767         /* Now do any requested locks */
5768         data += ((large_file_format ? 20 : 10)*num_ulocks);
5769         
5770         /* Data now points at the beginning of the list
5771            of smb_lkrng structs */
5772         
5773         for(i = 0; i < (int)num_locks; i++) {
5774                 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5775                                 READ_LOCK:WRITE_LOCK);
5776                 lock_pid = get_lock_pid( data, i, large_file_format);
5777                 count = get_lock_count( data, i, large_file_format);
5778                 offset = get_lock_offset( data, i, large_file_format, &err);
5779                 
5780                 /*
5781                  * There is no error code marked "stupid client bug".... :-).
5782                  */
5783                 if(err) {
5784                         END_PROFILE(SMBlockingX);
5785                         return ERROR_DOS(ERRDOS,ERRnoaccess);
5786                 }
5787                 
5788                 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5789                           "%u, file %s timeout = %d\n", (double)offset,
5790                           (double)count, (unsigned int)lock_pid,
5791                           fsp->fsp_name, (int)lock_timeout ));
5792                 
5793                 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5794                         if (lp_blocking_locks(SNUM(conn))) {
5795
5796                                 /* Schedule a message to ourselves to
5797                                    remove the blocking lock record and
5798                                    return the right error. */
5799
5800                                 if (!blocking_lock_cancel(fsp,
5801                                                 lock_pid,
5802                                                 offset,
5803                                                 count,
5804                                                 WINDOWS_LOCK,
5805                                                 locktype,
5806                                                 NT_STATUS_FILE_LOCK_CONFLICT)) {
5807                                         END_PROFILE(SMBlockingX);
5808                                         return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5809                                 }
5810                         }
5811                         /* Remove a matching pending lock. */
5812                         status = do_lock_cancel(fsp,
5813                                                 lock_pid,
5814                                                 count,
5815                                                 offset,
5816                                                 WINDOWS_LOCK);
5817                 } else {
5818                         BOOL blocking_lock = lock_timeout ? True : False;
5819                         BOOL defer_lock = False;
5820                         struct byte_range_lock *br_lck;
5821                         uint32 block_smbpid;
5822
5823                         br_lck = do_lock(smbd_messaging_context(),
5824                                         fsp,
5825                                         lock_pid,
5826                                         count,
5827                                         offset, 
5828                                         lock_type,
5829                                         WINDOWS_LOCK,
5830                                         blocking_lock,
5831                                         &status,
5832                                         &block_smbpid);
5833
5834                         if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5835                                 /* Windows internal resolution for blocking locks seems
5836                                    to be about 200ms... Don't wait for less than that. JRA. */
5837                                 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5838                                         lock_timeout = lp_lock_spin_time();
5839                                 }
5840                                 defer_lock = True;
5841                         }
5842
5843                         /* This heuristic seems to match W2K3 very well. If a
5844                            lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5845                            it pretends we asked for a timeout of between 150 - 300 milliseconds as
5846                            far as I can tell. Replacement for do_lock_spin(). JRA. */
5847
5848                         if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5849                                         NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5850                                 defer_lock = True;
5851                                 lock_timeout = lp_lock_spin_time();
5852                         }
5853
5854                         if (br_lck && defer_lock) {
5855                                 /*
5856                                  * A blocking lock was requested. Package up
5857                                  * this smb into a queued request and push it
5858                                  * onto the blocking lock queue.
5859                                  */
5860                                 if(push_blocking_lock_request(br_lck,
5861                                                         inbuf, length,
5862                                                         fsp,
5863                                                         lock_timeout,
5864                                                         i,
5865                                                         lock_pid,
5866                                                         lock_type,
5867                                                         WINDOWS_LOCK,
5868                                                         offset,
5869                                                         count,
5870                                                         block_smbpid)) {
5871                                         TALLOC_FREE(br_lck);
5872                                         END_PROFILE(SMBlockingX);
5873                                         return -1;
5874                                 }
5875                         }
5876
5877                         TALLOC_FREE(br_lck);
5878                 }
5879
5880                 if (NT_STATUS_V(status)) {
5881                         END_PROFILE(SMBlockingX);
5882                         return ERROR_NT(status);
5883                 }
5884         }
5885         
5886         /* If any of the above locks failed, then we must unlock
5887            all of the previous locks (X/Open spec). */
5888
5889         if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5890                         (i != num_locks) &&
5891                         (num_locks != 0)) {
5892                 /*
5893                  * Ensure we don't do a remove on the lock that just failed,
5894                  * as under POSIX rules, if we have a lock already there, we
5895                  * will delete it (and we shouldn't) .....
5896                  */
5897                 for(i--; i >= 0; i--) {
5898                         lock_pid = get_lock_pid( data, i, large_file_format);
5899                         count = get_lock_count( data, i, large_file_format);
5900                         offset = get_lock_offset( data, i, large_file_format,
5901                                                   &err);
5902                         
5903                         /*
5904                          * There is no error code marked "stupid client
5905                          * bug".... :-).
5906                          */
5907                         if(err) {
5908                                 END_PROFILE(SMBlockingX);
5909                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
5910                         }
5911                         
5912                         do_unlock(smbd_messaging_context(),
5913                                 fsp,
5914                                 lock_pid,
5915                                 count,
5916                                 offset,
5917                                 WINDOWS_LOCK);
5918                 }
5919                 END_PROFILE(SMBlockingX);
5920                 return ERROR_NT(status);
5921         }
5922
5923         set_message(inbuf,outbuf,2,0,True);
5924         
5925         DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5926                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5927         
5928         END_PROFILE(SMBlockingX);
5929         return chain_reply(inbuf,&outbuf,length,bufsize);
5930 }
5931
5932 #undef DBGC_CLASS
5933 #define DBGC_CLASS DBGC_ALL
5934
5935 /****************************************************************************
5936  Reply to a SMBreadbmpx (read block multiplex) request.
5937 ****************************************************************************/
5938
5939 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5940 {
5941         ssize_t nread = -1;
5942         ssize_t total_read;
5943         char *data;
5944         SMB_OFF_T startpos;
5945         int outsize;
5946         size_t maxcount;
5947         int max_per_packet;
5948         size_t tcount;
5949         int pad;
5950         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
5951         START_PROFILE(SMBreadBmpx);
5952
5953         /* this function doesn't seem to work - disable by default */
5954         if (!lp_readbmpx()) {
5955                 END_PROFILE(SMBreadBmpx);
5956                 return ERROR_DOS(ERRSRV,ERRuseSTD);
5957         }
5958
5959         outsize = set_message(inbuf,outbuf,8,0,True);
5960
5961         CHECK_FSP(fsp,conn);
5962         if (!CHECK_READ(fsp,inbuf)) {
5963                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5964         }
5965
5966         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5967         maxcount = SVAL(inbuf,smb_vwv3);
5968
5969         data = smb_buf(outbuf);
5970         pad = ((long)data)%4;
5971         if (pad)
5972                 pad = 4 - pad;
5973         data += pad;
5974
5975         max_per_packet = bufsize-(outsize+pad);
5976         tcount = maxcount;
5977         total_read = 0;
5978
5979         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5980                 END_PROFILE(SMBreadBmpx);
5981                 return ERROR_DOS(ERRDOS,ERRlock);
5982         }
5983
5984         do {
5985                 size_t N = MIN(max_per_packet,tcount-total_read);
5986   
5987                 nread = read_file(fsp,data,startpos,N);
5988
5989                 if (nread <= 0)
5990                         nread = 0;
5991
5992                 if (nread < (ssize_t)N)
5993                         tcount = total_read + nread;
5994
5995                 set_message(inbuf,outbuf,8,nread+pad,False);
5996                 SIVAL(outbuf,smb_vwv0,startpos);
5997                 SSVAL(outbuf,smb_vwv2,tcount);
5998                 SSVAL(outbuf,smb_vwv6,nread);
5999                 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
6000
6001                 show_msg(outbuf);
6002                 if (!send_smb(smbd_server_fd(),outbuf))
6003                         exit_server_cleanly("reply_readbmpx: send_smb failed.");
6004
6005                 total_read += nread;
6006                 startpos += nread;
6007         } while (total_read < (ssize_t)tcount);
6008
6009         END_PROFILE(SMBreadBmpx);
6010         return(-1);
6011 }
6012
6013 /****************************************************************************
6014  Reply to a SMBsetattrE.
6015 ****************************************************************************/
6016
6017 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6018 {
6019         struct timespec ts[2];
6020         int outsize = 0;
6021         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6022         START_PROFILE(SMBsetattrE);
6023
6024         outsize = set_message(inbuf,outbuf,0,0,False);
6025
6026         if(!fsp || (fsp->conn != conn)) {
6027                 END_PROFILE(SMBsetattrE);
6028                 return ERROR_DOS(ERRDOS,ERRbadfid);
6029         }
6030
6031         /*
6032          * Convert the DOS times into unix times. Ignore create
6033          * time as UNIX can't set this.
6034          */
6035
6036         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
6037         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
6038   
6039         /* 
6040          * Patch from Ray Frush <frush@engr.colostate.edu>
6041          * Sometimes times are sent as zero - ignore them.
6042          */
6043
6044         if (null_timespec(ts[0]) && null_timespec(ts[1])) {
6045                 /* Ignore request */
6046                 if( DEBUGLVL( 3 ) ) {
6047                         dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
6048                         dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
6049                 }
6050                 END_PROFILE(SMBsetattrE);
6051                 return(outsize);
6052         } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
6053                 /* set modify time = to access time if modify time was unset */
6054                 ts[1] = ts[0];
6055         }
6056
6057         /* Set the date on this file */
6058         /* Should we set pending modtime here ? JRA */
6059         if(file_ntimes(conn, fsp->fsp_name, ts)) {
6060                 END_PROFILE(SMBsetattrE);
6061                 return ERROR_DOS(ERRDOS,ERRnoaccess);
6062         }
6063   
6064         DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
6065                 fsp->fnum,
6066                 (unsigned int)ts[0].tv_sec,
6067                 (unsigned int)ts[1].tv_sec));
6068
6069         END_PROFILE(SMBsetattrE);
6070         return(outsize);
6071 }
6072
6073
6074 /* Back from the dead for OS/2..... JRA. */
6075
6076 /****************************************************************************
6077  Reply to a SMBwritebmpx (write block multiplex primary) request.
6078 ****************************************************************************/
6079
6080 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6081 {
6082         size_t numtowrite;
6083         ssize_t nwritten = -1;
6084         int outsize = 0;
6085         SMB_OFF_T startpos;
6086         size_t tcount;
6087         BOOL write_through;
6088         int smb_doff;
6089         char *data;
6090         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6091         NTSTATUS status;
6092         START_PROFILE(SMBwriteBmpx);
6093
6094         CHECK_FSP(fsp,conn);
6095         if (!CHECK_WRITE(fsp)) {
6096                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6097         }
6098         if (HAS_CACHED_ERROR(fsp)) {
6099                 return(CACHED_ERROR(fsp));
6100         }
6101
6102         tcount = SVAL(inbuf,smb_vwv1);
6103         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
6104         write_through = BITSETW(inbuf+smb_vwv7,0);
6105         numtowrite = SVAL(inbuf,smb_vwv10);
6106         smb_doff = SVAL(inbuf,smb_vwv11);
6107
6108         data = smb_base(inbuf) + smb_doff;
6109
6110         /* If this fails we need to send an SMBwriteC response,
6111                 not an SMBwritebmpx - set this up now so we don't forget */
6112         SCVAL(outbuf,smb_com,SMBwritec);
6113
6114         if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
6115                 END_PROFILE(SMBwriteBmpx);
6116                 return(ERROR_DOS(ERRDOS,ERRlock));
6117         }
6118
6119         nwritten = write_file(fsp,data,startpos,numtowrite);
6120
6121         status = sync_file(conn, fsp, write_through);
6122         if (!NT_STATUS_IS_OK(status)) {
6123                 END_PROFILE(SMBwriteBmpx);
6124                 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
6125                         fsp->fsp_name, nt_errstr(status) ));
6126                 return ERROR_NT(status);
6127         }
6128   
6129         if(nwritten < (ssize_t)numtowrite) {
6130                 END_PROFILE(SMBwriteBmpx);
6131                 return(UNIXERROR(ERRHRD,ERRdiskfull));
6132         }
6133
6134         /* If the maximum to be written to this file
6135                 is greater than what we just wrote then set
6136                 up a secondary struct to be attached to this
6137                 fd, we will use this to cache error messages etc. */
6138
6139         if((ssize_t)tcount > nwritten) {
6140                 write_bmpx_struct *wbms;
6141                 if(fsp->wbmpx_ptr != NULL)
6142                         wbms = fsp->wbmpx_ptr; /* Use an existing struct */
6143                 else
6144                         wbms = SMB_MALLOC_P(write_bmpx_struct);
6145                 if(!wbms) {
6146                         DEBUG(0,("Out of memory in reply_readmpx\n"));
6147                         END_PROFILE(SMBwriteBmpx);
6148                         return(ERROR_DOS(ERRSRV,ERRnoresource));
6149                 }
6150                 wbms->wr_mode = write_through;
6151                 wbms->wr_discard = False; /* No errors yet */
6152                 wbms->wr_total_written = nwritten;
6153                 wbms->wr_errclass = 0;
6154                 wbms->wr_error = 0;
6155                 fsp->wbmpx_ptr = wbms;
6156         }
6157
6158         /* We are returning successfully, set the message type back to
6159                 SMBwritebmpx */
6160         SCVAL(outbuf,smb_com,SMBwriteBmpx);
6161   
6162         outsize = set_message(inbuf,outbuf,1,0,True);
6163   
6164         SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
6165   
6166         DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
6167                         fsp->fnum, (int)numtowrite, (int)nwritten ) );
6168
6169         if (write_through && tcount==nwritten) {
6170                 /* We need to send both a primary and a secondary response */
6171                 smb_setlen(inbuf,outbuf,outsize - 4);
6172                 show_msg(outbuf);
6173                 if (!send_smb(smbd_server_fd(),outbuf))
6174                         exit_server_cleanly("reply_writebmpx: send_smb failed.");
6175
6176                 /* Now the secondary */
6177                 outsize = set_message(inbuf,outbuf,1,0,True);
6178                 SCVAL(outbuf,smb_com,SMBwritec);
6179                 SSVAL(outbuf,smb_vwv0,nwritten);
6180         }
6181
6182         END_PROFILE(SMBwriteBmpx);
6183         return(outsize);
6184 }
6185
6186 /****************************************************************************
6187  Reply to a SMBwritebs (write block multiplex secondary) request.
6188 ****************************************************************************/
6189
6190 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
6191 {
6192         size_t numtowrite;
6193         ssize_t nwritten = -1;
6194         int outsize = 0;
6195         SMB_OFF_T startpos;
6196         size_t tcount;
6197         BOOL write_through;
6198         int smb_doff;
6199         char *data;
6200         write_bmpx_struct *wbms;
6201         BOOL send_response = False; 
6202         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6203         NTSTATUS status;
6204         START_PROFILE(SMBwriteBs);
6205
6206         CHECK_FSP(fsp,conn);
6207         if (!CHECK_WRITE(fsp)) {
6208                 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6209         }
6210
6211         tcount = SVAL(inbuf,smb_vwv1);
6212         startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6213         numtowrite = SVAL(inbuf,smb_vwv6);
6214         smb_doff = SVAL(inbuf,smb_vwv7);
6215
6216         data = smb_base(inbuf) + smb_doff;
6217
6218         /* We need to send an SMBwriteC response, not an SMBwritebs */
6219         SCVAL(outbuf,smb_com,SMBwritec);
6220
6221         /* This fd should have an auxiliary struct attached,
6222                 check that it does */
6223         wbms = fsp->wbmpx_ptr;
6224         if(!wbms) {
6225                 END_PROFILE(SMBwriteBs);
6226                 return(-1);
6227         }
6228
6229         /* If write through is set we can return errors, else we must cache them */
6230         write_through = wbms->wr_mode;
6231
6232         /* Check for an earlier error */
6233         if(wbms->wr_discard) {
6234                 END_PROFILE(SMBwriteBs);
6235                 return -1; /* Just discard the packet */
6236         }
6237
6238         nwritten = write_file(fsp,data,startpos,numtowrite);
6239
6240         status = sync_file(conn, fsp, write_through);
6241   
6242         if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6243                 if(write_through) {
6244                         /* We are returning an error - we can delete the aux struct */
6245                         if (wbms)
6246                                 free((char *)wbms);
6247                         fsp->wbmpx_ptr = NULL;
6248                         END_PROFILE(SMBwriteBs);
6249                         return(ERROR_DOS(ERRHRD,ERRdiskfull));
6250                 }
6251                 wbms->wr_errclass = ERRHRD;
6252                 wbms->wr_error = ERRdiskfull;
6253                 wbms->wr_status = NT_STATUS_DISK_FULL;
6254                 wbms->wr_discard = True;
6255                 END_PROFILE(SMBwriteBs);
6256                 return -1;
6257         }
6258
6259         /* Increment the total written, if this matches tcount
6260                 we can discard the auxiliary struct (hurrah !) and return a writeC */
6261         wbms->wr_total_written += nwritten;
6262         if(wbms->wr_total_written >= tcount) {
6263                 if (write_through) {
6264                         outsize = set_message(inbuf,outbuf,1,0,True);
6265                         SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);    
6266                         send_response = True;
6267                 }
6268
6269                 free((char *)wbms);
6270                 fsp->wbmpx_ptr = NULL;
6271         }
6272
6273         if(send_response) {
6274                 END_PROFILE(SMBwriteBs);
6275                 return(outsize);
6276         }
6277
6278         END_PROFILE(SMBwriteBs);
6279         return(-1);
6280 }
6281
6282 /****************************************************************************
6283  Reply to a SMBgetattrE.
6284 ****************************************************************************/
6285
6286 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6287 {
6288         SMB_STRUCT_STAT sbuf;
6289         int outsize = 0;
6290         int mode;
6291         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6292         START_PROFILE(SMBgetattrE);
6293
6294         outsize = set_message(inbuf,outbuf,11,0,True);
6295
6296         if(!fsp || (fsp->conn != conn)) {
6297                 END_PROFILE(SMBgetattrE);
6298                 return ERROR_DOS(ERRDOS,ERRbadfid);
6299         }
6300
6301         /* Do an fstat on this file */
6302         if(fsp_stat(fsp, &sbuf)) {
6303                 END_PROFILE(SMBgetattrE);
6304                 return(UNIXERROR(ERRDOS,ERRnoaccess));
6305         }
6306   
6307         mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6308   
6309         /*
6310          * Convert the times into dos times. Set create
6311          * date to be last modify date as UNIX doesn't save
6312          * this.
6313          */
6314
6315         srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6316         srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6317         /* Should we check pending modtime here ? JRA */
6318         srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6319
6320         if (mode & aDIR) {
6321                 SIVAL(outbuf,smb_vwv6,0);
6322                 SIVAL(outbuf,smb_vwv8,0);
6323         } else {
6324                 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6325                 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6326                 SIVAL(outbuf,smb_vwv8,allocation_size);
6327         }
6328         SSVAL(outbuf,smb_vwv10, mode);
6329   
6330         DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6331   
6332         END_PROFILE(SMBgetattrE);
6333         return(outsize);
6334 }