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