r24071: Fix a missing END_PROFILE call
[Samba/gebeck_regimport.git] / source / smbd / reply.c
blobc347182b99457304a6c3aa32c8175c07eacf1919
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(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 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1012 int outsize = 0;
1013 SMB_BIG_UINT dfree,dsize,bsize;
1014 START_PROFILE(SMBdskattr);
1016 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1017 END_PROFILE(SMBdskattr);
1018 return(UNIXERROR(ERRHRD,ERRgeneral));
1021 outsize = set_message(inbuf,outbuf,5,0,True);
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(outbuf,smb_vwv0,dsize);
1041 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1042 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
1043 SSVAL(outbuf,smb_vwv3,dfree);
1044 } else {
1045 SSVAL(outbuf,smb_vwv0,dsize);
1046 SSVAL(outbuf,smb_vwv1,bsize/512);
1047 SSVAL(outbuf,smb_vwv2,512);
1048 SSVAL(outbuf,smb_vwv3,dfree);
1051 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1053 END_PROFILE(SMBdskattr);
1054 return(outsize);
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 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1674 uint16 vuid = SVAL(inbuf,smb_uid);
1675 user_struct *vuser = get_valid_user_struct(vuid);
1676 START_PROFILE(SMBulogoffX);
1678 if(vuser == 0)
1679 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1681 /* in user level security we are supposed to close any files
1682 open by this user */
1683 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1684 file_close_user(vuid);
1686 invalidate_vuid(vuid);
1688 set_message(inbuf,outbuf,2,0,True);
1690 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1692 END_PROFILE(SMBulogoffX);
1693 return chain_reply(inbuf,&outbuf,length,bufsize);
1696 /****************************************************************************
1697 Reply to a mknew or a create.
1698 ****************************************************************************/
1700 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1702 pstring fname;
1703 int com;
1704 int outsize = 0;
1705 uint32 fattr = SVAL(inbuf,smb_vwv0);
1706 struct timespec ts[2];
1707 files_struct *fsp;
1708 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1709 SMB_STRUCT_STAT sbuf;
1710 NTSTATUS status;
1711 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1712 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1713 uint32 create_disposition;
1714 uint32 create_options = 0;
1715 struct smb_request req;
1717 START_PROFILE(SMBcreate);
1719 init_smb_request(&req, (uint8 *)inbuf);
1721 com = SVAL(inbuf,smb_com);
1723 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1725 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1,
1726 sizeof(fname), 0, STR_TERMINATE, &status);
1727 if (!NT_STATUS_IS_OK(status)) {
1728 END_PROFILE(SMBcreate);
1729 return ERROR_NT(status);
1732 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1733 if (!NT_STATUS_IS_OK(status)) {
1734 END_PROFILE(SMBcreate);
1735 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1736 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1738 return ERROR_NT(status);
1741 status = unix_convert(conn, fname, False, NULL, &sbuf);
1742 if (!NT_STATUS_IS_OK(status)) {
1743 END_PROFILE(SMBcreate);
1744 return ERROR_NT(status);
1747 status = check_name(conn, fname);
1748 if (!NT_STATUS_IS_OK(status)) {
1749 END_PROFILE(SMBcreate);
1750 return ERROR_NT(status);
1753 if (fattr & aVOLID) {
1754 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1757 if(com == SMBmknew) {
1758 /* We should fail if file exists. */
1759 create_disposition = FILE_CREATE;
1760 } else {
1761 /* Create if file doesn't exist, truncate if it does. */
1762 create_disposition = FILE_OVERWRITE_IF;
1765 /* Open file using ntcreate. */
1766 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1767 access_mask,
1768 share_mode,
1769 create_disposition,
1770 create_options,
1771 fattr,
1772 oplock_request,
1773 NULL, &fsp);
1775 if (!NT_STATUS_IS_OK(status)) {
1776 END_PROFILE(SMBcreate);
1777 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1778 /* We have re-scheduled this call. */
1779 return -1;
1781 return ERROR_NT(status);
1784 ts[0] = get_atimespec(&sbuf); /* atime. */
1785 file_ntimes(conn, fname, ts);
1787 outsize = set_message(inbuf,outbuf,1,0,True);
1788 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1790 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1791 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1794 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1795 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1798 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1799 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1801 END_PROFILE(SMBcreate);
1802 return(outsize);
1805 /****************************************************************************
1806 Reply to a create temporary file.
1807 ****************************************************************************/
1809 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1811 pstring fname;
1812 int outsize = 0;
1813 uint32 fattr = SVAL(inbuf,smb_vwv0);
1814 files_struct *fsp;
1815 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1816 int tmpfd;
1817 SMB_STRUCT_STAT sbuf;
1818 char *p, *s;
1819 NTSTATUS status;
1820 unsigned int namelen;
1821 struct smb_request req;
1823 START_PROFILE(SMBctemp);
1825 init_smb_request(&req, (uint8 *)inbuf);
1827 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1828 sizeof(fname), 0, STR_TERMINATE, &status);
1829 if (!NT_STATUS_IS_OK(status)) {
1830 END_PROFILE(SMBctemp);
1831 return ERROR_NT(status);
1833 if (*fname) {
1834 pstrcat(fname,"/TMXXXXXX");
1835 } else {
1836 pstrcat(fname,"TMXXXXXX");
1839 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1840 if (!NT_STATUS_IS_OK(status)) {
1841 END_PROFILE(SMBctemp);
1842 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1843 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1845 return ERROR_NT(status);
1848 status = unix_convert(conn, fname, False, NULL, &sbuf);
1849 if (!NT_STATUS_IS_OK(status)) {
1850 END_PROFILE(SMBctemp);
1851 return ERROR_NT(status);
1854 status = check_name(conn, fname);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 END_PROFILE(SMBctemp);
1857 return ERROR_NT(status);
1860 tmpfd = smb_mkstemp(fname);
1861 if (tmpfd == -1) {
1862 END_PROFILE(SMBctemp);
1863 return(UNIXERROR(ERRDOS,ERRnoaccess));
1866 SMB_VFS_STAT(conn,fname,&sbuf);
1868 /* We should fail if file does not exist. */
1869 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1870 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1871 FILE_SHARE_READ|FILE_SHARE_WRITE,
1872 FILE_OPEN,
1874 fattr,
1875 oplock_request,
1876 NULL, &fsp);
1878 /* close fd from smb_mkstemp() */
1879 close(tmpfd);
1881 if (!NT_STATUS_IS_OK(status)) {
1882 END_PROFILE(SMBctemp);
1883 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1884 /* We have re-scheduled this call. */
1885 return -1;
1887 return ERROR_NT(status);
1890 outsize = set_message(inbuf,outbuf,1,0,True);
1891 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1893 /* the returned filename is relative to the directory */
1894 s = strrchr_m(fname, '/');
1895 if (!s) {
1896 s = fname;
1897 } else {
1898 s++;
1901 p = smb_buf(outbuf);
1902 #if 0
1903 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1904 thing in the byte section. JRA */
1905 SSVALS(p, 0, -1); /* what is this? not in spec */
1906 #endif
1907 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1908 p += namelen;
1909 outsize = set_message_end(inbuf,outbuf, p);
1911 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1912 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1915 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1916 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1919 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1920 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1921 (unsigned int)sbuf.st_mode ) );
1923 END_PROFILE(SMBctemp);
1924 return(outsize);
1927 /*******************************************************************
1928 Check if a user is allowed to rename a file.
1929 ********************************************************************/
1931 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1932 uint16 dirtype, SMB_STRUCT_STAT *pst)
1934 uint32 fmode;
1936 if (!CAN_WRITE(conn)) {
1937 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1940 fmode = dos_mode(conn, fsp->fsp_name, pst);
1941 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1942 return NT_STATUS_NO_SUCH_FILE;
1945 if (S_ISDIR(pst->st_mode)) {
1946 return NT_STATUS_OK;
1949 if (fsp->access_mask & DELETE_ACCESS) {
1950 return NT_STATUS_OK;
1953 return NT_STATUS_ACCESS_DENIED;
1956 /*******************************************************************
1957 * unlink a file with all relevant access checks
1958 *******************************************************************/
1960 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
1961 char *fname, uint32 dirtype)
1963 SMB_STRUCT_STAT sbuf;
1964 uint32 fattr;
1965 files_struct *fsp;
1966 uint32 dirtype_orig = dirtype;
1967 NTSTATUS status;
1969 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
1971 if (!CAN_WRITE(conn)) {
1972 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1975 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1976 return map_nt_error_from_unix(errno);
1979 fattr = dos_mode(conn,fname,&sbuf);
1981 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1982 dirtype = aDIR|aARCH|aRONLY;
1985 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1986 if (!dirtype) {
1987 return NT_STATUS_NO_SUCH_FILE;
1990 if (!dir_check_ftype(conn, fattr, dirtype)) {
1991 if (fattr & aDIR) {
1992 return NT_STATUS_FILE_IS_A_DIRECTORY;
1994 return NT_STATUS_NO_SUCH_FILE;
1997 if (dirtype_orig & 0x8000) {
1998 /* These will never be set for POSIX. */
1999 return NT_STATUS_NO_SUCH_FILE;
2002 #if 0
2003 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2004 return NT_STATUS_FILE_IS_A_DIRECTORY;
2007 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2008 return NT_STATUS_NO_SUCH_FILE;
2011 if (dirtype & 0xFF00) {
2012 /* These will never be set for POSIX. */
2013 return NT_STATUS_NO_SUCH_FILE;
2016 dirtype &= 0xFF;
2017 if (!dirtype) {
2018 return NT_STATUS_NO_SUCH_FILE;
2021 /* Can't delete a directory. */
2022 if (fattr & aDIR) {
2023 return NT_STATUS_FILE_IS_A_DIRECTORY;
2025 #endif
2027 #if 0 /* JRATEST */
2028 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2029 return NT_STATUS_OBJECT_NAME_INVALID;
2030 #endif /* JRATEST */
2032 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2034 On a Windows share, a file with read-only dosmode can be opened with
2035 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2036 fails with NT_STATUS_CANNOT_DELETE error.
2038 This semantic causes a problem that a user can not
2039 rename a file with read-only dosmode on a Samba share
2040 from a Windows command prompt (i.e. cmd.exe, but can rename
2041 from Windows Explorer).
2044 if (!lp_delete_readonly(SNUM(conn))) {
2045 if (fattr & aRONLY) {
2046 return NT_STATUS_CANNOT_DELETE;
2050 /* On open checks the open itself will check the share mode, so
2051 don't do it here as we'll get it wrong. */
2053 status = open_file_ntcreate(conn, req, fname, &sbuf,
2054 DELETE_ACCESS,
2055 FILE_SHARE_NONE,
2056 FILE_OPEN,
2058 FILE_ATTRIBUTE_NORMAL,
2059 req != NULL ? 0 : INTERNAL_OPEN_ONLY,
2060 NULL, &fsp);
2062 if (!NT_STATUS_IS_OK(status)) {
2063 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2064 nt_errstr(status)));
2065 return status;
2068 /* The set is across all open files on this dev/inode pair. */
2069 if (!set_delete_on_close(fsp, True, &current_user.ut)) {
2070 close_file(fsp, NORMAL_CLOSE);
2071 return NT_STATUS_ACCESS_DENIED;
2074 return close_file(fsp,NORMAL_CLOSE);
2077 /****************************************************************************
2078 The guts of the unlink command, split out so it may be called by the NT SMB
2079 code.
2080 ****************************************************************************/
2082 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2083 uint32 dirtype, char *name, BOOL has_wild)
2085 pstring directory;
2086 pstring mask;
2087 char *p;
2088 int count=0;
2089 NTSTATUS status = NT_STATUS_OK;
2090 SMB_STRUCT_STAT sbuf;
2092 *directory = *mask = 0;
2094 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
2095 if (!NT_STATUS_IS_OK(status)) {
2096 return status;
2099 p = strrchr_m(name,'/');
2100 if (!p) {
2101 pstrcpy(directory,".");
2102 pstrcpy(mask,name);
2103 } else {
2104 *p = 0;
2105 pstrcpy(directory,name);
2106 pstrcpy(mask,p+1);
2110 * We should only check the mangled cache
2111 * here if unix_convert failed. This means
2112 * that the path in 'mask' doesn't exist
2113 * on the file system and so we need to look
2114 * for a possible mangle. This patch from
2115 * Tine Smukavec <valentin.smukavec@hermes.si>.
2118 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
2119 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
2121 if (!has_wild) {
2122 pstrcat(directory,"/");
2123 pstrcat(directory,mask);
2124 if (dirtype == 0) {
2125 dirtype = FILE_ATTRIBUTE_NORMAL;
2128 status = check_name(conn, directory);
2129 if (!NT_STATUS_IS_OK(status)) {
2130 return status;
2133 status = do_unlink(conn, req, directory, dirtype);
2134 if (!NT_STATUS_IS_OK(status)) {
2135 return status;
2138 count++;
2139 } else {
2140 struct smb_Dir *dir_hnd = NULL;
2141 long offset = 0;
2142 const char *dname;
2144 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2145 return NT_STATUS_OBJECT_NAME_INVALID;
2148 if (strequal(mask,"????????.???")) {
2149 pstrcpy(mask,"*");
2152 status = check_name(conn, directory);
2153 if (!NT_STATUS_IS_OK(status)) {
2154 return status;
2157 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2158 if (dir_hnd == NULL) {
2159 return map_nt_error_from_unix(errno);
2162 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2163 the pattern matches against the long name, otherwise the short name
2164 We don't implement this yet XXXX
2167 status = NT_STATUS_NO_SUCH_FILE;
2169 while ((dname = ReadDirName(dir_hnd, &offset))) {
2170 SMB_STRUCT_STAT st;
2171 pstring fname;
2172 pstrcpy(fname,dname);
2174 if (!is_visible_file(conn, directory, dname, &st, True)) {
2175 continue;
2178 /* Quick check for "." and ".." */
2179 if (fname[0] == '.') {
2180 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2181 continue;
2185 if(!mask_match(fname, mask, conn->case_sensitive)) {
2186 continue;
2189 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2191 status = check_name(conn, fname);
2192 if (!NT_STATUS_IS_OK(status)) {
2193 CloseDir(dir_hnd);
2194 return status;
2197 status = do_unlink(conn, req, fname, dirtype);
2198 if (!NT_STATUS_IS_OK(status)) {
2199 continue;
2202 count++;
2203 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2204 fname));
2206 CloseDir(dir_hnd);
2209 if (count == 0 && NT_STATUS_IS_OK(status)) {
2210 status = map_nt_error_from_unix(errno);
2213 return status;
2216 /****************************************************************************
2217 Reply to a unlink
2218 ****************************************************************************/
2220 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2221 int dum_buffsize)
2223 int outsize = 0;
2224 pstring name;
2225 uint32 dirtype;
2226 NTSTATUS status;
2227 BOOL path_contains_wcard = False;
2228 struct smb_request req;
2230 START_PROFILE(SMBunlink);
2232 init_smb_request(&req, (uint8 *)inbuf);
2234 dirtype = SVAL(inbuf,smb_vwv0);
2236 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name,
2237 smb_buf(inbuf) + 1, sizeof(name), 0,
2238 STR_TERMINATE, &status, &path_contains_wcard);
2239 if (!NT_STATUS_IS_OK(status)) {
2240 END_PROFILE(SMBunlink);
2241 return ERROR_NT(status);
2244 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 END_PROFILE(SMBunlink);
2247 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2248 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
2250 return ERROR_NT(status);
2253 DEBUG(3,("reply_unlink : %s\n",name));
2255 status = unlink_internals(conn, &req, dirtype, name,
2256 path_contains_wcard);
2257 if (!NT_STATUS_IS_OK(status)) {
2258 END_PROFILE(SMBunlink);
2259 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2260 /* We have re-scheduled this call. */
2261 return -1;
2263 return ERROR_NT(status);
2266 outsize = set_message(inbuf,outbuf,0,0,False);
2268 END_PROFILE(SMBunlink);
2269 return outsize;
2272 /****************************************************************************
2273 Fail for readbraw.
2274 ****************************************************************************/
2276 static void fail_readraw(void)
2278 pstring errstr;
2279 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2280 strerror(errno) );
2281 exit_server_cleanly(errstr);
2284 /****************************************************************************
2285 Fake (read/write) sendfile. Returns -1 on read or write fail.
2286 ****************************************************************************/
2288 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
2290 size_t tosend = nread;
2292 while (tosend > 0) {
2293 ssize_t ret;
2294 size_t cur_read;
2296 if (tosend > bufsize) {
2297 cur_read = bufsize;
2298 } else {
2299 cur_read = tosend;
2301 ret = read_file(fsp,buf,startpos,cur_read);
2302 if (ret == -1) {
2303 return -1;
2306 /* If we had a short read, fill with zeros. */
2307 if (ret < cur_read) {
2308 memset(buf, '\0', cur_read - ret);
2311 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2312 return -1;
2314 tosend -= cur_read;
2315 startpos += cur_read;
2318 return (ssize_t)nread;
2321 /****************************************************************************
2322 Use sendfile in readbraw.
2323 ****************************************************************************/
2325 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2326 ssize_t mincount, char *outbuf, int out_buffsize)
2328 ssize_t ret=0;
2330 #if defined(WITH_SENDFILE)
2332 * We can only use sendfile on a non-chained packet
2333 * but we can use on a non-oplocked file. tridge proved this
2334 * on a train in Germany :-). JRA.
2335 * reply_readbraw has already checked the length.
2338 if ( (chain_size == 0) && (nread > 0) &&
2339 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2340 DATA_BLOB header;
2342 _smb_setlen(outbuf,nread);
2343 header.data = (uint8 *)outbuf;
2344 header.length = 4;
2345 header.free = NULL;
2347 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2348 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2349 if (errno == ENOSYS) {
2350 goto normal_readbraw;
2354 * Special hack for broken Linux with no working sendfile. If we
2355 * return EINTR we sent the header but not the rest of the data.
2356 * Fake this up by doing read/write calls.
2358 if (errno == EINTR) {
2359 /* Ensure we don't do this again. */
2360 set_use_sendfile(SNUM(conn), False);
2361 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2363 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2364 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2365 fsp->fsp_name, strerror(errno) ));
2366 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2368 return;
2371 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2372 fsp->fsp_name, strerror(errno) ));
2373 exit_server_cleanly("send_file_readbraw sendfile failed");
2376 return;
2378 #endif
2380 normal_readbraw:
2382 if (nread > 0) {
2383 ret = read_file(fsp,outbuf+4,startpos,nread);
2384 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2385 if (ret < mincount)
2386 ret = 0;
2387 #else
2388 if (ret < nread)
2389 ret = 0;
2390 #endif
2393 _smb_setlen(outbuf,ret);
2394 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2395 fail_readraw();
2398 /****************************************************************************
2399 Reply to a readbraw (core+ protocol).
2400 ****************************************************************************/
2402 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2404 ssize_t maxcount,mincount;
2405 size_t nread = 0;
2406 SMB_OFF_T startpos;
2407 char *header = outbuf;
2408 files_struct *fsp;
2409 START_PROFILE(SMBreadbraw);
2411 if (srv_is_signing_active()) {
2412 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2416 * Special check if an oplock break has been issued
2417 * and the readraw request croses on the wire, we must
2418 * return a zero length response here.
2421 fsp = file_fsp(inbuf,smb_vwv0);
2423 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2425 * fsp could be NULL here so use the value from the packet. JRA.
2427 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2428 _smb_setlen(header,0);
2429 if (write_data(smbd_server_fd(),header,4) != 4)
2430 fail_readraw();
2431 END_PROFILE(SMBreadbraw);
2432 return(-1);
2435 CHECK_FSP(fsp,conn);
2437 flush_write_cache(fsp, READRAW_FLUSH);
2439 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2440 if(CVAL(inbuf,smb_wct) == 10) {
2442 * This is a large offset (64 bit) read.
2444 #ifdef LARGE_SMB_OFF_T
2446 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2448 #else /* !LARGE_SMB_OFF_T */
2451 * Ensure we haven't been sent a >32 bit offset.
2454 if(IVAL(inbuf,smb_vwv8) != 0) {
2455 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2456 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2457 _smb_setlen(header,0);
2458 if (write_data(smbd_server_fd(),header,4) != 4)
2459 fail_readraw();
2460 END_PROFILE(SMBreadbraw);
2461 return(-1);
2464 #endif /* LARGE_SMB_OFF_T */
2466 if(startpos < 0) {
2467 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2468 _smb_setlen(header,0);
2469 if (write_data(smbd_server_fd(),header,4) != 4)
2470 fail_readraw();
2471 END_PROFILE(SMBreadbraw);
2472 return(-1);
2475 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2476 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2478 /* ensure we don't overrun the packet size */
2479 maxcount = MIN(65535,maxcount);
2481 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2482 SMB_STRUCT_STAT st;
2483 SMB_OFF_T size = 0;
2485 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2486 size = st.st_size;
2489 if (startpos >= size) {
2490 nread = 0;
2491 } else {
2492 nread = MIN(maxcount,(size - startpos));
2496 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2497 if (nread < mincount)
2498 nread = 0;
2499 #endif
2501 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2502 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2504 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2506 DEBUG(5,("readbraw finished\n"));
2507 END_PROFILE(SMBreadbraw);
2508 return -1;
2511 #undef DBGC_CLASS
2512 #define DBGC_CLASS DBGC_LOCKING
2514 /****************************************************************************
2515 Reply to a lockread (core+ protocol).
2516 ****************************************************************************/
2518 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2520 ssize_t nread = -1;
2521 char *data;
2522 int outsize = 0;
2523 SMB_OFF_T startpos;
2524 size_t numtoread;
2525 NTSTATUS status;
2526 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2527 struct byte_range_lock *br_lck = NULL;
2528 START_PROFILE(SMBlockread);
2530 CHECK_FSP(fsp,conn);
2531 if (!CHECK_READ(fsp,inbuf)) {
2532 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2535 release_level_2_oplocks_on_change(fsp);
2537 numtoread = SVAL(inbuf,smb_vwv1);
2538 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2540 outsize = set_message(inbuf,outbuf,5,3,True);
2541 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2542 data = smb_buf(outbuf) + 3;
2545 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2546 * protocol request that predates the read/write lock concept.
2547 * Thus instead of asking for a read lock here we need to ask
2548 * for a write lock. JRA.
2549 * Note that the requested lock size is unaffected by max_recv.
2552 br_lck = do_lock(smbd_messaging_context(),
2553 fsp,
2554 (uint32)SVAL(inbuf,smb_pid),
2555 (SMB_BIG_UINT)numtoread,
2556 (SMB_BIG_UINT)startpos,
2557 WRITE_LOCK,
2558 WINDOWS_LOCK,
2559 False, /* Non-blocking lock. */
2560 &status,
2561 NULL);
2562 TALLOC_FREE(br_lck);
2564 if (NT_STATUS_V(status)) {
2565 END_PROFILE(SMBlockread);
2566 return ERROR_NT(status);
2570 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2573 if (numtoread > max_recv) {
2574 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2575 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2576 (unsigned int)numtoread, (unsigned int)max_recv ));
2577 numtoread = MIN(numtoread,max_recv);
2579 nread = read_file(fsp,data,startpos,numtoread);
2581 if (nread < 0) {
2582 END_PROFILE(SMBlockread);
2583 return(UNIXERROR(ERRDOS,ERRnoaccess));
2586 outsize += nread;
2587 SSVAL(outbuf,smb_vwv0,nread);
2588 SSVAL(outbuf,smb_vwv5,nread+3);
2589 SSVAL(smb_buf(outbuf),1,nread);
2591 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2592 fsp->fnum, (int)numtoread, (int)nread));
2594 END_PROFILE(SMBlockread);
2595 return(outsize);
2598 #undef DBGC_CLASS
2599 #define DBGC_CLASS DBGC_ALL
2601 /****************************************************************************
2602 Reply to a read.
2603 ****************************************************************************/
2605 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2607 size_t numtoread;
2608 ssize_t nread = 0;
2609 char *data;
2610 SMB_OFF_T startpos;
2611 int outsize = 0;
2612 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2613 START_PROFILE(SMBread);
2615 CHECK_FSP(fsp,conn);
2616 if (!CHECK_READ(fsp,inbuf)) {
2617 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2620 numtoread = SVAL(inbuf,smb_vwv1);
2621 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2623 outsize = set_message(inbuf,outbuf,5,3,True);
2624 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2626 * The requested read size cannot be greater than max_recv. JRA.
2628 if (numtoread > max_recv) {
2629 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2630 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2631 (unsigned int)numtoread, (unsigned int)max_recv ));
2632 numtoread = MIN(numtoread,max_recv);
2635 data = smb_buf(outbuf) + 3;
2637 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2638 END_PROFILE(SMBread);
2639 return ERROR_DOS(ERRDOS,ERRlock);
2642 if (numtoread > 0)
2643 nread = read_file(fsp,data,startpos,numtoread);
2645 if (nread < 0) {
2646 END_PROFILE(SMBread);
2647 return(UNIXERROR(ERRDOS,ERRnoaccess));
2650 outsize += nread;
2651 SSVAL(outbuf,smb_vwv0,nread);
2652 SSVAL(outbuf,smb_vwv5,nread+3);
2653 SCVAL(smb_buf(outbuf),0,1);
2654 SSVAL(smb_buf(outbuf),1,nread);
2656 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2657 fsp->fnum, (int)numtoread, (int)nread ) );
2659 END_PROFILE(SMBread);
2660 return(outsize);
2663 /****************************************************************************
2664 Setup readX header.
2665 ****************************************************************************/
2667 static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
2669 int outsize;
2670 char *data = smb_buf(outbuf);
2672 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2673 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2674 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2675 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2676 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2677 SCVAL(outbuf,smb_vwv0,0xFF);
2678 outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
2679 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2680 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2681 return outsize;
2684 /****************************************************************************
2685 Reply to a read and X - possibly using sendfile.
2686 ****************************************************************************/
2688 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2689 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2691 SMB_STRUCT_STAT sbuf;
2692 int outsize = 0;
2693 ssize_t nread = -1;
2694 char *data = smb_buf(outbuf);
2696 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2697 return(UNIXERROR(ERRDOS,ERRnoaccess));
2700 if (startpos > sbuf.st_size) {
2701 smb_maxcnt = 0;
2702 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
2703 smb_maxcnt = (sbuf.st_size - startpos);
2706 if (smb_maxcnt == 0) {
2707 goto normal_read;
2710 #if defined(WITH_SENDFILE)
2712 * We can only use sendfile on a non-chained packet
2713 * but we can use on a non-oplocked file. tridge proved this
2714 * on a train in Germany :-). JRA.
2717 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2718 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2719 DATA_BLOB header;
2722 * Set up the packet header before send. We
2723 * assume here the sendfile will work (get the
2724 * correct amount of data).
2727 setup_readX_header(inbuf,outbuf,smb_maxcnt);
2728 set_message(inbuf,outbuf,12,smb_maxcnt,False);
2729 header.data = (uint8 *)outbuf;
2730 header.length = data - outbuf;
2731 header.free = NULL;
2733 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2734 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2735 if (errno == ENOSYS) {
2736 goto normal_read;
2740 * Special hack for broken Linux with no working sendfile. If we
2741 * return EINTR we sent the header but not the rest of the data.
2742 * Fake this up by doing read/write calls.
2745 if (errno == EINTR) {
2746 /* Ensure we don't do this again. */
2747 set_use_sendfile(SNUM(conn), False);
2748 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2750 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2751 len_outbuf - (data-outbuf))) == -1) {
2752 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2753 fsp->fsp_name, strerror(errno) ));
2754 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2756 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2757 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2758 /* Returning -1 here means successful sendfile. */
2759 return -1;
2762 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2763 fsp->fsp_name, strerror(errno) ));
2764 exit_server_cleanly("send_file_readX sendfile failed");
2767 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2768 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2769 /* Returning -1 here means successful sendfile. */
2770 return -1;
2773 #endif
2775 normal_read:
2777 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
2778 int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
2779 /* Send out the header. */
2780 if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
2781 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2782 fsp->fsp_name, strerror(errno) ));
2783 exit_server_cleanly("send_file_readX sendfile failed");
2785 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2786 len_outbuf - (data-outbuf))) == -1) {
2787 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2788 fsp->fsp_name, strerror(errno) ));
2789 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2791 return -1;
2792 } else {
2793 nread = read_file(fsp,data,startpos,smb_maxcnt);
2795 if (nread < 0) {
2796 return(UNIXERROR(ERRDOS,ERRnoaccess));
2799 outsize = setup_readX_header(inbuf, outbuf,nread);
2801 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2802 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2804 /* Returning the number of bytes we want to send back - including header. */
2805 return outsize;
2809 /****************************************************************************
2810 Reply to a read and X.
2811 ****************************************************************************/
2813 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2815 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2816 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2817 ssize_t nread = -1;
2818 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2819 BOOL big_readX = False;
2820 #if 0
2821 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2822 #endif
2824 START_PROFILE(SMBreadX);
2826 /* If it's an IPC, pass off the pipe handler. */
2827 if (IS_IPC(conn)) {
2828 END_PROFILE(SMBreadX);
2829 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2832 CHECK_FSP(fsp,conn);
2833 if (!CHECK_READ(fsp,inbuf)) {
2834 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2837 set_message(inbuf,outbuf,12,0,True);
2839 if (global_client_caps & CAP_LARGE_READX) {
2840 size_t upper_size = SVAL(inbuf,smb_vwv7);
2841 smb_maxcnt |= (upper_size<<16);
2842 if (upper_size > 1) {
2843 /* Can't do this on a chained packet. */
2844 if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
2845 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2847 /* We currently don't do this on signed or sealed data. */
2848 if (srv_is_signing_active() || srv_encryption_on()) {
2849 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2851 /* Is there room in the reply for this data ? */
2852 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
2853 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2855 big_readX = True;
2859 if(CVAL(inbuf,smb_wct) == 12) {
2860 #ifdef LARGE_SMB_OFF_T
2862 * This is a large offset (64 bit) read.
2864 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2866 #else /* !LARGE_SMB_OFF_T */
2869 * Ensure we haven't been sent a >32 bit offset.
2872 if(IVAL(inbuf,smb_vwv10) != 0) {
2873 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2874 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2875 END_PROFILE(SMBreadX);
2876 return ERROR_DOS(ERRDOS,ERRbadaccess);
2879 #endif /* LARGE_SMB_OFF_T */
2883 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2884 END_PROFILE(SMBreadX);
2885 return ERROR_DOS(ERRDOS,ERRlock);
2888 if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2889 END_PROFILE(SMBreadX);
2890 return -1;
2893 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2894 /* Only call chain_reply if not an error. */
2895 if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2896 nread = chain_reply(inbuf,&outbuf,length,bufsize);
2899 END_PROFILE(SMBreadX);
2900 return nread;
2903 /****************************************************************************
2904 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2905 ****************************************************************************/
2907 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2909 ssize_t nwritten=0;
2910 ssize_t total_written=0;
2911 size_t numtowrite=0;
2912 size_t tcount;
2913 SMB_OFF_T startpos;
2914 char *data=NULL;
2915 BOOL write_through;
2916 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2917 int outsize = 0;
2918 NTSTATUS status;
2919 START_PROFILE(SMBwritebraw);
2921 if (srv_is_signing_active()) {
2922 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2925 CHECK_FSP(fsp,conn);
2926 if (!CHECK_WRITE(fsp)) {
2927 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2930 tcount = IVAL(inbuf,smb_vwv1);
2931 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2932 write_through = BITSETW(inbuf+smb_vwv7,0);
2934 /* We have to deal with slightly different formats depending
2935 on whether we are using the core+ or lanman1.0 protocol */
2937 if(Protocol <= PROTOCOL_COREPLUS) {
2938 numtowrite = SVAL(smb_buf(inbuf),-2);
2939 data = smb_buf(inbuf);
2940 } else {
2941 numtowrite = SVAL(inbuf,smb_vwv10);
2942 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2945 /* force the error type */
2946 SCVAL(inbuf,smb_com,SMBwritec);
2947 SCVAL(outbuf,smb_com,SMBwritec);
2949 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2950 END_PROFILE(SMBwritebraw);
2951 return(ERROR_DOS(ERRDOS,ERRlock));
2954 if (numtowrite>0)
2955 nwritten = write_file(fsp,data,startpos,numtowrite);
2957 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2958 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2960 if (nwritten < (ssize_t)numtowrite) {
2961 END_PROFILE(SMBwritebraw);
2962 return(UNIXERROR(ERRHRD,ERRdiskfull));
2965 total_written = nwritten;
2967 /* Return a message to the redirector to tell it to send more bytes */
2968 SCVAL(outbuf,smb_com,SMBwritebraw);
2969 SSVALS(outbuf,smb_vwv0,-1);
2970 outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2971 show_msg(outbuf);
2972 if (!send_smb(smbd_server_fd(),outbuf))
2973 exit_server_cleanly("reply_writebraw: send_smb failed.");
2975 /* Now read the raw data into the buffer and write it */
2976 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2977 exit_server_cleanly("secondary writebraw failed");
2980 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2981 numtowrite = smb_len(inbuf);
2983 /* Set up outbuf to return the correct return */
2984 outsize = set_message(inbuf,outbuf,1,0,True);
2985 SCVAL(outbuf,smb_com,SMBwritec);
2987 if (numtowrite != 0) {
2989 if (numtowrite > BUFFER_SIZE) {
2990 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2991 (unsigned int)numtowrite ));
2992 exit_server_cleanly("secondary writebraw failed");
2995 if (tcount > nwritten+numtowrite) {
2996 DEBUG(3,("Client overestimated the write %d %d %d\n",
2997 (int)tcount,(int)nwritten,(int)numtowrite));
3000 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
3001 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
3002 strerror(errno) ));
3003 exit_server_cleanly("secondary writebraw failed");
3006 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
3007 if (nwritten == -1) {
3008 END_PROFILE(SMBwritebraw);
3009 return(UNIXERROR(ERRHRD,ERRdiskfull));
3012 if (nwritten < (ssize_t)numtowrite) {
3013 SCVAL(outbuf,smb_rcls,ERRHRD);
3014 SSVAL(outbuf,smb_err,ERRdiskfull);
3017 if (nwritten > 0)
3018 total_written += nwritten;
3021 SSVAL(outbuf,smb_vwv0,total_written);
3023 status = sync_file(conn, fsp, write_through);
3024 if (!NT_STATUS_IS_OK(status)) {
3025 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3026 fsp->fsp_name, nt_errstr(status) ));
3027 END_PROFILE(SMBwritebraw);
3028 return ERROR_NT(status);
3031 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
3032 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
3034 /* we won't return a status if write through is not selected - this follows what WfWg does */
3035 END_PROFILE(SMBwritebraw);
3036 if (!write_through && total_written==tcount) {
3038 #if RABBIT_PELLET_FIX
3040 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3041 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
3043 if (!send_keepalive(smbd_server_fd()))
3044 exit_server_cleanly("reply_writebraw: send of keepalive failed");
3045 #endif
3046 return(-1);
3049 return(outsize);
3052 #undef DBGC_CLASS
3053 #define DBGC_CLASS DBGC_LOCKING
3055 /****************************************************************************
3056 Reply to a writeunlock (core+).
3057 ****************************************************************************/
3059 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
3060 int size, int dum_buffsize)
3062 ssize_t nwritten = -1;
3063 size_t numtowrite;
3064 SMB_OFF_T startpos;
3065 char *data;
3066 NTSTATUS status = NT_STATUS_OK;
3067 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3068 int outsize = 0;
3069 START_PROFILE(SMBwriteunlock);
3071 CHECK_FSP(fsp,conn);
3072 if (!CHECK_WRITE(fsp)) {
3073 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3076 numtowrite = SVAL(inbuf,smb_vwv1);
3077 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3078 data = smb_buf(inbuf) + 3;
3080 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3081 END_PROFILE(SMBwriteunlock);
3082 return ERROR_DOS(ERRDOS,ERRlock);
3085 /* The special X/Open SMB protocol handling of
3086 zero length writes is *NOT* done for
3087 this call */
3088 if(numtowrite == 0) {
3089 nwritten = 0;
3090 } else {
3091 nwritten = write_file(fsp,data,startpos,numtowrite);
3094 status = sync_file(conn, fsp, False /* write through */);
3095 if (!NT_STATUS_IS_OK(status)) {
3096 END_PROFILE(SMBwriteunlock);
3097 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3098 fsp->fsp_name, nt_errstr(status) ));
3099 return ERROR_NT(status);
3102 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3103 END_PROFILE(SMBwriteunlock);
3104 return(UNIXERROR(ERRHRD,ERRdiskfull));
3107 if (numtowrite) {
3108 status = do_unlock(smbd_messaging_context(),
3109 fsp,
3110 (uint32)SVAL(inbuf,smb_pid),
3111 (SMB_BIG_UINT)numtowrite,
3112 (SMB_BIG_UINT)startpos,
3113 WINDOWS_LOCK);
3115 if (NT_STATUS_V(status)) {
3116 END_PROFILE(SMBwriteunlock);
3117 return ERROR_NT(status);
3121 outsize = set_message(inbuf,outbuf,1,0,True);
3123 SSVAL(outbuf,smb_vwv0,nwritten);
3125 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3126 fsp->fnum, (int)numtowrite, (int)nwritten));
3128 END_PROFILE(SMBwriteunlock);
3129 return outsize;
3132 #undef DBGC_CLASS
3133 #define DBGC_CLASS DBGC_ALL
3135 /****************************************************************************
3136 Reply to a write.
3137 ****************************************************************************/
3139 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
3141 size_t numtowrite;
3142 ssize_t nwritten = -1;
3143 SMB_OFF_T startpos;
3144 char *data;
3145 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3146 int outsize = 0;
3147 NTSTATUS status;
3148 START_PROFILE(SMBwrite);
3150 /* If it's an IPC, pass off the pipe handler. */
3151 if (IS_IPC(conn)) {
3152 END_PROFILE(SMBwrite);
3153 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3156 CHECK_FSP(fsp,conn);
3157 if (!CHECK_WRITE(fsp)) {
3158 END_PROFILE(SMBwrite);
3159 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3162 numtowrite = SVAL(inbuf,smb_vwv1);
3163 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3164 data = smb_buf(inbuf) + 3;
3166 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3167 END_PROFILE(SMBwrite);
3168 return ERROR_DOS(ERRDOS,ERRlock);
3172 * X/Open SMB protocol says that if smb_vwv1 is
3173 * zero then the file size should be extended or
3174 * truncated to the size given in smb_vwv[2-3].
3177 if(numtowrite == 0) {
3179 * This is actually an allocate call, and set EOF. JRA.
3181 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3182 if (nwritten < 0) {
3183 END_PROFILE(SMBwrite);
3184 return ERROR_NT(NT_STATUS_DISK_FULL);
3186 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3187 if (nwritten < 0) {
3188 END_PROFILE(SMBwrite);
3189 return ERROR_NT(NT_STATUS_DISK_FULL);
3191 } else
3192 nwritten = write_file(fsp,data,startpos,numtowrite);
3194 status = sync_file(conn, fsp, False);
3195 if (!NT_STATUS_IS_OK(status)) {
3196 END_PROFILE(SMBwrite);
3197 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3198 fsp->fsp_name, nt_errstr(status) ));
3199 return ERROR_NT(status);
3202 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3203 END_PROFILE(SMBwrite);
3204 return(UNIXERROR(ERRHRD,ERRdiskfull));
3207 outsize = set_message(inbuf,outbuf,1,0,True);
3209 SSVAL(outbuf,smb_vwv0,nwritten);
3211 if (nwritten < (ssize_t)numtowrite) {
3212 SCVAL(outbuf,smb_rcls,ERRHRD);
3213 SSVAL(outbuf,smb_err,ERRdiskfull);
3216 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3218 END_PROFILE(SMBwrite);
3219 return(outsize);
3222 /****************************************************************************
3223 Reply to a write and X.
3224 ****************************************************************************/
3226 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3228 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3229 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3230 size_t numtowrite = SVAL(inbuf,smb_vwv10);
3231 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3232 ssize_t nwritten = -1;
3233 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3234 unsigned int smblen = smb_len(inbuf);
3235 char *data;
3236 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3237 NTSTATUS status;
3238 START_PROFILE(SMBwriteX);
3240 /* If it's an IPC, pass off the pipe handler. */
3241 if (IS_IPC(conn)) {
3242 END_PROFILE(SMBwriteX);
3243 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3246 CHECK_FSP(fsp,conn);
3247 if (!CHECK_WRITE(fsp)) {
3248 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3251 set_message(inbuf,outbuf,6,0,True);
3253 /* Deal with possible LARGE_WRITEX */
3254 if (large_writeX) {
3255 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3258 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3259 END_PROFILE(SMBwriteX);
3260 return ERROR_DOS(ERRDOS,ERRbadmem);
3263 data = smb_base(inbuf) + smb_doff;
3265 if(CVAL(inbuf,smb_wct) == 14) {
3266 #ifdef LARGE_SMB_OFF_T
3268 * This is a large offset (64 bit) write.
3270 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3272 #else /* !LARGE_SMB_OFF_T */
3275 * Ensure we haven't been sent a >32 bit offset.
3278 if(IVAL(inbuf,smb_vwv12) != 0) {
3279 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3280 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3281 END_PROFILE(SMBwriteX);
3282 return ERROR_DOS(ERRDOS,ERRbadaccess);
3285 #endif /* LARGE_SMB_OFF_T */
3288 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3289 END_PROFILE(SMBwriteX);
3290 return ERROR_DOS(ERRDOS,ERRlock);
3293 /* X/Open SMB protocol says that, unlike SMBwrite
3294 if the length is zero then NO truncation is
3295 done, just a write of zero. To truncate a file,
3296 use SMBwrite. */
3298 if(numtowrite == 0) {
3299 nwritten = 0;
3300 } else {
3302 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3303 fsp,data,startpos,numtowrite)) {
3304 END_PROFILE(SMBwriteX);
3305 return -1;
3308 nwritten = write_file(fsp,data,startpos,numtowrite);
3311 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3312 END_PROFILE(SMBwriteX);
3313 return(UNIXERROR(ERRHRD,ERRdiskfull));
3316 SSVAL(outbuf,smb_vwv2,nwritten);
3317 if (large_writeX)
3318 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3320 if (nwritten < (ssize_t)numtowrite) {
3321 SCVAL(outbuf,smb_rcls,ERRHRD);
3322 SSVAL(outbuf,smb_err,ERRdiskfull);
3325 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3326 fsp->fnum, (int)numtowrite, (int)nwritten));
3328 status = sync_file(conn, fsp, write_through);
3329 if (!NT_STATUS_IS_OK(status)) {
3330 END_PROFILE(SMBwriteX);
3331 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3332 fsp->fsp_name, nt_errstr(status) ));
3333 return ERROR_NT(status);
3336 END_PROFILE(SMBwriteX);
3337 return chain_reply(inbuf,&outbuf,length,bufsize);
3340 /****************************************************************************
3341 Reply to a lseek.
3342 ****************************************************************************/
3344 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3346 SMB_OFF_T startpos;
3347 SMB_OFF_T res= -1;
3348 int mode,umode;
3349 int outsize = 0;
3350 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3351 START_PROFILE(SMBlseek);
3353 CHECK_FSP(fsp,conn);
3355 flush_write_cache(fsp, SEEK_FLUSH);
3357 mode = SVAL(inbuf,smb_vwv1) & 3;
3358 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3359 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3361 switch (mode) {
3362 case 0:
3363 umode = SEEK_SET;
3364 res = startpos;
3365 break;
3366 case 1:
3367 umode = SEEK_CUR;
3368 res = fsp->fh->pos + startpos;
3369 break;
3370 case 2:
3371 umode = SEEK_END;
3372 break;
3373 default:
3374 umode = SEEK_SET;
3375 res = startpos;
3376 break;
3379 if (umode == SEEK_END) {
3380 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3381 if(errno == EINVAL) {
3382 SMB_OFF_T current_pos = startpos;
3383 SMB_STRUCT_STAT sbuf;
3385 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3386 END_PROFILE(SMBlseek);
3387 return(UNIXERROR(ERRDOS,ERRnoaccess));
3390 current_pos += sbuf.st_size;
3391 if(current_pos < 0)
3392 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3396 if(res == -1) {
3397 END_PROFILE(SMBlseek);
3398 return(UNIXERROR(ERRDOS,ERRnoaccess));
3402 fsp->fh->pos = res;
3404 outsize = set_message(inbuf,outbuf,2,0,True);
3405 SIVAL(outbuf,smb_vwv0,res);
3407 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3408 fsp->fnum, (double)startpos, (double)res, mode));
3410 END_PROFILE(SMBlseek);
3411 return(outsize);
3414 /****************************************************************************
3415 Reply to a flush.
3416 ****************************************************************************/
3418 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3420 int outsize = set_message(inbuf,outbuf,0,0,False);
3421 uint16 fnum = SVAL(inbuf,smb_vwv0);
3422 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3423 START_PROFILE(SMBflush);
3425 if (fnum != 0xFFFF)
3426 CHECK_FSP(fsp,conn);
3428 if (!fsp) {
3429 file_sync_all(conn);
3430 } else {
3431 NTSTATUS status = sync_file(conn, fsp, True);
3432 if (!NT_STATUS_IS_OK(status)) {
3433 END_PROFILE(SMBflush);
3434 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3435 fsp->fsp_name, nt_errstr(status) ));
3436 return ERROR_NT(status);
3440 DEBUG(3,("flush\n"));
3441 END_PROFILE(SMBflush);
3442 return(outsize);
3445 /****************************************************************************
3446 Reply to a exit.
3447 conn POINTER CAN BE NULL HERE !
3448 ****************************************************************************/
3450 int reply_exit(connection_struct *conn,
3451 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3453 int outsize;
3454 START_PROFILE(SMBexit);
3456 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3458 outsize = set_message(inbuf,outbuf,0,0,False);
3460 DEBUG(3,("exit\n"));
3462 END_PROFILE(SMBexit);
3463 return(outsize);
3466 /****************************************************************************
3467 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3468 ****************************************************************************/
3470 void reply_close(connection_struct *conn, struct smb_request *req)
3472 NTSTATUS status = NT_STATUS_OK;
3473 files_struct *fsp = NULL;
3474 START_PROFILE(SMBclose);
3476 if (req->wct < 3) {
3477 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3478 END_PROFILE(SMBclose);
3479 return;
3482 /* If it's an IPC, pass off to the pipe handler. */
3483 if (IS_IPC(conn)) {
3484 reply_pipe_close(conn, req);
3485 END_PROFILE(SMBclose);
3486 return;
3489 fsp = file_fsp((char *)req->inbuf,smb_vwv0);
3492 * We can only use CHECK_FSP if we know it's not a directory.
3495 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3496 reply_doserror(req, ERRDOS, ERRbadfid);
3497 END_PROFILE(SMBclose);
3498 return;
3501 if(fsp->is_directory) {
3503 * Special case - close NT SMB directory handle.
3505 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3506 status = close_file(fsp,NORMAL_CLOSE);
3507 } else {
3509 * Close ordinary file.
3512 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3513 fsp->fh->fd, fsp->fnum,
3514 conn->num_files_open));
3517 * Take care of any time sent in the close.
3520 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
3521 srv_make_unix_date3(
3522 req->inbuf+smb_vwv1)));
3525 * close_file() returns the unix errno if an error
3526 * was detected on close - normally this is due to
3527 * a disk full error. If not then it was probably an I/O error.
3530 status = close_file(fsp,NORMAL_CLOSE);
3533 if (!NT_STATUS_IS_OK(status)) {
3534 reply_nterror(req, status);
3535 END_PROFILE(SMBclose);
3536 return;
3539 reply_outbuf(req, 0, 0);
3540 END_PROFILE(SMBclose);
3541 return;
3544 /****************************************************************************
3545 Reply to a writeclose (Core+ protocol).
3546 ****************************************************************************/
3548 int reply_writeclose(connection_struct *conn,
3549 char *inbuf,char *outbuf, int size, int dum_buffsize)
3551 size_t numtowrite;
3552 ssize_t nwritten = -1;
3553 int outsize = 0;
3554 NTSTATUS close_status = NT_STATUS_OK;
3555 SMB_OFF_T startpos;
3556 char *data;
3557 struct timespec mtime;
3558 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3559 START_PROFILE(SMBwriteclose);
3561 CHECK_FSP(fsp,conn);
3562 if (!CHECK_WRITE(fsp)) {
3563 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3566 numtowrite = SVAL(inbuf,smb_vwv1);
3567 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3568 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3569 data = smb_buf(inbuf) + 1;
3571 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3572 END_PROFILE(SMBwriteclose);
3573 return ERROR_DOS(ERRDOS,ERRlock);
3576 nwritten = write_file(fsp,data,startpos,numtowrite);
3578 set_filetime(conn, fsp->fsp_name, mtime);
3581 * More insanity. W2K only closes the file if writelen > 0.
3582 * JRA.
3585 if (numtowrite) {
3586 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3587 fsp->fsp_name ));
3588 close_status = close_file(fsp,NORMAL_CLOSE);
3591 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3592 fsp->fnum, (int)numtowrite, (int)nwritten,
3593 conn->num_files_open));
3595 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3596 END_PROFILE(SMBwriteclose);
3597 return(UNIXERROR(ERRHRD,ERRdiskfull));
3600 if(!NT_STATUS_IS_OK(close_status)) {
3601 END_PROFILE(SMBwriteclose);
3602 return ERROR_NT(close_status);
3605 outsize = set_message(inbuf,outbuf,1,0,True);
3607 SSVAL(outbuf,smb_vwv0,nwritten);
3608 END_PROFILE(SMBwriteclose);
3609 return(outsize);
3612 #undef DBGC_CLASS
3613 #define DBGC_CLASS DBGC_LOCKING
3615 /****************************************************************************
3616 Reply to a lock.
3617 ****************************************************************************/
3619 int reply_lock(connection_struct *conn,
3620 char *inbuf,char *outbuf, int length, int dum_buffsize)
3622 int outsize = set_message(inbuf,outbuf,0,0,False);
3623 SMB_BIG_UINT count,offset;
3624 NTSTATUS status;
3625 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3626 struct byte_range_lock *br_lck = NULL;
3628 START_PROFILE(SMBlock);
3630 CHECK_FSP(fsp,conn);
3632 release_level_2_oplocks_on_change(fsp);
3634 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3635 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3637 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3638 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3640 br_lck = do_lock(smbd_messaging_context(),
3641 fsp,
3642 (uint32)SVAL(inbuf,smb_pid),
3643 count,
3644 offset,
3645 WRITE_LOCK,
3646 WINDOWS_LOCK,
3647 False, /* Non-blocking lock. */
3648 &status,
3649 NULL);
3651 TALLOC_FREE(br_lck);
3653 if (NT_STATUS_V(status)) {
3654 END_PROFILE(SMBlock);
3655 return ERROR_NT(status);
3658 END_PROFILE(SMBlock);
3659 return(outsize);
3662 /****************************************************************************
3663 Reply to a unlock.
3664 ****************************************************************************/
3666 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3667 int dum_buffsize)
3669 int outsize = set_message(inbuf,outbuf,0,0,False);
3670 SMB_BIG_UINT count,offset;
3671 NTSTATUS status;
3672 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3673 START_PROFILE(SMBunlock);
3675 CHECK_FSP(fsp,conn);
3677 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3678 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3680 status = do_unlock(smbd_messaging_context(),
3681 fsp,
3682 (uint32)SVAL(inbuf,smb_pid),
3683 count,
3684 offset,
3685 WINDOWS_LOCK);
3687 if (NT_STATUS_V(status)) {
3688 END_PROFILE(SMBunlock);
3689 return ERROR_NT(status);
3692 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3693 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3695 END_PROFILE(SMBunlock);
3696 return(outsize);
3699 #undef DBGC_CLASS
3700 #define DBGC_CLASS DBGC_ALL
3702 /****************************************************************************
3703 Reply to a tdis.
3704 conn POINTER CAN BE NULL HERE !
3705 ****************************************************************************/
3707 int reply_tdis(connection_struct *conn,
3708 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3710 int outsize = set_message(inbuf,outbuf,0,0,False);
3711 uint16 vuid;
3712 START_PROFILE(SMBtdis);
3714 vuid = SVAL(inbuf,smb_uid);
3716 if (!conn) {
3717 DEBUG(4,("Invalid connection in tdis\n"));
3718 END_PROFILE(SMBtdis);
3719 return ERROR_DOS(ERRSRV,ERRinvnid);
3722 conn->used = False;
3724 close_cnum(conn,vuid);
3726 END_PROFILE(SMBtdis);
3727 return outsize;
3730 /****************************************************************************
3731 Reply to a echo.
3732 conn POINTER CAN BE NULL HERE !
3733 ****************************************************************************/
3735 int reply_echo(connection_struct *conn,
3736 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3738 int smb_reverb = SVAL(inbuf,smb_vwv0);
3739 int seq_num;
3740 unsigned int data_len = smb_buflen(inbuf);
3741 int outsize = set_message(inbuf,outbuf,1,data_len,True);
3742 START_PROFILE(SMBecho);
3744 if (data_len > BUFFER_SIZE) {
3745 DEBUG(0,("reply_echo: data_len too large.\n"));
3746 END_PROFILE(SMBecho);
3747 return -1;
3750 /* copy any incoming data back out */
3751 if (data_len > 0)
3752 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3754 if (smb_reverb > 100) {
3755 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3756 smb_reverb = 100;
3759 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3760 SSVAL(outbuf,smb_vwv0,seq_num);
3762 smb_setlen(inbuf,outbuf,outsize - 4);
3764 show_msg(outbuf);
3765 if (!send_smb(smbd_server_fd(),outbuf))
3766 exit_server_cleanly("reply_echo: send_smb failed.");
3769 DEBUG(3,("echo %d times\n", smb_reverb));
3771 smb_echo_count++;
3773 END_PROFILE(SMBecho);
3774 return -1;
3777 /****************************************************************************
3778 Reply to a printopen.
3779 ****************************************************************************/
3781 int reply_printopen(connection_struct *conn,
3782 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3784 int outsize = 0;
3785 files_struct *fsp;
3786 NTSTATUS status;
3788 START_PROFILE(SMBsplopen);
3790 if (!CAN_PRINT(conn)) {
3791 END_PROFILE(SMBsplopen);
3792 return ERROR_DOS(ERRDOS,ERRnoaccess);
3795 /* Open for exclusive use, write only. */
3796 status = print_fsp_open(conn, NULL, &fsp);
3798 if (!NT_STATUS_IS_OK(status)) {
3799 END_PROFILE(SMBsplopen);
3800 return(ERROR_NT(status));
3803 outsize = set_message(inbuf,outbuf,1,0,True);
3804 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3806 DEBUG(3,("openprint fd=%d fnum=%d\n",
3807 fsp->fh->fd, fsp->fnum));
3809 END_PROFILE(SMBsplopen);
3810 return(outsize);
3813 /****************************************************************************
3814 Reply to a printclose.
3815 ****************************************************************************/
3817 int reply_printclose(connection_struct *conn,
3818 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3820 int outsize = set_message(inbuf,outbuf,0,0,False);
3821 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3822 NTSTATUS status;
3823 START_PROFILE(SMBsplclose);
3825 CHECK_FSP(fsp,conn);
3827 if (!CAN_PRINT(conn)) {
3828 END_PROFILE(SMBsplclose);
3829 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3832 DEBUG(3,("printclose fd=%d fnum=%d\n",
3833 fsp->fh->fd,fsp->fnum));
3835 status = close_file(fsp,NORMAL_CLOSE);
3837 if(!NT_STATUS_IS_OK(status)) {
3838 END_PROFILE(SMBsplclose);
3839 return ERROR_NT(status);
3842 END_PROFILE(SMBsplclose);
3843 return(outsize);
3846 /****************************************************************************
3847 Reply to a printqueue.
3848 ****************************************************************************/
3850 int reply_printqueue(connection_struct *conn,
3851 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3853 int outsize = set_message(inbuf,outbuf,2,3,True);
3854 int max_count = SVAL(inbuf,smb_vwv0);
3855 int start_index = SVAL(inbuf,smb_vwv1);
3856 START_PROFILE(SMBsplretq);
3858 /* we used to allow the client to get the cnum wrong, but that
3859 is really quite gross and only worked when there was only
3860 one printer - I think we should now only accept it if they
3861 get it right (tridge) */
3862 if (!CAN_PRINT(conn)) {
3863 END_PROFILE(SMBsplretq);
3864 return ERROR_DOS(ERRDOS,ERRnoaccess);
3867 SSVAL(outbuf,smb_vwv0,0);
3868 SSVAL(outbuf,smb_vwv1,0);
3869 SCVAL(smb_buf(outbuf),0,1);
3870 SSVAL(smb_buf(outbuf),1,0);
3872 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3873 start_index, max_count));
3876 print_queue_struct *queue = NULL;
3877 print_status_struct status;
3878 char *p = smb_buf(outbuf) + 3;
3879 int count = print_queue_status(SNUM(conn), &queue, &status);
3880 int num_to_get = ABS(max_count);
3881 int first = (max_count>0?start_index:start_index+max_count+1);
3882 int i;
3884 if (first >= count)
3885 num_to_get = 0;
3886 else
3887 num_to_get = MIN(num_to_get,count-first);
3890 for (i=first;i<first+num_to_get;i++) {
3891 srv_put_dos_date2(p,0,queue[i].time);
3892 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3893 SSVAL(p,5, queue[i].job);
3894 SIVAL(p,7,queue[i].size);
3895 SCVAL(p,11,0);
3896 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3897 p += 28;
3900 if (count > 0) {
3901 outsize = set_message(inbuf,outbuf,2,28*count+3,False);
3902 SSVAL(outbuf,smb_vwv0,count);
3903 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3904 SCVAL(smb_buf(outbuf),0,1);
3905 SSVAL(smb_buf(outbuf),1,28*count);
3908 SAFE_FREE(queue);
3910 DEBUG(3,("%d entries returned in queue\n",count));
3913 END_PROFILE(SMBsplretq);
3914 return(outsize);
3917 /****************************************************************************
3918 Reply to a printwrite.
3919 ****************************************************************************/
3921 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3923 int numtowrite;
3924 int outsize = set_message(inbuf,outbuf,0,0,False);
3925 char *data;
3926 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3928 START_PROFILE(SMBsplwr);
3930 if (!CAN_PRINT(conn)) {
3931 END_PROFILE(SMBsplwr);
3932 return ERROR_DOS(ERRDOS,ERRnoaccess);
3935 CHECK_FSP(fsp,conn);
3936 if (!CHECK_WRITE(fsp)) {
3937 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3940 numtowrite = SVAL(smb_buf(inbuf),1);
3941 data = smb_buf(inbuf) + 3;
3943 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3944 END_PROFILE(SMBsplwr);
3945 return(UNIXERROR(ERRHRD,ERRdiskfull));
3948 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3950 END_PROFILE(SMBsplwr);
3951 return(outsize);
3954 /****************************************************************************
3955 Reply to a mkdir.
3956 ****************************************************************************/
3958 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3960 pstring directory;
3961 int outsize;
3962 NTSTATUS status;
3963 SMB_STRUCT_STAT sbuf;
3965 START_PROFILE(SMBmkdir);
3967 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
3968 smb_buf(inbuf) + 1, sizeof(directory), 0,
3969 STR_TERMINATE, &status);
3970 if (!NT_STATUS_IS_OK(status)) {
3971 END_PROFILE(SMBmkdir);
3972 return ERROR_NT(status);
3975 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
3976 if (!NT_STATUS_IS_OK(status)) {
3977 END_PROFILE(SMBmkdir);
3978 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3979 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3981 return ERROR_NT(status);
3984 status = unix_convert(conn, directory, False, NULL, &sbuf);
3985 if (!NT_STATUS_IS_OK(status)) {
3986 END_PROFILE(SMBmkdir);
3987 return ERROR_NT(status);
3990 status = check_name(conn, directory);
3991 if (!NT_STATUS_IS_OK(status)) {
3992 END_PROFILE(SMBmkdir);
3993 return ERROR_NT(status);
3996 status = create_directory(conn, directory);
3998 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4000 if (!NT_STATUS_IS_OK(status)) {
4002 if (!use_nt_status()
4003 && NT_STATUS_EQUAL(status,
4004 NT_STATUS_OBJECT_NAME_COLLISION)) {
4006 * Yes, in the DOS error code case we get a
4007 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4008 * samba4 torture test.
4010 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4013 END_PROFILE(SMBmkdir);
4014 return ERROR_NT(status);
4017 outsize = set_message(inbuf,outbuf,0,0,False);
4019 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
4021 END_PROFILE(SMBmkdir);
4022 return(outsize);
4025 /****************************************************************************
4026 Static function used by reply_rmdir to delete an entire directory
4027 tree recursively. Return True on ok, False on fail.
4028 ****************************************************************************/
4030 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
4032 const char *dname = NULL;
4033 BOOL ret = True;
4034 long offset = 0;
4035 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4037 if(dir_hnd == NULL)
4038 return False;
4040 while((dname = ReadDirName(dir_hnd, &offset))) {
4041 pstring fullname;
4042 SMB_STRUCT_STAT st;
4044 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4045 continue;
4047 if (!is_visible_file(conn, directory, dname, &st, False))
4048 continue;
4050 /* Construct the full name. */
4051 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4052 errno = ENOMEM;
4053 ret = False;
4054 break;
4057 pstrcpy(fullname, directory);
4058 pstrcat(fullname, "/");
4059 pstrcat(fullname, dname);
4061 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4062 ret = False;
4063 break;
4066 if(st.st_mode & S_IFDIR) {
4067 if(!recursive_rmdir(conn, fullname)) {
4068 ret = False;
4069 break;
4071 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4072 ret = False;
4073 break;
4075 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4076 ret = False;
4077 break;
4080 CloseDir(dir_hnd);
4081 return ret;
4084 /****************************************************************************
4085 The internals of the rmdir code - called elsewhere.
4086 ****************************************************************************/
4088 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4090 int ret;
4091 SMB_STRUCT_STAT st;
4093 /* Might be a symlink. */
4094 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4095 return map_nt_error_from_unix(errno);
4098 if (S_ISLNK(st.st_mode)) {
4099 /* Is what it points to a directory ? */
4100 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4101 return map_nt_error_from_unix(errno);
4103 if (!(S_ISDIR(st.st_mode))) {
4104 return NT_STATUS_NOT_A_DIRECTORY;
4106 ret = SMB_VFS_UNLINK(conn,directory);
4107 } else {
4108 ret = SMB_VFS_RMDIR(conn,directory);
4110 if (ret == 0) {
4111 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4112 FILE_NOTIFY_CHANGE_DIR_NAME,
4113 directory);
4114 return NT_STATUS_OK;
4117 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4119 * Check to see if the only thing in this directory are
4120 * vetoed files/directories. If so then delete them and
4121 * retry. If we fail to delete any of them (and we *don't*
4122 * do a recursive delete) then fail the rmdir.
4124 const char *dname;
4125 long dirpos = 0;
4126 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4128 if(dir_hnd == NULL) {
4129 errno = ENOTEMPTY;
4130 goto err;
4133 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4134 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4135 continue;
4136 if (!is_visible_file(conn, directory, dname, &st, False))
4137 continue;
4138 if(!IS_VETO_PATH(conn, dname)) {
4139 CloseDir(dir_hnd);
4140 errno = ENOTEMPTY;
4141 goto err;
4145 /* We only have veto files/directories. Recursive delete. */
4147 RewindDir(dir_hnd,&dirpos);
4148 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4149 pstring fullname;
4151 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4152 continue;
4153 if (!is_visible_file(conn, directory, dname, &st, False))
4154 continue;
4156 /* Construct the full name. */
4157 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4158 errno = ENOMEM;
4159 break;
4162 pstrcpy(fullname, directory);
4163 pstrcat(fullname, "/");
4164 pstrcat(fullname, dname);
4166 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4167 break;
4168 if(st.st_mode & S_IFDIR) {
4169 if(lp_recursive_veto_delete(SNUM(conn))) {
4170 if(!recursive_rmdir(conn, fullname))
4171 break;
4173 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4174 break;
4175 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4176 break;
4178 CloseDir(dir_hnd);
4179 /* Retry the rmdir */
4180 ret = SMB_VFS_RMDIR(conn,directory);
4183 err:
4185 if (ret != 0) {
4186 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4187 "%s\n", directory,strerror(errno)));
4188 return map_nt_error_from_unix(errno);
4191 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4192 FILE_NOTIFY_CHANGE_DIR_NAME,
4193 directory);
4195 return NT_STATUS_OK;
4198 /****************************************************************************
4199 Reply to a rmdir.
4200 ****************************************************************************/
4202 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4204 pstring directory;
4205 int outsize = 0;
4206 SMB_STRUCT_STAT sbuf;
4207 NTSTATUS status;
4208 START_PROFILE(SMBrmdir);
4210 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
4211 smb_buf(inbuf) + 1, sizeof(directory), 0,
4212 STR_TERMINATE, &status);
4213 if (!NT_STATUS_IS_OK(status)) {
4214 END_PROFILE(SMBrmdir);
4215 return ERROR_NT(status);
4218 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
4219 if (!NT_STATUS_IS_OK(status)) {
4220 END_PROFILE(SMBrmdir);
4221 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4222 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4224 return ERROR_NT(status);
4227 status = unix_convert(conn, directory, False, NULL, &sbuf);
4228 if (!NT_STATUS_IS_OK(status)) {
4229 END_PROFILE(SMBrmdir);
4230 return ERROR_NT(status);
4233 status = check_name(conn, directory);
4234 if (!NT_STATUS_IS_OK(status)) {
4235 END_PROFILE(SMBrmdir);
4236 return ERROR_NT(status);
4239 dptr_closepath(directory,SVAL(inbuf,smb_pid));
4240 status = rmdir_internals(conn, directory);
4241 if (!NT_STATUS_IS_OK(status)) {
4242 END_PROFILE(SMBrmdir);
4243 return ERROR_NT(status);
4246 outsize = set_message(inbuf,outbuf,0,0,False);
4248 DEBUG( 3, ( "rmdir %s\n", directory ) );
4250 END_PROFILE(SMBrmdir);
4251 return(outsize);
4254 /*******************************************************************
4255 Resolve wildcards in a filename rename.
4256 Note that name is in UNIX charset and thus potentially can be more
4257 than fstring buffer (255 bytes) especially in default UTF-8 case.
4258 Therefore, we use pstring inside and all calls should ensure that
4259 name2 is at least pstring-long (they do already)
4260 ********************************************************************/
4262 static BOOL resolve_wildcards(const char *name1, char *name2)
4264 pstring root1,root2;
4265 pstring ext1,ext2;
4266 char *p,*p2, *pname1, *pname2;
4267 int available_space, actual_space;
4269 pname1 = strrchr_m(name1,'/');
4270 pname2 = strrchr_m(name2,'/');
4272 if (!pname1 || !pname2)
4273 return(False);
4275 pstrcpy(root1,pname1);
4276 pstrcpy(root2,pname2);
4277 p = strrchr_m(root1,'.');
4278 if (p) {
4279 *p = 0;
4280 pstrcpy(ext1,p+1);
4281 } else {
4282 pstrcpy(ext1,"");
4284 p = strrchr_m(root2,'.');
4285 if (p) {
4286 *p = 0;
4287 pstrcpy(ext2,p+1);
4288 } else {
4289 pstrcpy(ext2,"");
4292 p = root1;
4293 p2 = root2;
4294 while (*p2) {
4295 if (*p2 == '?') {
4296 *p2 = *p;
4297 p2++;
4298 } else if (*p2 == '*') {
4299 pstrcpy(p2, p);
4300 break;
4301 } else {
4302 p2++;
4304 if (*p)
4305 p++;
4308 p = ext1;
4309 p2 = ext2;
4310 while (*p2) {
4311 if (*p2 == '?') {
4312 *p2 = *p;
4313 p2++;
4314 } else if (*p2 == '*') {
4315 pstrcpy(p2, p);
4316 break;
4317 } else {
4318 p2++;
4320 if (*p)
4321 p++;
4324 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4326 if (ext2[0]) {
4327 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4328 if (actual_space >= available_space - 1) {
4329 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4330 actual_space - available_space));
4332 } else {
4333 pstrcpy_base(pname2, root2, name2);
4336 return(True);
4339 /****************************************************************************
4340 Ensure open files have their names updated. Updated to notify other smbd's
4341 asynchronously.
4342 ****************************************************************************/
4344 static void rename_open_files(connection_struct *conn,
4345 struct share_mode_lock *lck,
4346 const char *newname)
4348 files_struct *fsp;
4349 BOOL did_rename = False;
4351 for(fsp = file_find_di_first(lck->id); fsp;
4352 fsp = file_find_di_next(fsp)) {
4353 /* fsp_name is a relative path under the fsp. To change this for other
4354 sharepaths we need to manipulate relative paths. */
4355 /* TODO - create the absolute path and manipulate the newname
4356 relative to the sharepath. */
4357 if (fsp->conn != conn) {
4358 continue;
4360 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4361 fsp->fnum, file_id_static_string(&fsp->file_id),
4362 fsp->fsp_name, newname ));
4363 string_set(&fsp->fsp_name, newname);
4364 did_rename = True;
4367 if (!did_rename) {
4368 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4369 file_id_static_string(&lck->id), newname ));
4372 /* Send messages to all smbd's (not ourself) that the name has changed. */
4373 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4374 newname);
4377 /****************************************************************************
4378 We need to check if the source path is a parent directory of the destination
4379 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4380 refuse the rename with a sharing violation. Under UNIX the above call can
4381 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4382 probably need to check that the client is a Windows one before disallowing
4383 this as a UNIX client (one with UNIX extensions) can know the source is a
4384 symlink and make this decision intelligently. Found by an excellent bug
4385 report from <AndyLiebman@aol.com>.
4386 ****************************************************************************/
4388 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4390 const char *psrc = src;
4391 const char *pdst = dest;
4392 size_t slen;
4394 if (psrc[0] == '.' && psrc[1] == '/') {
4395 psrc += 2;
4397 if (pdst[0] == '.' && pdst[1] == '/') {
4398 pdst += 2;
4400 if ((slen = strlen(psrc)) > strlen(pdst)) {
4401 return False;
4403 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4407 * Do the notify calls from a rename
4410 static void notify_rename(connection_struct *conn, BOOL is_dir,
4411 const char *oldpath, const char *newpath)
4413 char *olddir, *newdir;
4414 const char *oldname, *newname;
4415 uint32 mask;
4417 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4418 : FILE_NOTIFY_CHANGE_FILE_NAME;
4420 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4421 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4422 TALLOC_FREE(olddir);
4423 return;
4426 if (strcmp(olddir, newdir) == 0) {
4427 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4428 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4430 else {
4431 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4432 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4434 TALLOC_FREE(olddir);
4435 TALLOC_FREE(newdir);
4437 /* this is a strange one. w2k3 gives an additional event for
4438 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4439 files, but not directories */
4440 if (!is_dir) {
4441 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4442 FILE_NOTIFY_CHANGE_ATTRIBUTES
4443 |FILE_NOTIFY_CHANGE_CREATION,
4444 newpath);
4448 /****************************************************************************
4449 Rename an open file - given an fsp.
4450 ****************************************************************************/
4452 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4454 SMB_STRUCT_STAT sbuf, sbuf1;
4455 pstring newname_last_component;
4456 NTSTATUS status = NT_STATUS_OK;
4457 struct share_mode_lock *lck = NULL;
4458 BOOL dst_exists;
4460 ZERO_STRUCT(sbuf);
4462 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4464 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4466 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4467 return status;
4470 status = check_name(conn, newname);
4471 if (!NT_STATUS_IS_OK(status)) {
4472 return status;
4475 /* Ensure newname contains a '/' */
4476 if(strrchr_m(newname,'/') == 0) {
4477 pstring tmpstr;
4479 pstrcpy(tmpstr, "./");
4480 pstrcat(tmpstr, newname);
4481 pstrcpy(newname, tmpstr);
4485 * Check for special case with case preserving and not
4486 * case sensitive. If the old last component differs from the original
4487 * last component only by case, then we should allow
4488 * the rename (user is trying to change the case of the
4489 * filename).
4492 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4493 strequal(newname, fsp->fsp_name)) {
4494 char *p;
4495 pstring newname_modified_last_component;
4498 * Get the last component of the modified name.
4499 * Note that we guarantee that newname contains a '/'
4500 * character above.
4502 p = strrchr_m(newname,'/');
4503 pstrcpy(newname_modified_last_component,p+1);
4505 if(strcsequal(newname_modified_last_component,
4506 newname_last_component) == False) {
4508 * Replace the modified last component with
4509 * the original.
4511 pstrcpy(p+1, newname_last_component);
4516 * If the src and dest names are identical - including case,
4517 * don't do the rename, just return success.
4520 if (strcsequal(fsp->fsp_name, newname)) {
4521 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4522 newname));
4523 return NT_STATUS_OK;
4527 * Have vfs_object_exist also fill sbuf1
4529 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4531 if(!replace_if_exists && dst_exists) {
4532 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4533 fsp->fsp_name,newname));
4534 return NT_STATUS_OBJECT_NAME_COLLISION;
4537 if (dst_exists) {
4538 files_struct *dst_fsp = file_find_di_first(file_id_sbuf(&sbuf1));
4539 if (dst_fsp) {
4540 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4541 return NT_STATUS_ACCESS_DENIED;
4545 /* Ensure we have a valid stat struct for the source. */
4546 if (fsp->fh->fd != -1) {
4547 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4548 return map_nt_error_from_unix(errno);
4550 } else {
4551 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4552 return map_nt_error_from_unix(errno);
4556 status = can_rename(conn, fsp, attrs, &sbuf);
4558 if (!NT_STATUS_IS_OK(status)) {
4559 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4560 nt_errstr(status), fsp->fsp_name,newname));
4561 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4562 status = NT_STATUS_ACCESS_DENIED;
4563 return status;
4566 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4567 return NT_STATUS_ACCESS_DENIED;
4570 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4573 * We have the file open ourselves, so not being able to get the
4574 * corresponding share mode lock is a fatal error.
4577 SMB_ASSERT(lck != NULL);
4579 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4580 uint32 create_options = fsp->fh->private_options;
4582 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4583 fsp->fsp_name,newname));
4585 rename_open_files(conn, lck, newname);
4587 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4590 * A rename acts as a new file create w.r.t. allowing an initial delete
4591 * on close, probably because in Windows there is a new handle to the
4592 * new file. If initial delete on close was requested but not
4593 * originally set, we need to set it here. This is probably not 100% correct,
4594 * but will work for the CIFSFS client which in non-posix mode
4595 * depends on these semantics. JRA.
4598 set_allow_initial_delete_on_close(lck, fsp, True);
4600 if (create_options & FILE_DELETE_ON_CLOSE) {
4601 status = can_set_delete_on_close(fsp, True, 0);
4603 if (NT_STATUS_IS_OK(status)) {
4604 /* Note that here we set the *inital* delete on close flag,
4605 * not the regular one. The magic gets handled in close. */
4606 fsp->initial_delete_on_close = True;
4609 TALLOC_FREE(lck);
4610 return NT_STATUS_OK;
4613 TALLOC_FREE(lck);
4615 if (errno == ENOTDIR || errno == EISDIR) {
4616 status = NT_STATUS_OBJECT_NAME_COLLISION;
4617 } else {
4618 status = map_nt_error_from_unix(errno);
4621 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4622 nt_errstr(status), fsp->fsp_name,newname));
4624 return status;
4627 /****************************************************************************
4628 The guts of the rename command, split out so it may be called by the NT SMB
4629 code.
4630 ****************************************************************************/
4632 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
4633 pstring name,
4634 pstring newname,
4635 uint32 attrs,
4636 BOOL replace_if_exists,
4637 BOOL src_has_wild,
4638 BOOL dest_has_wild)
4640 pstring directory;
4641 pstring mask;
4642 pstring last_component_src;
4643 pstring last_component_dest;
4644 char *p;
4645 int count=0;
4646 NTSTATUS status = NT_STATUS_OK;
4647 SMB_STRUCT_STAT sbuf1, sbuf2;
4648 struct smb_Dir *dir_hnd = NULL;
4649 const char *dname;
4650 long offset = 0;
4651 pstring destname;
4653 *directory = *mask = 0;
4655 ZERO_STRUCT(sbuf1);
4656 ZERO_STRUCT(sbuf2);
4658 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4659 if (!NT_STATUS_IS_OK(status)) {
4660 return status;
4663 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4664 if (!NT_STATUS_IS_OK(status)) {
4665 return status;
4669 * Split the old name into directory and last component
4670 * strings. Note that unix_convert may have stripped off a
4671 * leading ./ from both name and newname if the rename is
4672 * at the root of the share. We need to make sure either both
4673 * name and newname contain a / character or neither of them do
4674 * as this is checked in resolve_wildcards().
4677 p = strrchr_m(name,'/');
4678 if (!p) {
4679 pstrcpy(directory,".");
4680 pstrcpy(mask,name);
4681 } else {
4682 *p = 0;
4683 pstrcpy(directory,name);
4684 pstrcpy(mask,p+1);
4685 *p = '/'; /* Replace needed for exceptional test below. */
4689 * We should only check the mangled cache
4690 * here if unix_convert failed. This means
4691 * that the path in 'mask' doesn't exist
4692 * on the file system and so we need to look
4693 * for a possible mangle. This patch from
4694 * Tine Smukavec <valentin.smukavec@hermes.si>.
4697 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4698 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4701 if (!src_has_wild) {
4702 files_struct *fsp;
4705 * No wildcards - just process the one file.
4707 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4709 /* Add a terminating '/' to the directory name. */
4710 pstrcat(directory,"/");
4711 pstrcat(directory,mask);
4713 /* Ensure newname contains a '/' also */
4714 if(strrchr_m(newname,'/') == 0) {
4715 pstring tmpstr;
4717 pstrcpy(tmpstr, "./");
4718 pstrcat(tmpstr, newname);
4719 pstrcpy(newname, tmpstr);
4722 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4723 "case_preserve = %d, short case preserve = %d, "
4724 "directory = %s, newname = %s, "
4725 "last_component_dest = %s, is_8_3 = %d\n",
4726 conn->case_sensitive, conn->case_preserve,
4727 conn->short_case_preserve, directory,
4728 newname, last_component_dest, is_short_name));
4730 /* The dest name still may have wildcards. */
4731 if (dest_has_wild) {
4732 if (!resolve_wildcards(directory,newname)) {
4733 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4734 directory,newname));
4735 return NT_STATUS_NO_MEMORY;
4739 ZERO_STRUCT(sbuf1);
4740 SMB_VFS_STAT(conn, directory, &sbuf1);
4742 status = S_ISDIR(sbuf1.st_mode) ?
4743 open_directory(conn, req, directory, &sbuf1,
4744 DELETE_ACCESS,
4745 FILE_SHARE_READ|FILE_SHARE_WRITE,
4746 FILE_OPEN, 0, 0, NULL,
4747 &fsp)
4748 : open_file_ntcreate(conn, req, directory, &sbuf1,
4749 DELETE_ACCESS,
4750 FILE_SHARE_READ|FILE_SHARE_WRITE,
4751 FILE_OPEN, 0, 0, 0, NULL,
4752 &fsp);
4754 if (!NT_STATUS_IS_OK(status)) {
4755 DEBUG(3, ("Could not open rename source %s: %s\n",
4756 directory, nt_errstr(status)));
4757 return status;
4760 status = rename_internals_fsp(conn, fsp, newname, attrs,
4761 replace_if_exists);
4763 close_file(fsp, NORMAL_CLOSE);
4765 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4766 nt_errstr(status), directory,newname));
4768 return status;
4772 * Wildcards - process each file that matches.
4774 if (strequal(mask,"????????.???")) {
4775 pstrcpy(mask,"*");
4778 status = check_name(conn, directory);
4779 if (!NT_STATUS_IS_OK(status)) {
4780 return status;
4783 dir_hnd = OpenDir(conn, directory, mask, attrs);
4784 if (dir_hnd == NULL) {
4785 return map_nt_error_from_unix(errno);
4788 status = NT_STATUS_NO_SUCH_FILE;
4790 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4791 * - gentest fix. JRA
4794 while ((dname = ReadDirName(dir_hnd, &offset))) {
4795 files_struct *fsp;
4796 pstring fname;
4797 BOOL sysdir_entry = False;
4799 pstrcpy(fname,dname);
4801 /* Quick check for "." and ".." */
4802 if (fname[0] == '.') {
4803 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4804 if (attrs & aDIR) {
4805 sysdir_entry = True;
4806 } else {
4807 continue;
4812 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4813 continue;
4816 if(!mask_match(fname, mask, conn->case_sensitive)) {
4817 continue;
4820 if (sysdir_entry) {
4821 status = NT_STATUS_OBJECT_NAME_INVALID;
4822 break;
4825 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4827 pstrcpy(destname,newname);
4829 if (!resolve_wildcards(fname,destname)) {
4830 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4831 fname, destname));
4832 continue;
4835 ZERO_STRUCT(sbuf1);
4836 SMB_VFS_STAT(conn, fname, &sbuf1);
4838 status = S_ISDIR(sbuf1.st_mode) ?
4839 open_directory(conn, req, fname, &sbuf1,
4840 DELETE_ACCESS,
4841 FILE_SHARE_READ|FILE_SHARE_WRITE,
4842 FILE_OPEN, 0, 0, NULL,
4843 &fsp)
4844 : open_file_ntcreate(conn, req, fname, &sbuf1,
4845 DELETE_ACCESS,
4846 FILE_SHARE_READ|FILE_SHARE_WRITE,
4847 FILE_OPEN, 0, 0, 0, NULL,
4848 &fsp);
4850 if (!NT_STATUS_IS_OK(status)) {
4851 DEBUG(3,("rename_internals: open_file_ntcreate "
4852 "returned %s rename %s -> %s\n",
4853 nt_errstr(status), directory, newname));
4854 break;
4857 status = rename_internals_fsp(conn, fsp, destname, attrs,
4858 replace_if_exists);
4860 close_file(fsp, NORMAL_CLOSE);
4862 if (!NT_STATUS_IS_OK(status)) {
4863 DEBUG(3, ("rename_internals_fsp returned %s for "
4864 "rename %s -> %s\n", nt_errstr(status),
4865 directory, newname));
4866 break;
4869 count++;
4871 DEBUG(3,("rename_internals: doing rename on %s -> "
4872 "%s\n",fname,destname));
4874 CloseDir(dir_hnd);
4876 if (count == 0 && NT_STATUS_IS_OK(status)) {
4877 status = map_nt_error_from_unix(errno);
4880 return status;
4883 /****************************************************************************
4884 Reply to a mv.
4885 ****************************************************************************/
4887 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4888 int dum_buffsize)
4890 int outsize = 0;
4891 pstring name;
4892 pstring newname;
4893 char *p;
4894 uint32 attrs = SVAL(inbuf,smb_vwv0);
4895 NTSTATUS status;
4896 BOOL src_has_wcard = False;
4897 BOOL dest_has_wcard = False;
4898 struct smb_request req;
4900 START_PROFILE(SMBmv);
4902 init_smb_request(&req, (uint8 *)inbuf);
4904 p = smb_buf(inbuf) + 1;
4905 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
4906 sizeof(name), 0, STR_TERMINATE, &status,
4907 &src_has_wcard);
4908 if (!NT_STATUS_IS_OK(status)) {
4909 END_PROFILE(SMBmv);
4910 return ERROR_NT(status);
4912 p++;
4913 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
4914 sizeof(newname), 0, STR_TERMINATE, &status,
4915 &dest_has_wcard);
4916 if (!NT_STATUS_IS_OK(status)) {
4917 END_PROFILE(SMBmv);
4918 return ERROR_NT(status);
4921 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
4922 if (!NT_STATUS_IS_OK(status)) {
4923 END_PROFILE(SMBmv);
4924 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4925 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4927 return ERROR_NT(status);
4930 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4931 if (!NT_STATUS_IS_OK(status)) {
4932 END_PROFILE(SMBmv);
4933 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4934 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4936 return ERROR_NT(status);
4939 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4941 status = rename_internals(conn, &req, name, newname, attrs, False,
4942 src_has_wcard, dest_has_wcard);
4943 if (!NT_STATUS_IS_OK(status)) {
4944 END_PROFILE(SMBmv);
4945 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4946 /* We have re-scheduled this call. */
4947 return -1;
4949 return ERROR_NT(status);
4952 outsize = set_message(inbuf,outbuf,0,0,False);
4954 END_PROFILE(SMBmv);
4955 return(outsize);
4958 /*******************************************************************
4959 Copy a file as part of a reply_copy.
4960 ******************************************************************/
4963 * TODO: check error codes on all callers
4966 NTSTATUS copy_file(connection_struct *conn,
4967 char *src,
4968 char *dest1,
4969 int ofun,
4970 int count,
4971 BOOL target_is_directory)
4973 SMB_STRUCT_STAT src_sbuf, sbuf2;
4974 SMB_OFF_T ret=-1;
4975 files_struct *fsp1,*fsp2;
4976 pstring dest;
4977 uint32 dosattrs;
4978 uint32 new_create_disposition;
4979 NTSTATUS status;
4981 pstrcpy(dest,dest1);
4982 if (target_is_directory) {
4983 char *p = strrchr_m(src,'/');
4984 if (p) {
4985 p++;
4986 } else {
4987 p = src;
4989 pstrcat(dest,"/");
4990 pstrcat(dest,p);
4993 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4994 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4997 if (!target_is_directory && count) {
4998 new_create_disposition = FILE_OPEN;
4999 } else {
5000 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5001 NULL, NULL, &new_create_disposition, NULL)) {
5002 return NT_STATUS_INVALID_PARAMETER;
5006 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5007 FILE_GENERIC_READ,
5008 FILE_SHARE_READ|FILE_SHARE_WRITE,
5009 FILE_OPEN,
5011 FILE_ATTRIBUTE_NORMAL,
5012 INTERNAL_OPEN_ONLY,
5013 NULL, &fsp1);
5015 if (!NT_STATUS_IS_OK(status)) {
5016 return status;
5019 dosattrs = dos_mode(conn, src, &src_sbuf);
5020 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
5021 ZERO_STRUCTP(&sbuf2);
5024 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
5025 FILE_GENERIC_WRITE,
5026 FILE_SHARE_READ|FILE_SHARE_WRITE,
5027 new_create_disposition,
5029 dosattrs,
5030 INTERNAL_OPEN_ONLY,
5031 NULL, &fsp2);
5033 if (!NT_STATUS_IS_OK(status)) {
5034 close_file(fsp1,ERROR_CLOSE);
5035 return status;
5038 if ((ofun&3) == 1) {
5039 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
5040 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
5042 * Stop the copy from occurring.
5044 ret = -1;
5045 src_sbuf.st_size = 0;
5049 if (src_sbuf.st_size) {
5050 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
5053 close_file(fsp1,NORMAL_CLOSE);
5055 /* Ensure the modtime is set correctly on the destination file. */
5056 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
5059 * As we are opening fsp1 read-only we only expect
5060 * an error on close on fsp2 if we are out of space.
5061 * Thus we don't look at the error return from the
5062 * close of fsp1.
5064 status = close_file(fsp2,NORMAL_CLOSE);
5066 if (!NT_STATUS_IS_OK(status)) {
5067 return status;
5070 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
5071 return NT_STATUS_DISK_FULL;
5074 return NT_STATUS_OK;
5077 /****************************************************************************
5078 Reply to a file copy.
5079 ****************************************************************************/
5081 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5083 int outsize = 0;
5084 pstring name;
5085 pstring directory;
5086 pstring mask,newname;
5087 char *p;
5088 int count=0;
5089 int error = ERRnoaccess;
5090 int err = 0;
5091 int tid2 = SVAL(inbuf,smb_vwv0);
5092 int ofun = SVAL(inbuf,smb_vwv1);
5093 int flags = SVAL(inbuf,smb_vwv2);
5094 BOOL target_is_directory=False;
5095 BOOL source_has_wild = False;
5096 BOOL dest_has_wild = False;
5097 SMB_STRUCT_STAT sbuf1, sbuf2;
5098 NTSTATUS status;
5099 START_PROFILE(SMBcopy);
5101 *directory = *mask = 0;
5103 p = smb_buf(inbuf);
5104 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5105 sizeof(name), 0, STR_TERMINATE, &status,
5106 &source_has_wild);
5107 if (!NT_STATUS_IS_OK(status)) {
5108 END_PROFILE(SMBcopy);
5109 return ERROR_NT(status);
5111 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5112 sizeof(newname), 0, STR_TERMINATE, &status,
5113 &dest_has_wild);
5114 if (!NT_STATUS_IS_OK(status)) {
5115 END_PROFILE(SMBcopy);
5116 return ERROR_NT(status);
5119 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5121 if (tid2 != conn->cnum) {
5122 /* can't currently handle inter share copies XXXX */
5123 DEBUG(3,("Rejecting inter-share copy\n"));
5124 END_PROFILE(SMBcopy);
5125 return ERROR_DOS(ERRSRV,ERRinvdevice);
5128 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5129 if (!NT_STATUS_IS_OK(status)) {
5130 END_PROFILE(SMBcopy);
5131 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5132 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5134 return ERROR_NT(status);
5137 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5138 if (!NT_STATUS_IS_OK(status)) {
5139 END_PROFILE(SMBcopy);
5140 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5141 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5143 return ERROR_NT(status);
5146 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5147 if (!NT_STATUS_IS_OK(status)) {
5148 END_PROFILE(SMBcopy);
5149 return ERROR_NT(status);
5152 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5153 if (!NT_STATUS_IS_OK(status)) {
5154 END_PROFILE(SMBcopy);
5155 return ERROR_NT(status);
5158 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5160 if ((flags&1) && target_is_directory) {
5161 END_PROFILE(SMBcopy);
5162 return ERROR_DOS(ERRDOS,ERRbadfile);
5165 if ((flags&2) && !target_is_directory) {
5166 END_PROFILE(SMBcopy);
5167 return ERROR_DOS(ERRDOS,ERRbadpath);
5170 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5171 /* wants a tree copy! XXXX */
5172 DEBUG(3,("Rejecting tree copy\n"));
5173 END_PROFILE(SMBcopy);
5174 return ERROR_DOS(ERRSRV,ERRerror);
5177 p = strrchr_m(name,'/');
5178 if (!p) {
5179 pstrcpy(directory,"./");
5180 pstrcpy(mask,name);
5181 } else {
5182 *p = 0;
5183 pstrcpy(directory,name);
5184 pstrcpy(mask,p+1);
5188 * We should only check the mangled cache
5189 * here if unix_convert failed. This means
5190 * that the path in 'mask' doesn't exist
5191 * on the file system and so we need to look
5192 * for a possible mangle. This patch from
5193 * Tine Smukavec <valentin.smukavec@hermes.si>.
5196 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5197 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5200 if (!source_has_wild) {
5201 pstrcat(directory,"/");
5202 pstrcat(directory,mask);
5203 if (dest_has_wild) {
5204 if (!resolve_wildcards(directory,newname)) {
5205 END_PROFILE(SMBcopy);
5206 return ERROR_NT(NT_STATUS_NO_MEMORY);
5210 status = check_name(conn, directory);
5211 if (!NT_STATUS_IS_OK(status)) {
5212 return ERROR_NT(status);
5215 status = check_name(conn, newname);
5216 if (!NT_STATUS_IS_OK(status)) {
5217 return ERROR_NT(status);
5220 status = copy_file(conn,directory,newname,ofun,
5221 count,target_is_directory);
5223 if(!NT_STATUS_IS_OK(status)) {
5224 END_PROFILE(SMBcopy);
5225 return ERROR_NT(status);
5226 } else {
5227 count++;
5229 } else {
5230 struct smb_Dir *dir_hnd = NULL;
5231 const char *dname;
5232 long offset = 0;
5233 pstring destname;
5235 if (strequal(mask,"????????.???"))
5236 pstrcpy(mask,"*");
5238 status = check_name(conn, directory);
5239 if (!NT_STATUS_IS_OK(status)) {
5240 return ERROR_NT(status);
5243 dir_hnd = OpenDir(conn, directory, mask, 0);
5244 if (dir_hnd == NULL) {
5245 status = map_nt_error_from_unix(errno);
5246 return ERROR_NT(status);
5249 error = ERRbadfile;
5251 while ((dname = ReadDirName(dir_hnd, &offset))) {
5252 pstring fname;
5253 pstrcpy(fname,dname);
5255 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5256 continue;
5259 if(!mask_match(fname, mask, conn->case_sensitive)) {
5260 continue;
5263 error = ERRnoaccess;
5264 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5265 pstrcpy(destname,newname);
5266 if (!resolve_wildcards(fname,destname)) {
5267 continue;
5270 status = check_name(conn, fname);
5271 if (!NT_STATUS_IS_OK(status)) {
5272 return ERROR_NT(status);
5275 status = check_name(conn, destname);
5276 if (!NT_STATUS_IS_OK(status)) {
5277 return ERROR_NT(status);
5280 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5282 status = copy_file(conn,fname,destname,ofun,
5283 count,target_is_directory);
5284 if (NT_STATUS_IS_OK(status)) {
5285 count++;
5288 CloseDir(dir_hnd);
5291 if (count == 0) {
5292 if(err) {
5293 /* Error on close... */
5294 errno = err;
5295 END_PROFILE(SMBcopy);
5296 return(UNIXERROR(ERRHRD,ERRgeneral));
5299 END_PROFILE(SMBcopy);
5300 return ERROR_DOS(ERRDOS,error);
5303 outsize = set_message(inbuf,outbuf,1,0,True);
5304 SSVAL(outbuf,smb_vwv0,count);
5306 END_PROFILE(SMBcopy);
5307 return(outsize);
5310 /****************************************************************************
5311 Reply to a setdir.
5312 ****************************************************************************/
5314 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5316 int snum;
5317 int outsize = 0;
5318 pstring newdir;
5319 NTSTATUS status;
5321 START_PROFILE(pathworks_setdir);
5323 snum = SNUM(conn);
5324 if (!CAN_SETDIR(snum)) {
5325 END_PROFILE(pathworks_setdir);
5326 return ERROR_DOS(ERRDOS,ERRnoaccess);
5329 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
5330 smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
5331 &status);
5332 if (!NT_STATUS_IS_OK(status)) {
5333 END_PROFILE(pathworks_setdir);
5334 return ERROR_NT(status);
5337 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5338 if (!NT_STATUS_IS_OK(status)) {
5339 END_PROFILE(pathworks_setdir);
5340 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5341 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5343 return ERROR_NT(status);
5346 if (strlen(newdir) != 0) {
5347 if (!vfs_directory_exist(conn,newdir,NULL)) {
5348 END_PROFILE(pathworks_setdir);
5349 return ERROR_DOS(ERRDOS,ERRbadpath);
5351 set_conn_connectpath(conn,newdir);
5354 outsize = set_message(inbuf,outbuf,0,0,False);
5355 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5357 DEBUG(3,("setdir %s\n", newdir));
5359 END_PROFILE(pathworks_setdir);
5360 return(outsize);
5363 #undef DBGC_CLASS
5364 #define DBGC_CLASS DBGC_LOCKING
5366 /****************************************************************************
5367 Get a lock pid, dealing with large count requests.
5368 ****************************************************************************/
5370 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5372 if(!large_file_format)
5373 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5374 else
5375 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5378 /****************************************************************************
5379 Get a lock count, dealing with large count requests.
5380 ****************************************************************************/
5382 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5384 SMB_BIG_UINT count = 0;
5386 if(!large_file_format) {
5387 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5388 } else {
5390 #if defined(HAVE_LONGLONG)
5391 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5392 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5393 #else /* HAVE_LONGLONG */
5396 * NT4.x seems to be broken in that it sends large file (64 bit)
5397 * lockingX calls even if the CAP_LARGE_FILES was *not*
5398 * negotiated. For boxes without large unsigned ints truncate the
5399 * lock count by dropping the top 32 bits.
5402 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5403 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5404 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5405 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5406 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5409 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5410 #endif /* HAVE_LONGLONG */
5413 return count;
5416 #if !defined(HAVE_LONGLONG)
5417 /****************************************************************************
5418 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5419 ****************************************************************************/
5421 static uint32 map_lock_offset(uint32 high, uint32 low)
5423 unsigned int i;
5424 uint32 mask = 0;
5425 uint32 highcopy = high;
5428 * Try and find out how many significant bits there are in high.
5431 for(i = 0; highcopy; i++)
5432 highcopy >>= 1;
5435 * We use 31 bits not 32 here as POSIX
5436 * lock offsets may not be negative.
5439 mask = (~0) << (31 - i);
5441 if(low & mask)
5442 return 0; /* Fail. */
5444 high <<= (31 - i);
5446 return (high|low);
5448 #endif /* !defined(HAVE_LONGLONG) */
5450 /****************************************************************************
5451 Get a lock offset, dealing with large offset requests.
5452 ****************************************************************************/
5454 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5456 SMB_BIG_UINT offset = 0;
5458 *err = False;
5460 if(!large_file_format) {
5461 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5462 } else {
5464 #if defined(HAVE_LONGLONG)
5465 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5466 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5467 #else /* HAVE_LONGLONG */
5470 * NT4.x seems to be broken in that it sends large file (64 bit)
5471 * lockingX calls even if the CAP_LARGE_FILES was *not*
5472 * negotiated. For boxes without large unsigned ints mangle the
5473 * lock offset by mapping the top 32 bits onto the lower 32.
5476 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5477 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5478 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5479 uint32 new_low = 0;
5481 if((new_low = map_lock_offset(high, low)) == 0) {
5482 *err = True;
5483 return (SMB_BIG_UINT)-1;
5486 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5487 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5488 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5489 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5492 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5493 #endif /* HAVE_LONGLONG */
5496 return offset;
5499 /****************************************************************************
5500 Reply to a lockingX request.
5501 ****************************************************************************/
5503 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5504 int length, int bufsize)
5506 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5507 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5508 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5509 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5510 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5511 SMB_BIG_UINT count = 0, offset = 0;
5512 uint32 lock_pid;
5513 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5514 int i;
5515 char *data;
5516 BOOL large_file_format =
5517 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5518 BOOL err;
5519 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5521 START_PROFILE(SMBlockingX);
5523 CHECK_FSP(fsp,conn);
5525 data = smb_buf(inbuf);
5527 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5528 /* we don't support these - and CANCEL_LOCK makes w2k
5529 and XP reboot so I don't really want to be
5530 compatible! (tridge) */
5531 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5534 /* Check if this is an oplock break on a file
5535 we have granted an oplock on.
5537 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5538 /* Client can insist on breaking to none. */
5539 BOOL break_to_none = (oplocklevel == 0);
5540 BOOL result;
5542 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5543 "for fnum = %d\n", (unsigned int)oplocklevel,
5544 fsp->fnum ));
5547 * Make sure we have granted an exclusive or batch oplock on
5548 * this file.
5551 if (fsp->oplock_type == 0) {
5553 /* The Samba4 nbench simulator doesn't understand
5554 the difference between break to level2 and break
5555 to none from level2 - it sends oplock break
5556 replies in both cases. Don't keep logging an error
5557 message here - just ignore it. JRA. */
5559 DEBUG(5,("reply_lockingX: Error : oplock break from "
5560 "client for fnum = %d (oplock=%d) and no "
5561 "oplock granted on this file (%s).\n",
5562 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5564 /* if this is a pure oplock break request then don't
5565 * send a reply */
5566 if (num_locks == 0 && num_ulocks == 0) {
5567 END_PROFILE(SMBlockingX);
5568 return -1;
5569 } else {
5570 END_PROFILE(SMBlockingX);
5571 return ERROR_DOS(ERRDOS,ERRlock);
5575 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5576 (break_to_none)) {
5577 result = remove_oplock(fsp);
5578 } else {
5579 result = downgrade_oplock(fsp);
5582 if (!result) {
5583 DEBUG(0, ("reply_lockingX: error in removing "
5584 "oplock on file %s\n", fsp->fsp_name));
5585 /* Hmmm. Is this panic justified? */
5586 smb_panic("internal tdb error");
5589 reply_to_oplock_break_requests(fsp);
5591 /* if this is a pure oplock break request then don't send a
5592 * reply */
5593 if (num_locks == 0 && num_ulocks == 0) {
5594 /* Sanity check - ensure a pure oplock break is not a
5595 chained request. */
5596 if(CVAL(inbuf,smb_vwv0) != 0xff)
5597 DEBUG(0,("reply_lockingX: Error : pure oplock "
5598 "break is a chained %d request !\n",
5599 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5600 END_PROFILE(SMBlockingX);
5601 return -1;
5606 * We do this check *after* we have checked this is not a oplock break
5607 * response message. JRA.
5610 release_level_2_oplocks_on_change(fsp);
5612 /* Data now points at the beginning of the list
5613 of smb_unlkrng structs */
5614 for(i = 0; i < (int)num_ulocks; i++) {
5615 lock_pid = get_lock_pid( data, i, large_file_format);
5616 count = get_lock_count( data, i, large_file_format);
5617 offset = get_lock_offset( data, i, large_file_format, &err);
5620 * There is no error code marked "stupid client bug".... :-).
5622 if(err) {
5623 END_PROFILE(SMBlockingX);
5624 return ERROR_DOS(ERRDOS,ERRnoaccess);
5627 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5628 "pid %u, file %s\n", (double)offset, (double)count,
5629 (unsigned int)lock_pid, fsp->fsp_name ));
5631 status = do_unlock(smbd_messaging_context(),
5632 fsp,
5633 lock_pid,
5634 count,
5635 offset,
5636 WINDOWS_LOCK);
5638 if (NT_STATUS_V(status)) {
5639 END_PROFILE(SMBlockingX);
5640 return ERROR_NT(status);
5644 /* Setup the timeout in seconds. */
5646 if (!lp_blocking_locks(SNUM(conn))) {
5647 lock_timeout = 0;
5650 /* Now do any requested locks */
5651 data += ((large_file_format ? 20 : 10)*num_ulocks);
5653 /* Data now points at the beginning of the list
5654 of smb_lkrng structs */
5656 for(i = 0; i < (int)num_locks; i++) {
5657 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5658 READ_LOCK:WRITE_LOCK);
5659 lock_pid = get_lock_pid( data, i, large_file_format);
5660 count = get_lock_count( data, i, large_file_format);
5661 offset = get_lock_offset( data, i, large_file_format, &err);
5664 * There is no error code marked "stupid client bug".... :-).
5666 if(err) {
5667 END_PROFILE(SMBlockingX);
5668 return ERROR_DOS(ERRDOS,ERRnoaccess);
5671 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5672 "%u, file %s timeout = %d\n", (double)offset,
5673 (double)count, (unsigned int)lock_pid,
5674 fsp->fsp_name, (int)lock_timeout ));
5676 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5677 if (lp_blocking_locks(SNUM(conn))) {
5679 /* Schedule a message to ourselves to
5680 remove the blocking lock record and
5681 return the right error. */
5683 if (!blocking_lock_cancel(fsp,
5684 lock_pid,
5685 offset,
5686 count,
5687 WINDOWS_LOCK,
5688 locktype,
5689 NT_STATUS_FILE_LOCK_CONFLICT)) {
5690 END_PROFILE(SMBlockingX);
5691 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5694 /* Remove a matching pending lock. */
5695 status = do_lock_cancel(fsp,
5696 lock_pid,
5697 count,
5698 offset,
5699 WINDOWS_LOCK);
5700 } else {
5701 BOOL blocking_lock = lock_timeout ? True : False;
5702 BOOL defer_lock = False;
5703 struct byte_range_lock *br_lck;
5704 uint32 block_smbpid;
5706 br_lck = do_lock(smbd_messaging_context(),
5707 fsp,
5708 lock_pid,
5709 count,
5710 offset,
5711 lock_type,
5712 WINDOWS_LOCK,
5713 blocking_lock,
5714 &status,
5715 &block_smbpid);
5717 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5718 /* Windows internal resolution for blocking locks seems
5719 to be about 200ms... Don't wait for less than that. JRA. */
5720 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5721 lock_timeout = lp_lock_spin_time();
5723 defer_lock = True;
5726 /* This heuristic seems to match W2K3 very well. If a
5727 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5728 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5729 far as I can tell. Replacement for do_lock_spin(). JRA. */
5731 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5732 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5733 defer_lock = True;
5734 lock_timeout = lp_lock_spin_time();
5737 if (br_lck && defer_lock) {
5739 * A blocking lock was requested. Package up
5740 * this smb into a queued request and push it
5741 * onto the blocking lock queue.
5743 if(push_blocking_lock_request(br_lck,
5744 inbuf, length,
5745 fsp,
5746 lock_timeout,
5748 lock_pid,
5749 lock_type,
5750 WINDOWS_LOCK,
5751 offset,
5752 count,
5753 block_smbpid)) {
5754 TALLOC_FREE(br_lck);
5755 END_PROFILE(SMBlockingX);
5756 return -1;
5760 TALLOC_FREE(br_lck);
5763 if (NT_STATUS_V(status)) {
5764 END_PROFILE(SMBlockingX);
5765 return ERROR_NT(status);
5769 /* If any of the above locks failed, then we must unlock
5770 all of the previous locks (X/Open spec). */
5772 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5773 (i != num_locks) &&
5774 (num_locks != 0)) {
5776 * Ensure we don't do a remove on the lock that just failed,
5777 * as under POSIX rules, if we have a lock already there, we
5778 * will delete it (and we shouldn't) .....
5780 for(i--; i >= 0; i--) {
5781 lock_pid = get_lock_pid( data, i, large_file_format);
5782 count = get_lock_count( data, i, large_file_format);
5783 offset = get_lock_offset( data, i, large_file_format,
5784 &err);
5787 * There is no error code marked "stupid client
5788 * bug".... :-).
5790 if(err) {
5791 END_PROFILE(SMBlockingX);
5792 return ERROR_DOS(ERRDOS,ERRnoaccess);
5795 do_unlock(smbd_messaging_context(),
5796 fsp,
5797 lock_pid,
5798 count,
5799 offset,
5800 WINDOWS_LOCK);
5802 END_PROFILE(SMBlockingX);
5803 return ERROR_NT(status);
5806 set_message(inbuf,outbuf,2,0,True);
5808 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5809 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5811 END_PROFILE(SMBlockingX);
5812 return chain_reply(inbuf,&outbuf,length,bufsize);
5815 #undef DBGC_CLASS
5816 #define DBGC_CLASS DBGC_ALL
5818 /****************************************************************************
5819 Reply to a SMBreadbmpx (read block multiplex) request.
5820 ****************************************************************************/
5822 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5824 ssize_t nread = -1;
5825 ssize_t total_read;
5826 char *data;
5827 SMB_OFF_T startpos;
5828 int outsize;
5829 size_t maxcount;
5830 int max_per_packet;
5831 size_t tcount;
5832 int pad;
5833 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5834 START_PROFILE(SMBreadBmpx);
5836 /* this function doesn't seem to work - disable by default */
5837 if (!lp_readbmpx()) {
5838 END_PROFILE(SMBreadBmpx);
5839 return ERROR_DOS(ERRSRV,ERRuseSTD);
5842 outsize = set_message(inbuf,outbuf,8,0,True);
5844 CHECK_FSP(fsp,conn);
5845 if (!CHECK_READ(fsp,inbuf)) {
5846 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5849 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5850 maxcount = SVAL(inbuf,smb_vwv3);
5852 data = smb_buf(outbuf);
5853 pad = ((long)data)%4;
5854 if (pad)
5855 pad = 4 - pad;
5856 data += pad;
5858 max_per_packet = bufsize-(outsize+pad);
5859 tcount = maxcount;
5860 total_read = 0;
5862 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5863 END_PROFILE(SMBreadBmpx);
5864 return ERROR_DOS(ERRDOS,ERRlock);
5867 do {
5868 size_t N = MIN(max_per_packet,tcount-total_read);
5870 nread = read_file(fsp,data,startpos,N);
5872 if (nread <= 0)
5873 nread = 0;
5875 if (nread < (ssize_t)N)
5876 tcount = total_read + nread;
5878 set_message(inbuf,outbuf,8,nread+pad,False);
5879 SIVAL(outbuf,smb_vwv0,startpos);
5880 SSVAL(outbuf,smb_vwv2,tcount);
5881 SSVAL(outbuf,smb_vwv6,nread);
5882 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5884 show_msg(outbuf);
5885 if (!send_smb(smbd_server_fd(),outbuf))
5886 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5888 total_read += nread;
5889 startpos += nread;
5890 } while (total_read < (ssize_t)tcount);
5892 END_PROFILE(SMBreadBmpx);
5893 return(-1);
5896 /****************************************************************************
5897 Reply to a SMBsetattrE.
5898 ****************************************************************************/
5900 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5902 struct timespec ts[2];
5903 int outsize = 0;
5904 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5905 START_PROFILE(SMBsetattrE);
5907 outsize = set_message(inbuf,outbuf,0,0,False);
5909 if(!fsp || (fsp->conn != conn)) {
5910 END_PROFILE(SMBsetattrE);
5911 return ERROR_DOS(ERRDOS,ERRbadfid);
5915 * Convert the DOS times into unix times. Ignore create
5916 * time as UNIX can't set this.
5919 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5920 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5923 * Patch from Ray Frush <frush@engr.colostate.edu>
5924 * Sometimes times are sent as zero - ignore them.
5927 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5928 /* Ignore request */
5929 if( DEBUGLVL( 3 ) ) {
5930 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5931 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5933 END_PROFILE(SMBsetattrE);
5934 return(outsize);
5935 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5936 /* set modify time = to access time if modify time was unset */
5937 ts[1] = ts[0];
5940 /* Set the date on this file */
5941 /* Should we set pending modtime here ? JRA */
5942 if(file_ntimes(conn, fsp->fsp_name, ts)) {
5943 END_PROFILE(SMBsetattrE);
5944 return ERROR_DOS(ERRDOS,ERRnoaccess);
5947 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5948 fsp->fnum,
5949 (unsigned int)ts[0].tv_sec,
5950 (unsigned int)ts[1].tv_sec));
5952 END_PROFILE(SMBsetattrE);
5953 return(outsize);
5957 /* Back from the dead for OS/2..... JRA. */
5959 /****************************************************************************
5960 Reply to a SMBwritebmpx (write block multiplex primary) request.
5961 ****************************************************************************/
5963 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5965 size_t numtowrite;
5966 ssize_t nwritten = -1;
5967 int outsize = 0;
5968 SMB_OFF_T startpos;
5969 size_t tcount;
5970 BOOL write_through;
5971 int smb_doff;
5972 char *data;
5973 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5974 NTSTATUS status;
5975 START_PROFILE(SMBwriteBmpx);
5977 CHECK_FSP(fsp,conn);
5978 if (!CHECK_WRITE(fsp)) {
5979 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5981 if (HAS_CACHED_ERROR(fsp)) {
5982 return(CACHED_ERROR(fsp));
5985 tcount = SVAL(inbuf,smb_vwv1);
5986 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5987 write_through = BITSETW(inbuf+smb_vwv7,0);
5988 numtowrite = SVAL(inbuf,smb_vwv10);
5989 smb_doff = SVAL(inbuf,smb_vwv11);
5991 data = smb_base(inbuf) + smb_doff;
5993 /* If this fails we need to send an SMBwriteC response,
5994 not an SMBwritebmpx - set this up now so we don't forget */
5995 SCVAL(outbuf,smb_com,SMBwritec);
5997 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5998 END_PROFILE(SMBwriteBmpx);
5999 return(ERROR_DOS(ERRDOS,ERRlock));
6002 nwritten = write_file(fsp,data,startpos,numtowrite);
6004 status = sync_file(conn, fsp, write_through);
6005 if (!NT_STATUS_IS_OK(status)) {
6006 END_PROFILE(SMBwriteBmpx);
6007 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
6008 fsp->fsp_name, nt_errstr(status) ));
6009 return ERROR_NT(status);
6012 if(nwritten < (ssize_t)numtowrite) {
6013 END_PROFILE(SMBwriteBmpx);
6014 return(UNIXERROR(ERRHRD,ERRdiskfull));
6017 /* If the maximum to be written to this file
6018 is greater than what we just wrote then set
6019 up a secondary struct to be attached to this
6020 fd, we will use this to cache error messages etc. */
6022 if((ssize_t)tcount > nwritten) {
6023 write_bmpx_struct *wbms;
6024 if(fsp->wbmpx_ptr != NULL)
6025 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
6026 else
6027 wbms = SMB_MALLOC_P(write_bmpx_struct);
6028 if(!wbms) {
6029 DEBUG(0,("Out of memory in reply_readmpx\n"));
6030 END_PROFILE(SMBwriteBmpx);
6031 return(ERROR_DOS(ERRSRV,ERRnoresource));
6033 wbms->wr_mode = write_through;
6034 wbms->wr_discard = False; /* No errors yet */
6035 wbms->wr_total_written = nwritten;
6036 wbms->wr_errclass = 0;
6037 wbms->wr_error = 0;
6038 fsp->wbmpx_ptr = wbms;
6041 /* We are returning successfully, set the message type back to
6042 SMBwritebmpx */
6043 SCVAL(outbuf,smb_com,SMBwriteBmpx);
6045 outsize = set_message(inbuf,outbuf,1,0,True);
6047 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
6049 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
6050 fsp->fnum, (int)numtowrite, (int)nwritten ) );
6052 if (write_through && tcount==nwritten) {
6053 /* We need to send both a primary and a secondary response */
6054 smb_setlen(inbuf,outbuf,outsize - 4);
6055 show_msg(outbuf);
6056 if (!send_smb(smbd_server_fd(),outbuf))
6057 exit_server_cleanly("reply_writebmpx: send_smb failed.");
6059 /* Now the secondary */
6060 outsize = set_message(inbuf,outbuf,1,0,True);
6061 SCVAL(outbuf,smb_com,SMBwritec);
6062 SSVAL(outbuf,smb_vwv0,nwritten);
6065 END_PROFILE(SMBwriteBmpx);
6066 return(outsize);
6069 /****************************************************************************
6070 Reply to a SMBwritebs (write block multiplex secondary) request.
6071 ****************************************************************************/
6073 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
6075 size_t numtowrite;
6076 ssize_t nwritten = -1;
6077 int outsize = 0;
6078 SMB_OFF_T startpos;
6079 size_t tcount;
6080 BOOL write_through;
6081 int smb_doff;
6082 char *data;
6083 write_bmpx_struct *wbms;
6084 BOOL send_response = False;
6085 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
6086 NTSTATUS status;
6087 START_PROFILE(SMBwriteBs);
6089 CHECK_FSP(fsp,conn);
6090 if (!CHECK_WRITE(fsp)) {
6091 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6094 tcount = SVAL(inbuf,smb_vwv1);
6095 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6096 numtowrite = SVAL(inbuf,smb_vwv6);
6097 smb_doff = SVAL(inbuf,smb_vwv7);
6099 data = smb_base(inbuf) + smb_doff;
6101 /* We need to send an SMBwriteC response, not an SMBwritebs */
6102 SCVAL(outbuf,smb_com,SMBwritec);
6104 /* This fd should have an auxiliary struct attached,
6105 check that it does */
6106 wbms = fsp->wbmpx_ptr;
6107 if(!wbms) {
6108 END_PROFILE(SMBwriteBs);
6109 return(-1);
6112 /* If write through is set we can return errors, else we must cache them */
6113 write_through = wbms->wr_mode;
6115 /* Check for an earlier error */
6116 if(wbms->wr_discard) {
6117 END_PROFILE(SMBwriteBs);
6118 return -1; /* Just discard the packet */
6121 nwritten = write_file(fsp,data,startpos,numtowrite);
6123 status = sync_file(conn, fsp, write_through);
6125 if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6126 if(write_through) {
6127 /* We are returning an error - we can delete the aux struct */
6128 if (wbms)
6129 free((char *)wbms);
6130 fsp->wbmpx_ptr = NULL;
6131 END_PROFILE(SMBwriteBs);
6132 return(ERROR_DOS(ERRHRD,ERRdiskfull));
6134 wbms->wr_errclass = ERRHRD;
6135 wbms->wr_error = ERRdiskfull;
6136 wbms->wr_status = NT_STATUS_DISK_FULL;
6137 wbms->wr_discard = True;
6138 END_PROFILE(SMBwriteBs);
6139 return -1;
6142 /* Increment the total written, if this matches tcount
6143 we can discard the auxiliary struct (hurrah !) and return a writeC */
6144 wbms->wr_total_written += nwritten;
6145 if(wbms->wr_total_written >= tcount) {
6146 if (write_through) {
6147 outsize = set_message(inbuf,outbuf,1,0,True);
6148 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
6149 send_response = True;
6152 free((char *)wbms);
6153 fsp->wbmpx_ptr = NULL;
6156 if(send_response) {
6157 END_PROFILE(SMBwriteBs);
6158 return(outsize);
6161 END_PROFILE(SMBwriteBs);
6162 return(-1);
6165 /****************************************************************************
6166 Reply to a SMBgetattrE.
6167 ****************************************************************************/
6169 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6171 SMB_STRUCT_STAT sbuf;
6172 int outsize = 0;
6173 int mode;
6174 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
6175 START_PROFILE(SMBgetattrE);
6177 outsize = set_message(inbuf,outbuf,11,0,True);
6179 if(!fsp || (fsp->conn != conn)) {
6180 END_PROFILE(SMBgetattrE);
6181 return ERROR_DOS(ERRDOS,ERRbadfid);
6184 /* Do an fstat on this file */
6185 if(fsp_stat(fsp, &sbuf)) {
6186 END_PROFILE(SMBgetattrE);
6187 return(UNIXERROR(ERRDOS,ERRnoaccess));
6190 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6193 * Convert the times into dos times. Set create
6194 * date to be last modify date as UNIX doesn't save
6195 * this.
6198 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6199 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6200 /* Should we check pending modtime here ? JRA */
6201 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6203 if (mode & aDIR) {
6204 SIVAL(outbuf,smb_vwv6,0);
6205 SIVAL(outbuf,smb_vwv8,0);
6206 } else {
6207 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6208 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6209 SIVAL(outbuf,smb_vwv8,allocation_size);
6211 SSVAL(outbuf,smb_vwv10, mode);
6213 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6215 END_PROFILE(SMBgetattrE);
6216 return(outsize);