2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
28 /* look in server.c for some explanation of these variables */
29 extern enum protocol_types Protocol;
31 unsigned int smb_echo_count = 0;
32 extern uint32 global_client_caps;
34 extern struct current_user current_user;
35 extern BOOL global_encrypted_passwords_negotiated;
37 /****************************************************************************
38 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
39 path or anything including wildcards.
40 We're assuming here that '/' is not the second byte in any multibyte char
41 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
43 ****************************************************************************/
45 /* Custom version for processing POSIX paths. */
46 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
48 static NTSTATUS check_path_syntax_internal(char *path,
50 BOOL *p_last_component_contains_wcard)
54 NTSTATUS ret = NT_STATUS_OK;
55 BOOL start_of_name_component = True;
57 *p_last_component_contains_wcard = False;
60 if (IS_PATH_SEP(*s,posix_path)) {
62 * Safe to assume is not the second part of a mb char
63 * as this is handled below.
65 /* Eat multiple '/' or '\\' */
66 while (IS_PATH_SEP(*s,posix_path)) {
69 if ((d != path) && (*s != '\0')) {
70 /* We only care about non-leading or trailing '/' or '\\' */
74 start_of_name_component = True;
76 *p_last_component_contains_wcard = False;
80 if (start_of_name_component) {
81 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
82 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
85 * No mb char starts with '.' so we're safe checking the directory separator here.
88 /* If we just added a '/' - delete it */
89 if ((d > path) && (*(d-1) == '/')) {
94 /* Are we at the start ? Can't go back further if so. */
96 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
99 /* Go back one level... */
100 /* We know this is safe as '/' cannot be part of a mb sequence. */
101 /* NOTE - if this assumption is invalid we are not in good shape... */
102 /* Decrement d first as d points to the *next* char to write into. */
103 for (d--; d > path; d--) {
107 s += 2; /* Else go past the .. */
108 /* We're still at the start of a name component, just the previous one. */
111 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
124 return NT_STATUS_OBJECT_NAME_INVALID;
132 *p_last_component_contains_wcard = True;
141 /* Get the size of the next MB character. */
142 next_codepoint(s,&siz);
160 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
162 return NT_STATUS_INVALID_PARAMETER;
165 start_of_name_component = False;
172 /****************************************************************************
173 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
174 No wildcards allowed.
175 ****************************************************************************/
177 NTSTATUS check_path_syntax(char *path)
180 return check_path_syntax_internal(path, False, &ignore);
183 /****************************************************************************
184 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
185 Wildcards allowed - p_contains_wcard returns true if the last component contained
187 ****************************************************************************/
189 NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
191 return check_path_syntax_internal(path, False, p_contains_wcard);
194 /****************************************************************************
195 Check the path for a POSIX client.
196 We're assuming here that '/' is not the second byte in any multibyte char
197 set (a safe assumption).
198 ****************************************************************************/
200 NTSTATUS check_path_syntax_posix(char *path)
203 return check_path_syntax_internal(path, True, &ignore);
206 /****************************************************************************
207 Pull a string and check the path allowing a wilcard - provide for error return.
208 ****************************************************************************/
210 size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest,
211 const char *src, size_t dest_len, size_t src_len,
212 int flags, NTSTATUS *err, BOOL *contains_wcard)
216 SMB_ASSERT(dest_len == sizeof(pstring));
220 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
223 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
224 dest_len, src_len, flags);
227 *contains_wcard = False;
229 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
231 * For a DFS path the function parse_dfs_path()
232 * will do the path processing, just make a copy.
238 if (lp_posix_pathnames()) {
239 *err = check_path_syntax_posix(dest);
241 *err = check_path_syntax_wcard(dest, contains_wcard);
247 /****************************************************************************
248 Pull a string and check the path - provide for error return.
249 ****************************************************************************/
251 size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest,
252 const char *src, size_t dest_len, size_t src_len,
253 int flags, NTSTATUS *err)
257 SMB_ASSERT(dest_len == sizeof(pstring));
261 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
264 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
265 dest_len, src_len, flags);
268 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
270 * For a DFS path the function parse_dfs_path()
271 * will do the path processing, just make a copy.
277 if (lp_posix_pathnames()) {
278 *err = check_path_syntax_posix(dest);
280 *err = check_path_syntax(dest);
286 /****************************************************************************
287 Reply to a (netbios-level) special message.
288 ****************************************************************************/
290 void reply_special(char *inbuf)
292 int msg_type = CVAL(inbuf,0);
293 int msg_flags = CVAL(inbuf,1);
298 * We only really use 4 bytes of the outbuf, but for the smb_setlen
299 * calculation & friends (send_smb uses that) we need the full smb
302 char outbuf[smb_size];
304 static BOOL already_got_session = False;
308 memset(outbuf, '\0', sizeof(outbuf));
310 smb_setlen(inbuf,outbuf,0);
313 case 0x81: /* session request */
315 if (already_got_session) {
316 exit_server_cleanly("multiple session request not permitted");
319 SCVAL(outbuf,0,0x82);
321 if (name_len(inbuf+4) > 50 ||
322 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
323 DEBUG(0,("Invalid name length in session request\n"));
326 name_extract(inbuf,4,name1);
327 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
328 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
331 set_local_machine_name(name1, True);
332 set_remote_machine_name(name2, True);
334 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
335 get_local_machine_name(), get_remote_machine_name(),
338 if (name_type == 'R') {
339 /* We are being asked for a pathworks session ---
341 SCVAL(outbuf, 0,0x83);
345 /* only add the client's machine name to the list
346 of possibly valid usernames if we are operating
347 in share mode security */
348 if (lp_security() == SEC_SHARE) {
349 add_session_user(get_remote_machine_name());
352 reload_services(True);
355 already_got_session = True;
358 case 0x89: /* session keepalive request
359 (some old clients produce this?) */
360 SCVAL(outbuf,0,SMBkeepalive);
364 case 0x82: /* positive session response */
365 case 0x83: /* negative session response */
366 case 0x84: /* retarget session response */
367 DEBUG(0,("Unexpected session response\n"));
370 case SMBkeepalive: /* session keepalive */
375 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
376 msg_type, msg_flags));
378 send_smb(smbd_server_fd(), outbuf);
382 /****************************************************************************
384 conn POINTER CAN BE NULL HERE !
385 ****************************************************************************/
387 int reply_tcon(connection_struct *conn,
388 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
392 char *service_buf = NULL;
393 char *password = NULL;
396 uint16 vuid = SVAL(inbuf,smb_uid);
400 DATA_BLOB password_blob;
402 START_PROFILE(SMBtcon);
404 ctx = talloc_init("reply_tcon");
406 END_PROFILE(SMBtcon);
407 return ERROR_NT(NT_STATUS_NO_MEMORY);
410 p = smb_buf(inbuf)+1;
411 p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
412 &service_buf, p, STR_TERMINATE) + 1;
413 pwlen = srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
414 &password, p, STR_TERMINATE) + 1;
416 p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
417 &dev, p, STR_TERMINATE) + 1;
419 if (service_buf == NULL || password == NULL || dev == NULL) {
421 END_PROFILE(SMBtcon);
422 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
424 p = strrchr_m(service_buf,'\\');
428 service = service_buf;
431 password_blob = data_blob(password, pwlen+1);
433 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
435 data_blob_clear_free(&password_blob);
439 END_PROFILE(SMBtcon);
440 return ERROR_NT(nt_status);
443 outsize = set_message(inbuf,outbuf,2,0,True);
444 SSVAL(outbuf,smb_vwv0,max_recv);
445 SSVAL(outbuf,smb_vwv1,conn->cnum);
446 SSVAL(outbuf,smb_tid,conn->cnum);
448 DEBUG(3,("tcon service=%s cnum=%d\n",
449 service, conn->cnum));
451 END_PROFILE(SMBtcon);
456 /****************************************************************************
457 Reply to a tcon and X.
458 conn POINTER CAN BE NULL HERE !
459 ****************************************************************************/
461 void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
463 char *service = NULL;
466 TALLOC_CTX *ctx = NULL;
467 /* what the cleint thinks the device is */
468 char *client_devicetype = NULL;
469 /* what the server tells the client the share represents */
470 const char *server_devicetype;
477 START_PROFILE(SMBtconX);
480 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
481 END_PROFILE(SMBtconX);
485 passlen = SVAL(req->inbuf,smb_vwv3);
486 tcon_flags = SVAL(req->inbuf,smb_vwv2);
488 /* we might have to close an old one */
489 if ((tcon_flags & 0x1) && conn) {
490 close_cnum(conn,req->vuid);
493 if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
494 reply_doserror(req, ERRDOS, ERRbuftoosmall);
495 END_PROFILE(SMBtconX);
499 if (global_encrypted_passwords_negotiated) {
500 password = data_blob(smb_buf(req->inbuf),passlen);
501 if (lp_security() == SEC_SHARE) {
503 * Security = share always has a pad byte
504 * after the password.
506 p = smb_buf(req->inbuf) + passlen + 1;
508 p = smb_buf(req->inbuf) + passlen;
511 password = data_blob(smb_buf(req->inbuf),passlen+1);
512 /* Ensure correct termination */
513 password.data[passlen]=0;
514 p = smb_buf(req->inbuf) + passlen + 1;
517 ctx = talloc_init("reply_tcon_and_X");
519 data_blob_clear_free(&password);
520 reply_nterror(req, NT_STATUS_NO_MEMORY);
521 END_PROFILE(SMBtconX);
524 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
528 data_blob_clear_free(&password);
530 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
531 END_PROFILE(SMBtconX);
536 * the service name can be either: \\server\share
537 * or share directly like on the DELL PowerVault 705
540 q = strchr_m(path+2,'\\');
542 data_blob_clear_free(&password);
544 reply_doserror(req, ERRDOS, ERRnosuchshare);
545 END_PROFILE(SMBtconX);
553 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
554 &client_devicetype, p,
555 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
557 if (client_devicetype == NULL) {
558 data_blob_clear_free(&password);
560 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
561 END_PROFILE(SMBtconX);
565 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
567 conn = make_connection(service, password, client_devicetype,
568 req->vuid, &nt_status);
570 data_blob_clear_free(&password);
574 reply_nterror(req, nt_status);
575 END_PROFILE(SMBtconX);
580 server_devicetype = "IPC";
581 else if ( IS_PRINT(conn) )
582 server_devicetype = "LPT1:";
584 server_devicetype = "A:";
586 if (Protocol < PROTOCOL_NT1) {
587 reply_outbuf(req, 2, 0);
588 if (message_push_string(&req->outbuf, server_devicetype,
589 STR_TERMINATE|STR_ASCII) == -1) {
591 reply_nterror(req, NT_STATUS_NO_MEMORY);
592 END_PROFILE(SMBtconX);
596 /* NT sets the fstype of IPC$ to the null string */
597 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
599 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
600 /* Return permissions. */
604 reply_outbuf(req, 7, 0);
607 perm1 = FILE_ALL_ACCESS;
608 perm2 = FILE_ALL_ACCESS;
610 perm1 = CAN_WRITE(conn) ?
615 SIVAL(req->outbuf, smb_vwv3, perm1);
616 SIVAL(req->outbuf, smb_vwv5, perm2);
618 reply_outbuf(req, 3, 0);
621 if ((message_push_string(&req->outbuf, server_devicetype,
622 STR_TERMINATE|STR_ASCII) == -1)
623 || (message_push_string(&req->outbuf, fstype,
624 STR_TERMINATE) == -1)) {
626 reply_nterror(req, NT_STATUS_NO_MEMORY);
627 END_PROFILE(SMBtconX);
631 /* what does setting this bit do? It is set by NT4 and
632 may affect the ability to autorun mounted cdroms */
633 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
634 (lp_csc_policy(SNUM(conn)) << 2));
636 init_dfsroot(conn, req->inbuf, req->outbuf);
640 DEBUG(3,("tconX service=%s \n",
643 /* set the incoming and outgoing tid to the just created one */
644 SSVAL(req->inbuf,smb_tid,conn->cnum);
645 SSVAL(req->outbuf,smb_tid,conn->cnum);
648 END_PROFILE(SMBtconX);
650 chain_reply_new(req);
654 /****************************************************************************
655 Reply to an unknown type.
656 ****************************************************************************/
658 int reply_unknown(char *inbuf,char *outbuf)
661 type = CVAL(inbuf,smb_com);
663 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
664 smb_fn_name(type), type, type));
666 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
669 void reply_unknown_new(struct smb_request *req, uint8 type)
671 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
672 smb_fn_name(type), type, type));
673 reply_doserror(req, ERRSRV, ERRunknownsmb);
677 /****************************************************************************
679 conn POINTER CAN BE NULL HERE !
680 ****************************************************************************/
682 int reply_ioctl(connection_struct *conn,
683 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
685 uint16 device = SVAL(inbuf,smb_vwv1);
686 uint16 function = SVAL(inbuf,smb_vwv2);
687 uint32 ioctl_code = (device << 16) + function;
688 int replysize, outsize;
690 START_PROFILE(SMBioctl);
692 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
694 switch (ioctl_code) {
695 case IOCTL_QUERY_JOB_INFO:
699 END_PROFILE(SMBioctl);
700 return(ERROR_DOS(ERRSRV,ERRnosupport));
703 outsize = set_message(inbuf,outbuf,8,replysize+1,True);
704 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
705 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
706 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
707 p = smb_buf(outbuf) + 1; /* Allow for alignment */
709 switch (ioctl_code) {
710 case IOCTL_QUERY_JOB_INFO:
712 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
714 END_PROFILE(SMBioctl);
715 return(UNIXERROR(ERRDOS,ERRbadfid));
717 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
718 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
720 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
726 END_PROFILE(SMBioctl);
730 /****************************************************************************
731 Strange checkpath NTSTATUS mapping.
732 ****************************************************************************/
734 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
736 /* Strange DOS error code semantics only for checkpath... */
737 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
738 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
739 /* We need to map to ERRbadpath */
740 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
746 /****************************************************************************
747 Reply to a checkpath.
748 ****************************************************************************/
750 void reply_checkpath(connection_struct *conn, struct smb_request *req)
753 SMB_STRUCT_STAT sbuf;
756 START_PROFILE(SMBcheckpath);
758 srvstr_get_path((char *)req->inbuf, req->flags2, name,
759 smb_buf(req->inbuf) + 1, sizeof(name), 0,
760 STR_TERMINATE, &status);
761 if (!NT_STATUS_IS_OK(status)) {
762 status = map_checkpath_error((char *)req->inbuf, status);
763 reply_nterror(req, status);
764 END_PROFILE(SMBcheckpath);
768 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name);
769 if (!NT_STATUS_IS_OK(status)) {
770 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
771 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
773 END_PROFILE(SMBcheckpath);
779 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
781 status = unix_convert(conn, name, False, NULL, &sbuf);
782 if (!NT_STATUS_IS_OK(status)) {
786 status = check_name(conn, name);
787 if (!NT_STATUS_IS_OK(status)) {
788 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
792 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
793 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
794 status = map_nt_error_from_unix(errno);
798 if (!S_ISDIR(sbuf.st_mode)) {
799 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
801 END_PROFILE(SMBcheckpath);
805 reply_outbuf(req, 0, 0);
807 END_PROFILE(SMBcheckpath);
812 END_PROFILE(SMBcheckpath);
814 /* We special case this - as when a Windows machine
815 is parsing a path is steps through the components
816 one at a time - if a component fails it expects
817 ERRbadpath, not ERRbadfile.
819 status = map_checkpath_error((char *)req->inbuf, status);
820 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
822 * Windows returns different error codes if
823 * the parent directory is valid but not the
824 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
825 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
826 * if the path is invalid.
828 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
833 reply_nterror(req, status);
836 /****************************************************************************
838 ****************************************************************************/
840 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
844 SMB_STRUCT_STAT sbuf;
851 START_PROFILE(SMBgetatr);
853 p = smb_buf(inbuf) + 1;
854 p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
855 sizeof(fname), 0, STR_TERMINATE, &status);
856 if (!NT_STATUS_IS_OK(status)) {
857 END_PROFILE(SMBgetatr);
858 return ERROR_NT(status);
861 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
862 if (!NT_STATUS_IS_OK(status)) {
863 END_PROFILE(SMBgetatr);
864 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
865 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
867 return ERROR_NT(status);
870 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
871 under WfWg - weird! */
872 if (*fname == '\0') {
873 mode = aHIDDEN | aDIR;
874 if (!CAN_WRITE(conn)) {
880 status = unix_convert(conn, fname, False, NULL,&sbuf);
881 if (!NT_STATUS_IS_OK(status)) {
882 END_PROFILE(SMBgetatr);
883 return ERROR_NT(status);
885 status = check_name(conn, fname);
886 if (!NT_STATUS_IS_OK(status)) {
887 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
888 END_PROFILE(SMBgetatr);
889 return ERROR_NT(status);
891 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
892 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
893 return UNIXERROR(ERRDOS,ERRbadfile);
896 mode = dos_mode(conn,fname,&sbuf);
898 mtime = sbuf.st_mtime;
904 outsize = set_message(inbuf,outbuf,10,0,True);
906 SSVAL(outbuf,smb_vwv0,mode);
907 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
908 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
910 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
912 SIVAL(outbuf,smb_vwv3,(uint32)size);
914 if (Protocol >= PROTOCOL_NT1) {
915 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
918 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
920 END_PROFILE(SMBgetatr);
924 /****************************************************************************
926 ****************************************************************************/
928 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
934 SMB_STRUCT_STAT sbuf;
938 START_PROFILE(SMBsetatr);
940 p = smb_buf(inbuf) + 1;
941 p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
942 sizeof(fname), 0, STR_TERMINATE, &status);
943 if (!NT_STATUS_IS_OK(status)) {
944 END_PROFILE(SMBsetatr);
945 return ERROR_NT(status);
948 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
949 if (!NT_STATUS_IS_OK(status)) {
950 END_PROFILE(SMBsetatr);
951 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
952 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
954 return ERROR_NT(status);
957 status = unix_convert(conn, fname, False, NULL, &sbuf);
958 if (!NT_STATUS_IS_OK(status)) {
959 END_PROFILE(SMBsetatr);
960 return ERROR_NT(status);
963 status = check_name(conn, fname);
964 if (!NT_STATUS_IS_OK(status)) {
965 END_PROFILE(SMBsetatr);
966 return ERROR_NT(status);
969 if (fname[0] == '.' && fname[1] == '\0') {
971 * Not sure here is the right place to catch this
972 * condition. Might be moved to somewhere else later -- vl
974 END_PROFILE(SMBsetatr);
975 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
978 mode = SVAL(inbuf,smb_vwv0);
979 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
981 if (mode != FILE_ATTRIBUTE_NORMAL) {
982 if (VALID_STAT_OF_DIR(sbuf))
987 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
988 END_PROFILE(SMBsetatr);
989 return UNIXERROR(ERRDOS, ERRnoaccess);
993 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
994 END_PROFILE(SMBsetatr);
995 return UNIXERROR(ERRDOS, ERRnoaccess);
998 outsize = set_message(inbuf,outbuf,0,0,False);
1000 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1002 END_PROFILE(SMBsetatr);
1006 /****************************************************************************
1008 ****************************************************************************/
1010 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1013 SMB_BIG_UINT dfree,dsize,bsize;
1014 START_PROFILE(SMBdskattr);
1016 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1017 END_PROFILE(SMBdskattr);
1018 return(UNIXERROR(ERRHRD,ERRgeneral));
1021 outsize = set_message(inbuf,outbuf,5,0,True);
1023 if (Protocol <= PROTOCOL_LANMAN2) {
1024 double total_space, free_space;
1025 /* we need to scale this to a number that DOS6 can handle. We
1026 use floating point so we can handle large drives on systems
1027 that don't have 64 bit integers
1029 we end up displaying a maximum of 2G to DOS systems
1031 total_space = dsize * (double)bsize;
1032 free_space = dfree * (double)bsize;
1034 dsize = (total_space+63*512) / (64*512);
1035 dfree = (free_space+63*512) / (64*512);
1037 if (dsize > 0xFFFF) dsize = 0xFFFF;
1038 if (dfree > 0xFFFF) dfree = 0xFFFF;
1040 SSVAL(outbuf,smb_vwv0,dsize);
1041 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1042 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
1043 SSVAL(outbuf,smb_vwv3,dfree);
1045 SSVAL(outbuf,smb_vwv0,dsize);
1046 SSVAL(outbuf,smb_vwv1,bsize/512);
1047 SSVAL(outbuf,smb_vwv2,512);
1048 SSVAL(outbuf,smb_vwv3,dfree);
1051 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1053 END_PROFILE(SMBdskattr);
1057 /****************************************************************************
1059 Can be called from SMBsearch, SMBffirst or SMBfunique.
1060 ****************************************************************************/
1062 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1072 unsigned int numentries = 0;
1073 unsigned int maxentries = 0;
1074 BOOL finished = False;
1080 BOOL check_descend = False;
1081 BOOL expect_close = False;
1083 BOOL mask_contains_wcard = False;
1084 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1086 START_PROFILE(SMBsearch);
1088 if (lp_posix_pathnames()) {
1089 END_PROFILE(SMBsearch);
1090 return reply_unknown(inbuf, outbuf);
1093 *mask = *directory = *fname = 0;
1095 /* If we were called as SMBffirst then we must expect close. */
1096 if(CVAL(inbuf,smb_com) == SMBffirst) {
1097 expect_close = True;
1100 outsize = set_message(inbuf,outbuf,1,3,True);
1101 maxentries = SVAL(inbuf,smb_vwv0);
1102 dirtype = SVAL(inbuf,smb_vwv1);
1103 p = smb_buf(inbuf) + 1;
1104 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1105 sizeof(path), 0, STR_TERMINATE, &nt_status,
1106 &mask_contains_wcard);
1107 if (!NT_STATUS_IS_OK(nt_status)) {
1108 END_PROFILE(SMBsearch);
1109 return ERROR_NT(nt_status);
1112 nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
1113 if (!NT_STATUS_IS_OK(nt_status)) {
1114 END_PROFILE(SMBsearch);
1115 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1116 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1118 return ERROR_NT(nt_status);
1122 status_len = SVAL(p, 0);
1125 /* dirtype &= ~aDIR; */
1127 if (status_len == 0) {
1128 SMB_STRUCT_STAT sbuf;
1130 pstrcpy(directory,path);
1131 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1132 if (!NT_STATUS_IS_OK(nt_status)) {
1133 END_PROFILE(SMBsearch);
1134 return ERROR_NT(nt_status);
1137 nt_status = check_name(conn, directory);
1138 if (!NT_STATUS_IS_OK(nt_status)) {
1139 END_PROFILE(SMBsearch);
1140 return ERROR_NT(nt_status);
1143 p = strrchr_m(directory,'/');
1145 pstrcpy(mask,directory);
1146 pstrcpy(directory,".");
1152 if (*directory == '\0') {
1153 pstrcpy(directory,".");
1155 memset((char *)status,'\0',21);
1156 SCVAL(status,0,(dirtype & 0x1F));
1160 memcpy(status,p,21);
1161 status_dirtype = CVAL(status,0) & 0x1F;
1162 if (status_dirtype != (dirtype & 0x1F)) {
1163 dirtype = status_dirtype;
1166 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1167 if (!conn->dirptr) {
1170 string_set(&conn->dirpath,dptr_path(dptr_num));
1171 pstrcpy(mask, dptr_wcard(dptr_num));
1173 * For a 'continue' search we have no string. So
1174 * check from the initial saved string.
1176 mask_contains_wcard = ms_has_wild(mask);
1179 p = smb_buf(outbuf) + 3;
1181 if (status_len == 0) {
1182 nt_status = dptr_create(conn,
1186 SVAL(inbuf,smb_pid),
1188 mask_contains_wcard,
1191 if (!NT_STATUS_IS_OK(nt_status)) {
1192 return ERROR_NT(nt_status);
1194 dptr_num = dptr_dnum(conn->dirptr);
1196 dirtype = dptr_attr(dptr_num);
1199 DEBUG(4,("dptr_num is %d\n",dptr_num));
1201 if ((dirtype&0x1F) == aVOLID) {
1202 memcpy(p,status,21);
1203 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1204 0,aVOLID,0,!allow_long_path_components);
1205 dptr_fill(p+12,dptr_num);
1206 if (dptr_zero(p+12) && (status_len==0)) {
1211 p += DIR_STRUCT_SIZE;
1214 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1216 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1217 conn->dirpath,lp_dontdescend(SNUM(conn))));
1218 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1219 check_descend = True;
1222 for (i=numentries;(i<maxentries) && !finished;i++) {
1223 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1225 memcpy(p,status,21);
1226 make_dir_struct(p,mask,fname,size, mode,date,
1227 !allow_long_path_components);
1228 if (!dptr_fill(p+12,dptr_num)) {
1232 p += DIR_STRUCT_SIZE;
1239 /* If we were called as SMBffirst with smb_search_id == NULL
1240 and no entries were found then return error and close dirptr
1243 if (numentries == 0) {
1244 dptr_close(&dptr_num);
1245 } else if(expect_close && status_len == 0) {
1246 /* Close the dptr - we know it's gone */
1247 dptr_close(&dptr_num);
1250 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1251 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1252 dptr_close(&dptr_num);
1255 if ((numentries == 0) && !mask_contains_wcard) {
1256 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1259 SSVAL(outbuf,smb_vwv0,numentries);
1260 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1261 SCVAL(smb_buf(outbuf),0,5);
1262 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1264 /* The replies here are never long name. */
1265 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1266 if (!allow_long_path_components) {
1267 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1270 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1271 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1273 outsize += DIR_STRUCT_SIZE*numentries;
1274 smb_setlen(inbuf,outbuf,outsize - 4);
1276 if ((! *directory) && dptr_path(dptr_num))
1277 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1279 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1280 smb_fn_name(CVAL(inbuf,smb_com)),
1281 mask, directory, dirtype, numentries, maxentries ) );
1283 END_PROFILE(SMBsearch);
1287 /****************************************************************************
1288 Reply to a fclose (stop directory search).
1289 ****************************************************************************/
1291 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1300 BOOL path_contains_wcard = False;
1302 START_PROFILE(SMBfclose);
1304 if (lp_posix_pathnames()) {
1305 END_PROFILE(SMBfclose);
1306 return reply_unknown(inbuf, outbuf);
1309 outsize = set_message(inbuf,outbuf,1,0,True);
1310 p = smb_buf(inbuf) + 1;
1311 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1312 sizeof(path), 0, STR_TERMINATE, &err,
1313 &path_contains_wcard);
1314 if (!NT_STATUS_IS_OK(err)) {
1315 END_PROFILE(SMBfclose);
1316 return ERROR_NT(err);
1319 status_len = SVAL(p,0);
1322 if (status_len == 0) {
1323 END_PROFILE(SMBfclose);
1324 return ERROR_DOS(ERRSRV,ERRsrverror);
1327 memcpy(status,p,21);
1329 if(dptr_fetch(status+12,&dptr_num)) {
1330 /* Close the dptr - we know it's gone */
1331 dptr_close(&dptr_num);
1334 SSVAL(outbuf,smb_vwv0,0);
1336 DEBUG(3,("search close\n"));
1338 END_PROFILE(SMBfclose);
1342 /****************************************************************************
1344 ****************************************************************************/
1346 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1354 SMB_STRUCT_STAT sbuf;
1356 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1358 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1361 uint32 create_disposition;
1362 uint32 create_options = 0;
1364 struct smb_request req;
1366 START_PROFILE(SMBopen);
1368 init_smb_request(&req, (uint8 *)inbuf);
1370 deny_mode = SVAL(inbuf,smb_vwv0);
1372 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1373 sizeof(fname), 0, STR_TERMINATE, &status);
1374 if (!NT_STATUS_IS_OK(status)) {
1375 END_PROFILE(SMBopen);
1376 return ERROR_NT(status);
1379 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1380 if (!NT_STATUS_IS_OK(status)) {
1381 END_PROFILE(SMBopen);
1382 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1383 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1385 return ERROR_NT(status);
1388 status = unix_convert(conn, fname, False, NULL, &sbuf);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 END_PROFILE(SMBopen);
1391 return ERROR_NT(status);
1394 status = check_name(conn, fname);
1395 if (!NT_STATUS_IS_OK(status)) {
1396 END_PROFILE(SMBopen);
1397 return ERROR_NT(status);
1400 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1401 &access_mask, &share_mode, &create_disposition, &create_options)) {
1402 END_PROFILE(SMBopen);
1403 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1406 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1415 if (!NT_STATUS_IS_OK(status)) {
1416 END_PROFILE(SMBopen);
1417 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1418 /* We have re-scheduled this call. */
1421 return ERROR_NT(status);
1424 size = sbuf.st_size;
1425 fattr = dos_mode(conn,fname,&sbuf);
1426 mtime = sbuf.st_mtime;
1429 DEBUG(3,("attempt to open a directory %s\n",fname));
1430 close_file(fsp,ERROR_CLOSE);
1431 END_PROFILE(SMBopen);
1432 return ERROR_DOS(ERRDOS,ERRnoaccess);
1435 outsize = set_message(inbuf,outbuf,7,0,True);
1436 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1437 SSVAL(outbuf,smb_vwv1,fattr);
1438 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1439 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1441 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1443 SIVAL(outbuf,smb_vwv4,(uint32)size);
1444 SSVAL(outbuf,smb_vwv6,deny_mode);
1446 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1447 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1450 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1451 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1453 END_PROFILE(SMBopen);
1457 /****************************************************************************
1458 Reply to an open and X.
1459 ****************************************************************************/
1461 void reply_open_and_X(connection_struct *conn, struct smb_request *req)
1467 /* Breakout the oplock request bits so we can set the
1468 reply bits separately. */
1469 int ex_oplock_request;
1470 int core_oplock_request;
1473 int smb_sattr = SVAL(req->inbuf,smb_vwv4);
1474 uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
1479 SMB_STRUCT_STAT sbuf;
1483 SMB_BIG_UINT allocation_size;
1484 ssize_t retval = -1;
1487 uint32 create_disposition;
1488 uint32 create_options = 0;
1490 START_PROFILE(SMBopenX);
1492 if (req->wct < 15) {
1493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1494 END_PROFILE(SMBopenX);
1498 open_flags = SVAL(req->inbuf,smb_vwv2);
1499 deny_mode = SVAL(req->inbuf,smb_vwv3);
1500 smb_attr = SVAL(req->inbuf,smb_vwv5);
1501 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1502 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1503 oplock_request = ex_oplock_request | core_oplock_request;
1504 smb_ofun = SVAL(req->inbuf,smb_vwv8);
1505 allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
1507 /* If it's an IPC, pass off the pipe handler. */
1509 if (lp_nt_pipe_support()) {
1510 reply_open_pipe_and_X(conn, req);
1512 reply_doserror(req, ERRSRV, ERRaccess);
1514 END_PROFILE(SMBopenX);
1518 /* XXXX we need to handle passed times, sattr and flags */
1519 srvstr_get_path((char *)req->inbuf, req->flags2, fname,
1520 smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE,
1522 if (!NT_STATUS_IS_OK(status)) {
1523 reply_nterror(req, status);
1524 END_PROFILE(SMBopenX);
1528 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1530 if (!NT_STATUS_IS_OK(status)) {
1531 END_PROFILE(SMBopenX);
1532 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1533 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1534 ERRSRV, ERRbadpath);
1537 reply_nterror(req, status);
1541 status = unix_convert(conn, fname, False, NULL, &sbuf);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 reply_nterror(req, status);
1544 END_PROFILE(SMBopenX);
1548 status = check_name(conn, fname);
1549 if (!NT_STATUS_IS_OK(status)) {
1550 reply_nterror(req, status);
1551 END_PROFILE(SMBopenX);
1555 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1558 &create_disposition,
1560 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1561 END_PROFILE(SMBopenX);
1565 status = open_file_ntcreate(conn, req, fname, &sbuf,
1574 if (!NT_STATUS_IS_OK(status)) {
1575 END_PROFILE(SMBopenX);
1576 if (open_was_deferred(req->mid)) {
1577 /* We have re-scheduled this call. */
1580 reply_nterror(req, status);
1584 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1585 if the file is truncated or created. */
1586 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1587 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1588 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1589 close_file(fsp,ERROR_CLOSE);
1590 reply_nterror(req, NT_STATUS_DISK_FULL);
1591 END_PROFILE(SMBopenX);
1594 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1596 close_file(fsp,ERROR_CLOSE);
1597 reply_nterror(req, NT_STATUS_DISK_FULL);
1598 END_PROFILE(SMBopenX);
1601 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1604 fattr = dos_mode(conn,fname,&sbuf);
1605 mtime = sbuf.st_mtime;
1607 close_file(fsp,ERROR_CLOSE);
1608 reply_doserror(req, ERRDOS, ERRnoaccess);
1609 END_PROFILE(SMBopenX);
1613 /* If the caller set the extended oplock request bit
1614 and we granted one (by whatever means) - set the
1615 correct bit for extended oplock reply.
1618 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1619 smb_action |= EXTENDED_OPLOCK_GRANTED;
1622 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1623 smb_action |= EXTENDED_OPLOCK_GRANTED;
1626 /* If the caller set the core oplock request bit
1627 and we granted one (by whatever means) - set the
1628 correct bit for core oplock reply.
1631 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1632 reply_outbuf(req, 19, 0);
1634 reply_outbuf(req, 15, 0);
1637 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1638 SCVAL(req->outbuf, smb_flg,
1639 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1642 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1643 SCVAL(req->outbuf, smb_flg,
1644 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1647 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1648 SSVAL(req->outbuf,smb_vwv3,fattr);
1649 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1650 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1652 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1654 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1655 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1656 SSVAL(req->outbuf,smb_vwv11,smb_action);
1658 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1659 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1662 END_PROFILE(SMBopenX);
1663 chain_reply_new(req);
1667 /****************************************************************************
1668 Reply to a SMBulogoffX.
1669 conn POINTER CAN BE NULL HERE !
1670 ****************************************************************************/
1672 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1674 uint16 vuid = SVAL(inbuf,smb_uid);
1675 user_struct *vuser = get_valid_user_struct(vuid);
1676 START_PROFILE(SMBulogoffX);
1679 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1681 /* in user level security we are supposed to close any files
1682 open by this user */
1683 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1684 file_close_user(vuid);
1686 invalidate_vuid(vuid);
1688 set_message(inbuf,outbuf,2,0,True);
1690 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1692 END_PROFILE(SMBulogoffX);
1693 return chain_reply(inbuf,&outbuf,length,bufsize);
1696 /****************************************************************************
1697 Reply to a mknew or a create.
1698 ****************************************************************************/
1700 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1705 uint32 fattr = SVAL(inbuf,smb_vwv0);
1706 struct timespec ts[2];
1708 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1709 SMB_STRUCT_STAT sbuf;
1711 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1712 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1713 uint32 create_disposition;
1714 uint32 create_options = 0;
1715 struct smb_request req;
1717 START_PROFILE(SMBcreate);
1719 init_smb_request(&req, (uint8 *)inbuf);
1721 com = SVAL(inbuf,smb_com);
1723 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1725 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1,
1726 sizeof(fname), 0, STR_TERMINATE, &status);
1727 if (!NT_STATUS_IS_OK(status)) {
1728 END_PROFILE(SMBcreate);
1729 return ERROR_NT(status);
1732 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1733 if (!NT_STATUS_IS_OK(status)) {
1734 END_PROFILE(SMBcreate);
1735 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1736 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1738 return ERROR_NT(status);
1741 status = unix_convert(conn, fname, False, NULL, &sbuf);
1742 if (!NT_STATUS_IS_OK(status)) {
1743 END_PROFILE(SMBcreate);
1744 return ERROR_NT(status);
1747 status = check_name(conn, fname);
1748 if (!NT_STATUS_IS_OK(status)) {
1749 END_PROFILE(SMBcreate);
1750 return ERROR_NT(status);
1753 if (fattr & aVOLID) {
1754 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1757 if(com == SMBmknew) {
1758 /* We should fail if file exists. */
1759 create_disposition = FILE_CREATE;
1761 /* Create if file doesn't exist, truncate if it does. */
1762 create_disposition = FILE_OVERWRITE_IF;
1765 /* Open file using ntcreate. */
1766 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1775 if (!NT_STATUS_IS_OK(status)) {
1776 END_PROFILE(SMBcreate);
1777 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1778 /* We have re-scheduled this call. */
1781 return ERROR_NT(status);
1784 ts[0] = get_atimespec(&sbuf); /* atime. */
1785 file_ntimes(conn, fname, ts);
1787 outsize = set_message(inbuf,outbuf,1,0,True);
1788 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1790 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1791 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1794 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1795 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1798 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1799 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1801 END_PROFILE(SMBcreate);
1805 /****************************************************************************
1806 Reply to a create temporary file.
1807 ****************************************************************************/
1809 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1813 uint32 fattr = SVAL(inbuf,smb_vwv0);
1815 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1817 SMB_STRUCT_STAT sbuf;
1820 unsigned int namelen;
1821 struct smb_request req;
1823 START_PROFILE(SMBctemp);
1825 init_smb_request(&req, (uint8 *)inbuf);
1827 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1828 sizeof(fname), 0, STR_TERMINATE, &status);
1829 if (!NT_STATUS_IS_OK(status)) {
1830 END_PROFILE(SMBctemp);
1831 return ERROR_NT(status);
1834 pstrcat(fname,"/TMXXXXXX");
1836 pstrcat(fname,"TMXXXXXX");
1839 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1840 if (!NT_STATUS_IS_OK(status)) {
1841 END_PROFILE(SMBctemp);
1842 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1843 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1845 return ERROR_NT(status);
1848 status = unix_convert(conn, fname, False, NULL, &sbuf);
1849 if (!NT_STATUS_IS_OK(status)) {
1850 END_PROFILE(SMBctemp);
1851 return ERROR_NT(status);
1854 status = check_name(conn, fname);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 END_PROFILE(SMBctemp);
1857 return ERROR_NT(status);
1860 tmpfd = smb_mkstemp(fname);
1862 END_PROFILE(SMBctemp);
1863 return(UNIXERROR(ERRDOS,ERRnoaccess));
1866 SMB_VFS_STAT(conn,fname,&sbuf);
1868 /* We should fail if file does not exist. */
1869 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1870 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1871 FILE_SHARE_READ|FILE_SHARE_WRITE,
1878 /* close fd from smb_mkstemp() */
1881 if (!NT_STATUS_IS_OK(status)) {
1882 END_PROFILE(SMBctemp);
1883 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1884 /* We have re-scheduled this call. */
1887 return ERROR_NT(status);
1890 outsize = set_message(inbuf,outbuf,1,0,True);
1891 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1893 /* the returned filename is relative to the directory */
1894 s = strrchr_m(fname, '/');
1901 p = smb_buf(outbuf);
1903 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1904 thing in the byte section. JRA */
1905 SSVALS(p, 0, -1); /* what is this? not in spec */
1907 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1909 outsize = set_message_end(inbuf,outbuf, p);
1911 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1912 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1915 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1916 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1919 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1920 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1921 (unsigned int)sbuf.st_mode ) );
1923 END_PROFILE(SMBctemp);
1927 /*******************************************************************
1928 Check if a user is allowed to rename a file.
1929 ********************************************************************/
1931 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1932 uint16 dirtype, SMB_STRUCT_STAT *pst)
1936 if (!CAN_WRITE(conn)) {
1937 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1940 fmode = dos_mode(conn, fsp->fsp_name, pst);
1941 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1942 return NT_STATUS_NO_SUCH_FILE;
1945 if (S_ISDIR(pst->st_mode)) {
1946 return NT_STATUS_OK;
1949 if (fsp->access_mask & DELETE_ACCESS) {
1950 return NT_STATUS_OK;
1953 return NT_STATUS_ACCESS_DENIED;
1956 /*******************************************************************
1957 * unlink a file with all relevant access checks
1958 *******************************************************************/
1960 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
1961 char *fname, uint32 dirtype)
1963 SMB_STRUCT_STAT sbuf;
1966 uint32 dirtype_orig = dirtype;
1969 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
1971 if (!CAN_WRITE(conn)) {
1972 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1975 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1976 return map_nt_error_from_unix(errno);
1979 fattr = dos_mode(conn,fname,&sbuf);
1981 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1982 dirtype = aDIR|aARCH|aRONLY;
1985 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1987 return NT_STATUS_NO_SUCH_FILE;
1990 if (!dir_check_ftype(conn, fattr, dirtype)) {
1992 return NT_STATUS_FILE_IS_A_DIRECTORY;
1994 return NT_STATUS_NO_SUCH_FILE;
1997 if (dirtype_orig & 0x8000) {
1998 /* These will never be set for POSIX. */
1999 return NT_STATUS_NO_SUCH_FILE;
2003 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2004 return NT_STATUS_FILE_IS_A_DIRECTORY;
2007 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2008 return NT_STATUS_NO_SUCH_FILE;
2011 if (dirtype & 0xFF00) {
2012 /* These will never be set for POSIX. */
2013 return NT_STATUS_NO_SUCH_FILE;
2018 return NT_STATUS_NO_SUCH_FILE;
2021 /* Can't delete a directory. */
2023 return NT_STATUS_FILE_IS_A_DIRECTORY;
2028 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2029 return NT_STATUS_OBJECT_NAME_INVALID;
2030 #endif /* JRATEST */
2032 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2034 On a Windows share, a file with read-only dosmode can be opened with
2035 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2036 fails with NT_STATUS_CANNOT_DELETE error.
2038 This semantic causes a problem that a user can not
2039 rename a file with read-only dosmode on a Samba share
2040 from a Windows command prompt (i.e. cmd.exe, but can rename
2041 from Windows Explorer).
2044 if (!lp_delete_readonly(SNUM(conn))) {
2045 if (fattr & aRONLY) {
2046 return NT_STATUS_CANNOT_DELETE;
2050 /* On open checks the open itself will check the share mode, so
2051 don't do it here as we'll get it wrong. */
2053 status = open_file_ntcreate(conn, req, fname, &sbuf,
2058 FILE_ATTRIBUTE_NORMAL,
2059 req != NULL ? 0 : INTERNAL_OPEN_ONLY,
2062 if (!NT_STATUS_IS_OK(status)) {
2063 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2064 nt_errstr(status)));
2068 /* The set is across all open files on this dev/inode pair. */
2069 if (!set_delete_on_close(fsp, True, ¤t_user.ut)) {
2070 close_file(fsp, NORMAL_CLOSE);
2071 return NT_STATUS_ACCESS_DENIED;
2074 return close_file(fsp,NORMAL_CLOSE);
2077 /****************************************************************************
2078 The guts of the unlink command, split out so it may be called by the NT SMB
2080 ****************************************************************************/
2082 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2083 uint32 dirtype, char *name, BOOL has_wild)
2089 NTSTATUS status = NT_STATUS_OK;
2090 SMB_STRUCT_STAT sbuf;
2092 *directory = *mask = 0;
2094 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
2095 if (!NT_STATUS_IS_OK(status)) {
2099 p = strrchr_m(name,'/');
2101 pstrcpy(directory,".");
2105 pstrcpy(directory,name);
2110 * We should only check the mangled cache
2111 * here if unix_convert failed. This means
2112 * that the path in 'mask' doesn't exist
2113 * on the file system and so we need to look
2114 * for a possible mangle. This patch from
2115 * Tine Smukavec <valentin.smukavec@hermes.si>.
2118 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
2119 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
2122 pstrcat(directory,"/");
2123 pstrcat(directory,mask);
2125 dirtype = FILE_ATTRIBUTE_NORMAL;
2128 status = check_name(conn, directory);
2129 if (!NT_STATUS_IS_OK(status)) {
2133 status = do_unlink(conn, req, directory, dirtype);
2134 if (!NT_STATUS_IS_OK(status)) {
2140 struct smb_Dir *dir_hnd = NULL;
2144 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2145 return NT_STATUS_OBJECT_NAME_INVALID;
2148 if (strequal(mask,"????????.???")) {
2152 status = check_name(conn, directory);
2153 if (!NT_STATUS_IS_OK(status)) {
2157 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2158 if (dir_hnd == NULL) {
2159 return map_nt_error_from_unix(errno);
2162 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2163 the pattern matches against the long name, otherwise the short name
2164 We don't implement this yet XXXX
2167 status = NT_STATUS_NO_SUCH_FILE;
2169 while ((dname = ReadDirName(dir_hnd, &offset))) {
2172 pstrcpy(fname,dname);
2174 if (!is_visible_file(conn, directory, dname, &st, True)) {
2178 /* Quick check for "." and ".." */
2179 if (fname[0] == '.') {
2180 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2185 if(!mask_match(fname, mask, conn->case_sensitive)) {
2189 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2191 status = check_name(conn, fname);
2192 if (!NT_STATUS_IS_OK(status)) {
2197 status = do_unlink(conn, req, fname, dirtype);
2198 if (!NT_STATUS_IS_OK(status)) {
2203 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2209 if (count == 0 && NT_STATUS_IS_OK(status)) {
2210 status = map_nt_error_from_unix(errno);
2216 /****************************************************************************
2218 ****************************************************************************/
2220 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2227 BOOL path_contains_wcard = False;
2228 struct smb_request req;
2230 START_PROFILE(SMBunlink);
2232 init_smb_request(&req, (uint8 *)inbuf);
2234 dirtype = SVAL(inbuf,smb_vwv0);
2236 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name,
2237 smb_buf(inbuf) + 1, sizeof(name), 0,
2238 STR_TERMINATE, &status, &path_contains_wcard);
2239 if (!NT_STATUS_IS_OK(status)) {
2240 END_PROFILE(SMBunlink);
2241 return ERROR_NT(status);
2244 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 END_PROFILE(SMBunlink);
2247 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2248 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
2250 return ERROR_NT(status);
2253 DEBUG(3,("reply_unlink : %s\n",name));
2255 status = unlink_internals(conn, &req, dirtype, name,
2256 path_contains_wcard);
2257 if (!NT_STATUS_IS_OK(status)) {
2258 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2259 /* We have re-scheduled this call. */
2262 return ERROR_NT(status);
2265 outsize = set_message(inbuf,outbuf,0,0,False);
2267 END_PROFILE(SMBunlink);
2271 /****************************************************************************
2273 ****************************************************************************/
2275 static void fail_readraw(void)
2278 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2280 exit_server_cleanly(errstr);
2283 /****************************************************************************
2284 Fake (read/write) sendfile. Returns -1 on read or write fail.
2285 ****************************************************************************/
2287 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
2289 size_t tosend = nread;
2291 while (tosend > 0) {
2295 if (tosend > bufsize) {
2300 ret = read_file(fsp,buf,startpos,cur_read);
2305 /* If we had a short read, fill with zeros. */
2306 if (ret < cur_read) {
2307 memset(buf, '\0', cur_read - ret);
2310 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2314 startpos += cur_read;
2317 return (ssize_t)nread;
2320 /****************************************************************************
2321 Use sendfile in readbraw.
2322 ****************************************************************************/
2324 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2325 ssize_t mincount, char *outbuf, int out_buffsize)
2329 #if defined(WITH_SENDFILE)
2331 * We can only use sendfile on a non-chained packet
2332 * but we can use on a non-oplocked file. tridge proved this
2333 * on a train in Germany :-). JRA.
2334 * reply_readbraw has already checked the length.
2337 if ( (chain_size == 0) && (nread > 0) &&
2338 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2341 _smb_setlen(outbuf,nread);
2342 header.data = (uint8 *)outbuf;
2346 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2347 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2348 if (errno == ENOSYS) {
2349 goto normal_readbraw;
2353 * Special hack for broken Linux with no working sendfile. If we
2354 * return EINTR we sent the header but not the rest of the data.
2355 * Fake this up by doing read/write calls.
2357 if (errno == EINTR) {
2358 /* Ensure we don't do this again. */
2359 set_use_sendfile(SNUM(conn), False);
2360 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2362 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2363 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2364 fsp->fsp_name, strerror(errno) ));
2365 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2370 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2371 fsp->fsp_name, strerror(errno) ));
2372 exit_server_cleanly("send_file_readbraw sendfile failed");
2382 ret = read_file(fsp,outbuf+4,startpos,nread);
2383 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2392 _smb_setlen(outbuf,ret);
2393 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2397 /****************************************************************************
2398 Reply to a readbraw (core+ protocol).
2399 ****************************************************************************/
2401 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2403 ssize_t maxcount,mincount;
2406 char *header = outbuf;
2408 START_PROFILE(SMBreadbraw);
2410 if (srv_is_signing_active()) {
2411 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2415 * Special check if an oplock break has been issued
2416 * and the readraw request croses on the wire, we must
2417 * return a zero length response here.
2420 fsp = file_fsp(inbuf,smb_vwv0);
2422 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2424 * fsp could be NULL here so use the value from the packet. JRA.
2426 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2427 _smb_setlen(header,0);
2428 if (write_data(smbd_server_fd(),header,4) != 4)
2430 END_PROFILE(SMBreadbraw);
2434 CHECK_FSP(fsp,conn);
2436 flush_write_cache(fsp, READRAW_FLUSH);
2438 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2439 if(CVAL(inbuf,smb_wct) == 10) {
2441 * This is a large offset (64 bit) read.
2443 #ifdef LARGE_SMB_OFF_T
2445 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2447 #else /* !LARGE_SMB_OFF_T */
2450 * Ensure we haven't been sent a >32 bit offset.
2453 if(IVAL(inbuf,smb_vwv8) != 0) {
2454 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2455 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2456 _smb_setlen(header,0);
2457 if (write_data(smbd_server_fd(),header,4) != 4)
2459 END_PROFILE(SMBreadbraw);
2463 #endif /* LARGE_SMB_OFF_T */
2466 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2467 _smb_setlen(header,0);
2468 if (write_data(smbd_server_fd(),header,4) != 4)
2470 END_PROFILE(SMBreadbraw);
2474 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2475 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2477 /* ensure we don't overrun the packet size */
2478 maxcount = MIN(65535,maxcount);
2480 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2484 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2488 if (startpos >= size) {
2491 nread = MIN(maxcount,(size - startpos));
2495 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2496 if (nread < mincount)
2500 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2501 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2503 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2505 DEBUG(5,("readbraw finished\n"));
2506 END_PROFILE(SMBreadbraw);
2511 #define DBGC_CLASS DBGC_LOCKING
2513 /****************************************************************************
2514 Reply to a lockread (core+ protocol).
2515 ****************************************************************************/
2517 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2525 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2526 struct byte_range_lock *br_lck = NULL;
2527 START_PROFILE(SMBlockread);
2529 CHECK_FSP(fsp,conn);
2530 if (!CHECK_READ(fsp,inbuf)) {
2531 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2534 release_level_2_oplocks_on_change(fsp);
2536 numtoread = SVAL(inbuf,smb_vwv1);
2537 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2539 outsize = set_message(inbuf,outbuf,5,3,True);
2540 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2541 data = smb_buf(outbuf) + 3;
2544 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2545 * protocol request that predates the read/write lock concept.
2546 * Thus instead of asking for a read lock here we need to ask
2547 * for a write lock. JRA.
2548 * Note that the requested lock size is unaffected by max_recv.
2551 br_lck = do_lock(smbd_messaging_context(),
2553 (uint32)SVAL(inbuf,smb_pid),
2554 (SMB_BIG_UINT)numtoread,
2555 (SMB_BIG_UINT)startpos,
2558 False, /* Non-blocking lock. */
2561 TALLOC_FREE(br_lck);
2563 if (NT_STATUS_V(status)) {
2564 END_PROFILE(SMBlockread);
2565 return ERROR_NT(status);
2569 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2572 if (numtoread > max_recv) {
2573 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2574 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2575 (unsigned int)numtoread, (unsigned int)max_recv ));
2576 numtoread = MIN(numtoread,max_recv);
2578 nread = read_file(fsp,data,startpos,numtoread);
2581 END_PROFILE(SMBlockread);
2582 return(UNIXERROR(ERRDOS,ERRnoaccess));
2586 SSVAL(outbuf,smb_vwv0,nread);
2587 SSVAL(outbuf,smb_vwv5,nread+3);
2588 SSVAL(smb_buf(outbuf),1,nread);
2590 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2591 fsp->fnum, (int)numtoread, (int)nread));
2593 END_PROFILE(SMBlockread);
2598 #define DBGC_CLASS DBGC_ALL
2600 /****************************************************************************
2602 ****************************************************************************/
2604 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2611 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2612 START_PROFILE(SMBread);
2614 CHECK_FSP(fsp,conn);
2615 if (!CHECK_READ(fsp,inbuf)) {
2616 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2619 numtoread = SVAL(inbuf,smb_vwv1);
2620 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2622 outsize = set_message(inbuf,outbuf,5,3,True);
2623 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2625 * The requested read size cannot be greater than max_recv. JRA.
2627 if (numtoread > max_recv) {
2628 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2629 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2630 (unsigned int)numtoread, (unsigned int)max_recv ));
2631 numtoread = MIN(numtoread,max_recv);
2634 data = smb_buf(outbuf) + 3;
2636 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2637 END_PROFILE(SMBread);
2638 return ERROR_DOS(ERRDOS,ERRlock);
2642 nread = read_file(fsp,data,startpos,numtoread);
2645 END_PROFILE(SMBread);
2646 return(UNIXERROR(ERRDOS,ERRnoaccess));
2650 SSVAL(outbuf,smb_vwv0,nread);
2651 SSVAL(outbuf,smb_vwv5,nread+3);
2652 SCVAL(smb_buf(outbuf),0,1);
2653 SSVAL(smb_buf(outbuf),1,nread);
2655 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2656 fsp->fnum, (int)numtoread, (int)nread ) );
2658 END_PROFILE(SMBread);
2662 /****************************************************************************
2664 ****************************************************************************/
2666 static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
2669 char *data = smb_buf(outbuf);
2671 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2672 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2673 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2674 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2675 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2676 SCVAL(outbuf,smb_vwv0,0xFF);
2677 outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
2678 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2679 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2683 /****************************************************************************
2684 Reply to a read and X - possibly using sendfile.
2685 ****************************************************************************/
2687 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2688 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2690 SMB_STRUCT_STAT sbuf;
2693 char *data = smb_buf(outbuf);
2695 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2696 return(UNIXERROR(ERRDOS,ERRnoaccess));
2699 if (startpos > sbuf.st_size) {
2701 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
2702 smb_maxcnt = (sbuf.st_size - startpos);
2705 if (smb_maxcnt == 0) {
2709 #if defined(WITH_SENDFILE)
2711 * We can only use sendfile on a non-chained packet
2712 * but we can use on a non-oplocked file. tridge proved this
2713 * on a train in Germany :-). JRA.
2716 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2717 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2721 * Set up the packet header before send. We
2722 * assume here the sendfile will work (get the
2723 * correct amount of data).
2726 setup_readX_header(inbuf,outbuf,smb_maxcnt);
2727 set_message(inbuf,outbuf,12,smb_maxcnt,False);
2728 header.data = (uint8 *)outbuf;
2729 header.length = data - outbuf;
2732 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2733 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2734 if (errno == ENOSYS) {
2739 * Special hack for broken Linux with no working sendfile. If we
2740 * return EINTR we sent the header but not the rest of the data.
2741 * Fake this up by doing read/write calls.
2744 if (errno == EINTR) {
2745 /* Ensure we don't do this again. */
2746 set_use_sendfile(SNUM(conn), False);
2747 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2749 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2750 len_outbuf - (data-outbuf))) == -1) {
2751 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2752 fsp->fsp_name, strerror(errno) ));
2753 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2755 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2756 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2757 /* Returning -1 here means successful sendfile. */
2761 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2762 fsp->fsp_name, strerror(errno) ));
2763 exit_server_cleanly("send_file_readX sendfile failed");
2766 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2767 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2768 /* Returning -1 here means successful sendfile. */
2776 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
2777 int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
2778 /* Send out the header. */
2779 if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
2780 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2781 fsp->fsp_name, strerror(errno) ));
2782 exit_server_cleanly("send_file_readX sendfile failed");
2784 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2785 len_outbuf - (data-outbuf))) == -1) {
2786 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2787 fsp->fsp_name, strerror(errno) ));
2788 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2792 nread = read_file(fsp,data,startpos,smb_maxcnt);
2795 return(UNIXERROR(ERRDOS,ERRnoaccess));
2798 outsize = setup_readX_header(inbuf, outbuf,nread);
2800 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2801 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2803 /* Returning the number of bytes we want to send back - including header. */
2808 /****************************************************************************
2809 Reply to a read and X.
2810 ****************************************************************************/
2812 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2814 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2815 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2817 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2818 BOOL big_readX = False;
2820 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2823 START_PROFILE(SMBreadX);
2825 /* If it's an IPC, pass off the pipe handler. */
2827 END_PROFILE(SMBreadX);
2828 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2831 CHECK_FSP(fsp,conn);
2832 if (!CHECK_READ(fsp,inbuf)) {
2833 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2836 set_message(inbuf,outbuf,12,0,True);
2838 if (global_client_caps & CAP_LARGE_READX) {
2839 size_t upper_size = SVAL(inbuf,smb_vwv7);
2840 smb_maxcnt |= (upper_size<<16);
2841 if (upper_size > 1) {
2842 /* Can't do this on a chained packet. */
2843 if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
2844 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2846 /* We currently don't do this on signed or sealed data. */
2847 if (srv_is_signing_active() || srv_encryption_on()) {
2848 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2850 /* Is there room in the reply for this data ? */
2851 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
2852 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2858 if(CVAL(inbuf,smb_wct) == 12) {
2859 #ifdef LARGE_SMB_OFF_T
2861 * This is a large offset (64 bit) read.
2863 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2865 #else /* !LARGE_SMB_OFF_T */
2868 * Ensure we haven't been sent a >32 bit offset.
2871 if(IVAL(inbuf,smb_vwv10) != 0) {
2872 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2873 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2874 END_PROFILE(SMBreadX);
2875 return ERROR_DOS(ERRDOS,ERRbadaccess);
2878 #endif /* LARGE_SMB_OFF_T */
2882 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2883 END_PROFILE(SMBreadX);
2884 return ERROR_DOS(ERRDOS,ERRlock);
2887 if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2888 END_PROFILE(SMBreadX);
2892 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2893 /* Only call chain_reply if not an error. */
2894 if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2895 nread = chain_reply(inbuf,&outbuf,length,bufsize);
2898 END_PROFILE(SMBreadX);
2902 /****************************************************************************
2903 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2904 ****************************************************************************/
2906 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2909 ssize_t total_written=0;
2910 size_t numtowrite=0;
2915 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2918 START_PROFILE(SMBwritebraw);
2920 if (srv_is_signing_active()) {
2921 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2924 CHECK_FSP(fsp,conn);
2925 if (!CHECK_WRITE(fsp)) {
2926 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2929 tcount = IVAL(inbuf,smb_vwv1);
2930 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2931 write_through = BITSETW(inbuf+smb_vwv7,0);
2933 /* We have to deal with slightly different formats depending
2934 on whether we are using the core+ or lanman1.0 protocol */
2936 if(Protocol <= PROTOCOL_COREPLUS) {
2937 numtowrite = SVAL(smb_buf(inbuf),-2);
2938 data = smb_buf(inbuf);
2940 numtowrite = SVAL(inbuf,smb_vwv10);
2941 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2944 /* force the error type */
2945 SCVAL(inbuf,smb_com,SMBwritec);
2946 SCVAL(outbuf,smb_com,SMBwritec);
2948 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2949 END_PROFILE(SMBwritebraw);
2950 return(ERROR_DOS(ERRDOS,ERRlock));
2954 nwritten = write_file(fsp,data,startpos,numtowrite);
2956 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2957 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2959 if (nwritten < (ssize_t)numtowrite) {
2960 END_PROFILE(SMBwritebraw);
2961 return(UNIXERROR(ERRHRD,ERRdiskfull));
2964 total_written = nwritten;
2966 /* Return a message to the redirector to tell it to send more bytes */
2967 SCVAL(outbuf,smb_com,SMBwritebraw);
2968 SSVALS(outbuf,smb_vwv0,-1);
2969 outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2971 if (!send_smb(smbd_server_fd(),outbuf))
2972 exit_server_cleanly("reply_writebraw: send_smb failed.");
2974 /* Now read the raw data into the buffer and write it */
2975 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2976 exit_server_cleanly("secondary writebraw failed");
2979 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2980 numtowrite = smb_len(inbuf);
2982 /* Set up outbuf to return the correct return */
2983 outsize = set_message(inbuf,outbuf,1,0,True);
2984 SCVAL(outbuf,smb_com,SMBwritec);
2986 if (numtowrite != 0) {
2988 if (numtowrite > BUFFER_SIZE) {
2989 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2990 (unsigned int)numtowrite ));
2991 exit_server_cleanly("secondary writebraw failed");
2994 if (tcount > nwritten+numtowrite) {
2995 DEBUG(3,("Client overestimated the write %d %d %d\n",
2996 (int)tcount,(int)nwritten,(int)numtowrite));
2999 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
3000 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
3002 exit_server_cleanly("secondary writebraw failed");
3005 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
3006 if (nwritten == -1) {
3007 END_PROFILE(SMBwritebraw);
3008 return(UNIXERROR(ERRHRD,ERRdiskfull));
3011 if (nwritten < (ssize_t)numtowrite) {
3012 SCVAL(outbuf,smb_rcls,ERRHRD);
3013 SSVAL(outbuf,smb_err,ERRdiskfull);
3017 total_written += nwritten;
3020 SSVAL(outbuf,smb_vwv0,total_written);
3022 status = sync_file(conn, fsp, write_through);
3023 if (!NT_STATUS_IS_OK(status)) {
3024 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3025 fsp->fsp_name, nt_errstr(status) ));
3026 END_PROFILE(SMBwritebraw);
3027 return ERROR_NT(status);
3030 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
3031 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
3033 /* we won't return a status if write through is not selected - this follows what WfWg does */
3034 END_PROFILE(SMBwritebraw);
3035 if (!write_through && total_written==tcount) {
3037 #if RABBIT_PELLET_FIX
3039 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3040 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
3042 if (!send_keepalive(smbd_server_fd()))
3043 exit_server_cleanly("reply_writebraw: send of keepalive failed");
3052 #define DBGC_CLASS DBGC_LOCKING
3054 /****************************************************************************
3055 Reply to a writeunlock (core+).
3056 ****************************************************************************/
3058 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
3059 int size, int dum_buffsize)
3061 ssize_t nwritten = -1;
3065 NTSTATUS status = NT_STATUS_OK;
3066 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3068 START_PROFILE(SMBwriteunlock);
3070 CHECK_FSP(fsp,conn);
3071 if (!CHECK_WRITE(fsp)) {
3072 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3075 numtowrite = SVAL(inbuf,smb_vwv1);
3076 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3077 data = smb_buf(inbuf) + 3;
3079 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3080 END_PROFILE(SMBwriteunlock);
3081 return ERROR_DOS(ERRDOS,ERRlock);
3084 /* The special X/Open SMB protocol handling of
3085 zero length writes is *NOT* done for
3087 if(numtowrite == 0) {
3090 nwritten = write_file(fsp,data,startpos,numtowrite);
3093 status = sync_file(conn, fsp, False /* write through */);
3094 if (!NT_STATUS_IS_OK(status)) {
3095 END_PROFILE(SMBwriteunlock);
3096 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3097 fsp->fsp_name, nt_errstr(status) ));
3098 return ERROR_NT(status);
3101 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3102 END_PROFILE(SMBwriteunlock);
3103 return(UNIXERROR(ERRHRD,ERRdiskfull));
3107 status = do_unlock(smbd_messaging_context(),
3109 (uint32)SVAL(inbuf,smb_pid),
3110 (SMB_BIG_UINT)numtowrite,
3111 (SMB_BIG_UINT)startpos,
3114 if (NT_STATUS_V(status)) {
3115 END_PROFILE(SMBwriteunlock);
3116 return ERROR_NT(status);
3120 outsize = set_message(inbuf,outbuf,1,0,True);
3122 SSVAL(outbuf,smb_vwv0,nwritten);
3124 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3125 fsp->fnum, (int)numtowrite, (int)nwritten));
3127 END_PROFILE(SMBwriteunlock);
3132 #define DBGC_CLASS DBGC_ALL
3134 /****************************************************************************
3136 ****************************************************************************/
3138 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
3141 ssize_t nwritten = -1;
3144 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3147 START_PROFILE(SMBwrite);
3149 /* If it's an IPC, pass off the pipe handler. */
3151 END_PROFILE(SMBwrite);
3152 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3155 CHECK_FSP(fsp,conn);
3156 if (!CHECK_WRITE(fsp)) {
3157 END_PROFILE(SMBwrite);
3158 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3161 numtowrite = SVAL(inbuf,smb_vwv1);
3162 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3163 data = smb_buf(inbuf) + 3;
3165 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3166 END_PROFILE(SMBwrite);
3167 return ERROR_DOS(ERRDOS,ERRlock);
3171 * X/Open SMB protocol says that if smb_vwv1 is
3172 * zero then the file size should be extended or
3173 * truncated to the size given in smb_vwv[2-3].
3176 if(numtowrite == 0) {
3178 * This is actually an allocate call, and set EOF. JRA.
3180 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3182 END_PROFILE(SMBwrite);
3183 return ERROR_NT(NT_STATUS_DISK_FULL);
3185 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3187 END_PROFILE(SMBwrite);
3188 return ERROR_NT(NT_STATUS_DISK_FULL);
3191 nwritten = write_file(fsp,data,startpos,numtowrite);
3193 status = sync_file(conn, fsp, False);
3194 if (!NT_STATUS_IS_OK(status)) {
3195 END_PROFILE(SMBwrite);
3196 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3197 fsp->fsp_name, nt_errstr(status) ));
3198 return ERROR_NT(status);
3201 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3202 END_PROFILE(SMBwrite);
3203 return(UNIXERROR(ERRHRD,ERRdiskfull));
3206 outsize = set_message(inbuf,outbuf,1,0,True);
3208 SSVAL(outbuf,smb_vwv0,nwritten);
3210 if (nwritten < (ssize_t)numtowrite) {
3211 SCVAL(outbuf,smb_rcls,ERRHRD);
3212 SSVAL(outbuf,smb_err,ERRdiskfull);
3215 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3217 END_PROFILE(SMBwrite);
3221 /****************************************************************************
3222 Reply to a write and X.
3223 ****************************************************************************/
3225 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3227 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3228 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3229 size_t numtowrite = SVAL(inbuf,smb_vwv10);
3230 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3231 ssize_t nwritten = -1;
3232 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3233 unsigned int smblen = smb_len(inbuf);
3235 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3237 START_PROFILE(SMBwriteX);
3239 /* If it's an IPC, pass off the pipe handler. */
3241 END_PROFILE(SMBwriteX);
3242 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3245 CHECK_FSP(fsp,conn);
3246 if (!CHECK_WRITE(fsp)) {
3247 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3250 set_message(inbuf,outbuf,6,0,True);
3252 /* Deal with possible LARGE_WRITEX */
3254 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3257 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3258 END_PROFILE(SMBwriteX);
3259 return ERROR_DOS(ERRDOS,ERRbadmem);
3262 data = smb_base(inbuf) + smb_doff;
3264 if(CVAL(inbuf,smb_wct) == 14) {
3265 #ifdef LARGE_SMB_OFF_T
3267 * This is a large offset (64 bit) write.
3269 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3271 #else /* !LARGE_SMB_OFF_T */
3274 * Ensure we haven't been sent a >32 bit offset.
3277 if(IVAL(inbuf,smb_vwv12) != 0) {
3278 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3279 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3280 END_PROFILE(SMBwriteX);
3281 return ERROR_DOS(ERRDOS,ERRbadaccess);
3284 #endif /* LARGE_SMB_OFF_T */
3287 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3288 END_PROFILE(SMBwriteX);
3289 return ERROR_DOS(ERRDOS,ERRlock);
3292 /* X/Open SMB protocol says that, unlike SMBwrite
3293 if the length is zero then NO truncation is
3294 done, just a write of zero. To truncate a file,
3297 if(numtowrite == 0) {
3301 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3302 fsp,data,startpos,numtowrite)) {
3303 END_PROFILE(SMBwriteX);
3307 nwritten = write_file(fsp,data,startpos,numtowrite);
3310 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3311 END_PROFILE(SMBwriteX);
3312 return(UNIXERROR(ERRHRD,ERRdiskfull));
3315 SSVAL(outbuf,smb_vwv2,nwritten);
3317 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3319 if (nwritten < (ssize_t)numtowrite) {
3320 SCVAL(outbuf,smb_rcls,ERRHRD);
3321 SSVAL(outbuf,smb_err,ERRdiskfull);
3324 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3325 fsp->fnum, (int)numtowrite, (int)nwritten));
3327 status = sync_file(conn, fsp, write_through);
3328 if (!NT_STATUS_IS_OK(status)) {
3329 END_PROFILE(SMBwriteX);
3330 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3331 fsp->fsp_name, nt_errstr(status) ));
3332 return ERROR_NT(status);
3335 END_PROFILE(SMBwriteX);
3336 return chain_reply(inbuf,&outbuf,length,bufsize);
3339 /****************************************************************************
3341 ****************************************************************************/
3343 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3349 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3350 START_PROFILE(SMBlseek);
3352 CHECK_FSP(fsp,conn);
3354 flush_write_cache(fsp, SEEK_FLUSH);
3356 mode = SVAL(inbuf,smb_vwv1) & 3;
3357 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3358 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3367 res = fsp->fh->pos + startpos;
3378 if (umode == SEEK_END) {
3379 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3380 if(errno == EINVAL) {
3381 SMB_OFF_T current_pos = startpos;
3382 SMB_STRUCT_STAT sbuf;
3384 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3385 END_PROFILE(SMBlseek);
3386 return(UNIXERROR(ERRDOS,ERRnoaccess));
3389 current_pos += sbuf.st_size;
3391 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3396 END_PROFILE(SMBlseek);
3397 return(UNIXERROR(ERRDOS,ERRnoaccess));
3403 outsize = set_message(inbuf,outbuf,2,0,True);
3404 SIVAL(outbuf,smb_vwv0,res);
3406 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3407 fsp->fnum, (double)startpos, (double)res, mode));
3409 END_PROFILE(SMBlseek);
3413 /****************************************************************************
3415 ****************************************************************************/
3417 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3419 int outsize = set_message(inbuf,outbuf,0,0,False);
3420 uint16 fnum = SVAL(inbuf,smb_vwv0);
3421 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3422 START_PROFILE(SMBflush);
3425 CHECK_FSP(fsp,conn);
3428 file_sync_all(conn);
3430 NTSTATUS status = sync_file(conn, fsp, True);
3431 if (!NT_STATUS_IS_OK(status)) {
3432 END_PROFILE(SMBflush);
3433 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3434 fsp->fsp_name, nt_errstr(status) ));
3435 return ERROR_NT(status);
3439 DEBUG(3,("flush\n"));
3440 END_PROFILE(SMBflush);
3444 /****************************************************************************
3446 conn POINTER CAN BE NULL HERE !
3447 ****************************************************************************/
3449 int reply_exit(connection_struct *conn,
3450 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3453 START_PROFILE(SMBexit);
3455 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3457 outsize = set_message(inbuf,outbuf,0,0,False);
3459 DEBUG(3,("exit\n"));
3461 END_PROFILE(SMBexit);
3465 /****************************************************************************
3466 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3467 ****************************************************************************/
3469 void reply_close(connection_struct *conn, struct smb_request *req)
3471 NTSTATUS status = NT_STATUS_OK;
3472 files_struct *fsp = NULL;
3473 START_PROFILE(SMBclose);
3476 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3477 END_PROFILE(SMBclose);
3481 /* If it's an IPC, pass off to the pipe handler. */
3483 reply_pipe_close(conn, req);
3484 END_PROFILE(SMBclose);
3488 fsp = file_fsp((char *)req->inbuf,smb_vwv0);
3491 * We can only use CHECK_FSP if we know it's not a directory.
3494 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3495 reply_doserror(req, ERRDOS, ERRbadfid);
3496 END_PROFILE(SMBclose);
3500 if(fsp->is_directory) {
3502 * Special case - close NT SMB directory handle.
3504 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3505 status = close_file(fsp,NORMAL_CLOSE);
3508 * Close ordinary file.
3511 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3512 fsp->fh->fd, fsp->fnum,
3513 conn->num_files_open));
3516 * Take care of any time sent in the close.
3519 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
3520 srv_make_unix_date3(
3521 req->inbuf+smb_vwv1)));
3524 * close_file() returns the unix errno if an error
3525 * was detected on close - normally this is due to
3526 * a disk full error. If not then it was probably an I/O error.
3529 status = close_file(fsp,NORMAL_CLOSE);
3532 if (!NT_STATUS_IS_OK(status)) {
3533 reply_nterror(req, status);
3534 END_PROFILE(SMBclose);
3538 reply_outbuf(req, 0, 0);
3539 END_PROFILE(SMBclose);
3543 /****************************************************************************
3544 Reply to a writeclose (Core+ protocol).
3545 ****************************************************************************/
3547 int reply_writeclose(connection_struct *conn,
3548 char *inbuf,char *outbuf, int size, int dum_buffsize)
3551 ssize_t nwritten = -1;
3553 NTSTATUS close_status = NT_STATUS_OK;
3556 struct timespec mtime;
3557 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3558 START_PROFILE(SMBwriteclose);
3560 CHECK_FSP(fsp,conn);
3561 if (!CHECK_WRITE(fsp)) {
3562 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3565 numtowrite = SVAL(inbuf,smb_vwv1);
3566 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3567 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3568 data = smb_buf(inbuf) + 1;
3570 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3571 END_PROFILE(SMBwriteclose);
3572 return ERROR_DOS(ERRDOS,ERRlock);
3575 nwritten = write_file(fsp,data,startpos,numtowrite);
3577 set_filetime(conn, fsp->fsp_name, mtime);
3580 * More insanity. W2K only closes the file if writelen > 0.
3585 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3587 close_status = close_file(fsp,NORMAL_CLOSE);
3590 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3591 fsp->fnum, (int)numtowrite, (int)nwritten,
3592 conn->num_files_open));
3594 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3595 END_PROFILE(SMBwriteclose);
3596 return(UNIXERROR(ERRHRD,ERRdiskfull));
3599 if(!NT_STATUS_IS_OK(close_status)) {
3600 END_PROFILE(SMBwriteclose);
3601 return ERROR_NT(close_status);
3604 outsize = set_message(inbuf,outbuf,1,0,True);
3606 SSVAL(outbuf,smb_vwv0,nwritten);
3607 END_PROFILE(SMBwriteclose);
3612 #define DBGC_CLASS DBGC_LOCKING
3614 /****************************************************************************
3616 ****************************************************************************/
3618 int reply_lock(connection_struct *conn,
3619 char *inbuf,char *outbuf, int length, int dum_buffsize)
3621 int outsize = set_message(inbuf,outbuf,0,0,False);
3622 SMB_BIG_UINT count,offset;
3624 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3625 struct byte_range_lock *br_lck = NULL;
3627 START_PROFILE(SMBlock);
3629 CHECK_FSP(fsp,conn);
3631 release_level_2_oplocks_on_change(fsp);
3633 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3634 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3636 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3637 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3639 br_lck = do_lock(smbd_messaging_context(),
3641 (uint32)SVAL(inbuf,smb_pid),
3646 False, /* Non-blocking lock. */
3650 TALLOC_FREE(br_lck);
3652 if (NT_STATUS_V(status)) {
3653 END_PROFILE(SMBlock);
3654 return ERROR_NT(status);
3657 END_PROFILE(SMBlock);
3661 /****************************************************************************
3663 ****************************************************************************/
3665 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3668 int outsize = set_message(inbuf,outbuf,0,0,False);
3669 SMB_BIG_UINT count,offset;
3671 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3672 START_PROFILE(SMBunlock);
3674 CHECK_FSP(fsp,conn);
3676 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3677 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3679 status = do_unlock(smbd_messaging_context(),
3681 (uint32)SVAL(inbuf,smb_pid),
3686 if (NT_STATUS_V(status)) {
3687 END_PROFILE(SMBunlock);
3688 return ERROR_NT(status);
3691 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3692 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3694 END_PROFILE(SMBunlock);
3699 #define DBGC_CLASS DBGC_ALL
3701 /****************************************************************************
3703 conn POINTER CAN BE NULL HERE !
3704 ****************************************************************************/
3706 int reply_tdis(connection_struct *conn,
3707 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3709 int outsize = set_message(inbuf,outbuf,0,0,False);
3711 START_PROFILE(SMBtdis);
3713 vuid = SVAL(inbuf,smb_uid);
3716 DEBUG(4,("Invalid connection in tdis\n"));
3717 END_PROFILE(SMBtdis);
3718 return ERROR_DOS(ERRSRV,ERRinvnid);
3723 close_cnum(conn,vuid);
3725 END_PROFILE(SMBtdis);
3729 /****************************************************************************
3731 conn POINTER CAN BE NULL HERE !
3732 ****************************************************************************/
3734 int reply_echo(connection_struct *conn,
3735 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3737 int smb_reverb = SVAL(inbuf,smb_vwv0);
3739 unsigned int data_len = smb_buflen(inbuf);
3740 int outsize = set_message(inbuf,outbuf,1,data_len,True);
3741 START_PROFILE(SMBecho);
3743 if (data_len > BUFFER_SIZE) {
3744 DEBUG(0,("reply_echo: data_len too large.\n"));
3745 END_PROFILE(SMBecho);
3749 /* copy any incoming data back out */
3751 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3753 if (smb_reverb > 100) {
3754 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3758 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3759 SSVAL(outbuf,smb_vwv0,seq_num);
3761 smb_setlen(inbuf,outbuf,outsize - 4);
3764 if (!send_smb(smbd_server_fd(),outbuf))
3765 exit_server_cleanly("reply_echo: send_smb failed.");
3768 DEBUG(3,("echo %d times\n", smb_reverb));
3772 END_PROFILE(SMBecho);
3776 /****************************************************************************
3777 Reply to a printopen.
3778 ****************************************************************************/
3780 int reply_printopen(connection_struct *conn,
3781 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3787 START_PROFILE(SMBsplopen);
3789 if (!CAN_PRINT(conn)) {
3790 END_PROFILE(SMBsplopen);
3791 return ERROR_DOS(ERRDOS,ERRnoaccess);
3794 /* Open for exclusive use, write only. */
3795 status = print_fsp_open(conn, NULL, &fsp);
3797 if (!NT_STATUS_IS_OK(status)) {
3798 END_PROFILE(SMBsplopen);
3799 return(ERROR_NT(status));
3802 outsize = set_message(inbuf,outbuf,1,0,True);
3803 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3805 DEBUG(3,("openprint fd=%d fnum=%d\n",
3806 fsp->fh->fd, fsp->fnum));
3808 END_PROFILE(SMBsplopen);
3812 /****************************************************************************
3813 Reply to a printclose.
3814 ****************************************************************************/
3816 int reply_printclose(connection_struct *conn,
3817 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3819 int outsize = set_message(inbuf,outbuf,0,0,False);
3820 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3822 START_PROFILE(SMBsplclose);
3824 CHECK_FSP(fsp,conn);
3826 if (!CAN_PRINT(conn)) {
3827 END_PROFILE(SMBsplclose);
3828 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3831 DEBUG(3,("printclose fd=%d fnum=%d\n",
3832 fsp->fh->fd,fsp->fnum));
3834 status = close_file(fsp,NORMAL_CLOSE);
3836 if(!NT_STATUS_IS_OK(status)) {
3837 END_PROFILE(SMBsplclose);
3838 return ERROR_NT(status);
3841 END_PROFILE(SMBsplclose);
3845 /****************************************************************************
3846 Reply to a printqueue.
3847 ****************************************************************************/
3849 int reply_printqueue(connection_struct *conn,
3850 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3852 int outsize = set_message(inbuf,outbuf,2,3,True);
3853 int max_count = SVAL(inbuf,smb_vwv0);
3854 int start_index = SVAL(inbuf,smb_vwv1);
3855 START_PROFILE(SMBsplretq);
3857 /* we used to allow the client to get the cnum wrong, but that
3858 is really quite gross and only worked when there was only
3859 one printer - I think we should now only accept it if they
3860 get it right (tridge) */
3861 if (!CAN_PRINT(conn)) {
3862 END_PROFILE(SMBsplretq);
3863 return ERROR_DOS(ERRDOS,ERRnoaccess);
3866 SSVAL(outbuf,smb_vwv0,0);
3867 SSVAL(outbuf,smb_vwv1,0);
3868 SCVAL(smb_buf(outbuf),0,1);
3869 SSVAL(smb_buf(outbuf),1,0);
3871 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3872 start_index, max_count));
3875 print_queue_struct *queue = NULL;
3876 print_status_struct status;
3877 char *p = smb_buf(outbuf) + 3;
3878 int count = print_queue_status(SNUM(conn), &queue, &status);
3879 int num_to_get = ABS(max_count);
3880 int first = (max_count>0?start_index:start_index+max_count+1);
3886 num_to_get = MIN(num_to_get,count-first);
3889 for (i=first;i<first+num_to_get;i++) {
3890 srv_put_dos_date2(p,0,queue[i].time);
3891 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3892 SSVAL(p,5, queue[i].job);
3893 SIVAL(p,7,queue[i].size);
3895 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3900 outsize = set_message(inbuf,outbuf,2,28*count+3,False);
3901 SSVAL(outbuf,smb_vwv0,count);
3902 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3903 SCVAL(smb_buf(outbuf),0,1);
3904 SSVAL(smb_buf(outbuf),1,28*count);
3909 DEBUG(3,("%d entries returned in queue\n",count));
3912 END_PROFILE(SMBsplretq);
3916 /****************************************************************************
3917 Reply to a printwrite.
3918 ****************************************************************************/
3920 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3923 int outsize = set_message(inbuf,outbuf,0,0,False);
3925 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3927 START_PROFILE(SMBsplwr);
3929 if (!CAN_PRINT(conn)) {
3930 END_PROFILE(SMBsplwr);
3931 return ERROR_DOS(ERRDOS,ERRnoaccess);
3934 CHECK_FSP(fsp,conn);
3935 if (!CHECK_WRITE(fsp)) {
3936 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3939 numtowrite = SVAL(smb_buf(inbuf),1);
3940 data = smb_buf(inbuf) + 3;
3942 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3943 END_PROFILE(SMBsplwr);
3944 return(UNIXERROR(ERRHRD,ERRdiskfull));
3947 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3949 END_PROFILE(SMBsplwr);
3953 /****************************************************************************
3955 ****************************************************************************/
3957 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3962 SMB_STRUCT_STAT sbuf;
3964 START_PROFILE(SMBmkdir);
3966 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
3967 smb_buf(inbuf) + 1, sizeof(directory), 0,
3968 STR_TERMINATE, &status);
3969 if (!NT_STATUS_IS_OK(status)) {
3970 END_PROFILE(SMBmkdir);
3971 return ERROR_NT(status);
3974 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
3975 if (!NT_STATUS_IS_OK(status)) {
3976 END_PROFILE(SMBmkdir);
3977 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3978 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3980 return ERROR_NT(status);
3983 status = unix_convert(conn, directory, False, NULL, &sbuf);
3984 if (!NT_STATUS_IS_OK(status)) {
3985 END_PROFILE(SMBmkdir);
3986 return ERROR_NT(status);
3989 status = check_name(conn, directory);
3990 if (!NT_STATUS_IS_OK(status)) {
3991 END_PROFILE(SMBmkdir);
3992 return ERROR_NT(status);
3995 status = create_directory(conn, directory);
3997 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3999 if (!NT_STATUS_IS_OK(status)) {
4001 if (!use_nt_status()
4002 && NT_STATUS_EQUAL(status,
4003 NT_STATUS_OBJECT_NAME_COLLISION)) {
4005 * Yes, in the DOS error code case we get a
4006 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4007 * samba4 torture test.
4009 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4012 END_PROFILE(SMBmkdir);
4013 return ERROR_NT(status);
4016 outsize = set_message(inbuf,outbuf,0,0,False);
4018 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
4020 END_PROFILE(SMBmkdir);
4024 /****************************************************************************
4025 Static function used by reply_rmdir to delete an entire directory
4026 tree recursively. Return True on ok, False on fail.
4027 ****************************************************************************/
4029 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
4031 const char *dname = NULL;
4034 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4039 while((dname = ReadDirName(dir_hnd, &offset))) {
4043 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4046 if (!is_visible_file(conn, directory, dname, &st, False))
4049 /* Construct the full name. */
4050 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4056 pstrcpy(fullname, directory);
4057 pstrcat(fullname, "/");
4058 pstrcat(fullname, dname);
4060 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4065 if(st.st_mode & S_IFDIR) {
4066 if(!recursive_rmdir(conn, fullname)) {
4070 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4074 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4083 /****************************************************************************
4084 The internals of the rmdir code - called elsewhere.
4085 ****************************************************************************/
4087 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4092 /* Might be a symlink. */
4093 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4094 return map_nt_error_from_unix(errno);
4097 if (S_ISLNK(st.st_mode)) {
4098 /* Is what it points to a directory ? */
4099 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4100 return map_nt_error_from_unix(errno);
4102 if (!(S_ISDIR(st.st_mode))) {
4103 return NT_STATUS_NOT_A_DIRECTORY;
4105 ret = SMB_VFS_UNLINK(conn,directory);
4107 ret = SMB_VFS_RMDIR(conn,directory);
4110 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4111 FILE_NOTIFY_CHANGE_DIR_NAME,
4113 return NT_STATUS_OK;
4116 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4118 * Check to see if the only thing in this directory are
4119 * vetoed files/directories. If so then delete them and
4120 * retry. If we fail to delete any of them (and we *don't*
4121 * do a recursive delete) then fail the rmdir.
4125 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4127 if(dir_hnd == NULL) {
4132 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4133 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4135 if (!is_visible_file(conn, directory, dname, &st, False))
4137 if(!IS_VETO_PATH(conn, dname)) {
4144 /* We only have veto files/directories. Recursive delete. */
4146 RewindDir(dir_hnd,&dirpos);
4147 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4150 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4152 if (!is_visible_file(conn, directory, dname, &st, False))
4155 /* Construct the full name. */
4156 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4161 pstrcpy(fullname, directory);
4162 pstrcat(fullname, "/");
4163 pstrcat(fullname, dname);
4165 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4167 if(st.st_mode & S_IFDIR) {
4168 if(lp_recursive_veto_delete(SNUM(conn))) {
4169 if(!recursive_rmdir(conn, fullname))
4172 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4174 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4178 /* Retry the rmdir */
4179 ret = SMB_VFS_RMDIR(conn,directory);
4185 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4186 "%s\n", directory,strerror(errno)));
4187 return map_nt_error_from_unix(errno);
4190 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4191 FILE_NOTIFY_CHANGE_DIR_NAME,
4194 return NT_STATUS_OK;
4197 /****************************************************************************
4199 ****************************************************************************/
4201 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4205 SMB_STRUCT_STAT sbuf;
4207 START_PROFILE(SMBrmdir);
4209 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
4210 smb_buf(inbuf) + 1, sizeof(directory), 0,
4211 STR_TERMINATE, &status);
4212 if (!NT_STATUS_IS_OK(status)) {
4213 END_PROFILE(SMBrmdir);
4214 return ERROR_NT(status);
4217 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
4218 if (!NT_STATUS_IS_OK(status)) {
4219 END_PROFILE(SMBrmdir);
4220 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4221 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4223 return ERROR_NT(status);
4226 status = unix_convert(conn, directory, False, NULL, &sbuf);
4227 if (!NT_STATUS_IS_OK(status)) {
4228 END_PROFILE(SMBrmdir);
4229 return ERROR_NT(status);
4232 status = check_name(conn, directory);
4233 if (!NT_STATUS_IS_OK(status)) {
4234 END_PROFILE(SMBrmdir);
4235 return ERROR_NT(status);
4238 dptr_closepath(directory,SVAL(inbuf,smb_pid));
4239 status = rmdir_internals(conn, directory);
4240 if (!NT_STATUS_IS_OK(status)) {
4241 END_PROFILE(SMBrmdir);
4242 return ERROR_NT(status);
4245 outsize = set_message(inbuf,outbuf,0,0,False);
4247 DEBUG( 3, ( "rmdir %s\n", directory ) );
4249 END_PROFILE(SMBrmdir);
4253 /*******************************************************************
4254 Resolve wildcards in a filename rename.
4255 Note that name is in UNIX charset and thus potentially can be more
4256 than fstring buffer (255 bytes) especially in default UTF-8 case.
4257 Therefore, we use pstring inside and all calls should ensure that
4258 name2 is at least pstring-long (they do already)
4259 ********************************************************************/
4261 static BOOL resolve_wildcards(const char *name1, char *name2)
4263 pstring root1,root2;
4265 char *p,*p2, *pname1, *pname2;
4266 int available_space, actual_space;
4268 pname1 = strrchr_m(name1,'/');
4269 pname2 = strrchr_m(name2,'/');
4271 if (!pname1 || !pname2)
4274 pstrcpy(root1,pname1);
4275 pstrcpy(root2,pname2);
4276 p = strrchr_m(root1,'.');
4283 p = strrchr_m(root2,'.');
4297 } else if (*p2 == '*') {
4313 } else if (*p2 == '*') {
4323 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4326 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4327 if (actual_space >= available_space - 1) {
4328 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4329 actual_space - available_space));
4332 pstrcpy_base(pname2, root2, name2);
4338 /****************************************************************************
4339 Ensure open files have their names updated. Updated to notify other smbd's
4341 ****************************************************************************/
4343 static void rename_open_files(connection_struct *conn,
4344 struct share_mode_lock *lck,
4345 const char *newname)
4348 BOOL did_rename = False;
4350 for(fsp = file_find_di_first(lck->id); fsp;
4351 fsp = file_find_di_next(fsp)) {
4352 /* fsp_name is a relative path under the fsp. To change this for other
4353 sharepaths we need to manipulate relative paths. */
4354 /* TODO - create the absolute path and manipulate the newname
4355 relative to the sharepath. */
4356 if (fsp->conn != conn) {
4359 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4360 fsp->fnum, file_id_static_string(&fsp->file_id),
4361 fsp->fsp_name, newname ));
4362 string_set(&fsp->fsp_name, newname);
4367 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4368 file_id_static_string(&lck->id), newname ));
4371 /* Send messages to all smbd's (not ourself) that the name has changed. */
4372 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4376 /****************************************************************************
4377 We need to check if the source path is a parent directory of the destination
4378 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4379 refuse the rename with a sharing violation. Under UNIX the above call can
4380 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4381 probably need to check that the client is a Windows one before disallowing
4382 this as a UNIX client (one with UNIX extensions) can know the source is a
4383 symlink and make this decision intelligently. Found by an excellent bug
4384 report from <AndyLiebman@aol.com>.
4385 ****************************************************************************/
4387 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4389 const char *psrc = src;
4390 const char *pdst = dest;
4393 if (psrc[0] == '.' && psrc[1] == '/') {
4396 if (pdst[0] == '.' && pdst[1] == '/') {
4399 if ((slen = strlen(psrc)) > strlen(pdst)) {
4402 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4406 * Do the notify calls from a rename
4409 static void notify_rename(connection_struct *conn, BOOL is_dir,
4410 const char *oldpath, const char *newpath)
4412 char *olddir, *newdir;
4413 const char *oldname, *newname;
4416 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4417 : FILE_NOTIFY_CHANGE_FILE_NAME;
4419 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4420 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4421 TALLOC_FREE(olddir);
4425 if (strcmp(olddir, newdir) == 0) {
4426 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4427 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4430 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4431 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4433 TALLOC_FREE(olddir);
4434 TALLOC_FREE(newdir);
4436 /* this is a strange one. w2k3 gives an additional event for
4437 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4438 files, but not directories */
4440 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4441 FILE_NOTIFY_CHANGE_ATTRIBUTES
4442 |FILE_NOTIFY_CHANGE_CREATION,
4447 /****************************************************************************
4448 Rename an open file - given an fsp.
4449 ****************************************************************************/
4451 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4453 SMB_STRUCT_STAT sbuf, sbuf1;
4454 pstring newname_last_component;
4455 NTSTATUS status = NT_STATUS_OK;
4456 struct share_mode_lock *lck = NULL;
4461 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4463 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4465 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4469 status = check_name(conn, newname);
4470 if (!NT_STATUS_IS_OK(status)) {
4474 /* Ensure newname contains a '/' */
4475 if(strrchr_m(newname,'/') == 0) {
4478 pstrcpy(tmpstr, "./");
4479 pstrcat(tmpstr, newname);
4480 pstrcpy(newname, tmpstr);
4484 * Check for special case with case preserving and not
4485 * case sensitive. If the old last component differs from the original
4486 * last component only by case, then we should allow
4487 * the rename (user is trying to change the case of the
4491 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4492 strequal(newname, fsp->fsp_name)) {
4494 pstring newname_modified_last_component;
4497 * Get the last component of the modified name.
4498 * Note that we guarantee that newname contains a '/'
4501 p = strrchr_m(newname,'/');
4502 pstrcpy(newname_modified_last_component,p+1);
4504 if(strcsequal(newname_modified_last_component,
4505 newname_last_component) == False) {
4507 * Replace the modified last component with
4510 pstrcpy(p+1, newname_last_component);
4515 * If the src and dest names are identical - including case,
4516 * don't do the rename, just return success.
4519 if (strcsequal(fsp->fsp_name, newname)) {
4520 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4522 return NT_STATUS_OK;
4526 * Have vfs_object_exist also fill sbuf1
4528 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4530 if(!replace_if_exists && dst_exists) {
4531 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4532 fsp->fsp_name,newname));
4533 return NT_STATUS_OBJECT_NAME_COLLISION;
4537 files_struct *dst_fsp = file_find_di_first(file_id_sbuf(&sbuf1));
4539 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4540 return NT_STATUS_ACCESS_DENIED;
4544 /* Ensure we have a valid stat struct for the source. */
4545 if (fsp->fh->fd != -1) {
4546 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4547 return map_nt_error_from_unix(errno);
4550 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4551 return map_nt_error_from_unix(errno);
4555 status = can_rename(conn, fsp, attrs, &sbuf);
4557 if (!NT_STATUS_IS_OK(status)) {
4558 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4559 nt_errstr(status), fsp->fsp_name,newname));
4560 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4561 status = NT_STATUS_ACCESS_DENIED;
4565 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4566 return NT_STATUS_ACCESS_DENIED;
4569 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4572 * We have the file open ourselves, so not being able to get the
4573 * corresponding share mode lock is a fatal error.
4576 SMB_ASSERT(lck != NULL);
4578 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4579 uint32 create_options = fsp->fh->private_options;
4581 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4582 fsp->fsp_name,newname));
4584 rename_open_files(conn, lck, newname);
4586 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4589 * A rename acts as a new file create w.r.t. allowing an initial delete
4590 * on close, probably because in Windows there is a new handle to the
4591 * new file. If initial delete on close was requested but not
4592 * originally set, we need to set it here. This is probably not 100% correct,
4593 * but will work for the CIFSFS client which in non-posix mode
4594 * depends on these semantics. JRA.
4597 set_allow_initial_delete_on_close(lck, fsp, True);
4599 if (create_options & FILE_DELETE_ON_CLOSE) {
4600 status = can_set_delete_on_close(fsp, True, 0);
4602 if (NT_STATUS_IS_OK(status)) {
4603 /* Note that here we set the *inital* delete on close flag,
4604 * not the regular one. The magic gets handled in close. */
4605 fsp->initial_delete_on_close = True;
4609 return NT_STATUS_OK;
4614 if (errno == ENOTDIR || errno == EISDIR) {
4615 status = NT_STATUS_OBJECT_NAME_COLLISION;
4617 status = map_nt_error_from_unix(errno);
4620 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4621 nt_errstr(status), fsp->fsp_name,newname));
4626 /****************************************************************************
4627 The guts of the rename command, split out so it may be called by the NT SMB
4629 ****************************************************************************/
4631 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
4635 BOOL replace_if_exists,
4641 pstring last_component_src;
4642 pstring last_component_dest;
4645 NTSTATUS status = NT_STATUS_OK;
4646 SMB_STRUCT_STAT sbuf1, sbuf2;
4647 struct smb_Dir *dir_hnd = NULL;
4652 *directory = *mask = 0;
4657 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4658 if (!NT_STATUS_IS_OK(status)) {
4662 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4663 if (!NT_STATUS_IS_OK(status)) {
4668 * Split the old name into directory and last component
4669 * strings. Note that unix_convert may have stripped off a
4670 * leading ./ from both name and newname if the rename is
4671 * at the root of the share. We need to make sure either both
4672 * name and newname contain a / character or neither of them do
4673 * as this is checked in resolve_wildcards().
4676 p = strrchr_m(name,'/');
4678 pstrcpy(directory,".");
4682 pstrcpy(directory,name);
4684 *p = '/'; /* Replace needed for exceptional test below. */
4688 * We should only check the mangled cache
4689 * here if unix_convert failed. This means
4690 * that the path in 'mask' doesn't exist
4691 * on the file system and so we need to look
4692 * for a possible mangle. This patch from
4693 * Tine Smukavec <valentin.smukavec@hermes.si>.
4696 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4697 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4700 if (!src_has_wild) {
4704 * No wildcards - just process the one file.
4706 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4708 /* Add a terminating '/' to the directory name. */
4709 pstrcat(directory,"/");
4710 pstrcat(directory,mask);
4712 /* Ensure newname contains a '/' also */
4713 if(strrchr_m(newname,'/') == 0) {
4716 pstrcpy(tmpstr, "./");
4717 pstrcat(tmpstr, newname);
4718 pstrcpy(newname, tmpstr);
4721 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4722 "case_preserve = %d, short case preserve = %d, "
4723 "directory = %s, newname = %s, "
4724 "last_component_dest = %s, is_8_3 = %d\n",
4725 conn->case_sensitive, conn->case_preserve,
4726 conn->short_case_preserve, directory,
4727 newname, last_component_dest, is_short_name));
4729 /* The dest name still may have wildcards. */
4730 if (dest_has_wild) {
4731 if (!resolve_wildcards(directory,newname)) {
4732 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4733 directory,newname));
4734 return NT_STATUS_NO_MEMORY;
4739 SMB_VFS_STAT(conn, directory, &sbuf1);
4741 status = S_ISDIR(sbuf1.st_mode) ?
4742 open_directory(conn, req, directory, &sbuf1,
4744 FILE_SHARE_READ|FILE_SHARE_WRITE,
4745 FILE_OPEN, 0, 0, NULL,
4747 : open_file_ntcreate(conn, req, directory, &sbuf1,
4749 FILE_SHARE_READ|FILE_SHARE_WRITE,
4750 FILE_OPEN, 0, 0, 0, NULL,
4753 if (!NT_STATUS_IS_OK(status)) {
4754 DEBUG(3, ("Could not open rename source %s: %s\n",
4755 directory, nt_errstr(status)));
4759 status = rename_internals_fsp(conn, fsp, newname, attrs,
4762 close_file(fsp, NORMAL_CLOSE);
4764 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4765 nt_errstr(status), directory,newname));
4771 * Wildcards - process each file that matches.
4773 if (strequal(mask,"????????.???")) {
4777 status = check_name(conn, directory);
4778 if (!NT_STATUS_IS_OK(status)) {
4782 dir_hnd = OpenDir(conn, directory, mask, attrs);
4783 if (dir_hnd == NULL) {
4784 return map_nt_error_from_unix(errno);
4787 status = NT_STATUS_NO_SUCH_FILE;
4789 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4790 * - gentest fix. JRA
4793 while ((dname = ReadDirName(dir_hnd, &offset))) {
4796 BOOL sysdir_entry = False;
4798 pstrcpy(fname,dname);
4800 /* Quick check for "." and ".." */
4801 if (fname[0] == '.') {
4802 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4804 sysdir_entry = True;
4811 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4815 if(!mask_match(fname, mask, conn->case_sensitive)) {
4820 status = NT_STATUS_OBJECT_NAME_INVALID;
4824 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4826 pstrcpy(destname,newname);
4828 if (!resolve_wildcards(fname,destname)) {
4829 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4835 SMB_VFS_STAT(conn, fname, &sbuf1);
4837 status = S_ISDIR(sbuf1.st_mode) ?
4838 open_directory(conn, req, fname, &sbuf1,
4840 FILE_SHARE_READ|FILE_SHARE_WRITE,
4841 FILE_OPEN, 0, 0, NULL,
4843 : open_file_ntcreate(conn, req, fname, &sbuf1,
4845 FILE_SHARE_READ|FILE_SHARE_WRITE,
4846 FILE_OPEN, 0, 0, 0, NULL,
4849 if (!NT_STATUS_IS_OK(status)) {
4850 DEBUG(3,("rename_internals: open_file_ntcreate "
4851 "returned %s rename %s -> %s\n",
4852 nt_errstr(status), directory, newname));
4856 status = rename_internals_fsp(conn, fsp, destname, attrs,
4859 close_file(fsp, NORMAL_CLOSE);
4861 if (!NT_STATUS_IS_OK(status)) {
4862 DEBUG(3, ("rename_internals_fsp returned %s for "
4863 "rename %s -> %s\n", nt_errstr(status),
4864 directory, newname));
4870 DEBUG(3,("rename_internals: doing rename on %s -> "
4871 "%s\n",fname,destname));
4875 if (count == 0 && NT_STATUS_IS_OK(status)) {
4876 status = map_nt_error_from_unix(errno);
4882 /****************************************************************************
4884 ****************************************************************************/
4886 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4893 uint32 attrs = SVAL(inbuf,smb_vwv0);
4895 BOOL src_has_wcard = False;
4896 BOOL dest_has_wcard = False;
4897 struct smb_request req;
4899 START_PROFILE(SMBmv);
4901 init_smb_request(&req, (uint8 *)inbuf);
4903 p = smb_buf(inbuf) + 1;
4904 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
4905 sizeof(name), 0, STR_TERMINATE, &status,
4907 if (!NT_STATUS_IS_OK(status)) {
4909 return ERROR_NT(status);
4912 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
4913 sizeof(newname), 0, STR_TERMINATE, &status,
4915 if (!NT_STATUS_IS_OK(status)) {
4917 return ERROR_NT(status);
4920 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
4921 if (!NT_STATUS_IS_OK(status)) {
4923 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4924 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4926 return ERROR_NT(status);
4929 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4930 if (!NT_STATUS_IS_OK(status)) {
4932 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4933 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4935 return ERROR_NT(status);
4938 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4940 status = rename_internals(conn, &req, name, newname, attrs, False,
4941 src_has_wcard, dest_has_wcard);
4942 if (!NT_STATUS_IS_OK(status)) {
4944 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4945 /* We have re-scheduled this call. */
4948 return ERROR_NT(status);
4951 outsize = set_message(inbuf,outbuf,0,0,False);
4957 /*******************************************************************
4958 Copy a file as part of a reply_copy.
4959 ******************************************************************/
4962 * TODO: check error codes on all callers
4965 NTSTATUS copy_file(connection_struct *conn,
4970 BOOL target_is_directory)
4972 SMB_STRUCT_STAT src_sbuf, sbuf2;
4974 files_struct *fsp1,*fsp2;
4977 uint32 new_create_disposition;
4980 pstrcpy(dest,dest1);
4981 if (target_is_directory) {
4982 char *p = strrchr_m(src,'/');
4992 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4993 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4996 if (!target_is_directory && count) {
4997 new_create_disposition = FILE_OPEN;
4999 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5000 NULL, NULL, &new_create_disposition, NULL)) {
5001 return NT_STATUS_INVALID_PARAMETER;
5005 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5007 FILE_SHARE_READ|FILE_SHARE_WRITE,
5010 FILE_ATTRIBUTE_NORMAL,
5014 if (!NT_STATUS_IS_OK(status)) {
5018 dosattrs = dos_mode(conn, src, &src_sbuf);
5019 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
5020 ZERO_STRUCTP(&sbuf2);
5023 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
5025 FILE_SHARE_READ|FILE_SHARE_WRITE,
5026 new_create_disposition,
5032 if (!NT_STATUS_IS_OK(status)) {
5033 close_file(fsp1,ERROR_CLOSE);
5037 if ((ofun&3) == 1) {
5038 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
5039 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
5041 * Stop the copy from occurring.
5044 src_sbuf.st_size = 0;
5048 if (src_sbuf.st_size) {
5049 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
5052 close_file(fsp1,NORMAL_CLOSE);
5054 /* Ensure the modtime is set correctly on the destination file. */
5055 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
5058 * As we are opening fsp1 read-only we only expect
5059 * an error on close on fsp2 if we are out of space.
5060 * Thus we don't look at the error return from the
5063 status = close_file(fsp2,NORMAL_CLOSE);
5065 if (!NT_STATUS_IS_OK(status)) {
5069 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
5070 return NT_STATUS_DISK_FULL;
5073 return NT_STATUS_OK;
5076 /****************************************************************************
5077 Reply to a file copy.
5078 ****************************************************************************/
5080 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5085 pstring mask,newname;
5088 int error = ERRnoaccess;
5090 int tid2 = SVAL(inbuf,smb_vwv0);
5091 int ofun = SVAL(inbuf,smb_vwv1);
5092 int flags = SVAL(inbuf,smb_vwv2);
5093 BOOL target_is_directory=False;
5094 BOOL source_has_wild = False;
5095 BOOL dest_has_wild = False;
5096 SMB_STRUCT_STAT sbuf1, sbuf2;
5098 START_PROFILE(SMBcopy);
5100 *directory = *mask = 0;
5103 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5104 sizeof(name), 0, STR_TERMINATE, &status,
5106 if (!NT_STATUS_IS_OK(status)) {
5107 END_PROFILE(SMBcopy);
5108 return ERROR_NT(status);
5110 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5111 sizeof(newname), 0, STR_TERMINATE, &status,
5113 if (!NT_STATUS_IS_OK(status)) {
5114 END_PROFILE(SMBcopy);
5115 return ERROR_NT(status);
5118 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5120 if (tid2 != conn->cnum) {
5121 /* can't currently handle inter share copies XXXX */
5122 DEBUG(3,("Rejecting inter-share copy\n"));
5123 END_PROFILE(SMBcopy);
5124 return ERROR_DOS(ERRSRV,ERRinvdevice);
5127 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5128 if (!NT_STATUS_IS_OK(status)) {
5129 END_PROFILE(SMBcopy);
5130 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5131 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5133 return ERROR_NT(status);
5136 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5137 if (!NT_STATUS_IS_OK(status)) {
5138 END_PROFILE(SMBcopy);
5139 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5140 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5142 return ERROR_NT(status);
5145 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5146 if (!NT_STATUS_IS_OK(status)) {
5147 END_PROFILE(SMBcopy);
5148 return ERROR_NT(status);
5151 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5152 if (!NT_STATUS_IS_OK(status)) {
5153 END_PROFILE(SMBcopy);
5154 return ERROR_NT(status);
5157 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5159 if ((flags&1) && target_is_directory) {
5160 END_PROFILE(SMBcopy);
5161 return ERROR_DOS(ERRDOS,ERRbadfile);
5164 if ((flags&2) && !target_is_directory) {
5165 END_PROFILE(SMBcopy);
5166 return ERROR_DOS(ERRDOS,ERRbadpath);
5169 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5170 /* wants a tree copy! XXXX */
5171 DEBUG(3,("Rejecting tree copy\n"));
5172 END_PROFILE(SMBcopy);
5173 return ERROR_DOS(ERRSRV,ERRerror);
5176 p = strrchr_m(name,'/');
5178 pstrcpy(directory,"./");
5182 pstrcpy(directory,name);
5187 * We should only check the mangled cache
5188 * here if unix_convert failed. This means
5189 * that the path in 'mask' doesn't exist
5190 * on the file system and so we need to look
5191 * for a possible mangle. This patch from
5192 * Tine Smukavec <valentin.smukavec@hermes.si>.
5195 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5196 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5199 if (!source_has_wild) {
5200 pstrcat(directory,"/");
5201 pstrcat(directory,mask);
5202 if (dest_has_wild) {
5203 if (!resolve_wildcards(directory,newname)) {
5204 END_PROFILE(SMBcopy);
5205 return ERROR_NT(NT_STATUS_NO_MEMORY);
5209 status = check_name(conn, directory);
5210 if (!NT_STATUS_IS_OK(status)) {
5211 return ERROR_NT(status);
5214 status = check_name(conn, newname);
5215 if (!NT_STATUS_IS_OK(status)) {
5216 return ERROR_NT(status);
5219 status = copy_file(conn,directory,newname,ofun,
5220 count,target_is_directory);
5222 if(!NT_STATUS_IS_OK(status)) {
5223 END_PROFILE(SMBcopy);
5224 return ERROR_NT(status);
5229 struct smb_Dir *dir_hnd = NULL;
5234 if (strequal(mask,"????????.???"))
5237 status = check_name(conn, directory);
5238 if (!NT_STATUS_IS_OK(status)) {
5239 return ERROR_NT(status);
5242 dir_hnd = OpenDir(conn, directory, mask, 0);
5243 if (dir_hnd == NULL) {
5244 status = map_nt_error_from_unix(errno);
5245 return ERROR_NT(status);
5250 while ((dname = ReadDirName(dir_hnd, &offset))) {
5252 pstrcpy(fname,dname);
5254 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5258 if(!mask_match(fname, mask, conn->case_sensitive)) {
5262 error = ERRnoaccess;
5263 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5264 pstrcpy(destname,newname);
5265 if (!resolve_wildcards(fname,destname)) {
5269 status = check_name(conn, fname);
5270 if (!NT_STATUS_IS_OK(status)) {
5271 return ERROR_NT(status);
5274 status = check_name(conn, destname);
5275 if (!NT_STATUS_IS_OK(status)) {
5276 return ERROR_NT(status);
5279 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5281 status = copy_file(conn,fname,destname,ofun,
5282 count,target_is_directory);
5283 if (NT_STATUS_IS_OK(status)) {
5292 /* Error on close... */
5294 END_PROFILE(SMBcopy);
5295 return(UNIXERROR(ERRHRD,ERRgeneral));
5298 END_PROFILE(SMBcopy);
5299 return ERROR_DOS(ERRDOS,error);
5302 outsize = set_message(inbuf,outbuf,1,0,True);
5303 SSVAL(outbuf,smb_vwv0,count);
5305 END_PROFILE(SMBcopy);
5309 /****************************************************************************
5311 ****************************************************************************/
5313 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5320 START_PROFILE(pathworks_setdir);
5323 if (!CAN_SETDIR(snum)) {
5324 END_PROFILE(pathworks_setdir);
5325 return ERROR_DOS(ERRDOS,ERRnoaccess);
5328 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
5329 smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
5331 if (!NT_STATUS_IS_OK(status)) {
5332 END_PROFILE(pathworks_setdir);
5333 return ERROR_NT(status);
5336 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5337 if (!NT_STATUS_IS_OK(status)) {
5338 END_PROFILE(pathworks_setdir);
5339 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5340 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5342 return ERROR_NT(status);
5345 if (strlen(newdir) != 0) {
5346 if (!vfs_directory_exist(conn,newdir,NULL)) {
5347 END_PROFILE(pathworks_setdir);
5348 return ERROR_DOS(ERRDOS,ERRbadpath);
5350 set_conn_connectpath(conn,newdir);
5353 outsize = set_message(inbuf,outbuf,0,0,False);
5354 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5356 DEBUG(3,("setdir %s\n", newdir));
5358 END_PROFILE(pathworks_setdir);
5363 #define DBGC_CLASS DBGC_LOCKING
5365 /****************************************************************************
5366 Get a lock pid, dealing with large count requests.
5367 ****************************************************************************/
5369 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5371 if(!large_file_format)
5372 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5374 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5377 /****************************************************************************
5378 Get a lock count, dealing with large count requests.
5379 ****************************************************************************/
5381 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5383 SMB_BIG_UINT count = 0;
5385 if(!large_file_format) {
5386 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5389 #if defined(HAVE_LONGLONG)
5390 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5391 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5392 #else /* HAVE_LONGLONG */
5395 * NT4.x seems to be broken in that it sends large file (64 bit)
5396 * lockingX calls even if the CAP_LARGE_FILES was *not*
5397 * negotiated. For boxes without large unsigned ints truncate the
5398 * lock count by dropping the top 32 bits.
5401 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5402 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5403 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5404 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5405 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5408 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5409 #endif /* HAVE_LONGLONG */
5415 #if !defined(HAVE_LONGLONG)
5416 /****************************************************************************
5417 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5418 ****************************************************************************/
5420 static uint32 map_lock_offset(uint32 high, uint32 low)
5424 uint32 highcopy = high;
5427 * Try and find out how many significant bits there are in high.
5430 for(i = 0; highcopy; i++)
5434 * We use 31 bits not 32 here as POSIX
5435 * lock offsets may not be negative.
5438 mask = (~0) << (31 - i);
5441 return 0; /* Fail. */
5447 #endif /* !defined(HAVE_LONGLONG) */
5449 /****************************************************************************
5450 Get a lock offset, dealing with large offset requests.
5451 ****************************************************************************/
5453 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5455 SMB_BIG_UINT offset = 0;
5459 if(!large_file_format) {
5460 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5463 #if defined(HAVE_LONGLONG)
5464 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5465 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5466 #else /* HAVE_LONGLONG */
5469 * NT4.x seems to be broken in that it sends large file (64 bit)
5470 * lockingX calls even if the CAP_LARGE_FILES was *not*
5471 * negotiated. For boxes without large unsigned ints mangle the
5472 * lock offset by mapping the top 32 bits onto the lower 32.
5475 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5476 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5477 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5480 if((new_low = map_lock_offset(high, low)) == 0) {
5482 return (SMB_BIG_UINT)-1;
5485 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5486 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5487 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5488 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5491 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5492 #endif /* HAVE_LONGLONG */
5498 /****************************************************************************
5499 Reply to a lockingX request.
5500 ****************************************************************************/
5502 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5503 int length, int bufsize)
5505 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5506 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5507 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5508 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5509 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5510 SMB_BIG_UINT count = 0, offset = 0;
5512 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5515 BOOL large_file_format =
5516 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5518 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5520 START_PROFILE(SMBlockingX);
5522 CHECK_FSP(fsp,conn);
5524 data = smb_buf(inbuf);
5526 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5527 /* we don't support these - and CANCEL_LOCK makes w2k
5528 and XP reboot so I don't really want to be
5529 compatible! (tridge) */
5530 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5533 /* Check if this is an oplock break on a file
5534 we have granted an oplock on.
5536 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5537 /* Client can insist on breaking to none. */
5538 BOOL break_to_none = (oplocklevel == 0);
5541 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5542 "for fnum = %d\n", (unsigned int)oplocklevel,
5546 * Make sure we have granted an exclusive or batch oplock on
5550 if (fsp->oplock_type == 0) {
5552 /* The Samba4 nbench simulator doesn't understand
5553 the difference between break to level2 and break
5554 to none from level2 - it sends oplock break
5555 replies in both cases. Don't keep logging an error
5556 message here - just ignore it. JRA. */
5558 DEBUG(5,("reply_lockingX: Error : oplock break from "
5559 "client for fnum = %d (oplock=%d) and no "
5560 "oplock granted on this file (%s).\n",
5561 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5563 /* if this is a pure oplock break request then don't
5565 if (num_locks == 0 && num_ulocks == 0) {
5566 END_PROFILE(SMBlockingX);
5569 END_PROFILE(SMBlockingX);
5570 return ERROR_DOS(ERRDOS,ERRlock);
5574 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5576 result = remove_oplock(fsp);
5578 result = downgrade_oplock(fsp);
5582 DEBUG(0, ("reply_lockingX: error in removing "
5583 "oplock on file %s\n", fsp->fsp_name));
5584 /* Hmmm. Is this panic justified? */
5585 smb_panic("internal tdb error");
5588 reply_to_oplock_break_requests(fsp);
5590 /* if this is a pure oplock break request then don't send a
5592 if (num_locks == 0 && num_ulocks == 0) {
5593 /* Sanity check - ensure a pure oplock break is not a
5595 if(CVAL(inbuf,smb_vwv0) != 0xff)
5596 DEBUG(0,("reply_lockingX: Error : pure oplock "
5597 "break is a chained %d request !\n",
5598 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5599 END_PROFILE(SMBlockingX);
5605 * We do this check *after* we have checked this is not a oplock break
5606 * response message. JRA.
5609 release_level_2_oplocks_on_change(fsp);
5611 /* Data now points at the beginning of the list
5612 of smb_unlkrng structs */
5613 for(i = 0; i < (int)num_ulocks; i++) {
5614 lock_pid = get_lock_pid( data, i, large_file_format);
5615 count = get_lock_count( data, i, large_file_format);
5616 offset = get_lock_offset( data, i, large_file_format, &err);
5619 * There is no error code marked "stupid client bug".... :-).
5622 END_PROFILE(SMBlockingX);
5623 return ERROR_DOS(ERRDOS,ERRnoaccess);
5626 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5627 "pid %u, file %s\n", (double)offset, (double)count,
5628 (unsigned int)lock_pid, fsp->fsp_name ));
5630 status = do_unlock(smbd_messaging_context(),
5637 if (NT_STATUS_V(status)) {
5638 END_PROFILE(SMBlockingX);
5639 return ERROR_NT(status);
5643 /* Setup the timeout in seconds. */
5645 if (!lp_blocking_locks(SNUM(conn))) {
5649 /* Now do any requested locks */
5650 data += ((large_file_format ? 20 : 10)*num_ulocks);
5652 /* Data now points at the beginning of the list
5653 of smb_lkrng structs */
5655 for(i = 0; i < (int)num_locks; i++) {
5656 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5657 READ_LOCK:WRITE_LOCK);
5658 lock_pid = get_lock_pid( data, i, large_file_format);
5659 count = get_lock_count( data, i, large_file_format);
5660 offset = get_lock_offset( data, i, large_file_format, &err);
5663 * There is no error code marked "stupid client bug".... :-).
5666 END_PROFILE(SMBlockingX);
5667 return ERROR_DOS(ERRDOS,ERRnoaccess);
5670 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5671 "%u, file %s timeout = %d\n", (double)offset,
5672 (double)count, (unsigned int)lock_pid,
5673 fsp->fsp_name, (int)lock_timeout ));
5675 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5676 if (lp_blocking_locks(SNUM(conn))) {
5678 /* Schedule a message to ourselves to
5679 remove the blocking lock record and
5680 return the right error. */
5682 if (!blocking_lock_cancel(fsp,
5688 NT_STATUS_FILE_LOCK_CONFLICT)) {
5689 END_PROFILE(SMBlockingX);
5690 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5693 /* Remove a matching pending lock. */
5694 status = do_lock_cancel(fsp,
5700 BOOL blocking_lock = lock_timeout ? True : False;
5701 BOOL defer_lock = False;
5702 struct byte_range_lock *br_lck;
5703 uint32 block_smbpid;
5705 br_lck = do_lock(smbd_messaging_context(),
5716 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5717 /* Windows internal resolution for blocking locks seems
5718 to be about 200ms... Don't wait for less than that. JRA. */
5719 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5720 lock_timeout = lp_lock_spin_time();
5725 /* This heuristic seems to match W2K3 very well. If a
5726 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5727 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5728 far as I can tell. Replacement for do_lock_spin(). JRA. */
5730 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5731 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5733 lock_timeout = lp_lock_spin_time();
5736 if (br_lck && defer_lock) {
5738 * A blocking lock was requested. Package up
5739 * this smb into a queued request and push it
5740 * onto the blocking lock queue.
5742 if(push_blocking_lock_request(br_lck,
5753 TALLOC_FREE(br_lck);
5754 END_PROFILE(SMBlockingX);
5759 TALLOC_FREE(br_lck);
5762 if (NT_STATUS_V(status)) {
5763 END_PROFILE(SMBlockingX);
5764 return ERROR_NT(status);
5768 /* If any of the above locks failed, then we must unlock
5769 all of the previous locks (X/Open spec). */
5771 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5775 * Ensure we don't do a remove on the lock that just failed,
5776 * as under POSIX rules, if we have a lock already there, we
5777 * will delete it (and we shouldn't) .....
5779 for(i--; i >= 0; i--) {
5780 lock_pid = get_lock_pid( data, i, large_file_format);
5781 count = get_lock_count( data, i, large_file_format);
5782 offset = get_lock_offset( data, i, large_file_format,
5786 * There is no error code marked "stupid client
5790 END_PROFILE(SMBlockingX);
5791 return ERROR_DOS(ERRDOS,ERRnoaccess);
5794 do_unlock(smbd_messaging_context(),
5801 END_PROFILE(SMBlockingX);
5802 return ERROR_NT(status);
5805 set_message(inbuf,outbuf,2,0,True);
5807 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5808 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5810 END_PROFILE(SMBlockingX);
5811 return chain_reply(inbuf,&outbuf,length,bufsize);
5815 #define DBGC_CLASS DBGC_ALL
5817 /****************************************************************************
5818 Reply to a SMBreadbmpx (read block multiplex) request.
5819 ****************************************************************************/
5821 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5832 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5833 START_PROFILE(SMBreadBmpx);
5835 /* this function doesn't seem to work - disable by default */
5836 if (!lp_readbmpx()) {
5837 END_PROFILE(SMBreadBmpx);
5838 return ERROR_DOS(ERRSRV,ERRuseSTD);
5841 outsize = set_message(inbuf,outbuf,8,0,True);
5843 CHECK_FSP(fsp,conn);
5844 if (!CHECK_READ(fsp,inbuf)) {
5845 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5848 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5849 maxcount = SVAL(inbuf,smb_vwv3);
5851 data = smb_buf(outbuf);
5852 pad = ((long)data)%4;
5857 max_per_packet = bufsize-(outsize+pad);
5861 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5862 END_PROFILE(SMBreadBmpx);
5863 return ERROR_DOS(ERRDOS,ERRlock);
5867 size_t N = MIN(max_per_packet,tcount-total_read);
5869 nread = read_file(fsp,data,startpos,N);
5874 if (nread < (ssize_t)N)
5875 tcount = total_read + nread;
5877 set_message(inbuf,outbuf,8,nread+pad,False);
5878 SIVAL(outbuf,smb_vwv0,startpos);
5879 SSVAL(outbuf,smb_vwv2,tcount);
5880 SSVAL(outbuf,smb_vwv6,nread);
5881 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5884 if (!send_smb(smbd_server_fd(),outbuf))
5885 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5887 total_read += nread;
5889 } while (total_read < (ssize_t)tcount);
5891 END_PROFILE(SMBreadBmpx);
5895 /****************************************************************************
5896 Reply to a SMBsetattrE.
5897 ****************************************************************************/
5899 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5901 struct timespec ts[2];
5903 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5904 START_PROFILE(SMBsetattrE);
5906 outsize = set_message(inbuf,outbuf,0,0,False);
5908 if(!fsp || (fsp->conn != conn)) {
5909 END_PROFILE(SMBsetattrE);
5910 return ERROR_DOS(ERRDOS,ERRbadfid);
5914 * Convert the DOS times into unix times. Ignore create
5915 * time as UNIX can't set this.
5918 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5919 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5922 * Patch from Ray Frush <frush@engr.colostate.edu>
5923 * Sometimes times are sent as zero - ignore them.
5926 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5927 /* Ignore request */
5928 if( DEBUGLVL( 3 ) ) {
5929 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5930 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5932 END_PROFILE(SMBsetattrE);
5934 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5935 /* set modify time = to access time if modify time was unset */
5939 /* Set the date on this file */
5940 /* Should we set pending modtime here ? JRA */
5941 if(file_ntimes(conn, fsp->fsp_name, ts)) {
5942 END_PROFILE(SMBsetattrE);
5943 return ERROR_DOS(ERRDOS,ERRnoaccess);
5946 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5948 (unsigned int)ts[0].tv_sec,
5949 (unsigned int)ts[1].tv_sec));
5951 END_PROFILE(SMBsetattrE);
5956 /* Back from the dead for OS/2..... JRA. */
5958 /****************************************************************************
5959 Reply to a SMBwritebmpx (write block multiplex primary) request.
5960 ****************************************************************************/
5962 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5965 ssize_t nwritten = -1;
5972 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5974 START_PROFILE(SMBwriteBmpx);
5976 CHECK_FSP(fsp,conn);
5977 if (!CHECK_WRITE(fsp)) {
5978 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5980 if (HAS_CACHED_ERROR(fsp)) {
5981 return(CACHED_ERROR(fsp));
5984 tcount = SVAL(inbuf,smb_vwv1);
5985 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5986 write_through = BITSETW(inbuf+smb_vwv7,0);
5987 numtowrite = SVAL(inbuf,smb_vwv10);
5988 smb_doff = SVAL(inbuf,smb_vwv11);
5990 data = smb_base(inbuf) + smb_doff;
5992 /* If this fails we need to send an SMBwriteC response,
5993 not an SMBwritebmpx - set this up now so we don't forget */
5994 SCVAL(outbuf,smb_com,SMBwritec);
5996 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5997 END_PROFILE(SMBwriteBmpx);
5998 return(ERROR_DOS(ERRDOS,ERRlock));
6001 nwritten = write_file(fsp,data,startpos,numtowrite);
6003 status = sync_file(conn, fsp, write_through);
6004 if (!NT_STATUS_IS_OK(status)) {
6005 END_PROFILE(SMBwriteBmpx);
6006 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
6007 fsp->fsp_name, nt_errstr(status) ));
6008 return ERROR_NT(status);
6011 if(nwritten < (ssize_t)numtowrite) {
6012 END_PROFILE(SMBwriteBmpx);
6013 return(UNIXERROR(ERRHRD,ERRdiskfull));
6016 /* If the maximum to be written to this file
6017 is greater than what we just wrote then set
6018 up a secondary struct to be attached to this
6019 fd, we will use this to cache error messages etc. */
6021 if((ssize_t)tcount > nwritten) {
6022 write_bmpx_struct *wbms;
6023 if(fsp->wbmpx_ptr != NULL)
6024 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
6026 wbms = SMB_MALLOC_P(write_bmpx_struct);
6028 DEBUG(0,("Out of memory in reply_readmpx\n"));
6029 END_PROFILE(SMBwriteBmpx);
6030 return(ERROR_DOS(ERRSRV,ERRnoresource));
6032 wbms->wr_mode = write_through;
6033 wbms->wr_discard = False; /* No errors yet */
6034 wbms->wr_total_written = nwritten;
6035 wbms->wr_errclass = 0;
6037 fsp->wbmpx_ptr = wbms;
6040 /* We are returning successfully, set the message type back to
6042 SCVAL(outbuf,smb_com,SMBwriteBmpx);
6044 outsize = set_message(inbuf,outbuf,1,0,True);
6046 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
6048 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
6049 fsp->fnum, (int)numtowrite, (int)nwritten ) );
6051 if (write_through && tcount==nwritten) {
6052 /* We need to send both a primary and a secondary response */
6053 smb_setlen(inbuf,outbuf,outsize - 4);
6055 if (!send_smb(smbd_server_fd(),outbuf))
6056 exit_server_cleanly("reply_writebmpx: send_smb failed.");
6058 /* Now the secondary */
6059 outsize = set_message(inbuf,outbuf,1,0,True);
6060 SCVAL(outbuf,smb_com,SMBwritec);
6061 SSVAL(outbuf,smb_vwv0,nwritten);
6064 END_PROFILE(SMBwriteBmpx);
6068 /****************************************************************************
6069 Reply to a SMBwritebs (write block multiplex secondary) request.
6070 ****************************************************************************/
6072 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
6075 ssize_t nwritten = -1;
6082 write_bmpx_struct *wbms;
6083 BOOL send_response = False;
6084 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
6086 START_PROFILE(SMBwriteBs);
6088 CHECK_FSP(fsp,conn);
6089 if (!CHECK_WRITE(fsp)) {
6090 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6093 tcount = SVAL(inbuf,smb_vwv1);
6094 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6095 numtowrite = SVAL(inbuf,smb_vwv6);
6096 smb_doff = SVAL(inbuf,smb_vwv7);
6098 data = smb_base(inbuf) + smb_doff;
6100 /* We need to send an SMBwriteC response, not an SMBwritebs */
6101 SCVAL(outbuf,smb_com,SMBwritec);
6103 /* This fd should have an auxiliary struct attached,
6104 check that it does */
6105 wbms = fsp->wbmpx_ptr;
6107 END_PROFILE(SMBwriteBs);
6111 /* If write through is set we can return errors, else we must cache them */
6112 write_through = wbms->wr_mode;
6114 /* Check for an earlier error */
6115 if(wbms->wr_discard) {
6116 END_PROFILE(SMBwriteBs);
6117 return -1; /* Just discard the packet */
6120 nwritten = write_file(fsp,data,startpos,numtowrite);
6122 status = sync_file(conn, fsp, write_through);
6124 if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6126 /* We are returning an error - we can delete the aux struct */
6129 fsp->wbmpx_ptr = NULL;
6130 END_PROFILE(SMBwriteBs);
6131 return(ERROR_DOS(ERRHRD,ERRdiskfull));
6133 wbms->wr_errclass = ERRHRD;
6134 wbms->wr_error = ERRdiskfull;
6135 wbms->wr_status = NT_STATUS_DISK_FULL;
6136 wbms->wr_discard = True;
6137 END_PROFILE(SMBwriteBs);
6141 /* Increment the total written, if this matches tcount
6142 we can discard the auxiliary struct (hurrah !) and return a writeC */
6143 wbms->wr_total_written += nwritten;
6144 if(wbms->wr_total_written >= tcount) {
6145 if (write_through) {
6146 outsize = set_message(inbuf,outbuf,1,0,True);
6147 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
6148 send_response = True;
6152 fsp->wbmpx_ptr = NULL;
6156 END_PROFILE(SMBwriteBs);
6160 END_PROFILE(SMBwriteBs);
6164 /****************************************************************************
6165 Reply to a SMBgetattrE.
6166 ****************************************************************************/
6168 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6170 SMB_STRUCT_STAT sbuf;
6173 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
6174 START_PROFILE(SMBgetattrE);
6176 outsize = set_message(inbuf,outbuf,11,0,True);
6178 if(!fsp || (fsp->conn != conn)) {
6179 END_PROFILE(SMBgetattrE);
6180 return ERROR_DOS(ERRDOS,ERRbadfid);
6183 /* Do an fstat on this file */
6184 if(fsp_stat(fsp, &sbuf)) {
6185 END_PROFILE(SMBgetattrE);
6186 return(UNIXERROR(ERRDOS,ERRnoaccess));
6189 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6192 * Convert the times into dos times. Set create
6193 * date to be last modify date as UNIX doesn't save
6197 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6198 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6199 /* Should we check pending modtime here ? JRA */
6200 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6203 SIVAL(outbuf,smb_vwv6,0);
6204 SIVAL(outbuf,smb_vwv8,0);
6206 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6207 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6208 SIVAL(outbuf,smb_vwv8,allocation_size);
6210 SSVAL(outbuf,smb_vwv10, mode);
6212 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6214 END_PROFILE(SMBgetattrE);