r24102: Pass the fid instead of inbuf and an offset to file_fsp.
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blob385a47bbf3559c7129cd1bc5f231b7e9f64acb13
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.
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.
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.
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/>.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
26 #include "includes.h"
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;
34 extern struct current_user current_user;
35 extern BOOL global_encrypted_passwords_negotiated;
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 ****************************************************************************/
45 /* Custom version for processing POSIX paths. */
46 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
48 static NTSTATUS check_path_syntax_internal(char *path,
49 BOOL posix_path,
50 BOOL *p_last_component_contains_wcard)
52 char *d = path;
53 const char *s = path;
54 NTSTATUS ret = NT_STATUS_OK;
55 BOOL start_of_name_component = True;
57 *p_last_component_contains_wcard = False;
59 while (*s) {
60 if (IS_PATH_SEP(*s,posix_path)) {
62 * Safe to assume is not the second part of a mb char
63 * as this is handled below.
65 /* Eat multiple '/' or '\\' */
66 while (IS_PATH_SEP(*s,posix_path)) {
67 s++;
69 if ((d != path) && (*s != '\0')) {
70 /* We only care about non-leading or trailing '/' or '\\' */
71 *d++ = '/';
74 start_of_name_component = True;
75 /* New component. */
76 *p_last_component_contains_wcard = False;
77 continue;
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" ! */
85 * No mb char starts with '.' so we're safe checking the directory separator here.
88 /* If we just added a '/' - delete it */
89 if ((d > path) && (*(d-1) == '/')) {
90 *(d-1) = '\0';
91 d--;
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;
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;
107 s += 2; /* Else go past the .. */
108 /* We're still at the start of a name component, just the previous one. */
109 continue;
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;
121 if (!(*s & 0x80)) {
122 if (!posix_path) {
123 if (*s <= 0x1f) {
124 return NT_STATUS_OBJECT_NAME_INVALID;
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;
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;
165 start_of_name_component = False;
168 *d = '\0';
169 return ret;
172 /****************************************************************************
173 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
174 No wildcards allowed.
175 ****************************************************************************/
177 NTSTATUS check_path_syntax(char *path)
179 BOOL ignore;
180 return check_path_syntax_internal(path, False, &ignore);
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 ****************************************************************************/
189 NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
191 return check_path_syntax_internal(path, False, p_contains_wcard);
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 ****************************************************************************/
200 NTSTATUS check_path_syntax_posix(char *path)
202 BOOL ignore;
203 return check_path_syntax_internal(path, True, &ignore);
206 /****************************************************************************
207 Pull a string and check the path allowing a wilcard - provide for error return.
208 ****************************************************************************/
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)
214 size_t ret;
215 #ifdef DEVELOPER
216 SMB_ASSERT(dest_len == sizeof(pstring));
217 #endif
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);
227 *contains_wcard = False;
229 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
231 * For a DFS path the function parse_dfs_path()
232 * will do the path processing, just make a copy.
234 *err = NT_STATUS_OK;
235 return ret;
238 if (lp_posix_pathnames()) {
239 *err = check_path_syntax_posix(dest);
240 } else {
241 *err = check_path_syntax_wcard(dest, contains_wcard);
244 return ret;
247 /****************************************************************************
248 Pull a string and check the path - provide for error return.
249 ****************************************************************************/
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)
255 size_t ret;
256 #ifdef DEVELOPER
257 SMB_ASSERT(dest_len == sizeof(pstring));
258 #endif
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);
268 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270 * For a DFS path the function parse_dfs_path()
271 * will do the path processing, just make a copy.
273 *err = NT_STATUS_OK;
274 return ret;
277 if (lp_posix_pathnames()) {
278 *err = check_path_syntax_posix(dest);
279 } else {
280 *err = check_path_syntax(dest);
283 return ret;
286 /****************************************************************************
287 Reply to a (netbios-level) special message.
288 ****************************************************************************/
290 void reply_special(char *inbuf)
292 int msg_type = CVAL(inbuf,0);
293 int msg_flags = CVAL(inbuf,1);
294 fstring name1,name2;
295 char name_type = 0;
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.
302 char outbuf[smb_size];
304 static BOOL already_got_session = False;
306 *name1 = *name2 = 0;
308 memset(outbuf, '\0', sizeof(outbuf));
310 smb_setlen(inbuf,outbuf,0);
312 switch (msg_type) {
313 case 0x81: /* session request */
315 if (already_got_session) {
316 exit_server_cleanly("multiple session request not permitted");
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;
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));
331 set_local_machine_name(name1, True);
332 set_remote_machine_name(name2, True);
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));
338 if (name_type == 'R') {
339 /* We are being asked for a pathworks session ---
340 no thanks! */
341 SCVAL(outbuf, 0,0x83);
342 break;
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());
352 reload_services(True);
353 reopen_logs();
355 already_got_session = True;
356 break;
358 case 0x89: /* session keepalive request
359 (some old clients produce this?) */
360 SCVAL(outbuf,0,SMBkeepalive);
361 SCVAL(outbuf,3,0);
362 break;
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;
370 case SMBkeepalive: /* session keepalive */
371 default:
372 return;
375 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
376 msg_type, msg_flags));
378 send_smb(smbd_server_fd(), outbuf);
379 return;
382 /****************************************************************************
383 Reply to a tcon.
384 conn POINTER CAN BE NULL HERE !
385 ****************************************************************************/
387 int reply_tcon(connection_struct *conn,
388 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
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;
402 START_PROFILE(SMBtcon);
404 ctx = talloc_init("reply_tcon");
405 if (!ctx) {
406 END_PROFILE(SMBtcon);
407 return ERROR_NT(NT_STATUS_NO_MEMORY);
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;
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);
424 p = strrchr_m(service_buf,'\\');
425 if (p) {
426 service = p+1;
427 } else {
428 service = service_buf;
431 password_blob = data_blob(password, pwlen+1);
433 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
435 data_blob_clear_free(&password_blob);
437 if (!conn) {
438 TALLOC_FREE(ctx);
439 END_PROFILE(SMBtcon);
440 return ERROR_NT(nt_status);
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);
448 DEBUG(3,("tcon service=%s cnum=%d\n",
449 service, conn->cnum));
451 END_PROFILE(SMBtcon);
452 TALLOC_FREE(ctx);
453 return(outsize);
456 /****************************************************************************
457 Reply to a tcon and X.
458 conn POINTER CAN BE NULL HERE !
459 ****************************************************************************/
461 void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
463 char *service = NULL;
464 DATA_BLOB password;
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;
477 START_PROFILE(SMBtconX);
479 if (req->wct < 4) {
480 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
481 END_PROFILE(SMBtconX);
482 return;
485 passlen = SVAL(req->inbuf,smb_vwv3);
486 tcon_flags = SVAL(req->inbuf,smb_vwv2);
488 /* we might have to close an old one */
489 if ((tcon_flags & 0x1) && conn) {
490 close_cnum(conn,req->vuid);
493 if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
494 reply_doserror(req, ERRDOS, ERRbuftoosmall);
495 END_PROFILE(SMBtconX);
496 return;
499 if (global_encrypted_passwords_negotiated) {
500 password = data_blob(smb_buf(req->inbuf),passlen);
501 if (lp_security() == SEC_SHARE) {
503 * Security = share always has a pad byte
504 * after the password.
506 p = smb_buf(req->inbuf) + passlen + 1;
507 } else {
508 p = smb_buf(req->inbuf) + passlen;
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;
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;
524 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
525 STR_TERMINATE);
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;
536 * the service name can be either: \\server\share
537 * or share directly like on the DELL PowerVault 705
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;
548 service = q+1;
549 } else {
550 service = path;
553 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
554 &client_devicetype, p,
555 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
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;
565 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
567 conn = make_connection(service, password, client_devicetype,
568 req->vuid, &nt_status);
570 data_blob_clear_free(&password);
572 if (!conn) {
573 TALLOC_FREE(ctx);
574 reply_nterror(req, nt_status);
575 END_PROFILE(SMBtconX);
576 return;
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:";
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;
595 } else {
596 /* NT sets the fstype of IPC$ to the null string */
597 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
599 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
600 /* Return permissions. */
601 uint32 perm1 = 0;
602 uint32 perm2 = 0;
604 reply_outbuf(req, 7, 0);
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;
615 SIVAL(req->outbuf, smb_vwv3, perm1);
616 SIVAL(req->outbuf, smb_vwv5, perm2);
617 } else {
618 reply_outbuf(req, 3, 0);
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;
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));
636 init_dfsroot(conn, req->inbuf, req->outbuf);
640 DEBUG(3,("tconX service=%s \n",
641 service));
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);
647 TALLOC_FREE(ctx);
648 END_PROFILE(SMBtconX);
650 chain_reply_new(req);
651 return;
654 /****************************************************************************
655 Reply to an unknown type.
656 ****************************************************************************/
658 int reply_unknown(char *inbuf,char *outbuf)
660 int type;
661 type = CVAL(inbuf,smb_com);
663 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
664 smb_fn_name(type), type, type));
666 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
669 void reply_unknown_new(struct smb_request *req, uint8 type)
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;
677 /****************************************************************************
678 Reply to an ioctl.
679 conn POINTER CAN BE NULL HERE !
680 ****************************************************************************/
682 int reply_ioctl(connection_struct *conn,
683 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
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);
692 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
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));
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 */
709 switch (ioctl_code) {
710 case IOCTL_QUERY_JOB_INFO:
712 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
713 if (!fsp) {
714 END_PROFILE(SMBioctl);
715 return(UNIXERROR(ERRDOS,ERRbadfid));
717 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
718 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
719 if (conn) {
720 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
722 break;
726 END_PROFILE(SMBioctl);
727 return outsize;
730 /****************************************************************************
731 Strange checkpath NTSTATUS mapping.
732 ****************************************************************************/
734 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
736 /* Strange DOS error code semantics only for checkpath... */
737 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
738 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
739 /* We need to map to ERRbadpath */
740 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
743 return status;
746 /****************************************************************************
747 Reply to a checkpath.
748 ****************************************************************************/
750 void reply_checkpath(connection_struct *conn, struct smb_request *req)
752 pstring name;
753 SMB_STRUCT_STAT sbuf;
754 NTSTATUS status;
756 START_PROFILE(SMBcheckpath);
758 srvstr_get_path((char *)req->inbuf, req->flags2, name,
759 smb_buf(req->inbuf) + 1, sizeof(name), 0,
760 STR_TERMINATE, &status);
761 if (!NT_STATUS_IS_OK(status)) {
762 status = map_checkpath_error((char *)req->inbuf, status);
763 reply_nterror(req, status);
764 END_PROFILE(SMBcheckpath);
765 return;
768 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name);
769 if (!NT_STATUS_IS_OK(status)) {
770 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
771 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
772 ERRSRV, ERRbadpath);
773 END_PROFILE(SMBcheckpath);
774 return;
776 goto path_err;
779 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
781 status = unix_convert(conn, name, False, NULL, &sbuf);
782 if (!NT_STATUS_IS_OK(status)) {
783 goto path_err;
786 status = check_name(conn, name);
787 if (!NT_STATUS_IS_OK(status)) {
788 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
789 goto path_err;
792 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
793 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
794 status = map_nt_error_from_unix(errno);
795 goto path_err;
798 if (!S_ISDIR(sbuf.st_mode)) {
799 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
800 ERRDOS, ERRbadpath);
801 END_PROFILE(SMBcheckpath);
802 return;
805 reply_outbuf(req, 0, 0);
807 END_PROFILE(SMBcheckpath);
808 return;
810 path_err:
812 END_PROFILE(SMBcheckpath);
814 /* We special case this - as when a Windows machine
815 is parsing a path is steps through the components
816 one at a time - if a component fails it expects
817 ERRbadpath, not ERRbadfile.
819 status = map_checkpath_error((char *)req->inbuf, status);
820 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
822 * Windows returns different error codes if
823 * the parent directory is valid but not the
824 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
825 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
826 * if the path is invalid.
828 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
829 ERRDOS, ERRbadpath);
830 return;
833 reply_nterror(req, status);
836 /****************************************************************************
837 Reply to a getatr.
838 ****************************************************************************/
840 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
842 pstring fname;
843 int outsize = 0;
844 SMB_STRUCT_STAT sbuf;
845 int mode=0;
846 SMB_OFF_T size=0;
847 time_t mtime=0;
848 char *p;
849 NTSTATUS status;
851 START_PROFILE(SMBgetatr);
853 p = smb_buf(inbuf) + 1;
854 p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
855 sizeof(fname), 0, STR_TERMINATE, &status);
856 if (!NT_STATUS_IS_OK(status)) {
857 END_PROFILE(SMBgetatr);
858 return ERROR_NT(status);
861 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
862 if (!NT_STATUS_IS_OK(status)) {
863 END_PROFILE(SMBgetatr);
864 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
865 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
867 return ERROR_NT(status);
870 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
871 under WfWg - weird! */
872 if (*fname == '\0') {
873 mode = aHIDDEN | aDIR;
874 if (!CAN_WRITE(conn)) {
875 mode |= aRONLY;
877 size = 0;
878 mtime = 0;
879 } else {
880 status = unix_convert(conn, fname, False, NULL,&sbuf);
881 if (!NT_STATUS_IS_OK(status)) {
882 END_PROFILE(SMBgetatr);
883 return ERROR_NT(status);
885 status = check_name(conn, fname);
886 if (!NT_STATUS_IS_OK(status)) {
887 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
888 END_PROFILE(SMBgetatr);
889 return ERROR_NT(status);
891 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
892 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
893 return UNIXERROR(ERRDOS,ERRbadfile);
896 mode = dos_mode(conn,fname,&sbuf);
897 size = sbuf.st_size;
898 mtime = sbuf.st_mtime;
899 if (mode & aDIR) {
900 size = 0;
904 outsize = set_message(inbuf,outbuf,10,0,True);
906 SSVAL(outbuf,smb_vwv0,mode);
907 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
908 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
909 } else {
910 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
912 SIVAL(outbuf,smb_vwv3,(uint32)size);
914 if (Protocol >= PROTOCOL_NT1) {
915 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
918 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
920 END_PROFILE(SMBgetatr);
921 return(outsize);
924 /****************************************************************************
925 Reply to a setatr.
926 ****************************************************************************/
928 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
930 pstring fname;
931 int outsize = 0;
932 int mode;
933 time_t mtime;
934 SMB_STRUCT_STAT sbuf;
935 char *p;
936 NTSTATUS status;
938 START_PROFILE(SMBsetatr);
940 p = smb_buf(inbuf) + 1;
941 p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
942 sizeof(fname), 0, STR_TERMINATE, &status);
943 if (!NT_STATUS_IS_OK(status)) {
944 END_PROFILE(SMBsetatr);
945 return ERROR_NT(status);
948 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
949 if (!NT_STATUS_IS_OK(status)) {
950 END_PROFILE(SMBsetatr);
951 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
952 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
954 return ERROR_NT(status);
957 status = unix_convert(conn, fname, False, NULL, &sbuf);
958 if (!NT_STATUS_IS_OK(status)) {
959 END_PROFILE(SMBsetatr);
960 return ERROR_NT(status);
963 status = check_name(conn, fname);
964 if (!NT_STATUS_IS_OK(status)) {
965 END_PROFILE(SMBsetatr);
966 return ERROR_NT(status);
969 if (fname[0] == '.' && fname[1] == '\0') {
971 * Not sure here is the right place to catch this
972 * condition. Might be moved to somewhere else later -- vl
974 END_PROFILE(SMBsetatr);
975 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
978 mode = SVAL(inbuf,smb_vwv0);
979 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
981 if (mode != FILE_ATTRIBUTE_NORMAL) {
982 if (VALID_STAT_OF_DIR(sbuf))
983 mode |= aDIR;
984 else
985 mode &= ~aDIR;
987 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
988 END_PROFILE(SMBsetatr);
989 return UNIXERROR(ERRDOS, ERRnoaccess);
993 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
994 END_PROFILE(SMBsetatr);
995 return UNIXERROR(ERRDOS, ERRnoaccess);
998 outsize = set_message(inbuf,outbuf,0,0,False);
1000 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1002 END_PROFILE(SMBsetatr);
1003 return(outsize);
1006 /****************************************************************************
1007 Reply to a dskattr.
1008 ****************************************************************************/
1010 void reply_dskattr(connection_struct *conn, struct smb_request *req)
1012 SMB_BIG_UINT dfree,dsize,bsize;
1013 START_PROFILE(SMBdskattr);
1015 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1016 reply_unixerror(req, ERRHRD, ERRgeneral);
1017 END_PROFILE(SMBdskattr);
1018 return;
1021 reply_outbuf(req, 5, 0);
1023 if (Protocol <= PROTOCOL_LANMAN2) {
1024 double total_space, free_space;
1025 /* we need to scale this to a number that DOS6 can handle. We
1026 use floating point so we can handle large drives on systems
1027 that don't have 64 bit integers
1029 we end up displaying a maximum of 2G to DOS systems
1031 total_space = dsize * (double)bsize;
1032 free_space = dfree * (double)bsize;
1034 dsize = (total_space+63*512) / (64*512);
1035 dfree = (free_space+63*512) / (64*512);
1037 if (dsize > 0xFFFF) dsize = 0xFFFF;
1038 if (dfree > 0xFFFF) dfree = 0xFFFF;
1040 SSVAL(req->outbuf,smb_vwv0,dsize);
1041 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1042 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1043 SSVAL(req->outbuf,smb_vwv3,dfree);
1044 } else {
1045 SSVAL(req->outbuf,smb_vwv0,dsize);
1046 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1047 SSVAL(req->outbuf,smb_vwv2,512);
1048 SSVAL(req->outbuf,smb_vwv3,dfree);
1051 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1053 END_PROFILE(SMBdskattr);
1054 return;
1057 /****************************************************************************
1058 Reply to a search.
1059 Can be called from SMBsearch, SMBffirst or SMBfunique.
1060 ****************************************************************************/
1062 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1064 pstring mask;
1065 pstring directory;
1066 pstring fname;
1067 SMB_OFF_T size;
1068 uint32 mode;
1069 time_t date;
1070 uint32 dirtype;
1071 int outsize = 0;
1072 unsigned int numentries = 0;
1073 unsigned int maxentries = 0;
1074 BOOL finished = False;
1075 char *p;
1076 int status_len;
1077 pstring path;
1078 char status[21];
1079 int dptr_num= -1;
1080 BOOL check_descend = False;
1081 BOOL expect_close = False;
1082 NTSTATUS nt_status;
1083 BOOL mask_contains_wcard = False;
1084 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1086 START_PROFILE(SMBsearch);
1088 if (lp_posix_pathnames()) {
1089 END_PROFILE(SMBsearch);
1090 return reply_unknown(inbuf, outbuf);
1093 *mask = *directory = *fname = 0;
1095 /* If we were called as SMBffirst then we must expect close. */
1096 if(CVAL(inbuf,smb_com) == SMBffirst) {
1097 expect_close = True;
1100 outsize = set_message(inbuf,outbuf,1,3,True);
1101 maxentries = SVAL(inbuf,smb_vwv0);
1102 dirtype = SVAL(inbuf,smb_vwv1);
1103 p = smb_buf(inbuf) + 1;
1104 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1105 sizeof(path), 0, STR_TERMINATE, &nt_status,
1106 &mask_contains_wcard);
1107 if (!NT_STATUS_IS_OK(nt_status)) {
1108 END_PROFILE(SMBsearch);
1109 return ERROR_NT(nt_status);
1112 nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
1113 if (!NT_STATUS_IS_OK(nt_status)) {
1114 END_PROFILE(SMBsearch);
1115 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1116 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1118 return ERROR_NT(nt_status);
1121 p++;
1122 status_len = SVAL(p, 0);
1123 p += 2;
1125 /* dirtype &= ~aDIR; */
1127 if (status_len == 0) {
1128 SMB_STRUCT_STAT sbuf;
1130 pstrcpy(directory,path);
1131 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1132 if (!NT_STATUS_IS_OK(nt_status)) {
1133 END_PROFILE(SMBsearch);
1134 return ERROR_NT(nt_status);
1137 nt_status = check_name(conn, directory);
1138 if (!NT_STATUS_IS_OK(nt_status)) {
1139 END_PROFILE(SMBsearch);
1140 return ERROR_NT(nt_status);
1143 p = strrchr_m(directory,'/');
1144 if (!p) {
1145 pstrcpy(mask,directory);
1146 pstrcpy(directory,".");
1147 } else {
1148 *p = 0;
1149 pstrcpy(mask,p+1);
1152 if (*directory == '\0') {
1153 pstrcpy(directory,".");
1155 memset((char *)status,'\0',21);
1156 SCVAL(status,0,(dirtype & 0x1F));
1157 } else {
1158 int status_dirtype;
1160 memcpy(status,p,21);
1161 status_dirtype = CVAL(status,0) & 0x1F;
1162 if (status_dirtype != (dirtype & 0x1F)) {
1163 dirtype = status_dirtype;
1166 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1167 if (!conn->dirptr) {
1168 goto SearchEmpty;
1170 string_set(&conn->dirpath,dptr_path(dptr_num));
1171 pstrcpy(mask, dptr_wcard(dptr_num));
1173 * For a 'continue' search we have no string. So
1174 * check from the initial saved string.
1176 mask_contains_wcard = ms_has_wild(mask);
1179 p = smb_buf(outbuf) + 3;
1181 if (status_len == 0) {
1182 nt_status = dptr_create(conn,
1183 directory,
1184 True,
1185 expect_close,
1186 SVAL(inbuf,smb_pid),
1187 mask,
1188 mask_contains_wcard,
1189 dirtype,
1190 &conn->dirptr);
1191 if (!NT_STATUS_IS_OK(nt_status)) {
1192 return ERROR_NT(nt_status);
1194 dptr_num = dptr_dnum(conn->dirptr);
1195 } else {
1196 dirtype = dptr_attr(dptr_num);
1199 DEBUG(4,("dptr_num is %d\n",dptr_num));
1201 if ((dirtype&0x1F) == aVOLID) {
1202 memcpy(p,status,21);
1203 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1204 0,aVOLID,0,!allow_long_path_components);
1205 dptr_fill(p+12,dptr_num);
1206 if (dptr_zero(p+12) && (status_len==0)) {
1207 numentries = 1;
1208 } else {
1209 numentries = 0;
1211 p += DIR_STRUCT_SIZE;
1212 } else {
1213 unsigned int i;
1214 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1216 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1217 conn->dirpath,lp_dontdescend(SNUM(conn))));
1218 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1219 check_descend = True;
1222 for (i=numentries;(i<maxentries) && !finished;i++) {
1223 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1224 if (!finished) {
1225 memcpy(p,status,21);
1226 make_dir_struct(p,mask,fname,size, mode,date,
1227 !allow_long_path_components);
1228 if (!dptr_fill(p+12,dptr_num)) {
1229 break;
1231 numentries++;
1232 p += DIR_STRUCT_SIZE;
1237 SearchEmpty:
1239 /* If we were called as SMBffirst with smb_search_id == NULL
1240 and no entries were found then return error and close dirptr
1241 (X/Open spec) */
1243 if (numentries == 0) {
1244 dptr_close(&dptr_num);
1245 } else if(expect_close && status_len == 0) {
1246 /* Close the dptr - we know it's gone */
1247 dptr_close(&dptr_num);
1250 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1251 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1252 dptr_close(&dptr_num);
1255 if ((numentries == 0) && !mask_contains_wcard) {
1256 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1259 SSVAL(outbuf,smb_vwv0,numentries);
1260 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1261 SCVAL(smb_buf(outbuf),0,5);
1262 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1264 /* The replies here are never long name. */
1265 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1266 if (!allow_long_path_components) {
1267 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1270 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1271 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1273 outsize += DIR_STRUCT_SIZE*numentries;
1274 smb_setlen(inbuf,outbuf,outsize - 4);
1276 if ((! *directory) && dptr_path(dptr_num))
1277 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1279 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1280 smb_fn_name(CVAL(inbuf,smb_com)),
1281 mask, directory, dirtype, numentries, maxentries ) );
1283 END_PROFILE(SMBsearch);
1284 return(outsize);
1287 /****************************************************************************
1288 Reply to a fclose (stop directory search).
1289 ****************************************************************************/
1291 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1293 int outsize = 0;
1294 int status_len;
1295 pstring path;
1296 char status[21];
1297 int dptr_num= -2;
1298 char *p;
1299 NTSTATUS err;
1300 BOOL path_contains_wcard = False;
1302 START_PROFILE(SMBfclose);
1304 if (lp_posix_pathnames()) {
1305 END_PROFILE(SMBfclose);
1306 return reply_unknown(inbuf, outbuf);
1309 outsize = set_message(inbuf,outbuf,1,0,True);
1310 p = smb_buf(inbuf) + 1;
1311 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1312 sizeof(path), 0, STR_TERMINATE, &err,
1313 &path_contains_wcard);
1314 if (!NT_STATUS_IS_OK(err)) {
1315 END_PROFILE(SMBfclose);
1316 return ERROR_NT(err);
1318 p++;
1319 status_len = SVAL(p,0);
1320 p += 2;
1322 if (status_len == 0) {
1323 END_PROFILE(SMBfclose);
1324 return ERROR_DOS(ERRSRV,ERRsrverror);
1327 memcpy(status,p,21);
1329 if(dptr_fetch(status+12,&dptr_num)) {
1330 /* Close the dptr - we know it's gone */
1331 dptr_close(&dptr_num);
1334 SSVAL(outbuf,smb_vwv0,0);
1336 DEBUG(3,("search close\n"));
1338 END_PROFILE(SMBfclose);
1339 return(outsize);
1342 /****************************************************************************
1343 Reply to an open.
1344 ****************************************************************************/
1346 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1348 pstring fname;
1349 int outsize = 0;
1350 uint32 fattr=0;
1351 SMB_OFF_T size = 0;
1352 time_t mtime=0;
1353 int info;
1354 SMB_STRUCT_STAT sbuf;
1355 files_struct *fsp;
1356 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1357 int deny_mode;
1358 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1359 uint32 access_mask;
1360 uint32 share_mode;
1361 uint32 create_disposition;
1362 uint32 create_options = 0;
1363 NTSTATUS status;
1364 struct smb_request req;
1366 START_PROFILE(SMBopen);
1368 init_smb_request(&req, (uint8 *)inbuf);
1370 deny_mode = SVAL(inbuf,smb_vwv0);
1372 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1373 sizeof(fname), 0, STR_TERMINATE, &status);
1374 if (!NT_STATUS_IS_OK(status)) {
1375 END_PROFILE(SMBopen);
1376 return ERROR_NT(status);
1379 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1380 if (!NT_STATUS_IS_OK(status)) {
1381 END_PROFILE(SMBopen);
1382 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1383 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1385 return ERROR_NT(status);
1388 status = unix_convert(conn, fname, False, NULL, &sbuf);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 END_PROFILE(SMBopen);
1391 return ERROR_NT(status);
1394 status = check_name(conn, fname);
1395 if (!NT_STATUS_IS_OK(status)) {
1396 END_PROFILE(SMBopen);
1397 return ERROR_NT(status);
1400 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1401 &access_mask, &share_mode, &create_disposition, &create_options)) {
1402 END_PROFILE(SMBopen);
1403 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1406 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1407 access_mask,
1408 share_mode,
1409 create_disposition,
1410 create_options,
1411 dos_attr,
1412 oplock_request,
1413 &info, &fsp);
1415 if (!NT_STATUS_IS_OK(status)) {
1416 END_PROFILE(SMBopen);
1417 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1418 /* We have re-scheduled this call. */
1419 return -1;
1421 return ERROR_NT(status);
1424 size = sbuf.st_size;
1425 fattr = dos_mode(conn,fname,&sbuf);
1426 mtime = sbuf.st_mtime;
1428 if (fattr & aDIR) {
1429 DEBUG(3,("attempt to open a directory %s\n",fname));
1430 close_file(fsp,ERROR_CLOSE);
1431 END_PROFILE(SMBopen);
1432 return ERROR_DOS(ERRDOS,ERRnoaccess);
1435 outsize = set_message(inbuf,outbuf,7,0,True);
1436 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1437 SSVAL(outbuf,smb_vwv1,fattr);
1438 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1439 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1440 } else {
1441 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1443 SIVAL(outbuf,smb_vwv4,(uint32)size);
1444 SSVAL(outbuf,smb_vwv6,deny_mode);
1446 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1447 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1450 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1451 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1453 END_PROFILE(SMBopen);
1454 return(outsize);
1457 /****************************************************************************
1458 Reply to an open and X.
1459 ****************************************************************************/
1461 void reply_open_and_X(connection_struct *conn, struct smb_request *req)
1463 pstring fname;
1464 uint16 open_flags;
1465 int deny_mode;
1466 uint32 smb_attr;
1467 /* Breakout the oplock request bits so we can set the
1468 reply bits separately. */
1469 int ex_oplock_request;
1470 int core_oplock_request;
1471 int oplock_request;
1472 #if 0
1473 int smb_sattr = SVAL(req->inbuf,smb_vwv4);
1474 uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
1475 #endif
1476 int smb_ofun;
1477 uint32 fattr=0;
1478 int mtime=0;
1479 SMB_STRUCT_STAT sbuf;
1480 int smb_action = 0;
1481 files_struct *fsp;
1482 NTSTATUS status;
1483 SMB_BIG_UINT allocation_size;
1484 ssize_t retval = -1;
1485 uint32 access_mask;
1486 uint32 share_mode;
1487 uint32 create_disposition;
1488 uint32 create_options = 0;
1490 START_PROFILE(SMBopenX);
1492 if (req->wct < 15) {
1493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1494 END_PROFILE(SMBopenX);
1495 return;
1498 open_flags = SVAL(req->inbuf,smb_vwv2);
1499 deny_mode = SVAL(req->inbuf,smb_vwv3);
1500 smb_attr = SVAL(req->inbuf,smb_vwv5);
1501 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1502 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1503 oplock_request = ex_oplock_request | core_oplock_request;
1504 smb_ofun = SVAL(req->inbuf,smb_vwv8);
1505 allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
1507 /* If it's an IPC, pass off the pipe handler. */
1508 if (IS_IPC(conn)) {
1509 if (lp_nt_pipe_support()) {
1510 reply_open_pipe_and_X(conn, req);
1511 } else {
1512 reply_doserror(req, ERRSRV, ERRaccess);
1514 END_PROFILE(SMBopenX);
1515 return;
1518 /* XXXX we need to handle passed times, sattr and flags */
1519 srvstr_get_path((char *)req->inbuf, req->flags2, fname,
1520 smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE,
1521 &status);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 reply_nterror(req, status);
1524 END_PROFILE(SMBopenX);
1525 return;
1528 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1529 fname);
1530 if (!NT_STATUS_IS_OK(status)) {
1531 END_PROFILE(SMBopenX);
1532 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1533 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1534 ERRSRV, ERRbadpath);
1535 return;
1537 reply_nterror(req, status);
1538 return;
1541 status = unix_convert(conn, fname, False, NULL, &sbuf);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 reply_nterror(req, status);
1544 END_PROFILE(SMBopenX);
1545 return;
1548 status = check_name(conn, fname);
1549 if (!NT_STATUS_IS_OK(status)) {
1550 reply_nterror(req, status);
1551 END_PROFILE(SMBopenX);
1552 return;
1555 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1556 &access_mask,
1557 &share_mode,
1558 &create_disposition,
1559 &create_options)) {
1560 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1561 END_PROFILE(SMBopenX);
1562 return;
1565 status = open_file_ntcreate(conn, req, fname, &sbuf,
1566 access_mask,
1567 share_mode,
1568 create_disposition,
1569 create_options,
1570 smb_attr,
1571 oplock_request,
1572 &smb_action, &fsp);
1574 if (!NT_STATUS_IS_OK(status)) {
1575 END_PROFILE(SMBopenX);
1576 if (open_was_deferred(req->mid)) {
1577 /* We have re-scheduled this call. */
1578 return;
1580 reply_nterror(req, status);
1581 return;
1584 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1585 if the file is truncated or created. */
1586 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1587 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1588 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1589 close_file(fsp,ERROR_CLOSE);
1590 reply_nterror(req, NT_STATUS_DISK_FULL);
1591 END_PROFILE(SMBopenX);
1592 return;
1594 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1595 if (retval < 0) {
1596 close_file(fsp,ERROR_CLOSE);
1597 reply_nterror(req, NT_STATUS_DISK_FULL);
1598 END_PROFILE(SMBopenX);
1599 return;
1601 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1604 fattr = dos_mode(conn,fname,&sbuf);
1605 mtime = sbuf.st_mtime;
1606 if (fattr & aDIR) {
1607 close_file(fsp,ERROR_CLOSE);
1608 reply_doserror(req, ERRDOS, ERRnoaccess);
1609 END_PROFILE(SMBopenX);
1610 return;
1613 /* If the caller set the extended oplock request bit
1614 and we granted one (by whatever means) - set the
1615 correct bit for extended oplock reply.
1618 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1619 smb_action |= EXTENDED_OPLOCK_GRANTED;
1622 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1623 smb_action |= EXTENDED_OPLOCK_GRANTED;
1626 /* If the caller set the core oplock request bit
1627 and we granted one (by whatever means) - set the
1628 correct bit for core oplock reply.
1631 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1632 reply_outbuf(req, 19, 0);
1633 } else {
1634 reply_outbuf(req, 15, 0);
1637 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1638 SCVAL(req->outbuf, smb_flg,
1639 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1642 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1643 SCVAL(req->outbuf, smb_flg,
1644 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1647 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1648 SSVAL(req->outbuf,smb_vwv3,fattr);
1649 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1650 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1651 } else {
1652 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1654 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1655 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1656 SSVAL(req->outbuf,smb_vwv11,smb_action);
1658 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1659 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1662 END_PROFILE(SMBopenX);
1663 chain_reply_new(req);
1664 return;
1667 /****************************************************************************
1668 Reply to a SMBulogoffX.
1669 conn POINTER CAN BE NULL HERE !
1670 ****************************************************************************/
1672 void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
1674 user_struct *vuser;
1676 START_PROFILE(SMBulogoffX);
1678 vuser = get_valid_user_struct(req->vuid);
1680 if(vuser == NULL) {
1681 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1682 req->vuid));
1685 /* in user level security we are supposed to close any files
1686 open by this user */
1687 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1688 file_close_user(req->vuid);
1691 invalidate_vuid(req->vuid);
1693 reply_outbuf(req, 2, 0);
1695 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1697 END_PROFILE(SMBulogoffX);
1698 chain_reply_new(req);
1701 /****************************************************************************
1702 Reply to a mknew or a create.
1703 ****************************************************************************/
1705 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1707 pstring fname;
1708 int com;
1709 int outsize = 0;
1710 uint32 fattr = SVAL(inbuf,smb_vwv0);
1711 struct timespec ts[2];
1712 files_struct *fsp;
1713 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1714 SMB_STRUCT_STAT sbuf;
1715 NTSTATUS status;
1716 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1717 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1718 uint32 create_disposition;
1719 uint32 create_options = 0;
1720 struct smb_request req;
1722 START_PROFILE(SMBcreate);
1724 init_smb_request(&req, (uint8 *)inbuf);
1726 com = SVAL(inbuf,smb_com);
1728 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1730 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1,
1731 sizeof(fname), 0, STR_TERMINATE, &status);
1732 if (!NT_STATUS_IS_OK(status)) {
1733 END_PROFILE(SMBcreate);
1734 return ERROR_NT(status);
1737 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1738 if (!NT_STATUS_IS_OK(status)) {
1739 END_PROFILE(SMBcreate);
1740 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1741 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1743 return ERROR_NT(status);
1746 status = unix_convert(conn, fname, False, NULL, &sbuf);
1747 if (!NT_STATUS_IS_OK(status)) {
1748 END_PROFILE(SMBcreate);
1749 return ERROR_NT(status);
1752 status = check_name(conn, fname);
1753 if (!NT_STATUS_IS_OK(status)) {
1754 END_PROFILE(SMBcreate);
1755 return ERROR_NT(status);
1758 if (fattr & aVOLID) {
1759 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1762 if(com == SMBmknew) {
1763 /* We should fail if file exists. */
1764 create_disposition = FILE_CREATE;
1765 } else {
1766 /* Create if file doesn't exist, truncate if it does. */
1767 create_disposition = FILE_OVERWRITE_IF;
1770 /* Open file using ntcreate. */
1771 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1772 access_mask,
1773 share_mode,
1774 create_disposition,
1775 create_options,
1776 fattr,
1777 oplock_request,
1778 NULL, &fsp);
1780 if (!NT_STATUS_IS_OK(status)) {
1781 END_PROFILE(SMBcreate);
1782 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1783 /* We have re-scheduled this call. */
1784 return -1;
1786 return ERROR_NT(status);
1789 ts[0] = get_atimespec(&sbuf); /* atime. */
1790 file_ntimes(conn, fname, ts);
1792 outsize = set_message(inbuf,outbuf,1,0,True);
1793 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1795 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1796 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1799 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1800 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1803 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1804 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1806 END_PROFILE(SMBcreate);
1807 return(outsize);
1810 /****************************************************************************
1811 Reply to a create temporary file.
1812 ****************************************************************************/
1814 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1816 pstring fname;
1817 int outsize = 0;
1818 uint32 fattr = SVAL(inbuf,smb_vwv0);
1819 files_struct *fsp;
1820 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1821 int tmpfd;
1822 SMB_STRUCT_STAT sbuf;
1823 char *p, *s;
1824 NTSTATUS status;
1825 unsigned int namelen;
1826 struct smb_request req;
1828 START_PROFILE(SMBctemp);
1830 init_smb_request(&req, (uint8 *)inbuf);
1832 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1833 sizeof(fname), 0, STR_TERMINATE, &status);
1834 if (!NT_STATUS_IS_OK(status)) {
1835 END_PROFILE(SMBctemp);
1836 return ERROR_NT(status);
1838 if (*fname) {
1839 pstrcat(fname,"/TMXXXXXX");
1840 } else {
1841 pstrcat(fname,"TMXXXXXX");
1844 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1845 if (!NT_STATUS_IS_OK(status)) {
1846 END_PROFILE(SMBctemp);
1847 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1848 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1850 return ERROR_NT(status);
1853 status = unix_convert(conn, fname, False, NULL, &sbuf);
1854 if (!NT_STATUS_IS_OK(status)) {
1855 END_PROFILE(SMBctemp);
1856 return ERROR_NT(status);
1859 status = check_name(conn, fname);
1860 if (!NT_STATUS_IS_OK(status)) {
1861 END_PROFILE(SMBctemp);
1862 return ERROR_NT(status);
1865 tmpfd = smb_mkstemp(fname);
1866 if (tmpfd == -1) {
1867 END_PROFILE(SMBctemp);
1868 return(UNIXERROR(ERRDOS,ERRnoaccess));
1871 SMB_VFS_STAT(conn,fname,&sbuf);
1873 /* We should fail if file does not exist. */
1874 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1875 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1876 FILE_SHARE_READ|FILE_SHARE_WRITE,
1877 FILE_OPEN,
1879 fattr,
1880 oplock_request,
1881 NULL, &fsp);
1883 /* close fd from smb_mkstemp() */
1884 close(tmpfd);
1886 if (!NT_STATUS_IS_OK(status)) {
1887 END_PROFILE(SMBctemp);
1888 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1889 /* We have re-scheduled this call. */
1890 return -1;
1892 return ERROR_NT(status);
1895 outsize = set_message(inbuf,outbuf,1,0,True);
1896 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1898 /* the returned filename is relative to the directory */
1899 s = strrchr_m(fname, '/');
1900 if (!s) {
1901 s = fname;
1902 } else {
1903 s++;
1906 p = smb_buf(outbuf);
1907 #if 0
1908 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1909 thing in the byte section. JRA */
1910 SSVALS(p, 0, -1); /* what is this? not in spec */
1911 #endif
1912 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1913 p += namelen;
1914 outsize = set_message_end(inbuf,outbuf, p);
1916 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1917 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1920 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1921 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1924 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1925 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1926 (unsigned int)sbuf.st_mode ) );
1928 END_PROFILE(SMBctemp);
1929 return(outsize);
1932 /*******************************************************************
1933 Check if a user is allowed to rename a file.
1934 ********************************************************************/
1936 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1937 uint16 dirtype, SMB_STRUCT_STAT *pst)
1939 uint32 fmode;
1941 if (!CAN_WRITE(conn)) {
1942 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1945 fmode = dos_mode(conn, fsp->fsp_name, pst);
1946 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1947 return NT_STATUS_NO_SUCH_FILE;
1950 if (S_ISDIR(pst->st_mode)) {
1951 return NT_STATUS_OK;
1954 if (fsp->access_mask & DELETE_ACCESS) {
1955 return NT_STATUS_OK;
1958 return NT_STATUS_ACCESS_DENIED;
1961 /*******************************************************************
1962 * unlink a file with all relevant access checks
1963 *******************************************************************/
1965 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
1966 char *fname, uint32 dirtype)
1968 SMB_STRUCT_STAT sbuf;
1969 uint32 fattr;
1970 files_struct *fsp;
1971 uint32 dirtype_orig = dirtype;
1972 NTSTATUS status;
1974 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
1976 if (!CAN_WRITE(conn)) {
1977 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1980 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1981 return map_nt_error_from_unix(errno);
1984 fattr = dos_mode(conn,fname,&sbuf);
1986 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1987 dirtype = aDIR|aARCH|aRONLY;
1990 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1991 if (!dirtype) {
1992 return NT_STATUS_NO_SUCH_FILE;
1995 if (!dir_check_ftype(conn, fattr, dirtype)) {
1996 if (fattr & aDIR) {
1997 return NT_STATUS_FILE_IS_A_DIRECTORY;
1999 return NT_STATUS_NO_SUCH_FILE;
2002 if (dirtype_orig & 0x8000) {
2003 /* These will never be set for POSIX. */
2004 return NT_STATUS_NO_SUCH_FILE;
2007 #if 0
2008 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2009 return NT_STATUS_FILE_IS_A_DIRECTORY;
2012 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2013 return NT_STATUS_NO_SUCH_FILE;
2016 if (dirtype & 0xFF00) {
2017 /* These will never be set for POSIX. */
2018 return NT_STATUS_NO_SUCH_FILE;
2021 dirtype &= 0xFF;
2022 if (!dirtype) {
2023 return NT_STATUS_NO_SUCH_FILE;
2026 /* Can't delete a directory. */
2027 if (fattr & aDIR) {
2028 return NT_STATUS_FILE_IS_A_DIRECTORY;
2030 #endif
2032 #if 0 /* JRATEST */
2033 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2034 return NT_STATUS_OBJECT_NAME_INVALID;
2035 #endif /* JRATEST */
2037 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2039 On a Windows share, a file with read-only dosmode can be opened with
2040 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2041 fails with NT_STATUS_CANNOT_DELETE error.
2043 This semantic causes a problem that a user can not
2044 rename a file with read-only dosmode on a Samba share
2045 from a Windows command prompt (i.e. cmd.exe, but can rename
2046 from Windows Explorer).
2049 if (!lp_delete_readonly(SNUM(conn))) {
2050 if (fattr & aRONLY) {
2051 return NT_STATUS_CANNOT_DELETE;
2055 /* On open checks the open itself will check the share mode, so
2056 don't do it here as we'll get it wrong. */
2058 status = open_file_ntcreate(conn, req, fname, &sbuf,
2059 DELETE_ACCESS,
2060 FILE_SHARE_NONE,
2061 FILE_OPEN,
2063 FILE_ATTRIBUTE_NORMAL,
2064 req != NULL ? 0 : INTERNAL_OPEN_ONLY,
2065 NULL, &fsp);
2067 if (!NT_STATUS_IS_OK(status)) {
2068 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2069 nt_errstr(status)));
2070 return status;
2073 /* The set is across all open files on this dev/inode pair. */
2074 if (!set_delete_on_close(fsp, True, &current_user.ut)) {
2075 close_file(fsp, NORMAL_CLOSE);
2076 return NT_STATUS_ACCESS_DENIED;
2079 return close_file(fsp,NORMAL_CLOSE);
2082 /****************************************************************************
2083 The guts of the unlink command, split out so it may be called by the NT SMB
2084 code.
2085 ****************************************************************************/
2087 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2088 uint32 dirtype, char *name, BOOL has_wild)
2090 pstring directory;
2091 pstring mask;
2092 char *p;
2093 int count=0;
2094 NTSTATUS status = NT_STATUS_OK;
2095 SMB_STRUCT_STAT sbuf;
2097 *directory = *mask = 0;
2099 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
2100 if (!NT_STATUS_IS_OK(status)) {
2101 return status;
2104 p = strrchr_m(name,'/');
2105 if (!p) {
2106 pstrcpy(directory,".");
2107 pstrcpy(mask,name);
2108 } else {
2109 *p = 0;
2110 pstrcpy(directory,name);
2111 pstrcpy(mask,p+1);
2115 * We should only check the mangled cache
2116 * here if unix_convert failed. This means
2117 * that the path in 'mask' doesn't exist
2118 * on the file system and so we need to look
2119 * for a possible mangle. This patch from
2120 * Tine Smukavec <valentin.smukavec@hermes.si>.
2123 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
2124 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
2126 if (!has_wild) {
2127 pstrcat(directory,"/");
2128 pstrcat(directory,mask);
2129 if (dirtype == 0) {
2130 dirtype = FILE_ATTRIBUTE_NORMAL;
2133 status = check_name(conn, directory);
2134 if (!NT_STATUS_IS_OK(status)) {
2135 return status;
2138 status = do_unlink(conn, req, directory, dirtype);
2139 if (!NT_STATUS_IS_OK(status)) {
2140 return status;
2143 count++;
2144 } else {
2145 struct smb_Dir *dir_hnd = NULL;
2146 long offset = 0;
2147 const char *dname;
2149 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2150 return NT_STATUS_OBJECT_NAME_INVALID;
2153 if (strequal(mask,"????????.???")) {
2154 pstrcpy(mask,"*");
2157 status = check_name(conn, directory);
2158 if (!NT_STATUS_IS_OK(status)) {
2159 return status;
2162 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2163 if (dir_hnd == NULL) {
2164 return map_nt_error_from_unix(errno);
2167 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2168 the pattern matches against the long name, otherwise the short name
2169 We don't implement this yet XXXX
2172 status = NT_STATUS_NO_SUCH_FILE;
2174 while ((dname = ReadDirName(dir_hnd, &offset))) {
2175 SMB_STRUCT_STAT st;
2176 pstring fname;
2177 pstrcpy(fname,dname);
2179 if (!is_visible_file(conn, directory, dname, &st, True)) {
2180 continue;
2183 /* Quick check for "." and ".." */
2184 if (fname[0] == '.') {
2185 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2186 continue;
2190 if(!mask_match(fname, mask, conn->case_sensitive)) {
2191 continue;
2194 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2196 status = check_name(conn, fname);
2197 if (!NT_STATUS_IS_OK(status)) {
2198 CloseDir(dir_hnd);
2199 return status;
2202 status = do_unlink(conn, req, fname, dirtype);
2203 if (!NT_STATUS_IS_OK(status)) {
2204 continue;
2207 count++;
2208 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2209 fname));
2211 CloseDir(dir_hnd);
2214 if (count == 0 && NT_STATUS_IS_OK(status)) {
2215 status = map_nt_error_from_unix(errno);
2218 return status;
2221 /****************************************************************************
2222 Reply to a unlink
2223 ****************************************************************************/
2225 void reply_unlink(connection_struct *conn, struct smb_request *req)
2227 pstring name;
2228 uint32 dirtype;
2229 NTSTATUS status;
2230 BOOL path_contains_wcard = False;
2232 START_PROFILE(SMBunlink);
2234 if (req->wct < 1) {
2235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2236 END_PROFILE(SMBunlink);
2237 return;
2240 dirtype = SVAL(req->inbuf,smb_vwv0);
2242 srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name,
2243 smb_buf(req->inbuf) + 1, sizeof(name), 0,
2244 STR_TERMINATE, &status, &path_contains_wcard);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 reply_nterror(req, status);
2247 END_PROFILE(SMBunlink);
2248 return;
2251 status = resolve_dfspath_wcard(conn,
2252 req->flags2 & FLAGS2_DFS_PATHNAMES,
2253 name, &path_contains_wcard);
2254 if (!NT_STATUS_IS_OK(status)) {
2255 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2256 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2257 ERRSRV, ERRbadpath);
2258 END_PROFILE(SMBunlink);
2259 return;
2261 reply_nterror(req, status);
2262 END_PROFILE(SMBunlink);
2263 return;
2266 DEBUG(3,("reply_unlink : %s\n",name));
2268 status = unlink_internals(conn, req, dirtype, name,
2269 path_contains_wcard);
2270 if (!NT_STATUS_IS_OK(status)) {
2271 if (open_was_deferred(req->mid)) {
2272 /* We have re-scheduled this call. */
2273 END_PROFILE(SMBunlink);
2274 return;
2276 reply_nterror(req, status);
2277 END_PROFILE(SMBunlink);
2278 return;
2281 reply_outbuf(req, 0, 0);
2282 END_PROFILE(SMBunlink);
2284 return;
2287 /****************************************************************************
2288 Fail for readbraw.
2289 ****************************************************************************/
2291 static void fail_readraw(void)
2293 pstring errstr;
2294 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2295 strerror(errno) );
2296 exit_server_cleanly(errstr);
2299 /****************************************************************************
2300 Fake (read/write) sendfile. Returns -1 on read or write fail.
2301 ****************************************************************************/
2303 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
2305 size_t tosend = nread;
2307 while (tosend > 0) {
2308 ssize_t ret;
2309 size_t cur_read;
2311 if (tosend > bufsize) {
2312 cur_read = bufsize;
2313 } else {
2314 cur_read = tosend;
2316 ret = read_file(fsp,buf,startpos,cur_read);
2317 if (ret == -1) {
2318 return -1;
2321 /* If we had a short read, fill with zeros. */
2322 if (ret < cur_read) {
2323 memset(buf, '\0', cur_read - ret);
2326 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2327 return -1;
2329 tosend -= cur_read;
2330 startpos += cur_read;
2333 return (ssize_t)nread;
2336 /****************************************************************************
2337 Use sendfile in readbraw.
2338 ****************************************************************************/
2340 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2341 ssize_t mincount, char *outbuf, int out_buffsize)
2343 ssize_t ret=0;
2345 #if defined(WITH_SENDFILE)
2347 * We can only use sendfile on a non-chained packet
2348 * but we can use on a non-oplocked file. tridge proved this
2349 * on a train in Germany :-). JRA.
2350 * reply_readbraw has already checked the length.
2353 if ( (chain_size == 0) && (nread > 0) &&
2354 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2355 DATA_BLOB header;
2357 _smb_setlen(outbuf,nread);
2358 header.data = (uint8 *)outbuf;
2359 header.length = 4;
2360 header.free = NULL;
2362 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2363 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2364 if (errno == ENOSYS) {
2365 goto normal_readbraw;
2369 * Special hack for broken Linux with no working sendfile. If we
2370 * return EINTR we sent the header but not the rest of the data.
2371 * Fake this up by doing read/write calls.
2373 if (errno == EINTR) {
2374 /* Ensure we don't do this again. */
2375 set_use_sendfile(SNUM(conn), False);
2376 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2378 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2379 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2380 fsp->fsp_name, strerror(errno) ));
2381 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2383 return;
2386 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2387 fsp->fsp_name, strerror(errno) ));
2388 exit_server_cleanly("send_file_readbraw sendfile failed");
2391 return;
2393 #endif
2395 normal_readbraw:
2397 if (nread > 0) {
2398 ret = read_file(fsp,outbuf+4,startpos,nread);
2399 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2400 if (ret < mincount)
2401 ret = 0;
2402 #else
2403 if (ret < nread)
2404 ret = 0;
2405 #endif
2408 _smb_setlen(outbuf,ret);
2409 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2410 fail_readraw();
2413 /****************************************************************************
2414 Reply to a readbraw (core+ protocol).
2415 ****************************************************************************/
2417 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2419 ssize_t maxcount,mincount;
2420 size_t nread = 0;
2421 SMB_OFF_T startpos;
2422 char *header = outbuf;
2423 files_struct *fsp;
2424 START_PROFILE(SMBreadbraw);
2426 if (srv_is_signing_active()) {
2427 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2431 * Special check if an oplock break has been issued
2432 * and the readraw request croses on the wire, we must
2433 * return a zero length response here.
2436 fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2438 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2440 * fsp could be NULL here so use the value from the packet. JRA.
2442 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2443 _smb_setlen(header,0);
2444 if (write_data(smbd_server_fd(),header,4) != 4)
2445 fail_readraw();
2446 END_PROFILE(SMBreadbraw);
2447 return(-1);
2450 CHECK_FSP(fsp,conn);
2452 flush_write_cache(fsp, READRAW_FLUSH);
2454 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2455 if(CVAL(inbuf,smb_wct) == 10) {
2457 * This is a large offset (64 bit) read.
2459 #ifdef LARGE_SMB_OFF_T
2461 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2463 #else /* !LARGE_SMB_OFF_T */
2466 * Ensure we haven't been sent a >32 bit offset.
2469 if(IVAL(inbuf,smb_vwv8) != 0) {
2470 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2471 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2472 _smb_setlen(header,0);
2473 if (write_data(smbd_server_fd(),header,4) != 4)
2474 fail_readraw();
2475 END_PROFILE(SMBreadbraw);
2476 return(-1);
2479 #endif /* LARGE_SMB_OFF_T */
2481 if(startpos < 0) {
2482 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2483 _smb_setlen(header,0);
2484 if (write_data(smbd_server_fd(),header,4) != 4)
2485 fail_readraw();
2486 END_PROFILE(SMBreadbraw);
2487 return(-1);
2490 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2491 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2493 /* ensure we don't overrun the packet size */
2494 maxcount = MIN(65535,maxcount);
2496 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2497 SMB_STRUCT_STAT st;
2498 SMB_OFF_T size = 0;
2500 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2501 size = st.st_size;
2504 if (startpos >= size) {
2505 nread = 0;
2506 } else {
2507 nread = MIN(maxcount,(size - startpos));
2511 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2512 if (nread < mincount)
2513 nread = 0;
2514 #endif
2516 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2517 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2519 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2521 DEBUG(5,("readbraw finished\n"));
2522 END_PROFILE(SMBreadbraw);
2523 return -1;
2526 #undef DBGC_CLASS
2527 #define DBGC_CLASS DBGC_LOCKING
2529 /****************************************************************************
2530 Reply to a lockread (core+ protocol).
2531 ****************************************************************************/
2533 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2535 ssize_t nread = -1;
2536 char *data;
2537 int outsize = 0;
2538 SMB_OFF_T startpos;
2539 size_t numtoread;
2540 NTSTATUS status;
2541 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2542 struct byte_range_lock *br_lck = NULL;
2543 START_PROFILE(SMBlockread);
2545 CHECK_FSP(fsp,conn);
2546 if (!CHECK_READ(fsp,inbuf)) {
2547 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2550 release_level_2_oplocks_on_change(fsp);
2552 numtoread = SVAL(inbuf,smb_vwv1);
2553 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2555 outsize = set_message(inbuf,outbuf,5,3,True);
2556 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2557 data = smb_buf(outbuf) + 3;
2560 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2561 * protocol request that predates the read/write lock concept.
2562 * Thus instead of asking for a read lock here we need to ask
2563 * for a write lock. JRA.
2564 * Note that the requested lock size is unaffected by max_recv.
2567 br_lck = do_lock(smbd_messaging_context(),
2568 fsp,
2569 (uint32)SVAL(inbuf,smb_pid),
2570 (SMB_BIG_UINT)numtoread,
2571 (SMB_BIG_UINT)startpos,
2572 WRITE_LOCK,
2573 WINDOWS_LOCK,
2574 False, /* Non-blocking lock. */
2575 &status,
2576 NULL);
2577 TALLOC_FREE(br_lck);
2579 if (NT_STATUS_V(status)) {
2580 END_PROFILE(SMBlockread);
2581 return ERROR_NT(status);
2585 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2588 if (numtoread > max_recv) {
2589 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2590 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2591 (unsigned int)numtoread, (unsigned int)max_recv ));
2592 numtoread = MIN(numtoread,max_recv);
2594 nread = read_file(fsp,data,startpos,numtoread);
2596 if (nread < 0) {
2597 END_PROFILE(SMBlockread);
2598 return(UNIXERROR(ERRDOS,ERRnoaccess));
2601 outsize += nread;
2602 SSVAL(outbuf,smb_vwv0,nread);
2603 SSVAL(outbuf,smb_vwv5,nread+3);
2604 SSVAL(smb_buf(outbuf),1,nread);
2606 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2607 fsp->fnum, (int)numtoread, (int)nread));
2609 END_PROFILE(SMBlockread);
2610 return(outsize);
2613 #undef DBGC_CLASS
2614 #define DBGC_CLASS DBGC_ALL
2616 /****************************************************************************
2617 Reply to a read.
2618 ****************************************************************************/
2620 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2622 size_t numtoread;
2623 ssize_t nread = 0;
2624 char *data;
2625 SMB_OFF_T startpos;
2626 int outsize = 0;
2627 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2628 START_PROFILE(SMBread);
2630 CHECK_FSP(fsp,conn);
2631 if (!CHECK_READ(fsp,inbuf)) {
2632 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2635 numtoread = SVAL(inbuf,smb_vwv1);
2636 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2638 outsize = set_message(inbuf,outbuf,5,3,True);
2639 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2641 * The requested read size cannot be greater than max_recv. JRA.
2643 if (numtoread > max_recv) {
2644 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2645 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2646 (unsigned int)numtoread, (unsigned int)max_recv ));
2647 numtoread = MIN(numtoread,max_recv);
2650 data = smb_buf(outbuf) + 3;
2652 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2653 END_PROFILE(SMBread);
2654 return ERROR_DOS(ERRDOS,ERRlock);
2657 if (numtoread > 0)
2658 nread = read_file(fsp,data,startpos,numtoread);
2660 if (nread < 0) {
2661 END_PROFILE(SMBread);
2662 return(UNIXERROR(ERRDOS,ERRnoaccess));
2665 outsize += nread;
2666 SSVAL(outbuf,smb_vwv0,nread);
2667 SSVAL(outbuf,smb_vwv5,nread+3);
2668 SCVAL(smb_buf(outbuf),0,1);
2669 SSVAL(smb_buf(outbuf),1,nread);
2671 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2672 fsp->fnum, (int)numtoread, (int)nread ) );
2674 END_PROFILE(SMBread);
2675 return(outsize);
2678 /****************************************************************************
2679 Setup readX header.
2680 ****************************************************************************/
2682 static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
2684 int outsize;
2685 char *data = smb_buf(outbuf);
2687 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2688 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2689 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2690 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2691 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2692 SCVAL(outbuf,smb_vwv0,0xFF);
2693 outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
2694 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2695 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2696 return outsize;
2699 /****************************************************************************
2700 Reply to a read and X - possibly using sendfile.
2701 ****************************************************************************/
2703 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2704 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2706 SMB_STRUCT_STAT sbuf;
2707 int outsize = 0;
2708 ssize_t nread = -1;
2709 char *data = smb_buf(outbuf);
2711 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2712 return(UNIXERROR(ERRDOS,ERRnoaccess));
2715 if (startpos > sbuf.st_size) {
2716 smb_maxcnt = 0;
2717 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
2718 smb_maxcnt = (sbuf.st_size - startpos);
2721 if (smb_maxcnt == 0) {
2722 goto normal_read;
2725 #if defined(WITH_SENDFILE)
2727 * We can only use sendfile on a non-chained packet
2728 * but we can use on a non-oplocked file. tridge proved this
2729 * on a train in Germany :-). JRA.
2732 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2733 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2734 DATA_BLOB header;
2737 * Set up the packet header before send. We
2738 * assume here the sendfile will work (get the
2739 * correct amount of data).
2742 setup_readX_header(inbuf,outbuf,smb_maxcnt);
2743 set_message(inbuf,outbuf,12,smb_maxcnt,False);
2744 header.data = (uint8 *)outbuf;
2745 header.length = data - outbuf;
2746 header.free = NULL;
2748 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2749 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2750 if (errno == ENOSYS) {
2751 goto normal_read;
2755 * Special hack for broken Linux with no working sendfile. If we
2756 * return EINTR we sent the header but not the rest of the data.
2757 * Fake this up by doing read/write calls.
2760 if (errno == EINTR) {
2761 /* Ensure we don't do this again. */
2762 set_use_sendfile(SNUM(conn), False);
2763 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2765 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2766 len_outbuf - (data-outbuf))) == -1) {
2767 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2768 fsp->fsp_name, strerror(errno) ));
2769 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2771 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2772 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2773 /* Returning -1 here means successful sendfile. */
2774 return -1;
2777 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2778 fsp->fsp_name, strerror(errno) ));
2779 exit_server_cleanly("send_file_readX sendfile failed");
2782 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2783 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2784 /* Returning -1 here means successful sendfile. */
2785 return -1;
2788 #endif
2790 normal_read:
2792 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
2793 int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
2794 /* Send out the header. */
2795 if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
2796 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2797 fsp->fsp_name, strerror(errno) ));
2798 exit_server_cleanly("send_file_readX sendfile failed");
2800 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2801 len_outbuf - (data-outbuf))) == -1) {
2802 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2803 fsp->fsp_name, strerror(errno) ));
2804 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2806 return -1;
2807 } else {
2808 nread = read_file(fsp,data,startpos,smb_maxcnt);
2810 if (nread < 0) {
2811 return(UNIXERROR(ERRDOS,ERRnoaccess));
2814 outsize = setup_readX_header(inbuf, outbuf,nread);
2816 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2817 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2819 /* Returning the number of bytes we want to send back - including header. */
2820 return outsize;
2824 /****************************************************************************
2825 Reply to a read and X.
2826 ****************************************************************************/
2828 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2830 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
2831 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2832 ssize_t nread = -1;
2833 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2834 BOOL big_readX = False;
2835 #if 0
2836 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2837 #endif
2839 START_PROFILE(SMBreadX);
2841 /* If it's an IPC, pass off the pipe handler. */
2842 if (IS_IPC(conn)) {
2843 END_PROFILE(SMBreadX);
2844 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2847 CHECK_FSP(fsp,conn);
2848 if (!CHECK_READ(fsp,inbuf)) {
2849 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2852 set_message(inbuf,outbuf,12,0,True);
2854 if (global_client_caps & CAP_LARGE_READX) {
2855 size_t upper_size = SVAL(inbuf,smb_vwv7);
2856 smb_maxcnt |= (upper_size<<16);
2857 if (upper_size > 1) {
2858 /* Can't do this on a chained packet. */
2859 if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
2860 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2862 /* We currently don't do this on signed or sealed data. */
2863 if (srv_is_signing_active() || srv_encryption_on()) {
2864 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2866 /* Is there room in the reply for this data ? */
2867 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
2868 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2870 big_readX = True;
2874 if(CVAL(inbuf,smb_wct) == 12) {
2875 #ifdef LARGE_SMB_OFF_T
2877 * This is a large offset (64 bit) read.
2879 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2881 #else /* !LARGE_SMB_OFF_T */
2884 * Ensure we haven't been sent a >32 bit offset.
2887 if(IVAL(inbuf,smb_vwv10) != 0) {
2888 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2889 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2890 END_PROFILE(SMBreadX);
2891 return ERROR_DOS(ERRDOS,ERRbadaccess);
2894 #endif /* LARGE_SMB_OFF_T */
2898 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2899 END_PROFILE(SMBreadX);
2900 return ERROR_DOS(ERRDOS,ERRlock);
2903 if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2904 END_PROFILE(SMBreadX);
2905 return -1;
2908 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2909 /* Only call chain_reply if not an error. */
2910 if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2911 nread = chain_reply(inbuf,&outbuf,length,bufsize);
2914 END_PROFILE(SMBreadX);
2915 return nread;
2918 /****************************************************************************
2919 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2920 ****************************************************************************/
2922 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2924 ssize_t nwritten=0;
2925 ssize_t total_written=0;
2926 size_t numtowrite=0;
2927 size_t tcount;
2928 SMB_OFF_T startpos;
2929 char *data=NULL;
2930 BOOL write_through;
2931 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2932 int outsize = 0;
2933 NTSTATUS status;
2934 START_PROFILE(SMBwritebraw);
2936 if (srv_is_signing_active()) {
2937 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2940 CHECK_FSP(fsp,conn);
2941 if (!CHECK_WRITE(fsp)) {
2942 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2945 tcount = IVAL(inbuf,smb_vwv1);
2946 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2947 write_through = BITSETW(inbuf+smb_vwv7,0);
2949 /* We have to deal with slightly different formats depending
2950 on whether we are using the core+ or lanman1.0 protocol */
2952 if(Protocol <= PROTOCOL_COREPLUS) {
2953 numtowrite = SVAL(smb_buf(inbuf),-2);
2954 data = smb_buf(inbuf);
2955 } else {
2956 numtowrite = SVAL(inbuf,smb_vwv10);
2957 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2960 /* force the error type */
2961 SCVAL(inbuf,smb_com,SMBwritec);
2962 SCVAL(outbuf,smb_com,SMBwritec);
2964 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2965 END_PROFILE(SMBwritebraw);
2966 return(ERROR_DOS(ERRDOS,ERRlock));
2969 if (numtowrite>0)
2970 nwritten = write_file(fsp,data,startpos,numtowrite);
2972 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2973 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2975 if (nwritten < (ssize_t)numtowrite) {
2976 END_PROFILE(SMBwritebraw);
2977 return(UNIXERROR(ERRHRD,ERRdiskfull));
2980 total_written = nwritten;
2982 /* Return a message to the redirector to tell it to send more bytes */
2983 SCVAL(outbuf,smb_com,SMBwritebraw);
2984 SSVALS(outbuf,smb_vwv0,-1);
2985 outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2986 show_msg(outbuf);
2987 if (!send_smb(smbd_server_fd(),outbuf))
2988 exit_server_cleanly("reply_writebraw: send_smb failed.");
2990 /* Now read the raw data into the buffer and write it */
2991 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2992 exit_server_cleanly("secondary writebraw failed");
2995 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2996 numtowrite = smb_len(inbuf);
2998 /* Set up outbuf to return the correct return */
2999 outsize = set_message(inbuf,outbuf,1,0,True);
3000 SCVAL(outbuf,smb_com,SMBwritec);
3002 if (numtowrite != 0) {
3004 if (numtowrite > BUFFER_SIZE) {
3005 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
3006 (unsigned int)numtowrite ));
3007 exit_server_cleanly("secondary writebraw failed");
3010 if (tcount > nwritten+numtowrite) {
3011 DEBUG(3,("Client overestimated the write %d %d %d\n",
3012 (int)tcount,(int)nwritten,(int)numtowrite));
3015 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
3016 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
3017 strerror(errno) ));
3018 exit_server_cleanly("secondary writebraw failed");
3021 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
3022 if (nwritten == -1) {
3023 END_PROFILE(SMBwritebraw);
3024 return(UNIXERROR(ERRHRD,ERRdiskfull));
3027 if (nwritten < (ssize_t)numtowrite) {
3028 SCVAL(outbuf,smb_rcls,ERRHRD);
3029 SSVAL(outbuf,smb_err,ERRdiskfull);
3032 if (nwritten > 0)
3033 total_written += nwritten;
3036 SSVAL(outbuf,smb_vwv0,total_written);
3038 status = sync_file(conn, fsp, write_through);
3039 if (!NT_STATUS_IS_OK(status)) {
3040 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3041 fsp->fsp_name, nt_errstr(status) ));
3042 END_PROFILE(SMBwritebraw);
3043 return ERROR_NT(status);
3046 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
3047 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
3049 /* we won't return a status if write through is not selected - this follows what WfWg does */
3050 END_PROFILE(SMBwritebraw);
3051 if (!write_through && total_written==tcount) {
3053 #if RABBIT_PELLET_FIX
3055 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3056 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
3058 if (!send_keepalive(smbd_server_fd()))
3059 exit_server_cleanly("reply_writebraw: send of keepalive failed");
3060 #endif
3061 return(-1);
3064 return(outsize);
3067 #undef DBGC_CLASS
3068 #define DBGC_CLASS DBGC_LOCKING
3070 /****************************************************************************
3071 Reply to a writeunlock (core+).
3072 ****************************************************************************/
3074 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
3075 int size, int dum_buffsize)
3077 ssize_t nwritten = -1;
3078 size_t numtowrite;
3079 SMB_OFF_T startpos;
3080 char *data;
3081 NTSTATUS status = NT_STATUS_OK;
3082 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3083 int outsize = 0;
3084 START_PROFILE(SMBwriteunlock);
3086 CHECK_FSP(fsp,conn);
3087 if (!CHECK_WRITE(fsp)) {
3088 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3091 numtowrite = SVAL(inbuf,smb_vwv1);
3092 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3093 data = smb_buf(inbuf) + 3;
3095 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3096 END_PROFILE(SMBwriteunlock);
3097 return ERROR_DOS(ERRDOS,ERRlock);
3100 /* The special X/Open SMB protocol handling of
3101 zero length writes is *NOT* done for
3102 this call */
3103 if(numtowrite == 0) {
3104 nwritten = 0;
3105 } else {
3106 nwritten = write_file(fsp,data,startpos,numtowrite);
3109 status = sync_file(conn, fsp, False /* write through */);
3110 if (!NT_STATUS_IS_OK(status)) {
3111 END_PROFILE(SMBwriteunlock);
3112 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3113 fsp->fsp_name, nt_errstr(status) ));
3114 return ERROR_NT(status);
3117 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3118 END_PROFILE(SMBwriteunlock);
3119 return(UNIXERROR(ERRHRD,ERRdiskfull));
3122 if (numtowrite) {
3123 status = do_unlock(smbd_messaging_context(),
3124 fsp,
3125 (uint32)SVAL(inbuf,smb_pid),
3126 (SMB_BIG_UINT)numtowrite,
3127 (SMB_BIG_UINT)startpos,
3128 WINDOWS_LOCK);
3130 if (NT_STATUS_V(status)) {
3131 END_PROFILE(SMBwriteunlock);
3132 return ERROR_NT(status);
3136 outsize = set_message(inbuf,outbuf,1,0,True);
3138 SSVAL(outbuf,smb_vwv0,nwritten);
3140 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3141 fsp->fnum, (int)numtowrite, (int)nwritten));
3143 END_PROFILE(SMBwriteunlock);
3144 return outsize;
3147 #undef DBGC_CLASS
3148 #define DBGC_CLASS DBGC_ALL
3150 /****************************************************************************
3151 Reply to a write.
3152 ****************************************************************************/
3154 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
3156 size_t numtowrite;
3157 ssize_t nwritten = -1;
3158 SMB_OFF_T startpos;
3159 char *data;
3160 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3161 int outsize = 0;
3162 NTSTATUS status;
3163 START_PROFILE(SMBwrite);
3165 /* If it's an IPC, pass off the pipe handler. */
3166 if (IS_IPC(conn)) {
3167 END_PROFILE(SMBwrite);
3168 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3171 CHECK_FSP(fsp,conn);
3172 if (!CHECK_WRITE(fsp)) {
3173 END_PROFILE(SMBwrite);
3174 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3177 numtowrite = SVAL(inbuf,smb_vwv1);
3178 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3179 data = smb_buf(inbuf) + 3;
3181 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3182 END_PROFILE(SMBwrite);
3183 return ERROR_DOS(ERRDOS,ERRlock);
3187 * X/Open SMB protocol says that if smb_vwv1 is
3188 * zero then the file size should be extended or
3189 * truncated to the size given in smb_vwv[2-3].
3192 if(numtowrite == 0) {
3194 * This is actually an allocate call, and set EOF. JRA.
3196 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3197 if (nwritten < 0) {
3198 END_PROFILE(SMBwrite);
3199 return ERROR_NT(NT_STATUS_DISK_FULL);
3201 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3202 if (nwritten < 0) {
3203 END_PROFILE(SMBwrite);
3204 return ERROR_NT(NT_STATUS_DISK_FULL);
3206 } else
3207 nwritten = write_file(fsp,data,startpos,numtowrite);
3209 status = sync_file(conn, fsp, False);
3210 if (!NT_STATUS_IS_OK(status)) {
3211 END_PROFILE(SMBwrite);
3212 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3213 fsp->fsp_name, nt_errstr(status) ));
3214 return ERROR_NT(status);
3217 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3218 END_PROFILE(SMBwrite);
3219 return(UNIXERROR(ERRHRD,ERRdiskfull));
3222 outsize = set_message(inbuf,outbuf,1,0,True);
3224 SSVAL(outbuf,smb_vwv0,nwritten);
3226 if (nwritten < (ssize_t)numtowrite) {
3227 SCVAL(outbuf,smb_rcls,ERRHRD);
3228 SSVAL(outbuf,smb_err,ERRdiskfull);
3231 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3233 END_PROFILE(SMBwrite);
3234 return(outsize);
3237 /****************************************************************************
3238 Reply to a write and X.
3239 ****************************************************************************/
3241 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3243 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
3244 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3245 size_t numtowrite = SVAL(inbuf,smb_vwv10);
3246 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3247 ssize_t nwritten = -1;
3248 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3249 unsigned int smblen = smb_len(inbuf);
3250 char *data;
3251 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3252 NTSTATUS status;
3253 START_PROFILE(SMBwriteX);
3255 /* If it's an IPC, pass off the pipe handler. */
3256 if (IS_IPC(conn)) {
3257 END_PROFILE(SMBwriteX);
3258 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3261 CHECK_FSP(fsp,conn);
3262 if (!CHECK_WRITE(fsp)) {
3263 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3266 set_message(inbuf,outbuf,6,0,True);
3268 /* Deal with possible LARGE_WRITEX */
3269 if (large_writeX) {
3270 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3273 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3274 END_PROFILE(SMBwriteX);
3275 return ERROR_DOS(ERRDOS,ERRbadmem);
3278 data = smb_base(inbuf) + smb_doff;
3280 if(CVAL(inbuf,smb_wct) == 14) {
3281 #ifdef LARGE_SMB_OFF_T
3283 * This is a large offset (64 bit) write.
3285 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3287 #else /* !LARGE_SMB_OFF_T */
3290 * Ensure we haven't been sent a >32 bit offset.
3293 if(IVAL(inbuf,smb_vwv12) != 0) {
3294 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3295 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3296 END_PROFILE(SMBwriteX);
3297 return ERROR_DOS(ERRDOS,ERRbadaccess);
3300 #endif /* LARGE_SMB_OFF_T */
3303 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3304 END_PROFILE(SMBwriteX);
3305 return ERROR_DOS(ERRDOS,ERRlock);
3308 /* X/Open SMB protocol says that, unlike SMBwrite
3309 if the length is zero then NO truncation is
3310 done, just a write of zero. To truncate a file,
3311 use SMBwrite. */
3313 if(numtowrite == 0) {
3314 nwritten = 0;
3315 } else {
3317 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3318 fsp,data,startpos,numtowrite)) {
3319 END_PROFILE(SMBwriteX);
3320 return -1;
3323 nwritten = write_file(fsp,data,startpos,numtowrite);
3326 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3327 END_PROFILE(SMBwriteX);
3328 return(UNIXERROR(ERRHRD,ERRdiskfull));
3331 SSVAL(outbuf,smb_vwv2,nwritten);
3332 if (large_writeX)
3333 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3335 if (nwritten < (ssize_t)numtowrite) {
3336 SCVAL(outbuf,smb_rcls,ERRHRD);
3337 SSVAL(outbuf,smb_err,ERRdiskfull);
3340 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3341 fsp->fnum, (int)numtowrite, (int)nwritten));
3343 status = sync_file(conn, fsp, write_through);
3344 if (!NT_STATUS_IS_OK(status)) {
3345 END_PROFILE(SMBwriteX);
3346 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3347 fsp->fsp_name, nt_errstr(status) ));
3348 return ERROR_NT(status);
3351 END_PROFILE(SMBwriteX);
3352 return chain_reply(inbuf,&outbuf,length,bufsize);
3355 /****************************************************************************
3356 Reply to a lseek.
3357 ****************************************************************************/
3359 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3361 SMB_OFF_T startpos;
3362 SMB_OFF_T res= -1;
3363 int mode,umode;
3364 int outsize = 0;
3365 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3366 START_PROFILE(SMBlseek);
3368 CHECK_FSP(fsp,conn);
3370 flush_write_cache(fsp, SEEK_FLUSH);
3372 mode = SVAL(inbuf,smb_vwv1) & 3;
3373 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3374 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3376 switch (mode) {
3377 case 0:
3378 umode = SEEK_SET;
3379 res = startpos;
3380 break;
3381 case 1:
3382 umode = SEEK_CUR;
3383 res = fsp->fh->pos + startpos;
3384 break;
3385 case 2:
3386 umode = SEEK_END;
3387 break;
3388 default:
3389 umode = SEEK_SET;
3390 res = startpos;
3391 break;
3394 if (umode == SEEK_END) {
3395 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3396 if(errno == EINVAL) {
3397 SMB_OFF_T current_pos = startpos;
3398 SMB_STRUCT_STAT sbuf;
3400 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3401 END_PROFILE(SMBlseek);
3402 return(UNIXERROR(ERRDOS,ERRnoaccess));
3405 current_pos += sbuf.st_size;
3406 if(current_pos < 0)
3407 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3411 if(res == -1) {
3412 END_PROFILE(SMBlseek);
3413 return(UNIXERROR(ERRDOS,ERRnoaccess));
3417 fsp->fh->pos = res;
3419 outsize = set_message(inbuf,outbuf,2,0,True);
3420 SIVAL(outbuf,smb_vwv0,res);
3422 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3423 fsp->fnum, (double)startpos, (double)res, mode));
3425 END_PROFILE(SMBlseek);
3426 return(outsize);
3429 /****************************************************************************
3430 Reply to a flush.
3431 ****************************************************************************/
3433 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3435 int outsize = set_message(inbuf,outbuf,0,0,False);
3436 uint16 fnum = SVAL(inbuf,smb_vwv0);
3437 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3438 START_PROFILE(SMBflush);
3440 if (fnum != 0xFFFF)
3441 CHECK_FSP(fsp,conn);
3443 if (!fsp) {
3444 file_sync_all(conn);
3445 } else {
3446 NTSTATUS status = sync_file(conn, fsp, True);
3447 if (!NT_STATUS_IS_OK(status)) {
3448 END_PROFILE(SMBflush);
3449 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3450 fsp->fsp_name, nt_errstr(status) ));
3451 return ERROR_NT(status);
3455 DEBUG(3,("flush\n"));
3456 END_PROFILE(SMBflush);
3457 return(outsize);
3460 /****************************************************************************
3461 Reply to a exit.
3462 conn POINTER CAN BE NULL HERE !
3463 ****************************************************************************/
3465 int reply_exit(connection_struct *conn,
3466 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3468 int outsize;
3469 START_PROFILE(SMBexit);
3471 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3473 outsize = set_message(inbuf,outbuf,0,0,False);
3475 DEBUG(3,("exit\n"));
3477 END_PROFILE(SMBexit);
3478 return(outsize);
3481 /****************************************************************************
3482 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3483 ****************************************************************************/
3485 void reply_close(connection_struct *conn, struct smb_request *req)
3487 NTSTATUS status = NT_STATUS_OK;
3488 files_struct *fsp = NULL;
3489 START_PROFILE(SMBclose);
3491 if (req->wct < 3) {
3492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3493 END_PROFILE(SMBclose);
3494 return;
3497 /* If it's an IPC, pass off to the pipe handler. */
3498 if (IS_IPC(conn)) {
3499 reply_pipe_close(conn, req);
3500 END_PROFILE(SMBclose);
3501 return;
3504 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3507 * We can only use CHECK_FSP if we know it's not a directory.
3510 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3511 reply_doserror(req, ERRDOS, ERRbadfid);
3512 END_PROFILE(SMBclose);
3513 return;
3516 if(fsp->is_directory) {
3518 * Special case - close NT SMB directory handle.
3520 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3521 status = close_file(fsp,NORMAL_CLOSE);
3522 } else {
3524 * Close ordinary file.
3527 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3528 fsp->fh->fd, fsp->fnum,
3529 conn->num_files_open));
3532 * Take care of any time sent in the close.
3535 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
3536 srv_make_unix_date3(
3537 req->inbuf+smb_vwv1)));
3540 * close_file() returns the unix errno if an error
3541 * was detected on close - normally this is due to
3542 * a disk full error. If not then it was probably an I/O error.
3545 status = close_file(fsp,NORMAL_CLOSE);
3548 if (!NT_STATUS_IS_OK(status)) {
3549 reply_nterror(req, status);
3550 END_PROFILE(SMBclose);
3551 return;
3554 reply_outbuf(req, 0, 0);
3555 END_PROFILE(SMBclose);
3556 return;
3559 /****************************************************************************
3560 Reply to a writeclose (Core+ protocol).
3561 ****************************************************************************/
3563 int reply_writeclose(connection_struct *conn,
3564 char *inbuf,char *outbuf, int size, int dum_buffsize)
3566 size_t numtowrite;
3567 ssize_t nwritten = -1;
3568 int outsize = 0;
3569 NTSTATUS close_status = NT_STATUS_OK;
3570 SMB_OFF_T startpos;
3571 char *data;
3572 struct timespec mtime;
3573 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3574 START_PROFILE(SMBwriteclose);
3576 CHECK_FSP(fsp,conn);
3577 if (!CHECK_WRITE(fsp)) {
3578 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3581 numtowrite = SVAL(inbuf,smb_vwv1);
3582 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3583 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3584 data = smb_buf(inbuf) + 1;
3586 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3587 END_PROFILE(SMBwriteclose);
3588 return ERROR_DOS(ERRDOS,ERRlock);
3591 nwritten = write_file(fsp,data,startpos,numtowrite);
3593 set_filetime(conn, fsp->fsp_name, mtime);
3596 * More insanity. W2K only closes the file if writelen > 0.
3597 * JRA.
3600 if (numtowrite) {
3601 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3602 fsp->fsp_name ));
3603 close_status = close_file(fsp,NORMAL_CLOSE);
3606 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3607 fsp->fnum, (int)numtowrite, (int)nwritten,
3608 conn->num_files_open));
3610 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3611 END_PROFILE(SMBwriteclose);
3612 return(UNIXERROR(ERRHRD,ERRdiskfull));
3615 if(!NT_STATUS_IS_OK(close_status)) {
3616 END_PROFILE(SMBwriteclose);
3617 return ERROR_NT(close_status);
3620 outsize = set_message(inbuf,outbuf,1,0,True);
3622 SSVAL(outbuf,smb_vwv0,nwritten);
3623 END_PROFILE(SMBwriteclose);
3624 return(outsize);
3627 #undef DBGC_CLASS
3628 #define DBGC_CLASS DBGC_LOCKING
3630 /****************************************************************************
3631 Reply to a lock.
3632 ****************************************************************************/
3634 int reply_lock(connection_struct *conn,
3635 char *inbuf,char *outbuf, int length, int dum_buffsize)
3637 int outsize = set_message(inbuf,outbuf,0,0,False);
3638 SMB_BIG_UINT count,offset;
3639 NTSTATUS status;
3640 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3641 struct byte_range_lock *br_lck = NULL;
3643 START_PROFILE(SMBlock);
3645 CHECK_FSP(fsp,conn);
3647 release_level_2_oplocks_on_change(fsp);
3649 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3650 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3652 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3653 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3655 br_lck = do_lock(smbd_messaging_context(),
3656 fsp,
3657 (uint32)SVAL(inbuf,smb_pid),
3658 count,
3659 offset,
3660 WRITE_LOCK,
3661 WINDOWS_LOCK,
3662 False, /* Non-blocking lock. */
3663 &status,
3664 NULL);
3666 TALLOC_FREE(br_lck);
3668 if (NT_STATUS_V(status)) {
3669 END_PROFILE(SMBlock);
3670 return ERROR_NT(status);
3673 END_PROFILE(SMBlock);
3674 return(outsize);
3677 /****************************************************************************
3678 Reply to a unlock.
3679 ****************************************************************************/
3681 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3682 int dum_buffsize)
3684 int outsize = set_message(inbuf,outbuf,0,0,False);
3685 SMB_BIG_UINT count,offset;
3686 NTSTATUS status;
3687 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3688 START_PROFILE(SMBunlock);
3690 CHECK_FSP(fsp,conn);
3692 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3693 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3695 status = do_unlock(smbd_messaging_context(),
3696 fsp,
3697 (uint32)SVAL(inbuf,smb_pid),
3698 count,
3699 offset,
3700 WINDOWS_LOCK);
3702 if (NT_STATUS_V(status)) {
3703 END_PROFILE(SMBunlock);
3704 return ERROR_NT(status);
3707 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3708 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3710 END_PROFILE(SMBunlock);
3711 return(outsize);
3714 #undef DBGC_CLASS
3715 #define DBGC_CLASS DBGC_ALL
3717 /****************************************************************************
3718 Reply to a tdis.
3719 conn POINTER CAN BE NULL HERE !
3720 ****************************************************************************/
3722 void reply_tdis(connection_struct *conn, struct smb_request *req)
3724 START_PROFILE(SMBtdis);
3726 if (!conn) {
3727 DEBUG(4,("Invalid connection in tdis\n"));
3728 reply_doserror(req, ERRSRV, ERRinvnid);
3729 END_PROFILE(SMBtdis);
3730 return;
3733 conn->used = False;
3735 close_cnum(conn,req->vuid);
3737 reply_outbuf(req, 0, 0);
3738 END_PROFILE(SMBtdis);
3739 return;
3742 /****************************************************************************
3743 Reply to a echo.
3744 conn POINTER CAN BE NULL HERE !
3745 ****************************************************************************/
3747 int reply_echo(connection_struct *conn,
3748 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3750 int smb_reverb = SVAL(inbuf,smb_vwv0);
3751 int seq_num;
3752 unsigned int data_len = smb_buflen(inbuf);
3753 int outsize = set_message(inbuf,outbuf,1,data_len,True);
3754 START_PROFILE(SMBecho);
3756 if (data_len > BUFFER_SIZE) {
3757 DEBUG(0,("reply_echo: data_len too large.\n"));
3758 END_PROFILE(SMBecho);
3759 return -1;
3762 /* copy any incoming data back out */
3763 if (data_len > 0)
3764 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3766 if (smb_reverb > 100) {
3767 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3768 smb_reverb = 100;
3771 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3772 SSVAL(outbuf,smb_vwv0,seq_num);
3774 smb_setlen(inbuf,outbuf,outsize - 4);
3776 show_msg(outbuf);
3777 if (!send_smb(smbd_server_fd(),outbuf))
3778 exit_server_cleanly("reply_echo: send_smb failed.");
3781 DEBUG(3,("echo %d times\n", smb_reverb));
3783 smb_echo_count++;
3785 END_PROFILE(SMBecho);
3786 return -1;
3789 /****************************************************************************
3790 Reply to a printopen.
3791 ****************************************************************************/
3793 int reply_printopen(connection_struct *conn,
3794 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3796 int outsize = 0;
3797 files_struct *fsp;
3798 NTSTATUS status;
3800 START_PROFILE(SMBsplopen);
3802 if (!CAN_PRINT(conn)) {
3803 END_PROFILE(SMBsplopen);
3804 return ERROR_DOS(ERRDOS,ERRnoaccess);
3807 /* Open for exclusive use, write only. */
3808 status = print_fsp_open(conn, NULL, &fsp);
3810 if (!NT_STATUS_IS_OK(status)) {
3811 END_PROFILE(SMBsplopen);
3812 return(ERROR_NT(status));
3815 outsize = set_message(inbuf,outbuf,1,0,True);
3816 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3818 DEBUG(3,("openprint fd=%d fnum=%d\n",
3819 fsp->fh->fd, fsp->fnum));
3821 END_PROFILE(SMBsplopen);
3822 return(outsize);
3825 /****************************************************************************
3826 Reply to a printclose.
3827 ****************************************************************************/
3829 int reply_printclose(connection_struct *conn,
3830 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3832 int outsize = set_message(inbuf,outbuf,0,0,False);
3833 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3834 NTSTATUS status;
3835 START_PROFILE(SMBsplclose);
3837 CHECK_FSP(fsp,conn);
3839 if (!CAN_PRINT(conn)) {
3840 END_PROFILE(SMBsplclose);
3841 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3844 DEBUG(3,("printclose fd=%d fnum=%d\n",
3845 fsp->fh->fd,fsp->fnum));
3847 status = close_file(fsp,NORMAL_CLOSE);
3849 if(!NT_STATUS_IS_OK(status)) {
3850 END_PROFILE(SMBsplclose);
3851 return ERROR_NT(status);
3854 END_PROFILE(SMBsplclose);
3855 return(outsize);
3858 /****************************************************************************
3859 Reply to a printqueue.
3860 ****************************************************************************/
3862 int reply_printqueue(connection_struct *conn,
3863 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3865 int outsize = set_message(inbuf,outbuf,2,3,True);
3866 int max_count = SVAL(inbuf,smb_vwv0);
3867 int start_index = SVAL(inbuf,smb_vwv1);
3868 START_PROFILE(SMBsplretq);
3870 /* we used to allow the client to get the cnum wrong, but that
3871 is really quite gross and only worked when there was only
3872 one printer - I think we should now only accept it if they
3873 get it right (tridge) */
3874 if (!CAN_PRINT(conn)) {
3875 END_PROFILE(SMBsplretq);
3876 return ERROR_DOS(ERRDOS,ERRnoaccess);
3879 SSVAL(outbuf,smb_vwv0,0);
3880 SSVAL(outbuf,smb_vwv1,0);
3881 SCVAL(smb_buf(outbuf),0,1);
3882 SSVAL(smb_buf(outbuf),1,0);
3884 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3885 start_index, max_count));
3888 print_queue_struct *queue = NULL;
3889 print_status_struct status;
3890 char *p = smb_buf(outbuf) + 3;
3891 int count = print_queue_status(SNUM(conn), &queue, &status);
3892 int num_to_get = ABS(max_count);
3893 int first = (max_count>0?start_index:start_index+max_count+1);
3894 int i;
3896 if (first >= count)
3897 num_to_get = 0;
3898 else
3899 num_to_get = MIN(num_to_get,count-first);
3902 for (i=first;i<first+num_to_get;i++) {
3903 srv_put_dos_date2(p,0,queue[i].time);
3904 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3905 SSVAL(p,5, queue[i].job);
3906 SIVAL(p,7,queue[i].size);
3907 SCVAL(p,11,0);
3908 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3909 p += 28;
3912 if (count > 0) {
3913 outsize = set_message(inbuf,outbuf,2,28*count+3,False);
3914 SSVAL(outbuf,smb_vwv0,count);
3915 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3916 SCVAL(smb_buf(outbuf),0,1);
3917 SSVAL(smb_buf(outbuf),1,28*count);
3920 SAFE_FREE(queue);
3922 DEBUG(3,("%d entries returned in queue\n",count));
3925 END_PROFILE(SMBsplretq);
3926 return(outsize);
3929 /****************************************************************************
3930 Reply to a printwrite.
3931 ****************************************************************************/
3933 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3935 int numtowrite;
3936 int outsize = set_message(inbuf,outbuf,0,0,False);
3937 char *data;
3938 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3940 START_PROFILE(SMBsplwr);
3942 if (!CAN_PRINT(conn)) {
3943 END_PROFILE(SMBsplwr);
3944 return ERROR_DOS(ERRDOS,ERRnoaccess);
3947 CHECK_FSP(fsp,conn);
3948 if (!CHECK_WRITE(fsp)) {
3949 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3952 numtowrite = SVAL(smb_buf(inbuf),1);
3953 data = smb_buf(inbuf) + 3;
3955 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3956 END_PROFILE(SMBsplwr);
3957 return(UNIXERROR(ERRHRD,ERRdiskfull));
3960 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3962 END_PROFILE(SMBsplwr);
3963 return(outsize);
3966 /****************************************************************************
3967 Reply to a mkdir.
3968 ****************************************************************************/
3970 void reply_mkdir(connection_struct *conn, struct smb_request *req)
3972 pstring directory;
3973 NTSTATUS status;
3974 SMB_STRUCT_STAT sbuf;
3976 START_PROFILE(SMBmkdir);
3978 srvstr_get_path((char *)req->inbuf, req->flags2, directory,
3979 smb_buf(req->inbuf) + 1, sizeof(directory), 0,
3980 STR_TERMINATE, &status);
3981 if (!NT_STATUS_IS_OK(status)) {
3982 reply_nterror(req, status);
3983 END_PROFILE(SMBmkdir);
3984 return;
3987 status = resolve_dfspath(conn,
3988 req->flags2 & FLAGS2_DFS_PATHNAMES,
3989 directory);
3990 if (!NT_STATUS_IS_OK(status)) {
3991 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3992 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3993 ERRSRV, ERRbadpath);
3994 END_PROFILE(SMBmkdir);
3995 return;
3997 reply_nterror(req, status);
3998 END_PROFILE(SMBmkdir);
3999 return;
4002 status = unix_convert(conn, directory, False, NULL, &sbuf);
4003 if (!NT_STATUS_IS_OK(status)) {
4004 reply_nterror(req, status);
4005 END_PROFILE(SMBmkdir);
4006 return;
4009 status = check_name(conn, directory);
4010 if (!NT_STATUS_IS_OK(status)) {
4011 reply_nterror(req, status);
4012 END_PROFILE(SMBmkdir);
4013 return;
4016 status = create_directory(conn, directory);
4018 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4020 if (!NT_STATUS_IS_OK(status)) {
4022 if (!use_nt_status()
4023 && NT_STATUS_EQUAL(status,
4024 NT_STATUS_OBJECT_NAME_COLLISION)) {
4026 * Yes, in the DOS error code case we get a
4027 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4028 * samba4 torture test.
4030 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4033 reply_nterror(req, status);
4034 END_PROFILE(SMBmkdir);
4035 return;
4038 reply_outbuf(req, 0, 0);
4040 DEBUG( 3, ( "mkdir %s\n", directory ) );
4042 END_PROFILE(SMBmkdir);
4043 return;
4046 /****************************************************************************
4047 Static function used by reply_rmdir to delete an entire directory
4048 tree recursively. Return True on ok, False on fail.
4049 ****************************************************************************/
4051 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
4053 const char *dname = NULL;
4054 BOOL ret = True;
4055 long offset = 0;
4056 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4058 if(dir_hnd == NULL)
4059 return False;
4061 while((dname = ReadDirName(dir_hnd, &offset))) {
4062 pstring fullname;
4063 SMB_STRUCT_STAT st;
4065 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4066 continue;
4068 if (!is_visible_file(conn, directory, dname, &st, False))
4069 continue;
4071 /* Construct the full name. */
4072 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4073 errno = ENOMEM;
4074 ret = False;
4075 break;
4078 pstrcpy(fullname, directory);
4079 pstrcat(fullname, "/");
4080 pstrcat(fullname, dname);
4082 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4083 ret = False;
4084 break;
4087 if(st.st_mode & S_IFDIR) {
4088 if(!recursive_rmdir(conn, fullname)) {
4089 ret = False;
4090 break;
4092 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4093 ret = False;
4094 break;
4096 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4097 ret = False;
4098 break;
4101 CloseDir(dir_hnd);
4102 return ret;
4105 /****************************************************************************
4106 The internals of the rmdir code - called elsewhere.
4107 ****************************************************************************/
4109 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4111 int ret;
4112 SMB_STRUCT_STAT st;
4114 /* Might be a symlink. */
4115 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4116 return map_nt_error_from_unix(errno);
4119 if (S_ISLNK(st.st_mode)) {
4120 /* Is what it points to a directory ? */
4121 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4122 return map_nt_error_from_unix(errno);
4124 if (!(S_ISDIR(st.st_mode))) {
4125 return NT_STATUS_NOT_A_DIRECTORY;
4127 ret = SMB_VFS_UNLINK(conn,directory);
4128 } else {
4129 ret = SMB_VFS_RMDIR(conn,directory);
4131 if (ret == 0) {
4132 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4133 FILE_NOTIFY_CHANGE_DIR_NAME,
4134 directory);
4135 return NT_STATUS_OK;
4138 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4140 * Check to see if the only thing in this directory are
4141 * vetoed files/directories. If so then delete them and
4142 * retry. If we fail to delete any of them (and we *don't*
4143 * do a recursive delete) then fail the rmdir.
4145 const char *dname;
4146 long dirpos = 0;
4147 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4149 if(dir_hnd == NULL) {
4150 errno = ENOTEMPTY;
4151 goto err;
4154 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4155 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4156 continue;
4157 if (!is_visible_file(conn, directory, dname, &st, False))
4158 continue;
4159 if(!IS_VETO_PATH(conn, dname)) {
4160 CloseDir(dir_hnd);
4161 errno = ENOTEMPTY;
4162 goto err;
4166 /* We only have veto files/directories. Recursive delete. */
4168 RewindDir(dir_hnd,&dirpos);
4169 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4170 pstring fullname;
4172 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4173 continue;
4174 if (!is_visible_file(conn, directory, dname, &st, False))
4175 continue;
4177 /* Construct the full name. */
4178 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4179 errno = ENOMEM;
4180 break;
4183 pstrcpy(fullname, directory);
4184 pstrcat(fullname, "/");
4185 pstrcat(fullname, dname);
4187 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4188 break;
4189 if(st.st_mode & S_IFDIR) {
4190 if(lp_recursive_veto_delete(SNUM(conn))) {
4191 if(!recursive_rmdir(conn, fullname))
4192 break;
4194 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4195 break;
4196 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4197 break;
4199 CloseDir(dir_hnd);
4200 /* Retry the rmdir */
4201 ret = SMB_VFS_RMDIR(conn,directory);
4204 err:
4206 if (ret != 0) {
4207 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4208 "%s\n", directory,strerror(errno)));
4209 return map_nt_error_from_unix(errno);
4212 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4213 FILE_NOTIFY_CHANGE_DIR_NAME,
4214 directory);
4216 return NT_STATUS_OK;
4219 /****************************************************************************
4220 Reply to a rmdir.
4221 ****************************************************************************/
4223 void reply_rmdir(connection_struct *conn, struct smb_request *req)
4225 pstring directory;
4226 SMB_STRUCT_STAT sbuf;
4227 NTSTATUS status;
4228 START_PROFILE(SMBrmdir);
4230 srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4231 smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4232 STR_TERMINATE, &status);
4233 if (!NT_STATUS_IS_OK(status)) {
4234 reply_nterror(req, status);
4235 END_PROFILE(SMBrmdir);
4236 return;
4239 status = resolve_dfspath(conn,
4240 req->flags2 & FLAGS2_DFS_PATHNAMES,
4241 directory);
4242 if (!NT_STATUS_IS_OK(status)) {
4243 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4244 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4245 ERRSRV, ERRbadpath);
4246 END_PROFILE(SMBrmdir);
4247 return;
4249 reply_nterror(req, status);
4250 END_PROFILE(SMBrmdir);
4251 return;
4254 status = unix_convert(conn, directory, False, NULL, &sbuf);
4255 if (!NT_STATUS_IS_OK(status)) {
4256 reply_nterror(req, status);
4257 END_PROFILE(SMBrmdir);
4258 return;
4261 status = check_name(conn, directory);
4262 if (!NT_STATUS_IS_OK(status)) {
4263 reply_nterror(req, status);
4264 END_PROFILE(SMBrmdir);
4265 return;
4268 dptr_closepath(directory, req->smbpid);
4269 status = rmdir_internals(conn, directory);
4270 if (!NT_STATUS_IS_OK(status)) {
4271 reply_nterror(req, status);
4272 END_PROFILE(SMBrmdir);
4273 return;
4276 reply_outbuf(req, 0, 0);
4278 DEBUG( 3, ( "rmdir %s\n", directory ) );
4280 END_PROFILE(SMBrmdir);
4281 return;
4284 /*******************************************************************
4285 Resolve wildcards in a filename rename.
4286 Note that name is in UNIX charset and thus potentially can be more
4287 than fstring buffer (255 bytes) especially in default UTF-8 case.
4288 Therefore, we use pstring inside and all calls should ensure that
4289 name2 is at least pstring-long (they do already)
4290 ********************************************************************/
4292 static BOOL resolve_wildcards(const char *name1, char *name2)
4294 pstring root1,root2;
4295 pstring ext1,ext2;
4296 char *p,*p2, *pname1, *pname2;
4297 int available_space, actual_space;
4299 pname1 = strrchr_m(name1,'/');
4300 pname2 = strrchr_m(name2,'/');
4302 if (!pname1 || !pname2)
4303 return(False);
4305 pstrcpy(root1,pname1);
4306 pstrcpy(root2,pname2);
4307 p = strrchr_m(root1,'.');
4308 if (p) {
4309 *p = 0;
4310 pstrcpy(ext1,p+1);
4311 } else {
4312 pstrcpy(ext1,"");
4314 p = strrchr_m(root2,'.');
4315 if (p) {
4316 *p = 0;
4317 pstrcpy(ext2,p+1);
4318 } else {
4319 pstrcpy(ext2,"");
4322 p = root1;
4323 p2 = root2;
4324 while (*p2) {
4325 if (*p2 == '?') {
4326 *p2 = *p;
4327 p2++;
4328 } else if (*p2 == '*') {
4329 pstrcpy(p2, p);
4330 break;
4331 } else {
4332 p2++;
4334 if (*p)
4335 p++;
4338 p = ext1;
4339 p2 = ext2;
4340 while (*p2) {
4341 if (*p2 == '?') {
4342 *p2 = *p;
4343 p2++;
4344 } else if (*p2 == '*') {
4345 pstrcpy(p2, p);
4346 break;
4347 } else {
4348 p2++;
4350 if (*p)
4351 p++;
4354 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4356 if (ext2[0]) {
4357 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4358 if (actual_space >= available_space - 1) {
4359 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4360 actual_space - available_space));
4362 } else {
4363 pstrcpy_base(pname2, root2, name2);
4366 return(True);
4369 /****************************************************************************
4370 Ensure open files have their names updated. Updated to notify other smbd's
4371 asynchronously.
4372 ****************************************************************************/
4374 static void rename_open_files(connection_struct *conn,
4375 struct share_mode_lock *lck,
4376 const char *newname)
4378 files_struct *fsp;
4379 BOOL did_rename = False;
4381 for(fsp = file_find_di_first(lck->id); fsp;
4382 fsp = file_find_di_next(fsp)) {
4383 /* fsp_name is a relative path under the fsp. To change this for other
4384 sharepaths we need to manipulate relative paths. */
4385 /* TODO - create the absolute path and manipulate the newname
4386 relative to the sharepath. */
4387 if (fsp->conn != conn) {
4388 continue;
4390 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4391 fsp->fnum, file_id_static_string(&fsp->file_id),
4392 fsp->fsp_name, newname ));
4393 string_set(&fsp->fsp_name, newname);
4394 did_rename = True;
4397 if (!did_rename) {
4398 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4399 file_id_static_string(&lck->id), newname ));
4402 /* Send messages to all smbd's (not ourself) that the name has changed. */
4403 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4404 newname);
4407 /****************************************************************************
4408 We need to check if the source path is a parent directory of the destination
4409 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4410 refuse the rename with a sharing violation. Under UNIX the above call can
4411 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4412 probably need to check that the client is a Windows one before disallowing
4413 this as a UNIX client (one with UNIX extensions) can know the source is a
4414 symlink and make this decision intelligently. Found by an excellent bug
4415 report from <AndyLiebman@aol.com>.
4416 ****************************************************************************/
4418 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4420 const char *psrc = src;
4421 const char *pdst = dest;
4422 size_t slen;
4424 if (psrc[0] == '.' && psrc[1] == '/') {
4425 psrc += 2;
4427 if (pdst[0] == '.' && pdst[1] == '/') {
4428 pdst += 2;
4430 if ((slen = strlen(psrc)) > strlen(pdst)) {
4431 return False;
4433 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4437 * Do the notify calls from a rename
4440 static void notify_rename(connection_struct *conn, BOOL is_dir,
4441 const char *oldpath, const char *newpath)
4443 char *olddir, *newdir;
4444 const char *oldname, *newname;
4445 uint32 mask;
4447 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4448 : FILE_NOTIFY_CHANGE_FILE_NAME;
4450 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4451 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4452 TALLOC_FREE(olddir);
4453 return;
4456 if (strcmp(olddir, newdir) == 0) {
4457 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4458 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4460 else {
4461 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4462 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4464 TALLOC_FREE(olddir);
4465 TALLOC_FREE(newdir);
4467 /* this is a strange one. w2k3 gives an additional event for
4468 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4469 files, but not directories */
4470 if (!is_dir) {
4471 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4472 FILE_NOTIFY_CHANGE_ATTRIBUTES
4473 |FILE_NOTIFY_CHANGE_CREATION,
4474 newpath);
4478 /****************************************************************************
4479 Rename an open file - given an fsp.
4480 ****************************************************************************/
4482 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4484 SMB_STRUCT_STAT sbuf, sbuf1;
4485 pstring newname_last_component;
4486 NTSTATUS status = NT_STATUS_OK;
4487 struct share_mode_lock *lck = NULL;
4488 BOOL dst_exists;
4490 ZERO_STRUCT(sbuf);
4492 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4494 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4496 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4497 return status;
4500 status = check_name(conn, newname);
4501 if (!NT_STATUS_IS_OK(status)) {
4502 return status;
4505 /* Ensure newname contains a '/' */
4506 if(strrchr_m(newname,'/') == 0) {
4507 pstring tmpstr;
4509 pstrcpy(tmpstr, "./");
4510 pstrcat(tmpstr, newname);
4511 pstrcpy(newname, tmpstr);
4515 * Check for special case with case preserving and not
4516 * case sensitive. If the old last component differs from the original
4517 * last component only by case, then we should allow
4518 * the rename (user is trying to change the case of the
4519 * filename).
4522 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4523 strequal(newname, fsp->fsp_name)) {
4524 char *p;
4525 pstring newname_modified_last_component;
4528 * Get the last component of the modified name.
4529 * Note that we guarantee that newname contains a '/'
4530 * character above.
4532 p = strrchr_m(newname,'/');
4533 pstrcpy(newname_modified_last_component,p+1);
4535 if(strcsequal(newname_modified_last_component,
4536 newname_last_component) == False) {
4538 * Replace the modified last component with
4539 * the original.
4541 pstrcpy(p+1, newname_last_component);
4546 * If the src and dest names are identical - including case,
4547 * don't do the rename, just return success.
4550 if (strcsequal(fsp->fsp_name, newname)) {
4551 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4552 newname));
4553 return NT_STATUS_OK;
4557 * Have vfs_object_exist also fill sbuf1
4559 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4561 if(!replace_if_exists && dst_exists) {
4562 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4563 fsp->fsp_name,newname));
4564 return NT_STATUS_OBJECT_NAME_COLLISION;
4567 if (dst_exists) {
4568 files_struct *dst_fsp = file_find_di_first(file_id_sbuf(&sbuf1));
4569 if (dst_fsp) {
4570 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4571 return NT_STATUS_ACCESS_DENIED;
4575 /* Ensure we have a valid stat struct for the source. */
4576 if (fsp->fh->fd != -1) {
4577 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4578 return map_nt_error_from_unix(errno);
4580 } else {
4581 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4582 return map_nt_error_from_unix(errno);
4586 status = can_rename(conn, fsp, attrs, &sbuf);
4588 if (!NT_STATUS_IS_OK(status)) {
4589 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4590 nt_errstr(status), fsp->fsp_name,newname));
4591 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4592 status = NT_STATUS_ACCESS_DENIED;
4593 return status;
4596 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4597 return NT_STATUS_ACCESS_DENIED;
4600 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4603 * We have the file open ourselves, so not being able to get the
4604 * corresponding share mode lock is a fatal error.
4607 SMB_ASSERT(lck != NULL);
4609 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4610 uint32 create_options = fsp->fh->private_options;
4612 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4613 fsp->fsp_name,newname));
4615 rename_open_files(conn, lck, newname);
4617 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4620 * A rename acts as a new file create w.r.t. allowing an initial delete
4621 * on close, probably because in Windows there is a new handle to the
4622 * new file. If initial delete on close was requested but not
4623 * originally set, we need to set it here. This is probably not 100% correct,
4624 * but will work for the CIFSFS client which in non-posix mode
4625 * depends on these semantics. JRA.
4628 set_allow_initial_delete_on_close(lck, fsp, True);
4630 if (create_options & FILE_DELETE_ON_CLOSE) {
4631 status = can_set_delete_on_close(fsp, True, 0);
4633 if (NT_STATUS_IS_OK(status)) {
4634 /* Note that here we set the *inital* delete on close flag,
4635 * not the regular one. The magic gets handled in close. */
4636 fsp->initial_delete_on_close = True;
4639 TALLOC_FREE(lck);
4640 return NT_STATUS_OK;
4643 TALLOC_FREE(lck);
4645 if (errno == ENOTDIR || errno == EISDIR) {
4646 status = NT_STATUS_OBJECT_NAME_COLLISION;
4647 } else {
4648 status = map_nt_error_from_unix(errno);
4651 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4652 nt_errstr(status), fsp->fsp_name,newname));
4654 return status;
4657 /****************************************************************************
4658 The guts of the rename command, split out so it may be called by the NT SMB
4659 code.
4660 ****************************************************************************/
4662 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
4663 pstring name,
4664 pstring newname,
4665 uint32 attrs,
4666 BOOL replace_if_exists,
4667 BOOL src_has_wild,
4668 BOOL dest_has_wild)
4670 pstring directory;
4671 pstring mask;
4672 pstring last_component_src;
4673 pstring last_component_dest;
4674 char *p;
4675 int count=0;
4676 NTSTATUS status = NT_STATUS_OK;
4677 SMB_STRUCT_STAT sbuf1, sbuf2;
4678 struct smb_Dir *dir_hnd = NULL;
4679 const char *dname;
4680 long offset = 0;
4681 pstring destname;
4683 *directory = *mask = 0;
4685 ZERO_STRUCT(sbuf1);
4686 ZERO_STRUCT(sbuf2);
4688 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4689 if (!NT_STATUS_IS_OK(status)) {
4690 return status;
4693 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4694 if (!NT_STATUS_IS_OK(status)) {
4695 return status;
4699 * Split the old name into directory and last component
4700 * strings. Note that unix_convert may have stripped off a
4701 * leading ./ from both name and newname if the rename is
4702 * at the root of the share. We need to make sure either both
4703 * name and newname contain a / character or neither of them do
4704 * as this is checked in resolve_wildcards().
4707 p = strrchr_m(name,'/');
4708 if (!p) {
4709 pstrcpy(directory,".");
4710 pstrcpy(mask,name);
4711 } else {
4712 *p = 0;
4713 pstrcpy(directory,name);
4714 pstrcpy(mask,p+1);
4715 *p = '/'; /* Replace needed for exceptional test below. */
4719 * We should only check the mangled cache
4720 * here if unix_convert failed. This means
4721 * that the path in 'mask' doesn't exist
4722 * on the file system and so we need to look
4723 * for a possible mangle. This patch from
4724 * Tine Smukavec <valentin.smukavec@hermes.si>.
4727 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4728 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4731 if (!src_has_wild) {
4732 files_struct *fsp;
4735 * No wildcards - just process the one file.
4737 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4739 /* Add a terminating '/' to the directory name. */
4740 pstrcat(directory,"/");
4741 pstrcat(directory,mask);
4743 /* Ensure newname contains a '/' also */
4744 if(strrchr_m(newname,'/') == 0) {
4745 pstring tmpstr;
4747 pstrcpy(tmpstr, "./");
4748 pstrcat(tmpstr, newname);
4749 pstrcpy(newname, tmpstr);
4752 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4753 "case_preserve = %d, short case preserve = %d, "
4754 "directory = %s, newname = %s, "
4755 "last_component_dest = %s, is_8_3 = %d\n",
4756 conn->case_sensitive, conn->case_preserve,
4757 conn->short_case_preserve, directory,
4758 newname, last_component_dest, is_short_name));
4760 /* The dest name still may have wildcards. */
4761 if (dest_has_wild) {
4762 if (!resolve_wildcards(directory,newname)) {
4763 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4764 directory,newname));
4765 return NT_STATUS_NO_MEMORY;
4769 ZERO_STRUCT(sbuf1);
4770 SMB_VFS_STAT(conn, directory, &sbuf1);
4772 status = S_ISDIR(sbuf1.st_mode) ?
4773 open_directory(conn, req, directory, &sbuf1,
4774 DELETE_ACCESS,
4775 FILE_SHARE_READ|FILE_SHARE_WRITE,
4776 FILE_OPEN, 0, 0, NULL,
4777 &fsp)
4778 : open_file_ntcreate(conn, req, directory, &sbuf1,
4779 DELETE_ACCESS,
4780 FILE_SHARE_READ|FILE_SHARE_WRITE,
4781 FILE_OPEN, 0, 0, 0, NULL,
4782 &fsp);
4784 if (!NT_STATUS_IS_OK(status)) {
4785 DEBUG(3, ("Could not open rename source %s: %s\n",
4786 directory, nt_errstr(status)));
4787 return status;
4790 status = rename_internals_fsp(conn, fsp, newname, attrs,
4791 replace_if_exists);
4793 close_file(fsp, NORMAL_CLOSE);
4795 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4796 nt_errstr(status), directory,newname));
4798 return status;
4802 * Wildcards - process each file that matches.
4804 if (strequal(mask,"????????.???")) {
4805 pstrcpy(mask,"*");
4808 status = check_name(conn, directory);
4809 if (!NT_STATUS_IS_OK(status)) {
4810 return status;
4813 dir_hnd = OpenDir(conn, directory, mask, attrs);
4814 if (dir_hnd == NULL) {
4815 return map_nt_error_from_unix(errno);
4818 status = NT_STATUS_NO_SUCH_FILE;
4820 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4821 * - gentest fix. JRA
4824 while ((dname = ReadDirName(dir_hnd, &offset))) {
4825 files_struct *fsp;
4826 pstring fname;
4827 BOOL sysdir_entry = False;
4829 pstrcpy(fname,dname);
4831 /* Quick check for "." and ".." */
4832 if (fname[0] == '.') {
4833 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4834 if (attrs & aDIR) {
4835 sysdir_entry = True;
4836 } else {
4837 continue;
4842 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4843 continue;
4846 if(!mask_match(fname, mask, conn->case_sensitive)) {
4847 continue;
4850 if (sysdir_entry) {
4851 status = NT_STATUS_OBJECT_NAME_INVALID;
4852 break;
4855 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4857 pstrcpy(destname,newname);
4859 if (!resolve_wildcards(fname,destname)) {
4860 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4861 fname, destname));
4862 continue;
4865 ZERO_STRUCT(sbuf1);
4866 SMB_VFS_STAT(conn, fname, &sbuf1);
4868 status = S_ISDIR(sbuf1.st_mode) ?
4869 open_directory(conn, req, fname, &sbuf1,
4870 DELETE_ACCESS,
4871 FILE_SHARE_READ|FILE_SHARE_WRITE,
4872 FILE_OPEN, 0, 0, NULL,
4873 &fsp)
4874 : open_file_ntcreate(conn, req, fname, &sbuf1,
4875 DELETE_ACCESS,
4876 FILE_SHARE_READ|FILE_SHARE_WRITE,
4877 FILE_OPEN, 0, 0, 0, NULL,
4878 &fsp);
4880 if (!NT_STATUS_IS_OK(status)) {
4881 DEBUG(3,("rename_internals: open_file_ntcreate "
4882 "returned %s rename %s -> %s\n",
4883 nt_errstr(status), directory, newname));
4884 break;
4887 status = rename_internals_fsp(conn, fsp, destname, attrs,
4888 replace_if_exists);
4890 close_file(fsp, NORMAL_CLOSE);
4892 if (!NT_STATUS_IS_OK(status)) {
4893 DEBUG(3, ("rename_internals_fsp returned %s for "
4894 "rename %s -> %s\n", nt_errstr(status),
4895 directory, newname));
4896 break;
4899 count++;
4901 DEBUG(3,("rename_internals: doing rename on %s -> "
4902 "%s\n",fname,destname));
4904 CloseDir(dir_hnd);
4906 if (count == 0 && NT_STATUS_IS_OK(status)) {
4907 status = map_nt_error_from_unix(errno);
4910 return status;
4913 /****************************************************************************
4914 Reply to a mv.
4915 ****************************************************************************/
4917 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4918 int dum_buffsize)
4920 int outsize = 0;
4921 pstring name;
4922 pstring newname;
4923 char *p;
4924 uint32 attrs = SVAL(inbuf,smb_vwv0);
4925 NTSTATUS status;
4926 BOOL src_has_wcard = False;
4927 BOOL dest_has_wcard = False;
4928 struct smb_request req;
4930 START_PROFILE(SMBmv);
4932 init_smb_request(&req, (uint8 *)inbuf);
4934 p = smb_buf(inbuf) + 1;
4935 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
4936 sizeof(name), 0, STR_TERMINATE, &status,
4937 &src_has_wcard);
4938 if (!NT_STATUS_IS_OK(status)) {
4939 END_PROFILE(SMBmv);
4940 return ERROR_NT(status);
4942 p++;
4943 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
4944 sizeof(newname), 0, STR_TERMINATE, &status,
4945 &dest_has_wcard);
4946 if (!NT_STATUS_IS_OK(status)) {
4947 END_PROFILE(SMBmv);
4948 return ERROR_NT(status);
4951 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
4952 if (!NT_STATUS_IS_OK(status)) {
4953 END_PROFILE(SMBmv);
4954 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4955 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4957 return ERROR_NT(status);
4960 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4961 if (!NT_STATUS_IS_OK(status)) {
4962 END_PROFILE(SMBmv);
4963 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4964 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4966 return ERROR_NT(status);
4969 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4971 status = rename_internals(conn, &req, name, newname, attrs, False,
4972 src_has_wcard, dest_has_wcard);
4973 if (!NT_STATUS_IS_OK(status)) {
4974 END_PROFILE(SMBmv);
4975 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4976 /* We have re-scheduled this call. */
4977 return -1;
4979 return ERROR_NT(status);
4982 outsize = set_message(inbuf,outbuf,0,0,False);
4984 END_PROFILE(SMBmv);
4985 return(outsize);
4988 /*******************************************************************
4989 Copy a file as part of a reply_copy.
4990 ******************************************************************/
4993 * TODO: check error codes on all callers
4996 NTSTATUS copy_file(connection_struct *conn,
4997 char *src,
4998 char *dest1,
4999 int ofun,
5000 int count,
5001 BOOL target_is_directory)
5003 SMB_STRUCT_STAT src_sbuf, sbuf2;
5004 SMB_OFF_T ret=-1;
5005 files_struct *fsp1,*fsp2;
5006 pstring dest;
5007 uint32 dosattrs;
5008 uint32 new_create_disposition;
5009 NTSTATUS status;
5011 pstrcpy(dest,dest1);
5012 if (target_is_directory) {
5013 char *p = strrchr_m(src,'/');
5014 if (p) {
5015 p++;
5016 } else {
5017 p = src;
5019 pstrcat(dest,"/");
5020 pstrcat(dest,p);
5023 if (!vfs_file_exist(conn,src,&src_sbuf)) {
5024 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5027 if (!target_is_directory && count) {
5028 new_create_disposition = FILE_OPEN;
5029 } else {
5030 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5031 NULL, NULL, &new_create_disposition, NULL)) {
5032 return NT_STATUS_INVALID_PARAMETER;
5036 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5037 FILE_GENERIC_READ,
5038 FILE_SHARE_READ|FILE_SHARE_WRITE,
5039 FILE_OPEN,
5041 FILE_ATTRIBUTE_NORMAL,
5042 INTERNAL_OPEN_ONLY,
5043 NULL, &fsp1);
5045 if (!NT_STATUS_IS_OK(status)) {
5046 return status;
5049 dosattrs = dos_mode(conn, src, &src_sbuf);
5050 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
5051 ZERO_STRUCTP(&sbuf2);
5054 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
5055 FILE_GENERIC_WRITE,
5056 FILE_SHARE_READ|FILE_SHARE_WRITE,
5057 new_create_disposition,
5059 dosattrs,
5060 INTERNAL_OPEN_ONLY,
5061 NULL, &fsp2);
5063 if (!NT_STATUS_IS_OK(status)) {
5064 close_file(fsp1,ERROR_CLOSE);
5065 return status;
5068 if ((ofun&3) == 1) {
5069 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
5070 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
5072 * Stop the copy from occurring.
5074 ret = -1;
5075 src_sbuf.st_size = 0;
5079 if (src_sbuf.st_size) {
5080 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
5083 close_file(fsp1,NORMAL_CLOSE);
5085 /* Ensure the modtime is set correctly on the destination file. */
5086 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
5089 * As we are opening fsp1 read-only we only expect
5090 * an error on close on fsp2 if we are out of space.
5091 * Thus we don't look at the error return from the
5092 * close of fsp1.
5094 status = close_file(fsp2,NORMAL_CLOSE);
5096 if (!NT_STATUS_IS_OK(status)) {
5097 return status;
5100 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
5101 return NT_STATUS_DISK_FULL;
5104 return NT_STATUS_OK;
5107 /****************************************************************************
5108 Reply to a file copy.
5109 ****************************************************************************/
5111 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5113 int outsize = 0;
5114 pstring name;
5115 pstring directory;
5116 pstring mask,newname;
5117 char *p;
5118 int count=0;
5119 int error = ERRnoaccess;
5120 int err = 0;
5121 int tid2 = SVAL(inbuf,smb_vwv0);
5122 int ofun = SVAL(inbuf,smb_vwv1);
5123 int flags = SVAL(inbuf,smb_vwv2);
5124 BOOL target_is_directory=False;
5125 BOOL source_has_wild = False;
5126 BOOL dest_has_wild = False;
5127 SMB_STRUCT_STAT sbuf1, sbuf2;
5128 NTSTATUS status;
5129 START_PROFILE(SMBcopy);
5131 *directory = *mask = 0;
5133 p = smb_buf(inbuf);
5134 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5135 sizeof(name), 0, STR_TERMINATE, &status,
5136 &source_has_wild);
5137 if (!NT_STATUS_IS_OK(status)) {
5138 END_PROFILE(SMBcopy);
5139 return ERROR_NT(status);
5141 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5142 sizeof(newname), 0, STR_TERMINATE, &status,
5143 &dest_has_wild);
5144 if (!NT_STATUS_IS_OK(status)) {
5145 END_PROFILE(SMBcopy);
5146 return ERROR_NT(status);
5149 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5151 if (tid2 != conn->cnum) {
5152 /* can't currently handle inter share copies XXXX */
5153 DEBUG(3,("Rejecting inter-share copy\n"));
5154 END_PROFILE(SMBcopy);
5155 return ERROR_DOS(ERRSRV,ERRinvdevice);
5158 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5159 if (!NT_STATUS_IS_OK(status)) {
5160 END_PROFILE(SMBcopy);
5161 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5162 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5164 return ERROR_NT(status);
5167 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5168 if (!NT_STATUS_IS_OK(status)) {
5169 END_PROFILE(SMBcopy);
5170 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5171 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5173 return ERROR_NT(status);
5176 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5177 if (!NT_STATUS_IS_OK(status)) {
5178 END_PROFILE(SMBcopy);
5179 return ERROR_NT(status);
5182 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5183 if (!NT_STATUS_IS_OK(status)) {
5184 END_PROFILE(SMBcopy);
5185 return ERROR_NT(status);
5188 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5190 if ((flags&1) && target_is_directory) {
5191 END_PROFILE(SMBcopy);
5192 return ERROR_DOS(ERRDOS,ERRbadfile);
5195 if ((flags&2) && !target_is_directory) {
5196 END_PROFILE(SMBcopy);
5197 return ERROR_DOS(ERRDOS,ERRbadpath);
5200 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5201 /* wants a tree copy! XXXX */
5202 DEBUG(3,("Rejecting tree copy\n"));
5203 END_PROFILE(SMBcopy);
5204 return ERROR_DOS(ERRSRV,ERRerror);
5207 p = strrchr_m(name,'/');
5208 if (!p) {
5209 pstrcpy(directory,"./");
5210 pstrcpy(mask,name);
5211 } else {
5212 *p = 0;
5213 pstrcpy(directory,name);
5214 pstrcpy(mask,p+1);
5218 * We should only check the mangled cache
5219 * here if unix_convert failed. This means
5220 * that the path in 'mask' doesn't exist
5221 * on the file system and so we need to look
5222 * for a possible mangle. This patch from
5223 * Tine Smukavec <valentin.smukavec@hermes.si>.
5226 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5227 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5230 if (!source_has_wild) {
5231 pstrcat(directory,"/");
5232 pstrcat(directory,mask);
5233 if (dest_has_wild) {
5234 if (!resolve_wildcards(directory,newname)) {
5235 END_PROFILE(SMBcopy);
5236 return ERROR_NT(NT_STATUS_NO_MEMORY);
5240 status = check_name(conn, directory);
5241 if (!NT_STATUS_IS_OK(status)) {
5242 return ERROR_NT(status);
5245 status = check_name(conn, newname);
5246 if (!NT_STATUS_IS_OK(status)) {
5247 return ERROR_NT(status);
5250 status = copy_file(conn,directory,newname,ofun,
5251 count,target_is_directory);
5253 if(!NT_STATUS_IS_OK(status)) {
5254 END_PROFILE(SMBcopy);
5255 return ERROR_NT(status);
5256 } else {
5257 count++;
5259 } else {
5260 struct smb_Dir *dir_hnd = NULL;
5261 const char *dname;
5262 long offset = 0;
5263 pstring destname;
5265 if (strequal(mask,"????????.???"))
5266 pstrcpy(mask,"*");
5268 status = check_name(conn, directory);
5269 if (!NT_STATUS_IS_OK(status)) {
5270 return ERROR_NT(status);
5273 dir_hnd = OpenDir(conn, directory, mask, 0);
5274 if (dir_hnd == NULL) {
5275 status = map_nt_error_from_unix(errno);
5276 return ERROR_NT(status);
5279 error = ERRbadfile;
5281 while ((dname = ReadDirName(dir_hnd, &offset))) {
5282 pstring fname;
5283 pstrcpy(fname,dname);
5285 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5286 continue;
5289 if(!mask_match(fname, mask, conn->case_sensitive)) {
5290 continue;
5293 error = ERRnoaccess;
5294 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5295 pstrcpy(destname,newname);
5296 if (!resolve_wildcards(fname,destname)) {
5297 continue;
5300 status = check_name(conn, fname);
5301 if (!NT_STATUS_IS_OK(status)) {
5302 return ERROR_NT(status);
5305 status = check_name(conn, destname);
5306 if (!NT_STATUS_IS_OK(status)) {
5307 return ERROR_NT(status);
5310 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5312 status = copy_file(conn,fname,destname,ofun,
5313 count,target_is_directory);
5314 if (NT_STATUS_IS_OK(status)) {
5315 count++;
5318 CloseDir(dir_hnd);
5321 if (count == 0) {
5322 if(err) {
5323 /* Error on close... */
5324 errno = err;
5325 END_PROFILE(SMBcopy);
5326 return(UNIXERROR(ERRHRD,ERRgeneral));
5329 END_PROFILE(SMBcopy);
5330 return ERROR_DOS(ERRDOS,error);
5333 outsize = set_message(inbuf,outbuf,1,0,True);
5334 SSVAL(outbuf,smb_vwv0,count);
5336 END_PROFILE(SMBcopy);
5337 return(outsize);
5340 /****************************************************************************
5341 Reply to a setdir.
5342 ****************************************************************************/
5344 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5346 int snum;
5347 int outsize = 0;
5348 pstring newdir;
5349 NTSTATUS status;
5351 START_PROFILE(pathworks_setdir);
5353 snum = SNUM(conn);
5354 if (!CAN_SETDIR(snum)) {
5355 END_PROFILE(pathworks_setdir);
5356 return ERROR_DOS(ERRDOS,ERRnoaccess);
5359 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
5360 smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
5361 &status);
5362 if (!NT_STATUS_IS_OK(status)) {
5363 END_PROFILE(pathworks_setdir);
5364 return ERROR_NT(status);
5367 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5368 if (!NT_STATUS_IS_OK(status)) {
5369 END_PROFILE(pathworks_setdir);
5370 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5371 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5373 return ERROR_NT(status);
5376 if (strlen(newdir) != 0) {
5377 if (!vfs_directory_exist(conn,newdir,NULL)) {
5378 END_PROFILE(pathworks_setdir);
5379 return ERROR_DOS(ERRDOS,ERRbadpath);
5381 set_conn_connectpath(conn,newdir);
5384 outsize = set_message(inbuf,outbuf,0,0,False);
5385 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5387 DEBUG(3,("setdir %s\n", newdir));
5389 END_PROFILE(pathworks_setdir);
5390 return(outsize);
5393 #undef DBGC_CLASS
5394 #define DBGC_CLASS DBGC_LOCKING
5396 /****************************************************************************
5397 Get a lock pid, dealing with large count requests.
5398 ****************************************************************************/
5400 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5402 if(!large_file_format)
5403 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5404 else
5405 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5408 /****************************************************************************
5409 Get a lock count, dealing with large count requests.
5410 ****************************************************************************/
5412 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5414 SMB_BIG_UINT count = 0;
5416 if(!large_file_format) {
5417 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5418 } else {
5420 #if defined(HAVE_LONGLONG)
5421 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5422 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5423 #else /* HAVE_LONGLONG */
5426 * NT4.x seems to be broken in that it sends large file (64 bit)
5427 * lockingX calls even if the CAP_LARGE_FILES was *not*
5428 * negotiated. For boxes without large unsigned ints truncate the
5429 * lock count by dropping the top 32 bits.
5432 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5433 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5434 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5435 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5436 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5439 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5440 #endif /* HAVE_LONGLONG */
5443 return count;
5446 #if !defined(HAVE_LONGLONG)
5447 /****************************************************************************
5448 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5449 ****************************************************************************/
5451 static uint32 map_lock_offset(uint32 high, uint32 low)
5453 unsigned int i;
5454 uint32 mask = 0;
5455 uint32 highcopy = high;
5458 * Try and find out how many significant bits there are in high.
5461 for(i = 0; highcopy; i++)
5462 highcopy >>= 1;
5465 * We use 31 bits not 32 here as POSIX
5466 * lock offsets may not be negative.
5469 mask = (~0) << (31 - i);
5471 if(low & mask)
5472 return 0; /* Fail. */
5474 high <<= (31 - i);
5476 return (high|low);
5478 #endif /* !defined(HAVE_LONGLONG) */
5480 /****************************************************************************
5481 Get a lock offset, dealing with large offset requests.
5482 ****************************************************************************/
5484 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5486 SMB_BIG_UINT offset = 0;
5488 *err = False;
5490 if(!large_file_format) {
5491 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5492 } else {
5494 #if defined(HAVE_LONGLONG)
5495 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5496 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5497 #else /* HAVE_LONGLONG */
5500 * NT4.x seems to be broken in that it sends large file (64 bit)
5501 * lockingX calls even if the CAP_LARGE_FILES was *not*
5502 * negotiated. For boxes without large unsigned ints mangle the
5503 * lock offset by mapping the top 32 bits onto the lower 32.
5506 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5507 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5508 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5509 uint32 new_low = 0;
5511 if((new_low = map_lock_offset(high, low)) == 0) {
5512 *err = True;
5513 return (SMB_BIG_UINT)-1;
5516 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5517 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5518 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5519 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5522 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5523 #endif /* HAVE_LONGLONG */
5526 return offset;
5529 /****************************************************************************
5530 Reply to a lockingX request.
5531 ****************************************************************************/
5533 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5534 int length, int bufsize)
5536 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
5537 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5538 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5539 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5540 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5541 SMB_BIG_UINT count = 0, offset = 0;
5542 uint32 lock_pid;
5543 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5544 int i;
5545 char *data;
5546 BOOL large_file_format =
5547 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5548 BOOL err;
5549 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5551 START_PROFILE(SMBlockingX);
5553 CHECK_FSP(fsp,conn);
5555 data = smb_buf(inbuf);
5557 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5558 /* we don't support these - and CANCEL_LOCK makes w2k
5559 and XP reboot so I don't really want to be
5560 compatible! (tridge) */
5561 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5564 /* Check if this is an oplock break on a file
5565 we have granted an oplock on.
5567 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5568 /* Client can insist on breaking to none. */
5569 BOOL break_to_none = (oplocklevel == 0);
5570 BOOL result;
5572 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5573 "for fnum = %d\n", (unsigned int)oplocklevel,
5574 fsp->fnum ));
5577 * Make sure we have granted an exclusive or batch oplock on
5578 * this file.
5581 if (fsp->oplock_type == 0) {
5583 /* The Samba4 nbench simulator doesn't understand
5584 the difference between break to level2 and break
5585 to none from level2 - it sends oplock break
5586 replies in both cases. Don't keep logging an error
5587 message here - just ignore it. JRA. */
5589 DEBUG(5,("reply_lockingX: Error : oplock break from "
5590 "client for fnum = %d (oplock=%d) and no "
5591 "oplock granted on this file (%s).\n",
5592 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5594 /* if this is a pure oplock break request then don't
5595 * send a reply */
5596 if (num_locks == 0 && num_ulocks == 0) {
5597 END_PROFILE(SMBlockingX);
5598 return -1;
5599 } else {
5600 END_PROFILE(SMBlockingX);
5601 return ERROR_DOS(ERRDOS,ERRlock);
5605 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5606 (break_to_none)) {
5607 result = remove_oplock(fsp);
5608 } else {
5609 result = downgrade_oplock(fsp);
5612 if (!result) {
5613 DEBUG(0, ("reply_lockingX: error in removing "
5614 "oplock on file %s\n", fsp->fsp_name));
5615 /* Hmmm. Is this panic justified? */
5616 smb_panic("internal tdb error");
5619 reply_to_oplock_break_requests(fsp);
5621 /* if this is a pure oplock break request then don't send a
5622 * reply */
5623 if (num_locks == 0 && num_ulocks == 0) {
5624 /* Sanity check - ensure a pure oplock break is not a
5625 chained request. */
5626 if(CVAL(inbuf,smb_vwv0) != 0xff)
5627 DEBUG(0,("reply_lockingX: Error : pure oplock "
5628 "break is a chained %d request !\n",
5629 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5630 END_PROFILE(SMBlockingX);
5631 return -1;
5636 * We do this check *after* we have checked this is not a oplock break
5637 * response message. JRA.
5640 release_level_2_oplocks_on_change(fsp);
5642 /* Data now points at the beginning of the list
5643 of smb_unlkrng structs */
5644 for(i = 0; i < (int)num_ulocks; i++) {
5645 lock_pid = get_lock_pid( data, i, large_file_format);
5646 count = get_lock_count( data, i, large_file_format);
5647 offset = get_lock_offset( data, i, large_file_format, &err);
5650 * There is no error code marked "stupid client bug".... :-).
5652 if(err) {
5653 END_PROFILE(SMBlockingX);
5654 return ERROR_DOS(ERRDOS,ERRnoaccess);
5657 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5658 "pid %u, file %s\n", (double)offset, (double)count,
5659 (unsigned int)lock_pid, fsp->fsp_name ));
5661 status = do_unlock(smbd_messaging_context(),
5662 fsp,
5663 lock_pid,
5664 count,
5665 offset,
5666 WINDOWS_LOCK);
5668 if (NT_STATUS_V(status)) {
5669 END_PROFILE(SMBlockingX);
5670 return ERROR_NT(status);
5674 /* Setup the timeout in seconds. */
5676 if (!lp_blocking_locks(SNUM(conn))) {
5677 lock_timeout = 0;
5680 /* Now do any requested locks */
5681 data += ((large_file_format ? 20 : 10)*num_ulocks);
5683 /* Data now points at the beginning of the list
5684 of smb_lkrng structs */
5686 for(i = 0; i < (int)num_locks; i++) {
5687 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5688 READ_LOCK:WRITE_LOCK);
5689 lock_pid = get_lock_pid( data, i, large_file_format);
5690 count = get_lock_count( data, i, large_file_format);
5691 offset = get_lock_offset( data, i, large_file_format, &err);
5694 * There is no error code marked "stupid client bug".... :-).
5696 if(err) {
5697 END_PROFILE(SMBlockingX);
5698 return ERROR_DOS(ERRDOS,ERRnoaccess);
5701 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5702 "%u, file %s timeout = %d\n", (double)offset,
5703 (double)count, (unsigned int)lock_pid,
5704 fsp->fsp_name, (int)lock_timeout ));
5706 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5707 if (lp_blocking_locks(SNUM(conn))) {
5709 /* Schedule a message to ourselves to
5710 remove the blocking lock record and
5711 return the right error. */
5713 if (!blocking_lock_cancel(fsp,
5714 lock_pid,
5715 offset,
5716 count,
5717 WINDOWS_LOCK,
5718 locktype,
5719 NT_STATUS_FILE_LOCK_CONFLICT)) {
5720 END_PROFILE(SMBlockingX);
5721 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5724 /* Remove a matching pending lock. */
5725 status = do_lock_cancel(fsp,
5726 lock_pid,
5727 count,
5728 offset,
5729 WINDOWS_LOCK);
5730 } else {
5731 BOOL blocking_lock = lock_timeout ? True : False;
5732 BOOL defer_lock = False;
5733 struct byte_range_lock *br_lck;
5734 uint32 block_smbpid;
5736 br_lck = do_lock(smbd_messaging_context(),
5737 fsp,
5738 lock_pid,
5739 count,
5740 offset,
5741 lock_type,
5742 WINDOWS_LOCK,
5743 blocking_lock,
5744 &status,
5745 &block_smbpid);
5747 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5748 /* Windows internal resolution for blocking locks seems
5749 to be about 200ms... Don't wait for less than that. JRA. */
5750 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5751 lock_timeout = lp_lock_spin_time();
5753 defer_lock = True;
5756 /* This heuristic seems to match W2K3 very well. If a
5757 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5758 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5759 far as I can tell. Replacement for do_lock_spin(). JRA. */
5761 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5762 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5763 defer_lock = True;
5764 lock_timeout = lp_lock_spin_time();
5767 if (br_lck && defer_lock) {
5769 * A blocking lock was requested. Package up
5770 * this smb into a queued request and push it
5771 * onto the blocking lock queue.
5773 if(push_blocking_lock_request(br_lck,
5774 inbuf, length,
5775 fsp,
5776 lock_timeout,
5778 lock_pid,
5779 lock_type,
5780 WINDOWS_LOCK,
5781 offset,
5782 count,
5783 block_smbpid)) {
5784 TALLOC_FREE(br_lck);
5785 END_PROFILE(SMBlockingX);
5786 return -1;
5790 TALLOC_FREE(br_lck);
5793 if (NT_STATUS_V(status)) {
5794 END_PROFILE(SMBlockingX);
5795 return ERROR_NT(status);
5799 /* If any of the above locks failed, then we must unlock
5800 all of the previous locks (X/Open spec). */
5802 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5803 (i != num_locks) &&
5804 (num_locks != 0)) {
5806 * Ensure we don't do a remove on the lock that just failed,
5807 * as under POSIX rules, if we have a lock already there, we
5808 * will delete it (and we shouldn't) .....
5810 for(i--; i >= 0; i--) {
5811 lock_pid = get_lock_pid( data, i, large_file_format);
5812 count = get_lock_count( data, i, large_file_format);
5813 offset = get_lock_offset( data, i, large_file_format,
5814 &err);
5817 * There is no error code marked "stupid client
5818 * bug".... :-).
5820 if(err) {
5821 END_PROFILE(SMBlockingX);
5822 return ERROR_DOS(ERRDOS,ERRnoaccess);
5825 do_unlock(smbd_messaging_context(),
5826 fsp,
5827 lock_pid,
5828 count,
5829 offset,
5830 WINDOWS_LOCK);
5832 END_PROFILE(SMBlockingX);
5833 return ERROR_NT(status);
5836 set_message(inbuf,outbuf,2,0,True);
5838 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5839 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5841 END_PROFILE(SMBlockingX);
5842 return chain_reply(inbuf,&outbuf,length,bufsize);
5845 #undef DBGC_CLASS
5846 #define DBGC_CLASS DBGC_ALL
5848 /****************************************************************************
5849 Reply to a SMBreadbmpx (read block multiplex) request.
5850 ****************************************************************************/
5852 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5854 ssize_t nread = -1;
5855 ssize_t total_read;
5856 char *data;
5857 SMB_OFF_T startpos;
5858 int outsize;
5859 size_t maxcount;
5860 int max_per_packet;
5861 size_t tcount;
5862 int pad;
5863 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
5864 START_PROFILE(SMBreadBmpx);
5866 /* this function doesn't seem to work - disable by default */
5867 if (!lp_readbmpx()) {
5868 END_PROFILE(SMBreadBmpx);
5869 return ERROR_DOS(ERRSRV,ERRuseSTD);
5872 outsize = set_message(inbuf,outbuf,8,0,True);
5874 CHECK_FSP(fsp,conn);
5875 if (!CHECK_READ(fsp,inbuf)) {
5876 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5879 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5880 maxcount = SVAL(inbuf,smb_vwv3);
5882 data = smb_buf(outbuf);
5883 pad = ((long)data)%4;
5884 if (pad)
5885 pad = 4 - pad;
5886 data += pad;
5888 max_per_packet = bufsize-(outsize+pad);
5889 tcount = maxcount;
5890 total_read = 0;
5892 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5893 END_PROFILE(SMBreadBmpx);
5894 return ERROR_DOS(ERRDOS,ERRlock);
5897 do {
5898 size_t N = MIN(max_per_packet,tcount-total_read);
5900 nread = read_file(fsp,data,startpos,N);
5902 if (nread <= 0)
5903 nread = 0;
5905 if (nread < (ssize_t)N)
5906 tcount = total_read + nread;
5908 set_message(inbuf,outbuf,8,nread+pad,False);
5909 SIVAL(outbuf,smb_vwv0,startpos);
5910 SSVAL(outbuf,smb_vwv2,tcount);
5911 SSVAL(outbuf,smb_vwv6,nread);
5912 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5914 show_msg(outbuf);
5915 if (!send_smb(smbd_server_fd(),outbuf))
5916 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5918 total_read += nread;
5919 startpos += nread;
5920 } while (total_read < (ssize_t)tcount);
5922 END_PROFILE(SMBreadBmpx);
5923 return(-1);
5926 /****************************************************************************
5927 Reply to a SMBsetattrE.
5928 ****************************************************************************/
5930 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5932 struct timespec ts[2];
5933 int outsize = 0;
5934 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
5935 START_PROFILE(SMBsetattrE);
5937 outsize = set_message(inbuf,outbuf,0,0,False);
5939 if(!fsp || (fsp->conn != conn)) {
5940 END_PROFILE(SMBsetattrE);
5941 return ERROR_DOS(ERRDOS,ERRbadfid);
5945 * Convert the DOS times into unix times. Ignore create
5946 * time as UNIX can't set this.
5949 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5950 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5953 * Patch from Ray Frush <frush@engr.colostate.edu>
5954 * Sometimes times are sent as zero - ignore them.
5957 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5958 /* Ignore request */
5959 if( DEBUGLVL( 3 ) ) {
5960 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5961 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5963 END_PROFILE(SMBsetattrE);
5964 return(outsize);
5965 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5966 /* set modify time = to access time if modify time was unset */
5967 ts[1] = ts[0];
5970 /* Set the date on this file */
5971 /* Should we set pending modtime here ? JRA */
5972 if(file_ntimes(conn, fsp->fsp_name, ts)) {
5973 END_PROFILE(SMBsetattrE);
5974 return ERROR_DOS(ERRDOS,ERRnoaccess);
5977 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5978 fsp->fnum,
5979 (unsigned int)ts[0].tv_sec,
5980 (unsigned int)ts[1].tv_sec));
5982 END_PROFILE(SMBsetattrE);
5983 return(outsize);
5987 /* Back from the dead for OS/2..... JRA. */
5989 /****************************************************************************
5990 Reply to a SMBwritebmpx (write block multiplex primary) request.
5991 ****************************************************************************/
5993 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5995 size_t numtowrite;
5996 ssize_t nwritten = -1;
5997 int outsize = 0;
5998 SMB_OFF_T startpos;
5999 size_t tcount;
6000 BOOL write_through;
6001 int smb_doff;
6002 char *data;
6003 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6004 NTSTATUS status;
6005 START_PROFILE(SMBwriteBmpx);
6007 CHECK_FSP(fsp,conn);
6008 if (!CHECK_WRITE(fsp)) {
6009 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6011 if (HAS_CACHED_ERROR(fsp)) {
6012 return(CACHED_ERROR(fsp));
6015 tcount = SVAL(inbuf,smb_vwv1);
6016 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
6017 write_through = BITSETW(inbuf+smb_vwv7,0);
6018 numtowrite = SVAL(inbuf,smb_vwv10);
6019 smb_doff = SVAL(inbuf,smb_vwv11);
6021 data = smb_base(inbuf) + smb_doff;
6023 /* If this fails we need to send an SMBwriteC response,
6024 not an SMBwritebmpx - set this up now so we don't forget */
6025 SCVAL(outbuf,smb_com,SMBwritec);
6027 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
6028 END_PROFILE(SMBwriteBmpx);
6029 return(ERROR_DOS(ERRDOS,ERRlock));
6032 nwritten = write_file(fsp,data,startpos,numtowrite);
6034 status = sync_file(conn, fsp, write_through);
6035 if (!NT_STATUS_IS_OK(status)) {
6036 END_PROFILE(SMBwriteBmpx);
6037 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
6038 fsp->fsp_name, nt_errstr(status) ));
6039 return ERROR_NT(status);
6042 if(nwritten < (ssize_t)numtowrite) {
6043 END_PROFILE(SMBwriteBmpx);
6044 return(UNIXERROR(ERRHRD,ERRdiskfull));
6047 /* If the maximum to be written to this file
6048 is greater than what we just wrote then set
6049 up a secondary struct to be attached to this
6050 fd, we will use this to cache error messages etc. */
6052 if((ssize_t)tcount > nwritten) {
6053 write_bmpx_struct *wbms;
6054 if(fsp->wbmpx_ptr != NULL)
6055 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
6056 else
6057 wbms = SMB_MALLOC_P(write_bmpx_struct);
6058 if(!wbms) {
6059 DEBUG(0,("Out of memory in reply_readmpx\n"));
6060 END_PROFILE(SMBwriteBmpx);
6061 return(ERROR_DOS(ERRSRV,ERRnoresource));
6063 wbms->wr_mode = write_through;
6064 wbms->wr_discard = False; /* No errors yet */
6065 wbms->wr_total_written = nwritten;
6066 wbms->wr_errclass = 0;
6067 wbms->wr_error = 0;
6068 fsp->wbmpx_ptr = wbms;
6071 /* We are returning successfully, set the message type back to
6072 SMBwritebmpx */
6073 SCVAL(outbuf,smb_com,SMBwriteBmpx);
6075 outsize = set_message(inbuf,outbuf,1,0,True);
6077 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
6079 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
6080 fsp->fnum, (int)numtowrite, (int)nwritten ) );
6082 if (write_through && tcount==nwritten) {
6083 /* We need to send both a primary and a secondary response */
6084 smb_setlen(inbuf,outbuf,outsize - 4);
6085 show_msg(outbuf);
6086 if (!send_smb(smbd_server_fd(),outbuf))
6087 exit_server_cleanly("reply_writebmpx: send_smb failed.");
6089 /* Now the secondary */
6090 outsize = set_message(inbuf,outbuf,1,0,True);
6091 SCVAL(outbuf,smb_com,SMBwritec);
6092 SSVAL(outbuf,smb_vwv0,nwritten);
6095 END_PROFILE(SMBwriteBmpx);
6096 return(outsize);
6099 /****************************************************************************
6100 Reply to a SMBwritebs (write block multiplex secondary) request.
6101 ****************************************************************************/
6103 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
6105 size_t numtowrite;
6106 ssize_t nwritten = -1;
6107 int outsize = 0;
6108 SMB_OFF_T startpos;
6109 size_t tcount;
6110 BOOL write_through;
6111 int smb_doff;
6112 char *data;
6113 write_bmpx_struct *wbms;
6114 BOOL send_response = False;
6115 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6116 NTSTATUS status;
6117 START_PROFILE(SMBwriteBs);
6119 CHECK_FSP(fsp,conn);
6120 if (!CHECK_WRITE(fsp)) {
6121 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6124 tcount = SVAL(inbuf,smb_vwv1);
6125 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6126 numtowrite = SVAL(inbuf,smb_vwv6);
6127 smb_doff = SVAL(inbuf,smb_vwv7);
6129 data = smb_base(inbuf) + smb_doff;
6131 /* We need to send an SMBwriteC response, not an SMBwritebs */
6132 SCVAL(outbuf,smb_com,SMBwritec);
6134 /* This fd should have an auxiliary struct attached,
6135 check that it does */
6136 wbms = fsp->wbmpx_ptr;
6137 if(!wbms) {
6138 END_PROFILE(SMBwriteBs);
6139 return(-1);
6142 /* If write through is set we can return errors, else we must cache them */
6143 write_through = wbms->wr_mode;
6145 /* Check for an earlier error */
6146 if(wbms->wr_discard) {
6147 END_PROFILE(SMBwriteBs);
6148 return -1; /* Just discard the packet */
6151 nwritten = write_file(fsp,data,startpos,numtowrite);
6153 status = sync_file(conn, fsp, write_through);
6155 if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6156 if(write_through) {
6157 /* We are returning an error - we can delete the aux struct */
6158 if (wbms)
6159 free((char *)wbms);
6160 fsp->wbmpx_ptr = NULL;
6161 END_PROFILE(SMBwriteBs);
6162 return(ERROR_DOS(ERRHRD,ERRdiskfull));
6164 wbms->wr_errclass = ERRHRD;
6165 wbms->wr_error = ERRdiskfull;
6166 wbms->wr_status = NT_STATUS_DISK_FULL;
6167 wbms->wr_discard = True;
6168 END_PROFILE(SMBwriteBs);
6169 return -1;
6172 /* Increment the total written, if this matches tcount
6173 we can discard the auxiliary struct (hurrah !) and return a writeC */
6174 wbms->wr_total_written += nwritten;
6175 if(wbms->wr_total_written >= tcount) {
6176 if (write_through) {
6177 outsize = set_message(inbuf,outbuf,1,0,True);
6178 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
6179 send_response = True;
6182 free((char *)wbms);
6183 fsp->wbmpx_ptr = NULL;
6186 if(send_response) {
6187 END_PROFILE(SMBwriteBs);
6188 return(outsize);
6191 END_PROFILE(SMBwriteBs);
6192 return(-1);
6195 /****************************************************************************
6196 Reply to a SMBgetattrE.
6197 ****************************************************************************/
6199 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6201 SMB_STRUCT_STAT sbuf;
6202 int outsize = 0;
6203 int mode;
6204 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6205 START_PROFILE(SMBgetattrE);
6207 outsize = set_message(inbuf,outbuf,11,0,True);
6209 if(!fsp || (fsp->conn != conn)) {
6210 END_PROFILE(SMBgetattrE);
6211 return ERROR_DOS(ERRDOS,ERRbadfid);
6214 /* Do an fstat on this file */
6215 if(fsp_stat(fsp, &sbuf)) {
6216 END_PROFILE(SMBgetattrE);
6217 return(UNIXERROR(ERRDOS,ERRnoaccess));
6220 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6223 * Convert the times into dos times. Set create
6224 * date to be last modify date as UNIX doesn't save
6225 * this.
6228 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6229 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6230 /* Should we check pending modtime here ? JRA */
6231 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6233 if (mode & aDIR) {
6234 SIVAL(outbuf,smb_vwv6,0);
6235 SIVAL(outbuf,smb_vwv8,0);
6236 } else {
6237 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6238 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6239 SIVAL(outbuf,smb_vwv8,allocation_size);
6241 SSVAL(outbuf,smb_vwv10, mode);
6243 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6245 END_PROFILE(SMBgetattrE);
6246 return(outsize);