2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
32 unsigned int smb_echo_count = 0;
33 extern uint32 global_client_caps;
35 extern struct current_user current_user;
36 extern BOOL global_encrypted_passwords_negotiated;
38 /****************************************************************************
39 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
40 path or anything including wildcards.
41 We're assuming here that '/' is not the second byte in any multibyte char
42 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44 ****************************************************************************/
46 /* Custom version for processing POSIX paths. */
47 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
49 static NTSTATUS check_path_syntax_internal(char *path,
51 BOOL *p_last_component_contains_wcard)
55 NTSTATUS ret = NT_STATUS_OK;
56 BOOL start_of_name_component = True;
58 *p_last_component_contains_wcard = False;
61 if (IS_PATH_SEP(*s,posix_path)) {
63 * Safe to assume is not the second part of a mb char
64 * as this is handled below.
66 /* Eat multiple '/' or '\\' */
67 while (IS_PATH_SEP(*s,posix_path)) {
70 if ((d != path) && (*s != '\0')) {
71 /* We only care about non-leading or trailing '/' or '\\' */
75 start_of_name_component = True;
77 *p_last_component_contains_wcard = False;
81 if (start_of_name_component) {
82 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
83 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
86 * No mb char starts with '.' so we're safe checking the directory separator here.
89 /* If we just added a '/' - delete it */
90 if ((d > path) && (*(d-1) == '/')) {
95 /* Are we at the start ? Can't go back further if so. */
97 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
100 /* Go back one level... */
101 /* We know this is safe as '/' cannot be part of a mb sequence. */
102 /* NOTE - if this assumption is invalid we are not in good shape... */
103 /* Decrement d first as d points to the *next* char to write into. */
104 for (d--; d > path; d--) {
108 s += 2; /* Else go past the .. */
109 /* We're still at the start of a name component, just the previous one. */
112 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
125 return NT_STATUS_OBJECT_NAME_INVALID;
133 *p_last_component_contains_wcard = True;
142 /* Get the size of the next MB character. */
143 next_codepoint(s,&siz);
161 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
163 return NT_STATUS_INVALID_PARAMETER;
166 start_of_name_component = False;
173 /****************************************************************************
174 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
175 No wildcards allowed.
176 ****************************************************************************/
178 NTSTATUS check_path_syntax(char *path)
181 return check_path_syntax_internal(path, False, &ignore);
184 /****************************************************************************
185 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
186 Wildcards allowed - p_contains_wcard returns true if the last component contained
188 ****************************************************************************/
190 NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
192 return check_path_syntax_internal(path, False, p_contains_wcard);
195 /****************************************************************************
196 Check the path for a POSIX client.
197 We're assuming here that '/' is not the second byte in any multibyte char
198 set (a safe assumption).
199 ****************************************************************************/
201 NTSTATUS check_path_syntax_posix(char *path)
204 return check_path_syntax_internal(path, True, &ignore);
207 /****************************************************************************
208 Pull a string and check the path allowing a wilcard - provide for error return.
209 ****************************************************************************/
211 size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest,
212 const char *src, size_t dest_len, size_t src_len,
213 int flags, NTSTATUS *err, BOOL *contains_wcard)
217 SMB_ASSERT(dest_len == sizeof(pstring));
221 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
224 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
225 dest_len, src_len, flags);
228 *contains_wcard = False;
230 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
232 * For a DFS path the function parse_dfs_path()
233 * will do the path processing, just make a copy.
239 if (lp_posix_pathnames()) {
240 *err = check_path_syntax_posix(dest);
242 *err = check_path_syntax_wcard(dest, contains_wcard);
248 /****************************************************************************
249 Pull a string and check the path - provide for error return.
250 ****************************************************************************/
252 size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest,
253 const char *src, size_t dest_len, size_t src_len,
254 int flags, NTSTATUS *err)
258 SMB_ASSERT(dest_len == sizeof(pstring));
262 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
265 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
266 dest_len, src_len, flags);
269 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
271 * For a DFS path the function parse_dfs_path()
272 * will do the path processing, just make a copy.
278 if (lp_posix_pathnames()) {
279 *err = check_path_syntax_posix(dest);
281 *err = check_path_syntax(dest);
287 /****************************************************************************
288 Reply to a (netbios-level) special message.
289 ****************************************************************************/
291 void reply_special(char *inbuf)
293 int msg_type = CVAL(inbuf,0);
294 int msg_flags = CVAL(inbuf,1);
299 * We only really use 4 bytes of the outbuf, but for the smb_setlen
300 * calculation & friends (send_smb uses that) we need the full smb
303 char outbuf[smb_size];
305 static BOOL already_got_session = False;
309 memset(outbuf, '\0', sizeof(outbuf));
311 smb_setlen(inbuf,outbuf,0);
314 case 0x81: /* session request */
316 if (already_got_session) {
317 exit_server_cleanly("multiple session request not permitted");
320 SCVAL(outbuf,0,0x82);
322 if (name_len(inbuf+4) > 50 ||
323 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
324 DEBUG(0,("Invalid name length in session request\n"));
327 name_extract(inbuf,4,name1);
328 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
329 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
332 set_local_machine_name(name1, True);
333 set_remote_machine_name(name2, True);
335 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
336 get_local_machine_name(), get_remote_machine_name(),
339 if (name_type == 'R') {
340 /* We are being asked for a pathworks session ---
342 SCVAL(outbuf, 0,0x83);
346 /* only add the client's machine name to the list
347 of possibly valid usernames if we are operating
348 in share mode security */
349 if (lp_security() == SEC_SHARE) {
350 add_session_user(get_remote_machine_name());
353 reload_services(True);
356 already_got_session = True;
359 case 0x89: /* session keepalive request
360 (some old clients produce this?) */
361 SCVAL(outbuf,0,SMBkeepalive);
365 case 0x82: /* positive session response */
366 case 0x83: /* negative session response */
367 case 0x84: /* retarget session response */
368 DEBUG(0,("Unexpected session response\n"));
371 case SMBkeepalive: /* session keepalive */
376 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
377 msg_type, msg_flags));
379 send_smb(smbd_server_fd(), outbuf);
383 /****************************************************************************
385 conn POINTER CAN BE NULL HERE !
386 ****************************************************************************/
388 int reply_tcon(connection_struct *conn,
389 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
393 char *service_buf = NULL;
394 char *password = NULL;
397 uint16 vuid = SVAL(inbuf,smb_uid);
401 DATA_BLOB password_blob;
403 START_PROFILE(SMBtcon);
405 ctx = talloc_init("reply_tcon");
407 END_PROFILE(SMBtcon);
408 return ERROR_NT(NT_STATUS_NO_MEMORY);
411 p = smb_buf(inbuf)+1;
412 p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
413 &service_buf, p, STR_TERMINATE) + 1;
414 pwlen = srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
415 &password, p, STR_TERMINATE) + 1;
417 p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
418 &dev, p, STR_TERMINATE) + 1;
420 if (service_buf == NULL || password == NULL || dev == NULL) {
422 END_PROFILE(SMBtcon);
423 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
425 p = strrchr_m(service_buf,'\\');
429 service = service_buf;
432 password_blob = data_blob(password, pwlen+1);
434 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
436 data_blob_clear_free(&password_blob);
440 END_PROFILE(SMBtcon);
441 return ERROR_NT(nt_status);
444 outsize = set_message(inbuf,outbuf,2,0,True);
445 SSVAL(outbuf,smb_vwv0,max_recv);
446 SSVAL(outbuf,smb_vwv1,conn->cnum);
447 SSVAL(outbuf,smb_tid,conn->cnum);
449 DEBUG(3,("tcon service=%s cnum=%d\n",
450 service, conn->cnum));
452 END_PROFILE(SMBtcon);
457 /****************************************************************************
458 Reply to a tcon and X.
459 conn POINTER CAN BE NULL HERE !
460 ****************************************************************************/
462 void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
464 char *service = NULL;
467 TALLOC_CTX *ctx = NULL;
468 /* what the cleint thinks the device is */
469 char *client_devicetype = NULL;
470 /* what the server tells the client the share represents */
471 const char *server_devicetype;
478 START_PROFILE(SMBtconX);
481 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
482 END_PROFILE(SMBtconX);
486 passlen = SVAL(req->inbuf,smb_vwv3);
487 tcon_flags = SVAL(req->inbuf,smb_vwv2);
489 /* we might have to close an old one */
490 if ((tcon_flags & 0x1) && conn) {
491 close_cnum(conn,req->vuid);
494 if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
495 reply_doserror(req, ERRDOS, ERRbuftoosmall);
496 END_PROFILE(SMBtconX);
500 if (global_encrypted_passwords_negotiated) {
501 password = data_blob(smb_buf(req->inbuf),passlen);
502 if (lp_security() == SEC_SHARE) {
504 * Security = share always has a pad byte
505 * after the password.
507 p = smb_buf(req->inbuf) + passlen + 1;
509 p = smb_buf(req->inbuf) + passlen;
512 password = data_blob(smb_buf(req->inbuf),passlen+1);
513 /* Ensure correct termination */
514 password.data[passlen]=0;
515 p = smb_buf(req->inbuf) + passlen + 1;
518 ctx = talloc_init("reply_tcon_and_X");
520 data_blob_clear_free(&password);
521 reply_nterror(req, NT_STATUS_NO_MEMORY);
522 END_PROFILE(SMBtconX);
525 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
529 data_blob_clear_free(&password);
531 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
532 END_PROFILE(SMBtconX);
537 * the service name can be either: \\server\share
538 * or share directly like on the DELL PowerVault 705
541 q = strchr_m(path+2,'\\');
543 data_blob_clear_free(&password);
545 reply_doserror(req, ERRDOS, ERRnosuchshare);
546 END_PROFILE(SMBtconX);
554 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
555 &client_devicetype, p,
556 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
558 if (client_devicetype == NULL) {
559 data_blob_clear_free(&password);
561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
562 END_PROFILE(SMBtconX);
566 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
568 conn = make_connection(service, password, client_devicetype,
569 req->vuid, &nt_status);
571 data_blob_clear_free(&password);
575 reply_nterror(req, nt_status);
576 END_PROFILE(SMBtconX);
581 server_devicetype = "IPC";
582 else if ( IS_PRINT(conn) )
583 server_devicetype = "LPT1:";
585 server_devicetype = "A:";
587 if (Protocol < PROTOCOL_NT1) {
588 reply_outbuf(req, 2, 0);
589 if (message_push_string(&req->outbuf, server_devicetype,
590 STR_TERMINATE|STR_ASCII) == -1) {
592 reply_nterror(req, NT_STATUS_NO_MEMORY);
593 END_PROFILE(SMBtconX);
597 /* NT sets the fstype of IPC$ to the null string */
598 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
600 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
601 /* Return permissions. */
605 reply_outbuf(req, 7, 0);
608 perm1 = FILE_ALL_ACCESS;
609 perm2 = FILE_ALL_ACCESS;
611 perm1 = CAN_WRITE(conn) ?
616 SIVAL(req->outbuf, smb_vwv3, perm1);
617 SIVAL(req->outbuf, smb_vwv5, perm2);
619 reply_outbuf(req, 3, 0);
622 if ((message_push_string(&req->outbuf, server_devicetype,
623 STR_TERMINATE|STR_ASCII) == -1)
624 || (message_push_string(&req->outbuf, fstype,
625 STR_TERMINATE) == -1)) {
627 reply_nterror(req, NT_STATUS_NO_MEMORY);
628 END_PROFILE(SMBtconX);
632 /* what does setting this bit do? It is set by NT4 and
633 may affect the ability to autorun mounted cdroms */
634 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
635 (lp_csc_policy(SNUM(conn)) << 2));
637 init_dfsroot(conn, req->inbuf, req->outbuf);
641 DEBUG(3,("tconX service=%s \n",
644 /* set the incoming and outgoing tid to the just created one */
645 SSVAL(req->inbuf,smb_tid,conn->cnum);
646 SSVAL(req->outbuf,smb_tid,conn->cnum);
649 END_PROFILE(SMBtconX);
651 chain_reply_new(req);
655 /****************************************************************************
656 Reply to an unknown type.
657 ****************************************************************************/
659 int reply_unknown(char *inbuf,char *outbuf)
662 type = CVAL(inbuf,smb_com);
664 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
665 smb_fn_name(type), type, type));
667 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
670 void reply_unknown_new(struct smb_request *req, uint8 type)
672 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
673 smb_fn_name(type), type, type));
674 reply_doserror(req, ERRSRV, ERRunknownsmb);
678 /****************************************************************************
680 conn POINTER CAN BE NULL HERE !
681 ****************************************************************************/
683 int reply_ioctl(connection_struct *conn,
684 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
686 uint16 device = SVAL(inbuf,smb_vwv1);
687 uint16 function = SVAL(inbuf,smb_vwv2);
688 uint32 ioctl_code = (device << 16) + function;
689 int replysize, outsize;
691 START_PROFILE(SMBioctl);
693 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
695 switch (ioctl_code) {
696 case IOCTL_QUERY_JOB_INFO:
700 END_PROFILE(SMBioctl);
701 return(ERROR_DOS(ERRSRV,ERRnosupport));
704 outsize = set_message(inbuf,outbuf,8,replysize+1,True);
705 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
706 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
707 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
708 p = smb_buf(outbuf) + 1; /* Allow for alignment */
710 switch (ioctl_code) {
711 case IOCTL_QUERY_JOB_INFO:
713 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
715 END_PROFILE(SMBioctl);
716 return(UNIXERROR(ERRDOS,ERRbadfid));
718 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
719 srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+2,
721 STR_TERMINATE|STR_ASCII);
723 srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
724 p+18, lp_servicename(SNUM(conn)),
725 13, STR_TERMINATE|STR_ASCII);
731 END_PROFILE(SMBioctl);
735 /****************************************************************************
736 Strange checkpath NTSTATUS mapping.
737 ****************************************************************************/
739 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
741 /* Strange DOS error code semantics only for checkpath... */
742 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
743 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
744 /* We need to map to ERRbadpath */
745 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
751 /****************************************************************************
752 Reply to a checkpath.
753 ****************************************************************************/
755 void reply_checkpath(connection_struct *conn, struct smb_request *req)
758 SMB_STRUCT_STAT sbuf;
761 START_PROFILE(SMBcheckpath);
763 srvstr_get_path((char *)req->inbuf, req->flags2, name,
764 smb_buf(req->inbuf) + 1, sizeof(name), 0,
765 STR_TERMINATE, &status);
766 if (!NT_STATUS_IS_OK(status)) {
767 status = map_checkpath_error((char *)req->inbuf, status);
768 reply_nterror(req, status);
769 END_PROFILE(SMBcheckpath);
773 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name);
774 if (!NT_STATUS_IS_OK(status)) {
775 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
776 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
778 END_PROFILE(SMBcheckpath);
784 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
786 status = unix_convert(conn, name, False, NULL, &sbuf);
787 if (!NT_STATUS_IS_OK(status)) {
791 status = check_name(conn, name);
792 if (!NT_STATUS_IS_OK(status)) {
793 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
797 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
798 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
799 status = map_nt_error_from_unix(errno);
803 if (!S_ISDIR(sbuf.st_mode)) {
804 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
806 END_PROFILE(SMBcheckpath);
810 reply_outbuf(req, 0, 0);
812 END_PROFILE(SMBcheckpath);
817 END_PROFILE(SMBcheckpath);
819 /* We special case this - as when a Windows machine
820 is parsing a path is steps through the components
821 one at a time - if a component fails it expects
822 ERRbadpath, not ERRbadfile.
824 status = map_checkpath_error((char *)req->inbuf, status);
825 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
827 * Windows returns different error codes if
828 * the parent directory is valid but not the
829 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
830 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
831 * if the path is invalid.
833 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
838 reply_nterror(req, status);
841 /****************************************************************************
843 ****************************************************************************/
845 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
849 SMB_STRUCT_STAT sbuf;
856 START_PROFILE(SMBgetatr);
858 p = smb_buf(inbuf) + 1;
859 p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
860 sizeof(fname), 0, STR_TERMINATE, &status);
861 if (!NT_STATUS_IS_OK(status)) {
862 END_PROFILE(SMBgetatr);
863 return ERROR_NT(status);
866 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
867 if (!NT_STATUS_IS_OK(status)) {
868 END_PROFILE(SMBgetatr);
869 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
870 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
872 return ERROR_NT(status);
875 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
876 under WfWg - weird! */
877 if (*fname == '\0') {
878 mode = aHIDDEN | aDIR;
879 if (!CAN_WRITE(conn)) {
885 status = unix_convert(conn, fname, False, NULL,&sbuf);
886 if (!NT_STATUS_IS_OK(status)) {
887 END_PROFILE(SMBgetatr);
888 return ERROR_NT(status);
890 status = check_name(conn, fname);
891 if (!NT_STATUS_IS_OK(status)) {
892 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
893 END_PROFILE(SMBgetatr);
894 return ERROR_NT(status);
896 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
897 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
898 return UNIXERROR(ERRDOS,ERRbadfile);
901 mode = dos_mode(conn,fname,&sbuf);
903 mtime = sbuf.st_mtime;
909 outsize = set_message(inbuf,outbuf,10,0,True);
911 SSVAL(outbuf,smb_vwv0,mode);
912 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
913 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
915 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
917 SIVAL(outbuf,smb_vwv3,(uint32)size);
919 if (Protocol >= PROTOCOL_NT1) {
920 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
923 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
925 END_PROFILE(SMBgetatr);
929 /****************************************************************************
931 ****************************************************************************/
933 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
939 SMB_STRUCT_STAT sbuf;
943 START_PROFILE(SMBsetatr);
945 p = smb_buf(inbuf) + 1;
946 p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
947 sizeof(fname), 0, STR_TERMINATE, &status);
948 if (!NT_STATUS_IS_OK(status)) {
949 END_PROFILE(SMBsetatr);
950 return ERROR_NT(status);
953 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
954 if (!NT_STATUS_IS_OK(status)) {
955 END_PROFILE(SMBsetatr);
956 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
957 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
959 return ERROR_NT(status);
962 status = unix_convert(conn, fname, False, NULL, &sbuf);
963 if (!NT_STATUS_IS_OK(status)) {
964 END_PROFILE(SMBsetatr);
965 return ERROR_NT(status);
968 status = check_name(conn, fname);
969 if (!NT_STATUS_IS_OK(status)) {
970 END_PROFILE(SMBsetatr);
971 return ERROR_NT(status);
974 if (fname[0] == '.' && fname[1] == '\0') {
976 * Not sure here is the right place to catch this
977 * condition. Might be moved to somewhere else later -- vl
979 END_PROFILE(SMBsetatr);
980 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
983 mode = SVAL(inbuf,smb_vwv0);
984 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
986 if (mode != FILE_ATTRIBUTE_NORMAL) {
987 if (VALID_STAT_OF_DIR(sbuf))
992 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
993 END_PROFILE(SMBsetatr);
994 return UNIXERROR(ERRDOS, ERRnoaccess);
998 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
999 END_PROFILE(SMBsetatr);
1000 return UNIXERROR(ERRDOS, ERRnoaccess);
1003 outsize = set_message(inbuf,outbuf,0,0,False);
1005 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1007 END_PROFILE(SMBsetatr);
1011 /****************************************************************************
1013 ****************************************************************************/
1015 void reply_dskattr(connection_struct *conn, struct smb_request *req)
1017 SMB_BIG_UINT dfree,dsize,bsize;
1018 START_PROFILE(SMBdskattr);
1020 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1021 reply_unixerror(req, ERRHRD, ERRgeneral);
1022 END_PROFILE(SMBdskattr);
1026 reply_outbuf(req, 5, 0);
1028 if (Protocol <= PROTOCOL_LANMAN2) {
1029 double total_space, free_space;
1030 /* we need to scale this to a number that DOS6 can handle. We
1031 use floating point so we can handle large drives on systems
1032 that don't have 64 bit integers
1034 we end up displaying a maximum of 2G to DOS systems
1036 total_space = dsize * (double)bsize;
1037 free_space = dfree * (double)bsize;
1039 dsize = (total_space+63*512) / (64*512);
1040 dfree = (free_space+63*512) / (64*512);
1042 if (dsize > 0xFFFF) dsize = 0xFFFF;
1043 if (dfree > 0xFFFF) dfree = 0xFFFF;
1045 SSVAL(req->outbuf,smb_vwv0,dsize);
1046 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1047 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1048 SSVAL(req->outbuf,smb_vwv3,dfree);
1050 SSVAL(req->outbuf,smb_vwv0,dsize);
1051 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1052 SSVAL(req->outbuf,smb_vwv2,512);
1053 SSVAL(req->outbuf,smb_vwv3,dfree);
1056 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1058 END_PROFILE(SMBdskattr);
1062 /****************************************************************************
1064 Can be called from SMBsearch, SMBffirst or SMBfunique.
1065 ****************************************************************************/
1067 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1077 unsigned int numentries = 0;
1078 unsigned int maxentries = 0;
1079 BOOL finished = False;
1085 BOOL check_descend = False;
1086 BOOL expect_close = False;
1088 BOOL mask_contains_wcard = False;
1089 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1091 START_PROFILE(SMBsearch);
1093 if (lp_posix_pathnames()) {
1094 END_PROFILE(SMBsearch);
1095 return reply_unknown(inbuf, outbuf);
1098 *mask = *directory = *fname = 0;
1100 /* If we were called as SMBffirst then we must expect close. */
1101 if(CVAL(inbuf,smb_com) == SMBffirst) {
1102 expect_close = True;
1105 outsize = set_message(inbuf,outbuf,1,3,True);
1106 maxentries = SVAL(inbuf,smb_vwv0);
1107 dirtype = SVAL(inbuf,smb_vwv1);
1108 p = smb_buf(inbuf) + 1;
1109 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1110 sizeof(path), 0, STR_TERMINATE, &nt_status,
1111 &mask_contains_wcard);
1112 if (!NT_STATUS_IS_OK(nt_status)) {
1113 END_PROFILE(SMBsearch);
1114 return ERROR_NT(nt_status);
1117 nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
1118 if (!NT_STATUS_IS_OK(nt_status)) {
1119 END_PROFILE(SMBsearch);
1120 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1121 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1123 return ERROR_NT(nt_status);
1127 status_len = SVAL(p, 0);
1130 /* dirtype &= ~aDIR; */
1132 if (status_len == 0) {
1133 SMB_STRUCT_STAT sbuf;
1135 pstrcpy(directory,path);
1136 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1137 if (!NT_STATUS_IS_OK(nt_status)) {
1138 END_PROFILE(SMBsearch);
1139 return ERROR_NT(nt_status);
1142 nt_status = check_name(conn, directory);
1143 if (!NT_STATUS_IS_OK(nt_status)) {
1144 END_PROFILE(SMBsearch);
1145 return ERROR_NT(nt_status);
1148 p = strrchr_m(directory,'/');
1150 pstrcpy(mask,directory);
1151 pstrcpy(directory,".");
1157 if (*directory == '\0') {
1158 pstrcpy(directory,".");
1160 memset((char *)status,'\0',21);
1161 SCVAL(status,0,(dirtype & 0x1F));
1165 memcpy(status,p,21);
1166 status_dirtype = CVAL(status,0) & 0x1F;
1167 if (status_dirtype != (dirtype & 0x1F)) {
1168 dirtype = status_dirtype;
1171 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1172 if (!conn->dirptr) {
1175 string_set(&conn->dirpath,dptr_path(dptr_num));
1176 pstrcpy(mask, dptr_wcard(dptr_num));
1178 * For a 'continue' search we have no string. So
1179 * check from the initial saved string.
1181 mask_contains_wcard = ms_has_wild(mask);
1184 p = smb_buf(outbuf) + 3;
1186 if (status_len == 0) {
1187 nt_status = dptr_create(conn,
1191 SVAL(inbuf,smb_pid),
1193 mask_contains_wcard,
1196 if (!NT_STATUS_IS_OK(nt_status)) {
1197 return ERROR_NT(nt_status);
1199 dptr_num = dptr_dnum(conn->dirptr);
1201 dirtype = dptr_attr(dptr_num);
1204 DEBUG(4,("dptr_num is %d\n",dptr_num));
1206 if ((dirtype&0x1F) == aVOLID) {
1207 memcpy(p,status,21);
1208 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1209 0,aVOLID,0,!allow_long_path_components);
1210 dptr_fill(p+12,dptr_num);
1211 if (dptr_zero(p+12) && (status_len==0)) {
1216 p += DIR_STRUCT_SIZE;
1219 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1221 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1222 conn->dirpath,lp_dontdescend(SNUM(conn))));
1223 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1224 check_descend = True;
1227 for (i=numentries;(i<maxentries) && !finished;i++) {
1228 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1230 memcpy(p,status,21);
1231 make_dir_struct(p,mask,fname,size, mode,date,
1232 !allow_long_path_components);
1233 if (!dptr_fill(p+12,dptr_num)) {
1237 p += DIR_STRUCT_SIZE;
1244 /* If we were called as SMBffirst with smb_search_id == NULL
1245 and no entries were found then return error and close dirptr
1248 if (numentries == 0) {
1249 dptr_close(&dptr_num);
1250 } else if(expect_close && status_len == 0) {
1251 /* Close the dptr - we know it's gone */
1252 dptr_close(&dptr_num);
1255 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1256 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1257 dptr_close(&dptr_num);
1260 if ((numentries == 0) && !mask_contains_wcard) {
1261 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1264 SSVAL(outbuf,smb_vwv0,numentries);
1265 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1266 SCVAL(smb_buf(outbuf),0,5);
1267 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1269 /* The replies here are never long name. */
1270 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1271 if (!allow_long_path_components) {
1272 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1275 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1276 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1278 outsize += DIR_STRUCT_SIZE*numentries;
1279 smb_setlen(inbuf,outbuf,outsize - 4);
1281 if ((! *directory) && dptr_path(dptr_num))
1282 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1284 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1285 smb_fn_name(CVAL(inbuf,smb_com)),
1286 mask, directory, dirtype, numentries, maxentries ) );
1288 END_PROFILE(SMBsearch);
1292 /****************************************************************************
1293 Reply to a fclose (stop directory search).
1294 ****************************************************************************/
1296 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1305 BOOL path_contains_wcard = False;
1307 START_PROFILE(SMBfclose);
1309 if (lp_posix_pathnames()) {
1310 END_PROFILE(SMBfclose);
1311 return reply_unknown(inbuf, outbuf);
1314 outsize = set_message(inbuf,outbuf,1,0,True);
1315 p = smb_buf(inbuf) + 1;
1316 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1317 sizeof(path), 0, STR_TERMINATE, &err,
1318 &path_contains_wcard);
1319 if (!NT_STATUS_IS_OK(err)) {
1320 END_PROFILE(SMBfclose);
1321 return ERROR_NT(err);
1324 status_len = SVAL(p,0);
1327 if (status_len == 0) {
1328 END_PROFILE(SMBfclose);
1329 return ERROR_DOS(ERRSRV,ERRsrverror);
1332 memcpy(status,p,21);
1334 if(dptr_fetch(status+12,&dptr_num)) {
1335 /* Close the dptr - we know it's gone */
1336 dptr_close(&dptr_num);
1339 SSVAL(outbuf,smb_vwv0,0);
1341 DEBUG(3,("search close\n"));
1343 END_PROFILE(SMBfclose);
1347 /****************************************************************************
1349 ****************************************************************************/
1351 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1359 SMB_STRUCT_STAT sbuf;
1361 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1363 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1366 uint32 create_disposition;
1367 uint32 create_options = 0;
1369 struct smb_request req;
1371 START_PROFILE(SMBopen);
1373 init_smb_request(&req, (uint8 *)inbuf);
1375 deny_mode = SVAL(inbuf,smb_vwv0);
1377 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1378 sizeof(fname), 0, STR_TERMINATE, &status);
1379 if (!NT_STATUS_IS_OK(status)) {
1380 END_PROFILE(SMBopen);
1381 return ERROR_NT(status);
1384 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1385 if (!NT_STATUS_IS_OK(status)) {
1386 END_PROFILE(SMBopen);
1387 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1388 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1390 return ERROR_NT(status);
1393 status = unix_convert(conn, fname, False, NULL, &sbuf);
1394 if (!NT_STATUS_IS_OK(status)) {
1395 END_PROFILE(SMBopen);
1396 return ERROR_NT(status);
1399 status = check_name(conn, fname);
1400 if (!NT_STATUS_IS_OK(status)) {
1401 END_PROFILE(SMBopen);
1402 return ERROR_NT(status);
1405 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1406 &access_mask, &share_mode, &create_disposition, &create_options)) {
1407 END_PROFILE(SMBopen);
1408 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1411 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1420 if (!NT_STATUS_IS_OK(status)) {
1421 END_PROFILE(SMBopen);
1422 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1423 /* We have re-scheduled this call. */
1426 return ERROR_NT(status);
1429 size = sbuf.st_size;
1430 fattr = dos_mode(conn,fname,&sbuf);
1431 mtime = sbuf.st_mtime;
1434 DEBUG(3,("attempt to open a directory %s\n",fname));
1435 close_file(fsp,ERROR_CLOSE);
1436 END_PROFILE(SMBopen);
1437 return ERROR_DOS(ERRDOS,ERRnoaccess);
1440 outsize = set_message(inbuf,outbuf,7,0,True);
1441 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1442 SSVAL(outbuf,smb_vwv1,fattr);
1443 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1444 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1446 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1448 SIVAL(outbuf,smb_vwv4,(uint32)size);
1449 SSVAL(outbuf,smb_vwv6,deny_mode);
1451 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1452 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1455 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1456 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1458 END_PROFILE(SMBopen);
1462 /****************************************************************************
1463 Reply to an open and X.
1464 ****************************************************************************/
1466 void reply_open_and_X(connection_struct *conn, struct smb_request *req)
1472 /* Breakout the oplock request bits so we can set the
1473 reply bits separately. */
1474 int ex_oplock_request;
1475 int core_oplock_request;
1478 int smb_sattr = SVAL(req->inbuf,smb_vwv4);
1479 uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
1484 SMB_STRUCT_STAT sbuf;
1488 SMB_BIG_UINT allocation_size;
1489 ssize_t retval = -1;
1492 uint32 create_disposition;
1493 uint32 create_options = 0;
1495 START_PROFILE(SMBopenX);
1497 if (req->wct < 15) {
1498 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1499 END_PROFILE(SMBopenX);
1503 open_flags = SVAL(req->inbuf,smb_vwv2);
1504 deny_mode = SVAL(req->inbuf,smb_vwv3);
1505 smb_attr = SVAL(req->inbuf,smb_vwv5);
1506 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1507 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1508 oplock_request = ex_oplock_request | core_oplock_request;
1509 smb_ofun = SVAL(req->inbuf,smb_vwv8);
1510 allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
1512 /* If it's an IPC, pass off the pipe handler. */
1514 if (lp_nt_pipe_support()) {
1515 reply_open_pipe_and_X(conn, req);
1517 reply_doserror(req, ERRSRV, ERRaccess);
1519 END_PROFILE(SMBopenX);
1523 /* XXXX we need to handle passed times, sattr and flags */
1524 srvstr_get_path((char *)req->inbuf, req->flags2, fname,
1525 smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE,
1527 if (!NT_STATUS_IS_OK(status)) {
1528 reply_nterror(req, status);
1529 END_PROFILE(SMBopenX);
1533 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1535 if (!NT_STATUS_IS_OK(status)) {
1536 END_PROFILE(SMBopenX);
1537 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1538 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1539 ERRSRV, ERRbadpath);
1542 reply_nterror(req, status);
1546 status = unix_convert(conn, fname, False, NULL, &sbuf);
1547 if (!NT_STATUS_IS_OK(status)) {
1548 reply_nterror(req, status);
1549 END_PROFILE(SMBopenX);
1553 status = check_name(conn, fname);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 reply_nterror(req, status);
1556 END_PROFILE(SMBopenX);
1560 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1563 &create_disposition,
1565 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1566 END_PROFILE(SMBopenX);
1570 status = open_file_ntcreate(conn, req, fname, &sbuf,
1579 if (!NT_STATUS_IS_OK(status)) {
1580 END_PROFILE(SMBopenX);
1581 if (open_was_deferred(req->mid)) {
1582 /* We have re-scheduled this call. */
1585 reply_nterror(req, status);
1589 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1590 if the file is truncated or created. */
1591 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1592 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1593 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1594 close_file(fsp,ERROR_CLOSE);
1595 reply_nterror(req, NT_STATUS_DISK_FULL);
1596 END_PROFILE(SMBopenX);
1599 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1601 close_file(fsp,ERROR_CLOSE);
1602 reply_nterror(req, NT_STATUS_DISK_FULL);
1603 END_PROFILE(SMBopenX);
1606 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1609 fattr = dos_mode(conn,fname,&sbuf);
1610 mtime = sbuf.st_mtime;
1612 close_file(fsp,ERROR_CLOSE);
1613 reply_doserror(req, ERRDOS, ERRnoaccess);
1614 END_PROFILE(SMBopenX);
1618 /* If the caller set the extended oplock request bit
1619 and we granted one (by whatever means) - set the
1620 correct bit for extended oplock reply.
1623 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1624 smb_action |= EXTENDED_OPLOCK_GRANTED;
1627 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1628 smb_action |= EXTENDED_OPLOCK_GRANTED;
1631 /* If the caller set the core oplock request bit
1632 and we granted one (by whatever means) - set the
1633 correct bit for core oplock reply.
1636 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1637 reply_outbuf(req, 19, 0);
1639 reply_outbuf(req, 15, 0);
1642 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1643 SCVAL(req->outbuf, smb_flg,
1644 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1647 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1648 SCVAL(req->outbuf, smb_flg,
1649 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1652 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1653 SSVAL(req->outbuf,smb_vwv3,fattr);
1654 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1655 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1657 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1659 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1660 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1661 SSVAL(req->outbuf,smb_vwv11,smb_action);
1663 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1664 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1667 END_PROFILE(SMBopenX);
1668 chain_reply_new(req);
1672 /****************************************************************************
1673 Reply to a SMBulogoffX.
1674 conn POINTER CAN BE NULL HERE !
1675 ****************************************************************************/
1677 void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
1681 START_PROFILE(SMBulogoffX);
1683 vuser = get_valid_user_struct(req->vuid);
1686 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1690 /* in user level security we are supposed to close any files
1691 open by this user */
1692 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1693 file_close_user(req->vuid);
1696 invalidate_vuid(req->vuid);
1698 reply_outbuf(req, 2, 0);
1700 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1702 END_PROFILE(SMBulogoffX);
1703 chain_reply_new(req);
1706 /****************************************************************************
1707 Reply to a mknew or a create.
1708 ****************************************************************************/
1710 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1715 uint32 fattr = SVAL(inbuf,smb_vwv0);
1716 struct timespec ts[2];
1718 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1719 SMB_STRUCT_STAT sbuf;
1721 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1722 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1723 uint32 create_disposition;
1724 uint32 create_options = 0;
1725 struct smb_request req;
1727 START_PROFILE(SMBcreate);
1729 init_smb_request(&req, (uint8 *)inbuf);
1731 com = SVAL(inbuf,smb_com);
1733 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1735 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1,
1736 sizeof(fname), 0, STR_TERMINATE, &status);
1737 if (!NT_STATUS_IS_OK(status)) {
1738 END_PROFILE(SMBcreate);
1739 return ERROR_NT(status);
1742 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1743 if (!NT_STATUS_IS_OK(status)) {
1744 END_PROFILE(SMBcreate);
1745 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1746 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1748 return ERROR_NT(status);
1751 status = unix_convert(conn, fname, False, NULL, &sbuf);
1752 if (!NT_STATUS_IS_OK(status)) {
1753 END_PROFILE(SMBcreate);
1754 return ERROR_NT(status);
1757 status = check_name(conn, fname);
1758 if (!NT_STATUS_IS_OK(status)) {
1759 END_PROFILE(SMBcreate);
1760 return ERROR_NT(status);
1763 if (fattr & aVOLID) {
1764 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1767 if(com == SMBmknew) {
1768 /* We should fail if file exists. */
1769 create_disposition = FILE_CREATE;
1771 /* Create if file doesn't exist, truncate if it does. */
1772 create_disposition = FILE_OVERWRITE_IF;
1775 /* Open file using ntcreate. */
1776 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1785 if (!NT_STATUS_IS_OK(status)) {
1786 END_PROFILE(SMBcreate);
1787 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1788 /* We have re-scheduled this call. */
1791 return ERROR_NT(status);
1794 ts[0] = get_atimespec(&sbuf); /* atime. */
1795 file_ntimes(conn, fname, ts);
1797 outsize = set_message(inbuf,outbuf,1,0,True);
1798 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1800 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1801 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1804 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1805 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1808 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1809 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1811 END_PROFILE(SMBcreate);
1815 /****************************************************************************
1816 Reply to a create temporary file.
1817 ****************************************************************************/
1819 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1823 uint32 fattr = SVAL(inbuf,smb_vwv0);
1825 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1827 SMB_STRUCT_STAT sbuf;
1830 unsigned int namelen;
1831 struct smb_request req;
1833 START_PROFILE(SMBctemp);
1835 init_smb_request(&req, (uint8 *)inbuf);
1837 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1838 sizeof(fname), 0, STR_TERMINATE, &status);
1839 if (!NT_STATUS_IS_OK(status)) {
1840 END_PROFILE(SMBctemp);
1841 return ERROR_NT(status);
1844 pstrcat(fname,"/TMXXXXXX");
1846 pstrcat(fname,"TMXXXXXX");
1849 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1850 if (!NT_STATUS_IS_OK(status)) {
1851 END_PROFILE(SMBctemp);
1852 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1853 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1855 return ERROR_NT(status);
1858 status = unix_convert(conn, fname, False, NULL, &sbuf);
1859 if (!NT_STATUS_IS_OK(status)) {
1860 END_PROFILE(SMBctemp);
1861 return ERROR_NT(status);
1864 status = check_name(conn, fname);
1865 if (!NT_STATUS_IS_OK(status)) {
1866 END_PROFILE(SMBctemp);
1867 return ERROR_NT(status);
1870 tmpfd = smb_mkstemp(fname);
1872 END_PROFILE(SMBctemp);
1873 return(UNIXERROR(ERRDOS,ERRnoaccess));
1876 SMB_VFS_STAT(conn,fname,&sbuf);
1878 /* We should fail if file does not exist. */
1879 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1880 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1881 FILE_SHARE_READ|FILE_SHARE_WRITE,
1888 /* close fd from smb_mkstemp() */
1891 if (!NT_STATUS_IS_OK(status)) {
1892 END_PROFILE(SMBctemp);
1893 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1894 /* We have re-scheduled this call. */
1897 return ERROR_NT(status);
1900 outsize = set_message(inbuf,outbuf,1,0,True);
1901 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1903 /* the returned filename is relative to the directory */
1904 s = strrchr_m(fname, '/');
1911 p = smb_buf(outbuf);
1913 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1914 thing in the byte section. JRA */
1915 SSVALS(p, 0, -1); /* what is this? not in spec */
1917 namelen = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, s, -1,
1918 STR_ASCII|STR_TERMINATE);
1920 outsize = set_message_end(inbuf,outbuf, p);
1922 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1923 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1926 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1927 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1930 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1931 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1932 (unsigned int)sbuf.st_mode ) );
1934 END_PROFILE(SMBctemp);
1938 /*******************************************************************
1939 Check if a user is allowed to rename a file.
1940 ********************************************************************/
1942 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1943 uint16 dirtype, SMB_STRUCT_STAT *pst)
1947 if (!CAN_WRITE(conn)) {
1948 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1951 fmode = dos_mode(conn, fsp->fsp_name, pst);
1952 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1953 return NT_STATUS_NO_SUCH_FILE;
1956 if (S_ISDIR(pst->st_mode)) {
1957 return NT_STATUS_OK;
1960 if (fsp->access_mask & DELETE_ACCESS) {
1961 return NT_STATUS_OK;
1964 return NT_STATUS_ACCESS_DENIED;
1967 /*******************************************************************
1968 * unlink a file with all relevant access checks
1969 *******************************************************************/
1971 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
1972 char *fname, uint32 dirtype)
1974 SMB_STRUCT_STAT sbuf;
1977 uint32 dirtype_orig = dirtype;
1980 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
1982 if (!CAN_WRITE(conn)) {
1983 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1986 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1987 return map_nt_error_from_unix(errno);
1990 fattr = dos_mode(conn,fname,&sbuf);
1992 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1993 dirtype = aDIR|aARCH|aRONLY;
1996 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1998 return NT_STATUS_NO_SUCH_FILE;
2001 if (!dir_check_ftype(conn, fattr, dirtype)) {
2003 return NT_STATUS_FILE_IS_A_DIRECTORY;
2005 return NT_STATUS_NO_SUCH_FILE;
2008 if (dirtype_orig & 0x8000) {
2009 /* These will never be set for POSIX. */
2010 return NT_STATUS_NO_SUCH_FILE;
2014 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2015 return NT_STATUS_FILE_IS_A_DIRECTORY;
2018 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2019 return NT_STATUS_NO_SUCH_FILE;
2022 if (dirtype & 0xFF00) {
2023 /* These will never be set for POSIX. */
2024 return NT_STATUS_NO_SUCH_FILE;
2029 return NT_STATUS_NO_SUCH_FILE;
2032 /* Can't delete a directory. */
2034 return NT_STATUS_FILE_IS_A_DIRECTORY;
2039 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2040 return NT_STATUS_OBJECT_NAME_INVALID;
2041 #endif /* JRATEST */
2043 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2045 On a Windows share, a file with read-only dosmode can be opened with
2046 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2047 fails with NT_STATUS_CANNOT_DELETE error.
2049 This semantic causes a problem that a user can not
2050 rename a file with read-only dosmode on a Samba share
2051 from a Windows command prompt (i.e. cmd.exe, but can rename
2052 from Windows Explorer).
2055 if (!lp_delete_readonly(SNUM(conn))) {
2056 if (fattr & aRONLY) {
2057 return NT_STATUS_CANNOT_DELETE;
2061 /* On open checks the open itself will check the share mode, so
2062 don't do it here as we'll get it wrong. */
2064 status = open_file_ntcreate(conn, req, fname, &sbuf,
2069 FILE_ATTRIBUTE_NORMAL,
2070 req != NULL ? 0 : INTERNAL_OPEN_ONLY,
2073 if (!NT_STATUS_IS_OK(status)) {
2074 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2075 nt_errstr(status)));
2079 /* The set is across all open files on this dev/inode pair. */
2080 if (!set_delete_on_close(fsp, True, ¤t_user.ut)) {
2081 close_file(fsp, NORMAL_CLOSE);
2082 return NT_STATUS_ACCESS_DENIED;
2085 return close_file(fsp,NORMAL_CLOSE);
2088 /****************************************************************************
2089 The guts of the unlink command, split out so it may be called by the NT SMB
2091 ****************************************************************************/
2093 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2094 uint32 dirtype, char *name, BOOL has_wild)
2100 NTSTATUS status = NT_STATUS_OK;
2101 SMB_STRUCT_STAT sbuf;
2103 *directory = *mask = 0;
2105 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
2106 if (!NT_STATUS_IS_OK(status)) {
2110 p = strrchr_m(name,'/');
2112 pstrcpy(directory,".");
2116 pstrcpy(directory,name);
2121 * We should only check the mangled cache
2122 * here if unix_convert failed. This means
2123 * that the path in 'mask' doesn't exist
2124 * on the file system and so we need to look
2125 * for a possible mangle. This patch from
2126 * Tine Smukavec <valentin.smukavec@hermes.si>.
2129 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
2130 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
2133 pstrcat(directory,"/");
2134 pstrcat(directory,mask);
2136 dirtype = FILE_ATTRIBUTE_NORMAL;
2139 status = check_name(conn, directory);
2140 if (!NT_STATUS_IS_OK(status)) {
2144 status = do_unlink(conn, req, directory, dirtype);
2145 if (!NT_STATUS_IS_OK(status)) {
2151 struct smb_Dir *dir_hnd = NULL;
2155 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2156 return NT_STATUS_OBJECT_NAME_INVALID;
2159 if (strequal(mask,"????????.???")) {
2163 status = check_name(conn, directory);
2164 if (!NT_STATUS_IS_OK(status)) {
2168 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2169 if (dir_hnd == NULL) {
2170 return map_nt_error_from_unix(errno);
2173 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2174 the pattern matches against the long name, otherwise the short name
2175 We don't implement this yet XXXX
2178 status = NT_STATUS_NO_SUCH_FILE;
2180 while ((dname = ReadDirName(dir_hnd, &offset))) {
2183 pstrcpy(fname,dname);
2185 if (!is_visible_file(conn, directory, dname, &st, True)) {
2189 /* Quick check for "." and ".." */
2190 if (fname[0] == '.') {
2191 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2196 if(!mask_match(fname, mask, conn->case_sensitive)) {
2200 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2202 status = check_name(conn, fname);
2203 if (!NT_STATUS_IS_OK(status)) {
2208 status = do_unlink(conn, req, fname, dirtype);
2209 if (!NT_STATUS_IS_OK(status)) {
2214 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2220 if (count == 0 && NT_STATUS_IS_OK(status)) {
2221 status = map_nt_error_from_unix(errno);
2227 /****************************************************************************
2229 ****************************************************************************/
2231 void reply_unlink(connection_struct *conn, struct smb_request *req)
2236 BOOL path_contains_wcard = False;
2238 START_PROFILE(SMBunlink);
2241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2242 END_PROFILE(SMBunlink);
2246 dirtype = SVAL(req->inbuf,smb_vwv0);
2248 srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name,
2249 smb_buf(req->inbuf) + 1, sizeof(name), 0,
2250 STR_TERMINATE, &status, &path_contains_wcard);
2251 if (!NT_STATUS_IS_OK(status)) {
2252 reply_nterror(req, status);
2253 END_PROFILE(SMBunlink);
2257 status = resolve_dfspath_wcard(conn,
2258 req->flags2 & FLAGS2_DFS_PATHNAMES,
2259 name, &path_contains_wcard);
2260 if (!NT_STATUS_IS_OK(status)) {
2261 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2262 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2263 ERRSRV, ERRbadpath);
2264 END_PROFILE(SMBunlink);
2267 reply_nterror(req, status);
2268 END_PROFILE(SMBunlink);
2272 DEBUG(3,("reply_unlink : %s\n",name));
2274 status = unlink_internals(conn, req, dirtype, name,
2275 path_contains_wcard);
2276 if (!NT_STATUS_IS_OK(status)) {
2277 if (open_was_deferred(req->mid)) {
2278 /* We have re-scheduled this call. */
2279 END_PROFILE(SMBunlink);
2282 reply_nterror(req, status);
2283 END_PROFILE(SMBunlink);
2287 reply_outbuf(req, 0, 0);
2288 END_PROFILE(SMBunlink);
2293 /****************************************************************************
2295 ****************************************************************************/
2297 static void fail_readraw(void)
2300 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2302 exit_server_cleanly(errstr);
2305 /****************************************************************************
2306 Fake (read/write) sendfile. Returns -1 on read or write fail.
2307 ****************************************************************************/
2309 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
2311 size_t tosend = nread;
2313 while (tosend > 0) {
2317 if (tosend > bufsize) {
2322 ret = read_file(fsp,buf,startpos,cur_read);
2327 /* If we had a short read, fill with zeros. */
2328 if (ret < cur_read) {
2329 memset(buf, '\0', cur_read - ret);
2332 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2336 startpos += cur_read;
2339 return (ssize_t)nread;
2342 /****************************************************************************
2343 Use sendfile in readbraw.
2344 ****************************************************************************/
2346 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2347 ssize_t mincount, char *outbuf, int out_buffsize)
2351 #if defined(WITH_SENDFILE)
2353 * We can only use sendfile on a non-chained packet
2354 * but we can use on a non-oplocked file. tridge proved this
2355 * on a train in Germany :-). JRA.
2356 * reply_readbraw has already checked the length.
2359 if ( (chain_size == 0) && (nread > 0) &&
2360 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2363 _smb_setlen(outbuf,nread);
2364 header.data = (uint8 *)outbuf;
2368 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2369 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2370 if (errno == ENOSYS) {
2371 goto normal_readbraw;
2375 * Special hack for broken Linux with no working sendfile. If we
2376 * return EINTR we sent the header but not the rest of the data.
2377 * Fake this up by doing read/write calls.
2379 if (errno == EINTR) {
2380 /* Ensure we don't do this again. */
2381 set_use_sendfile(SNUM(conn), False);
2382 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2384 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2385 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2386 fsp->fsp_name, strerror(errno) ));
2387 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2392 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2393 fsp->fsp_name, strerror(errno) ));
2394 exit_server_cleanly("send_file_readbraw sendfile failed");
2404 ret = read_file(fsp,outbuf+4,startpos,nread);
2405 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2414 _smb_setlen(outbuf,ret);
2415 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2419 /****************************************************************************
2420 Reply to a readbraw (core+ protocol).
2421 ****************************************************************************/
2423 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2425 ssize_t maxcount,mincount;
2428 char *header = outbuf;
2430 START_PROFILE(SMBreadbraw);
2432 if (srv_is_signing_active()) {
2433 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2437 * Special check if an oplock break has been issued
2438 * and the readraw request croses on the wire, we must
2439 * return a zero length response here.
2442 fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2444 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2446 * fsp could be NULL here so use the value from the packet. JRA.
2448 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2449 _smb_setlen(header,0);
2450 if (write_data(smbd_server_fd(),header,4) != 4)
2452 END_PROFILE(SMBreadbraw);
2456 CHECK_FSP(fsp,conn);
2458 flush_write_cache(fsp, READRAW_FLUSH);
2460 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2461 if(CVAL(inbuf,smb_wct) == 10) {
2463 * This is a large offset (64 bit) read.
2465 #ifdef LARGE_SMB_OFF_T
2467 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2469 #else /* !LARGE_SMB_OFF_T */
2472 * Ensure we haven't been sent a >32 bit offset.
2475 if(IVAL(inbuf,smb_vwv8) != 0) {
2476 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2477 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2478 _smb_setlen(header,0);
2479 if (write_data(smbd_server_fd(),header,4) != 4)
2481 END_PROFILE(SMBreadbraw);
2485 #endif /* LARGE_SMB_OFF_T */
2488 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2489 _smb_setlen(header,0);
2490 if (write_data(smbd_server_fd(),header,4) != 4)
2492 END_PROFILE(SMBreadbraw);
2496 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2497 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2499 /* ensure we don't overrun the packet size */
2500 maxcount = MIN(65535,maxcount);
2502 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2506 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2510 if (startpos >= size) {
2513 nread = MIN(maxcount,(size - startpos));
2517 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2518 if (nread < mincount)
2522 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2523 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2525 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2527 DEBUG(5,("readbraw finished\n"));
2528 END_PROFILE(SMBreadbraw);
2533 #define DBGC_CLASS DBGC_LOCKING
2535 /****************************************************************************
2536 Reply to a lockread (core+ protocol).
2537 ****************************************************************************/
2539 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2547 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2548 struct byte_range_lock *br_lck = NULL;
2549 START_PROFILE(SMBlockread);
2551 CHECK_FSP(fsp,conn);
2552 if (!CHECK_READ(fsp,inbuf)) {
2553 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2556 release_level_2_oplocks_on_change(fsp);
2558 numtoread = SVAL(inbuf,smb_vwv1);
2559 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2561 outsize = set_message(inbuf,outbuf,5,3,True);
2562 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2563 data = smb_buf(outbuf) + 3;
2566 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2567 * protocol request that predates the read/write lock concept.
2568 * Thus instead of asking for a read lock here we need to ask
2569 * for a write lock. JRA.
2570 * Note that the requested lock size is unaffected by max_recv.
2573 br_lck = do_lock(smbd_messaging_context(),
2575 (uint32)SVAL(inbuf,smb_pid),
2576 (SMB_BIG_UINT)numtoread,
2577 (SMB_BIG_UINT)startpos,
2580 False, /* Non-blocking lock. */
2583 TALLOC_FREE(br_lck);
2585 if (NT_STATUS_V(status)) {
2586 END_PROFILE(SMBlockread);
2587 return ERROR_NT(status);
2591 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2594 if (numtoread > max_recv) {
2595 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2596 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2597 (unsigned int)numtoread, (unsigned int)max_recv ));
2598 numtoread = MIN(numtoread,max_recv);
2600 nread = read_file(fsp,data,startpos,numtoread);
2603 END_PROFILE(SMBlockread);
2604 return(UNIXERROR(ERRDOS,ERRnoaccess));
2608 SSVAL(outbuf,smb_vwv0,nread);
2609 SSVAL(outbuf,smb_vwv5,nread+3);
2610 SSVAL(smb_buf(outbuf),1,nread);
2612 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2613 fsp->fnum, (int)numtoread, (int)nread));
2615 END_PROFILE(SMBlockread);
2620 #define DBGC_CLASS DBGC_ALL
2622 /****************************************************************************
2624 ****************************************************************************/
2626 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2633 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2634 START_PROFILE(SMBread);
2636 CHECK_FSP(fsp,conn);
2637 if (!CHECK_READ(fsp,inbuf)) {
2638 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2641 numtoread = SVAL(inbuf,smb_vwv1);
2642 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2644 outsize = set_message(inbuf,outbuf,5,3,True);
2645 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2647 * The requested read size cannot be greater than max_recv. JRA.
2649 if (numtoread > max_recv) {
2650 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2651 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2652 (unsigned int)numtoread, (unsigned int)max_recv ));
2653 numtoread = MIN(numtoread,max_recv);
2656 data = smb_buf(outbuf) + 3;
2658 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2659 END_PROFILE(SMBread);
2660 return ERROR_DOS(ERRDOS,ERRlock);
2664 nread = read_file(fsp,data,startpos,numtoread);
2667 END_PROFILE(SMBread);
2668 return(UNIXERROR(ERRDOS,ERRnoaccess));
2672 SSVAL(outbuf,smb_vwv0,nread);
2673 SSVAL(outbuf,smb_vwv5,nread+3);
2674 SCVAL(smb_buf(outbuf),0,1);
2675 SSVAL(smb_buf(outbuf),1,nread);
2677 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2678 fsp->fnum, (int)numtoread, (int)nread ) );
2680 END_PROFILE(SMBread);
2684 /****************************************************************************
2686 ****************************************************************************/
2688 static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
2691 char *data = smb_buf(outbuf);
2693 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2694 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2695 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2696 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2697 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2698 SCVAL(outbuf,smb_vwv0,0xFF);
2699 outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
2700 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2701 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2705 /****************************************************************************
2706 Reply to a read and X - possibly using sendfile.
2707 ****************************************************************************/
2709 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2710 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2712 SMB_STRUCT_STAT sbuf;
2715 char *data = smb_buf(outbuf);
2717 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2718 return(UNIXERROR(ERRDOS,ERRnoaccess));
2721 if (startpos > sbuf.st_size) {
2723 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
2724 smb_maxcnt = (sbuf.st_size - startpos);
2727 if (smb_maxcnt == 0) {
2731 #if defined(WITH_SENDFILE)
2733 * We can only use sendfile on a non-chained packet
2734 * but we can use on a non-oplocked file. tridge proved this
2735 * on a train in Germany :-). JRA.
2738 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2739 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2743 * Set up the packet header before send. We
2744 * assume here the sendfile will work (get the
2745 * correct amount of data).
2748 setup_readX_header(inbuf,outbuf,smb_maxcnt);
2749 set_message(inbuf,outbuf,12,smb_maxcnt,False);
2750 header.data = (uint8 *)outbuf;
2751 header.length = data - outbuf;
2754 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2755 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2756 if (errno == ENOSYS) {
2761 * Special hack for broken Linux with no working sendfile. If we
2762 * return EINTR we sent the header but not the rest of the data.
2763 * Fake this up by doing read/write calls.
2766 if (errno == EINTR) {
2767 /* Ensure we don't do this again. */
2768 set_use_sendfile(SNUM(conn), False);
2769 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2771 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2772 len_outbuf - (data-outbuf))) == -1) {
2773 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2774 fsp->fsp_name, strerror(errno) ));
2775 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2777 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2778 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2779 /* Returning -1 here means successful sendfile. */
2783 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2784 fsp->fsp_name, strerror(errno) ));
2785 exit_server_cleanly("send_file_readX sendfile failed");
2788 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2789 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2790 /* Returning -1 here means successful sendfile. */
2798 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
2799 int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
2800 /* Send out the header. */
2801 if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
2802 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2803 fsp->fsp_name, strerror(errno) ));
2804 exit_server_cleanly("send_file_readX sendfile failed");
2806 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2807 len_outbuf - (data-outbuf))) == -1) {
2808 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2809 fsp->fsp_name, strerror(errno) ));
2810 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2814 nread = read_file(fsp,data,startpos,smb_maxcnt);
2817 return(UNIXERROR(ERRDOS,ERRnoaccess));
2820 outsize = setup_readX_header(inbuf, outbuf,nread);
2822 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2823 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2825 /* Returning the number of bytes we want to send back - including header. */
2830 /****************************************************************************
2831 Reply to a read and X.
2832 ****************************************************************************/
2834 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2836 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
2837 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2839 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2840 BOOL big_readX = False;
2842 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2845 START_PROFILE(SMBreadX);
2847 /* If it's an IPC, pass off the pipe handler. */
2849 END_PROFILE(SMBreadX);
2850 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2853 CHECK_FSP(fsp,conn);
2854 if (!CHECK_READ(fsp,inbuf)) {
2855 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2858 set_message(inbuf,outbuf,12,0,True);
2860 if (global_client_caps & CAP_LARGE_READX) {
2861 size_t upper_size = SVAL(inbuf,smb_vwv7);
2862 smb_maxcnt |= (upper_size<<16);
2863 if (upper_size > 1) {
2864 /* Can't do this on a chained packet. */
2865 if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
2866 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2868 /* We currently don't do this on signed or sealed data. */
2869 if (srv_is_signing_active() || srv_encryption_on()) {
2870 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2872 /* Is there room in the reply for this data ? */
2873 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
2874 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2880 if(CVAL(inbuf,smb_wct) == 12) {
2881 #ifdef LARGE_SMB_OFF_T
2883 * This is a large offset (64 bit) read.
2885 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2887 #else /* !LARGE_SMB_OFF_T */
2890 * Ensure we haven't been sent a >32 bit offset.
2893 if(IVAL(inbuf,smb_vwv10) != 0) {
2894 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2895 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2896 END_PROFILE(SMBreadX);
2897 return ERROR_DOS(ERRDOS,ERRbadaccess);
2900 #endif /* LARGE_SMB_OFF_T */
2904 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2905 END_PROFILE(SMBreadX);
2906 return ERROR_DOS(ERRDOS,ERRlock);
2909 if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2910 END_PROFILE(SMBreadX);
2914 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2915 /* Only call chain_reply if not an error. */
2916 if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2917 nread = chain_reply(inbuf,&outbuf,length,bufsize);
2920 END_PROFILE(SMBreadX);
2924 /****************************************************************************
2925 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2926 ****************************************************************************/
2928 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2931 ssize_t total_written=0;
2932 size_t numtowrite=0;
2937 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2940 START_PROFILE(SMBwritebraw);
2942 if (srv_is_signing_active()) {
2943 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2946 CHECK_FSP(fsp,conn);
2947 if (!CHECK_WRITE(fsp)) {
2948 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2951 tcount = IVAL(inbuf,smb_vwv1);
2952 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2953 write_through = BITSETW(inbuf+smb_vwv7,0);
2955 /* We have to deal with slightly different formats depending
2956 on whether we are using the core+ or lanman1.0 protocol */
2958 if(Protocol <= PROTOCOL_COREPLUS) {
2959 numtowrite = SVAL(smb_buf(inbuf),-2);
2960 data = smb_buf(inbuf);
2962 numtowrite = SVAL(inbuf,smb_vwv10);
2963 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2966 /* force the error type */
2967 SCVAL(inbuf,smb_com,SMBwritec);
2968 SCVAL(outbuf,smb_com,SMBwritec);
2970 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2971 END_PROFILE(SMBwritebraw);
2972 return(ERROR_DOS(ERRDOS,ERRlock));
2976 nwritten = write_file(fsp,data,startpos,numtowrite);
2978 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2979 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2981 if (nwritten < (ssize_t)numtowrite) {
2982 END_PROFILE(SMBwritebraw);
2983 return(UNIXERROR(ERRHRD,ERRdiskfull));
2986 total_written = nwritten;
2988 /* Return a message to the redirector to tell it to send more bytes */
2989 SCVAL(outbuf,smb_com,SMBwritebraw);
2990 SSVALS(outbuf,smb_vwv0,-1);
2991 outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2993 if (!send_smb(smbd_server_fd(),outbuf))
2994 exit_server_cleanly("reply_writebraw: send_smb failed.");
2996 /* Now read the raw data into the buffer and write it */
2997 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2998 exit_server_cleanly("secondary writebraw failed");
3001 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
3002 numtowrite = smb_len(inbuf);
3004 /* Set up outbuf to return the correct return */
3005 outsize = set_message(inbuf,outbuf,1,0,True);
3006 SCVAL(outbuf,smb_com,SMBwritec);
3008 if (numtowrite != 0) {
3010 if (numtowrite > BUFFER_SIZE) {
3011 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
3012 (unsigned int)numtowrite ));
3013 exit_server_cleanly("secondary writebraw failed");
3016 if (tcount > nwritten+numtowrite) {
3017 DEBUG(3,("Client overestimated the write %d %d %d\n",
3018 (int)tcount,(int)nwritten,(int)numtowrite));
3021 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
3022 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
3024 exit_server_cleanly("secondary writebraw failed");
3027 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
3028 if (nwritten == -1) {
3029 END_PROFILE(SMBwritebraw);
3030 return(UNIXERROR(ERRHRD,ERRdiskfull));
3033 if (nwritten < (ssize_t)numtowrite) {
3034 SCVAL(outbuf,smb_rcls,ERRHRD);
3035 SSVAL(outbuf,smb_err,ERRdiskfull);
3039 total_written += nwritten;
3042 SSVAL(outbuf,smb_vwv0,total_written);
3044 status = sync_file(conn, fsp, write_through);
3045 if (!NT_STATUS_IS_OK(status)) {
3046 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3047 fsp->fsp_name, nt_errstr(status) ));
3048 END_PROFILE(SMBwritebraw);
3049 return ERROR_NT(status);
3052 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
3053 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
3055 /* we won't return a status if write through is not selected - this follows what WfWg does */
3056 END_PROFILE(SMBwritebraw);
3057 if (!write_through && total_written==tcount) {
3059 #if RABBIT_PELLET_FIX
3061 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3062 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
3064 if (!send_keepalive(smbd_server_fd()))
3065 exit_server_cleanly("reply_writebraw: send of keepalive failed");
3074 #define DBGC_CLASS DBGC_LOCKING
3076 /****************************************************************************
3077 Reply to a writeunlock (core+).
3078 ****************************************************************************/
3080 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
3081 int size, int dum_buffsize)
3083 ssize_t nwritten = -1;
3087 NTSTATUS status = NT_STATUS_OK;
3088 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3090 START_PROFILE(SMBwriteunlock);
3092 CHECK_FSP(fsp,conn);
3093 if (!CHECK_WRITE(fsp)) {
3094 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3097 numtowrite = SVAL(inbuf,smb_vwv1);
3098 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3099 data = smb_buf(inbuf) + 3;
3101 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3102 END_PROFILE(SMBwriteunlock);
3103 return ERROR_DOS(ERRDOS,ERRlock);
3106 /* The special X/Open SMB protocol handling of
3107 zero length writes is *NOT* done for
3109 if(numtowrite == 0) {
3112 nwritten = write_file(fsp,data,startpos,numtowrite);
3115 status = sync_file(conn, fsp, False /* write through */);
3116 if (!NT_STATUS_IS_OK(status)) {
3117 END_PROFILE(SMBwriteunlock);
3118 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3119 fsp->fsp_name, nt_errstr(status) ));
3120 return ERROR_NT(status);
3123 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3124 END_PROFILE(SMBwriteunlock);
3125 return(UNIXERROR(ERRHRD,ERRdiskfull));
3129 status = do_unlock(smbd_messaging_context(),
3131 (uint32)SVAL(inbuf,smb_pid),
3132 (SMB_BIG_UINT)numtowrite,
3133 (SMB_BIG_UINT)startpos,
3136 if (NT_STATUS_V(status)) {
3137 END_PROFILE(SMBwriteunlock);
3138 return ERROR_NT(status);
3142 outsize = set_message(inbuf,outbuf,1,0,True);
3144 SSVAL(outbuf,smb_vwv0,nwritten);
3146 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3147 fsp->fnum, (int)numtowrite, (int)nwritten));
3149 END_PROFILE(SMBwriteunlock);
3154 #define DBGC_CLASS DBGC_ALL
3156 /****************************************************************************
3158 ****************************************************************************/
3160 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
3163 ssize_t nwritten = -1;
3166 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3169 START_PROFILE(SMBwrite);
3171 /* If it's an IPC, pass off the pipe handler. */
3173 END_PROFILE(SMBwrite);
3174 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3177 CHECK_FSP(fsp,conn);
3178 if (!CHECK_WRITE(fsp)) {
3179 END_PROFILE(SMBwrite);
3180 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3183 numtowrite = SVAL(inbuf,smb_vwv1);
3184 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3185 data = smb_buf(inbuf) + 3;
3187 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3188 END_PROFILE(SMBwrite);
3189 return ERROR_DOS(ERRDOS,ERRlock);
3193 * X/Open SMB protocol says that if smb_vwv1 is
3194 * zero then the file size should be extended or
3195 * truncated to the size given in smb_vwv[2-3].
3198 if(numtowrite == 0) {
3200 * This is actually an allocate call, and set EOF. JRA.
3202 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3204 END_PROFILE(SMBwrite);
3205 return ERROR_NT(NT_STATUS_DISK_FULL);
3207 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3209 END_PROFILE(SMBwrite);
3210 return ERROR_NT(NT_STATUS_DISK_FULL);
3213 nwritten = write_file(fsp,data,startpos,numtowrite);
3215 status = sync_file(conn, fsp, False);
3216 if (!NT_STATUS_IS_OK(status)) {
3217 END_PROFILE(SMBwrite);
3218 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3219 fsp->fsp_name, nt_errstr(status) ));
3220 return ERROR_NT(status);
3223 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3224 END_PROFILE(SMBwrite);
3225 return(UNIXERROR(ERRHRD,ERRdiskfull));
3228 outsize = set_message(inbuf,outbuf,1,0,True);
3230 SSVAL(outbuf,smb_vwv0,nwritten);
3232 if (nwritten < (ssize_t)numtowrite) {
3233 SCVAL(outbuf,smb_rcls,ERRHRD);
3234 SSVAL(outbuf,smb_err,ERRdiskfull);
3237 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3239 END_PROFILE(SMBwrite);
3243 /****************************************************************************
3244 Reply to a write and X.
3245 ****************************************************************************/
3247 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3249 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
3250 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3251 size_t numtowrite = SVAL(inbuf,smb_vwv10);
3252 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3253 ssize_t nwritten = -1;
3254 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3255 unsigned int smblen = smb_len(inbuf);
3257 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3259 START_PROFILE(SMBwriteX);
3261 /* If it's an IPC, pass off the pipe handler. */
3263 END_PROFILE(SMBwriteX);
3264 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3267 CHECK_FSP(fsp,conn);
3268 if (!CHECK_WRITE(fsp)) {
3269 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3272 set_message(inbuf,outbuf,6,0,True);
3274 /* Deal with possible LARGE_WRITEX */
3276 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3279 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3280 END_PROFILE(SMBwriteX);
3281 return ERROR_DOS(ERRDOS,ERRbadmem);
3284 data = smb_base(inbuf) + smb_doff;
3286 if(CVAL(inbuf,smb_wct) == 14) {
3287 #ifdef LARGE_SMB_OFF_T
3289 * This is a large offset (64 bit) write.
3291 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3293 #else /* !LARGE_SMB_OFF_T */
3296 * Ensure we haven't been sent a >32 bit offset.
3299 if(IVAL(inbuf,smb_vwv12) != 0) {
3300 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3301 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3302 END_PROFILE(SMBwriteX);
3303 return ERROR_DOS(ERRDOS,ERRbadaccess);
3306 #endif /* LARGE_SMB_OFF_T */
3309 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3310 END_PROFILE(SMBwriteX);
3311 return ERROR_DOS(ERRDOS,ERRlock);
3314 /* X/Open SMB protocol says that, unlike SMBwrite
3315 if the length is zero then NO truncation is
3316 done, just a write of zero. To truncate a file,
3319 if(numtowrite == 0) {
3323 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3324 fsp,data,startpos,numtowrite)) {
3325 END_PROFILE(SMBwriteX);
3329 nwritten = write_file(fsp,data,startpos,numtowrite);
3332 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3333 END_PROFILE(SMBwriteX);
3334 return(UNIXERROR(ERRHRD,ERRdiskfull));
3337 SSVAL(outbuf,smb_vwv2,nwritten);
3339 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3341 if (nwritten < (ssize_t)numtowrite) {
3342 SCVAL(outbuf,smb_rcls,ERRHRD);
3343 SSVAL(outbuf,smb_err,ERRdiskfull);
3346 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3347 fsp->fnum, (int)numtowrite, (int)nwritten));
3349 status = sync_file(conn, fsp, write_through);
3350 if (!NT_STATUS_IS_OK(status)) {
3351 END_PROFILE(SMBwriteX);
3352 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3353 fsp->fsp_name, nt_errstr(status) ));
3354 return ERROR_NT(status);
3357 END_PROFILE(SMBwriteX);
3358 return chain_reply(inbuf,&outbuf,length,bufsize);
3361 /****************************************************************************
3363 ****************************************************************************/
3365 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3371 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3372 START_PROFILE(SMBlseek);
3374 CHECK_FSP(fsp,conn);
3376 flush_write_cache(fsp, SEEK_FLUSH);
3378 mode = SVAL(inbuf,smb_vwv1) & 3;
3379 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3380 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3389 res = fsp->fh->pos + startpos;
3400 if (umode == SEEK_END) {
3401 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3402 if(errno == EINVAL) {
3403 SMB_OFF_T current_pos = startpos;
3404 SMB_STRUCT_STAT sbuf;
3406 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3407 END_PROFILE(SMBlseek);
3408 return(UNIXERROR(ERRDOS,ERRnoaccess));
3411 current_pos += sbuf.st_size;
3413 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3418 END_PROFILE(SMBlseek);
3419 return(UNIXERROR(ERRDOS,ERRnoaccess));
3425 outsize = set_message(inbuf,outbuf,2,0,True);
3426 SIVAL(outbuf,smb_vwv0,res);
3428 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3429 fsp->fnum, (double)startpos, (double)res, mode));
3431 END_PROFILE(SMBlseek);
3435 /****************************************************************************
3437 ****************************************************************************/
3439 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3441 int outsize = set_message(inbuf,outbuf,0,0,False);
3442 uint16 fnum = SVAL(inbuf,smb_vwv0);
3443 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3444 START_PROFILE(SMBflush);
3447 CHECK_FSP(fsp,conn);
3450 file_sync_all(conn);
3452 NTSTATUS status = sync_file(conn, fsp, True);
3453 if (!NT_STATUS_IS_OK(status)) {
3454 END_PROFILE(SMBflush);
3455 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3456 fsp->fsp_name, nt_errstr(status) ));
3457 return ERROR_NT(status);
3461 DEBUG(3,("flush\n"));
3462 END_PROFILE(SMBflush);
3466 /****************************************************************************
3468 conn POINTER CAN BE NULL HERE !
3469 ****************************************************************************/
3471 void reply_exit(connection_struct *conn, struct smb_request *req)
3473 START_PROFILE(SMBexit);
3475 file_close_pid(req->smbpid, req->vuid);
3477 reply_outbuf(req, 0, 0);
3479 DEBUG(3,("exit\n"));
3481 END_PROFILE(SMBexit);
3485 /****************************************************************************
3486 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3487 ****************************************************************************/
3489 void reply_close(connection_struct *conn, struct smb_request *req)
3491 NTSTATUS status = NT_STATUS_OK;
3492 files_struct *fsp = NULL;
3493 START_PROFILE(SMBclose);
3496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3497 END_PROFILE(SMBclose);
3501 /* If it's an IPC, pass off to the pipe handler. */
3503 reply_pipe_close(conn, req);
3504 END_PROFILE(SMBclose);
3508 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3511 * We can only use CHECK_FSP if we know it's not a directory.
3514 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3515 reply_doserror(req, ERRDOS, ERRbadfid);
3516 END_PROFILE(SMBclose);
3520 if(fsp->is_directory) {
3522 * Special case - close NT SMB directory handle.
3524 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3525 status = close_file(fsp,NORMAL_CLOSE);
3528 * Close ordinary file.
3531 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3532 fsp->fh->fd, fsp->fnum,
3533 conn->num_files_open));
3536 * Take care of any time sent in the close.
3539 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
3540 srv_make_unix_date3(
3541 req->inbuf+smb_vwv1)));
3544 * close_file() returns the unix errno if an error
3545 * was detected on close - normally this is due to
3546 * a disk full error. If not then it was probably an I/O error.
3549 status = close_file(fsp,NORMAL_CLOSE);
3552 if (!NT_STATUS_IS_OK(status)) {
3553 reply_nterror(req, status);
3554 END_PROFILE(SMBclose);
3558 reply_outbuf(req, 0, 0);
3559 END_PROFILE(SMBclose);
3563 /****************************************************************************
3564 Reply to a writeclose (Core+ protocol).
3565 ****************************************************************************/
3567 int reply_writeclose(connection_struct *conn,
3568 char *inbuf,char *outbuf, int size, int dum_buffsize)
3571 ssize_t nwritten = -1;
3573 NTSTATUS close_status = NT_STATUS_OK;
3576 struct timespec mtime;
3577 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3578 START_PROFILE(SMBwriteclose);
3580 CHECK_FSP(fsp,conn);
3581 if (!CHECK_WRITE(fsp)) {
3582 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3585 numtowrite = SVAL(inbuf,smb_vwv1);
3586 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3587 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3588 data = smb_buf(inbuf) + 1;
3590 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3591 END_PROFILE(SMBwriteclose);
3592 return ERROR_DOS(ERRDOS,ERRlock);
3595 nwritten = write_file(fsp,data,startpos,numtowrite);
3597 set_filetime(conn, fsp->fsp_name, mtime);
3600 * More insanity. W2K only closes the file if writelen > 0.
3605 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3607 close_status = close_file(fsp,NORMAL_CLOSE);
3610 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3611 fsp->fnum, (int)numtowrite, (int)nwritten,
3612 conn->num_files_open));
3614 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3615 END_PROFILE(SMBwriteclose);
3616 return(UNIXERROR(ERRHRD,ERRdiskfull));
3619 if(!NT_STATUS_IS_OK(close_status)) {
3620 END_PROFILE(SMBwriteclose);
3621 return ERROR_NT(close_status);
3624 outsize = set_message(inbuf,outbuf,1,0,True);
3626 SSVAL(outbuf,smb_vwv0,nwritten);
3627 END_PROFILE(SMBwriteclose);
3632 #define DBGC_CLASS DBGC_LOCKING
3634 /****************************************************************************
3636 ****************************************************************************/
3638 int reply_lock(connection_struct *conn,
3639 char *inbuf,char *outbuf, int length, int dum_buffsize)
3641 int outsize = set_message(inbuf,outbuf,0,0,False);
3642 SMB_BIG_UINT count,offset;
3644 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3645 struct byte_range_lock *br_lck = NULL;
3647 START_PROFILE(SMBlock);
3649 CHECK_FSP(fsp,conn);
3651 release_level_2_oplocks_on_change(fsp);
3653 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3654 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3656 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3657 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3659 br_lck = do_lock(smbd_messaging_context(),
3661 (uint32)SVAL(inbuf,smb_pid),
3666 False, /* Non-blocking lock. */
3670 TALLOC_FREE(br_lck);
3672 if (NT_STATUS_V(status)) {
3673 END_PROFILE(SMBlock);
3674 return ERROR_NT(status);
3677 END_PROFILE(SMBlock);
3681 /****************************************************************************
3683 ****************************************************************************/
3685 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3688 int outsize = set_message(inbuf,outbuf,0,0,False);
3689 SMB_BIG_UINT count,offset;
3691 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3692 START_PROFILE(SMBunlock);
3694 CHECK_FSP(fsp,conn);
3696 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3697 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3699 status = do_unlock(smbd_messaging_context(),
3701 (uint32)SVAL(inbuf,smb_pid),
3706 if (NT_STATUS_V(status)) {
3707 END_PROFILE(SMBunlock);
3708 return ERROR_NT(status);
3711 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3712 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3714 END_PROFILE(SMBunlock);
3719 #define DBGC_CLASS DBGC_ALL
3721 /****************************************************************************
3723 conn POINTER CAN BE NULL HERE !
3724 ****************************************************************************/
3726 void reply_tdis(connection_struct *conn, struct smb_request *req)
3728 START_PROFILE(SMBtdis);
3731 DEBUG(4,("Invalid connection in tdis\n"));
3732 reply_doserror(req, ERRSRV, ERRinvnid);
3733 END_PROFILE(SMBtdis);
3739 close_cnum(conn,req->vuid);
3741 reply_outbuf(req, 0, 0);
3742 END_PROFILE(SMBtdis);
3746 /****************************************************************************
3748 conn POINTER CAN BE NULL HERE !
3749 ****************************************************************************/
3751 int reply_echo(connection_struct *conn,
3752 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3754 int smb_reverb = SVAL(inbuf,smb_vwv0);
3756 unsigned int data_len = smb_buflen(inbuf);
3757 int outsize = set_message(inbuf,outbuf,1,data_len,True);
3758 START_PROFILE(SMBecho);
3760 if (data_len > BUFFER_SIZE) {
3761 DEBUG(0,("reply_echo: data_len too large.\n"));
3762 END_PROFILE(SMBecho);
3766 /* copy any incoming data back out */
3768 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3770 if (smb_reverb > 100) {
3771 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3775 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3776 SSVAL(outbuf,smb_vwv0,seq_num);
3778 smb_setlen(inbuf,outbuf,outsize - 4);
3781 if (!send_smb(smbd_server_fd(),outbuf))
3782 exit_server_cleanly("reply_echo: send_smb failed.");
3785 DEBUG(3,("echo %d times\n", smb_reverb));
3789 END_PROFILE(SMBecho);
3793 /****************************************************************************
3794 Reply to a printopen.
3795 ****************************************************************************/
3797 int reply_printopen(connection_struct *conn,
3798 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3804 START_PROFILE(SMBsplopen);
3806 if (!CAN_PRINT(conn)) {
3807 END_PROFILE(SMBsplopen);
3808 return ERROR_DOS(ERRDOS,ERRnoaccess);
3811 /* Open for exclusive use, write only. */
3812 status = print_fsp_open(conn, NULL, &fsp);
3814 if (!NT_STATUS_IS_OK(status)) {
3815 END_PROFILE(SMBsplopen);
3816 return(ERROR_NT(status));
3819 outsize = set_message(inbuf,outbuf,1,0,True);
3820 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3822 DEBUG(3,("openprint fd=%d fnum=%d\n",
3823 fsp->fh->fd, fsp->fnum));
3825 END_PROFILE(SMBsplopen);
3829 /****************************************************************************
3830 Reply to a printclose.
3831 ****************************************************************************/
3833 int reply_printclose(connection_struct *conn,
3834 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3836 int outsize = set_message(inbuf,outbuf,0,0,False);
3837 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3839 START_PROFILE(SMBsplclose);
3841 CHECK_FSP(fsp,conn);
3843 if (!CAN_PRINT(conn)) {
3844 END_PROFILE(SMBsplclose);
3845 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3848 DEBUG(3,("printclose fd=%d fnum=%d\n",
3849 fsp->fh->fd,fsp->fnum));
3851 status = close_file(fsp,NORMAL_CLOSE);
3853 if(!NT_STATUS_IS_OK(status)) {
3854 END_PROFILE(SMBsplclose);
3855 return ERROR_NT(status);
3858 END_PROFILE(SMBsplclose);
3862 /****************************************************************************
3863 Reply to a printqueue.
3864 ****************************************************************************/
3866 int reply_printqueue(connection_struct *conn,
3867 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3869 int outsize = set_message(inbuf,outbuf,2,3,True);
3870 int max_count = SVAL(inbuf,smb_vwv0);
3871 int start_index = SVAL(inbuf,smb_vwv1);
3872 START_PROFILE(SMBsplretq);
3874 /* we used to allow the client to get the cnum wrong, but that
3875 is really quite gross and only worked when there was only
3876 one printer - I think we should now only accept it if they
3877 get it right (tridge) */
3878 if (!CAN_PRINT(conn)) {
3879 END_PROFILE(SMBsplretq);
3880 return ERROR_DOS(ERRDOS,ERRnoaccess);
3883 SSVAL(outbuf,smb_vwv0,0);
3884 SSVAL(outbuf,smb_vwv1,0);
3885 SCVAL(smb_buf(outbuf),0,1);
3886 SSVAL(smb_buf(outbuf),1,0);
3888 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3889 start_index, max_count));
3892 print_queue_struct *queue = NULL;
3893 print_status_struct status;
3894 char *p = smb_buf(outbuf) + 3;
3895 int count = print_queue_status(SNUM(conn), &queue, &status);
3896 int num_to_get = ABS(max_count);
3897 int first = (max_count>0?start_index:start_index+max_count+1);
3903 num_to_get = MIN(num_to_get,count-first);
3906 for (i=first;i<first+num_to_get;i++) {
3907 srv_put_dos_date2(p,0,queue[i].time);
3908 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3909 SSVAL(p,5, queue[i].job);
3910 SIVAL(p,7,queue[i].size);
3912 srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+12,
3913 queue[i].fs_user, 16, STR_ASCII);
3918 outsize = set_message(inbuf,outbuf,2,28*count+3,False);
3919 SSVAL(outbuf,smb_vwv0,count);
3920 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3921 SCVAL(smb_buf(outbuf),0,1);
3922 SSVAL(smb_buf(outbuf),1,28*count);
3927 DEBUG(3,("%d entries returned in queue\n",count));
3930 END_PROFILE(SMBsplretq);
3934 /****************************************************************************
3935 Reply to a printwrite.
3936 ****************************************************************************/
3938 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3941 int outsize = set_message(inbuf,outbuf,0,0,False);
3943 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3945 START_PROFILE(SMBsplwr);
3947 if (!CAN_PRINT(conn)) {
3948 END_PROFILE(SMBsplwr);
3949 return ERROR_DOS(ERRDOS,ERRnoaccess);
3952 CHECK_FSP(fsp,conn);
3953 if (!CHECK_WRITE(fsp)) {
3954 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3957 numtowrite = SVAL(smb_buf(inbuf),1);
3958 data = smb_buf(inbuf) + 3;
3960 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3961 END_PROFILE(SMBsplwr);
3962 return(UNIXERROR(ERRHRD,ERRdiskfull));
3965 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3967 END_PROFILE(SMBsplwr);
3971 /****************************************************************************
3973 ****************************************************************************/
3975 void reply_mkdir(connection_struct *conn, struct smb_request *req)
3979 SMB_STRUCT_STAT sbuf;
3981 START_PROFILE(SMBmkdir);
3983 srvstr_get_path((char *)req->inbuf, req->flags2, directory,
3984 smb_buf(req->inbuf) + 1, sizeof(directory), 0,
3985 STR_TERMINATE, &status);
3986 if (!NT_STATUS_IS_OK(status)) {
3987 reply_nterror(req, status);
3988 END_PROFILE(SMBmkdir);
3992 status = resolve_dfspath(conn,
3993 req->flags2 & FLAGS2_DFS_PATHNAMES,
3995 if (!NT_STATUS_IS_OK(status)) {
3996 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3997 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3998 ERRSRV, ERRbadpath);
3999 END_PROFILE(SMBmkdir);
4002 reply_nterror(req, status);
4003 END_PROFILE(SMBmkdir);
4007 status = unix_convert(conn, directory, False, NULL, &sbuf);
4008 if (!NT_STATUS_IS_OK(status)) {
4009 reply_nterror(req, status);
4010 END_PROFILE(SMBmkdir);
4014 status = check_name(conn, directory);
4015 if (!NT_STATUS_IS_OK(status)) {
4016 reply_nterror(req, status);
4017 END_PROFILE(SMBmkdir);
4021 status = create_directory(conn, directory);
4023 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4025 if (!NT_STATUS_IS_OK(status)) {
4027 if (!use_nt_status()
4028 && NT_STATUS_EQUAL(status,
4029 NT_STATUS_OBJECT_NAME_COLLISION)) {
4031 * Yes, in the DOS error code case we get a
4032 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4033 * samba4 torture test.
4035 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4038 reply_nterror(req, status);
4039 END_PROFILE(SMBmkdir);
4043 reply_outbuf(req, 0, 0);
4045 DEBUG( 3, ( "mkdir %s\n", directory ) );
4047 END_PROFILE(SMBmkdir);
4051 /****************************************************************************
4052 Static function used by reply_rmdir to delete an entire directory
4053 tree recursively. Return True on ok, False on fail.
4054 ****************************************************************************/
4056 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
4058 const char *dname = NULL;
4061 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4066 while((dname = ReadDirName(dir_hnd, &offset))) {
4070 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4073 if (!is_visible_file(conn, directory, dname, &st, False))
4076 /* Construct the full name. */
4077 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4083 pstrcpy(fullname, directory);
4084 pstrcat(fullname, "/");
4085 pstrcat(fullname, dname);
4087 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4092 if(st.st_mode & S_IFDIR) {
4093 if(!recursive_rmdir(conn, fullname)) {
4097 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4101 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4110 /****************************************************************************
4111 The internals of the rmdir code - called elsewhere.
4112 ****************************************************************************/
4114 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4119 /* Might be a symlink. */
4120 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4121 return map_nt_error_from_unix(errno);
4124 if (S_ISLNK(st.st_mode)) {
4125 /* Is what it points to a directory ? */
4126 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4127 return map_nt_error_from_unix(errno);
4129 if (!(S_ISDIR(st.st_mode))) {
4130 return NT_STATUS_NOT_A_DIRECTORY;
4132 ret = SMB_VFS_UNLINK(conn,directory);
4134 ret = SMB_VFS_RMDIR(conn,directory);
4137 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4138 FILE_NOTIFY_CHANGE_DIR_NAME,
4140 return NT_STATUS_OK;
4143 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4145 * Check to see if the only thing in this directory are
4146 * vetoed files/directories. If so then delete them and
4147 * retry. If we fail to delete any of them (and we *don't*
4148 * do a recursive delete) then fail the rmdir.
4152 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4154 if(dir_hnd == NULL) {
4159 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4160 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4162 if (!is_visible_file(conn, directory, dname, &st, False))
4164 if(!IS_VETO_PATH(conn, dname)) {
4171 /* We only have veto files/directories. Recursive delete. */
4173 RewindDir(dir_hnd,&dirpos);
4174 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4177 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4179 if (!is_visible_file(conn, directory, dname, &st, False))
4182 /* Construct the full name. */
4183 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4188 pstrcpy(fullname, directory);
4189 pstrcat(fullname, "/");
4190 pstrcat(fullname, dname);
4192 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4194 if(st.st_mode & S_IFDIR) {
4195 if(lp_recursive_veto_delete(SNUM(conn))) {
4196 if(!recursive_rmdir(conn, fullname))
4199 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4201 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4205 /* Retry the rmdir */
4206 ret = SMB_VFS_RMDIR(conn,directory);
4212 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4213 "%s\n", directory,strerror(errno)));
4214 return map_nt_error_from_unix(errno);
4217 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4218 FILE_NOTIFY_CHANGE_DIR_NAME,
4221 return NT_STATUS_OK;
4224 /****************************************************************************
4226 ****************************************************************************/
4228 void reply_rmdir(connection_struct *conn, struct smb_request *req)
4231 SMB_STRUCT_STAT sbuf;
4233 START_PROFILE(SMBrmdir);
4235 srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4236 smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4237 STR_TERMINATE, &status);
4238 if (!NT_STATUS_IS_OK(status)) {
4239 reply_nterror(req, status);
4240 END_PROFILE(SMBrmdir);
4244 status = resolve_dfspath(conn,
4245 req->flags2 & FLAGS2_DFS_PATHNAMES,
4247 if (!NT_STATUS_IS_OK(status)) {
4248 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4249 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4250 ERRSRV, ERRbadpath);
4251 END_PROFILE(SMBrmdir);
4254 reply_nterror(req, status);
4255 END_PROFILE(SMBrmdir);
4259 status = unix_convert(conn, directory, False, NULL, &sbuf);
4260 if (!NT_STATUS_IS_OK(status)) {
4261 reply_nterror(req, status);
4262 END_PROFILE(SMBrmdir);
4266 status = check_name(conn, directory);
4267 if (!NT_STATUS_IS_OK(status)) {
4268 reply_nterror(req, status);
4269 END_PROFILE(SMBrmdir);
4273 dptr_closepath(directory, req->smbpid);
4274 status = rmdir_internals(conn, directory);
4275 if (!NT_STATUS_IS_OK(status)) {
4276 reply_nterror(req, status);
4277 END_PROFILE(SMBrmdir);
4281 reply_outbuf(req, 0, 0);
4283 DEBUG( 3, ( "rmdir %s\n", directory ) );
4285 END_PROFILE(SMBrmdir);
4289 /*******************************************************************
4290 Resolve wildcards in a filename rename.
4291 Note that name is in UNIX charset and thus potentially can be more
4292 than fstring buffer (255 bytes) especially in default UTF-8 case.
4293 Therefore, we use pstring inside and all calls should ensure that
4294 name2 is at least pstring-long (they do already)
4295 ********************************************************************/
4297 static BOOL resolve_wildcards(const char *name1, char *name2)
4299 pstring root1,root2;
4301 char *p,*p2, *pname1, *pname2;
4302 int available_space, actual_space;
4304 pname1 = strrchr_m(name1,'/');
4305 pname2 = strrchr_m(name2,'/');
4307 if (!pname1 || !pname2)
4310 pstrcpy(root1,pname1);
4311 pstrcpy(root2,pname2);
4312 p = strrchr_m(root1,'.');
4319 p = strrchr_m(root2,'.');
4333 } else if (*p2 == '*') {
4349 } else if (*p2 == '*') {
4359 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4362 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4363 if (actual_space >= available_space - 1) {
4364 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4365 actual_space - available_space));
4368 pstrcpy_base(pname2, root2, name2);
4374 /****************************************************************************
4375 Ensure open files have their names updated. Updated to notify other smbd's
4377 ****************************************************************************/
4379 static void rename_open_files(connection_struct *conn,
4380 struct share_mode_lock *lck,
4381 const char *newname)
4384 BOOL did_rename = False;
4386 for(fsp = file_find_di_first(lck->id); fsp;
4387 fsp = file_find_di_next(fsp)) {
4388 /* fsp_name is a relative path under the fsp. To change this for other
4389 sharepaths we need to manipulate relative paths. */
4390 /* TODO - create the absolute path and manipulate the newname
4391 relative to the sharepath. */
4392 if (fsp->conn != conn) {
4395 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4396 fsp->fnum, file_id_static_string(&fsp->file_id),
4397 fsp->fsp_name, newname ));
4398 string_set(&fsp->fsp_name, newname);
4403 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4404 file_id_static_string(&lck->id), newname ));
4407 /* Send messages to all smbd's (not ourself) that the name has changed. */
4408 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4412 /****************************************************************************
4413 We need to check if the source path is a parent directory of the destination
4414 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4415 refuse the rename with a sharing violation. Under UNIX the above call can
4416 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4417 probably need to check that the client is a Windows one before disallowing
4418 this as a UNIX client (one with UNIX extensions) can know the source is a
4419 symlink and make this decision intelligently. Found by an excellent bug
4420 report from <AndyLiebman@aol.com>.
4421 ****************************************************************************/
4423 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4425 const char *psrc = src;
4426 const char *pdst = dest;
4429 if (psrc[0] == '.' && psrc[1] == '/') {
4432 if (pdst[0] == '.' && pdst[1] == '/') {
4435 if ((slen = strlen(psrc)) > strlen(pdst)) {
4438 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4442 * Do the notify calls from a rename
4445 static void notify_rename(connection_struct *conn, BOOL is_dir,
4446 const char *oldpath, const char *newpath)
4448 char *olddir, *newdir;
4449 const char *oldname, *newname;
4452 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4453 : FILE_NOTIFY_CHANGE_FILE_NAME;
4455 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4456 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4457 TALLOC_FREE(olddir);
4461 if (strcmp(olddir, newdir) == 0) {
4462 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4463 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4466 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4467 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4469 TALLOC_FREE(olddir);
4470 TALLOC_FREE(newdir);
4472 /* this is a strange one. w2k3 gives an additional event for
4473 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4474 files, but not directories */
4476 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4477 FILE_NOTIFY_CHANGE_ATTRIBUTES
4478 |FILE_NOTIFY_CHANGE_CREATION,
4483 /****************************************************************************
4484 Rename an open file - given an fsp.
4485 ****************************************************************************/
4487 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4489 SMB_STRUCT_STAT sbuf, sbuf1;
4490 pstring newname_last_component;
4491 NTSTATUS status = NT_STATUS_OK;
4492 struct share_mode_lock *lck = NULL;
4497 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4499 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4501 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4505 status = check_name(conn, newname);
4506 if (!NT_STATUS_IS_OK(status)) {
4510 /* Ensure newname contains a '/' */
4511 if(strrchr_m(newname,'/') == 0) {
4514 pstrcpy(tmpstr, "./");
4515 pstrcat(tmpstr, newname);
4516 pstrcpy(newname, tmpstr);
4520 * Check for special case with case preserving and not
4521 * case sensitive. If the old last component differs from the original
4522 * last component only by case, then we should allow
4523 * the rename (user is trying to change the case of the
4527 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4528 strequal(newname, fsp->fsp_name)) {
4530 pstring newname_modified_last_component;
4533 * Get the last component of the modified name.
4534 * Note that we guarantee that newname contains a '/'
4537 p = strrchr_m(newname,'/');
4538 pstrcpy(newname_modified_last_component,p+1);
4540 if(strcsequal(newname_modified_last_component,
4541 newname_last_component) == False) {
4543 * Replace the modified last component with
4546 pstrcpy(p+1, newname_last_component);
4551 * If the src and dest names are identical - including case,
4552 * don't do the rename, just return success.
4555 if (strcsequal(fsp->fsp_name, newname)) {
4556 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4558 return NT_STATUS_OK;
4562 * Have vfs_object_exist also fill sbuf1
4564 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4566 if(!replace_if_exists && dst_exists) {
4567 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4568 fsp->fsp_name,newname));
4569 return NT_STATUS_OBJECT_NAME_COLLISION;
4573 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
4574 files_struct *dst_fsp = file_find_di_first(fileid);
4576 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4577 return NT_STATUS_ACCESS_DENIED;
4581 /* Ensure we have a valid stat struct for the source. */
4582 if (fsp->fh->fd != -1) {
4583 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4584 return map_nt_error_from_unix(errno);
4587 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4588 return map_nt_error_from_unix(errno);
4592 status = can_rename(conn, fsp, attrs, &sbuf);
4594 if (!NT_STATUS_IS_OK(status)) {
4595 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4596 nt_errstr(status), fsp->fsp_name,newname));
4597 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4598 status = NT_STATUS_ACCESS_DENIED;
4602 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4603 return NT_STATUS_ACCESS_DENIED;
4606 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4609 * We have the file open ourselves, so not being able to get the
4610 * corresponding share mode lock is a fatal error.
4613 SMB_ASSERT(lck != NULL);
4615 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4616 uint32 create_options = fsp->fh->private_options;
4618 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4619 fsp->fsp_name,newname));
4621 rename_open_files(conn, lck, newname);
4623 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4626 * A rename acts as a new file create w.r.t. allowing an initial delete
4627 * on close, probably because in Windows there is a new handle to the
4628 * new file. If initial delete on close was requested but not
4629 * originally set, we need to set it here. This is probably not 100% correct,
4630 * but will work for the CIFSFS client which in non-posix mode
4631 * depends on these semantics. JRA.
4634 set_allow_initial_delete_on_close(lck, fsp, True);
4636 if (create_options & FILE_DELETE_ON_CLOSE) {
4637 status = can_set_delete_on_close(fsp, True, 0);
4639 if (NT_STATUS_IS_OK(status)) {
4640 /* Note that here we set the *inital* delete on close flag,
4641 * not the regular one. The magic gets handled in close. */
4642 fsp->initial_delete_on_close = True;
4646 return NT_STATUS_OK;
4651 if (errno == ENOTDIR || errno == EISDIR) {
4652 status = NT_STATUS_OBJECT_NAME_COLLISION;
4654 status = map_nt_error_from_unix(errno);
4657 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4658 nt_errstr(status), fsp->fsp_name,newname));
4663 /****************************************************************************
4664 The guts of the rename command, split out so it may be called by the NT SMB
4666 ****************************************************************************/
4668 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
4672 BOOL replace_if_exists,
4678 pstring last_component_src;
4679 pstring last_component_dest;
4682 NTSTATUS status = NT_STATUS_OK;
4683 SMB_STRUCT_STAT sbuf1, sbuf2;
4684 struct smb_Dir *dir_hnd = NULL;
4689 *directory = *mask = 0;
4694 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4695 if (!NT_STATUS_IS_OK(status)) {
4699 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4700 if (!NT_STATUS_IS_OK(status)) {
4705 * Split the old name into directory and last component
4706 * strings. Note that unix_convert may have stripped off a
4707 * leading ./ from both name and newname if the rename is
4708 * at the root of the share. We need to make sure either both
4709 * name and newname contain a / character or neither of them do
4710 * as this is checked in resolve_wildcards().
4713 p = strrchr_m(name,'/');
4715 pstrcpy(directory,".");
4719 pstrcpy(directory,name);
4721 *p = '/'; /* Replace needed for exceptional test below. */
4725 * We should only check the mangled cache
4726 * here if unix_convert failed. This means
4727 * that the path in 'mask' doesn't exist
4728 * on the file system and so we need to look
4729 * for a possible mangle. This patch from
4730 * Tine Smukavec <valentin.smukavec@hermes.si>.
4733 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4734 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4737 if (!src_has_wild) {
4741 * No wildcards - just process the one file.
4743 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4745 /* Add a terminating '/' to the directory name. */
4746 pstrcat(directory,"/");
4747 pstrcat(directory,mask);
4749 /* Ensure newname contains a '/' also */
4750 if(strrchr_m(newname,'/') == 0) {
4753 pstrcpy(tmpstr, "./");
4754 pstrcat(tmpstr, newname);
4755 pstrcpy(newname, tmpstr);
4758 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4759 "case_preserve = %d, short case preserve = %d, "
4760 "directory = %s, newname = %s, "
4761 "last_component_dest = %s, is_8_3 = %d\n",
4762 conn->case_sensitive, conn->case_preserve,
4763 conn->short_case_preserve, directory,
4764 newname, last_component_dest, is_short_name));
4766 /* The dest name still may have wildcards. */
4767 if (dest_has_wild) {
4768 if (!resolve_wildcards(directory,newname)) {
4769 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4770 directory,newname));
4771 return NT_STATUS_NO_MEMORY;
4776 SMB_VFS_STAT(conn, directory, &sbuf1);
4778 status = S_ISDIR(sbuf1.st_mode) ?
4779 open_directory(conn, req, directory, &sbuf1,
4781 FILE_SHARE_READ|FILE_SHARE_WRITE,
4782 FILE_OPEN, 0, 0, NULL,
4784 : open_file_ntcreate(conn, req, directory, &sbuf1,
4786 FILE_SHARE_READ|FILE_SHARE_WRITE,
4787 FILE_OPEN, 0, 0, 0, NULL,
4790 if (!NT_STATUS_IS_OK(status)) {
4791 DEBUG(3, ("Could not open rename source %s: %s\n",
4792 directory, nt_errstr(status)));
4796 status = rename_internals_fsp(conn, fsp, newname, attrs,
4799 close_file(fsp, NORMAL_CLOSE);
4801 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4802 nt_errstr(status), directory,newname));
4808 * Wildcards - process each file that matches.
4810 if (strequal(mask,"????????.???")) {
4814 status = check_name(conn, directory);
4815 if (!NT_STATUS_IS_OK(status)) {
4819 dir_hnd = OpenDir(conn, directory, mask, attrs);
4820 if (dir_hnd == NULL) {
4821 return map_nt_error_from_unix(errno);
4824 status = NT_STATUS_NO_SUCH_FILE;
4826 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4827 * - gentest fix. JRA
4830 while ((dname = ReadDirName(dir_hnd, &offset))) {
4833 BOOL sysdir_entry = False;
4835 pstrcpy(fname,dname);
4837 /* Quick check for "." and ".." */
4838 if (fname[0] == '.') {
4839 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4841 sysdir_entry = True;
4848 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4852 if(!mask_match(fname, mask, conn->case_sensitive)) {
4857 status = NT_STATUS_OBJECT_NAME_INVALID;
4861 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4863 pstrcpy(destname,newname);
4865 if (!resolve_wildcards(fname,destname)) {
4866 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4872 SMB_VFS_STAT(conn, fname, &sbuf1);
4874 status = S_ISDIR(sbuf1.st_mode) ?
4875 open_directory(conn, req, fname, &sbuf1,
4877 FILE_SHARE_READ|FILE_SHARE_WRITE,
4878 FILE_OPEN, 0, 0, NULL,
4880 : open_file_ntcreate(conn, req, fname, &sbuf1,
4882 FILE_SHARE_READ|FILE_SHARE_WRITE,
4883 FILE_OPEN, 0, 0, 0, NULL,
4886 if (!NT_STATUS_IS_OK(status)) {
4887 DEBUG(3,("rename_internals: open_file_ntcreate "
4888 "returned %s rename %s -> %s\n",
4889 nt_errstr(status), directory, newname));
4893 status = rename_internals_fsp(conn, fsp, destname, attrs,
4896 close_file(fsp, NORMAL_CLOSE);
4898 if (!NT_STATUS_IS_OK(status)) {
4899 DEBUG(3, ("rename_internals_fsp returned %s for "
4900 "rename %s -> %s\n", nt_errstr(status),
4901 directory, newname));
4907 DEBUG(3,("rename_internals: doing rename on %s -> "
4908 "%s\n",fname,destname));
4912 if (count == 0 && NT_STATUS_IS_OK(status)) {
4913 status = map_nt_error_from_unix(errno);
4919 /****************************************************************************
4921 ****************************************************************************/
4923 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4930 uint32 attrs = SVAL(inbuf,smb_vwv0);
4932 BOOL src_has_wcard = False;
4933 BOOL dest_has_wcard = False;
4934 struct smb_request req;
4936 START_PROFILE(SMBmv);
4938 init_smb_request(&req, (uint8 *)inbuf);
4940 p = smb_buf(inbuf) + 1;
4941 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
4942 sizeof(name), 0, STR_TERMINATE, &status,
4944 if (!NT_STATUS_IS_OK(status)) {
4946 return ERROR_NT(status);
4949 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
4950 sizeof(newname), 0, STR_TERMINATE, &status,
4952 if (!NT_STATUS_IS_OK(status)) {
4954 return ERROR_NT(status);
4957 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
4958 if (!NT_STATUS_IS_OK(status)) {
4960 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4961 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4963 return ERROR_NT(status);
4966 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4967 if (!NT_STATUS_IS_OK(status)) {
4969 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4970 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4972 return ERROR_NT(status);
4975 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4977 status = rename_internals(conn, &req, name, newname, attrs, False,
4978 src_has_wcard, dest_has_wcard);
4979 if (!NT_STATUS_IS_OK(status)) {
4981 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4982 /* We have re-scheduled this call. */
4985 return ERROR_NT(status);
4988 outsize = set_message(inbuf,outbuf,0,0,False);
4994 /*******************************************************************
4995 Copy a file as part of a reply_copy.
4996 ******************************************************************/
4999 * TODO: check error codes on all callers
5002 NTSTATUS copy_file(connection_struct *conn,
5007 BOOL target_is_directory)
5009 SMB_STRUCT_STAT src_sbuf, sbuf2;
5011 files_struct *fsp1,*fsp2;
5014 uint32 new_create_disposition;
5017 pstrcpy(dest,dest1);
5018 if (target_is_directory) {
5019 char *p = strrchr_m(src,'/');
5029 if (!vfs_file_exist(conn,src,&src_sbuf)) {
5030 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5033 if (!target_is_directory && count) {
5034 new_create_disposition = FILE_OPEN;
5036 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5037 NULL, NULL, &new_create_disposition, NULL)) {
5038 return NT_STATUS_INVALID_PARAMETER;
5042 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5044 FILE_SHARE_READ|FILE_SHARE_WRITE,
5047 FILE_ATTRIBUTE_NORMAL,
5051 if (!NT_STATUS_IS_OK(status)) {
5055 dosattrs = dos_mode(conn, src, &src_sbuf);
5056 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
5057 ZERO_STRUCTP(&sbuf2);
5060 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
5062 FILE_SHARE_READ|FILE_SHARE_WRITE,
5063 new_create_disposition,
5069 if (!NT_STATUS_IS_OK(status)) {
5070 close_file(fsp1,ERROR_CLOSE);
5074 if ((ofun&3) == 1) {
5075 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
5076 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
5078 * Stop the copy from occurring.
5081 src_sbuf.st_size = 0;
5085 if (src_sbuf.st_size) {
5086 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
5089 close_file(fsp1,NORMAL_CLOSE);
5091 /* Ensure the modtime is set correctly on the destination file. */
5092 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
5095 * As we are opening fsp1 read-only we only expect
5096 * an error on close on fsp2 if we are out of space.
5097 * Thus we don't look at the error return from the
5100 status = close_file(fsp2,NORMAL_CLOSE);
5102 if (!NT_STATUS_IS_OK(status)) {
5106 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
5107 return NT_STATUS_DISK_FULL;
5110 return NT_STATUS_OK;
5113 /****************************************************************************
5114 Reply to a file copy.
5115 ****************************************************************************/
5117 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5122 pstring mask,newname;
5125 int error = ERRnoaccess;
5127 int tid2 = SVAL(inbuf,smb_vwv0);
5128 int ofun = SVAL(inbuf,smb_vwv1);
5129 int flags = SVAL(inbuf,smb_vwv2);
5130 BOOL target_is_directory=False;
5131 BOOL source_has_wild = False;
5132 BOOL dest_has_wild = False;
5133 SMB_STRUCT_STAT sbuf1, sbuf2;
5135 START_PROFILE(SMBcopy);
5137 *directory = *mask = 0;
5140 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5141 sizeof(name), 0, STR_TERMINATE, &status,
5143 if (!NT_STATUS_IS_OK(status)) {
5144 END_PROFILE(SMBcopy);
5145 return ERROR_NT(status);
5147 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5148 sizeof(newname), 0, STR_TERMINATE, &status,
5150 if (!NT_STATUS_IS_OK(status)) {
5151 END_PROFILE(SMBcopy);
5152 return ERROR_NT(status);
5155 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5157 if (tid2 != conn->cnum) {
5158 /* can't currently handle inter share copies XXXX */
5159 DEBUG(3,("Rejecting inter-share copy\n"));
5160 END_PROFILE(SMBcopy);
5161 return ERROR_DOS(ERRSRV,ERRinvdevice);
5164 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5165 if (!NT_STATUS_IS_OK(status)) {
5166 END_PROFILE(SMBcopy);
5167 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5168 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5170 return ERROR_NT(status);
5173 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5174 if (!NT_STATUS_IS_OK(status)) {
5175 END_PROFILE(SMBcopy);
5176 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5177 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5179 return ERROR_NT(status);
5182 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5183 if (!NT_STATUS_IS_OK(status)) {
5184 END_PROFILE(SMBcopy);
5185 return ERROR_NT(status);
5188 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5189 if (!NT_STATUS_IS_OK(status)) {
5190 END_PROFILE(SMBcopy);
5191 return ERROR_NT(status);
5194 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5196 if ((flags&1) && target_is_directory) {
5197 END_PROFILE(SMBcopy);
5198 return ERROR_DOS(ERRDOS,ERRbadfile);
5201 if ((flags&2) && !target_is_directory) {
5202 END_PROFILE(SMBcopy);
5203 return ERROR_DOS(ERRDOS,ERRbadpath);
5206 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5207 /* wants a tree copy! XXXX */
5208 DEBUG(3,("Rejecting tree copy\n"));
5209 END_PROFILE(SMBcopy);
5210 return ERROR_DOS(ERRSRV,ERRerror);
5213 p = strrchr_m(name,'/');
5215 pstrcpy(directory,"./");
5219 pstrcpy(directory,name);
5224 * We should only check the mangled cache
5225 * here if unix_convert failed. This means
5226 * that the path in 'mask' doesn't exist
5227 * on the file system and so we need to look
5228 * for a possible mangle. This patch from
5229 * Tine Smukavec <valentin.smukavec@hermes.si>.
5232 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5233 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5236 if (!source_has_wild) {
5237 pstrcat(directory,"/");
5238 pstrcat(directory,mask);
5239 if (dest_has_wild) {
5240 if (!resolve_wildcards(directory,newname)) {
5241 END_PROFILE(SMBcopy);
5242 return ERROR_NT(NT_STATUS_NO_MEMORY);
5246 status = check_name(conn, directory);
5247 if (!NT_STATUS_IS_OK(status)) {
5248 return ERROR_NT(status);
5251 status = check_name(conn, newname);
5252 if (!NT_STATUS_IS_OK(status)) {
5253 return ERROR_NT(status);
5256 status = copy_file(conn,directory,newname,ofun,
5257 count,target_is_directory);
5259 if(!NT_STATUS_IS_OK(status)) {
5260 END_PROFILE(SMBcopy);
5261 return ERROR_NT(status);
5266 struct smb_Dir *dir_hnd = NULL;
5271 if (strequal(mask,"????????.???"))
5274 status = check_name(conn, directory);
5275 if (!NT_STATUS_IS_OK(status)) {
5276 return ERROR_NT(status);
5279 dir_hnd = OpenDir(conn, directory, mask, 0);
5280 if (dir_hnd == NULL) {
5281 status = map_nt_error_from_unix(errno);
5282 return ERROR_NT(status);
5287 while ((dname = ReadDirName(dir_hnd, &offset))) {
5289 pstrcpy(fname,dname);
5291 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5295 if(!mask_match(fname, mask, conn->case_sensitive)) {
5299 error = ERRnoaccess;
5300 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5301 pstrcpy(destname,newname);
5302 if (!resolve_wildcards(fname,destname)) {
5306 status = check_name(conn, fname);
5307 if (!NT_STATUS_IS_OK(status)) {
5308 return ERROR_NT(status);
5311 status = check_name(conn, destname);
5312 if (!NT_STATUS_IS_OK(status)) {
5313 return ERROR_NT(status);
5316 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5318 status = copy_file(conn,fname,destname,ofun,
5319 count,target_is_directory);
5320 if (NT_STATUS_IS_OK(status)) {
5329 /* Error on close... */
5331 END_PROFILE(SMBcopy);
5332 return(UNIXERROR(ERRHRD,ERRgeneral));
5335 END_PROFILE(SMBcopy);
5336 return ERROR_DOS(ERRDOS,error);
5339 outsize = set_message(inbuf,outbuf,1,0,True);
5340 SSVAL(outbuf,smb_vwv0,count);
5342 END_PROFILE(SMBcopy);
5346 /****************************************************************************
5348 ****************************************************************************/
5350 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5357 START_PROFILE(pathworks_setdir);
5360 if (!CAN_SETDIR(snum)) {
5361 END_PROFILE(pathworks_setdir);
5362 return ERROR_DOS(ERRDOS,ERRnoaccess);
5365 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
5366 smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
5368 if (!NT_STATUS_IS_OK(status)) {
5369 END_PROFILE(pathworks_setdir);
5370 return ERROR_NT(status);
5373 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5374 if (!NT_STATUS_IS_OK(status)) {
5375 END_PROFILE(pathworks_setdir);
5376 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5377 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5379 return ERROR_NT(status);
5382 if (strlen(newdir) != 0) {
5383 if (!vfs_directory_exist(conn,newdir,NULL)) {
5384 END_PROFILE(pathworks_setdir);
5385 return ERROR_DOS(ERRDOS,ERRbadpath);
5387 set_conn_connectpath(conn,newdir);
5390 outsize = set_message(inbuf,outbuf,0,0,False);
5391 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5393 DEBUG(3,("setdir %s\n", newdir));
5395 END_PROFILE(pathworks_setdir);
5400 #define DBGC_CLASS DBGC_LOCKING
5402 /****************************************************************************
5403 Get a lock pid, dealing with large count requests.
5404 ****************************************************************************/
5406 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5408 if(!large_file_format)
5409 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5411 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5414 /****************************************************************************
5415 Get a lock count, dealing with large count requests.
5416 ****************************************************************************/
5418 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5420 SMB_BIG_UINT count = 0;
5422 if(!large_file_format) {
5423 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5426 #if defined(HAVE_LONGLONG)
5427 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5428 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5429 #else /* HAVE_LONGLONG */
5432 * NT4.x seems to be broken in that it sends large file (64 bit)
5433 * lockingX calls even if the CAP_LARGE_FILES was *not*
5434 * negotiated. For boxes without large unsigned ints truncate the
5435 * lock count by dropping the top 32 bits.
5438 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5439 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5440 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5441 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5442 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5445 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5446 #endif /* HAVE_LONGLONG */
5452 #if !defined(HAVE_LONGLONG)
5453 /****************************************************************************
5454 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5455 ****************************************************************************/
5457 static uint32 map_lock_offset(uint32 high, uint32 low)
5461 uint32 highcopy = high;
5464 * Try and find out how many significant bits there are in high.
5467 for(i = 0; highcopy; i++)
5471 * We use 31 bits not 32 here as POSIX
5472 * lock offsets may not be negative.
5475 mask = (~0) << (31 - i);
5478 return 0; /* Fail. */
5484 #endif /* !defined(HAVE_LONGLONG) */
5486 /****************************************************************************
5487 Get a lock offset, dealing with large offset requests.
5488 ****************************************************************************/
5490 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5492 SMB_BIG_UINT offset = 0;
5496 if(!large_file_format) {
5497 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5500 #if defined(HAVE_LONGLONG)
5501 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5502 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5503 #else /* HAVE_LONGLONG */
5506 * NT4.x seems to be broken in that it sends large file (64 bit)
5507 * lockingX calls even if the CAP_LARGE_FILES was *not*
5508 * negotiated. For boxes without large unsigned ints mangle the
5509 * lock offset by mapping the top 32 bits onto the lower 32.
5512 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5513 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5514 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5517 if((new_low = map_lock_offset(high, low)) == 0) {
5519 return (SMB_BIG_UINT)-1;
5522 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5523 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5524 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5525 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5528 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5529 #endif /* HAVE_LONGLONG */
5535 /****************************************************************************
5536 Reply to a lockingX request.
5537 ****************************************************************************/
5539 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5540 int length, int bufsize)
5542 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
5543 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5544 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5545 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5546 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5547 SMB_BIG_UINT count = 0, offset = 0;
5549 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5552 BOOL large_file_format =
5553 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5555 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5557 START_PROFILE(SMBlockingX);
5559 CHECK_FSP(fsp,conn);
5561 data = smb_buf(inbuf);
5563 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5564 /* we don't support these - and CANCEL_LOCK makes w2k
5565 and XP reboot so I don't really want to be
5566 compatible! (tridge) */
5567 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5570 /* Check if this is an oplock break on a file
5571 we have granted an oplock on.
5573 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5574 /* Client can insist on breaking to none. */
5575 BOOL break_to_none = (oplocklevel == 0);
5578 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5579 "for fnum = %d\n", (unsigned int)oplocklevel,
5583 * Make sure we have granted an exclusive or batch oplock on
5587 if (fsp->oplock_type == 0) {
5589 /* The Samba4 nbench simulator doesn't understand
5590 the difference between break to level2 and break
5591 to none from level2 - it sends oplock break
5592 replies in both cases. Don't keep logging an error
5593 message here - just ignore it. JRA. */
5595 DEBUG(5,("reply_lockingX: Error : oplock break from "
5596 "client for fnum = %d (oplock=%d) and no "
5597 "oplock granted on this file (%s).\n",
5598 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5600 /* if this is a pure oplock break request then don't
5602 if (num_locks == 0 && num_ulocks == 0) {
5603 END_PROFILE(SMBlockingX);
5606 END_PROFILE(SMBlockingX);
5607 return ERROR_DOS(ERRDOS,ERRlock);
5611 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5613 result = remove_oplock(fsp);
5615 result = downgrade_oplock(fsp);
5619 DEBUG(0, ("reply_lockingX: error in removing "
5620 "oplock on file %s\n", fsp->fsp_name));
5621 /* Hmmm. Is this panic justified? */
5622 smb_panic("internal tdb error");
5625 reply_to_oplock_break_requests(fsp);
5627 /* if this is a pure oplock break request then don't send a
5629 if (num_locks == 0 && num_ulocks == 0) {
5630 /* Sanity check - ensure a pure oplock break is not a
5632 if(CVAL(inbuf,smb_vwv0) != 0xff)
5633 DEBUG(0,("reply_lockingX: Error : pure oplock "
5634 "break is a chained %d request !\n",
5635 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5636 END_PROFILE(SMBlockingX);
5642 * We do this check *after* we have checked this is not a oplock break
5643 * response message. JRA.
5646 release_level_2_oplocks_on_change(fsp);
5648 /* Data now points at the beginning of the list
5649 of smb_unlkrng structs */
5650 for(i = 0; i < (int)num_ulocks; i++) {
5651 lock_pid = get_lock_pid( data, i, large_file_format);
5652 count = get_lock_count( data, i, large_file_format);
5653 offset = get_lock_offset( data, i, large_file_format, &err);
5656 * There is no error code marked "stupid client bug".... :-).
5659 END_PROFILE(SMBlockingX);
5660 return ERROR_DOS(ERRDOS,ERRnoaccess);
5663 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5664 "pid %u, file %s\n", (double)offset, (double)count,
5665 (unsigned int)lock_pid, fsp->fsp_name ));
5667 status = do_unlock(smbd_messaging_context(),
5674 if (NT_STATUS_V(status)) {
5675 END_PROFILE(SMBlockingX);
5676 return ERROR_NT(status);
5680 /* Setup the timeout in seconds. */
5682 if (!lp_blocking_locks(SNUM(conn))) {
5686 /* Now do any requested locks */
5687 data += ((large_file_format ? 20 : 10)*num_ulocks);
5689 /* Data now points at the beginning of the list
5690 of smb_lkrng structs */
5692 for(i = 0; i < (int)num_locks; i++) {
5693 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5694 READ_LOCK:WRITE_LOCK);
5695 lock_pid = get_lock_pid( data, i, large_file_format);
5696 count = get_lock_count( data, i, large_file_format);
5697 offset = get_lock_offset( data, i, large_file_format, &err);
5700 * There is no error code marked "stupid client bug".... :-).
5703 END_PROFILE(SMBlockingX);
5704 return ERROR_DOS(ERRDOS,ERRnoaccess);
5707 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5708 "%u, file %s timeout = %d\n", (double)offset,
5709 (double)count, (unsigned int)lock_pid,
5710 fsp->fsp_name, (int)lock_timeout ));
5712 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5713 if (lp_blocking_locks(SNUM(conn))) {
5715 /* Schedule a message to ourselves to
5716 remove the blocking lock record and
5717 return the right error. */
5719 if (!blocking_lock_cancel(fsp,
5725 NT_STATUS_FILE_LOCK_CONFLICT)) {
5726 END_PROFILE(SMBlockingX);
5727 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5730 /* Remove a matching pending lock. */
5731 status = do_lock_cancel(fsp,
5737 BOOL blocking_lock = lock_timeout ? True : False;
5738 BOOL defer_lock = False;
5739 struct byte_range_lock *br_lck;
5740 uint32 block_smbpid;
5742 br_lck = do_lock(smbd_messaging_context(),
5753 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5754 /* Windows internal resolution for blocking locks seems
5755 to be about 200ms... Don't wait for less than that. JRA. */
5756 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5757 lock_timeout = lp_lock_spin_time();
5762 /* This heuristic seems to match W2K3 very well. If a
5763 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5764 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5765 far as I can tell. Replacement for do_lock_spin(). JRA. */
5767 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5768 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5770 lock_timeout = lp_lock_spin_time();
5773 if (br_lck && defer_lock) {
5775 * A blocking lock was requested. Package up
5776 * this smb into a queued request and push it
5777 * onto the blocking lock queue.
5779 if(push_blocking_lock_request(br_lck,
5790 TALLOC_FREE(br_lck);
5791 END_PROFILE(SMBlockingX);
5796 TALLOC_FREE(br_lck);
5799 if (NT_STATUS_V(status)) {
5800 END_PROFILE(SMBlockingX);
5801 return ERROR_NT(status);
5805 /* If any of the above locks failed, then we must unlock
5806 all of the previous locks (X/Open spec). */
5808 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5812 * Ensure we don't do a remove on the lock that just failed,
5813 * as under POSIX rules, if we have a lock already there, we
5814 * will delete it (and we shouldn't) .....
5816 for(i--; i >= 0; i--) {
5817 lock_pid = get_lock_pid( data, i, large_file_format);
5818 count = get_lock_count( data, i, large_file_format);
5819 offset = get_lock_offset( data, i, large_file_format,
5823 * There is no error code marked "stupid client
5827 END_PROFILE(SMBlockingX);
5828 return ERROR_DOS(ERRDOS,ERRnoaccess);
5831 do_unlock(smbd_messaging_context(),
5838 END_PROFILE(SMBlockingX);
5839 return ERROR_NT(status);
5842 set_message(inbuf,outbuf,2,0,True);
5844 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5845 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5847 END_PROFILE(SMBlockingX);
5848 return chain_reply(inbuf,&outbuf,length,bufsize);
5852 #define DBGC_CLASS DBGC_ALL
5854 /****************************************************************************
5855 Reply to a SMBreadbmpx (read block multiplex) request.
5856 ****************************************************************************/
5858 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5869 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
5870 START_PROFILE(SMBreadBmpx);
5872 /* this function doesn't seem to work - disable by default */
5873 if (!lp_readbmpx()) {
5874 END_PROFILE(SMBreadBmpx);
5875 return ERROR_DOS(ERRSRV,ERRuseSTD);
5878 outsize = set_message(inbuf,outbuf,8,0,True);
5880 CHECK_FSP(fsp,conn);
5881 if (!CHECK_READ(fsp,inbuf)) {
5882 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5885 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5886 maxcount = SVAL(inbuf,smb_vwv3);
5888 data = smb_buf(outbuf);
5889 pad = ((long)data)%4;
5894 max_per_packet = bufsize-(outsize+pad);
5898 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5899 END_PROFILE(SMBreadBmpx);
5900 return ERROR_DOS(ERRDOS,ERRlock);
5904 size_t N = MIN(max_per_packet,tcount-total_read);
5906 nread = read_file(fsp,data,startpos,N);
5911 if (nread < (ssize_t)N)
5912 tcount = total_read + nread;
5914 set_message(inbuf,outbuf,8,nread+pad,False);
5915 SIVAL(outbuf,smb_vwv0,startpos);
5916 SSVAL(outbuf,smb_vwv2,tcount);
5917 SSVAL(outbuf,smb_vwv6,nread);
5918 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5921 if (!send_smb(smbd_server_fd(),outbuf))
5922 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5924 total_read += nread;
5926 } while (total_read < (ssize_t)tcount);
5928 END_PROFILE(SMBreadBmpx);
5932 /****************************************************************************
5933 Reply to a SMBsetattrE.
5934 ****************************************************************************/
5936 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5938 struct timespec ts[2];
5940 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
5941 START_PROFILE(SMBsetattrE);
5943 outsize = set_message(inbuf,outbuf,0,0,False);
5945 if(!fsp || (fsp->conn != conn)) {
5946 END_PROFILE(SMBsetattrE);
5947 return ERROR_DOS(ERRDOS,ERRbadfid);
5951 * Convert the DOS times into unix times. Ignore create
5952 * time as UNIX can't set this.
5955 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5956 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5959 * Patch from Ray Frush <frush@engr.colostate.edu>
5960 * Sometimes times are sent as zero - ignore them.
5963 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5964 /* Ignore request */
5965 if( DEBUGLVL( 3 ) ) {
5966 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5967 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5969 END_PROFILE(SMBsetattrE);
5971 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5972 /* set modify time = to access time if modify time was unset */
5976 /* Set the date on this file */
5977 /* Should we set pending modtime here ? JRA */
5978 if(file_ntimes(conn, fsp->fsp_name, ts)) {
5979 END_PROFILE(SMBsetattrE);
5980 return ERROR_DOS(ERRDOS,ERRnoaccess);
5983 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5985 (unsigned int)ts[0].tv_sec,
5986 (unsigned int)ts[1].tv_sec));
5988 END_PROFILE(SMBsetattrE);
5993 /* Back from the dead for OS/2..... JRA. */
5995 /****************************************************************************
5996 Reply to a SMBwritebmpx (write block multiplex primary) request.
5997 ****************************************************************************/
5999 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6002 ssize_t nwritten = -1;
6009 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6011 START_PROFILE(SMBwriteBmpx);
6013 CHECK_FSP(fsp,conn);
6014 if (!CHECK_WRITE(fsp)) {
6015 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6017 if (HAS_CACHED_ERROR(fsp)) {
6018 return(CACHED_ERROR(fsp));
6021 tcount = SVAL(inbuf,smb_vwv1);
6022 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
6023 write_through = BITSETW(inbuf+smb_vwv7,0);
6024 numtowrite = SVAL(inbuf,smb_vwv10);
6025 smb_doff = SVAL(inbuf,smb_vwv11);
6027 data = smb_base(inbuf) + smb_doff;
6029 /* If this fails we need to send an SMBwriteC response,
6030 not an SMBwritebmpx - set this up now so we don't forget */
6031 SCVAL(outbuf,smb_com,SMBwritec);
6033 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
6034 END_PROFILE(SMBwriteBmpx);
6035 return(ERROR_DOS(ERRDOS,ERRlock));
6038 nwritten = write_file(fsp,data,startpos,numtowrite);
6040 status = sync_file(conn, fsp, write_through);
6041 if (!NT_STATUS_IS_OK(status)) {
6042 END_PROFILE(SMBwriteBmpx);
6043 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
6044 fsp->fsp_name, nt_errstr(status) ));
6045 return ERROR_NT(status);
6048 if(nwritten < (ssize_t)numtowrite) {
6049 END_PROFILE(SMBwriteBmpx);
6050 return(UNIXERROR(ERRHRD,ERRdiskfull));
6053 /* If the maximum to be written to this file
6054 is greater than what we just wrote then set
6055 up a secondary struct to be attached to this
6056 fd, we will use this to cache error messages etc. */
6058 if((ssize_t)tcount > nwritten) {
6059 write_bmpx_struct *wbms;
6060 if(fsp->wbmpx_ptr != NULL)
6061 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
6063 wbms = SMB_MALLOC_P(write_bmpx_struct);
6065 DEBUG(0,("Out of memory in reply_readmpx\n"));
6066 END_PROFILE(SMBwriteBmpx);
6067 return(ERROR_DOS(ERRSRV,ERRnoresource));
6069 wbms->wr_mode = write_through;
6070 wbms->wr_discard = False; /* No errors yet */
6071 wbms->wr_total_written = nwritten;
6072 wbms->wr_errclass = 0;
6074 fsp->wbmpx_ptr = wbms;
6077 /* We are returning successfully, set the message type back to
6079 SCVAL(outbuf,smb_com,SMBwriteBmpx);
6081 outsize = set_message(inbuf,outbuf,1,0,True);
6083 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
6085 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
6086 fsp->fnum, (int)numtowrite, (int)nwritten ) );
6088 if (write_through && tcount==nwritten) {
6089 /* We need to send both a primary and a secondary response */
6090 smb_setlen(inbuf,outbuf,outsize - 4);
6092 if (!send_smb(smbd_server_fd(),outbuf))
6093 exit_server_cleanly("reply_writebmpx: send_smb failed.");
6095 /* Now the secondary */
6096 outsize = set_message(inbuf,outbuf,1,0,True);
6097 SCVAL(outbuf,smb_com,SMBwritec);
6098 SSVAL(outbuf,smb_vwv0,nwritten);
6101 END_PROFILE(SMBwriteBmpx);
6105 /****************************************************************************
6106 Reply to a SMBwritebs (write block multiplex secondary) request.
6107 ****************************************************************************/
6109 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
6112 ssize_t nwritten = -1;
6119 write_bmpx_struct *wbms;
6120 BOOL send_response = False;
6121 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6123 START_PROFILE(SMBwriteBs);
6125 CHECK_FSP(fsp,conn);
6126 if (!CHECK_WRITE(fsp)) {
6127 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6130 tcount = SVAL(inbuf,smb_vwv1);
6131 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6132 numtowrite = SVAL(inbuf,smb_vwv6);
6133 smb_doff = SVAL(inbuf,smb_vwv7);
6135 data = smb_base(inbuf) + smb_doff;
6137 /* We need to send an SMBwriteC response, not an SMBwritebs */
6138 SCVAL(outbuf,smb_com,SMBwritec);
6140 /* This fd should have an auxiliary struct attached,
6141 check that it does */
6142 wbms = fsp->wbmpx_ptr;
6144 END_PROFILE(SMBwriteBs);
6148 /* If write through is set we can return errors, else we must cache them */
6149 write_through = wbms->wr_mode;
6151 /* Check for an earlier error */
6152 if(wbms->wr_discard) {
6153 END_PROFILE(SMBwriteBs);
6154 return -1; /* Just discard the packet */
6157 nwritten = write_file(fsp,data,startpos,numtowrite);
6159 status = sync_file(conn, fsp, write_through);
6161 if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6163 /* We are returning an error - we can delete the aux struct */
6166 fsp->wbmpx_ptr = NULL;
6167 END_PROFILE(SMBwriteBs);
6168 return(ERROR_DOS(ERRHRD,ERRdiskfull));
6170 wbms->wr_errclass = ERRHRD;
6171 wbms->wr_error = ERRdiskfull;
6172 wbms->wr_status = NT_STATUS_DISK_FULL;
6173 wbms->wr_discard = True;
6174 END_PROFILE(SMBwriteBs);
6178 /* Increment the total written, if this matches tcount
6179 we can discard the auxiliary struct (hurrah !) and return a writeC */
6180 wbms->wr_total_written += nwritten;
6181 if(wbms->wr_total_written >= tcount) {
6182 if (write_through) {
6183 outsize = set_message(inbuf,outbuf,1,0,True);
6184 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
6185 send_response = True;
6189 fsp->wbmpx_ptr = NULL;
6193 END_PROFILE(SMBwriteBs);
6197 END_PROFILE(SMBwriteBs);
6201 /****************************************************************************
6202 Reply to a SMBgetattrE.
6203 ****************************************************************************/
6205 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6207 SMB_STRUCT_STAT sbuf;
6210 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6211 START_PROFILE(SMBgetattrE);
6213 outsize = set_message(inbuf,outbuf,11,0,True);
6215 if(!fsp || (fsp->conn != conn)) {
6216 END_PROFILE(SMBgetattrE);
6217 return ERROR_DOS(ERRDOS,ERRbadfid);
6220 /* Do an fstat on this file */
6221 if(fsp_stat(fsp, &sbuf)) {
6222 END_PROFILE(SMBgetattrE);
6223 return(UNIXERROR(ERRDOS,ERRnoaccess));
6226 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6229 * Convert the times into dos times. Set create
6230 * date to be last modify date as UNIX doesn't save
6234 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6235 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6236 /* Should we check pending modtime here ? JRA */
6237 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6240 SIVAL(outbuf,smb_vwv6,0);
6241 SIVAL(outbuf,smb_vwv8,0);
6243 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6244 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6245 SIVAL(outbuf,smb_vwv8,allocation_size);
6247 SSVAL(outbuf,smb_vwv10, mode);
6249 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6251 END_PROFILE(SMBgetattrE);