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 Check if we have a correct fsp pointing to a file. Replacement for the
290 ****************************************************************************/
291 BOOL check_fsp(connection_struct *conn, struct smb_request *req,
292 files_struct *fsp, struct current_user *user)
294 if (!(fsp) || !(conn)) {
295 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
298 if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) {
299 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
302 if ((fsp)->is_directory) {
303 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
306 if ((fsp)->fh->fd == -1) {
307 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
310 (fsp)->num_smb_operations++;
314 /****************************************************************************
315 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
316 ****************************************************************************/
318 BOOL fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
319 files_struct *fsp, struct current_user *user)
321 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
322 && (current_user.vuid==(fsp)->vuid)) {
326 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
330 /****************************************************************************
331 Reply to a (netbios-level) special message.
332 ****************************************************************************/
334 void reply_special(char *inbuf)
336 int msg_type = CVAL(inbuf,0);
337 int msg_flags = CVAL(inbuf,1);
342 * We only really use 4 bytes of the outbuf, but for the smb_setlen
343 * calculation & friends (send_smb uses that) we need the full smb
346 char outbuf[smb_size];
348 static BOOL already_got_session = False;
352 memset(outbuf, '\0', sizeof(outbuf));
354 smb_setlen(inbuf,outbuf,0);
357 case 0x81: /* session request */
359 if (already_got_session) {
360 exit_server_cleanly("multiple session request not permitted");
363 SCVAL(outbuf,0,0x82);
365 if (name_len(inbuf+4) > 50 ||
366 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
367 DEBUG(0,("Invalid name length in session request\n"));
370 name_extract(inbuf,4,name1);
371 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
372 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
375 set_local_machine_name(name1, True);
376 set_remote_machine_name(name2, True);
378 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
379 get_local_machine_name(), get_remote_machine_name(),
382 if (name_type == 'R') {
383 /* We are being asked for a pathworks session ---
385 SCVAL(outbuf, 0,0x83);
389 /* only add the client's machine name to the list
390 of possibly valid usernames if we are operating
391 in share mode security */
392 if (lp_security() == SEC_SHARE) {
393 add_session_user(get_remote_machine_name());
396 reload_services(True);
399 already_got_session = True;
402 case 0x89: /* session keepalive request
403 (some old clients produce this?) */
404 SCVAL(outbuf,0,SMBkeepalive);
408 case 0x82: /* positive session response */
409 case 0x83: /* negative session response */
410 case 0x84: /* retarget session response */
411 DEBUG(0,("Unexpected session response\n"));
414 case SMBkeepalive: /* session keepalive */
419 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
420 msg_type, msg_flags));
422 send_smb(smbd_server_fd(), outbuf);
426 /****************************************************************************
428 conn POINTER CAN BE NULL HERE !
429 ****************************************************************************/
431 int reply_tcon(connection_struct *conn,
432 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
436 char *service_buf = NULL;
437 char *password = NULL;
440 uint16 vuid = SVAL(inbuf,smb_uid);
444 DATA_BLOB password_blob;
446 START_PROFILE(SMBtcon);
448 ctx = talloc_init("reply_tcon");
450 END_PROFILE(SMBtcon);
451 return ERROR_NT(NT_STATUS_NO_MEMORY);
454 p = smb_buf(inbuf)+1;
455 p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
456 &service_buf, p, STR_TERMINATE) + 1;
457 pwlen = srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
458 &password, p, STR_TERMINATE) + 1;
460 p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
461 &dev, p, STR_TERMINATE) + 1;
463 if (service_buf == NULL || password == NULL || dev == NULL) {
465 END_PROFILE(SMBtcon);
466 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
468 p = strrchr_m(service_buf,'\\');
472 service = service_buf;
475 password_blob = data_blob(password, pwlen+1);
477 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
479 data_blob_clear_free(&password_blob);
483 END_PROFILE(SMBtcon);
484 return ERROR_NT(nt_status);
487 outsize = set_message(inbuf,outbuf,2,0,True);
488 SSVAL(outbuf,smb_vwv0,max_recv);
489 SSVAL(outbuf,smb_vwv1,conn->cnum);
490 SSVAL(outbuf,smb_tid,conn->cnum);
492 DEBUG(3,("tcon service=%s cnum=%d\n",
493 service, conn->cnum));
495 END_PROFILE(SMBtcon);
500 /****************************************************************************
501 Reply to a tcon and X.
502 conn POINTER CAN BE NULL HERE !
503 ****************************************************************************/
505 void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
507 char *service = NULL;
510 TALLOC_CTX *ctx = NULL;
511 /* what the cleint thinks the device is */
512 char *client_devicetype = NULL;
513 /* what the server tells the client the share represents */
514 const char *server_devicetype;
521 START_PROFILE(SMBtconX);
524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
525 END_PROFILE(SMBtconX);
529 passlen = SVAL(req->inbuf,smb_vwv3);
530 tcon_flags = SVAL(req->inbuf,smb_vwv2);
532 /* we might have to close an old one */
533 if ((tcon_flags & 0x1) && conn) {
534 close_cnum(conn,req->vuid);
537 if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
538 reply_doserror(req, ERRDOS, ERRbuftoosmall);
539 END_PROFILE(SMBtconX);
543 if (global_encrypted_passwords_negotiated) {
544 password = data_blob(smb_buf(req->inbuf),passlen);
545 if (lp_security() == SEC_SHARE) {
547 * Security = share always has a pad byte
548 * after the password.
550 p = smb_buf(req->inbuf) + passlen + 1;
552 p = smb_buf(req->inbuf) + passlen;
555 password = data_blob(smb_buf(req->inbuf),passlen+1);
556 /* Ensure correct termination */
557 password.data[passlen]=0;
558 p = smb_buf(req->inbuf) + passlen + 1;
561 ctx = talloc_init("reply_tcon_and_X");
563 data_blob_clear_free(&password);
564 reply_nterror(req, NT_STATUS_NO_MEMORY);
565 END_PROFILE(SMBtconX);
568 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
572 data_blob_clear_free(&password);
574 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
575 END_PROFILE(SMBtconX);
580 * the service name can be either: \\server\share
581 * or share directly like on the DELL PowerVault 705
584 q = strchr_m(path+2,'\\');
586 data_blob_clear_free(&password);
588 reply_doserror(req, ERRDOS, ERRnosuchshare);
589 END_PROFILE(SMBtconX);
597 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
598 &client_devicetype, p,
599 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
601 if (client_devicetype == NULL) {
602 data_blob_clear_free(&password);
604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
605 END_PROFILE(SMBtconX);
609 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
611 conn = make_connection(service, password, client_devicetype,
612 req->vuid, &nt_status);
614 data_blob_clear_free(&password);
618 reply_nterror(req, nt_status);
619 END_PROFILE(SMBtconX);
624 server_devicetype = "IPC";
625 else if ( IS_PRINT(conn) )
626 server_devicetype = "LPT1:";
628 server_devicetype = "A:";
630 if (Protocol < PROTOCOL_NT1) {
631 reply_outbuf(req, 2, 0);
632 if (message_push_string(&req->outbuf, server_devicetype,
633 STR_TERMINATE|STR_ASCII) == -1) {
635 reply_nterror(req, NT_STATUS_NO_MEMORY);
636 END_PROFILE(SMBtconX);
640 /* NT sets the fstype of IPC$ to the null string */
641 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
643 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
644 /* Return permissions. */
648 reply_outbuf(req, 7, 0);
651 perm1 = FILE_ALL_ACCESS;
652 perm2 = FILE_ALL_ACCESS;
654 perm1 = CAN_WRITE(conn) ?
659 SIVAL(req->outbuf, smb_vwv3, perm1);
660 SIVAL(req->outbuf, smb_vwv5, perm2);
662 reply_outbuf(req, 3, 0);
665 if ((message_push_string(&req->outbuf, server_devicetype,
666 STR_TERMINATE|STR_ASCII) == -1)
667 || (message_push_string(&req->outbuf, fstype,
668 STR_TERMINATE) == -1)) {
670 reply_nterror(req, NT_STATUS_NO_MEMORY);
671 END_PROFILE(SMBtconX);
675 /* what does setting this bit do? It is set by NT4 and
676 may affect the ability to autorun mounted cdroms */
677 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
678 (lp_csc_policy(SNUM(conn)) << 2));
680 init_dfsroot(conn, req->inbuf, req->outbuf);
684 DEBUG(3,("tconX service=%s \n",
687 /* set the incoming and outgoing tid to the just created one */
688 SSVAL(req->inbuf,smb_tid,conn->cnum);
689 SSVAL(req->outbuf,smb_tid,conn->cnum);
692 END_PROFILE(SMBtconX);
694 chain_reply_new(req);
698 /****************************************************************************
699 Reply to an unknown type.
700 ****************************************************************************/
702 int reply_unknown(char *inbuf,char *outbuf)
705 type = CVAL(inbuf,smb_com);
707 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
708 smb_fn_name(type), type, type));
710 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
713 void reply_unknown_new(struct smb_request *req, uint8 type)
715 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
716 smb_fn_name(type), type, type));
717 reply_doserror(req, ERRSRV, ERRunknownsmb);
721 /****************************************************************************
723 conn POINTER CAN BE NULL HERE !
724 ****************************************************************************/
726 int reply_ioctl(connection_struct *conn,
727 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
729 uint16 device = SVAL(inbuf,smb_vwv1);
730 uint16 function = SVAL(inbuf,smb_vwv2);
731 uint32 ioctl_code = (device << 16) + function;
732 int replysize, outsize;
734 START_PROFILE(SMBioctl);
736 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
738 switch (ioctl_code) {
739 case IOCTL_QUERY_JOB_INFO:
743 END_PROFILE(SMBioctl);
744 return(ERROR_DOS(ERRSRV,ERRnosupport));
747 outsize = set_message(inbuf,outbuf,8,replysize+1,True);
748 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
749 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
750 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
751 p = smb_buf(outbuf) + 1; /* Allow for alignment */
753 switch (ioctl_code) {
754 case IOCTL_QUERY_JOB_INFO:
756 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
758 END_PROFILE(SMBioctl);
759 return(UNIXERROR(ERRDOS,ERRbadfid));
761 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
762 srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+2,
764 STR_TERMINATE|STR_ASCII);
766 srvstr_push(outbuf, SVAL(outbuf, smb_flg2),
767 p+18, lp_servicename(SNUM(conn)),
768 13, STR_TERMINATE|STR_ASCII);
774 END_PROFILE(SMBioctl);
778 /****************************************************************************
779 Strange checkpath NTSTATUS mapping.
780 ****************************************************************************/
782 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
784 /* Strange DOS error code semantics only for checkpath... */
785 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
786 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
787 /* We need to map to ERRbadpath */
788 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
794 /****************************************************************************
795 Reply to a checkpath.
796 ****************************************************************************/
798 void reply_checkpath(connection_struct *conn, struct smb_request *req)
801 SMB_STRUCT_STAT sbuf;
804 START_PROFILE(SMBcheckpath);
806 srvstr_get_path((char *)req->inbuf, req->flags2, name,
807 smb_buf(req->inbuf) + 1, sizeof(name), 0,
808 STR_TERMINATE, &status);
809 if (!NT_STATUS_IS_OK(status)) {
810 status = map_checkpath_error((char *)req->inbuf, status);
811 reply_nterror(req, status);
812 END_PROFILE(SMBcheckpath);
816 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name);
817 if (!NT_STATUS_IS_OK(status)) {
818 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
819 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
821 END_PROFILE(SMBcheckpath);
827 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
829 status = unix_convert(conn, name, False, NULL, &sbuf);
830 if (!NT_STATUS_IS_OK(status)) {
834 status = check_name(conn, name);
835 if (!NT_STATUS_IS_OK(status)) {
836 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
840 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
841 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
842 status = map_nt_error_from_unix(errno);
846 if (!S_ISDIR(sbuf.st_mode)) {
847 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
849 END_PROFILE(SMBcheckpath);
853 reply_outbuf(req, 0, 0);
855 END_PROFILE(SMBcheckpath);
860 END_PROFILE(SMBcheckpath);
862 /* We special case this - as when a Windows machine
863 is parsing a path is steps through the components
864 one at a time - if a component fails it expects
865 ERRbadpath, not ERRbadfile.
867 status = map_checkpath_error((char *)req->inbuf, status);
868 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
870 * Windows returns different error codes if
871 * the parent directory is valid but not the
872 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
873 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
874 * if the path is invalid.
876 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
881 reply_nterror(req, status);
884 /****************************************************************************
886 ****************************************************************************/
888 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
892 SMB_STRUCT_STAT sbuf;
899 START_PROFILE(SMBgetatr);
901 p = smb_buf(inbuf) + 1;
902 p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
903 sizeof(fname), 0, STR_TERMINATE, &status);
904 if (!NT_STATUS_IS_OK(status)) {
905 END_PROFILE(SMBgetatr);
906 return ERROR_NT(status);
909 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
910 if (!NT_STATUS_IS_OK(status)) {
911 END_PROFILE(SMBgetatr);
912 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
913 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
915 return ERROR_NT(status);
918 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
919 under WfWg - weird! */
920 if (*fname == '\0') {
921 mode = aHIDDEN | aDIR;
922 if (!CAN_WRITE(conn)) {
928 status = unix_convert(conn, fname, False, NULL,&sbuf);
929 if (!NT_STATUS_IS_OK(status)) {
930 END_PROFILE(SMBgetatr);
931 return ERROR_NT(status);
933 status = check_name(conn, fname);
934 if (!NT_STATUS_IS_OK(status)) {
935 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
936 END_PROFILE(SMBgetatr);
937 return ERROR_NT(status);
939 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
940 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
941 return UNIXERROR(ERRDOS,ERRbadfile);
944 mode = dos_mode(conn,fname,&sbuf);
946 mtime = sbuf.st_mtime;
952 outsize = set_message(inbuf,outbuf,10,0,True);
954 SSVAL(outbuf,smb_vwv0,mode);
955 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
956 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
958 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
960 SIVAL(outbuf,smb_vwv3,(uint32)size);
962 if (Protocol >= PROTOCOL_NT1) {
963 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
966 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
968 END_PROFILE(SMBgetatr);
972 /****************************************************************************
974 ****************************************************************************/
976 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
982 SMB_STRUCT_STAT sbuf;
986 START_PROFILE(SMBsetatr);
988 p = smb_buf(inbuf) + 1;
989 p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
990 sizeof(fname), 0, STR_TERMINATE, &status);
991 if (!NT_STATUS_IS_OK(status)) {
992 END_PROFILE(SMBsetatr);
993 return ERROR_NT(status);
996 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
997 if (!NT_STATUS_IS_OK(status)) {
998 END_PROFILE(SMBsetatr);
999 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1000 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1002 return ERROR_NT(status);
1005 status = unix_convert(conn, fname, False, NULL, &sbuf);
1006 if (!NT_STATUS_IS_OK(status)) {
1007 END_PROFILE(SMBsetatr);
1008 return ERROR_NT(status);
1011 status = check_name(conn, fname);
1012 if (!NT_STATUS_IS_OK(status)) {
1013 END_PROFILE(SMBsetatr);
1014 return ERROR_NT(status);
1017 if (fname[0] == '.' && fname[1] == '\0') {
1019 * Not sure here is the right place to catch this
1020 * condition. Might be moved to somewhere else later -- vl
1022 END_PROFILE(SMBsetatr);
1023 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
1026 mode = SVAL(inbuf,smb_vwv0);
1027 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
1029 if (mode != FILE_ATTRIBUTE_NORMAL) {
1030 if (VALID_STAT_OF_DIR(sbuf))
1035 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
1036 END_PROFILE(SMBsetatr);
1037 return UNIXERROR(ERRDOS, ERRnoaccess);
1041 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
1042 END_PROFILE(SMBsetatr);
1043 return UNIXERROR(ERRDOS, ERRnoaccess);
1046 outsize = set_message(inbuf,outbuf,0,0,False);
1048 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1050 END_PROFILE(SMBsetatr);
1054 /****************************************************************************
1056 ****************************************************************************/
1058 void reply_dskattr(connection_struct *conn, struct smb_request *req)
1060 SMB_BIG_UINT dfree,dsize,bsize;
1061 START_PROFILE(SMBdskattr);
1063 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1064 reply_unixerror(req, ERRHRD, ERRgeneral);
1065 END_PROFILE(SMBdskattr);
1069 reply_outbuf(req, 5, 0);
1071 if (Protocol <= PROTOCOL_LANMAN2) {
1072 double total_space, free_space;
1073 /* we need to scale this to a number that DOS6 can handle. We
1074 use floating point so we can handle large drives on systems
1075 that don't have 64 bit integers
1077 we end up displaying a maximum of 2G to DOS systems
1079 total_space = dsize * (double)bsize;
1080 free_space = dfree * (double)bsize;
1082 dsize = (total_space+63*512) / (64*512);
1083 dfree = (free_space+63*512) / (64*512);
1085 if (dsize > 0xFFFF) dsize = 0xFFFF;
1086 if (dfree > 0xFFFF) dfree = 0xFFFF;
1088 SSVAL(req->outbuf,smb_vwv0,dsize);
1089 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1090 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1091 SSVAL(req->outbuf,smb_vwv3,dfree);
1093 SSVAL(req->outbuf,smb_vwv0,dsize);
1094 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1095 SSVAL(req->outbuf,smb_vwv2,512);
1096 SSVAL(req->outbuf,smb_vwv3,dfree);
1099 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1101 END_PROFILE(SMBdskattr);
1105 /****************************************************************************
1107 Can be called from SMBsearch, SMBffirst or SMBfunique.
1108 ****************************************************************************/
1110 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1120 unsigned int numentries = 0;
1121 unsigned int maxentries = 0;
1122 BOOL finished = False;
1128 BOOL check_descend = False;
1129 BOOL expect_close = False;
1131 BOOL mask_contains_wcard = False;
1132 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1134 START_PROFILE(SMBsearch);
1136 if (lp_posix_pathnames()) {
1137 END_PROFILE(SMBsearch);
1138 return reply_unknown(inbuf, outbuf);
1141 *mask = *directory = *fname = 0;
1143 /* If we were called as SMBffirst then we must expect close. */
1144 if(CVAL(inbuf,smb_com) == SMBffirst) {
1145 expect_close = True;
1148 outsize = set_message(inbuf,outbuf,1,3,True);
1149 maxentries = SVAL(inbuf,smb_vwv0);
1150 dirtype = SVAL(inbuf,smb_vwv1);
1151 p = smb_buf(inbuf) + 1;
1152 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1153 sizeof(path), 0, STR_TERMINATE, &nt_status,
1154 &mask_contains_wcard);
1155 if (!NT_STATUS_IS_OK(nt_status)) {
1156 END_PROFILE(SMBsearch);
1157 return ERROR_NT(nt_status);
1160 nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
1161 if (!NT_STATUS_IS_OK(nt_status)) {
1162 END_PROFILE(SMBsearch);
1163 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1164 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1166 return ERROR_NT(nt_status);
1170 status_len = SVAL(p, 0);
1173 /* dirtype &= ~aDIR; */
1175 if (status_len == 0) {
1176 SMB_STRUCT_STAT sbuf;
1178 pstrcpy(directory,path);
1179 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1180 if (!NT_STATUS_IS_OK(nt_status)) {
1181 END_PROFILE(SMBsearch);
1182 return ERROR_NT(nt_status);
1185 nt_status = check_name(conn, directory);
1186 if (!NT_STATUS_IS_OK(nt_status)) {
1187 END_PROFILE(SMBsearch);
1188 return ERROR_NT(nt_status);
1191 p = strrchr_m(directory,'/');
1193 pstrcpy(mask,directory);
1194 pstrcpy(directory,".");
1200 if (*directory == '\0') {
1201 pstrcpy(directory,".");
1203 memset((char *)status,'\0',21);
1204 SCVAL(status,0,(dirtype & 0x1F));
1208 memcpy(status,p,21);
1209 status_dirtype = CVAL(status,0) & 0x1F;
1210 if (status_dirtype != (dirtype & 0x1F)) {
1211 dirtype = status_dirtype;
1214 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1215 if (!conn->dirptr) {
1218 string_set(&conn->dirpath,dptr_path(dptr_num));
1219 pstrcpy(mask, dptr_wcard(dptr_num));
1221 * For a 'continue' search we have no string. So
1222 * check from the initial saved string.
1224 mask_contains_wcard = ms_has_wild(mask);
1227 p = smb_buf(outbuf) + 3;
1229 if (status_len == 0) {
1230 nt_status = dptr_create(conn,
1234 SVAL(inbuf,smb_pid),
1236 mask_contains_wcard,
1239 if (!NT_STATUS_IS_OK(nt_status)) {
1240 return ERROR_NT(nt_status);
1242 dptr_num = dptr_dnum(conn->dirptr);
1244 dirtype = dptr_attr(dptr_num);
1247 DEBUG(4,("dptr_num is %d\n",dptr_num));
1249 if ((dirtype&0x1F) == aVOLID) {
1250 memcpy(p,status,21);
1251 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1252 0,aVOLID,0,!allow_long_path_components);
1253 dptr_fill(p+12,dptr_num);
1254 if (dptr_zero(p+12) && (status_len==0)) {
1259 p += DIR_STRUCT_SIZE;
1262 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1264 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1265 conn->dirpath,lp_dontdescend(SNUM(conn))));
1266 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1267 check_descend = True;
1270 for (i=numentries;(i<maxentries) && !finished;i++) {
1271 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1273 memcpy(p,status,21);
1274 make_dir_struct(p,mask,fname,size, mode,date,
1275 !allow_long_path_components);
1276 if (!dptr_fill(p+12,dptr_num)) {
1280 p += DIR_STRUCT_SIZE;
1287 /* If we were called as SMBffirst with smb_search_id == NULL
1288 and no entries were found then return error and close dirptr
1291 if (numentries == 0) {
1292 dptr_close(&dptr_num);
1293 } else if(expect_close && status_len == 0) {
1294 /* Close the dptr - we know it's gone */
1295 dptr_close(&dptr_num);
1298 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1299 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1300 dptr_close(&dptr_num);
1303 if ((numentries == 0) && !mask_contains_wcard) {
1304 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1307 SSVAL(outbuf,smb_vwv0,numentries);
1308 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1309 SCVAL(smb_buf(outbuf),0,5);
1310 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1312 /* The replies here are never long name. */
1313 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1314 if (!allow_long_path_components) {
1315 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1318 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1319 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1321 outsize += DIR_STRUCT_SIZE*numentries;
1322 smb_setlen(inbuf,outbuf,outsize - 4);
1324 if ((! *directory) && dptr_path(dptr_num))
1325 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1327 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1328 smb_fn_name(CVAL(inbuf,smb_com)),
1329 mask, directory, dirtype, numentries, maxentries ) );
1331 END_PROFILE(SMBsearch);
1335 /****************************************************************************
1336 Reply to a fclose (stop directory search).
1337 ****************************************************************************/
1339 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1348 BOOL path_contains_wcard = False;
1350 START_PROFILE(SMBfclose);
1352 if (lp_posix_pathnames()) {
1353 END_PROFILE(SMBfclose);
1354 return reply_unknown(inbuf, outbuf);
1357 outsize = set_message(inbuf,outbuf,1,0,True);
1358 p = smb_buf(inbuf) + 1;
1359 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1360 sizeof(path), 0, STR_TERMINATE, &err,
1361 &path_contains_wcard);
1362 if (!NT_STATUS_IS_OK(err)) {
1363 END_PROFILE(SMBfclose);
1364 return ERROR_NT(err);
1367 status_len = SVAL(p,0);
1370 if (status_len == 0) {
1371 END_PROFILE(SMBfclose);
1372 return ERROR_DOS(ERRSRV,ERRsrverror);
1375 memcpy(status,p,21);
1377 if(dptr_fetch(status+12,&dptr_num)) {
1378 /* Close the dptr - we know it's gone */
1379 dptr_close(&dptr_num);
1382 SSVAL(outbuf,smb_vwv0,0);
1384 DEBUG(3,("search close\n"));
1386 END_PROFILE(SMBfclose);
1390 /****************************************************************************
1392 ****************************************************************************/
1394 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1402 SMB_STRUCT_STAT sbuf;
1404 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1406 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1409 uint32 create_disposition;
1410 uint32 create_options = 0;
1412 struct smb_request req;
1414 START_PROFILE(SMBopen);
1416 init_smb_request(&req, (uint8 *)inbuf);
1418 deny_mode = SVAL(inbuf,smb_vwv0);
1420 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1421 sizeof(fname), 0, STR_TERMINATE, &status);
1422 if (!NT_STATUS_IS_OK(status)) {
1423 END_PROFILE(SMBopen);
1424 return ERROR_NT(status);
1427 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1428 if (!NT_STATUS_IS_OK(status)) {
1429 END_PROFILE(SMBopen);
1430 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1431 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1433 return ERROR_NT(status);
1436 status = unix_convert(conn, fname, False, NULL, &sbuf);
1437 if (!NT_STATUS_IS_OK(status)) {
1438 END_PROFILE(SMBopen);
1439 return ERROR_NT(status);
1442 status = check_name(conn, fname);
1443 if (!NT_STATUS_IS_OK(status)) {
1444 END_PROFILE(SMBopen);
1445 return ERROR_NT(status);
1448 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1449 &access_mask, &share_mode, &create_disposition, &create_options)) {
1450 END_PROFILE(SMBopen);
1451 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1454 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1463 if (!NT_STATUS_IS_OK(status)) {
1464 END_PROFILE(SMBopen);
1465 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1466 /* We have re-scheduled this call. */
1469 return ERROR_NT(status);
1472 size = sbuf.st_size;
1473 fattr = dos_mode(conn,fname,&sbuf);
1474 mtime = sbuf.st_mtime;
1477 DEBUG(3,("attempt to open a directory %s\n",fname));
1478 close_file(fsp,ERROR_CLOSE);
1479 END_PROFILE(SMBopen);
1480 return ERROR_DOS(ERRDOS,ERRnoaccess);
1483 outsize = set_message(inbuf,outbuf,7,0,True);
1484 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1485 SSVAL(outbuf,smb_vwv1,fattr);
1486 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1487 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1489 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1491 SIVAL(outbuf,smb_vwv4,(uint32)size);
1492 SSVAL(outbuf,smb_vwv6,deny_mode);
1494 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1495 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1498 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1499 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1501 END_PROFILE(SMBopen);
1505 /****************************************************************************
1506 Reply to an open and X.
1507 ****************************************************************************/
1509 void reply_open_and_X(connection_struct *conn, struct smb_request *req)
1515 /* Breakout the oplock request bits so we can set the
1516 reply bits separately. */
1517 int ex_oplock_request;
1518 int core_oplock_request;
1521 int smb_sattr = SVAL(req->inbuf,smb_vwv4);
1522 uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
1527 SMB_STRUCT_STAT sbuf;
1531 SMB_BIG_UINT allocation_size;
1532 ssize_t retval = -1;
1535 uint32 create_disposition;
1536 uint32 create_options = 0;
1538 START_PROFILE(SMBopenX);
1540 if (req->wct < 15) {
1541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1542 END_PROFILE(SMBopenX);
1546 open_flags = SVAL(req->inbuf,smb_vwv2);
1547 deny_mode = SVAL(req->inbuf,smb_vwv3);
1548 smb_attr = SVAL(req->inbuf,smb_vwv5);
1549 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1550 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1551 oplock_request = ex_oplock_request | core_oplock_request;
1552 smb_ofun = SVAL(req->inbuf,smb_vwv8);
1553 allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
1555 /* If it's an IPC, pass off the pipe handler. */
1557 if (lp_nt_pipe_support()) {
1558 reply_open_pipe_and_X(conn, req);
1560 reply_doserror(req, ERRSRV, ERRaccess);
1562 END_PROFILE(SMBopenX);
1566 /* XXXX we need to handle passed times, sattr and flags */
1567 srvstr_get_path((char *)req->inbuf, req->flags2, fname,
1568 smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE,
1570 if (!NT_STATUS_IS_OK(status)) {
1571 reply_nterror(req, status);
1572 END_PROFILE(SMBopenX);
1576 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1578 if (!NT_STATUS_IS_OK(status)) {
1579 END_PROFILE(SMBopenX);
1580 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1581 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1582 ERRSRV, ERRbadpath);
1585 reply_nterror(req, status);
1589 status = unix_convert(conn, fname, False, NULL, &sbuf);
1590 if (!NT_STATUS_IS_OK(status)) {
1591 reply_nterror(req, status);
1592 END_PROFILE(SMBopenX);
1596 status = check_name(conn, fname);
1597 if (!NT_STATUS_IS_OK(status)) {
1598 reply_nterror(req, status);
1599 END_PROFILE(SMBopenX);
1603 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1606 &create_disposition,
1608 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1609 END_PROFILE(SMBopenX);
1613 status = open_file_ntcreate(conn, req, fname, &sbuf,
1622 if (!NT_STATUS_IS_OK(status)) {
1623 END_PROFILE(SMBopenX);
1624 if (open_was_deferred(req->mid)) {
1625 /* We have re-scheduled this call. */
1628 reply_nterror(req, status);
1632 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1633 if the file is truncated or created. */
1634 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1635 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1636 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1637 close_file(fsp,ERROR_CLOSE);
1638 reply_nterror(req, NT_STATUS_DISK_FULL);
1639 END_PROFILE(SMBopenX);
1642 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1644 close_file(fsp,ERROR_CLOSE);
1645 reply_nterror(req, NT_STATUS_DISK_FULL);
1646 END_PROFILE(SMBopenX);
1649 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1652 fattr = dos_mode(conn,fname,&sbuf);
1653 mtime = sbuf.st_mtime;
1655 close_file(fsp,ERROR_CLOSE);
1656 reply_doserror(req, ERRDOS, ERRnoaccess);
1657 END_PROFILE(SMBopenX);
1661 /* If the caller set the extended oplock request bit
1662 and we granted one (by whatever means) - set the
1663 correct bit for extended oplock reply.
1666 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1667 smb_action |= EXTENDED_OPLOCK_GRANTED;
1670 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1671 smb_action |= EXTENDED_OPLOCK_GRANTED;
1674 /* If the caller set the core oplock request bit
1675 and we granted one (by whatever means) - set the
1676 correct bit for core oplock reply.
1679 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1680 reply_outbuf(req, 19, 0);
1682 reply_outbuf(req, 15, 0);
1685 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1686 SCVAL(req->outbuf, smb_flg,
1687 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1690 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1691 SCVAL(req->outbuf, smb_flg,
1692 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1695 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1696 SSVAL(req->outbuf,smb_vwv3,fattr);
1697 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1698 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1700 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1702 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1703 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1704 SSVAL(req->outbuf,smb_vwv11,smb_action);
1706 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1707 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1710 END_PROFILE(SMBopenX);
1711 chain_reply_new(req);
1715 /****************************************************************************
1716 Reply to a SMBulogoffX.
1717 conn POINTER CAN BE NULL HERE !
1718 ****************************************************************************/
1720 void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
1724 START_PROFILE(SMBulogoffX);
1726 vuser = get_valid_user_struct(req->vuid);
1729 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1733 /* in user level security we are supposed to close any files
1734 open by this user */
1735 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1736 file_close_user(req->vuid);
1739 invalidate_vuid(req->vuid);
1741 reply_outbuf(req, 2, 0);
1743 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1745 END_PROFILE(SMBulogoffX);
1746 chain_reply_new(req);
1749 /****************************************************************************
1750 Reply to a mknew or a create.
1751 ****************************************************************************/
1753 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1758 uint32 fattr = SVAL(inbuf,smb_vwv0);
1759 struct timespec ts[2];
1761 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1762 SMB_STRUCT_STAT sbuf;
1764 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1765 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1766 uint32 create_disposition;
1767 uint32 create_options = 0;
1768 struct smb_request req;
1770 START_PROFILE(SMBcreate);
1772 init_smb_request(&req, (uint8 *)inbuf);
1774 com = SVAL(inbuf,smb_com);
1776 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1778 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1,
1779 sizeof(fname), 0, STR_TERMINATE, &status);
1780 if (!NT_STATUS_IS_OK(status)) {
1781 END_PROFILE(SMBcreate);
1782 return ERROR_NT(status);
1785 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1786 if (!NT_STATUS_IS_OK(status)) {
1787 END_PROFILE(SMBcreate);
1788 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1789 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1791 return ERROR_NT(status);
1794 status = unix_convert(conn, fname, False, NULL, &sbuf);
1795 if (!NT_STATUS_IS_OK(status)) {
1796 END_PROFILE(SMBcreate);
1797 return ERROR_NT(status);
1800 status = check_name(conn, fname);
1801 if (!NT_STATUS_IS_OK(status)) {
1802 END_PROFILE(SMBcreate);
1803 return ERROR_NT(status);
1806 if (fattr & aVOLID) {
1807 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1810 if(com == SMBmknew) {
1811 /* We should fail if file exists. */
1812 create_disposition = FILE_CREATE;
1814 /* Create if file doesn't exist, truncate if it does. */
1815 create_disposition = FILE_OVERWRITE_IF;
1818 /* Open file using ntcreate. */
1819 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1828 if (!NT_STATUS_IS_OK(status)) {
1829 END_PROFILE(SMBcreate);
1830 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1831 /* We have re-scheduled this call. */
1834 return ERROR_NT(status);
1837 ts[0] = get_atimespec(&sbuf); /* atime. */
1838 file_ntimes(conn, fname, ts);
1840 outsize = set_message(inbuf,outbuf,1,0,True);
1841 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1843 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1844 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1847 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1848 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1851 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1852 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1854 END_PROFILE(SMBcreate);
1858 /****************************************************************************
1859 Reply to a create temporary file.
1860 ****************************************************************************/
1862 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1866 uint32 fattr = SVAL(inbuf,smb_vwv0);
1868 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1870 SMB_STRUCT_STAT sbuf;
1873 unsigned int namelen;
1874 struct smb_request req;
1876 START_PROFILE(SMBctemp);
1878 init_smb_request(&req, (uint8 *)inbuf);
1880 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1881 sizeof(fname), 0, STR_TERMINATE, &status);
1882 if (!NT_STATUS_IS_OK(status)) {
1883 END_PROFILE(SMBctemp);
1884 return ERROR_NT(status);
1887 pstrcat(fname,"/TMXXXXXX");
1889 pstrcat(fname,"TMXXXXXX");
1892 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1893 if (!NT_STATUS_IS_OK(status)) {
1894 END_PROFILE(SMBctemp);
1895 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1896 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1898 return ERROR_NT(status);
1901 status = unix_convert(conn, fname, False, NULL, &sbuf);
1902 if (!NT_STATUS_IS_OK(status)) {
1903 END_PROFILE(SMBctemp);
1904 return ERROR_NT(status);
1907 status = check_name(conn, fname);
1908 if (!NT_STATUS_IS_OK(status)) {
1909 END_PROFILE(SMBctemp);
1910 return ERROR_NT(status);
1913 tmpfd = smb_mkstemp(fname);
1915 END_PROFILE(SMBctemp);
1916 return(UNIXERROR(ERRDOS,ERRnoaccess));
1919 SMB_VFS_STAT(conn,fname,&sbuf);
1921 /* We should fail if file does not exist. */
1922 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1923 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1924 FILE_SHARE_READ|FILE_SHARE_WRITE,
1931 /* close fd from smb_mkstemp() */
1934 if (!NT_STATUS_IS_OK(status)) {
1935 END_PROFILE(SMBctemp);
1936 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1937 /* We have re-scheduled this call. */
1940 return ERROR_NT(status);
1943 outsize = set_message(inbuf,outbuf,1,0,True);
1944 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1946 /* the returned filename is relative to the directory */
1947 s = strrchr_m(fname, '/');
1954 p = smb_buf(outbuf);
1956 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1957 thing in the byte section. JRA */
1958 SSVALS(p, 0, -1); /* what is this? not in spec */
1960 namelen = srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p, s, -1,
1961 STR_ASCII|STR_TERMINATE);
1963 outsize = set_message_end(inbuf,outbuf, p);
1965 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1966 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1969 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1970 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1973 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1974 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1975 (unsigned int)sbuf.st_mode ) );
1977 END_PROFILE(SMBctemp);
1981 /*******************************************************************
1982 Check if a user is allowed to rename a file.
1983 ********************************************************************/
1985 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1986 uint16 dirtype, SMB_STRUCT_STAT *pst)
1990 if (!CAN_WRITE(conn)) {
1991 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1994 fmode = dos_mode(conn, fsp->fsp_name, pst);
1995 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1996 return NT_STATUS_NO_SUCH_FILE;
1999 if (S_ISDIR(pst->st_mode)) {
2000 return NT_STATUS_OK;
2003 if (fsp->access_mask & DELETE_ACCESS) {
2004 return NT_STATUS_OK;
2007 return NT_STATUS_ACCESS_DENIED;
2010 /*******************************************************************
2011 * unlink a file with all relevant access checks
2012 *******************************************************************/
2014 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
2015 char *fname, uint32 dirtype)
2017 SMB_STRUCT_STAT sbuf;
2020 uint32 dirtype_orig = dirtype;
2023 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2025 if (!CAN_WRITE(conn)) {
2026 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2029 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2030 return map_nt_error_from_unix(errno);
2033 fattr = dos_mode(conn,fname,&sbuf);
2035 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2036 dirtype = aDIR|aARCH|aRONLY;
2039 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2041 return NT_STATUS_NO_SUCH_FILE;
2044 if (!dir_check_ftype(conn, fattr, dirtype)) {
2046 return NT_STATUS_FILE_IS_A_DIRECTORY;
2048 return NT_STATUS_NO_SUCH_FILE;
2051 if (dirtype_orig & 0x8000) {
2052 /* These will never be set for POSIX. */
2053 return NT_STATUS_NO_SUCH_FILE;
2057 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2058 return NT_STATUS_FILE_IS_A_DIRECTORY;
2061 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2062 return NT_STATUS_NO_SUCH_FILE;
2065 if (dirtype & 0xFF00) {
2066 /* These will never be set for POSIX. */
2067 return NT_STATUS_NO_SUCH_FILE;
2072 return NT_STATUS_NO_SUCH_FILE;
2075 /* Can't delete a directory. */
2077 return NT_STATUS_FILE_IS_A_DIRECTORY;
2082 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2083 return NT_STATUS_OBJECT_NAME_INVALID;
2084 #endif /* JRATEST */
2086 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2088 On a Windows share, a file with read-only dosmode can be opened with
2089 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2090 fails with NT_STATUS_CANNOT_DELETE error.
2092 This semantic causes a problem that a user can not
2093 rename a file with read-only dosmode on a Samba share
2094 from a Windows command prompt (i.e. cmd.exe, but can rename
2095 from Windows Explorer).
2098 if (!lp_delete_readonly(SNUM(conn))) {
2099 if (fattr & aRONLY) {
2100 return NT_STATUS_CANNOT_DELETE;
2104 /* On open checks the open itself will check the share mode, so
2105 don't do it here as we'll get it wrong. */
2107 status = open_file_ntcreate(conn, req, fname, &sbuf,
2112 FILE_ATTRIBUTE_NORMAL,
2113 req != NULL ? 0 : INTERNAL_OPEN_ONLY,
2116 if (!NT_STATUS_IS_OK(status)) {
2117 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2118 nt_errstr(status)));
2122 /* The set is across all open files on this dev/inode pair. */
2123 if (!set_delete_on_close(fsp, True, ¤t_user.ut)) {
2124 close_file(fsp, NORMAL_CLOSE);
2125 return NT_STATUS_ACCESS_DENIED;
2128 return close_file(fsp,NORMAL_CLOSE);
2131 /****************************************************************************
2132 The guts of the unlink command, split out so it may be called by the NT SMB
2134 ****************************************************************************/
2136 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2137 uint32 dirtype, char *name, BOOL has_wild)
2143 NTSTATUS status = NT_STATUS_OK;
2144 SMB_STRUCT_STAT sbuf;
2146 *directory = *mask = 0;
2148 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
2149 if (!NT_STATUS_IS_OK(status)) {
2153 p = strrchr_m(name,'/');
2155 pstrcpy(directory,".");
2159 pstrcpy(directory,name);
2164 * We should only check the mangled cache
2165 * here if unix_convert failed. This means
2166 * that the path in 'mask' doesn't exist
2167 * on the file system and so we need to look
2168 * for a possible mangle. This patch from
2169 * Tine Smukavec <valentin.smukavec@hermes.si>.
2172 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
2173 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
2176 pstrcat(directory,"/");
2177 pstrcat(directory,mask);
2179 dirtype = FILE_ATTRIBUTE_NORMAL;
2182 status = check_name(conn, directory);
2183 if (!NT_STATUS_IS_OK(status)) {
2187 status = do_unlink(conn, req, directory, dirtype);
2188 if (!NT_STATUS_IS_OK(status)) {
2194 struct smb_Dir *dir_hnd = NULL;
2198 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2199 return NT_STATUS_OBJECT_NAME_INVALID;
2202 if (strequal(mask,"????????.???")) {
2206 status = check_name(conn, directory);
2207 if (!NT_STATUS_IS_OK(status)) {
2211 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2212 if (dir_hnd == NULL) {
2213 return map_nt_error_from_unix(errno);
2216 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2217 the pattern matches against the long name, otherwise the short name
2218 We don't implement this yet XXXX
2221 status = NT_STATUS_NO_SUCH_FILE;
2223 while ((dname = ReadDirName(dir_hnd, &offset))) {
2226 pstrcpy(fname,dname);
2228 if (!is_visible_file(conn, directory, dname, &st, True)) {
2232 /* Quick check for "." and ".." */
2233 if (fname[0] == '.') {
2234 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2239 if(!mask_match(fname, mask, conn->case_sensitive)) {
2243 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2245 status = check_name(conn, fname);
2246 if (!NT_STATUS_IS_OK(status)) {
2251 status = do_unlink(conn, req, fname, dirtype);
2252 if (!NT_STATUS_IS_OK(status)) {
2257 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2263 if (count == 0 && NT_STATUS_IS_OK(status)) {
2264 status = map_nt_error_from_unix(errno);
2270 /****************************************************************************
2272 ****************************************************************************/
2274 void reply_unlink(connection_struct *conn, struct smb_request *req)
2279 BOOL path_contains_wcard = False;
2281 START_PROFILE(SMBunlink);
2284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2285 END_PROFILE(SMBunlink);
2289 dirtype = SVAL(req->inbuf,smb_vwv0);
2291 srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name,
2292 smb_buf(req->inbuf) + 1, sizeof(name), 0,
2293 STR_TERMINATE, &status, &path_contains_wcard);
2294 if (!NT_STATUS_IS_OK(status)) {
2295 reply_nterror(req, status);
2296 END_PROFILE(SMBunlink);
2300 status = resolve_dfspath_wcard(conn,
2301 req->flags2 & FLAGS2_DFS_PATHNAMES,
2302 name, &path_contains_wcard);
2303 if (!NT_STATUS_IS_OK(status)) {
2304 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2305 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2306 ERRSRV, ERRbadpath);
2307 END_PROFILE(SMBunlink);
2310 reply_nterror(req, status);
2311 END_PROFILE(SMBunlink);
2315 DEBUG(3,("reply_unlink : %s\n",name));
2317 status = unlink_internals(conn, req, dirtype, name,
2318 path_contains_wcard);
2319 if (!NT_STATUS_IS_OK(status)) {
2320 if (open_was_deferred(req->mid)) {
2321 /* We have re-scheduled this call. */
2322 END_PROFILE(SMBunlink);
2325 reply_nterror(req, status);
2326 END_PROFILE(SMBunlink);
2330 reply_outbuf(req, 0, 0);
2331 END_PROFILE(SMBunlink);
2336 /****************************************************************************
2338 ****************************************************************************/
2340 static void fail_readraw(void)
2343 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2345 exit_server_cleanly(errstr);
2348 /****************************************************************************
2349 Fake (read/write) sendfile. Returns -1 on read or write fail.
2350 ****************************************************************************/
2352 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2356 size_t tosend = nread;
2363 bufsize = MIN(nread, 65536);
2365 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2369 while (tosend > 0) {
2373 if (tosend > bufsize) {
2378 ret = read_file(fsp,buf,startpos,cur_read);
2384 /* If we had a short read, fill with zeros. */
2385 if (ret < cur_read) {
2386 memset(buf, '\0', cur_read - ret);
2389 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2394 startpos += cur_read;
2398 return (ssize_t)nread;
2401 /****************************************************************************
2402 Use sendfile in readbraw.
2403 ****************************************************************************/
2405 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2406 ssize_t mincount, char *outbuf, int out_buffsize)
2410 #if defined(WITH_SENDFILE)
2412 * We can only use sendfile on a non-chained packet
2413 * but we can use on a non-oplocked file. tridge proved this
2414 * on a train in Germany :-). JRA.
2415 * reply_readbraw has already checked the length.
2418 if ( (chain_size == 0) && (nread > 0) &&
2419 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2422 _smb_setlen(outbuf,nread);
2423 header.data = (uint8 *)outbuf;
2427 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2428 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2429 if (errno == ENOSYS) {
2430 goto normal_readbraw;
2434 * Special hack for broken Linux with no working sendfile. If we
2435 * return EINTR we sent the header but not the rest of the data.
2436 * Fake this up by doing read/write calls.
2438 if (errno == EINTR) {
2439 /* Ensure we don't do this again. */
2440 set_use_sendfile(SNUM(conn), False);
2441 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2443 if (fake_sendfile(fsp, startpos, nread) == -1) {
2444 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2445 fsp->fsp_name, strerror(errno) ));
2446 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2451 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2452 fsp->fsp_name, strerror(errno) ));
2453 exit_server_cleanly("send_file_readbraw sendfile failed");
2463 ret = read_file(fsp,outbuf+4,startpos,nread);
2464 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2473 _smb_setlen(outbuf,ret);
2474 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2478 /****************************************************************************
2479 Reply to a readbraw (core+ protocol).
2480 ****************************************************************************/
2482 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2484 ssize_t maxcount,mincount;
2487 char *header = outbuf;
2489 START_PROFILE(SMBreadbraw);
2491 if (srv_is_signing_active()) {
2492 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2496 * Special check if an oplock break has been issued
2497 * and the readraw request croses on the wire, we must
2498 * return a zero length response here.
2501 fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2503 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2505 * fsp could be NULL here so use the value from the packet. JRA.
2507 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2508 _smb_setlen(header,0);
2509 if (write_data(smbd_server_fd(),header,4) != 4)
2511 END_PROFILE(SMBreadbraw);
2515 CHECK_FSP(fsp,conn);
2517 flush_write_cache(fsp, READRAW_FLUSH);
2519 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2520 if(CVAL(inbuf,smb_wct) == 10) {
2522 * This is a large offset (64 bit) read.
2524 #ifdef LARGE_SMB_OFF_T
2526 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2528 #else /* !LARGE_SMB_OFF_T */
2531 * Ensure we haven't been sent a >32 bit offset.
2534 if(IVAL(inbuf,smb_vwv8) != 0) {
2535 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2536 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2537 _smb_setlen(header,0);
2538 if (write_data(smbd_server_fd(),header,4) != 4)
2540 END_PROFILE(SMBreadbraw);
2544 #endif /* LARGE_SMB_OFF_T */
2547 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2548 _smb_setlen(header,0);
2549 if (write_data(smbd_server_fd(),header,4) != 4)
2551 END_PROFILE(SMBreadbraw);
2555 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2556 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2558 /* ensure we don't overrun the packet size */
2559 maxcount = MIN(65535,maxcount);
2561 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2565 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2569 if (startpos >= size) {
2572 nread = MIN(maxcount,(size - startpos));
2576 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2577 if (nread < mincount)
2581 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2582 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2584 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2586 DEBUG(5,("readbraw finished\n"));
2587 END_PROFILE(SMBreadbraw);
2592 #define DBGC_CLASS DBGC_LOCKING
2594 /****************************************************************************
2595 Reply to a lockread (core+ protocol).
2596 ****************************************************************************/
2598 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2606 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2607 struct byte_range_lock *br_lck = NULL;
2608 START_PROFILE(SMBlockread);
2610 CHECK_FSP(fsp,conn);
2611 if (!CHECK_READ(fsp,inbuf)) {
2612 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2615 release_level_2_oplocks_on_change(fsp);
2617 numtoread = SVAL(inbuf,smb_vwv1);
2618 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2620 outsize = set_message(inbuf,outbuf,5,3,True);
2621 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2622 data = smb_buf(outbuf) + 3;
2625 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2626 * protocol request that predates the read/write lock concept.
2627 * Thus instead of asking for a read lock here we need to ask
2628 * for a write lock. JRA.
2629 * Note that the requested lock size is unaffected by max_recv.
2632 br_lck = do_lock(smbd_messaging_context(),
2634 (uint32)SVAL(inbuf,smb_pid),
2635 (SMB_BIG_UINT)numtoread,
2636 (SMB_BIG_UINT)startpos,
2639 False, /* Non-blocking lock. */
2642 TALLOC_FREE(br_lck);
2644 if (NT_STATUS_V(status)) {
2645 END_PROFILE(SMBlockread);
2646 return ERROR_NT(status);
2650 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2653 if (numtoread > max_recv) {
2654 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2655 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2656 (unsigned int)numtoread, (unsigned int)max_recv ));
2657 numtoread = MIN(numtoread,max_recv);
2659 nread = read_file(fsp,data,startpos,numtoread);
2662 END_PROFILE(SMBlockread);
2663 return(UNIXERROR(ERRDOS,ERRnoaccess));
2667 SSVAL(outbuf,smb_vwv0,nread);
2668 SSVAL(outbuf,smb_vwv5,nread+3);
2669 SSVAL(smb_buf(outbuf),1,nread);
2671 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2672 fsp->fnum, (int)numtoread, (int)nread));
2674 END_PROFILE(SMBlockread);
2679 #define DBGC_CLASS DBGC_ALL
2681 /****************************************************************************
2683 ****************************************************************************/
2685 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2692 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
2693 START_PROFILE(SMBread);
2695 CHECK_FSP(fsp,conn);
2696 if (!CHECK_READ(fsp,inbuf)) {
2697 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2700 numtoread = SVAL(inbuf,smb_vwv1);
2701 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2703 outsize = set_message(inbuf,outbuf,5,3,True);
2704 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2706 * The requested read size cannot be greater than max_recv. JRA.
2708 if (numtoread > max_recv) {
2709 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2710 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2711 (unsigned int)numtoread, (unsigned int)max_recv ));
2712 numtoread = MIN(numtoread,max_recv);
2715 data = smb_buf(outbuf) + 3;
2717 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2718 END_PROFILE(SMBread);
2719 return ERROR_DOS(ERRDOS,ERRlock);
2723 nread = read_file(fsp,data,startpos,numtoread);
2726 END_PROFILE(SMBread);
2727 return(UNIXERROR(ERRDOS,ERRnoaccess));
2731 SSVAL(outbuf,smb_vwv0,nread);
2732 SSVAL(outbuf,smb_vwv5,nread+3);
2733 SCVAL(smb_buf(outbuf),0,1);
2734 SSVAL(smb_buf(outbuf),1,nread);
2736 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2737 fsp->fnum, (int)numtoread, (int)nread ) );
2739 END_PROFILE(SMBread);
2743 /****************************************************************************
2745 ****************************************************************************/
2747 static int setup_readX_header(const uint8 *inbuf, uint8 *outbuf,
2753 outsize = set_message((char *)inbuf, (char *)outbuf,12,smb_maxcnt,
2755 data = smb_buf(outbuf);
2757 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2758 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2759 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2760 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2761 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2762 SCVAL(outbuf,smb_vwv0,0xFF);
2763 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2764 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2768 /****************************************************************************
2769 Reply to a read and X - possibly using sendfile.
2770 ****************************************************************************/
2772 static void send_file_readX(connection_struct *conn, struct smb_request *req,
2773 files_struct *fsp, SMB_OFF_T startpos,
2776 SMB_STRUCT_STAT sbuf;
2779 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2780 reply_unixerror(req, ERRDOS, ERRnoaccess);
2784 if (startpos > sbuf.st_size) {
2786 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
2787 smb_maxcnt = (sbuf.st_size - startpos);
2790 if (smb_maxcnt == 0) {
2794 #if defined(WITH_SENDFILE)
2796 * We can only use sendfile on a non-chained packet
2797 * but we can use on a non-oplocked file. tridge proved this
2798 * on a train in Germany :-). JRA.
2801 if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
2802 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2803 uint8 headerbuf[smb_size + 12 * 2];
2807 * Set up the packet header before send. We
2808 * assume here the sendfile will work (get the
2809 * correct amount of data).
2812 header = data_blob_const(headerbuf, sizeof(headerbuf));
2814 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
2815 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
2817 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2818 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2819 if (errno == ENOSYS) {
2824 * Special hack for broken Linux with no working sendfile. If we
2825 * return EINTR we sent the header but not the rest of the data.
2826 * Fake this up by doing read/write calls.
2829 if (errno == EINTR) {
2830 /* Ensure we don't do this again. */
2831 set_use_sendfile(SNUM(conn), False);
2832 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2833 nread = fake_sendfile(fsp, startpos,
2836 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2837 fsp->fsp_name, strerror(errno) ));
2838 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2840 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2841 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2842 /* No outbuf here means successful sendfile. */
2843 TALLOC_FREE(req->outbuf);
2847 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2848 fsp->fsp_name, strerror(errno) ));
2849 exit_server_cleanly("send_file_readX sendfile failed");
2852 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2853 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2854 /* No outbuf here means successful sendfile. */
2855 TALLOC_FREE(req->outbuf);
2863 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
2864 uint8 headerbuf[smb_size + 2*12];
2866 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
2867 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
2869 /* Send out the header. */
2870 if (write_data(smbd_server_fd(), (char *)headerbuf,
2871 sizeof(headerbuf)) != sizeof(headerbuf)) {
2872 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2873 fsp->fsp_name, strerror(errno) ));
2874 exit_server_cleanly("send_file_readX sendfile failed");
2876 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
2878 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2879 fsp->fsp_name, strerror(errno) ));
2880 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2882 TALLOC_FREE(req->outbuf);
2885 reply_outbuf(req, 12, smb_maxcnt);
2887 nread = read_file(fsp, smb_buf(req->outbuf), startpos,
2890 reply_unixerror(req, ERRDOS, ERRnoaccess);
2894 setup_readX_header(req->inbuf, req->outbuf, nread);
2896 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2897 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2899 chain_reply_new(req);
2905 /****************************************************************************
2906 Reply to a read and X.
2907 ****************************************************************************/
2909 void reply_read_and_X(connection_struct *conn, struct smb_request *req)
2914 BOOL big_readX = False;
2916 size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
2919 START_PROFILE(SMBreadX);
2921 if ((req->wct != 10) && (req->wct != 12)) {
2922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2926 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
2927 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
2928 smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
2930 /* If it's an IPC, pass off the pipe handler. */
2932 reply_pipe_read_and_X(req);
2933 END_PROFILE(SMBreadX);
2937 if (!check_fsp(conn, req, fsp, ¤t_user)) {
2938 END_PROFILE(SMBreadX);
2942 if (!CHECK_READ(fsp,req->inbuf)) {
2943 reply_doserror(req, ERRDOS,ERRbadaccess);
2944 END_PROFILE(SMBreadX);
2948 if (global_client_caps & CAP_LARGE_READX) {
2949 size_t upper_size = SVAL(req->inbuf,smb_vwv7);
2950 smb_maxcnt |= (upper_size<<16);
2951 if (upper_size > 1) {
2952 /* Can't do this on a chained packet. */
2953 if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
2954 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
2955 END_PROFILE(SMBreadX);
2958 /* We currently don't do this on signed or sealed data. */
2959 if (srv_is_signing_active() || srv_encryption_on()) {
2960 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
2961 END_PROFILE(SMBreadX);
2964 /* Is there room in the reply for this data ? */
2965 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
2967 NT_STATUS_INVALID_PARAMETER);
2968 END_PROFILE(SMBreadX);
2975 if (req->wct == 12) {
2976 #ifdef LARGE_SMB_OFF_T
2978 * This is a large offset (64 bit) read.
2980 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
2982 #else /* !LARGE_SMB_OFF_T */
2985 * Ensure we haven't been sent a >32 bit offset.
2988 if(IVAL(req->inbuf,smb_vwv10) != 0) {
2989 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
2990 "used and we don't support 64 bit offsets.\n",
2991 (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
2992 END_PROFILE(SMBreadX);
2993 reply_doserror(req, ERRDOS, ERRbadaccess);
2997 #endif /* LARGE_SMB_OFF_T */
3001 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
3002 (SMB_BIG_UINT)startpos, READ_LOCK)) {
3003 END_PROFILE(SMBreadX);
3004 reply_doserror(req, ERRDOS, ERRlock);
3009 && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3010 END_PROFILE(SMBreadX);
3011 reply_post_legacy(req, -1);
3015 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3017 END_PROFILE(SMBreadX);
3021 /****************************************************************************
3022 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3023 ****************************************************************************/
3025 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3028 ssize_t total_written=0;
3029 size_t numtowrite=0;
3034 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3037 START_PROFILE(SMBwritebraw);
3039 if (srv_is_signing_active()) {
3040 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
3043 CHECK_FSP(fsp,conn);
3044 if (!CHECK_WRITE(fsp)) {
3045 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3048 tcount = IVAL(inbuf,smb_vwv1);
3049 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3050 write_through = BITSETW(inbuf+smb_vwv7,0);
3052 /* We have to deal with slightly different formats depending
3053 on whether we are using the core+ or lanman1.0 protocol */
3055 if(Protocol <= PROTOCOL_COREPLUS) {
3056 numtowrite = SVAL(smb_buf(inbuf),-2);
3057 data = smb_buf(inbuf);
3059 numtowrite = SVAL(inbuf,smb_vwv10);
3060 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
3063 /* force the error type */
3064 SCVAL(inbuf,smb_com,SMBwritec);
3065 SCVAL(outbuf,smb_com,SMBwritec);
3067 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3068 END_PROFILE(SMBwritebraw);
3069 return(ERROR_DOS(ERRDOS,ERRlock));
3073 nwritten = write_file(fsp,data,startpos,numtowrite);
3075 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
3076 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
3078 if (nwritten < (ssize_t)numtowrite) {
3079 END_PROFILE(SMBwritebraw);
3080 return(UNIXERROR(ERRHRD,ERRdiskfull));
3083 total_written = nwritten;
3085 /* Return a message to the redirector to tell it to send more bytes */
3086 SCVAL(outbuf,smb_com,SMBwritebraw);
3087 SSVALS(outbuf,smb_vwv0,-1);
3088 outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3090 if (!send_smb(smbd_server_fd(),outbuf))
3091 exit_server_cleanly("reply_writebraw: send_smb failed.");
3093 /* Now read the raw data into the buffer and write it */
3094 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
3095 exit_server_cleanly("secondary writebraw failed");
3098 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
3099 numtowrite = smb_len(inbuf);
3101 /* Set up outbuf to return the correct return */
3102 outsize = set_message(inbuf,outbuf,1,0,True);
3103 SCVAL(outbuf,smb_com,SMBwritec);
3105 if (numtowrite != 0) {
3107 if (numtowrite > BUFFER_SIZE) {
3108 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
3109 (unsigned int)numtowrite ));
3110 exit_server_cleanly("secondary writebraw failed");
3113 if (tcount > nwritten+numtowrite) {
3114 DEBUG(3,("Client overestimated the write %d %d %d\n",
3115 (int)tcount,(int)nwritten,(int)numtowrite));
3118 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
3119 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
3121 exit_server_cleanly("secondary writebraw failed");
3124 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
3125 if (nwritten == -1) {
3126 END_PROFILE(SMBwritebraw);
3127 return(UNIXERROR(ERRHRD,ERRdiskfull));
3130 if (nwritten < (ssize_t)numtowrite) {
3131 SCVAL(outbuf,smb_rcls,ERRHRD);
3132 SSVAL(outbuf,smb_err,ERRdiskfull);
3136 total_written += nwritten;
3139 SSVAL(outbuf,smb_vwv0,total_written);
3141 status = sync_file(conn, fsp, write_through);
3142 if (!NT_STATUS_IS_OK(status)) {
3143 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3144 fsp->fsp_name, nt_errstr(status) ));
3145 END_PROFILE(SMBwritebraw);
3146 return ERROR_NT(status);
3149 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
3150 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
3152 /* we won't return a status if write through is not selected - this follows what WfWg does */
3153 END_PROFILE(SMBwritebraw);
3154 if (!write_through && total_written==tcount) {
3156 #if RABBIT_PELLET_FIX
3158 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3159 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
3161 if (!send_keepalive(smbd_server_fd()))
3162 exit_server_cleanly("reply_writebraw: send of keepalive failed");
3171 #define DBGC_CLASS DBGC_LOCKING
3173 /****************************************************************************
3174 Reply to a writeunlock (core+).
3175 ****************************************************************************/
3177 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
3178 int size, int dum_buffsize)
3180 ssize_t nwritten = -1;
3184 NTSTATUS status = NT_STATUS_OK;
3185 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3187 START_PROFILE(SMBwriteunlock);
3189 CHECK_FSP(fsp,conn);
3190 if (!CHECK_WRITE(fsp)) {
3191 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3194 numtowrite = SVAL(inbuf,smb_vwv1);
3195 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3196 data = smb_buf(inbuf) + 3;
3198 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3199 END_PROFILE(SMBwriteunlock);
3200 return ERROR_DOS(ERRDOS,ERRlock);
3203 /* The special X/Open SMB protocol handling of
3204 zero length writes is *NOT* done for
3206 if(numtowrite == 0) {
3209 nwritten = write_file(fsp,data,startpos,numtowrite);
3212 status = sync_file(conn, fsp, False /* write through */);
3213 if (!NT_STATUS_IS_OK(status)) {
3214 END_PROFILE(SMBwriteunlock);
3215 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3216 fsp->fsp_name, nt_errstr(status) ));
3217 return ERROR_NT(status);
3220 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3221 END_PROFILE(SMBwriteunlock);
3222 return(UNIXERROR(ERRHRD,ERRdiskfull));
3226 status = do_unlock(smbd_messaging_context(),
3228 (uint32)SVAL(inbuf,smb_pid),
3229 (SMB_BIG_UINT)numtowrite,
3230 (SMB_BIG_UINT)startpos,
3233 if (NT_STATUS_V(status)) {
3234 END_PROFILE(SMBwriteunlock);
3235 return ERROR_NT(status);
3239 outsize = set_message(inbuf,outbuf,1,0,True);
3241 SSVAL(outbuf,smb_vwv0,nwritten);
3243 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3244 fsp->fnum, (int)numtowrite, (int)nwritten));
3246 END_PROFILE(SMBwriteunlock);
3251 #define DBGC_CLASS DBGC_ALL
3253 /****************************************************************************
3255 ****************************************************************************/
3257 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
3260 ssize_t nwritten = -1;
3263 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3266 START_PROFILE(SMBwrite);
3268 /* If it's an IPC, pass off the pipe handler. */
3270 END_PROFILE(SMBwrite);
3271 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3274 CHECK_FSP(fsp,conn);
3275 if (!CHECK_WRITE(fsp)) {
3276 END_PROFILE(SMBwrite);
3277 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3280 numtowrite = SVAL(inbuf,smb_vwv1);
3281 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3282 data = smb_buf(inbuf) + 3;
3284 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3285 END_PROFILE(SMBwrite);
3286 return ERROR_DOS(ERRDOS,ERRlock);
3290 * X/Open SMB protocol says that if smb_vwv1 is
3291 * zero then the file size should be extended or
3292 * truncated to the size given in smb_vwv[2-3].
3295 if(numtowrite == 0) {
3297 * This is actually an allocate call, and set EOF. JRA.
3299 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3301 END_PROFILE(SMBwrite);
3302 return ERROR_NT(NT_STATUS_DISK_FULL);
3304 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3306 END_PROFILE(SMBwrite);
3307 return ERROR_NT(NT_STATUS_DISK_FULL);
3310 nwritten = write_file(fsp,data,startpos,numtowrite);
3312 status = sync_file(conn, fsp, False);
3313 if (!NT_STATUS_IS_OK(status)) {
3314 END_PROFILE(SMBwrite);
3315 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3316 fsp->fsp_name, nt_errstr(status) ));
3317 return ERROR_NT(status);
3320 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3321 END_PROFILE(SMBwrite);
3322 return(UNIXERROR(ERRHRD,ERRdiskfull));
3325 outsize = set_message(inbuf,outbuf,1,0,True);
3327 SSVAL(outbuf,smb_vwv0,nwritten);
3329 if (nwritten < (ssize_t)numtowrite) {
3330 SCVAL(outbuf,smb_rcls,ERRHRD);
3331 SSVAL(outbuf,smb_err,ERRdiskfull);
3334 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3336 END_PROFILE(SMBwrite);
3340 /****************************************************************************
3341 Reply to a write and X.
3342 ****************************************************************************/
3344 void reply_write_and_X(connection_struct *conn, struct smb_request *req)
3351 unsigned int smb_doff;
3352 unsigned int smblen;
3357 START_PROFILE(SMBwriteX);
3359 if ((req->wct != 12) && (req->wct != 14)) {
3360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3361 END_PROFILE(SMBwriteX);
3365 numtowrite = SVAL(req->inbuf,smb_vwv10);
3366 smb_doff = SVAL(req->inbuf,smb_vwv11);
3367 smblen = smb_len(req->inbuf);
3368 large_writeX = ((req->wct == 14) && (smblen > 0xFFFF));
3370 /* Deal with possible LARGE_WRITEX */
3372 numtowrite |= ((((size_t)SVAL(req->inbuf,smb_vwv9)) & 1 )<<16);
3375 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3376 reply_doserror(req, ERRDOS, ERRbadmem);
3377 END_PROFILE(SMBwriteX);
3381 /* If it's an IPC, pass off the pipe handler. */
3383 reply_pipe_write_and_X(req);
3384 END_PROFILE(SMBwriteX);
3388 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3389 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3390 write_through = BITSETW(req->inbuf+smb_vwv7,0);
3392 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3393 END_PROFILE(SMBwriteX);
3397 if (!CHECK_WRITE(fsp)) {
3398 reply_doserror(req, ERRDOS, ERRbadaccess);
3399 END_PROFILE(SMBwriteX);
3403 data = smb_base(req->inbuf) + smb_doff;
3405 if(req->wct == 14) {
3406 #ifdef LARGE_SMB_OFF_T
3408 * This is a large offset (64 bit) write.
3410 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
3412 #else /* !LARGE_SMB_OFF_T */
3415 * Ensure we haven't been sent a >32 bit offset.
3418 if(IVAL(req->inbuf,smb_vwv12) != 0) {
3419 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
3420 "used and we don't support 64 bit offsets.\n",
3421 (unsigned int)IVAL(inbuf,smb_vwv12) ));
3422 reply_doserror(req, ERRDOS, ERRbadaccess);
3423 END_PROFILE(SMBwriteX);
3427 #endif /* LARGE_SMB_OFF_T */
3430 if (is_locked(fsp,(uint32)req->smbpid,
3431 (SMB_BIG_UINT)numtowrite,
3432 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3433 reply_doserror(req, ERRDOS, ERRlock);
3434 END_PROFILE(SMBwriteX);
3438 /* X/Open SMB protocol says that, unlike SMBwrite
3439 if the length is zero then NO truncation is
3440 done, just a write of zero. To truncate a file,
3443 if(numtowrite == 0) {
3447 if (schedule_aio_write_and_X(conn, req, fsp, data, startpos,
3449 END_PROFILE(SMBwriteX);
3453 nwritten = write_file(fsp,data,startpos,numtowrite);
3456 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3457 reply_unixerror(req, ERRHRD, ERRdiskfull);
3458 END_PROFILE(SMBwriteX);
3462 reply_outbuf(req, 6, 0);
3463 SSVAL(req->outbuf,smb_vwv2,nwritten);
3465 SSVAL(req->outbuf,smb_vwv4,(nwritten>>16)&1);
3467 if (nwritten < (ssize_t)numtowrite) {
3468 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3469 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3472 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3473 fsp->fnum, (int)numtowrite, (int)nwritten));
3475 status = sync_file(conn, fsp, write_through);
3476 if (!NT_STATUS_IS_OK(status)) {
3477 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3478 fsp->fsp_name, nt_errstr(status) ));
3479 reply_nterror(req, status);
3480 END_PROFILE(SMBwriteX);
3484 END_PROFILE(SMBwriteX);
3485 chain_reply_new(req);
3489 /****************************************************************************
3491 ****************************************************************************/
3493 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3499 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3500 START_PROFILE(SMBlseek);
3502 CHECK_FSP(fsp,conn);
3504 flush_write_cache(fsp, SEEK_FLUSH);
3506 mode = SVAL(inbuf,smb_vwv1) & 3;
3507 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3508 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3517 res = fsp->fh->pos + startpos;
3528 if (umode == SEEK_END) {
3529 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3530 if(errno == EINVAL) {
3531 SMB_OFF_T current_pos = startpos;
3532 SMB_STRUCT_STAT sbuf;
3534 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3535 END_PROFILE(SMBlseek);
3536 return(UNIXERROR(ERRDOS,ERRnoaccess));
3539 current_pos += sbuf.st_size;
3541 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3546 END_PROFILE(SMBlseek);
3547 return(UNIXERROR(ERRDOS,ERRnoaccess));
3553 outsize = set_message(inbuf,outbuf,2,0,True);
3554 SIVAL(outbuf,smb_vwv0,res);
3556 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3557 fsp->fnum, (double)startpos, (double)res, mode));
3559 END_PROFILE(SMBlseek);
3563 /****************************************************************************
3565 ****************************************************************************/
3567 void reply_flush(connection_struct *conn, struct smb_request *req)
3572 START_PROFILE(SMBflush);
3575 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3579 fnum = SVAL(req->inbuf,smb_vwv0);
3580 fsp = file_fsp(fnum);
3582 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, ¤t_user)) {
3587 file_sync_all(conn);
3589 NTSTATUS status = sync_file(conn, fsp, True);
3590 if (!NT_STATUS_IS_OK(status)) {
3591 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3592 fsp->fsp_name, nt_errstr(status) ));
3593 reply_nterror(req, status);
3594 END_PROFILE(SMBflush);
3599 reply_outbuf(req, 0, 0);
3601 DEBUG(3,("flush\n"));
3602 END_PROFILE(SMBflush);
3606 /****************************************************************************
3608 conn POINTER CAN BE NULL HERE !
3609 ****************************************************************************/
3611 void reply_exit(connection_struct *conn, struct smb_request *req)
3613 START_PROFILE(SMBexit);
3615 file_close_pid(req->smbpid, req->vuid);
3617 reply_outbuf(req, 0, 0);
3619 DEBUG(3,("exit\n"));
3621 END_PROFILE(SMBexit);
3625 /****************************************************************************
3626 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3627 ****************************************************************************/
3629 void reply_close(connection_struct *conn, struct smb_request *req)
3631 NTSTATUS status = NT_STATUS_OK;
3632 files_struct *fsp = NULL;
3633 START_PROFILE(SMBclose);
3636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3637 END_PROFILE(SMBclose);
3641 /* If it's an IPC, pass off to the pipe handler. */
3643 reply_pipe_close(conn, req);
3644 END_PROFILE(SMBclose);
3648 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3651 * We can only use CHECK_FSP if we know it's not a directory.
3654 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3655 reply_doserror(req, ERRDOS, ERRbadfid);
3656 END_PROFILE(SMBclose);
3660 if(fsp->is_directory) {
3662 * Special case - close NT SMB directory handle.
3664 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3665 status = close_file(fsp,NORMAL_CLOSE);
3668 * Close ordinary file.
3671 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3672 fsp->fh->fd, fsp->fnum,
3673 conn->num_files_open));
3676 * Take care of any time sent in the close.
3679 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
3680 srv_make_unix_date3(
3681 req->inbuf+smb_vwv1)));
3684 * close_file() returns the unix errno if an error
3685 * was detected on close - normally this is due to
3686 * a disk full error. If not then it was probably an I/O error.
3689 status = close_file(fsp,NORMAL_CLOSE);
3692 if (!NT_STATUS_IS_OK(status)) {
3693 reply_nterror(req, status);
3694 END_PROFILE(SMBclose);
3698 reply_outbuf(req, 0, 0);
3699 END_PROFILE(SMBclose);
3703 /****************************************************************************
3704 Reply to a writeclose (Core+ protocol).
3705 ****************************************************************************/
3707 int reply_writeclose(connection_struct *conn,
3708 char *inbuf,char *outbuf, int size, int dum_buffsize)
3711 ssize_t nwritten = -1;
3713 NTSTATUS close_status = NT_STATUS_OK;
3716 struct timespec mtime;
3717 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3718 START_PROFILE(SMBwriteclose);
3720 CHECK_FSP(fsp,conn);
3721 if (!CHECK_WRITE(fsp)) {
3722 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3725 numtowrite = SVAL(inbuf,smb_vwv1);
3726 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3727 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3728 data = smb_buf(inbuf) + 1;
3730 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3731 END_PROFILE(SMBwriteclose);
3732 return ERROR_DOS(ERRDOS,ERRlock);
3735 nwritten = write_file(fsp,data,startpos,numtowrite);
3737 set_filetime(conn, fsp->fsp_name, mtime);
3740 * More insanity. W2K only closes the file if writelen > 0.
3745 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3747 close_status = close_file(fsp,NORMAL_CLOSE);
3750 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3751 fsp->fnum, (int)numtowrite, (int)nwritten,
3752 conn->num_files_open));
3754 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3755 END_PROFILE(SMBwriteclose);
3756 return(UNIXERROR(ERRHRD,ERRdiskfull));
3759 if(!NT_STATUS_IS_OK(close_status)) {
3760 END_PROFILE(SMBwriteclose);
3761 return ERROR_NT(close_status);
3764 outsize = set_message(inbuf,outbuf,1,0,True);
3766 SSVAL(outbuf,smb_vwv0,nwritten);
3767 END_PROFILE(SMBwriteclose);
3772 #define DBGC_CLASS DBGC_LOCKING
3774 /****************************************************************************
3776 ****************************************************************************/
3778 int reply_lock(connection_struct *conn,
3779 char *inbuf,char *outbuf, int length, int dum_buffsize)
3781 int outsize = set_message(inbuf,outbuf,0,0,False);
3782 SMB_BIG_UINT count,offset;
3784 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3785 struct byte_range_lock *br_lck = NULL;
3787 START_PROFILE(SMBlock);
3789 CHECK_FSP(fsp,conn);
3791 release_level_2_oplocks_on_change(fsp);
3793 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3794 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3796 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3797 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3799 br_lck = do_lock(smbd_messaging_context(),
3801 (uint32)SVAL(inbuf,smb_pid),
3806 False, /* Non-blocking lock. */
3810 TALLOC_FREE(br_lck);
3812 if (NT_STATUS_V(status)) {
3813 END_PROFILE(SMBlock);
3814 return ERROR_NT(status);
3817 END_PROFILE(SMBlock);
3821 /****************************************************************************
3823 ****************************************************************************/
3825 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3828 int outsize = set_message(inbuf,outbuf,0,0,False);
3829 SMB_BIG_UINT count,offset;
3831 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3832 START_PROFILE(SMBunlock);
3834 CHECK_FSP(fsp,conn);
3836 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3837 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3839 status = do_unlock(smbd_messaging_context(),
3841 (uint32)SVAL(inbuf,smb_pid),
3846 if (NT_STATUS_V(status)) {
3847 END_PROFILE(SMBunlock);
3848 return ERROR_NT(status);
3851 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3852 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3854 END_PROFILE(SMBunlock);
3859 #define DBGC_CLASS DBGC_ALL
3861 /****************************************************************************
3863 conn POINTER CAN BE NULL HERE !
3864 ****************************************************************************/
3866 void reply_tdis(connection_struct *conn, struct smb_request *req)
3868 START_PROFILE(SMBtdis);
3871 DEBUG(4,("Invalid connection in tdis\n"));
3872 reply_doserror(req, ERRSRV, ERRinvnid);
3873 END_PROFILE(SMBtdis);
3879 close_cnum(conn,req->vuid);
3881 reply_outbuf(req, 0, 0);
3882 END_PROFILE(SMBtdis);
3886 /****************************************************************************
3888 conn POINTER CAN BE NULL HERE !
3889 ****************************************************************************/
3891 void reply_echo(connection_struct *conn, struct smb_request *req)
3895 unsigned int data_len = smb_buflen(req->inbuf);
3897 START_PROFILE(SMBecho);
3900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3901 END_PROFILE(SMBecho);
3905 if (data_len > BUFFER_SIZE) {
3906 DEBUG(0,("reply_echo: data_len too large.\n"));
3907 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
3908 END_PROFILE(SMBecho);
3912 smb_reverb = SVAL(req->inbuf,smb_vwv0);
3914 reply_outbuf(req, 1, data_len);
3916 /* copy any incoming data back out */
3918 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
3921 if (smb_reverb > 100) {
3922 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3926 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3927 SSVAL(req->outbuf,smb_vwv0,seq_num);
3929 show_msg((char *)req->outbuf);
3930 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
3931 exit_server_cleanly("reply_echo: send_smb failed.");
3934 DEBUG(3,("echo %d times\n", smb_reverb));
3936 TALLOC_FREE(req->outbuf);
3940 END_PROFILE(SMBecho);
3944 /****************************************************************************
3945 Reply to a printopen.
3946 ****************************************************************************/
3948 int reply_printopen(connection_struct *conn,
3949 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3955 START_PROFILE(SMBsplopen);
3957 if (!CAN_PRINT(conn)) {
3958 END_PROFILE(SMBsplopen);
3959 return ERROR_DOS(ERRDOS,ERRnoaccess);
3962 /* Open for exclusive use, write only. */
3963 status = print_fsp_open(conn, NULL, &fsp);
3965 if (!NT_STATUS_IS_OK(status)) {
3966 END_PROFILE(SMBsplopen);
3967 return(ERROR_NT(status));
3970 outsize = set_message(inbuf,outbuf,1,0,True);
3971 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3973 DEBUG(3,("openprint fd=%d fnum=%d\n",
3974 fsp->fh->fd, fsp->fnum));
3976 END_PROFILE(SMBsplopen);
3980 /****************************************************************************
3981 Reply to a printclose.
3982 ****************************************************************************/
3984 int reply_printclose(connection_struct *conn,
3985 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3987 int outsize = set_message(inbuf,outbuf,0,0,False);
3988 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3990 START_PROFILE(SMBsplclose);
3992 CHECK_FSP(fsp,conn);
3994 if (!CAN_PRINT(conn)) {
3995 END_PROFILE(SMBsplclose);
3996 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3999 DEBUG(3,("printclose fd=%d fnum=%d\n",
4000 fsp->fh->fd,fsp->fnum));
4002 status = close_file(fsp,NORMAL_CLOSE);
4004 if(!NT_STATUS_IS_OK(status)) {
4005 END_PROFILE(SMBsplclose);
4006 return ERROR_NT(status);
4009 END_PROFILE(SMBsplclose);
4013 /****************************************************************************
4014 Reply to a printqueue.
4015 ****************************************************************************/
4017 int reply_printqueue(connection_struct *conn,
4018 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4020 int outsize = set_message(inbuf,outbuf,2,3,True);
4021 int max_count = SVAL(inbuf,smb_vwv0);
4022 int start_index = SVAL(inbuf,smb_vwv1);
4023 START_PROFILE(SMBsplretq);
4025 /* we used to allow the client to get the cnum wrong, but that
4026 is really quite gross and only worked when there was only
4027 one printer - I think we should now only accept it if they
4028 get it right (tridge) */
4029 if (!CAN_PRINT(conn)) {
4030 END_PROFILE(SMBsplretq);
4031 return ERROR_DOS(ERRDOS,ERRnoaccess);
4034 SSVAL(outbuf,smb_vwv0,0);
4035 SSVAL(outbuf,smb_vwv1,0);
4036 SCVAL(smb_buf(outbuf),0,1);
4037 SSVAL(smb_buf(outbuf),1,0);
4039 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4040 start_index, max_count));
4043 print_queue_struct *queue = NULL;
4044 print_status_struct status;
4045 char *p = smb_buf(outbuf) + 3;
4046 int count = print_queue_status(SNUM(conn), &queue, &status);
4047 int num_to_get = ABS(max_count);
4048 int first = (max_count>0?start_index:start_index+max_count+1);
4054 num_to_get = MIN(num_to_get,count-first);
4057 for (i=first;i<first+num_to_get;i++) {
4058 srv_put_dos_date2(p,0,queue[i].time);
4059 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4060 SSVAL(p,5, queue[i].job);
4061 SIVAL(p,7,queue[i].size);
4063 srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+12,
4064 queue[i].fs_user, 16, STR_ASCII);
4069 outsize = set_message(inbuf,outbuf,2,28*count+3,False);
4070 SSVAL(outbuf,smb_vwv0,count);
4071 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
4072 SCVAL(smb_buf(outbuf),0,1);
4073 SSVAL(smb_buf(outbuf),1,28*count);
4078 DEBUG(3,("%d entries returned in queue\n",count));
4081 END_PROFILE(SMBsplretq);
4085 /****************************************************************************
4086 Reply to a printwrite.
4087 ****************************************************************************/
4089 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4092 int outsize = set_message(inbuf,outbuf,0,0,False);
4094 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
4096 START_PROFILE(SMBsplwr);
4098 if (!CAN_PRINT(conn)) {
4099 END_PROFILE(SMBsplwr);
4100 return ERROR_DOS(ERRDOS,ERRnoaccess);
4103 CHECK_FSP(fsp,conn);
4104 if (!CHECK_WRITE(fsp)) {
4105 return(ERROR_DOS(ERRDOS,ERRbadaccess));
4108 numtowrite = SVAL(smb_buf(inbuf),1);
4109 data = smb_buf(inbuf) + 3;
4111 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
4112 END_PROFILE(SMBsplwr);
4113 return(UNIXERROR(ERRHRD,ERRdiskfull));
4116 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4118 END_PROFILE(SMBsplwr);
4122 /****************************************************************************
4124 ****************************************************************************/
4126 void reply_mkdir(connection_struct *conn, struct smb_request *req)
4130 SMB_STRUCT_STAT sbuf;
4132 START_PROFILE(SMBmkdir);
4134 srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4135 smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4136 STR_TERMINATE, &status);
4137 if (!NT_STATUS_IS_OK(status)) {
4138 reply_nterror(req, status);
4139 END_PROFILE(SMBmkdir);
4143 status = resolve_dfspath(conn,
4144 req->flags2 & FLAGS2_DFS_PATHNAMES,
4146 if (!NT_STATUS_IS_OK(status)) {
4147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4148 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4149 ERRSRV, ERRbadpath);
4150 END_PROFILE(SMBmkdir);
4153 reply_nterror(req, status);
4154 END_PROFILE(SMBmkdir);
4158 status = unix_convert(conn, directory, False, NULL, &sbuf);
4159 if (!NT_STATUS_IS_OK(status)) {
4160 reply_nterror(req, status);
4161 END_PROFILE(SMBmkdir);
4165 status = check_name(conn, directory);
4166 if (!NT_STATUS_IS_OK(status)) {
4167 reply_nterror(req, status);
4168 END_PROFILE(SMBmkdir);
4172 status = create_directory(conn, directory);
4174 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4176 if (!NT_STATUS_IS_OK(status)) {
4178 if (!use_nt_status()
4179 && NT_STATUS_EQUAL(status,
4180 NT_STATUS_OBJECT_NAME_COLLISION)) {
4182 * Yes, in the DOS error code case we get a
4183 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4184 * samba4 torture test.
4186 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4189 reply_nterror(req, status);
4190 END_PROFILE(SMBmkdir);
4194 reply_outbuf(req, 0, 0);
4196 DEBUG( 3, ( "mkdir %s\n", directory ) );
4198 END_PROFILE(SMBmkdir);
4202 /****************************************************************************
4203 Static function used by reply_rmdir to delete an entire directory
4204 tree recursively. Return True on ok, False on fail.
4205 ****************************************************************************/
4207 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
4209 const char *dname = NULL;
4212 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4217 while((dname = ReadDirName(dir_hnd, &offset))) {
4221 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4224 if (!is_visible_file(conn, directory, dname, &st, False))
4227 /* Construct the full name. */
4228 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4234 pstrcpy(fullname, directory);
4235 pstrcat(fullname, "/");
4236 pstrcat(fullname, dname);
4238 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4243 if(st.st_mode & S_IFDIR) {
4244 if(!recursive_rmdir(conn, fullname)) {
4248 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4252 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4261 /****************************************************************************
4262 The internals of the rmdir code - called elsewhere.
4263 ****************************************************************************/
4265 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4270 /* Might be a symlink. */
4271 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4272 return map_nt_error_from_unix(errno);
4275 if (S_ISLNK(st.st_mode)) {
4276 /* Is what it points to a directory ? */
4277 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4278 return map_nt_error_from_unix(errno);
4280 if (!(S_ISDIR(st.st_mode))) {
4281 return NT_STATUS_NOT_A_DIRECTORY;
4283 ret = SMB_VFS_UNLINK(conn,directory);
4285 ret = SMB_VFS_RMDIR(conn,directory);
4288 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4289 FILE_NOTIFY_CHANGE_DIR_NAME,
4291 return NT_STATUS_OK;
4294 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4296 * Check to see if the only thing in this directory are
4297 * vetoed files/directories. If so then delete them and
4298 * retry. If we fail to delete any of them (and we *don't*
4299 * do a recursive delete) then fail the rmdir.
4303 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4305 if(dir_hnd == NULL) {
4310 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4311 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4313 if (!is_visible_file(conn, directory, dname, &st, False))
4315 if(!IS_VETO_PATH(conn, dname)) {
4322 /* We only have veto files/directories. Recursive delete. */
4324 RewindDir(dir_hnd,&dirpos);
4325 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4328 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4330 if (!is_visible_file(conn, directory, dname, &st, False))
4333 /* Construct the full name. */
4334 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4339 pstrcpy(fullname, directory);
4340 pstrcat(fullname, "/");
4341 pstrcat(fullname, dname);
4343 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4345 if(st.st_mode & S_IFDIR) {
4346 if(lp_recursive_veto_delete(SNUM(conn))) {
4347 if(!recursive_rmdir(conn, fullname))
4350 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4352 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4356 /* Retry the rmdir */
4357 ret = SMB_VFS_RMDIR(conn,directory);
4363 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4364 "%s\n", directory,strerror(errno)));
4365 return map_nt_error_from_unix(errno);
4368 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4369 FILE_NOTIFY_CHANGE_DIR_NAME,
4372 return NT_STATUS_OK;
4375 /****************************************************************************
4377 ****************************************************************************/
4379 void reply_rmdir(connection_struct *conn, struct smb_request *req)
4382 SMB_STRUCT_STAT sbuf;
4384 START_PROFILE(SMBrmdir);
4386 srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4387 smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4388 STR_TERMINATE, &status);
4389 if (!NT_STATUS_IS_OK(status)) {
4390 reply_nterror(req, status);
4391 END_PROFILE(SMBrmdir);
4395 status = resolve_dfspath(conn,
4396 req->flags2 & FLAGS2_DFS_PATHNAMES,
4398 if (!NT_STATUS_IS_OK(status)) {
4399 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4400 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4401 ERRSRV, ERRbadpath);
4402 END_PROFILE(SMBrmdir);
4405 reply_nterror(req, status);
4406 END_PROFILE(SMBrmdir);
4410 status = unix_convert(conn, directory, False, NULL, &sbuf);
4411 if (!NT_STATUS_IS_OK(status)) {
4412 reply_nterror(req, status);
4413 END_PROFILE(SMBrmdir);
4417 status = check_name(conn, directory);
4418 if (!NT_STATUS_IS_OK(status)) {
4419 reply_nterror(req, status);
4420 END_PROFILE(SMBrmdir);
4424 dptr_closepath(directory, req->smbpid);
4425 status = rmdir_internals(conn, directory);
4426 if (!NT_STATUS_IS_OK(status)) {
4427 reply_nterror(req, status);
4428 END_PROFILE(SMBrmdir);
4432 reply_outbuf(req, 0, 0);
4434 DEBUG( 3, ( "rmdir %s\n", directory ) );
4436 END_PROFILE(SMBrmdir);
4440 /*******************************************************************
4441 Resolve wildcards in a filename rename.
4442 Note that name is in UNIX charset and thus potentially can be more
4443 than fstring buffer (255 bytes) especially in default UTF-8 case.
4444 Therefore, we use pstring inside and all calls should ensure that
4445 name2 is at least pstring-long (they do already)
4446 ********************************************************************/
4448 static BOOL resolve_wildcards(const char *name1, char *name2)
4450 pstring root1,root2;
4452 char *p,*p2, *pname1, *pname2;
4453 int available_space, actual_space;
4455 pname1 = strrchr_m(name1,'/');
4456 pname2 = strrchr_m(name2,'/');
4458 if (!pname1 || !pname2)
4461 pstrcpy(root1,pname1);
4462 pstrcpy(root2,pname2);
4463 p = strrchr_m(root1,'.');
4470 p = strrchr_m(root2,'.');
4484 } else if (*p2 == '*') {
4500 } else if (*p2 == '*') {
4510 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4513 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4514 if (actual_space >= available_space - 1) {
4515 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4516 actual_space - available_space));
4519 pstrcpy_base(pname2, root2, name2);
4525 /****************************************************************************
4526 Ensure open files have their names updated. Updated to notify other smbd's
4528 ****************************************************************************/
4530 static void rename_open_files(connection_struct *conn,
4531 struct share_mode_lock *lck,
4532 const char *newname)
4535 BOOL did_rename = False;
4537 for(fsp = file_find_di_first(lck->id); fsp;
4538 fsp = file_find_di_next(fsp)) {
4539 /* fsp_name is a relative path under the fsp. To change this for other
4540 sharepaths we need to manipulate relative paths. */
4541 /* TODO - create the absolute path and manipulate the newname
4542 relative to the sharepath. */
4543 if (fsp->conn != conn) {
4546 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4547 fsp->fnum, file_id_static_string(&fsp->file_id),
4548 fsp->fsp_name, newname ));
4549 string_set(&fsp->fsp_name, newname);
4554 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4555 file_id_static_string(&lck->id), newname ));
4558 /* Send messages to all smbd's (not ourself) that the name has changed. */
4559 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4563 /****************************************************************************
4564 We need to check if the source path is a parent directory of the destination
4565 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4566 refuse the rename with a sharing violation. Under UNIX the above call can
4567 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4568 probably need to check that the client is a Windows one before disallowing
4569 this as a UNIX client (one with UNIX extensions) can know the source is a
4570 symlink and make this decision intelligently. Found by an excellent bug
4571 report from <AndyLiebman@aol.com>.
4572 ****************************************************************************/
4574 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4576 const char *psrc = src;
4577 const char *pdst = dest;
4580 if (psrc[0] == '.' && psrc[1] == '/') {
4583 if (pdst[0] == '.' && pdst[1] == '/') {
4586 if ((slen = strlen(psrc)) > strlen(pdst)) {
4589 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4593 * Do the notify calls from a rename
4596 static void notify_rename(connection_struct *conn, BOOL is_dir,
4597 const char *oldpath, const char *newpath)
4599 char *olddir, *newdir;
4600 const char *oldname, *newname;
4603 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4604 : FILE_NOTIFY_CHANGE_FILE_NAME;
4606 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4607 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4608 TALLOC_FREE(olddir);
4612 if (strcmp(olddir, newdir) == 0) {
4613 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4614 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4617 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4618 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4620 TALLOC_FREE(olddir);
4621 TALLOC_FREE(newdir);
4623 /* this is a strange one. w2k3 gives an additional event for
4624 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4625 files, but not directories */
4627 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4628 FILE_NOTIFY_CHANGE_ATTRIBUTES
4629 |FILE_NOTIFY_CHANGE_CREATION,
4634 /****************************************************************************
4635 Rename an open file - given an fsp.
4636 ****************************************************************************/
4638 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4640 SMB_STRUCT_STAT sbuf, sbuf1;
4641 pstring newname_last_component;
4642 NTSTATUS status = NT_STATUS_OK;
4643 struct share_mode_lock *lck = NULL;
4648 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4650 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4652 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4656 status = check_name(conn, newname);
4657 if (!NT_STATUS_IS_OK(status)) {
4661 /* Ensure newname contains a '/' */
4662 if(strrchr_m(newname,'/') == 0) {
4665 pstrcpy(tmpstr, "./");
4666 pstrcat(tmpstr, newname);
4667 pstrcpy(newname, tmpstr);
4671 * Check for special case with case preserving and not
4672 * case sensitive. If the old last component differs from the original
4673 * last component only by case, then we should allow
4674 * the rename (user is trying to change the case of the
4678 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4679 strequal(newname, fsp->fsp_name)) {
4681 pstring newname_modified_last_component;
4684 * Get the last component of the modified name.
4685 * Note that we guarantee that newname contains a '/'
4688 p = strrchr_m(newname,'/');
4689 pstrcpy(newname_modified_last_component,p+1);
4691 if(strcsequal(newname_modified_last_component,
4692 newname_last_component) == False) {
4694 * Replace the modified last component with
4697 pstrcpy(p+1, newname_last_component);
4702 * If the src and dest names are identical - including case,
4703 * don't do the rename, just return success.
4706 if (strcsequal(fsp->fsp_name, newname)) {
4707 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4709 return NT_STATUS_OK;
4713 * Have vfs_object_exist also fill sbuf1
4715 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4717 if(!replace_if_exists && dst_exists) {
4718 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4719 fsp->fsp_name,newname));
4720 return NT_STATUS_OBJECT_NAME_COLLISION;
4724 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
4725 files_struct *dst_fsp = file_find_di_first(fileid);
4727 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4728 return NT_STATUS_ACCESS_DENIED;
4732 /* Ensure we have a valid stat struct for the source. */
4733 if (fsp->fh->fd != -1) {
4734 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4735 return map_nt_error_from_unix(errno);
4738 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4739 return map_nt_error_from_unix(errno);
4743 status = can_rename(conn, fsp, attrs, &sbuf);
4745 if (!NT_STATUS_IS_OK(status)) {
4746 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4747 nt_errstr(status), fsp->fsp_name,newname));
4748 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4749 status = NT_STATUS_ACCESS_DENIED;
4753 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4754 return NT_STATUS_ACCESS_DENIED;
4757 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4760 * We have the file open ourselves, so not being able to get the
4761 * corresponding share mode lock is a fatal error.
4764 SMB_ASSERT(lck != NULL);
4766 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4767 uint32 create_options = fsp->fh->private_options;
4769 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4770 fsp->fsp_name,newname));
4772 rename_open_files(conn, lck, newname);
4774 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4777 * A rename acts as a new file create w.r.t. allowing an initial delete
4778 * on close, probably because in Windows there is a new handle to the
4779 * new file. If initial delete on close was requested but not
4780 * originally set, we need to set it here. This is probably not 100% correct,
4781 * but will work for the CIFSFS client which in non-posix mode
4782 * depends on these semantics. JRA.
4785 set_allow_initial_delete_on_close(lck, fsp, True);
4787 if (create_options & FILE_DELETE_ON_CLOSE) {
4788 status = can_set_delete_on_close(fsp, True, 0);
4790 if (NT_STATUS_IS_OK(status)) {
4791 /* Note that here we set the *inital* delete on close flag,
4792 * not the regular one. The magic gets handled in close. */
4793 fsp->initial_delete_on_close = True;
4797 return NT_STATUS_OK;
4802 if (errno == ENOTDIR || errno == EISDIR) {
4803 status = NT_STATUS_OBJECT_NAME_COLLISION;
4805 status = map_nt_error_from_unix(errno);
4808 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4809 nt_errstr(status), fsp->fsp_name,newname));
4814 /****************************************************************************
4815 The guts of the rename command, split out so it may be called by the NT SMB
4817 ****************************************************************************/
4819 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
4823 BOOL replace_if_exists,
4829 pstring last_component_src;
4830 pstring last_component_dest;
4833 NTSTATUS status = NT_STATUS_OK;
4834 SMB_STRUCT_STAT sbuf1, sbuf2;
4835 struct smb_Dir *dir_hnd = NULL;
4840 *directory = *mask = 0;
4845 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4846 if (!NT_STATUS_IS_OK(status)) {
4850 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4851 if (!NT_STATUS_IS_OK(status)) {
4856 * Split the old name into directory and last component
4857 * strings. Note that unix_convert may have stripped off a
4858 * leading ./ from both name and newname if the rename is
4859 * at the root of the share. We need to make sure either both
4860 * name and newname contain a / character or neither of them do
4861 * as this is checked in resolve_wildcards().
4864 p = strrchr_m(name,'/');
4866 pstrcpy(directory,".");
4870 pstrcpy(directory,name);
4872 *p = '/'; /* Replace needed for exceptional test below. */
4876 * We should only check the mangled cache
4877 * here if unix_convert failed. This means
4878 * that the path in 'mask' doesn't exist
4879 * on the file system and so we need to look
4880 * for a possible mangle. This patch from
4881 * Tine Smukavec <valentin.smukavec@hermes.si>.
4884 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4885 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4888 if (!src_has_wild) {
4892 * No wildcards - just process the one file.
4894 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4896 /* Add a terminating '/' to the directory name. */
4897 pstrcat(directory,"/");
4898 pstrcat(directory,mask);
4900 /* Ensure newname contains a '/' also */
4901 if(strrchr_m(newname,'/') == 0) {
4904 pstrcpy(tmpstr, "./");
4905 pstrcat(tmpstr, newname);
4906 pstrcpy(newname, tmpstr);
4909 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4910 "case_preserve = %d, short case preserve = %d, "
4911 "directory = %s, newname = %s, "
4912 "last_component_dest = %s, is_8_3 = %d\n",
4913 conn->case_sensitive, conn->case_preserve,
4914 conn->short_case_preserve, directory,
4915 newname, last_component_dest, is_short_name));
4917 /* The dest name still may have wildcards. */
4918 if (dest_has_wild) {
4919 if (!resolve_wildcards(directory,newname)) {
4920 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4921 directory,newname));
4922 return NT_STATUS_NO_MEMORY;
4927 SMB_VFS_STAT(conn, directory, &sbuf1);
4929 status = S_ISDIR(sbuf1.st_mode) ?
4930 open_directory(conn, req, directory, &sbuf1,
4932 FILE_SHARE_READ|FILE_SHARE_WRITE,
4933 FILE_OPEN, 0, 0, NULL,
4935 : open_file_ntcreate(conn, req, directory, &sbuf1,
4937 FILE_SHARE_READ|FILE_SHARE_WRITE,
4938 FILE_OPEN, 0, 0, 0, NULL,
4941 if (!NT_STATUS_IS_OK(status)) {
4942 DEBUG(3, ("Could not open rename source %s: %s\n",
4943 directory, nt_errstr(status)));
4947 status = rename_internals_fsp(conn, fsp, newname, attrs,
4950 close_file(fsp, NORMAL_CLOSE);
4952 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4953 nt_errstr(status), directory,newname));
4959 * Wildcards - process each file that matches.
4961 if (strequal(mask,"????????.???")) {
4965 status = check_name(conn, directory);
4966 if (!NT_STATUS_IS_OK(status)) {
4970 dir_hnd = OpenDir(conn, directory, mask, attrs);
4971 if (dir_hnd == NULL) {
4972 return map_nt_error_from_unix(errno);
4975 status = NT_STATUS_NO_SUCH_FILE;
4977 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4978 * - gentest fix. JRA
4981 while ((dname = ReadDirName(dir_hnd, &offset))) {
4984 BOOL sysdir_entry = False;
4986 pstrcpy(fname,dname);
4988 /* Quick check for "." and ".." */
4989 if (fname[0] == '.') {
4990 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4992 sysdir_entry = True;
4999 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5003 if(!mask_match(fname, mask, conn->case_sensitive)) {
5008 status = NT_STATUS_OBJECT_NAME_INVALID;
5012 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
5014 pstrcpy(destname,newname);
5016 if (!resolve_wildcards(fname,destname)) {
5017 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5023 SMB_VFS_STAT(conn, fname, &sbuf1);
5025 status = S_ISDIR(sbuf1.st_mode) ?
5026 open_directory(conn, req, fname, &sbuf1,
5028 FILE_SHARE_READ|FILE_SHARE_WRITE,
5029 FILE_OPEN, 0, 0, NULL,
5031 : open_file_ntcreate(conn, req, fname, &sbuf1,
5033 FILE_SHARE_READ|FILE_SHARE_WRITE,
5034 FILE_OPEN, 0, 0, 0, NULL,
5037 if (!NT_STATUS_IS_OK(status)) {
5038 DEBUG(3,("rename_internals: open_file_ntcreate "
5039 "returned %s rename %s -> %s\n",
5040 nt_errstr(status), directory, newname));
5044 status = rename_internals_fsp(conn, fsp, destname, attrs,
5047 close_file(fsp, NORMAL_CLOSE);
5049 if (!NT_STATUS_IS_OK(status)) {
5050 DEBUG(3, ("rename_internals_fsp returned %s for "
5051 "rename %s -> %s\n", nt_errstr(status),
5052 directory, newname));
5058 DEBUG(3,("rename_internals: doing rename on %s -> "
5059 "%s\n",fname,destname));
5063 if (count == 0 && NT_STATUS_IS_OK(status)) {
5064 status = map_nt_error_from_unix(errno);
5070 /****************************************************************************
5072 ****************************************************************************/
5074 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
5081 uint32 attrs = SVAL(inbuf,smb_vwv0);
5083 BOOL src_has_wcard = False;
5084 BOOL dest_has_wcard = False;
5085 struct smb_request req;
5087 START_PROFILE(SMBmv);
5089 init_smb_request(&req, (uint8 *)inbuf);
5091 p = smb_buf(inbuf) + 1;
5092 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5093 sizeof(name), 0, STR_TERMINATE, &status,
5095 if (!NT_STATUS_IS_OK(status)) {
5097 return ERROR_NT(status);
5100 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5101 sizeof(newname), 0, STR_TERMINATE, &status,
5103 if (!NT_STATUS_IS_OK(status)) {
5105 return ERROR_NT(status);
5108 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
5109 if (!NT_STATUS_IS_OK(status)) {
5111 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5112 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5114 return ERROR_NT(status);
5117 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
5118 if (!NT_STATUS_IS_OK(status)) {
5120 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5121 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5123 return ERROR_NT(status);
5126 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5128 status = rename_internals(conn, &req, name, newname, attrs, False,
5129 src_has_wcard, dest_has_wcard);
5130 if (!NT_STATUS_IS_OK(status)) {
5132 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5133 /* We have re-scheduled this call. */
5136 return ERROR_NT(status);
5139 outsize = set_message(inbuf,outbuf,0,0,False);
5145 /*******************************************************************
5146 Copy a file as part of a reply_copy.
5147 ******************************************************************/
5150 * TODO: check error codes on all callers
5153 NTSTATUS copy_file(connection_struct *conn,
5158 BOOL target_is_directory)
5160 SMB_STRUCT_STAT src_sbuf, sbuf2;
5162 files_struct *fsp1,*fsp2;
5165 uint32 new_create_disposition;
5168 pstrcpy(dest,dest1);
5169 if (target_is_directory) {
5170 char *p = strrchr_m(src,'/');
5180 if (!vfs_file_exist(conn,src,&src_sbuf)) {
5181 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5184 if (!target_is_directory && count) {
5185 new_create_disposition = FILE_OPEN;
5187 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5188 NULL, NULL, &new_create_disposition, NULL)) {
5189 return NT_STATUS_INVALID_PARAMETER;
5193 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5195 FILE_SHARE_READ|FILE_SHARE_WRITE,
5198 FILE_ATTRIBUTE_NORMAL,
5202 if (!NT_STATUS_IS_OK(status)) {
5206 dosattrs = dos_mode(conn, src, &src_sbuf);
5207 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
5208 ZERO_STRUCTP(&sbuf2);
5211 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
5213 FILE_SHARE_READ|FILE_SHARE_WRITE,
5214 new_create_disposition,
5220 if (!NT_STATUS_IS_OK(status)) {
5221 close_file(fsp1,ERROR_CLOSE);
5225 if ((ofun&3) == 1) {
5226 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
5227 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
5229 * Stop the copy from occurring.
5232 src_sbuf.st_size = 0;
5236 if (src_sbuf.st_size) {
5237 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
5240 close_file(fsp1,NORMAL_CLOSE);
5242 /* Ensure the modtime is set correctly on the destination file. */
5243 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
5246 * As we are opening fsp1 read-only we only expect
5247 * an error on close on fsp2 if we are out of space.
5248 * Thus we don't look at the error return from the
5251 status = close_file(fsp2,NORMAL_CLOSE);
5253 if (!NT_STATUS_IS_OK(status)) {
5257 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
5258 return NT_STATUS_DISK_FULL;
5261 return NT_STATUS_OK;
5264 /****************************************************************************
5265 Reply to a file copy.
5266 ****************************************************************************/
5268 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5273 pstring mask,newname;
5276 int error = ERRnoaccess;
5278 int tid2 = SVAL(inbuf,smb_vwv0);
5279 int ofun = SVAL(inbuf,smb_vwv1);
5280 int flags = SVAL(inbuf,smb_vwv2);
5281 BOOL target_is_directory=False;
5282 BOOL source_has_wild = False;
5283 BOOL dest_has_wild = False;
5284 SMB_STRUCT_STAT sbuf1, sbuf2;
5286 START_PROFILE(SMBcopy);
5288 *directory = *mask = 0;
5291 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
5292 sizeof(name), 0, STR_TERMINATE, &status,
5294 if (!NT_STATUS_IS_OK(status)) {
5295 END_PROFILE(SMBcopy);
5296 return ERROR_NT(status);
5298 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
5299 sizeof(newname), 0, STR_TERMINATE, &status,
5301 if (!NT_STATUS_IS_OK(status)) {
5302 END_PROFILE(SMBcopy);
5303 return ERROR_NT(status);
5306 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5308 if (tid2 != conn->cnum) {
5309 /* can't currently handle inter share copies XXXX */
5310 DEBUG(3,("Rejecting inter-share copy\n"));
5311 END_PROFILE(SMBcopy);
5312 return ERROR_DOS(ERRSRV,ERRinvdevice);
5315 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5316 if (!NT_STATUS_IS_OK(status)) {
5317 END_PROFILE(SMBcopy);
5318 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5319 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5321 return ERROR_NT(status);
5324 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5325 if (!NT_STATUS_IS_OK(status)) {
5326 END_PROFILE(SMBcopy);
5327 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5328 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5330 return ERROR_NT(status);
5333 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5334 if (!NT_STATUS_IS_OK(status)) {
5335 END_PROFILE(SMBcopy);
5336 return ERROR_NT(status);
5339 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5340 if (!NT_STATUS_IS_OK(status)) {
5341 END_PROFILE(SMBcopy);
5342 return ERROR_NT(status);
5345 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5347 if ((flags&1) && target_is_directory) {
5348 END_PROFILE(SMBcopy);
5349 return ERROR_DOS(ERRDOS,ERRbadfile);
5352 if ((flags&2) && !target_is_directory) {
5353 END_PROFILE(SMBcopy);
5354 return ERROR_DOS(ERRDOS,ERRbadpath);
5357 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5358 /* wants a tree copy! XXXX */
5359 DEBUG(3,("Rejecting tree copy\n"));
5360 END_PROFILE(SMBcopy);
5361 return ERROR_DOS(ERRSRV,ERRerror);
5364 p = strrchr_m(name,'/');
5366 pstrcpy(directory,"./");
5370 pstrcpy(directory,name);
5375 * We should only check the mangled cache
5376 * here if unix_convert failed. This means
5377 * that the path in 'mask' doesn't exist
5378 * on the file system and so we need to look
5379 * for a possible mangle. This patch from
5380 * Tine Smukavec <valentin.smukavec@hermes.si>.
5383 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5384 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5387 if (!source_has_wild) {
5388 pstrcat(directory,"/");
5389 pstrcat(directory,mask);
5390 if (dest_has_wild) {
5391 if (!resolve_wildcards(directory,newname)) {
5392 END_PROFILE(SMBcopy);
5393 return ERROR_NT(NT_STATUS_NO_MEMORY);
5397 status = check_name(conn, directory);
5398 if (!NT_STATUS_IS_OK(status)) {
5399 return ERROR_NT(status);
5402 status = check_name(conn, newname);
5403 if (!NT_STATUS_IS_OK(status)) {
5404 return ERROR_NT(status);
5407 status = copy_file(conn,directory,newname,ofun,
5408 count,target_is_directory);
5410 if(!NT_STATUS_IS_OK(status)) {
5411 END_PROFILE(SMBcopy);
5412 return ERROR_NT(status);
5417 struct smb_Dir *dir_hnd = NULL;
5422 if (strequal(mask,"????????.???"))
5425 status = check_name(conn, directory);
5426 if (!NT_STATUS_IS_OK(status)) {
5427 return ERROR_NT(status);
5430 dir_hnd = OpenDir(conn, directory, mask, 0);
5431 if (dir_hnd == NULL) {
5432 status = map_nt_error_from_unix(errno);
5433 return ERROR_NT(status);
5438 while ((dname = ReadDirName(dir_hnd, &offset))) {
5440 pstrcpy(fname,dname);
5442 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5446 if(!mask_match(fname, mask, conn->case_sensitive)) {
5450 error = ERRnoaccess;
5451 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5452 pstrcpy(destname,newname);
5453 if (!resolve_wildcards(fname,destname)) {
5457 status = check_name(conn, fname);
5458 if (!NT_STATUS_IS_OK(status)) {
5459 return ERROR_NT(status);
5462 status = check_name(conn, destname);
5463 if (!NT_STATUS_IS_OK(status)) {
5464 return ERROR_NT(status);
5467 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5469 status = copy_file(conn,fname,destname,ofun,
5470 count,target_is_directory);
5471 if (NT_STATUS_IS_OK(status)) {
5480 /* Error on close... */
5482 END_PROFILE(SMBcopy);
5483 return(UNIXERROR(ERRHRD,ERRgeneral));
5486 END_PROFILE(SMBcopy);
5487 return ERROR_DOS(ERRDOS,error);
5490 outsize = set_message(inbuf,outbuf,1,0,True);
5491 SSVAL(outbuf,smb_vwv0,count);
5493 END_PROFILE(SMBcopy);
5497 /****************************************************************************
5499 ****************************************************************************/
5501 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5508 START_PROFILE(pathworks_setdir);
5511 if (!CAN_SETDIR(snum)) {
5512 END_PROFILE(pathworks_setdir);
5513 return ERROR_DOS(ERRDOS,ERRnoaccess);
5516 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
5517 smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
5519 if (!NT_STATUS_IS_OK(status)) {
5520 END_PROFILE(pathworks_setdir);
5521 return ERROR_NT(status);
5524 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5525 if (!NT_STATUS_IS_OK(status)) {
5526 END_PROFILE(pathworks_setdir);
5527 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5528 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5530 return ERROR_NT(status);
5533 if (strlen(newdir) != 0) {
5534 if (!vfs_directory_exist(conn,newdir,NULL)) {
5535 END_PROFILE(pathworks_setdir);
5536 return ERROR_DOS(ERRDOS,ERRbadpath);
5538 set_conn_connectpath(conn,newdir);
5541 outsize = set_message(inbuf,outbuf,0,0,False);
5542 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5544 DEBUG(3,("setdir %s\n", newdir));
5546 END_PROFILE(pathworks_setdir);
5551 #define DBGC_CLASS DBGC_LOCKING
5553 /****************************************************************************
5554 Get a lock pid, dealing with large count requests.
5555 ****************************************************************************/
5557 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5559 if(!large_file_format)
5560 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5562 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5565 /****************************************************************************
5566 Get a lock count, dealing with large count requests.
5567 ****************************************************************************/
5569 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5571 SMB_BIG_UINT count = 0;
5573 if(!large_file_format) {
5574 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5577 #if defined(HAVE_LONGLONG)
5578 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5579 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5580 #else /* HAVE_LONGLONG */
5583 * NT4.x seems to be broken in that it sends large file (64 bit)
5584 * lockingX calls even if the CAP_LARGE_FILES was *not*
5585 * negotiated. For boxes without large unsigned ints truncate the
5586 * lock count by dropping the top 32 bits.
5589 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5590 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5591 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5592 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5593 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5596 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5597 #endif /* HAVE_LONGLONG */
5603 #if !defined(HAVE_LONGLONG)
5604 /****************************************************************************
5605 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5606 ****************************************************************************/
5608 static uint32 map_lock_offset(uint32 high, uint32 low)
5612 uint32 highcopy = high;
5615 * Try and find out how many significant bits there are in high.
5618 for(i = 0; highcopy; i++)
5622 * We use 31 bits not 32 here as POSIX
5623 * lock offsets may not be negative.
5626 mask = (~0) << (31 - i);
5629 return 0; /* Fail. */
5635 #endif /* !defined(HAVE_LONGLONG) */
5637 /****************************************************************************
5638 Get a lock offset, dealing with large offset requests.
5639 ****************************************************************************/
5641 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5643 SMB_BIG_UINT offset = 0;
5647 if(!large_file_format) {
5648 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5651 #if defined(HAVE_LONGLONG)
5652 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5653 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5654 #else /* HAVE_LONGLONG */
5657 * NT4.x seems to be broken in that it sends large file (64 bit)
5658 * lockingX calls even if the CAP_LARGE_FILES was *not*
5659 * negotiated. For boxes without large unsigned ints mangle the
5660 * lock offset by mapping the top 32 bits onto the lower 32.
5663 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5664 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5665 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5668 if((new_low = map_lock_offset(high, low)) == 0) {
5670 return (SMB_BIG_UINT)-1;
5673 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5674 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5675 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5676 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5679 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5680 #endif /* HAVE_LONGLONG */
5686 /****************************************************************************
5687 Reply to a lockingX request.
5688 ****************************************************************************/
5690 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5691 int length, int bufsize)
5693 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv2));
5694 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5695 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5696 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5697 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5698 SMB_BIG_UINT count = 0, offset = 0;
5700 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5703 BOOL large_file_format =
5704 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5706 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5708 START_PROFILE(SMBlockingX);
5710 CHECK_FSP(fsp,conn);
5712 data = smb_buf(inbuf);
5714 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5715 /* we don't support these - and CANCEL_LOCK makes w2k
5716 and XP reboot so I don't really want to be
5717 compatible! (tridge) */
5718 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5721 /* Check if this is an oplock break on a file
5722 we have granted an oplock on.
5724 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5725 /* Client can insist on breaking to none. */
5726 BOOL break_to_none = (oplocklevel == 0);
5729 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5730 "for fnum = %d\n", (unsigned int)oplocklevel,
5734 * Make sure we have granted an exclusive or batch oplock on
5738 if (fsp->oplock_type == 0) {
5740 /* The Samba4 nbench simulator doesn't understand
5741 the difference between break to level2 and break
5742 to none from level2 - it sends oplock break
5743 replies in both cases. Don't keep logging an error
5744 message here - just ignore it. JRA. */
5746 DEBUG(5,("reply_lockingX: Error : oplock break from "
5747 "client for fnum = %d (oplock=%d) and no "
5748 "oplock granted on this file (%s).\n",
5749 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5751 /* if this is a pure oplock break request then don't
5753 if (num_locks == 0 && num_ulocks == 0) {
5754 END_PROFILE(SMBlockingX);
5757 END_PROFILE(SMBlockingX);
5758 return ERROR_DOS(ERRDOS,ERRlock);
5762 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5764 result = remove_oplock(fsp);
5766 result = downgrade_oplock(fsp);
5770 DEBUG(0, ("reply_lockingX: error in removing "
5771 "oplock on file %s\n", fsp->fsp_name));
5772 /* Hmmm. Is this panic justified? */
5773 smb_panic("internal tdb error");
5776 reply_to_oplock_break_requests(fsp);
5778 /* if this is a pure oplock break request then don't send a
5780 if (num_locks == 0 && num_ulocks == 0) {
5781 /* Sanity check - ensure a pure oplock break is not a
5783 if(CVAL(inbuf,smb_vwv0) != 0xff)
5784 DEBUG(0,("reply_lockingX: Error : pure oplock "
5785 "break is a chained %d request !\n",
5786 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5787 END_PROFILE(SMBlockingX);
5793 * We do this check *after* we have checked this is not a oplock break
5794 * response message. JRA.
5797 release_level_2_oplocks_on_change(fsp);
5799 /* Data now points at the beginning of the list
5800 of smb_unlkrng structs */
5801 for(i = 0; i < (int)num_ulocks; i++) {
5802 lock_pid = get_lock_pid( data, i, large_file_format);
5803 count = get_lock_count( data, i, large_file_format);
5804 offset = get_lock_offset( data, i, large_file_format, &err);
5807 * There is no error code marked "stupid client bug".... :-).
5810 END_PROFILE(SMBlockingX);
5811 return ERROR_DOS(ERRDOS,ERRnoaccess);
5814 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5815 "pid %u, file %s\n", (double)offset, (double)count,
5816 (unsigned int)lock_pid, fsp->fsp_name ));
5818 status = do_unlock(smbd_messaging_context(),
5825 if (NT_STATUS_V(status)) {
5826 END_PROFILE(SMBlockingX);
5827 return ERROR_NT(status);
5831 /* Setup the timeout in seconds. */
5833 if (!lp_blocking_locks(SNUM(conn))) {
5837 /* Now do any requested locks */
5838 data += ((large_file_format ? 20 : 10)*num_ulocks);
5840 /* Data now points at the beginning of the list
5841 of smb_lkrng structs */
5843 for(i = 0; i < (int)num_locks; i++) {
5844 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5845 READ_LOCK:WRITE_LOCK);
5846 lock_pid = get_lock_pid( data, i, large_file_format);
5847 count = get_lock_count( data, i, large_file_format);
5848 offset = get_lock_offset( data, i, large_file_format, &err);
5851 * There is no error code marked "stupid client bug".... :-).
5854 END_PROFILE(SMBlockingX);
5855 return ERROR_DOS(ERRDOS,ERRnoaccess);
5858 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5859 "%u, file %s timeout = %d\n", (double)offset,
5860 (double)count, (unsigned int)lock_pid,
5861 fsp->fsp_name, (int)lock_timeout ));
5863 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5864 if (lp_blocking_locks(SNUM(conn))) {
5866 /* Schedule a message to ourselves to
5867 remove the blocking lock record and
5868 return the right error. */
5870 if (!blocking_lock_cancel(fsp,
5876 NT_STATUS_FILE_LOCK_CONFLICT)) {
5877 END_PROFILE(SMBlockingX);
5878 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5881 /* Remove a matching pending lock. */
5882 status = do_lock_cancel(fsp,
5888 BOOL blocking_lock = lock_timeout ? True : False;
5889 BOOL defer_lock = False;
5890 struct byte_range_lock *br_lck;
5891 uint32 block_smbpid;
5893 br_lck = do_lock(smbd_messaging_context(),
5904 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5905 /* Windows internal resolution for blocking locks seems
5906 to be about 200ms... Don't wait for less than that. JRA. */
5907 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5908 lock_timeout = lp_lock_spin_time();
5913 /* This heuristic seems to match W2K3 very well. If a
5914 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5915 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5916 far as I can tell. Replacement for do_lock_spin(). JRA. */
5918 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5919 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5921 lock_timeout = lp_lock_spin_time();
5924 if (br_lck && defer_lock) {
5926 * A blocking lock was requested. Package up
5927 * this smb into a queued request and push it
5928 * onto the blocking lock queue.
5930 if(push_blocking_lock_request(br_lck,
5941 TALLOC_FREE(br_lck);
5942 END_PROFILE(SMBlockingX);
5947 TALLOC_FREE(br_lck);
5950 if (NT_STATUS_V(status)) {
5951 END_PROFILE(SMBlockingX);
5952 return ERROR_NT(status);
5956 /* If any of the above locks failed, then we must unlock
5957 all of the previous locks (X/Open spec). */
5959 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5963 * Ensure we don't do a remove on the lock that just failed,
5964 * as under POSIX rules, if we have a lock already there, we
5965 * will delete it (and we shouldn't) .....
5967 for(i--; i >= 0; i--) {
5968 lock_pid = get_lock_pid( data, i, large_file_format);
5969 count = get_lock_count( data, i, large_file_format);
5970 offset = get_lock_offset( data, i, large_file_format,
5974 * There is no error code marked "stupid client
5978 END_PROFILE(SMBlockingX);
5979 return ERROR_DOS(ERRDOS,ERRnoaccess);
5982 do_unlock(smbd_messaging_context(),
5989 END_PROFILE(SMBlockingX);
5990 return ERROR_NT(status);
5993 set_message(inbuf,outbuf,2,0,True);
5995 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5996 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5998 END_PROFILE(SMBlockingX);
5999 return chain_reply(inbuf,&outbuf,length,bufsize);
6003 #define DBGC_CLASS DBGC_ALL
6005 /****************************************************************************
6006 Reply to a SMBreadbmpx (read block multiplex) request.
6007 ****************************************************************************/
6009 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
6020 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6021 START_PROFILE(SMBreadBmpx);
6023 /* this function doesn't seem to work - disable by default */
6024 if (!lp_readbmpx()) {
6025 END_PROFILE(SMBreadBmpx);
6026 return ERROR_DOS(ERRSRV,ERRuseSTD);
6029 outsize = set_message(inbuf,outbuf,8,0,True);
6031 CHECK_FSP(fsp,conn);
6032 if (!CHECK_READ(fsp,inbuf)) {
6033 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6036 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
6037 maxcount = SVAL(inbuf,smb_vwv3);
6039 data = smb_buf(outbuf);
6040 pad = ((long)data)%4;
6045 max_per_packet = bufsize-(outsize+pad);
6049 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
6050 END_PROFILE(SMBreadBmpx);
6051 return ERROR_DOS(ERRDOS,ERRlock);
6055 size_t N = MIN(max_per_packet,tcount-total_read);
6057 nread = read_file(fsp,data,startpos,N);
6062 if (nread < (ssize_t)N)
6063 tcount = total_read + nread;
6065 set_message(inbuf,outbuf,8,nread+pad,False);
6066 SIVAL(outbuf,smb_vwv0,startpos);
6067 SSVAL(outbuf,smb_vwv2,tcount);
6068 SSVAL(outbuf,smb_vwv6,nread);
6069 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
6072 if (!send_smb(smbd_server_fd(),outbuf))
6073 exit_server_cleanly("reply_readbmpx: send_smb failed.");
6075 total_read += nread;
6077 } while (total_read < (ssize_t)tcount);
6079 END_PROFILE(SMBreadBmpx);
6083 /****************************************************************************
6084 Reply to a SMBsetattrE.
6085 ****************************************************************************/
6087 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6089 struct timespec ts[2];
6091 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6092 START_PROFILE(SMBsetattrE);
6094 outsize = set_message(inbuf,outbuf,0,0,False);
6096 if(!fsp || (fsp->conn != conn)) {
6097 END_PROFILE(SMBsetattrE);
6098 return ERROR_DOS(ERRDOS,ERRbadfid);
6102 * Convert the DOS times into unix times. Ignore create
6103 * time as UNIX can't set this.
6106 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
6107 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
6110 * Patch from Ray Frush <frush@engr.colostate.edu>
6111 * Sometimes times are sent as zero - ignore them.
6114 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
6115 /* Ignore request */
6116 if( DEBUGLVL( 3 ) ) {
6117 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
6118 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
6120 END_PROFILE(SMBsetattrE);
6122 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
6123 /* set modify time = to access time if modify time was unset */
6127 /* Set the date on this file */
6128 /* Should we set pending modtime here ? JRA */
6129 if(file_ntimes(conn, fsp->fsp_name, ts)) {
6130 END_PROFILE(SMBsetattrE);
6131 return ERROR_DOS(ERRDOS,ERRnoaccess);
6134 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
6136 (unsigned int)ts[0].tv_sec,
6137 (unsigned int)ts[1].tv_sec));
6139 END_PROFILE(SMBsetattrE);
6144 /* Back from the dead for OS/2..... JRA. */
6146 /****************************************************************************
6147 Reply to a SMBwritebmpx (write block multiplex primary) request.
6148 ****************************************************************************/
6150 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6153 ssize_t nwritten = -1;
6160 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6162 START_PROFILE(SMBwriteBmpx);
6164 CHECK_FSP(fsp,conn);
6165 if (!CHECK_WRITE(fsp)) {
6166 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6168 if (HAS_CACHED_ERROR(fsp)) {
6169 return(CACHED_ERROR(fsp));
6172 tcount = SVAL(inbuf,smb_vwv1);
6173 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
6174 write_through = BITSETW(inbuf+smb_vwv7,0);
6175 numtowrite = SVAL(inbuf,smb_vwv10);
6176 smb_doff = SVAL(inbuf,smb_vwv11);
6178 data = smb_base(inbuf) + smb_doff;
6180 /* If this fails we need to send an SMBwriteC response,
6181 not an SMBwritebmpx - set this up now so we don't forget */
6182 SCVAL(outbuf,smb_com,SMBwritec);
6184 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
6185 END_PROFILE(SMBwriteBmpx);
6186 return(ERROR_DOS(ERRDOS,ERRlock));
6189 nwritten = write_file(fsp,data,startpos,numtowrite);
6191 status = sync_file(conn, fsp, write_through);
6192 if (!NT_STATUS_IS_OK(status)) {
6193 END_PROFILE(SMBwriteBmpx);
6194 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
6195 fsp->fsp_name, nt_errstr(status) ));
6196 return ERROR_NT(status);
6199 if(nwritten < (ssize_t)numtowrite) {
6200 END_PROFILE(SMBwriteBmpx);
6201 return(UNIXERROR(ERRHRD,ERRdiskfull));
6204 /* If the maximum to be written to this file
6205 is greater than what we just wrote then set
6206 up a secondary struct to be attached to this
6207 fd, we will use this to cache error messages etc. */
6209 if((ssize_t)tcount > nwritten) {
6210 write_bmpx_struct *wbms;
6211 if(fsp->wbmpx_ptr != NULL)
6212 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
6214 wbms = SMB_MALLOC_P(write_bmpx_struct);
6216 DEBUG(0,("Out of memory in reply_readmpx\n"));
6217 END_PROFILE(SMBwriteBmpx);
6218 return(ERROR_DOS(ERRSRV,ERRnoresource));
6220 wbms->wr_mode = write_through;
6221 wbms->wr_discard = False; /* No errors yet */
6222 wbms->wr_total_written = nwritten;
6223 wbms->wr_errclass = 0;
6225 fsp->wbmpx_ptr = wbms;
6228 /* We are returning successfully, set the message type back to
6230 SCVAL(outbuf,smb_com,SMBwriteBmpx);
6232 outsize = set_message(inbuf,outbuf,1,0,True);
6234 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
6236 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
6237 fsp->fnum, (int)numtowrite, (int)nwritten ) );
6239 if (write_through && tcount==nwritten) {
6240 /* We need to send both a primary and a secondary response */
6241 smb_setlen(inbuf,outbuf,outsize - 4);
6243 if (!send_smb(smbd_server_fd(),outbuf))
6244 exit_server_cleanly("reply_writebmpx: send_smb failed.");
6246 /* Now the secondary */
6247 outsize = set_message(inbuf,outbuf,1,0,True);
6248 SCVAL(outbuf,smb_com,SMBwritec);
6249 SSVAL(outbuf,smb_vwv0,nwritten);
6252 END_PROFILE(SMBwriteBmpx);
6256 /****************************************************************************
6257 Reply to a SMBwritebs (write block multiplex secondary) request.
6258 ****************************************************************************/
6260 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
6263 ssize_t nwritten = -1;
6270 write_bmpx_struct *wbms;
6271 BOOL send_response = False;
6272 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6274 START_PROFILE(SMBwriteBs);
6276 CHECK_FSP(fsp,conn);
6277 if (!CHECK_WRITE(fsp)) {
6278 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6281 tcount = SVAL(inbuf,smb_vwv1);
6282 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6283 numtowrite = SVAL(inbuf,smb_vwv6);
6284 smb_doff = SVAL(inbuf,smb_vwv7);
6286 data = smb_base(inbuf) + smb_doff;
6288 /* We need to send an SMBwriteC response, not an SMBwritebs */
6289 SCVAL(outbuf,smb_com,SMBwritec);
6291 /* This fd should have an auxiliary struct attached,
6292 check that it does */
6293 wbms = fsp->wbmpx_ptr;
6295 END_PROFILE(SMBwriteBs);
6299 /* If write through is set we can return errors, else we must cache them */
6300 write_through = wbms->wr_mode;
6302 /* Check for an earlier error */
6303 if(wbms->wr_discard) {
6304 END_PROFILE(SMBwriteBs);
6305 return -1; /* Just discard the packet */
6308 nwritten = write_file(fsp,data,startpos,numtowrite);
6310 status = sync_file(conn, fsp, write_through);
6312 if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6314 /* We are returning an error - we can delete the aux struct */
6317 fsp->wbmpx_ptr = NULL;
6318 END_PROFILE(SMBwriteBs);
6319 return(ERROR_DOS(ERRHRD,ERRdiskfull));
6321 wbms->wr_errclass = ERRHRD;
6322 wbms->wr_error = ERRdiskfull;
6323 wbms->wr_status = NT_STATUS_DISK_FULL;
6324 wbms->wr_discard = True;
6325 END_PROFILE(SMBwriteBs);
6329 /* Increment the total written, if this matches tcount
6330 we can discard the auxiliary struct (hurrah !) and return a writeC */
6331 wbms->wr_total_written += nwritten;
6332 if(wbms->wr_total_written >= tcount) {
6333 if (write_through) {
6334 outsize = set_message(inbuf,outbuf,1,0,True);
6335 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
6336 send_response = True;
6340 fsp->wbmpx_ptr = NULL;
6344 END_PROFILE(SMBwriteBs);
6348 END_PROFILE(SMBwriteBs);
6352 /****************************************************************************
6353 Reply to a SMBgetattrE.
6354 ****************************************************************************/
6356 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6358 SMB_STRUCT_STAT sbuf;
6361 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6362 START_PROFILE(SMBgetattrE);
6364 outsize = set_message(inbuf,outbuf,11,0,True);
6366 if(!fsp || (fsp->conn != conn)) {
6367 END_PROFILE(SMBgetattrE);
6368 return ERROR_DOS(ERRDOS,ERRbadfid);
6371 /* Do an fstat on this file */
6372 if(fsp_stat(fsp, &sbuf)) {
6373 END_PROFILE(SMBgetattrE);
6374 return(UNIXERROR(ERRDOS,ERRnoaccess));
6377 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6380 * Convert the times into dos times. Set create
6381 * date to be last modify date as UNIX doesn't save
6385 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6386 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6387 /* Should we check pending modtime here ? JRA */
6388 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6391 SIVAL(outbuf,smb_vwv6,0);
6392 SIVAL(outbuf,smb_vwv8,0);
6394 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6395 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6396 SIVAL(outbuf,smb_vwv8,allocation_size);
6398 SSVAL(outbuf,smb_vwv10, mode);
6400 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6402 END_PROFILE(SMBgetattrE);