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