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