r17915: Saturn fixes
[Samba/gbeck.git] / source / smbd / reply.c
blobe68e8662d74f2a236e3851f104e6e10cd67eb103
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-2004.
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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
27 #include "includes.h"
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_send;
32 extern int max_recv;
33 unsigned int smb_echo_count = 0;
34 extern uint32 global_client_caps;
36 extern struct current_user current_user;
37 extern BOOL global_encrypted_passwords_negotiated;
39 /****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
41 We're assuming here that '/' is not the second byte in any multibyte char
42 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
43 set.
44 ****************************************************************************/
46 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
48 char *d = destname;
49 const char *s = srcname;
50 NTSTATUS ret = NT_STATUS_OK;
51 BOOL start_of_name_component = True;
52 unsigned int num_bad_components = 0;
54 while (*s) {
55 if (IS_DIRECTORY_SEP(*s)) {
57 * Safe to assume is not the second part of a mb char as this is handled below.
59 /* Eat multiple '/' or '\\' */
60 while (IS_DIRECTORY_SEP(*s)) {
61 s++;
63 if ((d != destname) && (*s != '\0')) {
64 /* We only care about non-leading or trailing '/' or '\\' */
65 *d++ = '/';
68 start_of_name_component = True;
69 continue;
72 if (start_of_name_component) {
73 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
74 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
77 * No mb char starts with '.' so we're safe checking the directory separator here.
80 /* If we just added a '/' - delete it */
81 if ((d > destname) && (*(d-1) == '/')) {
82 *(d-1) = '\0';
83 d--;
86 /* Are we at the start ? Can't go back further if so. */
87 if (d <= destname) {
88 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
89 break;
91 /* Go back one level... */
92 /* We know this is safe as '/' cannot be part of a mb sequence. */
93 /* NOTE - if this assumption is invalid we are not in good shape... */
94 /* Decrement d first as d points to the *next* char to write into. */
95 for (d--; d > destname; d--) {
96 if (*d == '/')
97 break;
99 s += 2; /* Else go past the .. */
100 /* We're still at the start of a name component, just the previous one. */
102 if (num_bad_components) {
103 /* Hmmm. Should we only decrement the bad_components if
104 we're removing a bad component ? Need to check this. JRA. */
105 num_bad_components--;
108 continue;
110 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
111 /* Component of pathname can't be "." only. */
112 ret = NT_STATUS_OBJECT_NAME_INVALID;
113 num_bad_components++;
114 *d++ = *s++;
115 continue;
119 if (!(*s & 0x80)) {
120 if (*s <= 0x1f) {
121 return NT_STATUS_OBJECT_NAME_INVALID;
123 switch (*s) {
124 case '*':
125 case '?':
126 case '<':
127 case '>':
128 case '"':
129 return NT_STATUS_OBJECT_NAME_INVALID;
130 default:
131 *d++ = *s++;
132 break;
134 } else {
135 switch(next_mb_char_size(s)) {
136 case 4:
137 *d++ = *s++;
138 case 3:
139 *d++ = *s++;
140 case 2:
141 *d++ = *s++;
142 case 1:
143 *d++ = *s++;
144 break;
145 default:
146 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
147 *d = '\0';
148 return NT_STATUS_INVALID_PARAMETER;
151 if (start_of_name_component && num_bad_components) {
152 num_bad_components++;
154 start_of_name_component = False;
157 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
158 if (num_bad_components > 1) {
159 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
163 *d = '\0';
164 return ret;
167 /****************************************************************************
168 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
169 path or anything including wildcards.
170 We're assuming here that '/' is not the second byte in any multibyte char
171 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
172 set.
173 ****************************************************************************/
175 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
177 char *d = destname;
178 const char *s = srcname;
179 NTSTATUS ret = NT_STATUS_OK;
180 BOOL start_of_name_component = True;
181 unsigned int num_bad_components = 0;
183 *p_contains_wcard = False;
185 while (*s) {
186 if (IS_DIRECTORY_SEP(*s)) {
188 * Safe to assume is not the second part of a mb char as this is handled below.
190 /* Eat multiple '/' or '\\' */
191 while (IS_DIRECTORY_SEP(*s)) {
192 s++;
194 if ((d != destname) && (*s != '\0')) {
195 /* We only care about non-leading or trailing '/' or '\\' */
196 *d++ = '/';
199 start_of_name_component = True;
200 continue;
203 if (start_of_name_component) {
204 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
205 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
208 * No mb char starts with '.' so we're safe checking the directory separator here.
211 /* If we just added a '/' - delete it */
212 if ((d > destname) && (*(d-1) == '/')) {
213 *(d-1) = '\0';
214 d--;
217 /* Are we at the start ? Can't go back further if so. */
218 if (d <= destname) {
219 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
220 break;
222 /* Go back one level... */
223 /* We know this is safe as '/' cannot be part of a mb sequence. */
224 /* NOTE - if this assumption is invalid we are not in good shape... */
225 /* Decrement d first as d points to the *next* char to write into. */
226 for (d--; d > destname; d--) {
227 if (*d == '/')
228 break;
230 s += 2; /* Else go past the .. */
231 /* We're still at the start of a name component, just the previous one. */
233 if (num_bad_components) {
234 /* Hmmm. Should we only decrement the bad_components if
235 we're removing a bad component ? Need to check this. JRA. */
236 num_bad_components--;
239 continue;
241 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
242 /* Component of pathname can't be "." only. */
243 ret = NT_STATUS_OBJECT_NAME_INVALID;
244 num_bad_components++;
245 *d++ = *s++;
246 continue;
250 if (!(*s & 0x80)) {
251 if (*s <= 0x1f) {
252 return NT_STATUS_OBJECT_NAME_INVALID;
254 if (!*p_contains_wcard) {
255 switch (*s) {
256 case '*':
257 case '?':
258 case '<':
259 case '>':
260 case '"':
261 *p_contains_wcard = True;
262 break;
263 default:
264 break;
267 *d++ = *s++;
268 } else {
269 switch(next_mb_char_size(s)) {
270 case 4:
271 *d++ = *s++;
272 /*fall through*/
273 case 3:
274 *d++ = *s++;
275 /*fall through*/
276 case 2:
277 *d++ = *s++;
278 /*fall through*/
279 case 1:
280 *d++ = *s++;
281 break;
282 default:
283 DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
284 *d = '\0';
285 return NT_STATUS_INVALID_PARAMETER;
288 if (start_of_name_component && num_bad_components) {
289 num_bad_components++;
291 start_of_name_component = False;
294 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
295 /* For some strange reason being called from findfirst changes
296 the num_components number to cause the error return to change. JRA. */
297 if (num_bad_components > 2) {
298 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
302 *d = '\0';
303 return ret;
306 /****************************************************************************
307 Check the path for a POSIX client.
308 We're assuming here that '/' is not the second byte in any multibyte char
309 set (a safe assumption).
310 ****************************************************************************/
312 NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
314 char *d = destname;
315 const char *s = srcname;
316 NTSTATUS ret = NT_STATUS_OK;
317 BOOL start_of_name_component = True;
319 while (*s) {
320 if (*s == '/') {
322 * Safe to assume is not the second part of a mb char as this is handled below.
324 /* Eat multiple '/' or '\\' */
325 while (*s == '/') {
326 s++;
328 if ((d != destname) && (*s != '\0')) {
329 /* We only care about non-leading or trailing '/' */
330 *d++ = '/';
333 start_of_name_component = True;
334 continue;
337 if (start_of_name_component) {
338 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
339 /* Uh oh - "/../" or "/..\0" ! */
342 * No mb char starts with '.' so we're safe checking the directory separator here.
345 /* If we just added a '/' - delete it */
346 if ((d > destname) && (*(d-1) == '/')) {
347 *(d-1) = '\0';
348 d--;
351 /* Are we at the start ? Can't go back further if so. */
352 if (d <= destname) {
353 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
354 break;
356 /* Go back one level... */
357 /* We know this is safe as '/' cannot be part of a mb sequence. */
358 /* NOTE - if this assumption is invalid we are not in good shape... */
359 /* Decrement d first as d points to the *next* char to write into. */
360 for (d--; d > destname; d--) {
361 if (*d == '/')
362 break;
364 s += 2; /* Else go past the .. */
365 continue;
367 } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) {
368 /* Eat the '.' */
369 s++;
370 continue;
374 if (!(*s & 0x80)) {
375 *d++ = *s++;
376 } else {
377 switch(next_mb_char_size(s)) {
378 case 4:
379 *d++ = *s++;
380 /*fall through*/
381 case 3:
382 *d++ = *s++;
383 /*fall through*/
384 case 2:
385 *d++ = *s++;
386 /*fall through*/
387 case 1:
388 *d++ = *s++;
389 break;
390 default:
391 DEBUG(0,("check_path_syntax_posix: character length assumptions invalid !\n"));
392 *d = '\0';
393 return NT_STATUS_INVALID_PARAMETER;
396 start_of_name_component = False;
399 *d = '\0';
400 return ret;
403 /****************************************************************************
404 Pull a string and check the path allowing a wilcard - provide for error return.
405 ****************************************************************************/
407 size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
408 NTSTATUS *err, BOOL *contains_wcard)
410 pstring tmppath;
411 char *tmppath_ptr = tmppath;
412 size_t ret;
413 #ifdef DEVELOPER
414 SMB_ASSERT(dest_len == sizeof(pstring));
415 #endif
417 if (src_len == 0) {
418 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
419 } else {
420 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
423 *contains_wcard = False;
425 if (lp_posix_pathnames()) {
426 *err = check_path_syntax_posix(dest, tmppath);
427 } else {
428 *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
430 return ret;
433 /****************************************************************************
434 Pull a string and check the path - provide for error return.
435 ****************************************************************************/
437 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
439 pstring tmppath;
440 char *tmppath_ptr = tmppath;
441 size_t ret;
442 #ifdef DEVELOPER
443 SMB_ASSERT(dest_len == sizeof(pstring));
444 #endif
446 if (src_len == 0) {
447 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
448 } else {
449 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
451 if (lp_posix_pathnames()) {
452 *err = check_path_syntax_posix(dest, tmppath);
453 } else {
454 *err = check_path_syntax(dest, tmppath);
456 return ret;
459 /****************************************************************************
460 Reply to a special message.
461 ****************************************************************************/
463 int reply_special(char *inbuf,char *outbuf)
465 int outsize = 4;
466 int msg_type = CVAL(inbuf,0);
467 int msg_flags = CVAL(inbuf,1);
468 fstring name1,name2;
469 char name_type = 0;
471 static BOOL already_got_session = False;
473 *name1 = *name2 = 0;
475 memset(outbuf,'\0',smb_size);
477 smb_setlen(outbuf,0);
479 switch (msg_type) {
480 case 0x81: /* session request */
482 if (already_got_session) {
483 exit_server("multiple session request not permitted");
486 SCVAL(outbuf,0,0x82);
487 SCVAL(outbuf,3,0);
488 if (name_len(inbuf+4) > 50 ||
489 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
490 DEBUG(0,("Invalid name length in session request\n"));
491 return(0);
493 name_extract(inbuf,4,name1);
494 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
495 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
496 name1,name2));
498 set_local_machine_name(name1, True);
499 set_remote_machine_name(name2, True);
501 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
502 get_local_machine_name(), get_remote_machine_name(),
503 name_type));
505 if (name_type == 'R') {
506 /* We are being asked for a pathworks session ---
507 no thanks! */
508 SCVAL(outbuf, 0,0x83);
509 break;
512 /* only add the client's machine name to the list
513 of possibly valid usernames if we are operating
514 in share mode security */
515 if (lp_security() == SEC_SHARE) {
516 add_session_user(get_remote_machine_name());
519 reload_services(True);
520 reopen_logs();
522 already_got_session = True;
523 break;
525 case 0x89: /* session keepalive request
526 (some old clients produce this?) */
527 SCVAL(outbuf,0,SMBkeepalive);
528 SCVAL(outbuf,3,0);
529 break;
531 case 0x82: /* positive session response */
532 case 0x83: /* negative session response */
533 case 0x84: /* retarget session response */
534 DEBUG(0,("Unexpected session response\n"));
535 break;
537 case SMBkeepalive: /* session keepalive */
538 default:
539 return(0);
542 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
543 msg_type, msg_flags));
545 return(outsize);
548 /****************************************************************************
549 Reply to a tcon.
550 conn POINTER CAN BE NULL HERE !
551 ****************************************************************************/
553 int reply_tcon(connection_struct *conn,
554 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
556 const char *service;
557 pstring service_buf;
558 pstring password;
559 pstring dev;
560 int outsize = 0;
561 uint16 vuid = SVAL(inbuf,smb_uid);
562 int pwlen=0;
563 NTSTATUS nt_status;
564 char *p;
565 DATA_BLOB password_blob;
567 START_PROFILE(SMBtcon);
569 *service_buf = *password = *dev = 0;
571 p = smb_buf(inbuf)+1;
572 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
573 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
574 p += pwlen;
575 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
577 p = strrchr_m(service_buf,'\\');
578 if (p) {
579 service = p+1;
580 } else {
581 service = service_buf;
584 password_blob = data_blob(password, pwlen+1);
586 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
588 data_blob_clear_free(&password_blob);
590 if (!conn) {
591 END_PROFILE(SMBtcon);
592 return ERROR_NT(nt_status);
595 outsize = set_message(outbuf,2,0,True);
596 SSVAL(outbuf,smb_vwv0,max_recv);
597 SSVAL(outbuf,smb_vwv1,conn->cnum);
598 SSVAL(outbuf,smb_tid,conn->cnum);
600 DEBUG(3,("tcon service=%s cnum=%d\n",
601 service, conn->cnum));
603 END_PROFILE(SMBtcon);
604 return(outsize);
607 /****************************************************************************
608 Reply to a tcon and X.
609 conn POINTER CAN BE NULL HERE !
610 ****************************************************************************/
612 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
614 fstring service;
615 DATA_BLOB password;
617 /* what the cleint thinks the device is */
618 fstring client_devicetype;
619 /* what the server tells the client the share represents */
620 const char *server_devicetype;
621 NTSTATUS nt_status;
622 uint16 vuid = SVAL(inbuf,smb_uid);
623 int passlen = SVAL(inbuf,smb_vwv3);
624 pstring path;
625 char *p, *q;
627 START_PROFILE(SMBtconX);
629 *service = *client_devicetype = 0;
631 /* we might have to close an old one */
632 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
633 close_cnum(conn,vuid);
636 if (passlen > MAX_PASS_LEN) {
637 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
640 if (global_encrypted_passwords_negotiated) {
641 password = data_blob(smb_buf(inbuf),passlen);
642 } else {
643 password = data_blob(smb_buf(inbuf),passlen+1);
644 /* Ensure correct termination */
645 password.data[passlen]=0;
648 p = smb_buf(inbuf) + passlen;
649 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
652 * the service name can be either: \\server\share
653 * or share directly like on the DELL PowerVault 705
655 if (*path=='\\') {
656 q = strchr_m(path+2,'\\');
657 if (!q) {
658 END_PROFILE(SMBtconX);
659 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
661 fstrcpy(service,q+1);
663 else
664 fstrcpy(service,path);
666 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
668 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
670 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
672 data_blob_clear_free(&password);
674 if (!conn) {
675 END_PROFILE(SMBtconX);
676 return ERROR_NT(nt_status);
679 if ( IS_IPC(conn) )
680 server_devicetype = "IPC";
681 else if ( IS_PRINT(conn) )
682 server_devicetype = "LPT1:";
683 else
684 server_devicetype = "A:";
686 if (Protocol < PROTOCOL_NT1) {
687 set_message(outbuf,2,0,True);
688 p = smb_buf(outbuf);
689 p += srvstr_push(outbuf, p, server_devicetype, -1,
690 STR_TERMINATE|STR_ASCII);
691 set_message_end(outbuf,p);
692 } else {
693 /* NT sets the fstype of IPC$ to the null string */
694 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
696 set_message(outbuf,3,0,True);
698 p = smb_buf(outbuf);
699 p += srvstr_push(outbuf, p, server_devicetype, -1,
700 STR_TERMINATE|STR_ASCII);
701 p += srvstr_push(outbuf, p, fstype, -1,
702 STR_TERMINATE);
704 set_message_end(outbuf,p);
706 /* what does setting this bit do? It is set by NT4 and
707 may affect the ability to autorun mounted cdroms */
708 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
709 (lp_csc_policy(SNUM(conn)) << 2));
711 init_dfsroot(conn, inbuf, outbuf);
715 DEBUG(3,("tconX service=%s \n",
716 service));
718 /* set the incoming and outgoing tid to the just created one */
719 SSVAL(inbuf,smb_tid,conn->cnum);
720 SSVAL(outbuf,smb_tid,conn->cnum);
722 END_PROFILE(SMBtconX);
723 return chain_reply(inbuf,outbuf,length,bufsize);
726 /****************************************************************************
727 Reply to an unknown type.
728 ****************************************************************************/
730 int reply_unknown(char *inbuf,char *outbuf)
732 int type;
733 type = CVAL(inbuf,smb_com);
735 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
736 smb_fn_name(type), type, type));
738 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
741 /****************************************************************************
742 Reply to an ioctl.
743 conn POINTER CAN BE NULL HERE !
744 ****************************************************************************/
746 int reply_ioctl(connection_struct *conn,
747 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
749 uint16 device = SVAL(inbuf,smb_vwv1);
750 uint16 function = SVAL(inbuf,smb_vwv2);
751 uint32 ioctl_code = (device << 16) + function;
752 int replysize, outsize;
753 char *p;
754 START_PROFILE(SMBioctl);
756 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
758 switch (ioctl_code) {
759 case IOCTL_QUERY_JOB_INFO:
760 replysize = 32;
761 break;
762 default:
763 END_PROFILE(SMBioctl);
764 return(ERROR_DOS(ERRSRV,ERRnosupport));
767 outsize = set_message(outbuf,8,replysize+1,True);
768 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
769 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
770 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
771 p = smb_buf(outbuf) + 1; /* Allow for alignment */
773 switch (ioctl_code) {
774 case IOCTL_QUERY_JOB_INFO:
776 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
777 if (!fsp) {
778 END_PROFILE(SMBioctl);
779 return(UNIXERROR(ERRDOS,ERRbadfid));
781 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
782 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
783 if (conn) {
784 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
786 break;
790 END_PROFILE(SMBioctl);
791 return outsize;
794 /****************************************************************************
795 Reply to a chkpth.
796 ****************************************************************************/
798 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
800 int outsize = 0;
801 pstring name;
802 BOOL ok = False;
803 BOOL bad_path = False;
804 SMB_STRUCT_STAT sbuf;
805 NTSTATUS status;
807 START_PROFILE(SMBchkpth);
809 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
810 if (!NT_STATUS_IS_OK(status)) {
811 END_PROFILE(SMBchkpth);
812 return ERROR_NT(status);
815 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
817 unix_convert(name,conn,0,&bad_path,&sbuf);
818 if (bad_path) {
819 END_PROFILE(SMBchkpth);
820 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
823 if (check_name(name,conn)) {
824 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
825 if (!(ok = S_ISDIR(sbuf.st_mode))) {
826 END_PROFILE(SMBchkpth);
827 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
831 if (!ok) {
832 /* We special case this - as when a Windows machine
833 is parsing a path is steps through the components
834 one at a time - if a component fails it expects
835 ERRbadpath, not ERRbadfile.
837 if(errno == ENOENT) {
839 * Windows returns different error codes if
840 * the parent directory is valid but not the
841 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
842 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
843 * if the path is invalid. This is different from set_bad_path_error()
844 * in the non-NT error case.
846 END_PROFILE(SMBchkpth);
847 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
850 END_PROFILE(SMBchkpth);
851 return(UNIXERROR(ERRDOS,ERRbadpath));
854 outsize = set_message(outbuf,0,0,False);
855 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
857 END_PROFILE(SMBchkpth);
858 return(outsize);
861 /****************************************************************************
862 Reply to a getatr.
863 ****************************************************************************/
865 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
867 pstring fname;
868 int outsize = 0;
869 SMB_STRUCT_STAT sbuf;
870 BOOL ok = False;
871 int mode=0;
872 SMB_OFF_T size=0;
873 time_t mtime=0;
874 BOOL bad_path = False;
875 char *p;
876 NTSTATUS status;
878 START_PROFILE(SMBgetatr);
880 p = smb_buf(inbuf) + 1;
881 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
882 if (!NT_STATUS_IS_OK(status)) {
883 END_PROFILE(SMBgetatr);
884 return ERROR_NT(status);
887 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
889 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
890 under WfWg - weird! */
891 if (! (*fname)) {
892 mode = aHIDDEN | aDIR;
893 if (!CAN_WRITE(conn))
894 mode |= aRONLY;
895 size = 0;
896 mtime = 0;
897 ok = True;
898 } else {
899 unix_convert(fname,conn,0,&bad_path,&sbuf);
900 if (bad_path) {
901 END_PROFILE(SMBgetatr);
902 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
904 if (check_name(fname,conn)) {
905 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
906 mode = dos_mode(conn,fname,&sbuf);
907 size = sbuf.st_size;
908 mtime = sbuf.st_mtime;
909 if (mode & aDIR)
910 size = 0;
911 ok = True;
912 } else {
913 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
918 if (!ok) {
919 END_PROFILE(SMBgetatr);
920 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
923 outsize = set_message(outbuf,10,0,True);
925 SSVAL(outbuf,smb_vwv0,mode);
926 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
927 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
928 } else {
929 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
931 SIVAL(outbuf,smb_vwv3,(uint32)size);
933 if (Protocol >= PROTOCOL_NT1) {
934 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
937 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
939 END_PROFILE(SMBgetatr);
940 return(outsize);
943 /****************************************************************************
944 Reply to a setatr.
945 ****************************************************************************/
947 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
949 pstring fname;
950 int outsize = 0;
951 BOOL ok=False;
952 int mode;
953 time_t mtime;
954 SMB_STRUCT_STAT sbuf;
955 BOOL bad_path = False;
956 char *p;
957 NTSTATUS status;
959 START_PROFILE(SMBsetatr);
961 p = smb_buf(inbuf) + 1;
962 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
963 if (!NT_STATUS_IS_OK(status)) {
964 END_PROFILE(SMBsetatr);
965 return ERROR_NT(status);
968 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
970 unix_convert(fname,conn,0,&bad_path,&sbuf);
971 if (bad_path) {
972 END_PROFILE(SMBsetatr);
973 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
976 mode = SVAL(inbuf,smb_vwv0);
977 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
979 if (mode != FILE_ATTRIBUTE_NORMAL) {
980 if (VALID_STAT_OF_DIR(sbuf))
981 mode |= aDIR;
982 else
983 mode &= ~aDIR;
985 if (check_name(fname,conn)) {
986 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
988 } else {
989 ok = True;
992 if (ok)
993 ok = set_filetime(conn,fname,mtime);
995 if (!ok) {
996 END_PROFILE(SMBsetatr);
997 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1000 outsize = set_message(outbuf,0,0,False);
1002 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1004 END_PROFILE(SMBsetatr);
1005 return(outsize);
1008 /****************************************************************************
1009 Reply to a dskattr.
1010 ****************************************************************************/
1012 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1014 int outsize = 0;
1015 SMB_BIG_UINT dfree,dsize,bsize;
1016 START_PROFILE(SMBdskattr);
1018 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1019 END_PROFILE(SMBdskattr);
1020 return(UNIXERROR(ERRHRD,ERRgeneral));
1023 outsize = set_message(outbuf,5,0,True);
1025 if (Protocol <= PROTOCOL_LANMAN2) {
1026 double total_space, free_space;
1027 /* we need to scale this to a number that DOS6 can handle. We
1028 use floating point so we can handle large drives on systems
1029 that don't have 64 bit integers
1031 we end up displaying a maximum of 2G to DOS systems
1033 total_space = dsize * (double)bsize;
1034 free_space = dfree * (double)bsize;
1036 dsize = (total_space+63*512) / (64*512);
1037 dfree = (free_space+63*512) / (64*512);
1039 if (dsize > 0xFFFF) dsize = 0xFFFF;
1040 if (dfree > 0xFFFF) dfree = 0xFFFF;
1042 SSVAL(outbuf,smb_vwv0,dsize);
1043 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1044 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
1045 SSVAL(outbuf,smb_vwv3,dfree);
1046 } else {
1047 SSVAL(outbuf,smb_vwv0,dsize);
1048 SSVAL(outbuf,smb_vwv1,bsize/512);
1049 SSVAL(outbuf,smb_vwv2,512);
1050 SSVAL(outbuf,smb_vwv3,dfree);
1053 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1055 END_PROFILE(SMBdskattr);
1056 return(outsize);
1059 /****************************************************************************
1060 Reply to a search.
1061 Can be called from SMBsearch, SMBffirst or SMBfunique.
1062 ****************************************************************************/
1064 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1066 pstring mask;
1067 pstring directory;
1068 pstring fname;
1069 SMB_OFF_T size;
1070 uint32 mode;
1071 time_t date;
1072 uint32 dirtype;
1073 int outsize = 0;
1074 unsigned int numentries = 0;
1075 unsigned int maxentries = 0;
1076 BOOL finished = False;
1077 char *p;
1078 BOOL ok = False;
1079 int status_len;
1080 pstring path;
1081 char status[21];
1082 int dptr_num= -1;
1083 BOOL check_descend = False;
1084 BOOL expect_close = False;
1085 BOOL can_open = True;
1086 BOOL bad_path = False;
1087 NTSTATUS nt_status;
1088 BOOL mask_contains_wcard = False;
1089 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1091 START_PROFILE(SMBsearch);
1093 if (lp_posix_pathnames()) {
1094 END_PROFILE(SMBsearch);
1095 return reply_unknown(inbuf, outbuf);
1098 *mask = *directory = *fname = 0;
1100 /* If we were called as SMBffirst then we must expect close. */
1101 if(CVAL(inbuf,smb_com) == SMBffirst)
1102 expect_close = True;
1104 outsize = set_message(outbuf,1,3,True);
1105 maxentries = SVAL(inbuf,smb_vwv0);
1106 dirtype = SVAL(inbuf,smb_vwv1);
1107 p = smb_buf(inbuf) + 1;
1108 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
1109 if (!NT_STATUS_IS_OK(nt_status)) {
1110 END_PROFILE(SMBsearch);
1111 return ERROR_NT(nt_status);
1114 RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
1116 p++;
1117 status_len = SVAL(p, 0);
1118 p += 2;
1120 /* dirtype &= ~aDIR; */
1122 if (status_len == 0) {
1123 SMB_STRUCT_STAT sbuf;
1124 pstring dir2;
1126 pstrcpy(directory,path);
1127 pstrcpy(dir2,path);
1128 unix_convert(directory,conn,0,&bad_path,&sbuf);
1129 unix_format(dir2);
1131 if (!check_name(directory,conn))
1132 can_open = False;
1134 p = strrchr_m(dir2,'/');
1135 if (p == NULL) {
1136 pstrcpy(mask,dir2);
1137 *dir2 = 0;
1138 } else {
1139 *p = 0;
1140 pstrcpy(mask,p+1);
1143 p = strrchr_m(directory,'/');
1144 if (!p)
1145 *directory = 0;
1146 else
1147 *p = 0;
1149 if (strlen(directory) == 0)
1150 pstrcpy(directory,".");
1151 memset((char *)status,'\0',21);
1152 SCVAL(status,0,(dirtype & 0x1F));
1153 } else {
1154 int status_dirtype;
1156 memcpy(status,p,21);
1157 status_dirtype = CVAL(status,0) & 0x1F;
1158 if (status_dirtype != (dirtype & 0x1F))
1159 dirtype = status_dirtype;
1161 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1162 if (!conn->dirptr)
1163 goto SearchEmpty;
1164 string_set(&conn->dirpath,dptr_path(dptr_num));
1165 pstrcpy(mask, dptr_wcard(dptr_num));
1168 if (can_open) {
1169 p = smb_buf(outbuf) + 3;
1170 ok = True;
1172 if (status_len == 0) {
1173 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1174 if (dptr_num < 0) {
1175 if(dptr_num == -2) {
1176 END_PROFILE(SMBsearch);
1177 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
1179 END_PROFILE(SMBsearch);
1180 return ERROR_DOS(ERRDOS,ERRnofids);
1182 } else {
1183 dirtype = dptr_attr(dptr_num);
1186 DEBUG(4,("dptr_num is %d\n",dptr_num));
1188 if (ok) {
1189 if ((dirtype&0x1F) == aVOLID) {
1190 memcpy(p,status,21);
1191 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1192 0,aVOLID,0,!allow_long_path_components);
1193 dptr_fill(p+12,dptr_num);
1194 if (dptr_zero(p+12) && (status_len==0))
1195 numentries = 1;
1196 else
1197 numentries = 0;
1198 p += DIR_STRUCT_SIZE;
1199 } else {
1200 unsigned int i;
1201 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1203 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1204 conn->dirpath,lp_dontdescend(SNUM(conn))));
1205 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1206 check_descend = True;
1208 for (i=numentries;(i<maxentries) && !finished;i++) {
1209 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1210 if (!finished) {
1211 memcpy(p,status,21);
1212 make_dir_struct(p,mask,fname,size, mode,date,
1213 !allow_long_path_components);
1214 if (!dptr_fill(p+12,dptr_num)) {
1215 break;
1217 numentries++;
1218 p += DIR_STRUCT_SIZE;
1222 } /* if (ok ) */
1226 SearchEmpty:
1228 /* If we were called as SMBffirst with smb_search_id == NULL
1229 and no entries were found then return error and close dirptr
1230 (X/Open spec) */
1232 if (numentries == 0 || !ok) {
1233 dptr_close(&dptr_num);
1234 } else if(ok && expect_close && status_len == 0) {
1235 /* Close the dptr - we know it's gone */
1236 dptr_close(&dptr_num);
1239 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1240 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1241 dptr_close(&dptr_num);
1244 if ((numentries == 0) && !mask_contains_wcard) {
1245 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1248 SSVAL(outbuf,smb_vwv0,numentries);
1249 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1250 SCVAL(smb_buf(outbuf),0,5);
1251 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1253 /* The replies here are never long name. */
1254 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1255 if (!allow_long_path_components) {
1256 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1259 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1260 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1262 outsize += DIR_STRUCT_SIZE*numentries;
1263 smb_setlen(outbuf,outsize - 4);
1265 if ((! *directory) && dptr_path(dptr_num))
1266 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1268 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1269 smb_fn_name(CVAL(inbuf,smb_com)),
1270 mask, directory, dirtype, numentries, maxentries ) );
1272 END_PROFILE(SMBsearch);
1273 return(outsize);
1276 /****************************************************************************
1277 Reply to a fclose (stop directory search).
1278 ****************************************************************************/
1280 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1282 int outsize = 0;
1283 int status_len;
1284 pstring path;
1285 char status[21];
1286 int dptr_num= -2;
1287 char *p;
1288 NTSTATUS err;
1289 BOOL path_contains_wcard = False;
1291 START_PROFILE(SMBfclose);
1293 if (lp_posix_pathnames()) {
1294 END_PROFILE(SMBfclose);
1295 return reply_unknown(inbuf, outbuf);
1298 outsize = set_message(outbuf,1,0,True);
1299 p = smb_buf(inbuf) + 1;
1300 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1301 if (!NT_STATUS_IS_OK(err)) {
1302 END_PROFILE(SMBfclose);
1303 return ERROR_NT(err);
1305 p++;
1306 status_len = SVAL(p,0);
1307 p += 2;
1309 if (status_len == 0) {
1310 END_PROFILE(SMBfclose);
1311 return ERROR_DOS(ERRSRV,ERRsrverror);
1314 memcpy(status,p,21);
1316 if(dptr_fetch(status+12,&dptr_num)) {
1317 /* Close the dptr - we know it's gone */
1318 dptr_close(&dptr_num);
1321 SSVAL(outbuf,smb_vwv0,0);
1323 DEBUG(3,("search close\n"));
1325 END_PROFILE(SMBfclose);
1326 return(outsize);
1329 /****************************************************************************
1330 Reply to an open.
1331 ****************************************************************************/
1333 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1335 pstring fname;
1336 int outsize = 0;
1337 uint32 fattr=0;
1338 SMB_OFF_T size = 0;
1339 time_t mtime=0;
1340 int info;
1341 SMB_STRUCT_STAT sbuf;
1342 BOOL bad_path = False;
1343 files_struct *fsp;
1344 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1345 int deny_mode;
1346 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1347 uint32 access_mask;
1348 uint32 share_mode;
1349 uint32 create_disposition;
1350 uint32 create_options = 0;
1351 NTSTATUS status;
1352 START_PROFILE(SMBopen);
1354 deny_mode = SVAL(inbuf,smb_vwv0);
1356 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1357 if (!NT_STATUS_IS_OK(status)) {
1358 END_PROFILE(SMBopen);
1359 return ERROR_NT(status);
1362 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1364 unix_convert(fname,conn,0,&bad_path,&sbuf);
1365 if (bad_path) {
1366 END_PROFILE(SMBopen);
1367 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1370 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1371 &access_mask, &share_mode, &create_disposition, &create_options)) {
1372 END_PROFILE(SMBopen);
1373 return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
1376 fsp = open_file_ntcreate(conn,fname,&sbuf,
1377 access_mask,
1378 share_mode,
1379 create_disposition,
1380 create_options,
1381 dos_attr,
1382 oplock_request,
1383 &info);
1385 if (!fsp) {
1386 END_PROFILE(SMBopen);
1387 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1388 /* We have re-scheduled this call. */
1389 return -1;
1391 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1394 size = sbuf.st_size;
1395 fattr = dos_mode(conn,fname,&sbuf);
1396 mtime = sbuf.st_mtime;
1398 if (fattr & aDIR) {
1399 DEBUG(3,("attempt to open a directory %s\n",fname));
1400 close_file(fsp,ERROR_CLOSE);
1401 END_PROFILE(SMBopen);
1402 return ERROR_DOS(ERRDOS,ERRnoaccess);
1405 outsize = set_message(outbuf,7,0,True);
1406 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1407 SSVAL(outbuf,smb_vwv1,fattr);
1408 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1409 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1410 } else {
1411 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1413 SIVAL(outbuf,smb_vwv4,(uint32)size);
1414 SSVAL(outbuf,smb_vwv6,deny_mode);
1416 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1417 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1420 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1421 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1423 END_PROFILE(SMBopen);
1424 return(outsize);
1427 /****************************************************************************
1428 Reply to an open and X.
1429 ****************************************************************************/
1431 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1433 pstring fname;
1434 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1435 int deny_mode = SVAL(inbuf,smb_vwv3);
1436 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1437 /* Breakout the oplock request bits so we can set the
1438 reply bits separately. */
1439 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1440 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1441 int oplock_request = ex_oplock_request | core_oplock_request;
1442 #if 0
1443 int smb_sattr = SVAL(inbuf,smb_vwv4);
1444 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1445 #endif
1446 int smb_ofun = SVAL(inbuf,smb_vwv8);
1447 SMB_OFF_T size=0;
1448 uint32 fattr=0;
1449 int mtime=0;
1450 SMB_STRUCT_STAT sbuf;
1451 int smb_action = 0;
1452 BOOL bad_path = False;
1453 files_struct *fsp;
1454 NTSTATUS status;
1455 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1456 ssize_t retval = -1;
1457 uint32 access_mask;
1458 uint32 share_mode;
1459 uint32 create_disposition;
1460 uint32 create_options = 0;
1462 START_PROFILE(SMBopenX);
1464 /* If it's an IPC, pass off the pipe handler. */
1465 if (IS_IPC(conn)) {
1466 if (lp_nt_pipe_support()) {
1467 END_PROFILE(SMBopenX);
1468 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1469 } else {
1470 END_PROFILE(SMBopenX);
1471 return ERROR_DOS(ERRSRV,ERRaccess);
1475 /* XXXX we need to handle passed times, sattr and flags */
1476 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1477 if (!NT_STATUS_IS_OK(status)) {
1478 END_PROFILE(SMBopenX);
1479 return ERROR_NT(status);
1482 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1484 unix_convert(fname,conn,0,&bad_path,&sbuf);
1485 if (bad_path) {
1486 END_PROFILE(SMBopenX);
1487 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1490 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1491 &access_mask,
1492 &share_mode,
1493 &create_disposition,
1494 &create_options)) {
1495 END_PROFILE(SMBopenX);
1496 return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
1499 fsp = open_file_ntcreate(conn,fname,&sbuf,
1500 access_mask,
1501 share_mode,
1502 create_disposition,
1503 create_options,
1504 smb_attr,
1505 oplock_request,
1506 &smb_action);
1508 if (!fsp) {
1509 END_PROFILE(SMBopenX);
1510 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1511 /* We have re-scheduled this call. */
1512 return -1;
1514 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1517 size = sbuf.st_size;
1519 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1520 if the file is truncated or created. */
1521 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1522 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1523 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1524 close_file(fsp,ERROR_CLOSE);
1525 END_PROFILE(SMBopenX);
1526 return ERROR_NT(NT_STATUS_DISK_FULL);
1528 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1529 if (retval < 0) {
1530 close_file(fsp,ERROR_CLOSE);
1531 END_PROFILE(SMBopenX);
1532 return ERROR_NT(NT_STATUS_DISK_FULL);
1534 size = get_allocation_size(conn,fsp,&sbuf);
1537 fattr = dos_mode(conn,fname,&sbuf);
1538 mtime = sbuf.st_mtime;
1539 if (fattr & aDIR) {
1540 close_file(fsp,ERROR_CLOSE);
1541 END_PROFILE(SMBopenX);
1542 return ERROR_DOS(ERRDOS,ERRnoaccess);
1545 /* If the caller set the extended oplock request bit
1546 and we granted one (by whatever means) - set the
1547 correct bit for extended oplock reply.
1550 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1551 smb_action |= EXTENDED_OPLOCK_GRANTED;
1554 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1555 smb_action |= EXTENDED_OPLOCK_GRANTED;
1558 /* If the caller set the core oplock request bit
1559 and we granted one (by whatever means) - set the
1560 correct bit for core oplock reply.
1563 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1564 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1567 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1568 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1571 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1572 set_message(outbuf,19,0,True);
1573 } else {
1574 set_message(outbuf,15,0,True);
1576 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1577 SSVAL(outbuf,smb_vwv3,fattr);
1578 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1579 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1580 } else {
1581 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1583 SIVAL(outbuf,smb_vwv6,(uint32)size);
1584 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1585 SSVAL(outbuf,smb_vwv11,smb_action);
1587 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1588 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1591 END_PROFILE(SMBopenX);
1592 return chain_reply(inbuf,outbuf,length,bufsize);
1595 /****************************************************************************
1596 Reply to a SMBulogoffX.
1597 conn POINTER CAN BE NULL HERE !
1598 ****************************************************************************/
1600 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1602 uint16 vuid = SVAL(inbuf,smb_uid);
1603 user_struct *vuser = get_valid_user_struct(vuid);
1604 START_PROFILE(SMBulogoffX);
1606 if(vuser == 0)
1607 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1609 /* in user level security we are supposed to close any files
1610 open by this user */
1611 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1612 file_close_user(vuid);
1614 invalidate_vuid(vuid);
1616 set_message(outbuf,2,0,True);
1618 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1620 END_PROFILE(SMBulogoffX);
1621 return chain_reply(inbuf,outbuf,length,bufsize);
1624 /****************************************************************************
1625 Reply to a mknew or a create.
1626 ****************************************************************************/
1628 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1630 pstring fname;
1631 int com;
1632 int outsize = 0;
1633 uint32 fattr = SVAL(inbuf,smb_vwv0);
1634 BOOL bad_path = False;
1635 files_struct *fsp;
1636 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1637 SMB_STRUCT_STAT sbuf;
1638 NTSTATUS status;
1639 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1640 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1641 uint32 create_disposition;
1642 uint32 create_options = 0;
1644 START_PROFILE(SMBcreate);
1646 com = SVAL(inbuf,smb_com);
1648 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1649 if (!NT_STATUS_IS_OK(status)) {
1650 END_PROFILE(SMBcreate);
1651 return ERROR_NT(status);
1654 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1656 unix_convert(fname,conn,0,&bad_path,&sbuf);
1657 if (bad_path) {
1658 END_PROFILE(SMBcreate);
1659 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1662 if (fattr & aVOLID) {
1663 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1666 if(com == SMBmknew) {
1667 /* We should fail if file exists. */
1668 create_disposition = FILE_CREATE;
1669 } else {
1670 /* Create if file doesn't exist, truncate if it does. */
1671 create_disposition = FILE_OVERWRITE_IF;
1674 /* Open file using ntcreate. */
1675 fsp = open_file_ntcreate(conn,fname,&sbuf,
1676 access_mask,
1677 share_mode,
1678 create_disposition,
1679 create_options,
1680 fattr,
1681 oplock_request,
1682 NULL);
1684 if (!fsp) {
1685 END_PROFILE(SMBcreate);
1686 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1687 /* We have re-scheduled this call. */
1688 return -1;
1690 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1693 outsize = set_message(outbuf,1,0,True);
1694 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1696 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1697 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1700 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1701 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1704 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1705 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1707 END_PROFILE(SMBcreate);
1708 return(outsize);
1711 /****************************************************************************
1712 Reply to a create temporary file.
1713 ****************************************************************************/
1715 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1717 pstring fname;
1718 int outsize = 0;
1719 uint32 fattr = SVAL(inbuf,smb_vwv0);
1720 BOOL bad_path = False;
1721 files_struct *fsp;
1722 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1723 int tmpfd;
1724 SMB_STRUCT_STAT sbuf;
1725 char *p, *s;
1726 NTSTATUS status;
1727 unsigned int namelen;
1729 START_PROFILE(SMBctemp);
1731 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1732 if (!NT_STATUS_IS_OK(status)) {
1733 END_PROFILE(SMBctemp);
1734 return ERROR_NT(status);
1736 if (*fname) {
1737 pstrcat(fname,"/TMXXXXXX");
1738 } else {
1739 pstrcat(fname,"TMXXXXXX");
1742 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1744 unix_convert(fname,conn,0,&bad_path,&sbuf);
1745 if (bad_path) {
1746 END_PROFILE(SMBctemp);
1747 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1750 tmpfd = smb_mkstemp(fname);
1751 if (tmpfd == -1) {
1752 END_PROFILE(SMBctemp);
1753 return(UNIXERROR(ERRDOS,ERRnoaccess));
1756 SMB_VFS_STAT(conn,fname,&sbuf);
1758 /* We should fail if file does not exist. */
1759 fsp = open_file_ntcreate(conn,fname,&sbuf,
1760 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1761 FILE_SHARE_READ|FILE_SHARE_WRITE,
1762 FILE_OPEN,
1764 fattr,
1765 oplock_request,
1766 NULL);
1768 /* close fd from smb_mkstemp() */
1769 close(tmpfd);
1771 if (!fsp) {
1772 END_PROFILE(SMBctemp);
1773 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1774 /* We have re-scheduled this call. */
1775 return -1;
1777 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1780 outsize = set_message(outbuf,1,0,True);
1781 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1783 /* the returned filename is relative to the directory */
1784 s = strrchr_m(fname, '/');
1785 if (!s) {
1786 s = fname;
1787 } else {
1788 s++;
1791 p = smb_buf(outbuf);
1792 #if 0
1793 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1794 thing in the byte section. JRA */
1795 SSVALS(p, 0, -1); /* what is this? not in spec */
1796 #endif
1797 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1798 p += namelen;
1799 outsize = set_message_end(outbuf, p);
1801 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1802 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1805 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1806 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1809 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1810 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1811 (unsigned int)sbuf.st_mode ) );
1813 END_PROFILE(SMBctemp);
1814 return(outsize);
1817 /*******************************************************************
1818 Check if a user is allowed to rename a file.
1819 ********************************************************************/
1821 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1823 files_struct *fsp;
1824 uint32 fmode;
1826 if (!CAN_WRITE(conn)) {
1827 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1830 fmode = dos_mode(conn,fname,pst);
1831 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1832 return NT_STATUS_NO_SUCH_FILE;
1835 if (S_ISDIR(pst->st_mode)) {
1836 return NT_STATUS_OK;
1839 /* We need a better way to return NT status codes from open... */
1840 set_saved_ntstatus(NT_STATUS_OK);
1842 fsp = open_file_ntcreate(conn, fname, pst,
1843 DELETE_ACCESS,
1844 FILE_SHARE_READ|FILE_SHARE_WRITE,
1845 FILE_OPEN,
1847 FILE_ATTRIBUTE_NORMAL,
1849 NULL);
1851 if (!fsp) {
1852 NTSTATUS ret = get_saved_ntstatus();
1853 if (!NT_STATUS_IS_OK(ret)) {
1854 set_saved_ntstatus(NT_STATUS_OK);
1855 return ret;
1857 set_saved_ntstatus(NT_STATUS_OK);
1858 return NT_STATUS_ACCESS_DENIED;
1860 close_file(fsp,NORMAL_CLOSE);
1861 return NT_STATUS_OK;
1864 /*******************************************************************
1865 Check if a user is allowed to delete a file.
1866 ********************************************************************/
1868 NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open)
1870 SMB_STRUCT_STAT sbuf;
1871 uint32 fattr;
1872 files_struct *fsp;
1874 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1876 if (!CAN_WRITE(conn)) {
1877 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1880 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1881 if(errno == ENOENT) {
1882 if (bad_path) {
1883 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1884 } else {
1885 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1888 return map_nt_error_from_unix(errno);
1891 fattr = dos_mode(conn,fname,&sbuf);
1893 /* Can't delete a directory. */
1894 if (fattr & aDIR) {
1895 return NT_STATUS_FILE_IS_A_DIRECTORY;
1898 #if 0 /* JRATEST */
1899 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1900 return NT_STATUS_OBJECT_NAME_INVALID;
1901 #endif /* JRATEST */
1903 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1905 On a Windows share, a file with read-only dosmode can be opened with
1906 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1907 fails with NT_STATUS_CANNOT_DELETE error.
1909 This semantic causes a problem that a user can not
1910 rename a file with read-only dosmode on a Samba share
1911 from a Windows command prompt (i.e. cmd.exe, but can rename
1912 from Windows Explorer).
1915 if (!check_is_at_open && !lp_delete_readonly(SNUM(conn))) {
1916 if (fattr & aRONLY) {
1917 return NT_STATUS_CANNOT_DELETE;
1920 if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1921 return NT_STATUS_NO_SUCH_FILE;
1924 if (check_is_at_open) {
1925 if (!can_delete_file_in_directory(conn, fname)) {
1926 return NT_STATUS_ACCESS_DENIED;
1928 } else {
1929 /* On open checks the open itself will check the share mode, so
1930 don't do it here as we'll get it wrong. */
1932 /* We need a better way to return NT status codes from open... */
1933 set_saved_ntstatus(NT_STATUS_OK);
1935 fsp = open_file_ntcreate(conn, fname, &sbuf,
1936 DELETE_ACCESS,
1937 FILE_SHARE_NONE,
1938 FILE_OPEN,
1940 FILE_ATTRIBUTE_NORMAL,
1942 NULL);
1944 if (!fsp) {
1945 NTSTATUS ret = get_saved_ntstatus();
1946 if (!NT_STATUS_IS_OK(ret)) {
1947 set_saved_ntstatus(NT_STATUS_OK);
1948 return ret;
1950 set_saved_ntstatus(NT_STATUS_OK);
1951 return NT_STATUS_ACCESS_DENIED;
1953 close_file(fsp,NORMAL_CLOSE);
1955 return NT_STATUS_OK;
1958 /****************************************************************************
1959 The guts of the unlink command, split out so it may be called by the NT SMB
1960 code.
1961 ****************************************************************************/
1963 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name, BOOL has_wild)
1965 pstring directory;
1966 pstring mask;
1967 char *p;
1968 int count=0;
1969 NTSTATUS error = NT_STATUS_OK;
1970 BOOL bad_path = False;
1971 BOOL rc = True;
1972 SMB_STRUCT_STAT sbuf;
1974 *directory = *mask = 0;
1976 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1978 p = strrchr_m(name,'/');
1979 if (!p) {
1980 pstrcpy(directory,".");
1981 pstrcpy(mask,name);
1982 } else {
1983 *p = 0;
1984 pstrcpy(directory,name);
1985 pstrcpy(mask,p+1);
1989 * We should only check the mangled cache
1990 * here if unix_convert failed. This means
1991 * that the path in 'mask' doesn't exist
1992 * on the file system and so we need to look
1993 * for a possible mangle. This patch from
1994 * Tine Smukavec <valentin.smukavec@hermes.si>.
1997 if (!rc && mangle_is_mangled(mask,SNUM(conn)))
1998 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
2000 if (!has_wild) {
2001 pstrcat(directory,"/");
2002 pstrcat(directory,mask);
2003 error = can_delete(conn,directory,dirtype,bad_path,False);
2004 if (!NT_STATUS_IS_OK(error))
2005 return error;
2007 if (SMB_VFS_UNLINK(conn,directory) == 0) {
2008 count++;
2010 } else {
2011 struct smb_Dir *dir_hnd = NULL;
2012 const char *dname;
2014 if (strequal(mask,"????????.???"))
2015 pstrcpy(mask,"*");
2017 if (check_name(directory,conn))
2018 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2020 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2021 the pattern matches against the long name, otherwise the short name
2022 We don't implement this yet XXXX
2025 if (dir_hnd) {
2026 long offset = 0;
2027 error = NT_STATUS_NO_SUCH_FILE;
2029 while ((dname = ReadDirName(dir_hnd, &offset))) {
2030 SMB_STRUCT_STAT st;
2031 pstring fname;
2032 BOOL sys_direntry = False;
2033 pstrcpy(fname,dname);
2035 if (!is_visible_file(conn, directory, dname, &st, True)) {
2036 continue;
2039 /* Quick check for "." and ".." */
2040 if (fname[0] == '.') {
2041 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2042 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
2043 sys_direntry = True;
2044 } else {
2045 continue;
2050 if(!mask_match(fname, mask, conn->case_sensitive))
2051 continue;
2053 if (sys_direntry) {
2054 error = NT_STATUS_OBJECT_NAME_INVALID;
2055 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
2056 fname, mask));
2057 break;
2060 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2061 error = can_delete(conn,fname,dirtype,bad_path,False);
2062 if (!NT_STATUS_IS_OK(error)) {
2063 continue;
2065 if (SMB_VFS_UNLINK(conn,fname) == 0)
2066 count++;
2067 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
2069 CloseDir(dir_hnd);
2073 if (count == 0 && NT_STATUS_IS_OK(error)) {
2074 error = map_nt_error_from_unix(errno);
2077 return error;
2080 /****************************************************************************
2081 Reply to a unlink
2082 ****************************************************************************/
2084 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2085 int dum_buffsize)
2087 int outsize = 0;
2088 pstring name;
2089 uint32 dirtype;
2090 NTSTATUS status;
2091 BOOL path_contains_wcard = False;
2093 START_PROFILE(SMBunlink);
2095 dirtype = SVAL(inbuf,smb_vwv0);
2097 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
2098 if (!NT_STATUS_IS_OK(status)) {
2099 END_PROFILE(SMBunlink);
2100 return ERROR_NT(status);
2103 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
2105 DEBUG(3,("reply_unlink : %s\n",name));
2107 status = unlink_internals(conn, dirtype, name, path_contains_wcard);
2108 if (!NT_STATUS_IS_OK(status)) {
2109 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2110 /* We have re-scheduled this call. */
2111 return -1;
2113 return ERROR_NT(status);
2117 * Win2k needs a changenotify request response before it will
2118 * update after a rename..
2120 process_pending_change_notify_queue((time_t)0);
2122 outsize = set_message(outbuf,0,0,False);
2124 END_PROFILE(SMBunlink);
2125 return outsize;
2128 /****************************************************************************
2129 Fail for readbraw.
2130 ****************************************************************************/
2132 static void fail_readraw(void)
2134 pstring errstr;
2135 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2136 strerror(errno) );
2137 exit_server(errstr);
2140 #if defined(WITH_SENDFILE)
2141 /****************************************************************************
2142 Fake (read/write) sendfile. Returns -1 on read or write fail.
2143 ****************************************************************************/
2145 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2147 ssize_t ret=0;
2149 /* Paranioa check... */
2150 if (nread > bufsize) {
2151 fail_readraw();
2154 if (nread > 0) {
2155 ret = read_file(fsp,buf,startpos,nread);
2156 if (ret == -1) {
2157 return -1;
2161 /* If we had a short read, fill with zeros. */
2162 if (ret < nread) {
2163 memset(buf, '\0', nread - ret);
2166 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2167 return -1;
2170 return (ssize_t)nread;
2172 #endif
2174 /****************************************************************************
2175 Use sendfile in readbraw.
2176 ****************************************************************************/
2178 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2179 ssize_t mincount, char *outbuf, int out_buffsize)
2181 ssize_t ret=0;
2183 #if defined(WITH_SENDFILE)
2185 * We can only use sendfile on a non-chained packet
2186 * but we can use on a non-oplocked file. tridge proved this
2187 * on a train in Germany :-). JRA.
2188 * reply_readbraw has already checked the length.
2191 if ( (chain_size == 0) && (nread > 0) &&
2192 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2193 DATA_BLOB header;
2195 _smb_setlen(outbuf,nread);
2196 header.data = (uint8 *)outbuf;
2197 header.length = 4;
2198 header.free = NULL;
2200 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2201 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2202 if (errno == ENOSYS) {
2203 goto normal_readbraw;
2207 * Special hack for broken Linux with no working sendfile. If we
2208 * return EINTR we sent the header but not the rest of the data.
2209 * Fake this up by doing read/write calls.
2211 if (errno == EINTR) {
2212 /* Ensure we don't do this again. */
2213 set_use_sendfile(SNUM(conn), False);
2214 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2216 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2217 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2218 fsp->fsp_name, strerror(errno) ));
2219 exit_server("send_file_readbraw fake_sendfile failed");
2221 return;
2224 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2225 fsp->fsp_name, strerror(errno) ));
2226 exit_server("send_file_readbraw sendfile failed");
2231 normal_readbraw:
2233 #endif
2235 if (nread > 0) {
2236 ret = read_file(fsp,outbuf+4,startpos,nread);
2237 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2238 if (ret < mincount)
2239 ret = 0;
2240 #else
2241 if (ret < nread)
2242 ret = 0;
2243 #endif
2246 _smb_setlen(outbuf,ret);
2247 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2248 fail_readraw();
2251 /****************************************************************************
2252 Reply to a readbraw (core+ protocol).
2253 ****************************************************************************/
2255 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2257 ssize_t maxcount,mincount;
2258 size_t nread = 0;
2259 SMB_OFF_T startpos;
2260 char *header = outbuf;
2261 files_struct *fsp;
2262 START_PROFILE(SMBreadbraw);
2264 if (srv_is_signing_active()) {
2265 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2269 * Special check if an oplock break has been issued
2270 * and the readraw request croses on the wire, we must
2271 * return a zero length response here.
2274 fsp = file_fsp(inbuf,smb_vwv0);
2276 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2278 * fsp could be NULL here so use the value from the packet. JRA.
2280 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2281 _smb_setlen(header,0);
2282 if (write_data(smbd_server_fd(),header,4) != 4)
2283 fail_readraw();
2284 END_PROFILE(SMBreadbraw);
2285 return(-1);
2288 CHECK_FSP(fsp,conn);
2290 flush_write_cache(fsp, READRAW_FLUSH);
2292 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2293 if(CVAL(inbuf,smb_wct) == 10) {
2295 * This is a large offset (64 bit) read.
2297 #ifdef LARGE_SMB_OFF_T
2299 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2301 #else /* !LARGE_SMB_OFF_T */
2304 * Ensure we haven't been sent a >32 bit offset.
2307 if(IVAL(inbuf,smb_vwv8) != 0) {
2308 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2309 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2310 _smb_setlen(header,0);
2311 if (write_data(smbd_server_fd(),header,4) != 4)
2312 fail_readraw();
2313 END_PROFILE(SMBreadbraw);
2314 return(-1);
2317 #endif /* LARGE_SMB_OFF_T */
2319 if(startpos < 0) {
2320 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2321 _smb_setlen(header,0);
2322 if (write_data(smbd_server_fd(),header,4) != 4)
2323 fail_readraw();
2324 END_PROFILE(SMBreadbraw);
2325 return(-1);
2328 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2329 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2331 /* ensure we don't overrun the packet size */
2332 maxcount = MIN(65535,maxcount);
2334 if (!is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2335 SMB_STRUCT_STAT st;
2336 SMB_OFF_T size = 0;
2338 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2339 size = st.st_size;
2342 if (startpos >= size) {
2343 nread = 0;
2344 } else {
2345 nread = MIN(maxcount,(size - startpos));
2349 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2350 if (nread < mincount)
2351 nread = 0;
2352 #endif
2354 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2355 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2357 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2359 DEBUG(5,("readbraw finished\n"));
2360 END_PROFILE(SMBreadbraw);
2361 return -1;
2364 #undef DBGC_CLASS
2365 #define DBGC_CLASS DBGC_LOCKING
2367 /****************************************************************************
2368 Reply to a lockread (core+ protocol).
2369 ****************************************************************************/
2371 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2373 ssize_t nread = -1;
2374 char *data;
2375 int outsize = 0;
2376 SMB_OFF_T startpos;
2377 size_t numtoread;
2378 NTSTATUS status;
2379 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2380 BOOL my_lock_ctx = False;
2381 START_PROFILE(SMBlockread);
2383 CHECK_FSP(fsp,conn);
2384 if (!CHECK_READ(fsp,inbuf)) {
2385 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2388 release_level_2_oplocks_on_change(fsp);
2390 numtoread = SVAL(inbuf,smb_vwv1);
2391 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2393 outsize = set_message(outbuf,5,3,True);
2394 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2395 data = smb_buf(outbuf) + 3;
2398 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2399 * protocol request that predates the read/write lock concept.
2400 * Thus instead of asking for a read lock here we need to ask
2401 * for a write lock. JRA.
2402 * Note that the requested lock size is unaffected by max_recv.
2405 status = do_lock_spin(fsp,
2406 SVAL(inbuf,smb_pid),
2407 (SMB_BIG_UINT)numtoread,
2408 (SMB_BIG_UINT)startpos,
2409 WRITE_LOCK,
2410 WINDOWS_LOCK,
2411 &my_lock_ctx);
2413 if (NT_STATUS_V(status)) {
2414 #if 0
2416 * We used to make lockread a blocking lock. It turns out
2417 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2418 * tester. JRA.
2421 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2423 * A blocking lock was requested. Package up
2424 * this smb into a queued request and push it
2425 * onto the blocking lock queue.
2427 if(push_blocking_lock_request(inbuf, length,
2428 fsp,
2431 SVAL(inbuf,smb_pid),
2432 WRITE_LOCK,
2433 WINDOWS_LOCK,
2434 (SMB_BIG_UINT)startpos,
2435 (SMB_BIG_UINT)numtoread)) {
2436 END_PROFILE(SMBlockread);
2437 return -1;
2440 #endif
2441 END_PROFILE(SMBlockread);
2442 return ERROR_NT(status);
2446 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2449 if (numtoread > max_recv) {
2450 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2451 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2452 (unsigned int)numtoread, (unsigned int)max_recv ));
2453 numtoread = MIN(numtoread,max_recv);
2455 nread = read_file(fsp,data,startpos,numtoread);
2457 if (nread < 0) {
2458 END_PROFILE(SMBlockread);
2459 return(UNIXERROR(ERRDOS,ERRnoaccess));
2462 outsize += nread;
2463 SSVAL(outbuf,smb_vwv0,nread);
2464 SSVAL(outbuf,smb_vwv5,nread+3);
2465 SSVAL(smb_buf(outbuf),1,nread);
2467 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2468 fsp->fnum, (int)numtoread, (int)nread));
2470 END_PROFILE(SMBlockread);
2471 return(outsize);
2474 #undef DBGC_CLASS
2475 #define DBGC_CLASS DBGC_ALL
2477 /****************************************************************************
2478 Reply to a read.
2479 ****************************************************************************/
2481 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2483 size_t numtoread;
2484 ssize_t nread = 0;
2485 char *data;
2486 SMB_OFF_T startpos;
2487 int outsize = 0;
2488 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2489 START_PROFILE(SMBread);
2491 CHECK_FSP(fsp,conn);
2492 if (!CHECK_READ(fsp,inbuf)) {
2493 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2496 numtoread = SVAL(inbuf,smb_vwv1);
2497 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2499 outsize = set_message(outbuf,5,3,True);
2500 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2502 * The requested read size cannot be greater than max_recv. JRA.
2504 if (numtoread > max_recv) {
2505 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2506 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2507 (unsigned int)numtoread, (unsigned int)max_recv ));
2508 numtoread = MIN(numtoread,max_recv);
2511 data = smb_buf(outbuf) + 3;
2513 if (is_locked(fsp,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2514 END_PROFILE(SMBread);
2515 return ERROR_DOS(ERRDOS,ERRlock);
2518 if (numtoread > 0)
2519 nread = read_file(fsp,data,startpos,numtoread);
2521 if (nread < 0) {
2522 END_PROFILE(SMBread);
2523 return(UNIXERROR(ERRDOS,ERRnoaccess));
2526 outsize += nread;
2527 SSVAL(outbuf,smb_vwv0,nread);
2528 SSVAL(outbuf,smb_vwv5,nread+3);
2529 SCVAL(smb_buf(outbuf),0,1);
2530 SSVAL(smb_buf(outbuf),1,nread);
2532 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2533 fsp->fnum, (int)numtoread, (int)nread ) );
2535 END_PROFILE(SMBread);
2536 return(outsize);
2539 /****************************************************************************
2540 Reply to a read and X - possibly using sendfile.
2541 ****************************************************************************/
2543 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2544 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2546 int outsize = 0;
2547 ssize_t nread = -1;
2548 char *data = smb_buf(outbuf);
2550 #if defined(WITH_SENDFILE)
2552 * We can only use sendfile on a non-chained packet
2553 * but we can use on a non-oplocked file. tridge proved this
2554 * on a train in Germany :-). JRA.
2557 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2558 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2559 SMB_STRUCT_STAT sbuf;
2560 DATA_BLOB header;
2562 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2563 return(UNIXERROR(ERRDOS,ERRnoaccess));
2565 if (startpos > sbuf.st_size)
2566 goto normal_read;
2568 if (smb_maxcnt > (sbuf.st_size - startpos))
2569 smb_maxcnt = (sbuf.st_size - startpos);
2571 if (smb_maxcnt == 0)
2572 goto normal_read;
2575 * Set up the packet header before send. We
2576 * assume here the sendfile will work (get the
2577 * correct amount of data).
2580 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2581 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2582 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2583 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2584 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2585 SCVAL(outbuf,smb_vwv0,0xFF);
2586 set_message(outbuf,12,smb_maxcnt,False);
2587 header.data = (uint8 *)outbuf;
2588 header.length = data - outbuf;
2589 header.free = NULL;
2591 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2592 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2593 if (errno == ENOSYS) {
2594 goto normal_read;
2598 * Special hack for broken Linux with no working sendfile. If we
2599 * return EINTR we sent the header but not the rest of the data.
2600 * Fake this up by doing read/write calls.
2603 if (errno == EINTR) {
2604 /* Ensure we don't do this again. */
2605 set_use_sendfile(SNUM(conn), False);
2606 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2608 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2609 len_outbuf - (data-outbuf))) == -1) {
2610 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2611 fsp->fsp_name, strerror(errno) ));
2612 exit_server("send_file_readX: fake_sendfile failed");
2614 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2615 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2616 /* Returning -1 here means successful sendfile. */
2617 return -1;
2620 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2621 fsp->fsp_name, strerror(errno) ));
2622 exit_server("send_file_readX sendfile failed");
2625 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2626 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2627 /* Returning -1 here means successful sendfile. */
2628 return -1;
2631 normal_read:
2633 #endif
2635 nread = read_file(fsp,data,startpos,smb_maxcnt);
2637 if (nread < 0) {
2638 return(UNIXERROR(ERRDOS,ERRnoaccess));
2641 outsize = set_message(outbuf,12,nread,False);
2642 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2643 SSVAL(outbuf,smb_vwv5,nread);
2644 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2645 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2646 SSVAL(smb_buf(outbuf),-2,nread);
2648 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2649 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2651 /* Returning the number of bytes we want to send back - including header. */
2652 return outsize;
2655 /****************************************************************************
2656 Reply to a read and X.
2657 ****************************************************************************/
2659 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2661 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2662 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2663 ssize_t nread = -1;
2664 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2665 #if 0
2666 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2667 #endif
2669 START_PROFILE(SMBreadX);
2671 /* If it's an IPC, pass off the pipe handler. */
2672 if (IS_IPC(conn)) {
2673 END_PROFILE(SMBreadX);
2674 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2677 CHECK_FSP(fsp,conn);
2678 if (!CHECK_READ(fsp,inbuf)) {
2679 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2682 set_message(outbuf,12,0,True);
2684 if (global_client_caps & CAP_LARGE_READX) {
2685 if (SVAL(inbuf,smb_vwv7) == 1) {
2686 smb_maxcnt |= (1<<16);
2688 if (smb_maxcnt > BUFFER_SIZE) {
2689 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2690 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2691 END_PROFILE(SMBreadX);
2692 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2696 if(CVAL(inbuf,smb_wct) == 12) {
2697 #ifdef LARGE_SMB_OFF_T
2699 * This is a large offset (64 bit) read.
2701 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2703 #else /* !LARGE_SMB_OFF_T */
2706 * Ensure we haven't been sent a >32 bit offset.
2709 if(IVAL(inbuf,smb_vwv10) != 0) {
2710 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2711 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2712 END_PROFILE(SMBreadX);
2713 return ERROR_DOS(ERRDOS,ERRbadaccess);
2716 #endif /* LARGE_SMB_OFF_T */
2720 if (is_locked(fsp,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2721 END_PROFILE(SMBreadX);
2722 return ERROR_DOS(ERRDOS,ERRlock);
2725 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2726 END_PROFILE(SMBreadX);
2727 return -1;
2730 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2731 if (nread != -1)
2732 nread = chain_reply(inbuf,outbuf,length,bufsize);
2734 END_PROFILE(SMBreadX);
2735 return nread;
2738 /****************************************************************************
2739 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2740 ****************************************************************************/
2742 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2744 ssize_t nwritten=0;
2745 ssize_t total_written=0;
2746 size_t numtowrite=0;
2747 size_t tcount;
2748 SMB_OFF_T startpos;
2749 char *data=NULL;
2750 BOOL write_through;
2751 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2752 int outsize = 0;
2753 START_PROFILE(SMBwritebraw);
2755 if (srv_is_signing_active()) {
2756 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2759 CHECK_FSP(fsp,conn);
2760 if (!CHECK_WRITE(fsp)) {
2761 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2764 tcount = IVAL(inbuf,smb_vwv1);
2765 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2766 write_through = BITSETW(inbuf+smb_vwv7,0);
2768 /* We have to deal with slightly different formats depending
2769 on whether we are using the core+ or lanman1.0 protocol */
2771 if(Protocol <= PROTOCOL_COREPLUS) {
2772 numtowrite = SVAL(smb_buf(inbuf),-2);
2773 data = smb_buf(inbuf);
2774 } else {
2775 numtowrite = SVAL(inbuf,smb_vwv10);
2776 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2779 /* force the error type */
2780 SCVAL(inbuf,smb_com,SMBwritec);
2781 SCVAL(outbuf,smb_com,SMBwritec);
2783 if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2784 END_PROFILE(SMBwritebraw);
2785 return(ERROR_DOS(ERRDOS,ERRlock));
2788 if (numtowrite>0)
2789 nwritten = write_file(fsp,data,startpos,numtowrite);
2791 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2792 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2794 if (nwritten < (ssize_t)numtowrite) {
2795 END_PROFILE(SMBwritebraw);
2796 return(UNIXERROR(ERRHRD,ERRdiskfull));
2799 total_written = nwritten;
2801 /* Return a message to the redirector to tell it to send more bytes */
2802 SCVAL(outbuf,smb_com,SMBwritebraw);
2803 SSVALS(outbuf,smb_vwv0,-1);
2804 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2805 show_msg(outbuf);
2806 if (!send_smb(smbd_server_fd(),outbuf))
2807 exit_server("reply_writebraw: send_smb failed.");
2809 /* Now read the raw data into the buffer and write it */
2810 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2811 exit_server("secondary writebraw failed");
2814 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2815 numtowrite = smb_len(inbuf);
2817 /* Set up outbuf to return the correct return */
2818 outsize = set_message(outbuf,1,0,True);
2819 SCVAL(outbuf,smb_com,SMBwritec);
2821 if (numtowrite != 0) {
2823 if (numtowrite > BUFFER_SIZE) {
2824 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2825 (unsigned int)numtowrite ));
2826 exit_server("secondary writebraw failed");
2829 if (tcount > nwritten+numtowrite) {
2830 DEBUG(3,("Client overestimated the write %d %d %d\n",
2831 (int)tcount,(int)nwritten,(int)numtowrite));
2834 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2835 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2836 strerror(errno) ));
2837 exit_server("secondary writebraw failed");
2840 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2842 if (nwritten < (ssize_t)numtowrite) {
2843 SCVAL(outbuf,smb_rcls,ERRHRD);
2844 SSVAL(outbuf,smb_err,ERRdiskfull);
2847 if (nwritten > 0)
2848 total_written += nwritten;
2851 SSVAL(outbuf,smb_vwv0,total_written);
2853 sync_file(conn, fsp, write_through);
2855 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2856 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2858 /* we won't return a status if write through is not selected - this follows what WfWg does */
2859 END_PROFILE(SMBwritebraw);
2860 if (!write_through && total_written==tcount) {
2862 #if RABBIT_PELLET_FIX
2864 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2865 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2867 if (!send_keepalive(smbd_server_fd()))
2868 exit_server("reply_writebraw: send of keepalive failed");
2869 #endif
2870 return(-1);
2873 return(outsize);
2876 #undef DBGC_CLASS
2877 #define DBGC_CLASS DBGC_LOCKING
2879 /****************************************************************************
2880 Reply to a writeunlock (core+).
2881 ****************************************************************************/
2883 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2884 int size, int dum_buffsize)
2886 ssize_t nwritten = -1;
2887 size_t numtowrite;
2888 SMB_OFF_T startpos;
2889 char *data;
2890 NTSTATUS status = NT_STATUS_OK;
2891 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2892 int outsize = 0;
2893 START_PROFILE(SMBwriteunlock);
2895 CHECK_FSP(fsp,conn);
2896 if (!CHECK_WRITE(fsp)) {
2897 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2900 numtowrite = SVAL(inbuf,smb_vwv1);
2901 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2902 data = smb_buf(inbuf) + 3;
2904 if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2905 END_PROFILE(SMBwriteunlock);
2906 return ERROR_DOS(ERRDOS,ERRlock);
2909 /* The special X/Open SMB protocol handling of
2910 zero length writes is *NOT* done for
2911 this call */
2912 if(numtowrite == 0) {
2913 nwritten = 0;
2914 } else {
2915 nwritten = write_file(fsp,data,startpos,numtowrite);
2918 sync_file(conn, fsp, False /* write through */);
2920 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2921 END_PROFILE(SMBwriteunlock);
2922 return(UNIXERROR(ERRHRD,ERRdiskfull));
2925 if (numtowrite) {
2926 status = do_unlock(fsp,
2927 SVAL(inbuf,smb_pid),
2928 (SMB_BIG_UINT)numtowrite,
2929 (SMB_BIG_UINT)startpos,
2930 WINDOWS_LOCK);
2932 if (NT_STATUS_V(status)) {
2933 END_PROFILE(SMBwriteunlock);
2934 return ERROR_NT(status);
2938 outsize = set_message(outbuf,1,0,True);
2940 SSVAL(outbuf,smb_vwv0,nwritten);
2942 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2943 fsp->fnum, (int)numtowrite, (int)nwritten));
2945 END_PROFILE(SMBwriteunlock);
2946 return outsize;
2949 #undef DBGC_CLASS
2950 #define DBGC_CLASS DBGC_ALL
2952 /****************************************************************************
2953 Reply to a write.
2954 ****************************************************************************/
2956 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2958 size_t numtowrite;
2959 ssize_t nwritten = -1;
2960 SMB_OFF_T startpos;
2961 char *data;
2962 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2963 int outsize = 0;
2964 START_PROFILE(SMBwrite);
2966 /* If it's an IPC, pass off the pipe handler. */
2967 if (IS_IPC(conn)) {
2968 END_PROFILE(SMBwrite);
2969 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2972 CHECK_FSP(fsp,conn);
2973 if (!CHECK_WRITE(fsp)) {
2974 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2977 numtowrite = SVAL(inbuf,smb_vwv1);
2978 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2979 data = smb_buf(inbuf) + 3;
2981 if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2982 END_PROFILE(SMBwrite);
2983 return ERROR_DOS(ERRDOS,ERRlock);
2987 * X/Open SMB protocol says that if smb_vwv1 is
2988 * zero then the file size should be extended or
2989 * truncated to the size given in smb_vwv[2-3].
2992 if(numtowrite == 0) {
2994 * This is actually an allocate call, and set EOF. JRA.
2996 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2997 if (nwritten < 0) {
2998 END_PROFILE(SMBwrite);
2999 return ERROR_NT(NT_STATUS_DISK_FULL);
3001 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3002 if (nwritten < 0) {
3003 END_PROFILE(SMBwrite);
3004 return ERROR_NT(NT_STATUS_DISK_FULL);
3006 } else
3007 nwritten = write_file(fsp,data,startpos,numtowrite);
3009 sync_file(conn, fsp, False);
3011 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3012 END_PROFILE(SMBwrite);
3013 return(UNIXERROR(ERRHRD,ERRdiskfull));
3016 outsize = set_message(outbuf,1,0,True);
3018 SSVAL(outbuf,smb_vwv0,nwritten);
3020 if (nwritten < (ssize_t)numtowrite) {
3021 SCVAL(outbuf,smb_rcls,ERRHRD);
3022 SSVAL(outbuf,smb_err,ERRdiskfull);
3025 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3027 END_PROFILE(SMBwrite);
3028 return(outsize);
3031 /****************************************************************************
3032 Reply to a write and X.
3033 ****************************************************************************/
3035 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3037 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3038 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3039 size_t numtowrite = SVAL(inbuf,smb_vwv10);
3040 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3041 ssize_t nwritten = -1;
3042 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3043 unsigned int smblen = smb_len(inbuf);
3044 char *data;
3045 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3046 START_PROFILE(SMBwriteX);
3048 /* If it's an IPC, pass off the pipe handler. */
3049 if (IS_IPC(conn)) {
3050 END_PROFILE(SMBwriteX);
3051 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3054 CHECK_FSP(fsp,conn);
3055 if (!CHECK_WRITE(fsp)) {
3056 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3059 set_message(outbuf,6,0,True);
3061 /* Deal with possible LARGE_WRITEX */
3062 if (large_writeX) {
3063 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3066 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3067 END_PROFILE(SMBwriteX);
3068 return ERROR_DOS(ERRDOS,ERRbadmem);
3071 data = smb_base(inbuf) + smb_doff;
3073 if(CVAL(inbuf,smb_wct) == 14) {
3074 #ifdef LARGE_SMB_OFF_T
3076 * This is a large offset (64 bit) write.
3078 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3080 #else /* !LARGE_SMB_OFF_T */
3083 * Ensure we haven't been sent a >32 bit offset.
3086 if(IVAL(inbuf,smb_vwv12) != 0) {
3087 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3088 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3089 END_PROFILE(SMBwriteX);
3090 return ERROR_DOS(ERRDOS,ERRbadaccess);
3093 #endif /* LARGE_SMB_OFF_T */
3096 if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3097 END_PROFILE(SMBwriteX);
3098 return ERROR_DOS(ERRDOS,ERRlock);
3101 /* X/Open SMB protocol says that, unlike SMBwrite
3102 if the length is zero then NO truncation is
3103 done, just a write of zero. To truncate a file,
3104 use SMBwrite. */
3106 if(numtowrite == 0) {
3107 nwritten = 0;
3108 } else {
3110 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3111 fsp,data,startpos,numtowrite)) {
3112 END_PROFILE(SMBwriteX);
3113 return -1;
3116 nwritten = write_file(fsp,data,startpos,numtowrite);
3119 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3120 END_PROFILE(SMBwriteX);
3121 return(UNIXERROR(ERRHRD,ERRdiskfull));
3124 SSVAL(outbuf,smb_vwv2,nwritten);
3125 if (large_writeX)
3126 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3128 if (nwritten < (ssize_t)numtowrite) {
3129 SCVAL(outbuf,smb_rcls,ERRHRD);
3130 SSVAL(outbuf,smb_err,ERRdiskfull);
3133 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3134 fsp->fnum, (int)numtowrite, (int)nwritten));
3136 sync_file(conn, fsp, write_through);
3138 END_PROFILE(SMBwriteX);
3139 return chain_reply(inbuf,outbuf,length,bufsize);
3142 /****************************************************************************
3143 Reply to a lseek.
3144 ****************************************************************************/
3146 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3148 SMB_OFF_T startpos;
3149 SMB_OFF_T res= -1;
3150 int mode,umode;
3151 int outsize = 0;
3152 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3153 START_PROFILE(SMBlseek);
3155 CHECK_FSP(fsp,conn);
3157 flush_write_cache(fsp, SEEK_FLUSH);
3159 mode = SVAL(inbuf,smb_vwv1) & 3;
3160 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3161 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3163 switch (mode) {
3164 case 0:
3165 umode = SEEK_SET;
3166 res = startpos;
3167 break;
3168 case 1:
3169 umode = SEEK_CUR;
3170 res = fsp->fh->pos + startpos;
3171 break;
3172 case 2:
3173 umode = SEEK_END;
3174 break;
3175 default:
3176 umode = SEEK_SET;
3177 res = startpos;
3178 break;
3181 if (umode == SEEK_END) {
3182 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3183 if(errno == EINVAL) {
3184 SMB_OFF_T current_pos = startpos;
3185 SMB_STRUCT_STAT sbuf;
3187 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3188 END_PROFILE(SMBlseek);
3189 return(UNIXERROR(ERRDOS,ERRnoaccess));
3192 current_pos += sbuf.st_size;
3193 if(current_pos < 0)
3194 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3198 if(res == -1) {
3199 END_PROFILE(SMBlseek);
3200 return(UNIXERROR(ERRDOS,ERRnoaccess));
3204 fsp->fh->pos = res;
3206 outsize = set_message(outbuf,2,0,True);
3207 SIVAL(outbuf,smb_vwv0,res);
3209 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3210 fsp->fnum, (double)startpos, (double)res, mode));
3212 END_PROFILE(SMBlseek);
3213 return(outsize);
3216 /****************************************************************************
3217 Reply to a flush.
3218 ****************************************************************************/
3220 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3222 int outsize = set_message(outbuf,0,0,False);
3223 uint16 fnum = SVAL(inbuf,smb_vwv0);
3224 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3225 START_PROFILE(SMBflush);
3227 if (fnum != 0xFFFF)
3228 CHECK_FSP(fsp,conn);
3230 if (!fsp) {
3231 file_sync_all(conn);
3232 } else {
3233 sync_file(conn,fsp, True);
3236 DEBUG(3,("flush\n"));
3237 END_PROFILE(SMBflush);
3238 return(outsize);
3241 /****************************************************************************
3242 Reply to a exit.
3243 conn POINTER CAN BE NULL HERE !
3244 ****************************************************************************/
3246 int reply_exit(connection_struct *conn,
3247 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3249 int outsize;
3250 START_PROFILE(SMBexit);
3252 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3254 outsize = set_message(outbuf,0,0,False);
3256 DEBUG(3,("exit\n"));
3258 END_PROFILE(SMBexit);
3259 return(outsize);
3262 /****************************************************************************
3263 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3264 ****************************************************************************/
3266 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3267 int dum_buffsize)
3269 int outsize = 0;
3270 time_t mtime;
3271 int32 eclass = 0, err = 0;
3272 files_struct *fsp = NULL;
3273 START_PROFILE(SMBclose);
3275 outsize = set_message(outbuf,0,0,False);
3277 /* If it's an IPC, pass off to the pipe handler. */
3278 if (IS_IPC(conn)) {
3279 END_PROFILE(SMBclose);
3280 return reply_pipe_close(conn, inbuf,outbuf);
3283 fsp = file_fsp(inbuf,smb_vwv0);
3286 * We can only use CHECK_FSP if we know it's not a directory.
3289 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3290 END_PROFILE(SMBclose);
3291 return ERROR_DOS(ERRDOS,ERRbadfid);
3294 if(fsp->is_directory) {
3296 * Special case - close NT SMB directory handle.
3298 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3299 close_file(fsp,NORMAL_CLOSE);
3300 } else {
3302 * Close ordinary file.
3304 int close_err;
3305 pstring file_name;
3307 /* Save the name for time set in close. */
3308 pstrcpy( file_name, fsp->fsp_name);
3310 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3311 fsp->fh->fd, fsp->fnum,
3312 conn->num_files_open));
3315 * Take care of any time sent in the close.
3318 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
3319 fsp_set_pending_modtime(fsp, mtime);
3322 * close_file() returns the unix errno if an error
3323 * was detected on close - normally this is due to
3324 * a disk full error. If not then it was probably an I/O error.
3327 if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) {
3328 errno = close_err;
3329 END_PROFILE(SMBclose);
3330 return (UNIXERROR(ERRHRD,ERRgeneral));
3334 /* We have a cached error */
3335 if(eclass || err) {
3336 END_PROFILE(SMBclose);
3337 return ERROR_DOS(eclass,err);
3340 END_PROFILE(SMBclose);
3341 return(outsize);
3344 /****************************************************************************
3345 Reply to a writeclose (Core+ protocol).
3346 ****************************************************************************/
3348 int reply_writeclose(connection_struct *conn,
3349 char *inbuf,char *outbuf, int size, int dum_buffsize)
3351 size_t numtowrite;
3352 ssize_t nwritten = -1;
3353 int outsize = 0;
3354 int close_err = 0;
3355 SMB_OFF_T startpos;
3356 char *data;
3357 time_t mtime;
3358 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3359 START_PROFILE(SMBwriteclose);
3361 CHECK_FSP(fsp,conn);
3362 if (!CHECK_WRITE(fsp)) {
3363 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3366 numtowrite = SVAL(inbuf,smb_vwv1);
3367 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3368 mtime = srv_make_unix_date3(inbuf+smb_vwv4);
3369 data = smb_buf(inbuf) + 1;
3371 if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3372 END_PROFILE(SMBwriteclose);
3373 return ERROR_DOS(ERRDOS,ERRlock);
3376 nwritten = write_file(fsp,data,startpos,numtowrite);
3378 set_filetime(conn, fsp->fsp_name,mtime);
3381 * More insanity. W2K only closes the file if writelen > 0.
3382 * JRA.
3385 if (numtowrite) {
3386 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3387 fsp->fsp_name ));
3388 close_err = close_file(fsp,NORMAL_CLOSE);
3391 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3392 fsp->fnum, (int)numtowrite, (int)nwritten,
3393 conn->num_files_open));
3395 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3396 END_PROFILE(SMBwriteclose);
3397 return(UNIXERROR(ERRHRD,ERRdiskfull));
3400 if(close_err != 0) {
3401 errno = close_err;
3402 END_PROFILE(SMBwriteclose);
3403 return(UNIXERROR(ERRHRD,ERRgeneral));
3406 outsize = set_message(outbuf,1,0,True);
3408 SSVAL(outbuf,smb_vwv0,nwritten);
3409 END_PROFILE(SMBwriteclose);
3410 return(outsize);
3413 #undef DBGC_CLASS
3414 #define DBGC_CLASS DBGC_LOCKING
3416 /****************************************************************************
3417 Reply to a lock.
3418 ****************************************************************************/
3420 int reply_lock(connection_struct *conn,
3421 char *inbuf,char *outbuf, int length, int dum_buffsize)
3423 int outsize = set_message(outbuf,0,0,False);
3424 SMB_BIG_UINT count,offset;
3425 NTSTATUS status;
3426 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3427 BOOL my_lock_ctx = False;
3429 START_PROFILE(SMBlock);
3431 CHECK_FSP(fsp,conn);
3433 release_level_2_oplocks_on_change(fsp);
3435 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3436 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3438 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3439 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3441 status = do_lock_spin(fsp,
3442 SVAL(inbuf,smb_pid),
3443 count,
3444 offset,
3445 WRITE_LOCK,
3446 WINDOWS_LOCK,
3447 &my_lock_ctx);
3448 if (NT_STATUS_V(status)) {
3449 #if 0
3450 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3451 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3453 * A blocking lock was requested. Package up
3454 * this smb into a queued request and push it
3455 * onto the blocking lock queue.
3457 if(push_blocking_lock_request(inbuf, length,
3458 fsp,
3461 SVAL(inbuf,smb_pid),
3462 WRITE_LOCK,
3463 WINDOWS_LOCK,
3464 offset, count)) {
3465 END_PROFILE(SMBlock);
3466 return -1;
3469 #endif
3470 END_PROFILE(SMBlock);
3471 return ERROR_NT(status);
3474 END_PROFILE(SMBlock);
3475 return(outsize);
3478 /****************************************************************************
3479 Reply to a unlock.
3480 ****************************************************************************/
3482 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3483 int dum_buffsize)
3485 int outsize = set_message(outbuf,0,0,False);
3486 SMB_BIG_UINT count,offset;
3487 NTSTATUS status;
3488 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3489 START_PROFILE(SMBunlock);
3491 CHECK_FSP(fsp,conn);
3493 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3494 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3496 status = do_unlock(fsp,
3497 SVAL(inbuf,smb_pid),
3498 count,
3499 offset,
3500 WINDOWS_LOCK);
3502 if (NT_STATUS_V(status)) {
3503 END_PROFILE(SMBunlock);
3504 return ERROR_NT(status);
3507 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3508 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3510 END_PROFILE(SMBunlock);
3511 return(outsize);
3514 #undef DBGC_CLASS
3515 #define DBGC_CLASS DBGC_ALL
3517 /****************************************************************************
3518 Reply to a tdis.
3519 conn POINTER CAN BE NULL HERE !
3520 ****************************************************************************/
3522 int reply_tdis(connection_struct *conn,
3523 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3525 int outsize = set_message(outbuf,0,0,False);
3526 uint16 vuid;
3527 START_PROFILE(SMBtdis);
3529 vuid = SVAL(inbuf,smb_uid);
3531 if (!conn) {
3532 DEBUG(4,("Invalid connection in tdis\n"));
3533 END_PROFILE(SMBtdis);
3534 return ERROR_DOS(ERRSRV,ERRinvnid);
3537 conn->used = False;
3539 close_cnum(conn,vuid);
3541 END_PROFILE(SMBtdis);
3542 return outsize;
3545 /****************************************************************************
3546 Reply to a echo.
3547 conn POINTER CAN BE NULL HERE !
3548 ****************************************************************************/
3550 int reply_echo(connection_struct *conn,
3551 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3553 int smb_reverb = SVAL(inbuf,smb_vwv0);
3554 int seq_num;
3555 unsigned int data_len = smb_buflen(inbuf);
3556 int outsize = set_message(outbuf,1,data_len,True);
3557 START_PROFILE(SMBecho);
3559 if (data_len > BUFFER_SIZE) {
3560 DEBUG(0,("reply_echo: data_len too large.\n"));
3561 END_PROFILE(SMBecho);
3562 return -1;
3565 /* copy any incoming data back out */
3566 if (data_len > 0)
3567 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3569 if (smb_reverb > 100) {
3570 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3571 smb_reverb = 100;
3574 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3575 SSVAL(outbuf,smb_vwv0,seq_num);
3577 smb_setlen(outbuf,outsize - 4);
3579 show_msg(outbuf);
3580 if (!send_smb(smbd_server_fd(),outbuf))
3581 exit_server("reply_echo: send_smb failed.");
3584 DEBUG(3,("echo %d times\n", smb_reverb));
3586 smb_echo_count++;
3588 END_PROFILE(SMBecho);
3589 return -1;
3592 /****************************************************************************
3593 Reply to a printopen.
3594 ****************************************************************************/
3596 int reply_printopen(connection_struct *conn,
3597 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3599 int outsize = 0;
3600 files_struct *fsp;
3601 START_PROFILE(SMBsplopen);
3603 if (!CAN_PRINT(conn)) {
3604 END_PROFILE(SMBsplopen);
3605 return ERROR_DOS(ERRDOS,ERRnoaccess);
3608 /* Open for exclusive use, write only. */
3609 fsp = print_fsp_open(conn, NULL);
3611 if (!fsp) {
3612 END_PROFILE(SMBsplopen);
3613 return(UNIXERROR(ERRDOS,ERRnoaccess));
3616 outsize = set_message(outbuf,1,0,True);
3617 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3619 DEBUG(3,("openprint fd=%d fnum=%d\n",
3620 fsp->fh->fd, fsp->fnum));
3622 END_PROFILE(SMBsplopen);
3623 return(outsize);
3626 /****************************************************************************
3627 Reply to a printclose.
3628 ****************************************************************************/
3630 int reply_printclose(connection_struct *conn,
3631 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3633 int outsize = set_message(outbuf,0,0,False);
3634 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3635 int close_err = 0;
3636 START_PROFILE(SMBsplclose);
3638 CHECK_FSP(fsp,conn);
3640 if (!CAN_PRINT(conn)) {
3641 END_PROFILE(SMBsplclose);
3642 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3645 DEBUG(3,("printclose fd=%d fnum=%d\n",
3646 fsp->fh->fd,fsp->fnum));
3648 close_err = close_file(fsp,NORMAL_CLOSE);
3650 if(close_err != 0) {
3651 errno = close_err;
3652 END_PROFILE(SMBsplclose);
3653 return(UNIXERROR(ERRHRD,ERRgeneral));
3656 END_PROFILE(SMBsplclose);
3657 return(outsize);
3660 /****************************************************************************
3661 Reply to a printqueue.
3662 ****************************************************************************/
3664 int reply_printqueue(connection_struct *conn,
3665 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3667 int outsize = set_message(outbuf,2,3,True);
3668 int max_count = SVAL(inbuf,smb_vwv0);
3669 int start_index = SVAL(inbuf,smb_vwv1);
3670 START_PROFILE(SMBsplretq);
3672 /* we used to allow the client to get the cnum wrong, but that
3673 is really quite gross and only worked when there was only
3674 one printer - I think we should now only accept it if they
3675 get it right (tridge) */
3676 if (!CAN_PRINT(conn)) {
3677 END_PROFILE(SMBsplretq);
3678 return ERROR_DOS(ERRDOS,ERRnoaccess);
3681 SSVAL(outbuf,smb_vwv0,0);
3682 SSVAL(outbuf,smb_vwv1,0);
3683 SCVAL(smb_buf(outbuf),0,1);
3684 SSVAL(smb_buf(outbuf),1,0);
3686 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3687 start_index, max_count));
3690 print_queue_struct *queue = NULL;
3691 print_status_struct status;
3692 char *p = smb_buf(outbuf) + 3;
3693 int count = print_queue_status(SNUM(conn), &queue, &status);
3694 int num_to_get = ABS(max_count);
3695 int first = (max_count>0?start_index:start_index+max_count+1);
3696 int i;
3698 if (first >= count)
3699 num_to_get = 0;
3700 else
3701 num_to_get = MIN(num_to_get,count-first);
3704 for (i=first;i<first+num_to_get;i++) {
3705 srv_put_dos_date2(p,0,queue[i].time);
3706 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3707 SSVAL(p,5, queue[i].job);
3708 SIVAL(p,7,queue[i].size);
3709 SCVAL(p,11,0);
3710 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3711 p += 28;
3714 if (count > 0) {
3715 outsize = set_message(outbuf,2,28*count+3,False);
3716 SSVAL(outbuf,smb_vwv0,count);
3717 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3718 SCVAL(smb_buf(outbuf),0,1);
3719 SSVAL(smb_buf(outbuf),1,28*count);
3722 SAFE_FREE(queue);
3724 DEBUG(3,("%d entries returned in queue\n",count));
3727 END_PROFILE(SMBsplretq);
3728 return(outsize);
3731 /****************************************************************************
3732 Reply to a printwrite.
3733 ****************************************************************************/
3735 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3737 int numtowrite;
3738 int outsize = set_message(outbuf,0,0,False);
3739 char *data;
3740 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3742 START_PROFILE(SMBsplwr);
3744 if (!CAN_PRINT(conn)) {
3745 END_PROFILE(SMBsplwr);
3746 return ERROR_DOS(ERRDOS,ERRnoaccess);
3749 CHECK_FSP(fsp,conn);
3750 if (!CHECK_WRITE(fsp)) {
3751 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3754 numtowrite = SVAL(smb_buf(inbuf),1);
3755 data = smb_buf(inbuf) + 3;
3757 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3758 END_PROFILE(SMBsplwr);
3759 return(UNIXERROR(ERRHRD,ERRdiskfull));
3762 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3764 END_PROFILE(SMBsplwr);
3765 return(outsize);
3768 /****************************************************************************
3769 The guts of the mkdir command, split out so it may be called by the NT SMB
3770 code.
3771 ****************************************************************************/
3773 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3775 int ret= -1;
3777 if(!CAN_WRITE(conn)) {
3778 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3779 errno = EACCES;
3780 return map_nt_error_from_unix(errno);
3783 if (bad_path) {
3784 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3787 if (!check_name(directory, conn)) {
3788 if(errno == ENOENT) {
3789 if (bad_path) {
3790 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3791 } else {
3792 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3795 return map_nt_error_from_unix(errno);
3798 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3799 if (ret == -1) {
3800 if(errno == ENOENT) {
3801 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3803 return map_nt_error_from_unix(errno);
3806 return NT_STATUS_OK;
3809 /****************************************************************************
3810 Reply to a mkdir.
3811 ****************************************************************************/
3813 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3815 pstring directory;
3816 int outsize;
3817 NTSTATUS status;
3818 BOOL bad_path = False;
3819 SMB_STRUCT_STAT sbuf;
3821 START_PROFILE(SMBmkdir);
3823 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3824 if (!NT_STATUS_IS_OK(status)) {
3825 END_PROFILE(SMBmkdir);
3826 return ERROR_NT(status);
3829 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3831 unix_convert(directory,conn,0,&bad_path,&sbuf);
3833 if( is_ntfs_stream_name(directory)) {
3834 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3835 END_PROFILE(SMBmkdir);
3836 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
3839 status = mkdir_internal(conn, directory,bad_path);
3840 if (!NT_STATUS_IS_OK(status)) {
3841 END_PROFILE(SMBmkdir);
3842 return ERROR_NT(status);
3845 if (lp_inherit_owner(SNUM(conn))) {
3846 /* Ensure we're checking for a symlink here.... */
3847 /* We don't want to get caught by a symlink racer. */
3849 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3850 END_PROFILE(SMBmkdir);
3851 return(UNIXERROR(ERRDOS,ERRnoaccess));
3854 if(!S_ISDIR(sbuf.st_mode)) {
3855 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3856 END_PROFILE(SMBmkdir);
3857 return(UNIXERROR(ERRDOS,ERRnoaccess));
3860 change_owner_to_parent(conn, NULL, directory, &sbuf);
3863 outsize = set_message(outbuf,0,0,False);
3865 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3867 END_PROFILE(SMBmkdir);
3868 return(outsize);
3871 /****************************************************************************
3872 Static function used by reply_rmdir to delete an entire directory
3873 tree recursively. Return False on ok, True on fail.
3874 ****************************************************************************/
3876 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3878 const char *dname = NULL;
3879 BOOL ret = False;
3880 long offset = 0;
3881 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3883 if(dir_hnd == NULL)
3884 return True;
3886 while((dname = ReadDirName(dir_hnd, &offset))) {
3887 pstring fullname;
3888 SMB_STRUCT_STAT st;
3890 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3891 continue;
3893 if (!is_visible_file(conn, directory, dname, &st, False))
3894 continue;
3896 /* Construct the full name. */
3897 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3898 errno = ENOMEM;
3899 ret = True;
3900 break;
3903 pstrcpy(fullname, directory);
3904 pstrcat(fullname, "/");
3905 pstrcat(fullname, dname);
3907 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3908 ret = True;
3909 break;
3912 if(st.st_mode & S_IFDIR) {
3913 if(recursive_rmdir(conn, fullname)!=0) {
3914 ret = True;
3915 break;
3917 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3918 ret = True;
3919 break;
3921 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3922 ret = True;
3923 break;
3926 CloseDir(dir_hnd);
3927 return ret;
3930 /****************************************************************************
3931 The internals of the rmdir code - called elsewhere.
3932 ****************************************************************************/
3934 BOOL rmdir_internals(connection_struct *conn, char *directory)
3936 BOOL ok;
3937 SMB_STRUCT_STAT st;
3939 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3940 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3942 * Check to see if the only thing in this directory are
3943 * vetoed files/directories. If so then delete them and
3944 * retry. If we fail to delete any of them (and we *don't*
3945 * do a recursive delete) then fail the rmdir.
3947 BOOL all_veto_files = True;
3948 const char *dname;
3949 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3951 if(dir_hnd != NULL) {
3952 long dirpos = 0;
3953 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3954 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3955 continue;
3956 if (!is_visible_file(conn, directory, dname, &st, False))
3957 continue;
3958 if(!IS_VETO_PATH(conn, dname)) {
3959 all_veto_files = False;
3960 break;
3964 if(all_veto_files) {
3965 RewindDir(dir_hnd,&dirpos);
3966 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3967 pstring fullname;
3969 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3970 continue;
3971 if (!is_visible_file(conn, directory, dname, &st, False))
3972 continue;
3974 /* Construct the full name. */
3975 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3976 errno = ENOMEM;
3977 break;
3980 pstrcpy(fullname, directory);
3981 pstrcat(fullname, "/");
3982 pstrcat(fullname, dname);
3984 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3985 break;
3986 if(st.st_mode & S_IFDIR) {
3987 if(lp_recursive_veto_delete(SNUM(conn))) {
3988 if(recursive_rmdir(conn, fullname) != 0)
3989 break;
3991 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3992 break;
3993 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3994 break;
3996 CloseDir(dir_hnd);
3997 /* Retry the rmdir */
3998 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3999 } else {
4000 CloseDir(dir_hnd);
4002 } else {
4003 errno = ENOTEMPTY;
4007 if (!ok)
4008 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
4010 return ok;
4013 /****************************************************************************
4014 Reply to a rmdir.
4015 ****************************************************************************/
4017 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4019 pstring directory;
4020 int outsize = 0;
4021 BOOL ok = False;
4022 BOOL bad_path = False;
4023 SMB_STRUCT_STAT sbuf;
4024 NTSTATUS status;
4025 START_PROFILE(SMBrmdir);
4027 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
4028 if (!NT_STATUS_IS_OK(status)) {
4029 END_PROFILE(SMBrmdir);
4030 return ERROR_NT(status);
4033 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
4035 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
4036 if (bad_path) {
4037 END_PROFILE(SMBrmdir);
4038 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4041 if (check_name(directory,conn)) {
4042 dptr_closepath(directory,SVAL(inbuf,smb_pid));
4043 ok = rmdir_internals(conn, directory);
4046 if (!ok) {
4047 END_PROFILE(SMBrmdir);
4048 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
4051 outsize = set_message(outbuf,0,0,False);
4053 DEBUG( 3, ( "rmdir %s\n", directory ) );
4055 END_PROFILE(SMBrmdir);
4056 return(outsize);
4059 /*******************************************************************
4060 Resolve wildcards in a filename rename.
4061 Note that name is in UNIX charset and thus potentially can be more
4062 than fstring buffer (255 bytes) especially in default UTF-8 case.
4063 Therefore, we use pstring inside and all calls should ensure that
4064 name2 is at least pstring-long (they do already)
4065 ********************************************************************/
4067 static BOOL resolve_wildcards(const char *name1, char *name2)
4069 pstring root1,root2;
4070 pstring ext1,ext2;
4071 char *p,*p2, *pname1, *pname2;
4072 int available_space, actual_space;
4075 pname1 = strrchr_m(name1,'/');
4076 pname2 = strrchr_m(name2,'/');
4078 if (!pname1 || !pname2)
4079 return(False);
4081 pstrcpy(root1,pname1);
4082 pstrcpy(root2,pname2);
4083 p = strrchr_m(root1,'.');
4084 if (p) {
4085 *p = 0;
4086 pstrcpy(ext1,p+1);
4087 } else {
4088 pstrcpy(ext1,"");
4090 p = strrchr_m(root2,'.');
4091 if (p) {
4092 *p = 0;
4093 pstrcpy(ext2,p+1);
4094 } else {
4095 pstrcpy(ext2,"");
4098 p = root1;
4099 p2 = root2;
4100 while (*p2) {
4101 if (*p2 == '?') {
4102 *p2 = *p;
4103 p2++;
4104 } else if (*p2 == '*') {
4105 pstrcpy(p2, p);
4106 break;
4107 } else {
4108 p2++;
4110 if (*p)
4111 p++;
4114 p = ext1;
4115 p2 = ext2;
4116 while (*p2) {
4117 if (*p2 == '?') {
4118 *p2 = *p;
4119 p2++;
4120 } else if (*p2 == '*') {
4121 pstrcpy(p2, p);
4122 break;
4123 } else {
4124 p2++;
4126 if (*p)
4127 p++;
4130 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4132 if (ext2[0]) {
4133 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4134 if (actual_space >= available_space - 1) {
4135 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4136 actual_space - available_space));
4138 } else {
4139 pstrcpy_base(pname2, root2, name2);
4142 return(True);
4145 /****************************************************************************
4146 Ensure open files have their names updated. Updated to notify other smbd's
4147 asynchronously.
4148 ****************************************************************************/
4150 static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
4151 SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
4153 files_struct *fsp;
4154 BOOL did_rename = False;
4156 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
4157 /* fsp_name is a relative path under the fsp. To change this for other
4158 sharepaths we need to manipulate relative paths. */
4159 /* TODO - create the absolute path and manipulate the newname
4160 relative to the sharepath. */
4161 if (fsp->conn != conn) {
4162 continue;
4164 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
4165 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
4166 fsp->fsp_name, newname ));
4167 string_set(&fsp->fsp_name, newname);
4168 did_rename = True;
4171 if (!did_rename) {
4172 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
4173 (unsigned int)dev, (double)inode, newname ));
4176 /* Send messages to all smbd's (not ourself) that the name has changed. */
4177 rename_share_filename(lck, conn->connectpath, newname);
4180 /****************************************************************************
4181 We need to check if the source path is a parent directory of the destination
4182 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4183 refuse the rename with a sharing violation. Under UNIX the above call can
4184 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4185 probably need to check that the client is a Windows one before disallowing
4186 this as a UNIX client (one with UNIX extensions) can know the source is a
4187 symlink and make this decision intelligently. Found by an excellent bug
4188 report from <AndyLiebman@aol.com>.
4189 ****************************************************************************/
4191 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4193 const char *psrc = src;
4194 const char *pdst = dest;
4195 size_t slen;
4197 if (psrc[0] == '.' && psrc[1] == '/') {
4198 psrc += 2;
4200 if (pdst[0] == '.' && pdst[1] == '/') {
4201 pdst += 2;
4203 if ((slen = strlen(psrc)) > strlen(pdst)) {
4204 return False;
4206 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4209 /****************************************************************************
4210 Rename an open file - given an fsp.
4211 ****************************************************************************/
4213 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists)
4215 SMB_STRUCT_STAT sbuf;
4216 BOOL bad_path = False;
4217 pstring newname_last_component;
4218 NTSTATUS error = NT_STATUS_OK;
4219 BOOL dest_exists;
4220 BOOL rcdest = True;
4221 struct share_mode_lock *lck = NULL;
4223 ZERO_STRUCT(sbuf);
4224 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
4226 /* Quick check for "." and ".." */
4227 if (!bad_path && newname_last_component[0] == '.') {
4228 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
4229 return NT_STATUS_ACCESS_DENIED;
4232 if (!rcdest && bad_path) {
4233 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4236 /* Ensure newname contains a '/' */
4237 if(strrchr_m(newname,'/') == 0) {
4238 pstring tmpstr;
4240 pstrcpy(tmpstr, "./");
4241 pstrcat(tmpstr, newname);
4242 pstrcpy(newname, tmpstr);
4246 * Check for special case with case preserving and not
4247 * case sensitive. If the old last component differs from the original
4248 * last component only by case, then we should allow
4249 * the rename (user is trying to change the case of the
4250 * filename).
4253 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4254 strequal(newname, fsp->fsp_name)) {
4255 char *p;
4256 pstring newname_modified_last_component;
4259 * Get the last component of the modified name.
4260 * Note that we guarantee that newname contains a '/'
4261 * character above.
4263 p = strrchr_m(newname,'/');
4264 pstrcpy(newname_modified_last_component,p+1);
4266 if(strcsequal(newname_modified_last_component,
4267 newname_last_component) == False) {
4269 * Replace the modified last component with
4270 * the original.
4272 pstrcpy(p+1, newname_last_component);
4277 * If the src and dest names are identical - including case,
4278 * don't do the rename, just return success.
4281 if (strcsequal(fsp->fsp_name, newname)) {
4282 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4283 newname));
4284 return NT_STATUS_OK;
4287 dest_exists = vfs_object_exist(conn,newname,NULL);
4289 if(!replace_if_exists && dest_exists) {
4290 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4291 fsp->fsp_name,newname));
4292 return NT_STATUS_OBJECT_NAME_COLLISION;
4295 error = can_rename(conn,newname,attrs,&sbuf);
4297 if (dest_exists && !NT_STATUS_IS_OK(error)) {
4298 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4299 nt_errstr(error), fsp->fsp_name,newname));
4300 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
4301 error = NT_STATUS_ACCESS_DENIED;
4302 return error;
4305 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4306 return NT_STATUS_ACCESS_DENIED;
4309 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
4311 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4312 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4313 fsp->fsp_name,newname));
4314 rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
4315 TALLOC_FREE(lck);
4316 return NT_STATUS_OK;
4319 TALLOC_FREE(lck);
4321 if (errno == ENOTDIR || errno == EISDIR) {
4322 error = NT_STATUS_OBJECT_NAME_COLLISION;
4323 } else {
4324 error = map_nt_error_from_unix(errno);
4327 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4328 nt_errstr(error), fsp->fsp_name,newname));
4330 return error;
4333 /****************************************************************************
4334 The guts of the rename command, split out so it may be called by the NT SMB
4335 code.
4336 ****************************************************************************/
4338 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild)
4340 pstring directory;
4341 pstring mask;
4342 pstring last_component_src;
4343 pstring last_component_dest;
4344 char *p;
4345 BOOL bad_path_src = False;
4346 BOOL bad_path_dest = False;
4347 int count=0;
4348 NTSTATUS error = NT_STATUS_OK;
4349 BOOL rc = True;
4350 BOOL rcdest = True;
4351 SMB_STRUCT_STAT sbuf1, sbuf2;
4352 struct share_mode_lock *lck = NULL;
4354 *directory = *mask = 0;
4356 ZERO_STRUCT(sbuf1);
4357 ZERO_STRUCT(sbuf2);
4359 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
4360 if (!rc && bad_path_src) {
4361 if (ms_has_wild(last_component_src))
4362 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4363 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4366 /* Quick check for "." and ".." */
4367 if (last_component_src[0] == '.') {
4368 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
4369 return NT_STATUS_OBJECT_NAME_INVALID;
4373 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4375 /* Quick check for "." and ".." */
4376 if (last_component_dest[0] == '.') {
4377 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4378 return NT_STATUS_OBJECT_NAME_INVALID;
4383 * Split the old name into directory and last component
4384 * strings. Note that unix_convert may have stripped off a
4385 * leading ./ from both name and newname if the rename is
4386 * at the root of the share. We need to make sure either both
4387 * name and newname contain a / character or neither of them do
4388 * as this is checked in resolve_wildcards().
4391 p = strrchr_m(name,'/');
4392 if (!p) {
4393 pstrcpy(directory,".");
4394 pstrcpy(mask,name);
4395 } else {
4396 *p = 0;
4397 pstrcpy(directory,name);
4398 pstrcpy(mask,p+1);
4399 *p = '/'; /* Replace needed for exceptional test below. */
4403 * We should only check the mangled cache
4404 * here if unix_convert failed. This means
4405 * that the path in 'mask' doesn't exist
4406 * on the file system and so we need to look
4407 * for a possible mangle. This patch from
4408 * Tine Smukavec <valentin.smukavec@hermes.si>.
4411 if (!rc && mangle_is_mangled(mask,SNUM(conn)))
4412 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4414 if (!has_wild) {
4416 * No wildcards - just process the one file.
4418 BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn));
4420 /* Add a terminating '/' to the directory name. */
4421 pstrcat(directory,"/");
4422 pstrcat(directory,mask);
4424 /* Ensure newname contains a '/' also */
4425 if(strrchr_m(newname,'/') == 0) {
4426 pstring tmpstr;
4428 pstrcpy(tmpstr, "./");
4429 pstrcat(tmpstr, newname);
4430 pstrcpy(newname, tmpstr);
4433 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4434 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4435 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4436 newname, last_component_dest, is_short_name));
4439 * Check for special case with case preserving and not
4440 * case sensitive, if directory and newname are identical,
4441 * and the old last component differs from the original
4442 * last component only by case, then we should allow
4443 * the rename (user is trying to change the case of the
4444 * filename).
4446 if((conn->case_sensitive == False) &&
4447 (((conn->case_preserve == True) &&
4448 (is_short_name == False)) ||
4449 ((conn->short_case_preserve == True) &&
4450 (is_short_name == True))) &&
4451 strcsequal(directory, newname)) {
4452 pstring modified_last_component;
4455 * Get the last component of the modified name.
4456 * Note that we guarantee that newname contains a '/'
4457 * character above.
4459 p = strrchr_m(newname,'/');
4460 pstrcpy(modified_last_component,p+1);
4462 if(strcsequal(modified_last_component,
4463 last_component_dest) == False) {
4465 * Replace the modified last component with
4466 * the original.
4468 pstrcpy(p+1, last_component_dest);
4472 resolve_wildcards(directory,newname);
4475 * The source object must exist.
4478 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4479 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4480 directory,newname));
4482 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4484 * Must return different errors depending on whether the parent
4485 * directory existed or not.
4488 p = strrchr_m(directory, '/');
4489 if (!p)
4490 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4491 *p = '\0';
4492 if (vfs_object_exist(conn, directory, NULL))
4493 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4494 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4496 error = map_nt_error_from_unix(errno);
4497 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4498 nt_errstr(error), directory,newname));
4500 return error;
4503 if (!rcdest && bad_path_dest) {
4504 if (ms_has_wild(last_component_dest))
4505 return NT_STATUS_OBJECT_NAME_INVALID;
4506 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4509 error = can_rename(conn,directory,attrs,&sbuf1);
4511 if (!NT_STATUS_IS_OK(error)) {
4512 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4513 nt_errstr(error), directory,newname));
4514 return error;
4518 * If the src and dest names are identical - including case,
4519 * don't do the rename, just return success.
4522 if (strcsequal(directory, newname)) {
4523 rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
4524 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4525 return NT_STATUS_OK;
4528 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4529 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4530 directory,newname));
4531 return NT_STATUS_OBJECT_NAME_COLLISION;
4534 if (rename_path_prefix_equal(directory, newname)) {
4535 return NT_STATUS_SHARING_VIOLATION;
4538 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
4540 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4541 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4542 directory,newname));
4543 rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
4544 TALLOC_FREE(lck);
4545 return NT_STATUS_OK;
4548 TALLOC_FREE(lck);
4549 if (errno == ENOTDIR || errno == EISDIR)
4550 error = NT_STATUS_OBJECT_NAME_COLLISION;
4551 else
4552 error = map_nt_error_from_unix(errno);
4554 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4555 nt_errstr(error), directory,newname));
4557 return error;
4558 } else {
4560 * Wildcards - process each file that matches.
4562 struct smb_Dir *dir_hnd = NULL;
4563 const char *dname;
4564 pstring destname;
4566 if (strequal(mask,"????????.???"))
4567 pstrcpy(mask,"*");
4569 if (check_name(directory,conn))
4570 dir_hnd = OpenDir(conn, directory, mask, attrs);
4572 if (dir_hnd) {
4573 long offset = 0;
4574 error = NT_STATUS_NO_SUCH_FILE;
4575 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4577 while ((dname = ReadDirName(dir_hnd, &offset))) {
4578 pstring fname;
4579 BOOL sysdir_entry = False;
4581 pstrcpy(fname,dname);
4583 /* Quick check for "." and ".." */
4584 if (fname[0] == '.') {
4585 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4586 if (attrs & aDIR) {
4587 sysdir_entry = True;
4588 } else {
4589 continue;
4594 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4595 continue;
4597 if(!mask_match(fname, mask, conn->case_sensitive))
4598 continue;
4600 if (sysdir_entry) {
4601 error = NT_STATUS_OBJECT_NAME_INVALID;
4602 break;
4605 error = NT_STATUS_ACCESS_DENIED;
4606 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4607 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4608 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4609 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4610 continue;
4612 error = can_rename(conn,fname,attrs,&sbuf1);
4613 if (!NT_STATUS_IS_OK(error)) {
4614 DEBUG(6,("rename %s refused\n", fname));
4615 continue;
4617 pstrcpy(destname,newname);
4619 if (!resolve_wildcards(fname,destname)) {
4620 DEBUG(6,("resolve_wildcards %s %s failed\n",
4621 fname, destname));
4622 continue;
4625 if (strcsequal(fname,destname)) {
4626 rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
4627 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4628 count++;
4629 error = NT_STATUS_OK;
4630 continue;
4633 if (!replace_if_exists &&
4634 vfs_file_exist(conn,destname, NULL)) {
4635 DEBUG(6,("file_exist %s\n", destname));
4636 error = NT_STATUS_OBJECT_NAME_COLLISION;
4637 continue;
4640 if (rename_path_prefix_equal(fname, destname)) {
4641 return NT_STATUS_SHARING_VIOLATION;
4644 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
4646 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4647 rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
4648 count++;
4649 error = NT_STATUS_OK;
4651 TALLOC_FREE(lck);
4652 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4654 CloseDir(dir_hnd);
4657 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4658 if (!rcdest && bad_path_dest) {
4659 if (ms_has_wild(last_component_dest))
4660 return NT_STATUS_OBJECT_NAME_INVALID;
4661 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4666 if (count == 0 && NT_STATUS_IS_OK(error)) {
4667 error = map_nt_error_from_unix(errno);
4670 return error;
4673 /****************************************************************************
4674 Reply to a mv.
4675 ****************************************************************************/
4677 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4678 int dum_buffsize)
4680 int outsize = 0;
4681 pstring name;
4682 pstring newname;
4683 char *p;
4684 uint32 attrs = SVAL(inbuf,smb_vwv0);
4685 NTSTATUS status;
4686 BOOL path_contains_wcard = False;
4688 START_PROFILE(SMBmv);
4690 p = smb_buf(inbuf) + 1;
4691 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
4692 if (!NT_STATUS_IS_OK(status)) {
4693 END_PROFILE(SMBmv);
4694 return ERROR_NT(status);
4696 p++;
4697 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
4698 if (!NT_STATUS_IS_OK(status)) {
4699 END_PROFILE(SMBmv);
4700 return ERROR_NT(status);
4703 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4704 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4706 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4708 status = rename_internals(conn, name, newname, attrs, False, path_contains_wcard);
4709 if (!NT_STATUS_IS_OK(status)) {
4710 END_PROFILE(SMBmv);
4711 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4712 /* We have re-scheduled this call. */
4713 return -1;
4715 return ERROR_NT(status);
4719 * Win2k needs a changenotify request response before it will
4720 * update after a rename..
4722 process_pending_change_notify_queue((time_t)0);
4723 outsize = set_message(outbuf,0,0,False);
4725 END_PROFILE(SMBmv);
4726 return(outsize);
4729 /*******************************************************************
4730 Copy a file as part of a reply_copy.
4731 ******************************************************************/
4733 BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4734 int count,BOOL target_is_directory, int *err_ret)
4736 SMB_STRUCT_STAT src_sbuf, sbuf2;
4737 SMB_OFF_T ret=-1;
4738 files_struct *fsp1,*fsp2;
4739 pstring dest;
4740 uint32 dosattrs;
4741 uint32 new_create_disposition;
4743 *err_ret = 0;
4745 pstrcpy(dest,dest1);
4746 if (target_is_directory) {
4747 char *p = strrchr_m(src,'/');
4748 if (p) {
4749 p++;
4750 } else {
4751 p = src;
4753 pstrcat(dest,"/");
4754 pstrcat(dest,p);
4757 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4758 return(False);
4761 if (!target_is_directory && count) {
4762 new_create_disposition = FILE_OPEN;
4763 } else {
4764 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4765 NULL, NULL, &new_create_disposition, NULL)) {
4766 return(False);
4770 fsp1 = open_file_ntcreate(conn,src,&src_sbuf,
4771 FILE_GENERIC_READ,
4772 FILE_SHARE_READ|FILE_SHARE_WRITE,
4773 FILE_OPEN,
4775 FILE_ATTRIBUTE_NORMAL,
4776 INTERNAL_OPEN_ONLY,
4777 NULL);
4779 if (!fsp1) {
4780 return(False);
4783 dosattrs = dos_mode(conn, src, &src_sbuf);
4784 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4785 ZERO_STRUCTP(&sbuf2);
4788 fsp2 = open_file_ntcreate(conn,dest,&sbuf2,
4789 FILE_GENERIC_WRITE,
4790 FILE_SHARE_READ|FILE_SHARE_WRITE,
4791 new_create_disposition,
4793 dosattrs,
4794 INTERNAL_OPEN_ONLY,
4795 NULL);
4797 if (!fsp2) {
4798 close_file(fsp1,ERROR_CLOSE);
4799 return(False);
4802 if ((ofun&3) == 1) {
4803 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4804 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4806 * Stop the copy from occurring.
4808 ret = -1;
4809 src_sbuf.st_size = 0;
4813 if (src_sbuf.st_size) {
4814 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4817 close_file(fsp1,NORMAL_CLOSE);
4819 /* Ensure the modtime is set correctly on the destination file. */
4820 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4823 * As we are opening fsp1 read-only we only expect
4824 * an error on close on fsp2 if we are out of space.
4825 * Thus we don't look at the error return from the
4826 * close of fsp1.
4828 *err_ret = close_file(fsp2,NORMAL_CLOSE);
4830 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4833 /****************************************************************************
4834 Reply to a file copy.
4835 ****************************************************************************/
4837 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4839 int outsize = 0;
4840 pstring name;
4841 pstring directory;
4842 pstring mask,newname;
4843 char *p;
4844 int count=0;
4845 int error = ERRnoaccess;
4846 int err = 0;
4847 BOOL has_wild;
4848 BOOL exists=False;
4849 int tid2 = SVAL(inbuf,smb_vwv0);
4850 int ofun = SVAL(inbuf,smb_vwv1);
4851 int flags = SVAL(inbuf,smb_vwv2);
4852 BOOL target_is_directory=False;
4853 BOOL bad_path1 = False;
4854 BOOL bad_path2 = False;
4855 BOOL path_contains_wcard1 = False;
4856 BOOL path_contains_wcard2 = False;
4857 BOOL rc = True;
4858 SMB_STRUCT_STAT sbuf1, sbuf2;
4859 NTSTATUS status;
4860 START_PROFILE(SMBcopy);
4862 *directory = *mask = 0;
4864 p = smb_buf(inbuf);
4865 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
4866 if (!NT_STATUS_IS_OK(status)) {
4867 END_PROFILE(SMBcopy);
4868 return ERROR_NT(status);
4870 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2);
4871 if (!NT_STATUS_IS_OK(status)) {
4872 END_PROFILE(SMBcopy);
4873 return ERROR_NT(status);
4876 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4878 if (tid2 != conn->cnum) {
4879 /* can't currently handle inter share copies XXXX */
4880 DEBUG(3,("Rejecting inter-share copy\n"));
4881 END_PROFILE(SMBcopy);
4882 return ERROR_DOS(ERRSRV,ERRinvdevice);
4885 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4886 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4888 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4889 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4891 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4893 if ((flags&1) && target_is_directory) {
4894 END_PROFILE(SMBcopy);
4895 return ERROR_DOS(ERRDOS,ERRbadfile);
4898 if ((flags&2) && !target_is_directory) {
4899 END_PROFILE(SMBcopy);
4900 return ERROR_DOS(ERRDOS,ERRbadpath);
4903 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4904 /* wants a tree copy! XXXX */
4905 DEBUG(3,("Rejecting tree copy\n"));
4906 END_PROFILE(SMBcopy);
4907 return ERROR_DOS(ERRSRV,ERRerror);
4910 p = strrchr_m(name,'/');
4911 if (!p) {
4912 pstrcpy(directory,"./");
4913 pstrcpy(mask,name);
4914 } else {
4915 *p = 0;
4916 pstrcpy(directory,name);
4917 pstrcpy(mask,p+1);
4921 * We should only check the mangled cache
4922 * here if unix_convert failed. This means
4923 * that the path in 'mask' doesn't exist
4924 * on the file system and so we need to look
4925 * for a possible mangle. This patch from
4926 * Tine Smukavec <valentin.smukavec@hermes.si>.
4929 if (!rc && mangle_is_mangled(mask, SNUM(conn)))
4930 mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
4932 has_wild = path_contains_wcard1;
4934 if (!has_wild) {
4935 pstrcat(directory,"/");
4936 pstrcat(directory,mask);
4937 if (resolve_wildcards(directory,newname) &&
4938 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4939 count++;
4940 if(!count && err) {
4941 errno = err;
4942 END_PROFILE(SMBcopy);
4943 return(UNIXERROR(ERRHRD,ERRgeneral));
4945 if (!count) {
4946 exists = vfs_file_exist(conn,directory,NULL);
4948 } else {
4949 struct smb_Dir *dir_hnd = NULL;
4950 const char *dname;
4951 pstring destname;
4953 if (strequal(mask,"????????.???"))
4954 pstrcpy(mask,"*");
4956 if (check_name(directory,conn))
4957 dir_hnd = OpenDir(conn, directory, mask, 0);
4959 if (dir_hnd) {
4960 long offset = 0;
4961 error = ERRbadfile;
4963 while ((dname = ReadDirName(dir_hnd, &offset))) {
4964 pstring fname;
4965 pstrcpy(fname,dname);
4967 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4968 continue;
4970 if(!mask_match(fname, mask, conn->case_sensitive))
4971 continue;
4973 error = ERRnoaccess;
4974 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4975 pstrcpy(destname,newname);
4976 if (resolve_wildcards(fname,destname) &&
4977 copy_file(fname,destname,conn,ofun,
4978 count,target_is_directory,&err))
4979 count++;
4980 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4982 CloseDir(dir_hnd);
4986 if (count == 0) {
4987 if(err) {
4988 /* Error on close... */
4989 errno = err;
4990 END_PROFILE(SMBcopy);
4991 return(UNIXERROR(ERRHRD,ERRgeneral));
4994 if (exists) {
4995 END_PROFILE(SMBcopy);
4996 return ERROR_DOS(ERRDOS,error);
4997 } else {
4998 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4999 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
5001 END_PROFILE(SMBcopy);
5002 return(UNIXERROR(ERRDOS,error));
5006 outsize = set_message(outbuf,1,0,True);
5007 SSVAL(outbuf,smb_vwv0,count);
5009 END_PROFILE(SMBcopy);
5010 return(outsize);
5013 /****************************************************************************
5014 Reply to a setdir.
5015 ****************************************************************************/
5017 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5019 int snum;
5020 int outsize = 0;
5021 BOOL ok = False;
5022 pstring newdir;
5023 NTSTATUS status;
5025 START_PROFILE(pathworks_setdir);
5027 snum = SNUM(conn);
5028 if (!CAN_SETDIR(snum)) {
5029 END_PROFILE(pathworks_setdir);
5030 return ERROR_DOS(ERRDOS,ERRnoaccess);
5033 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
5034 if (!NT_STATUS_IS_OK(status)) {
5035 END_PROFILE(pathworks_setdir);
5036 return ERROR_NT(status);
5039 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
5041 if (strlen(newdir) == 0) {
5042 ok = True;
5043 } else {
5044 ok = vfs_directory_exist(conn,newdir,NULL);
5045 if (ok)
5046 set_conn_connectpath(conn,newdir);
5049 if (!ok) {
5050 END_PROFILE(pathworks_setdir);
5051 return ERROR_DOS(ERRDOS,ERRbadpath);
5054 outsize = set_message(outbuf,0,0,False);
5055 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5057 DEBUG(3,("setdir %s\n", newdir));
5059 END_PROFILE(pathworks_setdir);
5060 return(outsize);
5063 #undef DBGC_CLASS
5064 #define DBGC_CLASS DBGC_LOCKING
5066 /****************************************************************************
5067 Get a lock pid, dealing with large count requests.
5068 ****************************************************************************/
5070 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5072 if(!large_file_format)
5073 return SVAL(data,SMB_LPID_OFFSET(data_offset));
5074 else
5075 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5078 /****************************************************************************
5079 Get a lock count, dealing with large count requests.
5080 ****************************************************************************/
5082 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5084 SMB_BIG_UINT count = 0;
5086 if(!large_file_format) {
5087 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5088 } else {
5090 #if defined(HAVE_LONGLONG)
5091 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5092 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5093 #else /* HAVE_LONGLONG */
5096 * NT4.x seems to be broken in that it sends large file (64 bit)
5097 * lockingX calls even if the CAP_LARGE_FILES was *not*
5098 * negotiated. For boxes without large unsigned ints truncate the
5099 * lock count by dropping the top 32 bits.
5102 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5103 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5104 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5105 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5106 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5109 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5110 #endif /* HAVE_LONGLONG */
5113 return count;
5116 #if !defined(HAVE_LONGLONG)
5117 /****************************************************************************
5118 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5119 ****************************************************************************/
5121 static uint32 map_lock_offset(uint32 high, uint32 low)
5123 unsigned int i;
5124 uint32 mask = 0;
5125 uint32 highcopy = high;
5128 * Try and find out how many significant bits there are in high.
5131 for(i = 0; highcopy; i++)
5132 highcopy >>= 1;
5135 * We use 31 bits not 32 here as POSIX
5136 * lock offsets may not be negative.
5139 mask = (~0) << (31 - i);
5141 if(low & mask)
5142 return 0; /* Fail. */
5144 high <<= (31 - i);
5146 return (high|low);
5148 #endif /* !defined(HAVE_LONGLONG) */
5150 /****************************************************************************
5151 Get a lock offset, dealing with large offset requests.
5152 ****************************************************************************/
5154 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5156 SMB_BIG_UINT offset = 0;
5158 *err = False;
5160 if(!large_file_format) {
5161 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5162 } else {
5164 #if defined(HAVE_LONGLONG)
5165 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5166 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5167 #else /* HAVE_LONGLONG */
5170 * NT4.x seems to be broken in that it sends large file (64 bit)
5171 * lockingX calls even if the CAP_LARGE_FILES was *not*
5172 * negotiated. For boxes without large unsigned ints mangle the
5173 * lock offset by mapping the top 32 bits onto the lower 32.
5176 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5177 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5178 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5179 uint32 new_low = 0;
5181 if((new_low = map_lock_offset(high, low)) == 0) {
5182 *err = True;
5183 return (SMB_BIG_UINT)-1;
5186 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5187 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5188 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5189 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5192 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5193 #endif /* HAVE_LONGLONG */
5196 return offset;
5199 /****************************************************************************
5200 Reply to a lockingX request.
5201 ****************************************************************************/
5203 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5204 int length, int bufsize)
5206 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5207 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5208 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5209 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5210 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5211 SMB_BIG_UINT count = 0, offset = 0;
5212 uint16 lock_pid;
5213 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5214 int i;
5215 char *data;
5216 BOOL large_file_format =
5217 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5218 BOOL err;
5219 BOOL my_lock_ctx = False;
5220 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5222 START_PROFILE(SMBlockingX);
5224 CHECK_FSP(fsp,conn);
5226 data = smb_buf(inbuf);
5228 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5229 /* we don't support these - and CANCEL_LOCK makes w2k
5230 and XP reboot so I don't really want to be
5231 compatible! (tridge) */
5232 return ERROR_FORCE_DOS(ERRDOS, ERRnoatomiclocks);
5235 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5236 /* Need to make this like a cancel.... JRA. */
5237 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
5240 /* Check if this is an oplock break on a file
5241 we have granted an oplock on.
5243 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5244 /* Client can insist on breaking to none. */
5245 BOOL break_to_none = (oplocklevel == 0);
5246 BOOL result;
5248 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5249 "for fnum = %d\n", (unsigned int)oplocklevel,
5250 fsp->fnum ));
5253 * Make sure we have granted an exclusive or batch oplock on
5254 * this file.
5257 if (fsp->oplock_type == 0) {
5259 /* The Samba4 nbench simulator doesn't understand
5260 the difference between break to level2 and break
5261 to none from level2 - it sends oplock break
5262 replies in both cases. Don't keep logging an error
5263 message here - just ignore it. JRA. */
5265 DEBUG(5,("reply_lockingX: Error : oplock break from "
5266 "client for fnum = %d (oplock=%d) and no "
5267 "oplock granted on this file (%s).\n",
5268 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5270 /* if this is a pure oplock break request then don't
5271 * send a reply */
5272 if (num_locks == 0 && num_ulocks == 0) {
5273 END_PROFILE(SMBlockingX);
5274 return -1;
5275 } else {
5276 END_PROFILE(SMBlockingX);
5277 return ERROR_DOS(ERRDOS,ERRlock);
5281 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5282 (break_to_none)) {
5283 result = remove_oplock(fsp);
5284 } else {
5285 result = downgrade_oplock(fsp);
5288 if (!result) {
5289 DEBUG(0, ("reply_lockingX: error in removing "
5290 "oplock on file %s\n", fsp->fsp_name));
5291 /* Hmmm. Is this panic justified? */
5292 smb_panic("internal tdb error");
5295 reply_to_oplock_break_requests(fsp);
5297 /* if this is a pure oplock break request then don't send a
5298 * reply */
5299 if (num_locks == 0 && num_ulocks == 0) {
5300 /* Sanity check - ensure a pure oplock break is not a
5301 chained request. */
5302 if(CVAL(inbuf,smb_vwv0) != 0xff)
5303 DEBUG(0,("reply_lockingX: Error : pure oplock "
5304 "break is a chained %d request !\n",
5305 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5306 END_PROFILE(SMBlockingX);
5307 return -1;
5312 * We do this check *after* we have checked this is not a oplock break
5313 * response message. JRA.
5316 release_level_2_oplocks_on_change(fsp);
5318 /* Data now points at the beginning of the list
5319 of smb_unlkrng structs */
5320 for(i = 0; i < (int)num_ulocks; i++) {
5321 lock_pid = get_lock_pid( data, i, large_file_format);
5322 count = get_lock_count( data, i, large_file_format);
5323 offset = get_lock_offset( data, i, large_file_format, &err);
5326 * There is no error code marked "stupid client bug".... :-).
5328 if(err) {
5329 END_PROFILE(SMBlockingX);
5330 return ERROR_DOS(ERRDOS,ERRnoaccess);
5333 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5334 "pid %u, file %s\n", (double)offset, (double)count,
5335 (unsigned int)lock_pid, fsp->fsp_name ));
5337 status = do_unlock(fsp,
5338 lock_pid,
5339 count,
5340 offset,
5341 WINDOWS_LOCK);
5343 if (NT_STATUS_V(status)) {
5344 END_PROFILE(SMBlockingX);
5345 return ERROR_NT(status);
5349 /* Setup the timeout in seconds. */
5351 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
5353 /* Now do any requested locks */
5354 data += ((large_file_format ? 20 : 10)*num_ulocks);
5356 /* Data now points at the beginning of the list
5357 of smb_lkrng structs */
5359 for(i = 0; i < (int)num_locks; i++) {
5360 enum brl_type lock_type = ((locktype & 1) ? READ_LOCK:WRITE_LOCK);
5361 lock_pid = get_lock_pid( data, i, large_file_format);
5362 count = get_lock_count( data, i, large_file_format);
5363 offset = get_lock_offset( data, i, large_file_format, &err);
5366 * There is no error code marked "stupid client bug".... :-).
5368 if(err) {
5369 END_PROFILE(SMBlockingX);
5370 return ERROR_DOS(ERRDOS,ERRnoaccess);
5373 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5374 "%u, file %s timeout = %d\n", (double)offset,
5375 (double)count, (unsigned int)lock_pid,
5376 fsp->fsp_name, (int)lock_timeout ));
5378 status = do_lock_spin(fsp,
5379 lock_pid,
5380 count,
5381 offset,
5382 lock_type,
5383 WINDOWS_LOCK,
5384 &my_lock_ctx);
5386 if (NT_STATUS_V(status)) {
5388 * Interesting fact found by IFSTEST /t
5389 * LockOverlappedTest... Even if it's our own lock
5390 * context, we need to wait here as there may be an
5391 * unlock on the way. So I removed a "&&
5392 * !my_lock_ctx" from the following if statement. JRA.
5394 if ((lock_timeout != 0) &&
5395 lp_blocking_locks(SNUM(conn)) &&
5396 ERROR_WAS_LOCK_DENIED(status)) {
5398 * A blocking lock was requested. Package up
5399 * this smb into a queued request and push it
5400 * onto the blocking lock queue.
5402 if(push_blocking_lock_request(inbuf, length,
5403 fsp,
5404 lock_timeout,
5406 lock_pid,
5407 lock_type,
5408 WINDOWS_LOCK,
5409 offset,
5410 count)) {
5411 END_PROFILE(SMBlockingX);
5412 return -1;
5415 break;
5419 /* If any of the above locks failed, then we must unlock
5420 all of the previous locks (X/Open spec). */
5421 if (i != num_locks && num_locks != 0) {
5423 * Ensure we don't do a remove on the lock that just failed,
5424 * as under POSIX rules, if we have a lock already there, we
5425 * will delete it (and we shouldn't) .....
5427 for(i--; i >= 0; i--) {
5428 lock_pid = get_lock_pid( data, i, large_file_format);
5429 count = get_lock_count( data, i, large_file_format);
5430 offset = get_lock_offset( data, i, large_file_format,
5431 &err);
5434 * There is no error code marked "stupid client
5435 * bug".... :-).
5437 if(err) {
5438 END_PROFILE(SMBlockingX);
5439 return ERROR_DOS(ERRDOS,ERRnoaccess);
5442 do_unlock(fsp,
5443 lock_pid,
5444 count,
5445 offset,
5446 WINDOWS_LOCK);
5448 END_PROFILE(SMBlockingX);
5449 return ERROR_NT(status);
5452 set_message(outbuf,2,0,True);
5454 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5455 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5457 END_PROFILE(SMBlockingX);
5458 return chain_reply(inbuf,outbuf,length,bufsize);
5461 #undef DBGC_CLASS
5462 #define DBGC_CLASS DBGC_ALL
5464 /****************************************************************************
5465 Reply to a SMBreadbmpx (read block multiplex) request.
5466 ****************************************************************************/
5468 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5470 ssize_t nread = -1;
5471 ssize_t total_read;
5472 char *data;
5473 SMB_OFF_T startpos;
5474 int outsize;
5475 size_t maxcount;
5476 int max_per_packet;
5477 size_t tcount;
5478 int pad;
5479 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5480 START_PROFILE(SMBreadBmpx);
5482 /* this function doesn't seem to work - disable by default */
5483 if (!lp_readbmpx()) {
5484 END_PROFILE(SMBreadBmpx);
5485 return ERROR_DOS(ERRSRV,ERRuseSTD);
5488 outsize = set_message(outbuf,8,0,True);
5490 CHECK_FSP(fsp,conn);
5491 if (!CHECK_READ(fsp,inbuf)) {
5492 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5495 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5496 maxcount = SVAL(inbuf,smb_vwv3);
5498 data = smb_buf(outbuf);
5499 pad = ((long)data)%4;
5500 if (pad)
5501 pad = 4 - pad;
5502 data += pad;
5504 max_per_packet = bufsize-(outsize+pad);
5505 tcount = maxcount;
5506 total_read = 0;
5508 if (is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5509 END_PROFILE(SMBreadBmpx);
5510 return ERROR_DOS(ERRDOS,ERRlock);
5513 do {
5514 size_t N = MIN(max_per_packet,tcount-total_read);
5516 nread = read_file(fsp,data,startpos,N);
5518 if (nread <= 0)
5519 nread = 0;
5521 if (nread < (ssize_t)N)
5522 tcount = total_read + nread;
5524 set_message(outbuf,8,nread+pad,False);
5525 SIVAL(outbuf,smb_vwv0,startpos);
5526 SSVAL(outbuf,smb_vwv2,tcount);
5527 SSVAL(outbuf,smb_vwv6,nread);
5528 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5530 show_msg(outbuf);
5531 if (!send_smb(smbd_server_fd(),outbuf))
5532 exit_server("reply_readbmpx: send_smb failed.");
5534 total_read += nread;
5535 startpos += nread;
5536 } while (total_read < (ssize_t)tcount);
5538 END_PROFILE(SMBreadBmpx);
5539 return(-1);
5542 /****************************************************************************
5543 Reply to a SMBsetattrE.
5544 ****************************************************************************/
5546 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5548 struct utimbuf unix_times;
5549 int outsize = 0;
5550 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5551 START_PROFILE(SMBsetattrE);
5553 outsize = set_message(outbuf,0,0,False);
5555 if(!fsp || (fsp->conn != conn)) {
5556 END_PROFILE(SMBsetattrE);
5557 return ERROR_DOS(ERRDOS,ERRbadfid);
5561 * Convert the DOS times into unix times. Ignore create
5562 * time as UNIX can't set this.
5565 unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3);
5566 unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5);
5569 * Patch from Ray Frush <frush@engr.colostate.edu>
5570 * Sometimes times are sent as zero - ignore them.
5573 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5574 /* Ignore request */
5575 if( DEBUGLVL( 3 ) ) {
5576 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5577 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5579 END_PROFILE(SMBsetattrE);
5580 return(outsize);
5581 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5582 /* set modify time = to access time if modify time was unset */
5583 unix_times.modtime = unix_times.actime;
5586 /* Set the date on this file */
5587 /* Should we set pending modtime here ? JRA */
5588 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5589 END_PROFILE(SMBsetattrE);
5590 return ERROR_DOS(ERRDOS,ERRnoaccess);
5593 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5594 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5596 END_PROFILE(SMBsetattrE);
5597 return(outsize);
5601 /* Back from the dead for OS/2..... JRA. */
5603 /****************************************************************************
5604 Reply to a SMBwritebmpx (write block multiplex primary) request.
5605 ****************************************************************************/
5607 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5609 size_t numtowrite;
5610 ssize_t nwritten = -1;
5611 int outsize = 0;
5612 SMB_OFF_T startpos;
5613 size_t tcount;
5614 BOOL write_through;
5615 int smb_doff;
5616 char *data;
5617 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5618 START_PROFILE(SMBwriteBmpx);
5620 CHECK_FSP(fsp,conn);
5621 if (!CHECK_WRITE(fsp)) {
5622 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5624 if (HAS_CACHED_ERROR(fsp)) {
5625 return(CACHED_ERROR(fsp));
5628 tcount = SVAL(inbuf,smb_vwv1);
5629 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5630 write_through = BITSETW(inbuf+smb_vwv7,0);
5631 numtowrite = SVAL(inbuf,smb_vwv10);
5632 smb_doff = SVAL(inbuf,smb_vwv11);
5634 data = smb_base(inbuf) + smb_doff;
5636 /* If this fails we need to send an SMBwriteC response,
5637 not an SMBwritebmpx - set this up now so we don't forget */
5638 SCVAL(outbuf,smb_com,SMBwritec);
5640 if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5641 END_PROFILE(SMBwriteBmpx);
5642 return(ERROR_DOS(ERRDOS,ERRlock));
5645 nwritten = write_file(fsp,data,startpos,numtowrite);
5647 sync_file(conn, fsp, write_through);
5649 if(nwritten < (ssize_t)numtowrite) {
5650 END_PROFILE(SMBwriteBmpx);
5651 return(UNIXERROR(ERRHRD,ERRdiskfull));
5654 /* If the maximum to be written to this file
5655 is greater than what we just wrote then set
5656 up a secondary struct to be attached to this
5657 fd, we will use this to cache error messages etc. */
5659 if((ssize_t)tcount > nwritten) {
5660 write_bmpx_struct *wbms;
5661 if(fsp->wbmpx_ptr != NULL)
5662 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5663 else
5664 wbms = SMB_MALLOC_P(write_bmpx_struct);
5665 if(!wbms) {
5666 DEBUG(0,("Out of memory in reply_readmpx\n"));
5667 END_PROFILE(SMBwriteBmpx);
5668 return(ERROR_DOS(ERRSRV,ERRnoresource));
5670 wbms->wr_mode = write_through;
5671 wbms->wr_discard = False; /* No errors yet */
5672 wbms->wr_total_written = nwritten;
5673 wbms->wr_errclass = 0;
5674 wbms->wr_error = 0;
5675 fsp->wbmpx_ptr = wbms;
5678 /* We are returning successfully, set the message type back to
5679 SMBwritebmpx */
5680 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5682 outsize = set_message(outbuf,1,0,True);
5684 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5686 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5687 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5689 if (write_through && tcount==nwritten) {
5690 /* We need to send both a primary and a secondary response */
5691 smb_setlen(outbuf,outsize - 4);
5692 show_msg(outbuf);
5693 if (!send_smb(smbd_server_fd(),outbuf))
5694 exit_server("reply_writebmpx: send_smb failed.");
5696 /* Now the secondary */
5697 outsize = set_message(outbuf,1,0,True);
5698 SCVAL(outbuf,smb_com,SMBwritec);
5699 SSVAL(outbuf,smb_vwv0,nwritten);
5702 END_PROFILE(SMBwriteBmpx);
5703 return(outsize);
5706 /****************************************************************************
5707 Reply to a SMBwritebs (write block multiplex secondary) request.
5708 ****************************************************************************/
5710 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5712 size_t numtowrite;
5713 ssize_t nwritten = -1;
5714 int outsize = 0;
5715 SMB_OFF_T startpos;
5716 size_t tcount;
5717 BOOL write_through;
5718 int smb_doff;
5719 char *data;
5720 write_bmpx_struct *wbms;
5721 BOOL send_response = False;
5722 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5723 START_PROFILE(SMBwriteBs);
5725 CHECK_FSP(fsp,conn);
5726 if (!CHECK_WRITE(fsp)) {
5727 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5730 tcount = SVAL(inbuf,smb_vwv1);
5731 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5732 numtowrite = SVAL(inbuf,smb_vwv6);
5733 smb_doff = SVAL(inbuf,smb_vwv7);
5735 data = smb_base(inbuf) + smb_doff;
5737 /* We need to send an SMBwriteC response, not an SMBwritebs */
5738 SCVAL(outbuf,smb_com,SMBwritec);
5740 /* This fd should have an auxiliary struct attached,
5741 check that it does */
5742 wbms = fsp->wbmpx_ptr;
5743 if(!wbms) {
5744 END_PROFILE(SMBwriteBs);
5745 return(-1);
5748 /* If write through is set we can return errors, else we must cache them */
5749 write_through = wbms->wr_mode;
5751 /* Check for an earlier error */
5752 if(wbms->wr_discard) {
5753 END_PROFILE(SMBwriteBs);
5754 return -1; /* Just discard the packet */
5757 nwritten = write_file(fsp,data,startpos,numtowrite);
5759 sync_file(conn, fsp, write_through);
5761 if (nwritten < (ssize_t)numtowrite) {
5762 if(write_through) {
5763 /* We are returning an error - we can delete the aux struct */
5764 if (wbms)
5765 free((char *)wbms);
5766 fsp->wbmpx_ptr = NULL;
5767 END_PROFILE(SMBwriteBs);
5768 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5770 wbms->wr_errclass = ERRHRD;
5771 wbms->wr_error = ERRdiskfull;
5772 wbms->wr_status = NT_STATUS_DISK_FULL;
5773 wbms->wr_discard = True;
5774 END_PROFILE(SMBwriteBs);
5775 return -1;
5778 /* Increment the total written, if this matches tcount
5779 we can discard the auxiliary struct (hurrah !) and return a writeC */
5780 wbms->wr_total_written += nwritten;
5781 if(wbms->wr_total_written >= tcount) {
5782 if (write_through) {
5783 outsize = set_message(outbuf,1,0,True);
5784 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5785 send_response = True;
5788 free((char *)wbms);
5789 fsp->wbmpx_ptr = NULL;
5792 if(send_response) {
5793 END_PROFILE(SMBwriteBs);
5794 return(outsize);
5797 END_PROFILE(SMBwriteBs);
5798 return(-1);
5801 /****************************************************************************
5802 Reply to a SMBgetattrE.
5803 ****************************************************************************/
5805 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5807 SMB_STRUCT_STAT sbuf;
5808 int outsize = 0;
5809 int mode;
5810 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5811 START_PROFILE(SMBgetattrE);
5813 outsize = set_message(outbuf,11,0,True);
5815 if(!fsp || (fsp->conn != conn)) {
5816 END_PROFILE(SMBgetattrE);
5817 return ERROR_DOS(ERRDOS,ERRbadfid);
5820 /* Do an fstat on this file */
5821 if(fsp_stat(fsp, &sbuf)) {
5822 END_PROFILE(SMBgetattrE);
5823 return(UNIXERROR(ERRDOS,ERRnoaccess));
5826 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5829 * Convert the times into dos times. Set create
5830 * date to be last modify date as UNIX doesn't save
5831 * this.
5834 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5835 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5836 /* Should we check pending modtime here ? JRA */
5837 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5839 if (mode & aDIR) {
5840 SIVAL(outbuf,smb_vwv6,0);
5841 SIVAL(outbuf,smb_vwv8,0);
5842 } else {
5843 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5844 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5845 SIVAL(outbuf,smb_vwv8,allocation_size);
5847 SSVAL(outbuf,smb_vwv10, mode);
5849 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5851 END_PROFILE(SMBgetattrE);
5852 return(outsize);