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