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