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(TALLOC_CTX *ctx,
219 bool *contains_wcard)
226 ret = srvstr_pull_buf_talloc(ctx,
233 ret = srvstr_pull_talloc(ctx,
243 *err = NT_STATUS_INVALID_PARAMETER;
247 *contains_wcard = False;
249 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
251 * For a DFS path the function parse_dfs_path()
252 * will do the path processing, just make a copy.
258 if (lp_posix_pathnames()) {
259 *err = check_path_syntax_posix(*pp_dest);
261 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
267 /****************************************************************************
268 Pull a string and check the path - provide for error return.
269 ****************************************************************************/
271 size_t srvstr_get_path(TALLOC_CTX *ctx,
285 ret = srvstr_pull_buf_talloc(ctx,
292 ret = srvstr_pull_talloc(ctx,
302 *err = NT_STATUS_INVALID_PARAMETER;
306 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
308 * For a DFS path the function parse_dfs_path()
309 * will do the path processing, just make a copy.
315 if (lp_posix_pathnames()) {
316 *err = check_path_syntax_posix(*pp_dest);
318 *err = check_path_syntax(*pp_dest);
324 /****************************************************************************
325 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
326 ****************************************************************************/
328 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
329 files_struct *fsp, struct current_user *user)
331 if (!(fsp) || !(conn)) {
332 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
335 if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) {
336 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
342 /****************************************************************************
343 Check if we have a correct fsp pointing to a file. Replacement for the
345 ****************************************************************************/
347 bool check_fsp(connection_struct *conn, struct smb_request *req,
348 files_struct *fsp, struct current_user *user)
350 if (!check_fsp_open(conn, req, fsp, user)) {
353 if ((fsp)->is_directory) {
354 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
357 if ((fsp)->fh->fd == -1) {
358 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
361 (fsp)->num_smb_operations++;
365 /****************************************************************************
366 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
367 ****************************************************************************/
369 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
370 files_struct *fsp, struct current_user *user)
372 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
373 && (current_user.vuid==(fsp)->vuid)) {
377 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
381 /****************************************************************************
382 Reply to a (netbios-level) special message.
383 ****************************************************************************/
385 void reply_special(char *inbuf)
387 int msg_type = CVAL(inbuf,0);
388 int msg_flags = CVAL(inbuf,1);
393 * We only really use 4 bytes of the outbuf, but for the smb_setlen
394 * calculation & friends (srv_send_smb uses that) we need the full smb
397 char outbuf[smb_size];
399 static bool already_got_session = False;
403 memset(outbuf, '\0', sizeof(outbuf));
405 smb_setlen(outbuf,0);
408 case 0x81: /* session request */
410 if (already_got_session) {
411 exit_server_cleanly("multiple session request not permitted");
414 SCVAL(outbuf,0,0x82);
416 if (name_len(inbuf+4) > 50 ||
417 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
418 DEBUG(0,("Invalid name length in session request\n"));
421 name_extract(inbuf,4,name1);
422 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
423 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
426 set_local_machine_name(name1, True);
427 set_remote_machine_name(name2, True);
429 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
430 get_local_machine_name(), get_remote_machine_name(),
433 if (name_type == 'R') {
434 /* We are being asked for a pathworks session ---
436 SCVAL(outbuf, 0,0x83);
440 /* only add the client's machine name to the list
441 of possibly valid usernames if we are operating
442 in share mode security */
443 if (lp_security() == SEC_SHARE) {
444 add_session_user(get_remote_machine_name());
447 reload_services(True);
450 already_got_session = True;
453 case 0x89: /* session keepalive request
454 (some old clients produce this?) */
455 SCVAL(outbuf,0,SMBkeepalive);
459 case 0x82: /* positive session response */
460 case 0x83: /* negative session response */
461 case 0x84: /* retarget session response */
462 DEBUG(0,("Unexpected session response\n"));
465 case SMBkeepalive: /* session keepalive */
470 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
471 msg_type, msg_flags));
473 srv_send_smb(smbd_server_fd(), outbuf, false);
477 /****************************************************************************
479 conn POINTER CAN BE NULL HERE !
480 ****************************************************************************/
482 void reply_tcon(connection_struct *conn, struct smb_request *req)
485 char *service_buf = NULL;
486 char *password = NULL;
491 DATA_BLOB password_blob;
492 TALLOC_CTX *ctx = talloc_tos();
494 START_PROFILE(SMBtcon);
496 if (smb_buflen(req->inbuf) < 4) {
497 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
498 END_PROFILE(SMBtcon);
502 p = smb_buf(req->inbuf)+1;
503 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
504 &service_buf, p, STR_TERMINATE) + 1;
505 pwlen = srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
506 &password, p, STR_TERMINATE) + 1;
508 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
509 &dev, p, STR_TERMINATE) + 1;
511 if (service_buf == NULL || password == NULL || dev == NULL) {
512 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
513 END_PROFILE(SMBtcon);
516 p = strrchr_m(service_buf,'\\');
520 service = service_buf;
523 password_blob = data_blob(password, pwlen+1);
525 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
528 data_blob_clear_free(&password_blob);
531 reply_nterror(req, nt_status);
532 END_PROFILE(SMBtcon);
536 reply_outbuf(req, 2, 0);
537 SSVAL(req->outbuf,smb_vwv0,max_recv);
538 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
539 SSVAL(req->outbuf,smb_tid,conn->cnum);
541 DEBUG(3,("tcon service=%s cnum=%d\n",
542 service, conn->cnum));
544 END_PROFILE(SMBtcon);
548 /****************************************************************************
549 Reply to a tcon and X.
550 conn POINTER CAN BE NULL HERE !
551 ****************************************************************************/
553 void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
555 char *service = NULL;
557 TALLOC_CTX *ctx = talloc_tos();
558 /* what the cleint thinks the device is */
559 char *client_devicetype = NULL;
560 /* what the server tells the client the share represents */
561 const char *server_devicetype;
568 START_PROFILE(SMBtconX);
571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
572 END_PROFILE(SMBtconX);
576 passlen = SVAL(req->inbuf,smb_vwv3);
577 tcon_flags = SVAL(req->inbuf,smb_vwv2);
579 /* we might have to close an old one */
580 if ((tcon_flags & 0x1) && conn) {
581 close_cnum(conn,req->vuid);
585 if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
586 reply_doserror(req, ERRDOS, ERRbuftoosmall);
587 END_PROFILE(SMBtconX);
591 if (global_encrypted_passwords_negotiated) {
592 password = data_blob(smb_buf(req->inbuf),passlen);
593 if (lp_security() == SEC_SHARE) {
595 * Security = share always has a pad byte
596 * after the password.
598 p = smb_buf(req->inbuf) + passlen + 1;
600 p = smb_buf(req->inbuf) + passlen;
603 password = data_blob(smb_buf(req->inbuf),passlen+1);
604 /* Ensure correct termination */
605 password.data[passlen]=0;
606 p = smb_buf(req->inbuf) + passlen + 1;
609 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
613 data_blob_clear_free(&password);
614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
615 END_PROFILE(SMBtconX);
620 * the service name can be either: \\server\share
621 * or share directly like on the DELL PowerVault 705
624 q = strchr_m(path+2,'\\');
626 data_blob_clear_free(&password);
627 reply_doserror(req, ERRDOS, ERRnosuchshare);
628 END_PROFILE(SMBtconX);
636 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
637 &client_devicetype, p,
638 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
640 if (client_devicetype == NULL) {
641 data_blob_clear_free(&password);
642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
643 END_PROFILE(SMBtconX);
647 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
649 conn = make_connection(service, password, client_devicetype,
650 req->vuid, &nt_status);
653 data_blob_clear_free(&password);
656 reply_nterror(req, nt_status);
657 END_PROFILE(SMBtconX);
662 server_devicetype = "IPC";
663 else if ( IS_PRINT(conn) )
664 server_devicetype = "LPT1:";
666 server_devicetype = "A:";
668 if (Protocol < PROTOCOL_NT1) {
669 reply_outbuf(req, 2, 0);
670 if (message_push_string(&req->outbuf, server_devicetype,
671 STR_TERMINATE|STR_ASCII) == -1) {
672 reply_nterror(req, NT_STATUS_NO_MEMORY);
673 END_PROFILE(SMBtconX);
677 /* NT sets the fstype of IPC$ to the null string */
678 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
680 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
681 /* Return permissions. */
685 reply_outbuf(req, 7, 0);
688 perm1 = FILE_ALL_ACCESS;
689 perm2 = FILE_ALL_ACCESS;
691 perm1 = CAN_WRITE(conn) ?
696 SIVAL(req->outbuf, smb_vwv3, perm1);
697 SIVAL(req->outbuf, smb_vwv5, perm2);
699 reply_outbuf(req, 3, 0);
702 if ((message_push_string(&req->outbuf, server_devicetype,
703 STR_TERMINATE|STR_ASCII) == -1)
704 || (message_push_string(&req->outbuf, fstype,
705 STR_TERMINATE) == -1)) {
706 reply_nterror(req, NT_STATUS_NO_MEMORY);
707 END_PROFILE(SMBtconX);
711 /* what does setting this bit do? It is set by NT4 and
712 may affect the ability to autorun mounted cdroms */
713 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
714 (lp_csc_policy(SNUM(conn)) << 2));
716 init_dfsroot(conn, req->inbuf, req->outbuf);
720 DEBUG(3,("tconX service=%s \n",
723 /* set the incoming and outgoing tid to the just created one */
724 SSVAL(req->inbuf,smb_tid,conn->cnum);
725 SSVAL(req->outbuf,smb_tid,conn->cnum);
727 END_PROFILE(SMBtconX);
733 /****************************************************************************
734 Reply to an unknown type.
735 ****************************************************************************/
737 int reply_unknown(char *inbuf,char *outbuf)
740 type = CVAL(inbuf,smb_com);
742 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
743 smb_fn_name(type), type, type));
745 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
748 void reply_unknown_new(struct smb_request *req, uint8 type)
750 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
751 smb_fn_name(type), type, type));
752 reply_doserror(req, ERRSRV, ERRunknownsmb);
756 /****************************************************************************
758 conn POINTER CAN BE NULL HERE !
759 ****************************************************************************/
761 void reply_ioctl(connection_struct *conn, struct smb_request *req)
769 START_PROFILE(SMBioctl);
772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
773 END_PROFILE(SMBioctl);
777 device = SVAL(req->inbuf,smb_vwv1);
778 function = SVAL(req->inbuf,smb_vwv2);
779 ioctl_code = (device << 16) + function;
781 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
783 switch (ioctl_code) {
784 case IOCTL_QUERY_JOB_INFO:
788 reply_doserror(req, ERRSRV, ERRnosupport);
789 END_PROFILE(SMBioctl);
793 reply_outbuf(req, 8, replysize+1);
794 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
795 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
796 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
797 p = smb_buf(req->outbuf);
798 memset(p, '\0', replysize+1); /* valgrind-safe. */
799 p += 1; /* Allow for alignment */
801 switch (ioctl_code) {
802 case IOCTL_QUERY_JOB_INFO:
804 files_struct *fsp = file_fsp(SVAL(req->inbuf,
807 reply_doserror(req, ERRDOS, ERRbadfid);
808 END_PROFILE(SMBioctl);
811 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
812 srvstr_push((char *)req->outbuf, req->flags2, p+2,
814 STR_TERMINATE|STR_ASCII);
816 srvstr_push((char *)req->outbuf, req->flags2,
817 p+18, lp_servicename(SNUM(conn)),
818 13, STR_TERMINATE|STR_ASCII);
826 END_PROFILE(SMBioctl);
830 /****************************************************************************
831 Strange checkpath NTSTATUS mapping.
832 ****************************************************************************/
834 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
836 /* Strange DOS error code semantics only for checkpath... */
837 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
838 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
839 /* We need to map to ERRbadpath */
840 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
846 /****************************************************************************
847 Reply to a checkpath.
848 ****************************************************************************/
850 void reply_checkpath(connection_struct *conn, struct smb_request *req)
853 SMB_STRUCT_STAT sbuf;
855 TALLOC_CTX *ctx = talloc_tos();
857 START_PROFILE(SMBcheckpath);
859 srvstr_get_path(ctx,(char *)req->inbuf, req->flags2, &name,
860 smb_buf(req->inbuf) + 1, 0,
861 STR_TERMINATE, &status);
862 if (!NT_STATUS_IS_OK(status)) {
863 status = map_checkpath_error((char *)req->inbuf, status);
864 reply_nterror(req, status);
865 END_PROFILE(SMBcheckpath);
869 status = resolve_dfspath(ctx, conn,
870 req->flags2 & FLAGS2_DFS_PATHNAMES,
873 if (!NT_STATUS_IS_OK(status)) {
874 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
875 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
877 END_PROFILE(SMBcheckpath);
883 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
885 status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
886 if (!NT_STATUS_IS_OK(status)) {
890 status = check_name(conn, name);
891 if (!NT_STATUS_IS_OK(status)) {
892 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
896 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
897 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
898 status = map_nt_error_from_unix(errno);
902 if (!S_ISDIR(sbuf.st_mode)) {
903 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
905 END_PROFILE(SMBcheckpath);
909 reply_outbuf(req, 0, 0);
911 END_PROFILE(SMBcheckpath);
916 END_PROFILE(SMBcheckpath);
918 /* We special case this - as when a Windows machine
919 is parsing a path is steps through the components
920 one at a time - if a component fails it expects
921 ERRbadpath, not ERRbadfile.
923 status = map_checkpath_error((char *)req->inbuf, status);
924 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
926 * Windows returns different error codes if
927 * the parent directory is valid but not the
928 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
929 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
930 * if the path is invalid.
932 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
937 reply_nterror(req, status);
940 /****************************************************************************
942 ****************************************************************************/
944 void reply_getatr(connection_struct *conn, struct smb_request *req)
947 SMB_STRUCT_STAT sbuf;
953 TALLOC_CTX *ctx = talloc_tos();
955 START_PROFILE(SMBgetatr);
957 p = smb_buf(req->inbuf) + 1;
958 p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
959 0, STR_TERMINATE, &status);
960 if (!NT_STATUS_IS_OK(status)) {
961 reply_nterror(req, status);
962 END_PROFILE(SMBgetatr);
966 status = resolve_dfspath(ctx, conn,
967 req->flags2 & FLAGS2_DFS_PATHNAMES,
970 if (!NT_STATUS_IS_OK(status)) {
971 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
972 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
974 END_PROFILE(SMBgetatr);
977 reply_nterror(req, status);
978 END_PROFILE(SMBgetatr);
982 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
983 under WfWg - weird! */
984 if (*fname == '\0') {
985 mode = aHIDDEN | aDIR;
986 if (!CAN_WRITE(conn)) {
992 status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
993 if (!NT_STATUS_IS_OK(status)) {
994 reply_nterror(req, status);
995 END_PROFILE(SMBgetatr);
998 status = check_name(conn, fname);
999 if (!NT_STATUS_IS_OK(status)) {
1000 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1001 reply_nterror(req, status);
1002 END_PROFILE(SMBgetatr);
1005 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
1006 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1007 reply_unixerror(req, ERRDOS,ERRbadfile);
1008 END_PROFILE(SMBgetatr);
1012 mode = dos_mode(conn,fname,&sbuf);
1013 size = sbuf.st_size;
1014 mtime = sbuf.st_mtime;
1020 reply_outbuf(req, 10, 0);
1022 SSVAL(req->outbuf,smb_vwv0,mode);
1023 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1024 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1026 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1028 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1030 if (Protocol >= PROTOCOL_NT1) {
1031 SSVAL(req->outbuf, smb_flg2,
1032 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1035 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1037 END_PROFILE(SMBgetatr);
1041 /****************************************************************************
1043 ****************************************************************************/
1045 void reply_setatr(connection_struct *conn, struct smb_request *req)
1050 SMB_STRUCT_STAT sbuf;
1053 TALLOC_CTX *ctx = talloc_tos();
1055 START_PROFILE(SMBsetatr);
1058 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1062 p = smb_buf(req->inbuf) + 1;
1063 p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
1064 0, STR_TERMINATE, &status);
1065 if (!NT_STATUS_IS_OK(status)) {
1066 reply_nterror(req, status);
1067 END_PROFILE(SMBsetatr);
1071 status = resolve_dfspath(ctx, conn,
1072 req->flags2 & FLAGS2_DFS_PATHNAMES,
1075 if (!NT_STATUS_IS_OK(status)) {
1076 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1077 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1078 ERRSRV, ERRbadpath);
1079 END_PROFILE(SMBsetatr);
1082 reply_nterror(req, status);
1083 END_PROFILE(SMBsetatr);
1087 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
1088 if (!NT_STATUS_IS_OK(status)) {
1089 reply_nterror(req, status);
1090 END_PROFILE(SMBsetatr);
1094 status = check_name(conn, fname);
1095 if (!NT_STATUS_IS_OK(status)) {
1096 reply_nterror(req, status);
1097 END_PROFILE(SMBsetatr);
1101 if (fname[0] == '.' && fname[1] == '\0') {
1103 * Not sure here is the right place to catch this
1104 * condition. Might be moved to somewhere else later -- vl
1106 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1107 END_PROFILE(SMBsetatr);
1111 mode = SVAL(req->inbuf,smb_vwv0);
1112 mtime = srv_make_unix_date3(req->inbuf+smb_vwv1);
1114 if (mode != FILE_ATTRIBUTE_NORMAL) {
1115 if (VALID_STAT_OF_DIR(sbuf))
1120 if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
1121 reply_unixerror(req, ERRDOS, ERRnoaccess);
1122 END_PROFILE(SMBsetatr);
1127 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
1128 reply_unixerror(req, ERRDOS, ERRnoaccess);
1129 END_PROFILE(SMBsetatr);
1133 reply_outbuf(req, 0, 0);
1135 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1137 END_PROFILE(SMBsetatr);
1141 /****************************************************************************
1143 ****************************************************************************/
1145 void reply_dskattr(connection_struct *conn, struct smb_request *req)
1147 SMB_BIG_UINT dfree,dsize,bsize;
1148 START_PROFILE(SMBdskattr);
1150 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1151 reply_unixerror(req, ERRHRD, ERRgeneral);
1152 END_PROFILE(SMBdskattr);
1156 reply_outbuf(req, 5, 0);
1158 if (Protocol <= PROTOCOL_LANMAN2) {
1159 double total_space, free_space;
1160 /* we need to scale this to a number that DOS6 can handle. We
1161 use floating point so we can handle large drives on systems
1162 that don't have 64 bit integers
1164 we end up displaying a maximum of 2G to DOS systems
1166 total_space = dsize * (double)bsize;
1167 free_space = dfree * (double)bsize;
1169 dsize = (SMB_BIG_UINT)((total_space+63*512) / (64*512));
1170 dfree = (SMB_BIG_UINT)((free_space+63*512) / (64*512));
1172 if (dsize > 0xFFFF) dsize = 0xFFFF;
1173 if (dfree > 0xFFFF) dfree = 0xFFFF;
1175 SSVAL(req->outbuf,smb_vwv0,dsize);
1176 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1177 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1178 SSVAL(req->outbuf,smb_vwv3,dfree);
1180 SSVAL(req->outbuf,smb_vwv0,dsize);
1181 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1182 SSVAL(req->outbuf,smb_vwv2,512);
1183 SSVAL(req->outbuf,smb_vwv3,dfree);
1186 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1188 END_PROFILE(SMBdskattr);
1192 /****************************************************************************
1194 Can be called from SMBsearch, SMBffirst or SMBfunique.
1195 ****************************************************************************/
1197 void reply_search(connection_struct *conn, struct smb_request *req)
1200 char *directory = NULL;
1206 unsigned int numentries = 0;
1207 unsigned int maxentries = 0;
1208 bool finished = False;
1214 bool check_descend = False;
1215 bool expect_close = False;
1217 bool mask_contains_wcard = False;
1218 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1219 TALLOC_CTX *ctx = talloc_tos();
1221 START_PROFILE(SMBsearch);
1224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1225 END_PROFILE(SMBsearch);
1229 if (lp_posix_pathnames()) {
1230 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1231 END_PROFILE(SMBsearch);
1235 /* If we were called as SMBffirst then we must expect close. */
1236 if(CVAL(req->inbuf,smb_com) == SMBffirst) {
1237 expect_close = True;
1240 reply_outbuf(req, 1, 3);
1241 maxentries = SVAL(req->inbuf,smb_vwv0);
1242 dirtype = SVAL(req->inbuf,smb_vwv1);
1243 p = smb_buf(req->inbuf) + 1;
1244 p += srvstr_get_path_wcard(ctx,
1252 &mask_contains_wcard);
1253 if (!NT_STATUS_IS_OK(nt_status)) {
1254 reply_nterror(req, nt_status);
1255 END_PROFILE(SMBsearch);
1259 nt_status = resolve_dfspath_wcard(ctx, conn,
1260 req->flags2 & FLAGS2_DFS_PATHNAMES,
1263 &mask_contains_wcard);
1264 if (!NT_STATUS_IS_OK(nt_status)) {
1265 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1266 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1267 ERRSRV, ERRbadpath);
1268 END_PROFILE(SMBsearch);
1271 reply_nterror(req, nt_status);
1272 END_PROFILE(SMBsearch);
1277 status_len = SVAL(p, 0);
1280 /* dirtype &= ~aDIR; */
1282 if (status_len == 0) {
1283 SMB_STRUCT_STAT sbuf;
1285 nt_status = unix_convert(ctx, conn, path, True,
1286 &directory, NULL, &sbuf);
1287 if (!NT_STATUS_IS_OK(nt_status)) {
1288 reply_nterror(req, nt_status);
1289 END_PROFILE(SMBsearch);
1293 nt_status = check_name(conn, directory);
1294 if (!NT_STATUS_IS_OK(nt_status)) {
1295 reply_nterror(req, nt_status);
1296 END_PROFILE(SMBsearch);
1300 p = strrchr_m(directory,'/');
1303 directory = talloc_strdup(ctx,".");
1305 reply_nterror(req, NT_STATUS_NO_MEMORY);
1306 END_PROFILE(SMBsearch);
1314 if (*directory == '\0') {
1315 directory = talloc_strdup(ctx,".");
1317 reply_nterror(req, NT_STATUS_NO_MEMORY);
1318 END_PROFILE(SMBsearch);
1322 memset((char *)status,'\0',21);
1323 SCVAL(status,0,(dirtype & 0x1F));
1325 nt_status = dptr_create(conn,
1331 mask_contains_wcard,
1334 if (!NT_STATUS_IS_OK(nt_status)) {
1335 reply_nterror(req, nt_status);
1336 END_PROFILE(SMBsearch);
1339 dptr_num = dptr_dnum(conn->dirptr);
1343 memcpy(status,p,21);
1344 status_dirtype = CVAL(status,0) & 0x1F;
1345 if (status_dirtype != (dirtype & 0x1F)) {
1346 dirtype = status_dirtype;
1349 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1350 if (!conn->dirptr) {
1353 string_set(&conn->dirpath,dptr_path(dptr_num));
1354 mask = dptr_wcard(dptr_num);
1359 * For a 'continue' search we have no string. So
1360 * check from the initial saved string.
1362 mask_contains_wcard = ms_has_wild(mask);
1363 dirtype = dptr_attr(dptr_num);
1366 DEBUG(4,("dptr_num is %d\n",dptr_num));
1368 if ((dirtype&0x1F) == aVOLID) {
1369 char buf[DIR_STRUCT_SIZE];
1370 memcpy(buf,status,21);
1371 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1372 0,aVOLID,0,!allow_long_path_components)) {
1373 reply_nterror(req, NT_STATUS_NO_MEMORY);
1374 END_PROFILE(SMBsearch);
1377 dptr_fill(buf+12,dptr_num);
1378 if (dptr_zero(buf+12) && (status_len==0)) {
1383 if (message_push_blob(&req->outbuf,
1384 data_blob_const(buf, sizeof(buf)))
1386 reply_nterror(req, NT_STATUS_NO_MEMORY);
1387 END_PROFILE(SMBsearch);
1395 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1398 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1399 conn->dirpath,lp_dontdescend(SNUM(conn))));
1400 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1401 check_descend = True;
1404 for (i=numentries;(i<maxentries) && !finished;i++) {
1405 finished = !get_dir_entry(ctx,conn,mask,dirtype,&fname,
1406 &size,&mode,&date,check_descend);
1408 char buf[DIR_STRUCT_SIZE];
1409 memcpy(buf,status,21);
1410 if (!make_dir_struct(ctx,
1417 !allow_long_path_components)) {
1418 reply_nterror(req, NT_STATUS_NO_MEMORY);
1419 END_PROFILE(SMBsearch);
1422 if (!dptr_fill(buf+12,dptr_num)) {
1425 if (message_push_blob(&req->outbuf,
1426 data_blob_const(buf, sizeof(buf)))
1428 reply_nterror(req, NT_STATUS_NO_MEMORY);
1429 END_PROFILE(SMBsearch);
1439 /* If we were called as SMBffirst with smb_search_id == NULL
1440 and no entries were found then return error and close dirptr
1443 if (numentries == 0) {
1444 dptr_close(&dptr_num);
1445 } else if(expect_close && status_len == 0) {
1446 /* Close the dptr - we know it's gone */
1447 dptr_close(&dptr_num);
1450 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1451 if(dptr_num >= 0 && CVAL(req->inbuf,smb_com) == SMBfunique) {
1452 dptr_close(&dptr_num);
1455 if ((numentries == 0) && !mask_contains_wcard) {
1456 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1457 END_PROFILE(SMBsearch);
1461 SSVAL(req->outbuf,smb_vwv0,numentries);
1462 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1463 SCVAL(smb_buf(req->outbuf),0,5);
1464 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1466 /* The replies here are never long name. */
1467 SSVAL(req->outbuf, smb_flg2,
1468 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1469 if (!allow_long_path_components) {
1470 SSVAL(req->outbuf, smb_flg2,
1471 SVAL(req->outbuf, smb_flg2)
1472 & (~FLAGS2_LONG_PATH_COMPONENTS));
1475 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1476 SSVAL(req->outbuf, smb_flg2,
1477 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1480 directory = dptr_path(dptr_num);
1483 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1484 smb_fn_name(CVAL(req->inbuf,smb_com)),
1486 directory ? directory : "./",
1491 END_PROFILE(SMBsearch);
1495 /****************************************************************************
1496 Reply to a fclose (stop directory search).
1497 ****************************************************************************/
1499 void reply_fclose(connection_struct *conn, struct smb_request *req)
1507 bool path_contains_wcard = False;
1508 TALLOC_CTX *ctx = talloc_tos();
1510 START_PROFILE(SMBfclose);
1512 if (lp_posix_pathnames()) {
1513 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1514 END_PROFILE(SMBfclose);
1518 p = smb_buf(req->inbuf) + 1;
1519 p += srvstr_get_path_wcard(ctx,
1527 &path_contains_wcard);
1528 if (!NT_STATUS_IS_OK(err)) {
1529 reply_nterror(req, err);
1530 END_PROFILE(SMBfclose);
1534 status_len = SVAL(p,0);
1537 if (status_len == 0) {
1538 reply_doserror(req, ERRSRV, ERRsrverror);
1539 END_PROFILE(SMBfclose);
1543 memcpy(status,p,21);
1545 if(dptr_fetch(status+12,&dptr_num)) {
1546 /* Close the dptr - we know it's gone */
1547 dptr_close(&dptr_num);
1550 reply_outbuf(req, 1, 0);
1551 SSVAL(req->outbuf,smb_vwv0,0);
1553 DEBUG(3,("search close\n"));
1555 END_PROFILE(SMBfclose);
1559 /****************************************************************************
1561 ****************************************************************************/
1563 void reply_open(connection_struct *conn, struct smb_request *req)
1570 SMB_STRUCT_STAT sbuf;
1577 uint32 create_disposition;
1578 uint32 create_options = 0;
1580 TALLOC_CTX *ctx = talloc_tos();
1582 START_PROFILE(SMBopen);
1585 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1586 END_PROFILE(SMBopen);
1590 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1591 deny_mode = SVAL(req->inbuf,smb_vwv0);
1592 dos_attr = SVAL(req->inbuf,smb_vwv1);
1594 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
1595 smb_buf(req->inbuf)+1, 0,
1596 STR_TERMINATE, &status);
1597 if (!NT_STATUS_IS_OK(status)) {
1598 reply_nterror(req, status);
1599 END_PROFILE(SMBopen);
1603 if (!map_open_params_to_ntcreate(
1604 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1605 &share_mode, &create_disposition, &create_options)) {
1606 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1607 END_PROFILE(SMBopen);
1611 status = create_file(conn, /* conn */
1613 0, /* root_dir_fid */
1615 access_mask, /* access_mask */
1616 share_mode, /* share_access */
1617 create_disposition, /* create_disposition*/
1618 create_options, /* create_options */
1619 dos_attr, /* file_attributes */
1620 oplock_request, /* oplock_request */
1621 0, /* allocation_size */
1628 if (!NT_STATUS_IS_OK(status)) {
1629 if (open_was_deferred(req->mid)) {
1630 /* We have re-scheduled this call. */
1631 END_PROFILE(SMBopen);
1634 reply_openerror(req, status);
1635 END_PROFILE(SMBopen);
1639 size = sbuf.st_size;
1640 fattr = dos_mode(conn,fname,&sbuf);
1641 mtime = sbuf.st_mtime;
1644 DEBUG(3,("attempt to open a directory %s\n",fname));
1645 close_file(fsp,ERROR_CLOSE);
1646 reply_doserror(req, ERRDOS,ERRnoaccess);
1647 END_PROFILE(SMBopen);
1651 reply_outbuf(req, 7, 0);
1652 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1653 SSVAL(req->outbuf,smb_vwv1,fattr);
1654 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1655 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1657 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1659 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1660 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1662 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1663 SCVAL(req->outbuf,smb_flg,
1664 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1667 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1668 SCVAL(req->outbuf,smb_flg,
1669 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1671 END_PROFILE(SMBopen);
1675 /****************************************************************************
1676 Reply to an open and X.
1677 ****************************************************************************/
1679 void reply_open_and_X(connection_struct *conn, struct smb_request *req)
1685 /* Breakout the oplock request bits so we can set the
1686 reply bits separately. */
1687 int ex_oplock_request;
1688 int core_oplock_request;
1691 int smb_sattr = SVAL(req->inbuf,smb_vwv4);
1692 uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
1697 SMB_STRUCT_STAT sbuf;
1701 SMB_BIG_UINT allocation_size;
1702 ssize_t retval = -1;
1705 uint32 create_disposition;
1706 uint32 create_options = 0;
1707 TALLOC_CTX *ctx = talloc_tos();
1709 START_PROFILE(SMBopenX);
1711 if (req->wct < 15) {
1712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1713 END_PROFILE(SMBopenX);
1717 open_flags = SVAL(req->inbuf,smb_vwv2);
1718 deny_mode = SVAL(req->inbuf,smb_vwv3);
1719 smb_attr = SVAL(req->inbuf,smb_vwv5);
1720 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1721 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1722 oplock_request = ex_oplock_request | core_oplock_request;
1723 smb_ofun = SVAL(req->inbuf,smb_vwv8);
1724 allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
1726 /* If it's an IPC, pass off the pipe handler. */
1728 if (lp_nt_pipe_support()) {
1729 reply_open_pipe_and_X(conn, req);
1731 reply_doserror(req, ERRSRV, ERRaccess);
1733 END_PROFILE(SMBopenX);
1737 /* XXXX we need to handle passed times, sattr and flags */
1738 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
1739 smb_buf(req->inbuf), 0, STR_TERMINATE,
1741 if (!NT_STATUS_IS_OK(status)) {
1742 reply_nterror(req, status);
1743 END_PROFILE(SMBopenX);
1747 if (!map_open_params_to_ntcreate(
1748 fname, deny_mode, smb_ofun, &access_mask,
1749 &share_mode, &create_disposition, &create_options)) {
1750 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1751 END_PROFILE(SMBopenX);
1755 status = create_file(conn, /* conn */
1757 0, /* root_dir_fid */
1759 access_mask, /* access_mask */
1760 share_mode, /* share_access */
1761 create_disposition, /* create_disposition*/
1762 create_options, /* create_options */
1763 smb_attr, /* file_attributes */
1764 oplock_request, /* oplock_request */
1765 0, /* allocation_size */
1769 &smb_action, /* pinfo */
1772 if (!NT_STATUS_IS_OK(status)) {
1773 END_PROFILE(SMBopenX);
1774 if (open_was_deferred(req->mid)) {
1775 /* We have re-scheduled this call. */
1778 reply_openerror(req, status);
1782 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1783 if the file is truncated or created. */
1784 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1785 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1786 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1787 close_file(fsp,ERROR_CLOSE);
1788 reply_nterror(req, NT_STATUS_DISK_FULL);
1789 END_PROFILE(SMBopenX);
1792 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1794 close_file(fsp,ERROR_CLOSE);
1795 reply_nterror(req, NT_STATUS_DISK_FULL);
1796 END_PROFILE(SMBopenX);
1799 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1802 fattr = dos_mode(conn,fname,&sbuf);
1803 mtime = sbuf.st_mtime;
1805 close_file(fsp,ERROR_CLOSE);
1806 reply_doserror(req, ERRDOS, ERRnoaccess);
1807 END_PROFILE(SMBopenX);
1811 /* If the caller set the extended oplock request bit
1812 and we granted one (by whatever means) - set the
1813 correct bit for extended oplock reply.
1816 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1817 smb_action |= EXTENDED_OPLOCK_GRANTED;
1820 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1821 smb_action |= EXTENDED_OPLOCK_GRANTED;
1824 /* If the caller set the core oplock request bit
1825 and we granted one (by whatever means) - set the
1826 correct bit for core oplock reply.
1829 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1830 reply_outbuf(req, 19, 0);
1832 reply_outbuf(req, 15, 0);
1835 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1836 SCVAL(req->outbuf, smb_flg,
1837 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1840 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1841 SCVAL(req->outbuf, smb_flg,
1842 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1845 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1846 SSVAL(req->outbuf,smb_vwv3,fattr);
1847 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1848 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1850 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1852 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1853 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1854 SSVAL(req->outbuf,smb_vwv11,smb_action);
1856 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1857 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1860 END_PROFILE(SMBopenX);
1865 /****************************************************************************
1866 Reply to a SMBulogoffX.
1867 conn POINTER CAN BE NULL HERE !
1868 ****************************************************************************/
1870 void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
1874 START_PROFILE(SMBulogoffX);
1876 vuser = get_valid_user_struct(req->vuid);
1879 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1883 /* in user level security we are supposed to close any files
1884 open by this user */
1885 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1886 file_close_user(req->vuid);
1889 invalidate_vuid(req->vuid);
1891 reply_outbuf(req, 2, 0);
1893 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1895 END_PROFILE(SMBulogoffX);
1899 /****************************************************************************
1900 Reply to a mknew or a create.
1901 ****************************************************************************/
1903 void reply_mknew(connection_struct *conn, struct smb_request *req)
1908 struct timespec ts[2];
1910 int oplock_request = 0;
1911 SMB_STRUCT_STAT sbuf;
1913 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1914 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1915 uint32 create_disposition;
1916 uint32 create_options = 0;
1917 TALLOC_CTX *ctx = talloc_tos();
1919 START_PROFILE(SMBcreate);
1922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1923 END_PROFILE(SMBcreate);
1927 fattr = SVAL(req->inbuf,smb_vwv0);
1928 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1929 com = SVAL(req->inbuf,smb_com);
1931 ts[1] =convert_time_t_to_timespec(
1932 srv_make_unix_date3(req->inbuf + smb_vwv1));
1935 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
1936 smb_buf(req->inbuf) + 1, 0,
1937 STR_TERMINATE, &status);
1938 if (!NT_STATUS_IS_OK(status)) {
1939 reply_nterror(req, status);
1940 END_PROFILE(SMBcreate);
1944 if (fattr & aVOLID) {
1945 DEBUG(0,("Attempt to create file (%s) with volid set - "
1946 "please report this\n", fname));
1949 if(com == SMBmknew) {
1950 /* We should fail if file exists. */
1951 create_disposition = FILE_CREATE;
1953 /* Create if file doesn't exist, truncate if it does. */
1954 create_disposition = FILE_OVERWRITE_IF;
1957 status = create_file(conn, /* conn */
1959 0, /* root_dir_fid */
1961 access_mask, /* access_mask */
1962 share_mode, /* share_access */
1963 create_disposition, /* create_disposition*/
1964 create_options, /* create_options */
1965 fattr, /* file_attributes */
1966 oplock_request, /* oplock_request */
1967 0, /* allocation_size */
1974 if (!NT_STATUS_IS_OK(status)) {
1975 END_PROFILE(SMBcreate);
1976 if (open_was_deferred(req->mid)) {
1977 /* We have re-scheduled this call. */
1980 reply_openerror(req, status);
1984 ts[0] = get_atimespec(&sbuf); /* atime. */
1985 file_ntimes(conn, fname, ts);
1987 reply_outbuf(req, 1, 0);
1988 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1990 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1991 SCVAL(req->outbuf,smb_flg,
1992 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1995 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1996 SCVAL(req->outbuf,smb_flg,
1997 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2000 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
2001 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2002 fname, fsp->fh->fd, (unsigned int)fattr ) );
2004 END_PROFILE(SMBcreate);
2008 /****************************************************************************
2009 Reply to a create temporary file.
2010 ****************************************************************************/
2012 void reply_ctemp(connection_struct *conn, struct smb_request *req)
2019 SMB_STRUCT_STAT sbuf;
2022 TALLOC_CTX *ctx = talloc_tos();
2024 START_PROFILE(SMBctemp);
2027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2028 END_PROFILE(SMBctemp);
2032 fattr = SVAL(req->inbuf,smb_vwv0);
2033 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2035 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
2036 smb_buf(req->inbuf)+1, 0, STR_TERMINATE,
2038 if (!NT_STATUS_IS_OK(status)) {
2039 reply_nterror(req, status);
2040 END_PROFILE(SMBctemp);
2044 fname = talloc_asprintf(ctx,
2048 fname = talloc_strdup(ctx, "TMXXXXXX");
2052 reply_nterror(req, NT_STATUS_NO_MEMORY);
2053 END_PROFILE(SMBctemp);
2057 status = resolve_dfspath(ctx, conn,
2058 req->flags2 & FLAGS2_DFS_PATHNAMES,
2061 if (!NT_STATUS_IS_OK(status)) {
2062 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2063 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2064 ERRSRV, ERRbadpath);
2065 END_PROFILE(SMBctemp);
2068 reply_nterror(req, status);
2069 END_PROFILE(SMBctemp);
2073 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
2074 if (!NT_STATUS_IS_OK(status)) {
2075 reply_nterror(req, status);
2076 END_PROFILE(SMBctemp);
2080 status = check_name(conn, CONST_DISCARD(char *,fname));
2081 if (!NT_STATUS_IS_OK(status)) {
2082 reply_nterror(req, status);
2083 END_PROFILE(SMBctemp);
2087 tmpfd = smb_mkstemp(fname);
2089 reply_unixerror(req, ERRDOS, ERRnoaccess);
2090 END_PROFILE(SMBctemp);
2094 SMB_VFS_STAT(conn,fname,&sbuf);
2096 /* We should fail if file does not exist. */
2097 status = open_file_ntcreate(conn, req, fname, &sbuf,
2098 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
2099 FILE_SHARE_READ|FILE_SHARE_WRITE,
2106 /* close fd from smb_mkstemp() */
2109 if (!NT_STATUS_IS_OK(status)) {
2110 if (open_was_deferred(req->mid)) {
2111 /* We have re-scheduled this call. */
2112 END_PROFILE(SMBctemp);
2115 reply_openerror(req, status);
2116 END_PROFILE(SMBctemp);
2120 reply_outbuf(req, 1, 0);
2121 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2123 /* the returned filename is relative to the directory */
2124 s = strrchr_m(fname, '/');
2132 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2133 thing in the byte section. JRA */
2134 SSVALS(p, 0, -1); /* what is this? not in spec */
2136 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2138 reply_nterror(req, NT_STATUS_NO_MEMORY);
2139 END_PROFILE(SMBctemp);
2143 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2144 SCVAL(req->outbuf, smb_flg,
2145 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2148 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2149 SCVAL(req->outbuf, smb_flg,
2150 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2153 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
2154 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
2155 (unsigned int)sbuf.st_mode ) );
2157 END_PROFILE(SMBctemp);
2161 /*******************************************************************
2162 Check if a user is allowed to rename a file.
2163 ********************************************************************/
2165 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2166 uint16 dirtype, SMB_STRUCT_STAT *pst)
2170 if (!CAN_WRITE(conn)) {
2171 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2174 fmode = dos_mode(conn, fsp->fsp_name, pst);
2175 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2176 return NT_STATUS_NO_SUCH_FILE;
2179 if (S_ISDIR(pst->st_mode)) {
2180 return NT_STATUS_OK;
2183 if (fsp->access_mask & DELETE_ACCESS) {
2184 return NT_STATUS_OK;
2187 return NT_STATUS_ACCESS_DENIED;
2190 /*******************************************************************
2191 * unlink a file with all relevant access checks
2192 *******************************************************************/
2194 static NTSTATUS do_unlink(connection_struct *conn,
2195 struct smb_request *req,
2199 SMB_STRUCT_STAT sbuf;
2202 uint32 dirtype_orig = dirtype;
2205 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2207 if (!CAN_WRITE(conn)) {
2208 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2211 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2212 return map_nt_error_from_unix(errno);
2215 fattr = dos_mode(conn,fname,&sbuf);
2217 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2218 dirtype = aDIR|aARCH|aRONLY;
2221 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2223 return NT_STATUS_NO_SUCH_FILE;
2226 if (!dir_check_ftype(conn, fattr, dirtype)) {
2228 return NT_STATUS_FILE_IS_A_DIRECTORY;
2230 return NT_STATUS_NO_SUCH_FILE;
2233 if (dirtype_orig & 0x8000) {
2234 /* These will never be set for POSIX. */
2235 return NT_STATUS_NO_SUCH_FILE;
2239 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2240 return NT_STATUS_FILE_IS_A_DIRECTORY;
2243 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2244 return NT_STATUS_NO_SUCH_FILE;
2247 if (dirtype & 0xFF00) {
2248 /* These will never be set for POSIX. */
2249 return NT_STATUS_NO_SUCH_FILE;
2254 return NT_STATUS_NO_SUCH_FILE;
2257 /* Can't delete a directory. */
2259 return NT_STATUS_FILE_IS_A_DIRECTORY;
2264 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2265 return NT_STATUS_OBJECT_NAME_INVALID;
2266 #endif /* JRATEST */
2268 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2270 On a Windows share, a file with read-only dosmode can be opened with
2271 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2272 fails with NT_STATUS_CANNOT_DELETE error.
2274 This semantic causes a problem that a user can not
2275 rename a file with read-only dosmode on a Samba share
2276 from a Windows command prompt (i.e. cmd.exe, but can rename
2277 from Windows Explorer).
2280 if (!lp_delete_readonly(SNUM(conn))) {
2281 if (fattr & aRONLY) {
2282 return NT_STATUS_CANNOT_DELETE;
2286 /* On open checks the open itself will check the share mode, so
2287 don't do it here as we'll get it wrong. */
2289 status = open_file_ntcreate(conn, req, fname, &sbuf,
2294 FILE_ATTRIBUTE_NORMAL,
2295 req != NULL ? 0 : INTERNAL_OPEN_ONLY,
2298 if (!NT_STATUS_IS_OK(status)) {
2299 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2300 nt_errstr(status)));
2304 /* The set is across all open files on this dev/inode pair. */
2305 if (!set_delete_on_close(fsp, True, ¤t_user.ut)) {
2306 close_file(fsp, NORMAL_CLOSE);
2307 return NT_STATUS_ACCESS_DENIED;
2310 return close_file(fsp,NORMAL_CLOSE);
2313 /****************************************************************************
2314 The guts of the unlink command, split out so it may be called by the NT SMB
2316 ****************************************************************************/
2318 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2319 uint32 dirtype, const char *name_in, bool has_wild)
2321 const char *directory = NULL;
2326 NTSTATUS status = NT_STATUS_OK;
2327 SMB_STRUCT_STAT sbuf;
2328 TALLOC_CTX *ctx = talloc_tos();
2330 status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
2331 if (!NT_STATUS_IS_OK(status)) {
2335 p = strrchr_m(name,'/');
2337 directory = talloc_strdup(ctx, ".");
2339 return NT_STATUS_NO_MEMORY;
2349 * We should only check the mangled cache
2350 * here if unix_convert failed. This means
2351 * that the path in 'mask' doesn't exist
2352 * on the file system and so we need to look
2353 * for a possible mangle. This patch from
2354 * Tine Smukavec <valentin.smukavec@hermes.si>.
2357 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
2358 char *new_mask = NULL;
2359 mangle_lookup_name_from_8_3(ctx,
2369 directory = talloc_asprintf(ctx,
2374 return NT_STATUS_NO_MEMORY;
2377 dirtype = FILE_ATTRIBUTE_NORMAL;
2380 status = check_name(conn, directory);
2381 if (!NT_STATUS_IS_OK(status)) {
2385 status = do_unlink(conn, req, directory, dirtype);
2386 if (!NT_STATUS_IS_OK(status)) {
2392 struct smb_Dir *dir_hnd = NULL;
2396 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2397 return NT_STATUS_OBJECT_NAME_INVALID;
2400 if (strequal(mask,"????????.???")) {
2405 status = check_name(conn, directory);
2406 if (!NT_STATUS_IS_OK(status)) {
2410 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2411 if (dir_hnd == NULL) {
2412 return map_nt_error_from_unix(errno);
2415 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2416 the pattern matches against the long name, otherwise the short name
2417 We don't implement this yet XXXX
2420 status = NT_STATUS_NO_SUCH_FILE;
2422 while ((dname = ReadDirName(dir_hnd, &offset))) {
2426 if (!is_visible_file(conn, directory, dname, &st, True)) {
2430 /* Quick check for "." and ".." */
2431 if (ISDOT(dname) || ISDOTDOT(dname)) {
2435 if(!mask_match(dname, mask, conn->case_sensitive)) {
2439 fname = talloc_asprintf(ctx, "%s/%s",
2443 return NT_STATUS_NO_MEMORY;
2446 status = check_name(conn, fname);
2447 if (!NT_STATUS_IS_OK(status)) {
2452 status = do_unlink(conn, req, fname, dirtype);
2453 if (!NT_STATUS_IS_OK(status)) {
2459 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2467 if (count == 0 && NT_STATUS_IS_OK(status)) {
2468 status = map_nt_error_from_unix(errno);
2474 /****************************************************************************
2476 ****************************************************************************/
2478 void reply_unlink(connection_struct *conn, struct smb_request *req)
2483 bool path_contains_wcard = False;
2484 TALLOC_CTX *ctx = talloc_tos();
2486 START_PROFILE(SMBunlink);
2489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2490 END_PROFILE(SMBunlink);
2494 dirtype = SVAL(req->inbuf,smb_vwv0);
2496 srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name,
2497 smb_buf(req->inbuf) + 1, 0,
2498 STR_TERMINATE, &status, &path_contains_wcard);
2499 if (!NT_STATUS_IS_OK(status)) {
2500 reply_nterror(req, status);
2501 END_PROFILE(SMBunlink);
2505 status = resolve_dfspath_wcard(ctx, conn,
2506 req->flags2 & FLAGS2_DFS_PATHNAMES,
2509 &path_contains_wcard);
2510 if (!NT_STATUS_IS_OK(status)) {
2511 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2512 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2513 ERRSRV, ERRbadpath);
2514 END_PROFILE(SMBunlink);
2517 reply_nterror(req, status);
2518 END_PROFILE(SMBunlink);
2522 DEBUG(3,("reply_unlink : %s\n",name));
2524 status = unlink_internals(conn, req, dirtype, name,
2525 path_contains_wcard);
2526 if (!NT_STATUS_IS_OK(status)) {
2527 if (open_was_deferred(req->mid)) {
2528 /* We have re-scheduled this call. */
2529 END_PROFILE(SMBunlink);
2532 reply_nterror(req, status);
2533 END_PROFILE(SMBunlink);
2537 reply_outbuf(req, 0, 0);
2538 END_PROFILE(SMBunlink);
2543 /****************************************************************************
2545 ****************************************************************************/
2547 static void fail_readraw(void)
2549 const char *errstr = talloc_asprintf(talloc_tos(),
2550 "FAIL ! reply_readbraw: socket write fail (%s)",
2555 exit_server_cleanly(errstr);
2558 /****************************************************************************
2559 Fake (read/write) sendfile. Returns -1 on read or write fail.
2560 ****************************************************************************/
2562 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2566 size_t tosend = nread;
2573 bufsize = MIN(nread, 65536);
2575 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2579 while (tosend > 0) {
2583 if (tosend > bufsize) {
2588 ret = read_file(fsp,buf,startpos,cur_read);
2594 /* If we had a short read, fill with zeros. */
2595 if (ret < cur_read) {
2596 memset(buf, '\0', cur_read - ret);
2599 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2604 startpos += cur_read;
2608 return (ssize_t)nread;
2611 /****************************************************************************
2612 Return a readbraw error (4 bytes of zero).
2613 ****************************************************************************/
2615 static void reply_readbraw_error(void)
2619 if (write_data(smbd_server_fd(),header,4) != 4) {
2624 /****************************************************************************
2625 Use sendfile in readbraw.
2626 ****************************************************************************/
2628 void send_file_readbraw(connection_struct *conn,
2634 char *outbuf = NULL;
2637 #if defined(WITH_SENDFILE)
2639 * We can only use sendfile on a non-chained packet
2640 * but we can use on a non-oplocked file. tridge proved this
2641 * on a train in Germany :-). JRA.
2642 * reply_readbraw has already checked the length.
2645 if ( (chain_size == 0) && (nread > 0) &&
2646 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2648 DATA_BLOB header_blob;
2650 _smb_setlen(header,nread);
2651 header_blob = data_blob_const(header, 4);
2653 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd,
2654 &header_blob, startpos, nread) == -1) {
2655 /* Returning ENOSYS means no data at all was sent.
2656 * Do this as a normal read. */
2657 if (errno == ENOSYS) {
2658 goto normal_readbraw;
2662 * Special hack for broken Linux with no working sendfile. If we
2663 * return EINTR we sent the header but not the rest of the data.
2664 * Fake this up by doing read/write calls.
2666 if (errno == EINTR) {
2667 /* Ensure we don't do this again. */
2668 set_use_sendfile(SNUM(conn), False);
2669 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2671 if (fake_sendfile(fsp, startpos, nread) == -1) {
2672 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2673 fsp->fsp_name, strerror(errno) ));
2674 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2679 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2680 fsp->fsp_name, strerror(errno) ));
2681 exit_server_cleanly("send_file_readbraw sendfile failed");
2690 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2692 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2693 (unsigned)(nread+4)));
2694 reply_readbraw_error();
2699 ret = read_file(fsp,outbuf+4,startpos,nread);
2700 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2709 _smb_setlen(outbuf,ret);
2710 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2713 TALLOC_FREE(outbuf);
2716 /****************************************************************************
2717 Reply to a readbraw (core+ protocol).
2718 ****************************************************************************/
2720 void reply_readbraw(connection_struct *conn, struct smb_request *req)
2722 ssize_t maxcount,mincount;
2729 START_PROFILE(SMBreadbraw);
2731 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
2732 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2733 "raw reads/writes are disallowed.");
2737 reply_readbraw_error();
2738 END_PROFILE(SMBreadbraw);
2743 * Special check if an oplock break has been issued
2744 * and the readraw request croses on the wire, we must
2745 * return a zero length response here.
2748 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2751 * We have to do a check_fsp by hand here, as
2752 * we must always return 4 zero bytes on error,
2756 if (!fsp || !conn || conn != fsp->conn ||
2757 current_user.vuid != fsp->vuid ||
2758 fsp->is_directory || fsp->fh->fd == -1) {
2760 * fsp could be NULL here so use the value from the packet. JRA.
2762 DEBUG(3,("reply_readbraw: fnum %d not valid "
2764 (int)SVAL(req->inbuf,smb_vwv0)));
2765 reply_readbraw_error();
2766 END_PROFILE(SMBreadbraw);
2770 /* Do a "by hand" version of CHECK_READ. */
2771 if (!(fsp->can_read ||
2772 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2773 (fsp->access_mask & FILE_EXECUTE)))) {
2774 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2775 (int)SVAL(req->inbuf,smb_vwv0)));
2776 reply_readbraw_error();
2777 END_PROFILE(SMBreadbraw);
2781 flush_write_cache(fsp, READRAW_FLUSH);
2783 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1);
2784 if(req->wct == 10) {
2786 * This is a large offset (64 bit) read.
2788 #ifdef LARGE_SMB_OFF_T
2790 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv8)) << 32);
2792 #else /* !LARGE_SMB_OFF_T */
2795 * Ensure we haven't been sent a >32 bit offset.
2798 if(IVAL(req->inbuf,smb_vwv8) != 0) {
2799 DEBUG(0,("reply_readbraw: large offset "
2800 "(%x << 32) used and we don't support "
2801 "64 bit offsets.\n",
2802 (unsigned int)IVAL(req->inbuf,smb_vwv8) ));
2803 reply_readbraw_error();
2804 END_PROFILE(SMBreadbraw);
2808 #endif /* LARGE_SMB_OFF_T */
2811 DEBUG(0,("reply_readbraw: negative 64 bit "
2812 "readraw offset (%.0f) !\n",
2813 (double)startpos ));
2814 reply_readbraw_error();
2815 END_PROFILE(SMBreadbraw);
2820 maxcount = (SVAL(req->inbuf,smb_vwv3) & 0xFFFF);
2821 mincount = (SVAL(req->inbuf,smb_vwv4) & 0xFFFF);
2823 /* ensure we don't overrun the packet size */
2824 maxcount = MIN(65535,maxcount);
2826 if (is_locked(fsp,(uint32)req->smbpid,
2827 (SMB_BIG_UINT)maxcount,
2828 (SMB_BIG_UINT)startpos,
2830 reply_readbraw_error();
2831 END_PROFILE(SMBreadbraw);
2835 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2839 if (startpos >= size) {
2842 nread = MIN(maxcount,(size - startpos));
2845 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2846 if (nread < mincount)
2850 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2851 "min=%lu nread=%lu\n",
2852 fsp->fnum, (double)startpos,
2853 (unsigned long)maxcount,
2854 (unsigned long)mincount,
2855 (unsigned long)nread ) );
2857 send_file_readbraw(conn, fsp, startpos, nread, mincount);
2859 DEBUG(5,("reply_readbraw finished\n"));
2860 END_PROFILE(SMBreadbraw);
2864 #define DBGC_CLASS DBGC_LOCKING
2866 /****************************************************************************
2867 Reply to a lockread (core+ protocol).
2868 ****************************************************************************/
2870 void reply_lockread(connection_struct *conn, struct smb_request *req)
2878 struct byte_range_lock *br_lck = NULL;
2881 START_PROFILE(SMBlockread);
2884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2885 END_PROFILE(SMBlockread);
2889 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2891 if (!check_fsp(conn, req, fsp, ¤t_user)) {
2892 END_PROFILE(SMBlockread);
2896 if (!CHECK_READ(fsp,req->inbuf)) {
2897 reply_doserror(req, ERRDOS, ERRbadaccess);
2898 END_PROFILE(SMBlockread);
2902 release_level_2_oplocks_on_change(fsp);
2904 numtoread = SVAL(req->inbuf,smb_vwv1);
2905 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
2907 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
2909 reply_outbuf(req, 5, numtoread + 3);
2911 data = smb_buf(req->outbuf) + 3;
2914 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2915 * protocol request that predates the read/write lock concept.
2916 * Thus instead of asking for a read lock here we need to ask
2917 * for a write lock. JRA.
2918 * Note that the requested lock size is unaffected by max_recv.
2921 br_lck = do_lock(smbd_messaging_context(),
2924 (SMB_BIG_UINT)numtoread,
2925 (SMB_BIG_UINT)startpos,
2928 False, /* Non-blocking lock. */
2931 TALLOC_FREE(br_lck);
2933 if (NT_STATUS_V(status)) {
2934 reply_nterror(req, status);
2935 END_PROFILE(SMBlockread);
2940 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2943 if (numtoread > max_recv) {
2944 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2945 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2946 (unsigned int)numtoread, (unsigned int)max_recv ));
2947 numtoread = MIN(numtoread,max_recv);
2949 nread = read_file(fsp,data,startpos,numtoread);
2952 reply_unixerror(req, ERRDOS, ERRnoaccess);
2953 END_PROFILE(SMBlockread);
2957 srv_set_message((char *)req->outbuf, 5, nread+3, False);
2959 SSVAL(req->outbuf,smb_vwv0,nread);
2960 SSVAL(req->outbuf,smb_vwv5,nread+3);
2961 p = smb_buf(req->outbuf);
2962 SCVAL(p,0,0); /* pad byte. */
2965 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2966 fsp->fnum, (int)numtoread, (int)nread));
2968 END_PROFILE(SMBlockread);
2973 #define DBGC_CLASS DBGC_ALL
2975 /****************************************************************************
2977 ****************************************************************************/
2979 void reply_read(connection_struct *conn, struct smb_request *req)
2988 START_PROFILE(SMBread);
2991 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2992 END_PROFILE(SMBread);
2996 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2998 if (!check_fsp(conn, req, fsp, ¤t_user)) {
2999 END_PROFILE(SMBread);
3003 if (!CHECK_READ(fsp,req->inbuf)) {
3004 reply_doserror(req, ERRDOS, ERRbadaccess);
3005 END_PROFILE(SMBread);
3009 numtoread = SVAL(req->inbuf,smb_vwv1);
3010 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3012 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3015 * The requested read size cannot be greater than max_recv. JRA.
3017 if (numtoread > max_recv) {
3018 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3019 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3020 (unsigned int)numtoread, (unsigned int)max_recv ));
3021 numtoread = MIN(numtoread,max_recv);
3024 reply_outbuf(req, 5, numtoread+3);
3026 data = smb_buf(req->outbuf) + 3;
3028 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtoread,
3029 (SMB_BIG_UINT)startpos, READ_LOCK)) {
3030 reply_doserror(req, ERRDOS,ERRlock);
3031 END_PROFILE(SMBread);
3036 nread = read_file(fsp,data,startpos,numtoread);
3039 reply_unixerror(req, ERRDOS,ERRnoaccess);
3040 END_PROFILE(SMBread);
3044 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3046 SSVAL(req->outbuf,smb_vwv0,nread);
3047 SSVAL(req->outbuf,smb_vwv5,nread+3);
3048 SCVAL(smb_buf(req->outbuf),0,1);
3049 SSVAL(smb_buf(req->outbuf),1,nread);
3051 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3052 fsp->fnum, (int)numtoread, (int)nread ) );
3054 END_PROFILE(SMBread);
3058 /****************************************************************************
3060 ****************************************************************************/
3062 static int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3067 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3068 data = smb_buf(outbuf);
3070 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3072 SCVAL(outbuf,smb_vwv0,0xFF);
3073 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3074 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3075 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
3076 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3077 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
3078 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3079 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3083 /****************************************************************************
3084 Reply to a read and X - possibly using sendfile.
3085 ****************************************************************************/
3087 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3088 files_struct *fsp, SMB_OFF_T startpos,
3091 SMB_STRUCT_STAT sbuf;
3094 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3095 reply_unixerror(req, ERRDOS, ERRnoaccess);
3099 if (startpos > sbuf.st_size) {
3101 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3102 smb_maxcnt = (sbuf.st_size - startpos);
3105 if (smb_maxcnt == 0) {
3109 #if defined(WITH_SENDFILE)
3111 * We can only use sendfile on a non-chained packet
3112 * but we can use on a non-oplocked file. tridge proved this
3113 * on a train in Germany :-). JRA.
3116 if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
3117 !is_encrypted_packet(req->inbuf) &&
3118 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3119 uint8 headerbuf[smb_size + 12 * 2];
3123 * Set up the packet header before send. We
3124 * assume here the sendfile will work (get the
3125 * correct amount of data).
3128 header = data_blob_const(headerbuf, sizeof(headerbuf));
3130 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3131 setup_readX_header((char *)headerbuf, smb_maxcnt);
3133 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
3134 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
3135 if (errno == ENOSYS) {
3140 * Special hack for broken Linux with no working sendfile. If we
3141 * return EINTR we sent the header but not the rest of the data.
3142 * Fake this up by doing read/write calls.
3145 if (errno == EINTR) {
3146 /* Ensure we don't do this again. */
3147 set_use_sendfile(SNUM(conn), False);
3148 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3149 nread = fake_sendfile(fsp, startpos,
3152 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3153 fsp->fsp_name, strerror(errno) ));
3154 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3156 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3157 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3158 /* No outbuf here means successful sendfile. */
3159 TALLOC_FREE(req->outbuf);
3163 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3164 fsp->fsp_name, strerror(errno) ));
3165 exit_server_cleanly("send_file_readX sendfile failed");
3168 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3169 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3170 /* No outbuf here means successful sendfile. */
3171 TALLOC_FREE(req->outbuf);
3178 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3179 uint8 headerbuf[smb_size + 2*12];
3181 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3182 setup_readX_header((char *)headerbuf, smb_maxcnt);
3184 /* Send out the header. */
3185 if (write_data(smbd_server_fd(), (char *)headerbuf,
3186 sizeof(headerbuf)) != sizeof(headerbuf)) {
3187 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3188 fsp->fsp_name, strerror(errno) ));
3189 exit_server_cleanly("send_file_readX sendfile failed");
3191 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3193 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3194 fsp->fsp_name, strerror(errno) ));
3195 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3197 TALLOC_FREE(req->outbuf);
3200 reply_outbuf(req, 12, smb_maxcnt);
3202 nread = read_file(fsp, smb_buf(req->outbuf), startpos,
3205 reply_unixerror(req, ERRDOS, ERRnoaccess);
3209 setup_readX_header((char *)req->outbuf, nread);
3211 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3212 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3220 /****************************************************************************
3221 Reply to a read and X.
3222 ****************************************************************************/
3224 void reply_read_and_X(connection_struct *conn, struct smb_request *req)
3229 bool big_readX = False;
3231 size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
3234 START_PROFILE(SMBreadX);
3236 if ((req->wct != 10) && (req->wct != 12)) {
3237 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3241 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3242 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3243 smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
3245 /* If it's an IPC, pass off the pipe handler. */
3247 reply_pipe_read_and_X(req);
3248 END_PROFILE(SMBreadX);
3252 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3253 END_PROFILE(SMBreadX);
3257 if (!CHECK_READ(fsp,req->inbuf)) {
3258 reply_doserror(req, ERRDOS,ERRbadaccess);
3259 END_PROFILE(SMBreadX);
3263 if (global_client_caps & CAP_LARGE_READX) {
3264 size_t upper_size = SVAL(req->inbuf,smb_vwv7);
3265 smb_maxcnt |= (upper_size<<16);
3266 if (upper_size > 1) {
3267 /* Can't do this on a chained packet. */
3268 if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
3269 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3270 END_PROFILE(SMBreadX);
3273 /* We currently don't do this on signed or sealed data. */
3274 if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
3275 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3276 END_PROFILE(SMBreadX);
3279 /* Is there room in the reply for this data ? */
3280 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3282 NT_STATUS_INVALID_PARAMETER);
3283 END_PROFILE(SMBreadX);
3290 if (req->wct == 12) {
3291 #ifdef LARGE_SMB_OFF_T
3293 * This is a large offset (64 bit) read.
3295 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
3297 #else /* !LARGE_SMB_OFF_T */
3300 * Ensure we haven't been sent a >32 bit offset.
3303 if(IVAL(req->inbuf,smb_vwv10) != 0) {
3304 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3305 "used and we don't support 64 bit offsets.\n",
3306 (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
3307 END_PROFILE(SMBreadX);
3308 reply_doserror(req, ERRDOS, ERRbadaccess);
3312 #endif /* LARGE_SMB_OFF_T */
3316 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
3317 (SMB_BIG_UINT)startpos, READ_LOCK)) {
3318 END_PROFILE(SMBreadX);
3319 reply_doserror(req, ERRDOS, ERRlock);
3324 && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3325 END_PROFILE(SMBreadX);
3329 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3331 END_PROFILE(SMBreadX);
3335 /****************************************************************************
3336 Error replies to writebraw must have smb_wct == 1. Fix this up.
3337 ****************************************************************************/
3339 void error_to_writebrawerr(struct smb_request *req)
3341 uint8 *old_outbuf = req->outbuf;
3343 reply_outbuf(req, 1, 0);
3345 memcpy(req->outbuf, old_outbuf, smb_size);
3346 TALLOC_FREE(old_outbuf);
3349 /****************************************************************************
3350 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3351 ****************************************************************************/
3353 void reply_writebraw(connection_struct *conn, struct smb_request *req)
3358 ssize_t total_written=0;
3359 size_t numtowrite=0;
3367 START_PROFILE(SMBwritebraw);
3370 * If we ever reply with an error, it must have the SMB command
3371 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3374 SCVAL(req->inbuf,smb_com,SMBwritec);
3376 if (srv_is_signing_active()) {
3377 END_PROFILE(SMBwritebraw);
3378 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3379 "raw reads/writes are disallowed.");
3382 if (req->wct < 12) {
3383 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3384 error_to_writebrawerr(req);
3385 END_PROFILE(SMBwritebraw);
3389 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3390 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3391 error_to_writebrawerr(req);
3392 END_PROFILE(SMBwritebraw);
3396 if (!CHECK_WRITE(fsp)) {
3397 reply_doserror(req, ERRDOS, ERRbadaccess);
3398 error_to_writebrawerr(req);
3399 END_PROFILE(SMBwritebraw);
3403 tcount = IVAL(req->inbuf,smb_vwv1);
3404 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3405 write_through = BITSETW(req->inbuf+smb_vwv7,0);
3407 /* We have to deal with slightly different formats depending
3408 on whether we are using the core+ or lanman1.0 protocol */
3410 if(Protocol <= PROTOCOL_COREPLUS) {
3411 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3412 data = smb_buf(req->inbuf);
3414 numtowrite = SVAL(req->inbuf,smb_vwv10);
3415 data = smb_base(req->inbuf) + SVAL(req->inbuf, smb_vwv11);
3418 /* Ensure we don't write bytes past the end of this packet. */
3419 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3420 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3421 error_to_writebrawerr(req);
3422 END_PROFILE(SMBwritebraw);
3426 if (is_locked(fsp,(uint32)req->smbpid,(SMB_BIG_UINT)tcount,
3427 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3428 reply_doserror(req, ERRDOS, ERRlock);
3429 error_to_writebrawerr(req);
3430 END_PROFILE(SMBwritebraw);
3435 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3438 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3439 "wrote=%d sync=%d\n",
3440 fsp->fnum, (double)startpos, (int)numtowrite,
3441 (int)nwritten, (int)write_through));
3443 if (nwritten < (ssize_t)numtowrite) {
3444 reply_unixerror(req, ERRHRD, ERRdiskfull);
3445 error_to_writebrawerr(req);
3446 END_PROFILE(SMBwritebraw);
3450 total_written = nwritten;
3452 /* Allocate a buffer of 64k + length. */
3453 buf = TALLOC_ARRAY(NULL, char, 65540);
3455 reply_doserror(req, ERRDOS, ERRnomem);
3456 error_to_writebrawerr(req);
3457 END_PROFILE(SMBwritebraw);
3461 /* Return a SMBwritebraw message to the redirector to tell
3462 * it to send more bytes */
3464 memcpy(buf, req->inbuf, smb_size);
3465 outsize = srv_set_message(buf,
3466 Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3467 SCVAL(buf,smb_com,SMBwritebraw);
3468 SSVALS(buf,smb_vwv0,0xFFFF);
3470 if (!srv_send_smb(smbd_server_fd(),
3472 IS_CONN_ENCRYPTED(conn))) {
3473 exit_server_cleanly("reply_writebraw: srv_send_smb "
3477 /* Now read the raw data into the buffer and write it */
3478 if (read_smb_length(smbd_server_fd(),buf,
3479 SMB_SECONDARY_WAIT, get_srv_read_error()) == -1) {
3480 exit_server_cleanly("secondary writebraw failed");
3484 * Even though this is not an smb message,
3485 * smb_len returns the generic length of a packet.
3488 numtowrite = smb_len(buf);
3490 /* Set up outbuf to return the correct size */
3491 reply_outbuf(req, 1, 0);
3493 if (numtowrite != 0) {
3495 if (numtowrite > 0xFFFF) {
3496 DEBUG(0,("reply_writebraw: Oversize secondary write "
3497 "raw requested (%u). Terminating\n",
3498 (unsigned int)numtowrite ));
3499 exit_server_cleanly("secondary writebraw failed");
3502 if (tcount > nwritten+numtowrite) {
3503 DEBUG(3,("reply_writebraw: Client overestimated the "
3505 (int)tcount,(int)nwritten,(int)numtowrite));
3508 if (read_data(smbd_server_fd(), buf+4, numtowrite,get_srv_read_error())
3510 DEBUG(0,("reply_writebraw: Oversize secondary write "
3511 "raw read failed (%s). Terminating\n",
3513 exit_server_cleanly("secondary writebraw failed");
3516 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3517 if (nwritten == -1) {
3519 reply_unixerror(req, ERRHRD, ERRdiskfull);
3520 error_to_writebrawerr(req);
3521 END_PROFILE(SMBwritebraw);
3525 if (nwritten < (ssize_t)numtowrite) {
3526 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3527 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3531 total_written += nwritten;
3536 SSVAL(req->outbuf,smb_vwv0,total_written);
3538 status = sync_file(conn, fsp, write_through);
3539 if (!NT_STATUS_IS_OK(status)) {
3540 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3541 fsp->fsp_name, nt_errstr(status) ));
3542 reply_nterror(req, status);
3543 error_to_writebrawerr(req);
3544 END_PROFILE(SMBwritebraw);
3548 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3550 fsp->fnum, (double)startpos, (int)numtowrite,
3551 (int)total_written));
3553 /* We won't return a status if write through is not selected - this
3554 * follows what WfWg does */
3555 END_PROFILE(SMBwritebraw);
3557 if (!write_through && total_written==tcount) {
3559 #if RABBIT_PELLET_FIX
3561 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3562 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3565 if (!send_keepalive(smbd_server_fd())) {
3566 exit_server_cleanly("reply_writebraw: send of "
3567 "keepalive failed");
3570 TALLOC_FREE(req->outbuf);
3576 #define DBGC_CLASS DBGC_LOCKING
3578 /****************************************************************************
3579 Reply to a writeunlock (core+).
3580 ****************************************************************************/
3582 void reply_writeunlock(connection_struct *conn, struct smb_request *req)
3584 ssize_t nwritten = -1;
3588 NTSTATUS status = NT_STATUS_OK;
3591 START_PROFILE(SMBwriteunlock);
3594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3595 END_PROFILE(SMBwriteunlock);
3599 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3601 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3602 END_PROFILE(SMBwriteunlock);
3606 if (!CHECK_WRITE(fsp)) {
3607 reply_doserror(req, ERRDOS,ERRbadaccess);
3608 END_PROFILE(SMBwriteunlock);
3612 numtowrite = SVAL(req->inbuf,smb_vwv1);
3613 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3614 data = smb_buf(req->inbuf) + 3;
3617 && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3618 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3619 reply_doserror(req, ERRDOS, ERRlock);
3620 END_PROFILE(SMBwriteunlock);
3624 /* The special X/Open SMB protocol handling of
3625 zero length writes is *NOT* done for
3627 if(numtowrite == 0) {
3630 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3633 status = sync_file(conn, fsp, False /* write through */);
3634 if (!NT_STATUS_IS_OK(status)) {
3635 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3636 fsp->fsp_name, nt_errstr(status) ));
3637 reply_nterror(req, status);
3638 END_PROFILE(SMBwriteunlock);
3642 if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
3643 reply_unixerror(req, ERRHRD, ERRdiskfull);
3644 END_PROFILE(SMBwriteunlock);
3649 status = do_unlock(smbd_messaging_context(),
3652 (SMB_BIG_UINT)numtowrite,
3653 (SMB_BIG_UINT)startpos,
3656 if (NT_STATUS_V(status)) {
3657 reply_nterror(req, status);
3658 END_PROFILE(SMBwriteunlock);
3663 reply_outbuf(req, 1, 0);
3665 SSVAL(req->outbuf,smb_vwv0,nwritten);
3667 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3668 fsp->fnum, (int)numtowrite, (int)nwritten));
3670 END_PROFILE(SMBwriteunlock);
3675 #define DBGC_CLASS DBGC_ALL
3677 /****************************************************************************
3679 ****************************************************************************/
3681 void reply_write(connection_struct *conn, struct smb_request *req)
3684 ssize_t nwritten = -1;
3690 START_PROFILE(SMBwrite);
3693 END_PROFILE(SMBwrite);
3694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3698 /* If it's an IPC, pass off the pipe handler. */
3700 reply_pipe_write(req);
3701 END_PROFILE(SMBwrite);
3705 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3707 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3708 END_PROFILE(SMBwrite);
3712 if (!CHECK_WRITE(fsp)) {
3713 reply_doserror(req, ERRDOS, ERRbadaccess);
3714 END_PROFILE(SMBwrite);
3718 numtowrite = SVAL(req->inbuf,smb_vwv1);
3719 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3720 data = smb_buf(req->inbuf) + 3;
3722 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3723 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3724 reply_doserror(req, ERRDOS, ERRlock);
3725 END_PROFILE(SMBwrite);
3730 * X/Open SMB protocol says that if smb_vwv1 is
3731 * zero then the file size should be extended or
3732 * truncated to the size given in smb_vwv[2-3].
3735 if(numtowrite == 0) {
3737 * This is actually an allocate call, and set EOF. JRA.
3739 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3741 reply_nterror(req, NT_STATUS_DISK_FULL);
3742 END_PROFILE(SMBwrite);
3745 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3747 reply_nterror(req, NT_STATUS_DISK_FULL);
3748 END_PROFILE(SMBwrite);
3752 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3754 status = sync_file(conn, fsp, False);
3755 if (!NT_STATUS_IS_OK(status)) {
3756 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3757 fsp->fsp_name, nt_errstr(status) ));
3758 reply_nterror(req, status);
3759 END_PROFILE(SMBwrite);
3763 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3764 reply_unixerror(req, ERRHRD, ERRdiskfull);
3765 END_PROFILE(SMBwrite);
3769 reply_outbuf(req, 1, 0);
3771 SSVAL(req->outbuf,smb_vwv0,nwritten);
3773 if (nwritten < (ssize_t)numtowrite) {
3774 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3775 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3778 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3780 END_PROFILE(SMBwrite);
3784 /****************************************************************************
3785 Ensure a buffer is a valid writeX for recvfile purposes.
3786 ****************************************************************************/
3788 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
3789 (2*14) + /* word count (including bcc) */ \
3792 bool is_valid_writeX_buffer(const uint8_t *inbuf)
3795 connection_struct *conn = NULL;
3796 unsigned int doff = 0;
3797 size_t len = smb_len_large(inbuf);
3799 if (is_encrypted_packet(inbuf)) {
3800 /* Can't do this on encrypted
3805 if (CVAL(inbuf,smb_com) != SMBwriteX) {
3809 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
3810 CVAL(inbuf,smb_wct) != 14) {
3811 DEBUG(10,("is_valid_writeX_buffer: chained or "
3812 "invalid word length.\n"));
3816 conn = conn_find(SVAL(inbuf, smb_tid));
3818 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
3822 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
3825 doff = SVAL(inbuf,smb_vwv11);
3827 numtowrite = SVAL(inbuf,smb_vwv10);
3829 if (len > doff && len - doff > 0xFFFF) {
3830 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
3833 if (numtowrite == 0) {
3834 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
3838 /* Ensure the sizes match up. */
3839 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
3840 /* no pad byte...old smbclient :-( */
3841 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
3843 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
3847 if (len - doff != numtowrite) {
3848 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
3849 "len = %u, doff = %u, numtowrite = %u\n",
3852 (unsigned int)numtowrite ));
3856 DEBUG(10,("is_valid_writeX_buffer: true "
3857 "len = %u, doff = %u, numtowrite = %u\n",
3860 (unsigned int)numtowrite ));
3865 /****************************************************************************
3866 Reply to a write and X.
3867 ****************************************************************************/
3869 void reply_write_and_X(connection_struct *conn, struct smb_request *req)
3876 unsigned int smb_doff;
3877 unsigned int smblen;
3881 START_PROFILE(SMBwriteX);
3883 if ((req->wct != 12) && (req->wct != 14)) {
3884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3885 END_PROFILE(SMBwriteX);
3889 numtowrite = SVAL(req->inbuf,smb_vwv10);
3890 smb_doff = SVAL(req->inbuf,smb_vwv11);
3891 smblen = smb_len(req->inbuf);
3893 if (req->unread_bytes > 0xFFFF ||
3894 (smblen > smb_doff &&
3895 smblen - smb_doff > 0xFFFF)) {
3896 numtowrite |= (((size_t)SVAL(req->inbuf,smb_vwv9))<<16);
3899 if (req->unread_bytes) {
3900 /* Can't do a recvfile write on IPC$ */
3902 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3903 END_PROFILE(SMBwriteX);
3906 if (numtowrite != req->unread_bytes) {
3907 reply_doserror(req, ERRDOS, ERRbadmem);
3908 END_PROFILE(SMBwriteX);
3912 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
3913 smb_doff + numtowrite > smblen) {
3914 reply_doserror(req, ERRDOS, ERRbadmem);
3915 END_PROFILE(SMBwriteX);
3920 /* If it's an IPC, pass off the pipe handler. */
3922 if (req->unread_bytes) {
3923 reply_doserror(req, ERRDOS, ERRbadmem);
3924 END_PROFILE(SMBwriteX);
3927 reply_pipe_write_and_X(req);
3928 END_PROFILE(SMBwriteX);
3932 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3933 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3934 write_through = BITSETW(req->inbuf+smb_vwv7,0);
3936 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3937 END_PROFILE(SMBwriteX);
3941 if (!CHECK_WRITE(fsp)) {
3942 reply_doserror(req, ERRDOS, ERRbadaccess);
3943 END_PROFILE(SMBwriteX);
3947 data = smb_base(req->inbuf) + smb_doff;
3949 if(req->wct == 14) {
3950 #ifdef LARGE_SMB_OFF_T
3952 * This is a large offset (64 bit) write.
3954 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
3956 #else /* !LARGE_SMB_OFF_T */
3959 * Ensure we haven't been sent a >32 bit offset.
3962 if(IVAL(req->inbuf,smb_vwv12) != 0) {
3963 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
3964 "used and we don't support 64 bit offsets.\n",
3965 (unsigned int)IVAL(req->inbuf,smb_vwv12) ));
3966 reply_doserror(req, ERRDOS, ERRbadaccess);
3967 END_PROFILE(SMBwriteX);
3971 #endif /* LARGE_SMB_OFF_T */
3974 if (is_locked(fsp,(uint32)req->smbpid,
3975 (SMB_BIG_UINT)numtowrite,
3976 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3977 reply_doserror(req, ERRDOS, ERRlock);
3978 END_PROFILE(SMBwriteX);
3982 /* X/Open SMB protocol says that, unlike SMBwrite
3983 if the length is zero then NO truncation is
3984 done, just a write of zero. To truncate a file,
3987 if(numtowrite == 0) {
3991 if (req->unread_bytes == 0 &&
3992 schedule_aio_write_and_X(conn, req, fsp, data,
3993 startpos, numtowrite)) {
3994 END_PROFILE(SMBwriteX);
3998 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4001 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4002 reply_unixerror(req, ERRHRD, ERRdiskfull);
4003 END_PROFILE(SMBwriteX);
4007 reply_outbuf(req, 6, 0);
4008 SSVAL(req->outbuf,smb_vwv2,nwritten);
4009 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4011 if (nwritten < (ssize_t)numtowrite) {
4012 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4013 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4016 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4017 fsp->fnum, (int)numtowrite, (int)nwritten));
4019 status = sync_file(conn, fsp, write_through);
4020 if (!NT_STATUS_IS_OK(status)) {
4021 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4022 fsp->fsp_name, nt_errstr(status) ));
4023 reply_nterror(req, status);
4024 END_PROFILE(SMBwriteX);
4028 END_PROFILE(SMBwriteX);
4033 /****************************************************************************
4035 ****************************************************************************/
4037 void reply_lseek(connection_struct *conn, struct smb_request *req)
4044 START_PROFILE(SMBlseek);
4047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4048 END_PROFILE(SMBlseek);
4052 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4054 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4058 flush_write_cache(fsp, SEEK_FLUSH);
4060 mode = SVAL(req->inbuf,smb_vwv1) & 3;
4061 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4062 startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2);
4071 res = fsp->fh->pos + startpos;
4082 if (umode == SEEK_END) {
4083 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
4084 if(errno == EINVAL) {
4085 SMB_OFF_T current_pos = startpos;
4086 SMB_STRUCT_STAT sbuf;
4088 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
4089 reply_unixerror(req, ERRDOS,
4091 END_PROFILE(SMBlseek);
4095 current_pos += sbuf.st_size;
4097 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
4102 reply_unixerror(req, ERRDOS, ERRnoaccess);
4103 END_PROFILE(SMBlseek);
4110 reply_outbuf(req, 2, 0);
4111 SIVAL(req->outbuf,smb_vwv0,res);
4113 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4114 fsp->fnum, (double)startpos, (double)res, mode));
4116 END_PROFILE(SMBlseek);
4120 /****************************************************************************
4122 ****************************************************************************/
4124 void reply_flush(connection_struct *conn, struct smb_request *req)
4129 START_PROFILE(SMBflush);
4132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4136 fnum = SVAL(req->inbuf,smb_vwv0);
4137 fsp = file_fsp(fnum);
4139 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, ¤t_user)) {
4144 file_sync_all(conn);
4146 NTSTATUS status = sync_file(conn, fsp, True);
4147 if (!NT_STATUS_IS_OK(status)) {
4148 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4149 fsp->fsp_name, nt_errstr(status) ));
4150 reply_nterror(req, status);
4151 END_PROFILE(SMBflush);
4156 reply_outbuf(req, 0, 0);
4158 DEBUG(3,("flush\n"));
4159 END_PROFILE(SMBflush);
4163 /****************************************************************************
4165 conn POINTER CAN BE NULL HERE !
4166 ****************************************************************************/
4168 void reply_exit(connection_struct *conn, struct smb_request *req)
4170 START_PROFILE(SMBexit);
4172 file_close_pid(req->smbpid, req->vuid);
4174 reply_outbuf(req, 0, 0);
4176 DEBUG(3,("exit\n"));
4178 END_PROFILE(SMBexit);
4182 /****************************************************************************
4183 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4184 ****************************************************************************/
4186 void reply_close(connection_struct *conn, struct smb_request *req)
4188 NTSTATUS status = NT_STATUS_OK;
4189 files_struct *fsp = NULL;
4190 START_PROFILE(SMBclose);
4193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4194 END_PROFILE(SMBclose);
4198 /* If it's an IPC, pass off to the pipe handler. */
4200 reply_pipe_close(conn, req);
4201 END_PROFILE(SMBclose);
4205 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4208 * We can only use CHECK_FSP if we know it's not a directory.
4211 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
4212 reply_doserror(req, ERRDOS, ERRbadfid);
4213 END_PROFILE(SMBclose);
4217 if(fsp->is_directory) {
4219 * Special case - close NT SMB directory handle.
4221 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4222 status = close_file(fsp,NORMAL_CLOSE);
4225 * Close ordinary file.
4228 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4229 fsp->fh->fd, fsp->fnum,
4230 conn->num_files_open));
4233 * Take care of any time sent in the close.
4236 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
4237 srv_make_unix_date3(
4238 req->inbuf+smb_vwv1)));
4241 * close_file() returns the unix errno if an error
4242 * was detected on close - normally this is due to
4243 * a disk full error. If not then it was probably an I/O error.
4246 status = close_file(fsp,NORMAL_CLOSE);
4249 if (!NT_STATUS_IS_OK(status)) {
4250 reply_nterror(req, status);
4251 END_PROFILE(SMBclose);
4255 reply_outbuf(req, 0, 0);
4256 END_PROFILE(SMBclose);
4260 /****************************************************************************
4261 Reply to a writeclose (Core+ protocol).
4262 ****************************************************************************/
4264 void reply_writeclose(connection_struct *conn, struct smb_request *req)
4267 ssize_t nwritten = -1;
4268 NTSTATUS close_status = NT_STATUS_OK;
4271 struct timespec mtime;
4274 START_PROFILE(SMBwriteclose);
4277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4278 END_PROFILE(SMBwriteclose);
4282 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4284 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4285 END_PROFILE(SMBwriteclose);
4288 if (!CHECK_WRITE(fsp)) {
4289 reply_doserror(req, ERRDOS,ERRbadaccess);
4290 END_PROFILE(SMBwriteclose);
4294 numtowrite = SVAL(req->inbuf,smb_vwv1);
4295 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
4296 mtime = convert_time_t_to_timespec(srv_make_unix_date3(
4297 req->inbuf+smb_vwv4));
4298 data = smb_buf(req->inbuf) + 1;
4301 && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
4302 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
4303 reply_doserror(req, ERRDOS,ERRlock);
4304 END_PROFILE(SMBwriteclose);
4308 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4310 set_filetime(conn, fsp->fsp_name, mtime);
4313 * More insanity. W2K only closes the file if writelen > 0.
4318 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4320 close_status = close_file(fsp,NORMAL_CLOSE);
4323 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4324 fsp->fnum, (int)numtowrite, (int)nwritten,
4325 conn->num_files_open));
4327 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4328 reply_doserror(req, ERRHRD, ERRdiskfull);
4329 END_PROFILE(SMBwriteclose);
4333 if(!NT_STATUS_IS_OK(close_status)) {
4334 reply_nterror(req, close_status);
4335 END_PROFILE(SMBwriteclose);
4339 reply_outbuf(req, 1, 0);
4341 SSVAL(req->outbuf,smb_vwv0,nwritten);
4342 END_PROFILE(SMBwriteclose);
4347 #define DBGC_CLASS DBGC_LOCKING
4349 /****************************************************************************
4351 ****************************************************************************/
4353 void reply_lock(connection_struct *conn, struct smb_request *req)
4355 SMB_BIG_UINT count,offset;
4358 struct byte_range_lock *br_lck = NULL;
4360 START_PROFILE(SMBlock);
4363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4364 END_PROFILE(SMBlock);
4368 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4370 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4371 END_PROFILE(SMBlock);
4375 release_level_2_oplocks_on_change(fsp);
4377 count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4378 offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4380 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4381 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4383 br_lck = do_lock(smbd_messaging_context(),
4390 False, /* Non-blocking lock. */
4394 TALLOC_FREE(br_lck);
4396 if (NT_STATUS_V(status)) {
4397 reply_nterror(req, status);
4398 END_PROFILE(SMBlock);
4402 reply_outbuf(req, 0, 0);
4404 END_PROFILE(SMBlock);
4408 /****************************************************************************
4410 ****************************************************************************/
4412 void reply_unlock(connection_struct *conn, struct smb_request *req)
4414 SMB_BIG_UINT count,offset;
4418 START_PROFILE(SMBunlock);
4421 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4422 END_PROFILE(SMBunlock);
4426 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4428 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4429 END_PROFILE(SMBunlock);
4433 count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4434 offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4436 status = do_unlock(smbd_messaging_context(),
4443 if (NT_STATUS_V(status)) {
4444 reply_nterror(req, status);
4445 END_PROFILE(SMBunlock);
4449 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4450 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4452 reply_outbuf(req, 0, 0);
4454 END_PROFILE(SMBunlock);
4459 #define DBGC_CLASS DBGC_ALL
4461 /****************************************************************************
4463 conn POINTER CAN BE NULL HERE !
4464 ****************************************************************************/
4466 void reply_tdis(connection_struct *conn, struct smb_request *req)
4468 START_PROFILE(SMBtdis);
4471 DEBUG(4,("Invalid connection in tdis\n"));
4472 reply_doserror(req, ERRSRV, ERRinvnid);
4473 END_PROFILE(SMBtdis);
4479 close_cnum(conn,req->vuid);
4482 reply_outbuf(req, 0, 0);
4483 END_PROFILE(SMBtdis);
4487 /****************************************************************************
4489 conn POINTER CAN BE NULL HERE !
4490 ****************************************************************************/
4492 void reply_echo(connection_struct *conn, struct smb_request *req)
4496 unsigned int data_len = smb_buflen(req->inbuf);
4498 START_PROFILE(SMBecho);
4501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4502 END_PROFILE(SMBecho);
4506 if (data_len > BUFFER_SIZE) {
4507 DEBUG(0,("reply_echo: data_len too large.\n"));
4508 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
4509 END_PROFILE(SMBecho);
4513 smb_reverb = SVAL(req->inbuf,smb_vwv0);
4515 reply_outbuf(req, 1, data_len);
4517 /* copy any incoming data back out */
4519 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
4522 if (smb_reverb > 100) {
4523 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4527 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4528 SSVAL(req->outbuf,smb_vwv0,seq_num);
4530 show_msg((char *)req->outbuf);
4531 if (!srv_send_smb(smbd_server_fd(),
4532 (char *)req->outbuf,
4533 IS_CONN_ENCRYPTED(conn)||req->encrypted))
4534 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4537 DEBUG(3,("echo %d times\n", smb_reverb));
4539 TALLOC_FREE(req->outbuf);
4543 END_PROFILE(SMBecho);
4547 /****************************************************************************
4548 Reply to a printopen.
4549 ****************************************************************************/
4551 void reply_printopen(connection_struct *conn, struct smb_request *req)
4556 START_PROFILE(SMBsplopen);
4559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4560 END_PROFILE(SMBsplopen);
4564 if (!CAN_PRINT(conn)) {
4565 reply_doserror(req, ERRDOS, ERRnoaccess);
4566 END_PROFILE(SMBsplopen);
4570 /* Open for exclusive use, write only. */
4571 status = print_fsp_open(conn, NULL, &fsp);
4573 if (!NT_STATUS_IS_OK(status)) {
4574 reply_nterror(req, status);
4575 END_PROFILE(SMBsplopen);
4579 reply_outbuf(req, 1, 0);
4580 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4582 DEBUG(3,("openprint fd=%d fnum=%d\n",
4583 fsp->fh->fd, fsp->fnum));
4585 END_PROFILE(SMBsplopen);
4589 /****************************************************************************
4590 Reply to a printclose.
4591 ****************************************************************************/
4593 void reply_printclose(connection_struct *conn, struct smb_request *req)
4598 START_PROFILE(SMBsplclose);
4601 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4602 END_PROFILE(SMBsplclose);
4606 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4608 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4609 END_PROFILE(SMBsplclose);
4613 if (!CAN_PRINT(conn)) {
4614 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4615 END_PROFILE(SMBsplclose);
4619 DEBUG(3,("printclose fd=%d fnum=%d\n",
4620 fsp->fh->fd,fsp->fnum));
4622 status = close_file(fsp,NORMAL_CLOSE);
4624 if(!NT_STATUS_IS_OK(status)) {
4625 reply_nterror(req, status);
4626 END_PROFILE(SMBsplclose);
4630 END_PROFILE(SMBsplclose);
4634 /****************************************************************************
4635 Reply to a printqueue.
4636 ****************************************************************************/
4638 void reply_printqueue(connection_struct *conn, struct smb_request *req)
4643 START_PROFILE(SMBsplretq);
4646 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4647 END_PROFILE(SMBsplretq);
4651 max_count = SVAL(req->inbuf,smb_vwv0);
4652 start_index = SVAL(req->inbuf,smb_vwv1);
4654 /* we used to allow the client to get the cnum wrong, but that
4655 is really quite gross and only worked when there was only
4656 one printer - I think we should now only accept it if they
4657 get it right (tridge) */
4658 if (!CAN_PRINT(conn)) {
4659 reply_doserror(req, ERRDOS, ERRnoaccess);
4660 END_PROFILE(SMBsplretq);
4664 reply_outbuf(req, 2, 3);
4665 SSVAL(req->outbuf,smb_vwv0,0);
4666 SSVAL(req->outbuf,smb_vwv1,0);
4667 SCVAL(smb_buf(req->outbuf),0,1);
4668 SSVAL(smb_buf(req->outbuf),1,0);
4670 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4671 start_index, max_count));
4674 print_queue_struct *queue = NULL;
4675 print_status_struct status;
4676 int count = print_queue_status(SNUM(conn), &queue, &status);
4677 int num_to_get = ABS(max_count);
4678 int first = (max_count>0?start_index:start_index+max_count+1);
4684 num_to_get = MIN(num_to_get,count-first);
4687 for (i=first;i<first+num_to_get;i++) {
4691 srv_put_dos_date2(p,0,queue[i].time);
4692 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4693 SSVAL(p,5, queue[i].job);
4694 SIVAL(p,7,queue[i].size);
4696 srvstr_push(blob, req->flags2, p+12,
4697 queue[i].fs_user, 16, STR_ASCII);
4699 if (message_push_blob(
4702 blob, sizeof(blob))) == -1) {
4703 reply_nterror(req, NT_STATUS_NO_MEMORY);
4704 END_PROFILE(SMBsplretq);
4710 SSVAL(req->outbuf,smb_vwv0,count);
4711 SSVAL(req->outbuf,smb_vwv1,
4712 (max_count>0?first+count:first-1));
4713 SCVAL(smb_buf(req->outbuf),0,1);
4714 SSVAL(smb_buf(req->outbuf),1,28*count);
4719 DEBUG(3,("%d entries returned in queue\n",count));
4722 END_PROFILE(SMBsplretq);
4726 /****************************************************************************
4727 Reply to a printwrite.
4728 ****************************************************************************/
4730 void reply_printwrite(connection_struct *conn, struct smb_request *req)
4736 START_PROFILE(SMBsplwr);
4739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4740 END_PROFILE(SMBsplwr);
4744 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4746 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4747 END_PROFILE(SMBsplwr);
4751 if (!CAN_PRINT(conn)) {
4752 reply_doserror(req, ERRDOS, ERRnoaccess);
4753 END_PROFILE(SMBsplwr);
4757 if (!CHECK_WRITE(fsp)) {
4758 reply_doserror(req, ERRDOS, ERRbadaccess);
4759 END_PROFILE(SMBsplwr);
4763 numtowrite = SVAL(smb_buf(req->inbuf),1);
4765 if (smb_buflen(req->inbuf) < numtowrite + 3) {
4766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4767 END_PROFILE(SMBsplwr);
4771 data = smb_buf(req->inbuf) + 3;
4773 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
4774 reply_unixerror(req, ERRHRD, ERRdiskfull);
4775 END_PROFILE(SMBsplwr);
4779 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4781 END_PROFILE(SMBsplwr);
4785 /****************************************************************************
4787 ****************************************************************************/
4789 void reply_mkdir(connection_struct *conn, struct smb_request *req)
4791 char *directory = NULL;
4793 SMB_STRUCT_STAT sbuf;
4794 TALLOC_CTX *ctx = talloc_tos();
4796 START_PROFILE(SMBmkdir);
4798 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
4799 smb_buf(req->inbuf) + 1, 0,
4800 STR_TERMINATE, &status);
4801 if (!NT_STATUS_IS_OK(status)) {
4802 reply_nterror(req, status);
4803 END_PROFILE(SMBmkdir);
4807 status = resolve_dfspath(ctx, conn,
4808 req->flags2 & FLAGS2_DFS_PATHNAMES,
4811 if (!NT_STATUS_IS_OK(status)) {
4812 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4813 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4814 ERRSRV, ERRbadpath);
4815 END_PROFILE(SMBmkdir);
4818 reply_nterror(req, status);
4819 END_PROFILE(SMBmkdir);
4823 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
4824 if (!NT_STATUS_IS_OK(status)) {
4825 reply_nterror(req, status);
4826 END_PROFILE(SMBmkdir);
4830 status = check_name(conn, directory);
4831 if (!NT_STATUS_IS_OK(status)) {
4832 reply_nterror(req, status);
4833 END_PROFILE(SMBmkdir);
4837 status = create_directory(conn, req, directory);
4839 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4841 if (!NT_STATUS_IS_OK(status)) {
4843 if (!use_nt_status()
4844 && NT_STATUS_EQUAL(status,
4845 NT_STATUS_OBJECT_NAME_COLLISION)) {
4847 * Yes, in the DOS error code case we get a
4848 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4849 * samba4 torture test.
4851 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4854 reply_nterror(req, status);
4855 END_PROFILE(SMBmkdir);
4859 reply_outbuf(req, 0, 0);
4861 DEBUG( 3, ( "mkdir %s\n", directory ) );
4863 END_PROFILE(SMBmkdir);
4867 /****************************************************************************
4868 Static function used by reply_rmdir to delete an entire directory
4869 tree recursively. Return True on ok, False on fail.
4870 ****************************************************************************/
4872 static bool recursive_rmdir(TALLOC_CTX *ctx,
4873 connection_struct *conn,
4876 const char *dname = NULL;
4879 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4884 while((dname = ReadDirName(dir_hnd, &offset))) {
4885 char *fullname = NULL;
4888 if (ISDOT(dname) || ISDOTDOT(dname)) {
4892 if (!is_visible_file(conn, directory, dname, &st, False)) {
4896 /* Construct the full name. */
4897 fullname = talloc_asprintf(ctx,
4907 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4912 if(st.st_mode & S_IFDIR) {
4913 if(!recursive_rmdir(ctx, conn, fullname)) {
4917 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4921 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4925 TALLOC_FREE(fullname);
4931 /****************************************************************************
4932 The internals of the rmdir code - called elsewhere.
4933 ****************************************************************************/
4935 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
4936 connection_struct *conn,
4937 const char *directory)
4942 /* Might be a symlink. */
4943 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4944 return map_nt_error_from_unix(errno);
4947 if (S_ISLNK(st.st_mode)) {
4948 /* Is what it points to a directory ? */
4949 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4950 return map_nt_error_from_unix(errno);
4952 if (!(S_ISDIR(st.st_mode))) {
4953 return NT_STATUS_NOT_A_DIRECTORY;
4955 ret = SMB_VFS_UNLINK(conn,directory);
4957 ret = SMB_VFS_RMDIR(conn,directory);
4960 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4961 FILE_NOTIFY_CHANGE_DIR_NAME,
4963 return NT_STATUS_OK;
4966 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4968 * Check to see if the only thing in this directory are
4969 * vetoed files/directories. If so then delete them and
4970 * retry. If we fail to delete any of them (and we *don't*
4971 * do a recursive delete) then fail the rmdir.
4975 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4977 if(dir_hnd == NULL) {
4982 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4983 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4985 if (!is_visible_file(conn, directory, dname, &st, False))
4987 if(!IS_VETO_PATH(conn, dname)) {
4994 /* We only have veto files/directories. Recursive delete. */
4996 RewindDir(dir_hnd,&dirpos);
4997 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4998 char *fullname = NULL;
5000 if (ISDOT(dname) || ISDOTDOT(dname)) {
5003 if (!is_visible_file(conn, directory, dname, &st, False)) {
5007 fullname = talloc_asprintf(ctx,
5017 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
5020 if(st.st_mode & S_IFDIR) {
5021 if(lp_recursive_veto_delete(SNUM(conn))) {
5022 if(!recursive_rmdir(ctx, conn, fullname))
5025 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
5028 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
5031 TALLOC_FREE(fullname);
5034 /* Retry the rmdir */
5035 ret = SMB_VFS_RMDIR(conn,directory);
5041 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5042 "%s\n", directory,strerror(errno)));
5043 return map_nt_error_from_unix(errno);
5046 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5047 FILE_NOTIFY_CHANGE_DIR_NAME,
5050 return NT_STATUS_OK;
5053 /****************************************************************************
5055 ****************************************************************************/
5057 void reply_rmdir(connection_struct *conn, struct smb_request *req)
5059 char *directory = NULL;
5060 SMB_STRUCT_STAT sbuf;
5062 TALLOC_CTX *ctx = talloc_tos();
5064 START_PROFILE(SMBrmdir);
5066 srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
5067 smb_buf(req->inbuf) + 1, 0,
5068 STR_TERMINATE, &status);
5069 if (!NT_STATUS_IS_OK(status)) {
5070 reply_nterror(req, status);
5071 END_PROFILE(SMBrmdir);
5075 status = resolve_dfspath(ctx, conn,
5076 req->flags2 & FLAGS2_DFS_PATHNAMES,
5079 if (!NT_STATUS_IS_OK(status)) {
5080 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5081 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5082 ERRSRV, ERRbadpath);
5083 END_PROFILE(SMBrmdir);
5086 reply_nterror(req, status);
5087 END_PROFILE(SMBrmdir);
5091 status = unix_convert(ctx, conn, directory, False, &directory,
5093 if (!NT_STATUS_IS_OK(status)) {
5094 reply_nterror(req, status);
5095 END_PROFILE(SMBrmdir);
5099 status = check_name(conn, directory);
5100 if (!NT_STATUS_IS_OK(status)) {
5101 reply_nterror(req, status);
5102 END_PROFILE(SMBrmdir);
5106 dptr_closepath(directory, req->smbpid);
5107 status = rmdir_internals(ctx, conn, directory);
5108 if (!NT_STATUS_IS_OK(status)) {
5109 reply_nterror(req, status);
5110 END_PROFILE(SMBrmdir);
5114 reply_outbuf(req, 0, 0);
5116 DEBUG( 3, ( "rmdir %s\n", directory ) );
5118 END_PROFILE(SMBrmdir);
5122 /*******************************************************************
5123 Resolve wildcards in a filename rename.
5124 ********************************************************************/
5126 static bool resolve_wildcards(TALLOC_CTX *ctx,
5131 char *name2_copy = NULL;
5136 char *p,*p2, *pname1, *pname2;
5138 name2_copy = talloc_strdup(ctx, name2);
5143 pname1 = strrchr_m(name1,'/');
5144 pname2 = strrchr_m(name2_copy,'/');
5146 if (!pname1 || !pname2) {
5150 /* Truncate the copy of name2 at the last '/' */
5153 /* Now go past the '/' */
5157 root1 = talloc_strdup(ctx, pname1);
5158 root2 = talloc_strdup(ctx, pname2);
5160 if (!root1 || !root2) {
5164 p = strrchr_m(root1,'.');
5167 ext1 = talloc_strdup(ctx, p+1);
5169 ext1 = talloc_strdup(ctx, "");
5171 p = strrchr_m(root2,'.');
5174 ext2 = talloc_strdup(ctx, p+1);
5176 ext2 = talloc_strdup(ctx, "");
5179 if (!ext1 || !ext2) {
5187 /* Hmmm. Should this be mb-aware ? */
5190 } else if (*p2 == '*') {
5192 root2 = talloc_asprintf(ctx, "%s%s",
5211 /* Hmmm. Should this be mb-aware ? */
5214 } else if (*p2 == '*') {
5216 ext2 = talloc_asprintf(ctx, "%s%s",
5232 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5237 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5249 /****************************************************************************
5250 Ensure open files have their names updated. Updated to notify other smbd's
5252 ****************************************************************************/
5254 static void rename_open_files(connection_struct *conn,
5255 struct share_mode_lock *lck,
5256 const char *newname)
5259 bool did_rename = False;
5261 for(fsp = file_find_di_first(lck->id); fsp;
5262 fsp = file_find_di_next(fsp)) {
5263 /* fsp_name is a relative path under the fsp. To change this for other
5264 sharepaths we need to manipulate relative paths. */
5265 /* TODO - create the absolute path and manipulate the newname
5266 relative to the sharepath. */
5267 if (fsp->conn != conn) {
5270 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
5271 fsp->fnum, file_id_string_tos(&fsp->file_id),
5272 fsp->fsp_name, newname ));
5273 string_set(&fsp->fsp_name, newname);
5278 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
5279 file_id_string_tos(&lck->id), newname ));
5282 /* Send messages to all smbd's (not ourself) that the name has changed. */
5283 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5287 /****************************************************************************
5288 We need to check if the source path is a parent directory of the destination
5289 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5290 refuse the rename with a sharing violation. Under UNIX the above call can
5291 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5292 probably need to check that the client is a Windows one before disallowing
5293 this as a UNIX client (one with UNIX extensions) can know the source is a
5294 symlink and make this decision intelligently. Found by an excellent bug
5295 report from <AndyLiebman@aol.com>.
5296 ****************************************************************************/
5298 static bool rename_path_prefix_equal(const char *src, const char *dest)
5300 const char *psrc = src;
5301 const char *pdst = dest;
5304 if (psrc[0] == '.' && psrc[1] == '/') {
5307 if (pdst[0] == '.' && pdst[1] == '/') {
5310 if ((slen = strlen(psrc)) > strlen(pdst)) {
5313 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5317 * Do the notify calls from a rename
5320 static void notify_rename(connection_struct *conn, bool is_dir,
5321 const char *oldpath, const char *newpath)
5323 char *olddir, *newdir;
5324 const char *oldname, *newname;
5327 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5328 : FILE_NOTIFY_CHANGE_FILE_NAME;
5330 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
5331 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
5332 TALLOC_FREE(olddir);
5336 if (strcmp(olddir, newdir) == 0) {
5337 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5338 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5341 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5342 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5344 TALLOC_FREE(olddir);
5345 TALLOC_FREE(newdir);
5347 /* this is a strange one. w2k3 gives an additional event for
5348 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5349 files, but not directories */
5351 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5352 FILE_NOTIFY_CHANGE_ATTRIBUTES
5353 |FILE_NOTIFY_CHANGE_CREATION,
5358 /****************************************************************************
5359 Rename an open file - given an fsp.
5360 ****************************************************************************/
5362 NTSTATUS rename_internals_fsp(connection_struct *conn,
5365 const char *newname_last_component,
5367 bool replace_if_exists)
5369 TALLOC_CTX *ctx = talloc_tos();
5370 SMB_STRUCT_STAT sbuf, sbuf1;
5371 NTSTATUS status = NT_STATUS_OK;
5372 struct share_mode_lock *lck = NULL;
5377 status = check_name(conn, newname);
5378 if (!NT_STATUS_IS_OK(status)) {
5382 /* Ensure newname contains a '/' */
5383 if(strrchr_m(newname,'/') == 0) {
5384 newname = talloc_asprintf(ctx,
5388 return NT_STATUS_NO_MEMORY;
5393 * Check for special case with case preserving and not
5394 * case sensitive. If the old last component differs from the original
5395 * last component only by case, then we should allow
5396 * the rename (user is trying to change the case of the
5400 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5401 strequal(newname, fsp->fsp_name)) {
5403 char *newname_modified_last_component = NULL;
5406 * Get the last component of the modified name.
5407 * Note that we guarantee that newname contains a '/'
5410 p = strrchr_m(newname,'/');
5411 newname_modified_last_component = talloc_strdup(ctx,
5413 if (!newname_modified_last_component) {
5414 return NT_STATUS_NO_MEMORY;
5417 if(strcsequal(newname_modified_last_component,
5418 newname_last_component) == False) {
5420 * Replace the modified last component with
5423 *p = '\0'; /* Truncate at the '/' */
5424 newname = talloc_asprintf(ctx,
5427 newname_last_component);
5432 * If the src and dest names are identical - including case,
5433 * don't do the rename, just return success.
5436 if (strcsequal(fsp->fsp_name, newname)) {
5437 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5439 return NT_STATUS_OK;
5443 * Have vfs_object_exist also fill sbuf1
5445 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5447 if(!replace_if_exists && dst_exists) {
5448 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5449 fsp->fsp_name,newname));
5450 return NT_STATUS_OBJECT_NAME_COLLISION;
5454 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5455 files_struct *dst_fsp = file_find_di_first(fileid);
5457 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5458 return NT_STATUS_ACCESS_DENIED;
5462 /* Ensure we have a valid stat struct for the source. */
5463 if (fsp->fh->fd != -1) {
5464 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
5465 return map_nt_error_from_unix(errno);
5468 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5469 return map_nt_error_from_unix(errno);
5473 status = can_rename(conn, fsp, attrs, &sbuf);
5475 if (!NT_STATUS_IS_OK(status)) {
5476 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5477 nt_errstr(status), fsp->fsp_name,newname));
5478 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5479 status = NT_STATUS_ACCESS_DENIED;
5483 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5484 return NT_STATUS_ACCESS_DENIED;
5487 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
5490 * We have the file open ourselves, so not being able to get the
5491 * corresponding share mode lock is a fatal error.
5494 SMB_ASSERT(lck != NULL);
5496 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5497 uint32 create_options = fsp->fh->private_options;
5499 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5500 fsp->fsp_name,newname));
5502 rename_open_files(conn, lck, newname);
5504 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5507 * A rename acts as a new file create w.r.t. allowing an initial delete
5508 * on close, probably because in Windows there is a new handle to the
5509 * new file. If initial delete on close was requested but not
5510 * originally set, we need to set it here. This is probably not 100% correct,
5511 * but will work for the CIFSFS client which in non-posix mode
5512 * depends on these semantics. JRA.
5515 set_allow_initial_delete_on_close(lck, fsp, True);
5517 if (create_options & FILE_DELETE_ON_CLOSE) {
5518 status = can_set_delete_on_close(fsp, True, 0);
5520 if (NT_STATUS_IS_OK(status)) {
5521 /* Note that here we set the *inital* delete on close flag,
5522 * not the regular one. The magic gets handled in close. */
5523 fsp->initial_delete_on_close = True;
5527 return NT_STATUS_OK;
5532 if (errno == ENOTDIR || errno == EISDIR) {
5533 status = NT_STATUS_OBJECT_NAME_COLLISION;
5535 status = map_nt_error_from_unix(errno);
5538 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5539 nt_errstr(status), fsp->fsp_name,newname));
5544 /****************************************************************************
5545 The guts of the rename command, split out so it may be called by the NT SMB
5547 ****************************************************************************/
5549 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5550 connection_struct *conn,
5551 struct smb_request *req,
5552 const char *name_in,
5553 const char *newname_in,
5555 bool replace_if_exists,
5559 char *directory = NULL;
5561 char *last_component_src = NULL;
5562 char *last_component_dest = NULL;
5564 char *newname = NULL;
5567 NTSTATUS status = NT_STATUS_OK;
5568 SMB_STRUCT_STAT sbuf1, sbuf2;
5569 struct smb_Dir *dir_hnd = NULL;
5576 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5577 &last_component_src, &sbuf1);
5578 if (!NT_STATUS_IS_OK(status)) {
5582 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5583 &last_component_dest, &sbuf2);
5584 if (!NT_STATUS_IS_OK(status)) {
5589 * Split the old name into directory and last component
5590 * strings. Note that unix_convert may have stripped off a
5591 * leading ./ from both name and newname if the rename is
5592 * at the root of the share. We need to make sure either both
5593 * name and newname contain a / character or neither of them do
5594 * as this is checked in resolve_wildcards().
5597 p = strrchr_m(name,'/');
5599 directory = talloc_strdup(ctx, ".");
5601 return NT_STATUS_NO_MEMORY;
5606 directory = talloc_strdup(ctx, name);
5608 return NT_STATUS_NO_MEMORY;
5611 *p = '/'; /* Replace needed for exceptional test below. */
5615 * We should only check the mangled cache
5616 * here if unix_convert failed. This means
5617 * that the path in 'mask' doesn't exist
5618 * on the file system and so we need to look
5619 * for a possible mangle. This patch from
5620 * Tine Smukavec <valentin.smukavec@hermes.si>.
5623 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5624 char *new_mask = NULL;
5625 mangle_lookup_name_from_8_3(ctx,
5634 if (!src_has_wild) {
5638 * No wildcards - just process the one file.
5640 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5642 /* Add a terminating '/' to the directory name. */
5643 directory = talloc_asprintf_append(directory,
5647 return NT_STATUS_NO_MEMORY;
5650 /* Ensure newname contains a '/' also */
5651 if(strrchr_m(newname,'/') == 0) {
5652 newname = talloc_asprintf(ctx,
5656 return NT_STATUS_NO_MEMORY;
5660 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5661 "case_preserve = %d, short case preserve = %d, "
5662 "directory = %s, newname = %s, "
5663 "last_component_dest = %s, is_8_3 = %d\n",
5664 conn->case_sensitive, conn->case_preserve,
5665 conn->short_case_preserve, directory,
5666 newname, last_component_dest, is_short_name));
5668 /* The dest name still may have wildcards. */
5669 if (dest_has_wild) {
5670 char *mod_newname = NULL;
5671 if (!resolve_wildcards(ctx,
5672 directory,newname,&mod_newname)) {
5673 DEBUG(6, ("rename_internals: resolve_wildcards "
5677 return NT_STATUS_NO_MEMORY;
5679 newname = mod_newname;
5683 SMB_VFS_STAT(conn, directory, &sbuf1);
5685 status = S_ISDIR(sbuf1.st_mode) ?
5686 open_directory(conn, req, directory, &sbuf1,
5688 FILE_SHARE_READ|FILE_SHARE_WRITE,
5689 FILE_OPEN, 0, 0, NULL,
5691 : open_file_ntcreate(conn, req, directory, &sbuf1,
5693 FILE_SHARE_READ|FILE_SHARE_WRITE,
5694 FILE_OPEN, 0, 0, 0, NULL,
5697 if (!NT_STATUS_IS_OK(status)) {
5698 DEBUG(3, ("Could not open rename source %s: %s\n",
5699 directory, nt_errstr(status)));
5703 status = rename_internals_fsp(conn, fsp, newname,
5704 last_component_dest,
5705 attrs, replace_if_exists);
5707 close_file(fsp, NORMAL_CLOSE);
5709 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5710 nt_errstr(status), directory,newname));
5716 * Wildcards - process each file that matches.
5718 if (strequal(mask,"????????.???")) {
5723 status = check_name(conn, directory);
5724 if (!NT_STATUS_IS_OK(status)) {
5728 dir_hnd = OpenDir(conn, directory, mask, attrs);
5729 if (dir_hnd == NULL) {
5730 return map_nt_error_from_unix(errno);
5733 status = NT_STATUS_NO_SUCH_FILE;
5735 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5736 * - gentest fix. JRA
5739 while ((dname = ReadDirName(dir_hnd, &offset))) {
5740 files_struct *fsp = NULL;
5742 char *destname = NULL;
5743 bool sysdir_entry = False;
5745 /* Quick check for "." and ".." */
5746 if (ISDOT(dname) || ISDOTDOT(dname)) {
5748 sysdir_entry = True;
5754 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5758 if(!mask_match(dname, mask, conn->case_sensitive)) {
5763 status = NT_STATUS_OBJECT_NAME_INVALID;
5767 fname = talloc_asprintf(ctx,
5772 return NT_STATUS_NO_MEMORY;
5775 if (!resolve_wildcards(ctx,
5776 fname,newname,&destname)) {
5777 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5783 return NT_STATUS_NO_MEMORY;
5787 SMB_VFS_STAT(conn, fname, &sbuf1);
5789 status = S_ISDIR(sbuf1.st_mode) ?
5790 open_directory(conn, req, fname, &sbuf1,
5792 FILE_SHARE_READ|FILE_SHARE_WRITE,
5793 FILE_OPEN, 0, 0, NULL,
5795 : open_file_ntcreate(conn, req, fname, &sbuf1,
5797 FILE_SHARE_READ|FILE_SHARE_WRITE,
5798 FILE_OPEN, 0, 0, 0, NULL,
5801 if (!NT_STATUS_IS_OK(status)) {
5802 DEBUG(3,("rename_internals: open_file_ntcreate "
5803 "returned %s rename %s -> %s\n",
5804 nt_errstr(status), directory, newname));
5808 status = rename_internals_fsp(conn, fsp, destname, dname,
5809 attrs, replace_if_exists);
5811 close_file(fsp, NORMAL_CLOSE);
5813 if (!NT_STATUS_IS_OK(status)) {
5814 DEBUG(3, ("rename_internals_fsp returned %s for "
5815 "rename %s -> %s\n", nt_errstr(status),
5816 directory, newname));
5822 DEBUG(3,("rename_internals: doing rename on %s -> "
5823 "%s\n",fname,destname));
5826 TALLOC_FREE(destname);
5830 if (count == 0 && NT_STATUS_IS_OK(status)) {
5831 status = map_nt_error_from_unix(errno);
5837 /****************************************************************************
5839 ****************************************************************************/
5841 void reply_mv(connection_struct *conn, struct smb_request *req)
5844 char *newname = NULL;
5848 bool src_has_wcard = False;
5849 bool dest_has_wcard = False;
5850 TALLOC_CTX *ctx = talloc_tos();
5852 START_PROFILE(SMBmv);
5855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5860 attrs = SVAL(req->inbuf,smb_vwv0);
5862 p = smb_buf(req->inbuf) + 1;
5863 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
5864 0, STR_TERMINATE, &status,
5866 if (!NT_STATUS_IS_OK(status)) {
5867 reply_nterror(req, status);
5872 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
5873 0, STR_TERMINATE, &status,
5875 if (!NT_STATUS_IS_OK(status)) {
5876 reply_nterror(req, status);
5881 status = resolve_dfspath_wcard(ctx, conn,
5882 req->flags2 & FLAGS2_DFS_PATHNAMES,
5886 if (!NT_STATUS_IS_OK(status)) {
5887 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5888 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5889 ERRSRV, ERRbadpath);
5893 reply_nterror(req, status);
5898 status = resolve_dfspath_wcard(ctx, conn,
5899 req->flags2 & FLAGS2_DFS_PATHNAMES,
5903 if (!NT_STATUS_IS_OK(status)) {
5904 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5905 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5906 ERRSRV, ERRbadpath);
5910 reply_nterror(req, status);
5915 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5917 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
5918 src_has_wcard, dest_has_wcard);
5919 if (!NT_STATUS_IS_OK(status)) {
5920 if (open_was_deferred(req->mid)) {
5921 /* We have re-scheduled this call. */
5925 reply_nterror(req, status);
5930 reply_outbuf(req, 0, 0);
5936 /*******************************************************************
5937 Copy a file as part of a reply_copy.
5938 ******************************************************************/
5941 * TODO: check error codes on all callers
5944 NTSTATUS copy_file(TALLOC_CTX *ctx,
5945 connection_struct *conn,
5950 bool target_is_directory)
5952 SMB_STRUCT_STAT src_sbuf, sbuf2;
5954 files_struct *fsp1,*fsp2;
5957 uint32 new_create_disposition;
5960 dest = talloc_strdup(ctx, dest1);
5962 return NT_STATUS_NO_MEMORY;
5964 if (target_is_directory) {
5965 const char *p = strrchr_m(src,'/');
5971 dest = talloc_asprintf_append(dest,
5975 return NT_STATUS_NO_MEMORY;
5979 if (!vfs_file_exist(conn,src,&src_sbuf)) {
5981 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5984 if (!target_is_directory && count) {
5985 new_create_disposition = FILE_OPEN;
5987 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5988 NULL, NULL, &new_create_disposition, NULL)) {
5990 return NT_STATUS_INVALID_PARAMETER;
5994 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5996 FILE_SHARE_READ|FILE_SHARE_WRITE,
5999 FILE_ATTRIBUTE_NORMAL,
6003 if (!NT_STATUS_IS_OK(status)) {
6008 dosattrs = dos_mode(conn, src, &src_sbuf);
6009 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6010 ZERO_STRUCTP(&sbuf2);
6013 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
6015 FILE_SHARE_READ|FILE_SHARE_WRITE,
6016 new_create_disposition,
6024 if (!NT_STATUS_IS_OK(status)) {
6025 close_file(fsp1,ERROR_CLOSE);
6029 if ((ofun&3) == 1) {
6030 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
6031 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6033 * Stop the copy from occurring.
6036 src_sbuf.st_size = 0;
6040 if (src_sbuf.st_size) {
6041 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6044 close_file(fsp1,NORMAL_CLOSE);
6046 /* Ensure the modtime is set correctly on the destination file. */
6047 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
6050 * As we are opening fsp1 read-only we only expect
6051 * an error on close on fsp2 if we are out of space.
6052 * Thus we don't look at the error return from the
6055 status = close_file(fsp2,NORMAL_CLOSE);
6057 if (!NT_STATUS_IS_OK(status)) {
6061 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6062 return NT_STATUS_DISK_FULL;
6065 return NT_STATUS_OK;
6068 /****************************************************************************
6069 Reply to a file copy.
6070 ****************************************************************************/
6072 void reply_copy(connection_struct *conn, struct smb_request *req)
6075 char *newname = NULL;
6076 char *directory = NULL;
6080 int error = ERRnoaccess;
6085 bool target_is_directory=False;
6086 bool source_has_wild = False;
6087 bool dest_has_wild = False;
6088 SMB_STRUCT_STAT sbuf1, sbuf2;
6090 TALLOC_CTX *ctx = talloc_tos();
6092 START_PROFILE(SMBcopy);
6095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6096 END_PROFILE(SMBcopy);
6100 tid2 = SVAL(req->inbuf,smb_vwv0);
6101 ofun = SVAL(req->inbuf,smb_vwv1);
6102 flags = SVAL(req->inbuf,smb_vwv2);
6104 p = smb_buf(req->inbuf);
6105 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
6106 0, STR_TERMINATE, &status,
6108 if (!NT_STATUS_IS_OK(status)) {
6109 reply_nterror(req, status);
6110 END_PROFILE(SMBcopy);
6113 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
6114 0, STR_TERMINATE, &status,
6116 if (!NT_STATUS_IS_OK(status)) {
6117 reply_nterror(req, status);
6118 END_PROFILE(SMBcopy);
6122 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6124 if (tid2 != conn->cnum) {
6125 /* can't currently handle inter share copies XXXX */
6126 DEBUG(3,("Rejecting inter-share copy\n"));
6127 reply_doserror(req, ERRSRV, ERRinvdevice);
6128 END_PROFILE(SMBcopy);
6132 status = resolve_dfspath_wcard(ctx, conn,
6133 req->flags2 & FLAGS2_DFS_PATHNAMES,
6137 if (!NT_STATUS_IS_OK(status)) {
6138 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6139 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6140 ERRSRV, ERRbadpath);
6141 END_PROFILE(SMBcopy);
6144 reply_nterror(req, status);
6145 END_PROFILE(SMBcopy);
6149 status = resolve_dfspath_wcard(ctx, conn,
6150 req->flags2 & FLAGS2_DFS_PATHNAMES,
6154 if (!NT_STATUS_IS_OK(status)) {
6155 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6156 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6157 ERRSRV, ERRbadpath);
6158 END_PROFILE(SMBcopy);
6161 reply_nterror(req, status);
6162 END_PROFILE(SMBcopy);
6166 status = unix_convert(ctx, conn, name, source_has_wild,
6167 &name, NULL, &sbuf1);
6168 if (!NT_STATUS_IS_OK(status)) {
6169 reply_nterror(req, status);
6170 END_PROFILE(SMBcopy);
6174 status = unix_convert(ctx, conn, newname, dest_has_wild,
6175 &newname, NULL, &sbuf2);
6176 if (!NT_STATUS_IS_OK(status)) {
6177 reply_nterror(req, status);
6178 END_PROFILE(SMBcopy);
6182 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6184 if ((flags&1) && target_is_directory) {
6185 reply_doserror(req, ERRDOS, ERRbadfile);
6186 END_PROFILE(SMBcopy);
6190 if ((flags&2) && !target_is_directory) {
6191 reply_doserror(req, ERRDOS, ERRbadpath);
6192 END_PROFILE(SMBcopy);
6196 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6197 /* wants a tree copy! XXXX */
6198 DEBUG(3,("Rejecting tree copy\n"));
6199 reply_doserror(req, ERRSRV, ERRerror);
6200 END_PROFILE(SMBcopy);
6204 p = strrchr_m(name,'/');
6206 directory = talloc_strdup(ctx, "./");
6208 reply_nterror(req, NT_STATUS_NO_MEMORY);
6209 END_PROFILE(SMBcopy);
6215 directory = talloc_strdup(ctx, name);
6217 reply_nterror(req, NT_STATUS_NO_MEMORY);
6218 END_PROFILE(SMBcopy);
6225 * We should only check the mangled cache
6226 * here if unix_convert failed. This means
6227 * that the path in 'mask' doesn't exist
6228 * on the file system and so we need to look
6229 * for a possible mangle. This patch from
6230 * Tine Smukavec <valentin.smukavec@hermes.si>.
6233 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6234 char *new_mask = NULL;
6235 mangle_lookup_name_from_8_3(ctx,
6244 if (!source_has_wild) {
6245 directory = talloc_asprintf_append(directory,
6248 if (dest_has_wild) {
6249 char *mod_newname = NULL;
6250 if (!resolve_wildcards(ctx,
6251 directory,newname,&mod_newname)) {
6252 reply_nterror(req, NT_STATUS_NO_MEMORY);
6253 END_PROFILE(SMBcopy);
6256 newname = mod_newname;
6259 status = check_name(conn, directory);
6260 if (!NT_STATUS_IS_OK(status)) {
6261 reply_nterror(req, status);
6262 END_PROFILE(SMBcopy);
6266 status = check_name(conn, newname);
6267 if (!NT_STATUS_IS_OK(status)) {
6268 reply_nterror(req, status);
6269 END_PROFILE(SMBcopy);
6273 status = copy_file(ctx,conn,directory,newname,ofun,
6274 count,target_is_directory);
6276 if(!NT_STATUS_IS_OK(status)) {
6277 reply_nterror(req, status);
6278 END_PROFILE(SMBcopy);
6284 struct smb_Dir *dir_hnd = NULL;
6285 const char *dname = NULL;
6288 if (strequal(mask,"????????.???")) {
6293 status = check_name(conn, directory);
6294 if (!NT_STATUS_IS_OK(status)) {
6295 reply_nterror(req, status);
6296 END_PROFILE(SMBcopy);
6300 dir_hnd = OpenDir(conn, directory, mask, 0);
6301 if (dir_hnd == NULL) {
6302 status = map_nt_error_from_unix(errno);
6303 reply_nterror(req, status);
6304 END_PROFILE(SMBcopy);
6310 while ((dname = ReadDirName(dir_hnd, &offset))) {
6311 char *destname = NULL;
6314 if (ISDOT(dname) || ISDOTDOT(dname)) {
6318 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6322 if(!mask_match(dname, mask, conn->case_sensitive)) {
6326 error = ERRnoaccess;
6327 fname = talloc_asprintf(ctx,
6332 reply_nterror(req, NT_STATUS_NO_MEMORY);
6333 END_PROFILE(SMBcopy);
6337 if (!resolve_wildcards(ctx,
6338 fname,newname,&destname)) {
6342 reply_nterror(req, NT_STATUS_NO_MEMORY);
6343 END_PROFILE(SMBcopy);
6347 status = check_name(conn, fname);
6348 if (!NT_STATUS_IS_OK(status)) {
6349 reply_nterror(req, status);
6350 END_PROFILE(SMBcopy);
6354 status = check_name(conn, destname);
6355 if (!NT_STATUS_IS_OK(status)) {
6356 reply_nterror(req, status);
6357 END_PROFILE(SMBcopy);
6361 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6363 status = copy_file(ctx,conn,fname,destname,ofun,
6364 count,target_is_directory);
6365 if (NT_STATUS_IS_OK(status)) {
6369 TALLOC_FREE(destname);
6376 /* Error on close... */
6378 reply_unixerror(req, ERRHRD, ERRgeneral);
6379 END_PROFILE(SMBcopy);
6383 reply_doserror(req, ERRDOS, error);
6384 END_PROFILE(SMBcopy);
6388 reply_outbuf(req, 1, 0);
6389 SSVAL(req->outbuf,smb_vwv0,count);
6391 END_PROFILE(SMBcopy);
6396 #define DBGC_CLASS DBGC_LOCKING
6398 /****************************************************************************
6399 Get a lock pid, dealing with large count requests.
6400 ****************************************************************************/
6402 uint32 get_lock_pid( char *data, int data_offset, bool large_file_format)
6404 if(!large_file_format)
6405 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6407 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6410 /****************************************************************************
6411 Get a lock count, dealing with large count requests.
6412 ****************************************************************************/
6414 SMB_BIG_UINT get_lock_count( char *data, int data_offset, bool large_file_format)
6416 SMB_BIG_UINT count = 0;
6418 if(!large_file_format) {
6419 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6422 #if defined(HAVE_LONGLONG)
6423 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6424 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6425 #else /* HAVE_LONGLONG */
6428 * NT4.x seems to be broken in that it sends large file (64 bit)
6429 * lockingX calls even if the CAP_LARGE_FILES was *not*
6430 * negotiated. For boxes without large unsigned ints truncate the
6431 * lock count by dropping the top 32 bits.
6434 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6435 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6436 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6437 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6438 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6441 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6442 #endif /* HAVE_LONGLONG */
6448 #if !defined(HAVE_LONGLONG)
6449 /****************************************************************************
6450 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6451 ****************************************************************************/
6453 static uint32 map_lock_offset(uint32 high, uint32 low)
6457 uint32 highcopy = high;
6460 * Try and find out how many significant bits there are in high.
6463 for(i = 0; highcopy; i++)
6467 * We use 31 bits not 32 here as POSIX
6468 * lock offsets may not be negative.
6471 mask = (~0) << (31 - i);
6474 return 0; /* Fail. */
6480 #endif /* !defined(HAVE_LONGLONG) */
6482 /****************************************************************************
6483 Get a lock offset, dealing with large offset requests.
6484 ****************************************************************************/
6486 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_format, bool *err)
6488 SMB_BIG_UINT offset = 0;
6492 if(!large_file_format) {
6493 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6496 #if defined(HAVE_LONGLONG)
6497 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6498 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6499 #else /* HAVE_LONGLONG */
6502 * NT4.x seems to be broken in that it sends large file (64 bit)
6503 * lockingX calls even if the CAP_LARGE_FILES was *not*
6504 * negotiated. For boxes without large unsigned ints mangle the
6505 * lock offset by mapping the top 32 bits onto the lower 32.
6508 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6509 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6510 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6513 if((new_low = map_lock_offset(high, low)) == 0) {
6515 return (SMB_BIG_UINT)-1;
6518 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6519 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6520 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6521 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6524 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6525 #endif /* HAVE_LONGLONG */
6531 /****************************************************************************
6532 Reply to a lockingX request.
6533 ****************************************************************************/
6535 void reply_lockingX(connection_struct *conn, struct smb_request *req)
6538 unsigned char locktype;
6539 unsigned char oplocklevel;
6542 SMB_BIG_UINT count = 0, offset = 0;
6547 bool large_file_format;
6549 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6551 START_PROFILE(SMBlockingX);
6554 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6555 END_PROFILE(SMBlockingX);
6559 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
6560 locktype = CVAL(req->inbuf,smb_vwv3);
6561 oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
6562 num_ulocks = SVAL(req->inbuf,smb_vwv6);
6563 num_locks = SVAL(req->inbuf,smb_vwv7);
6564 lock_timeout = IVAL(req->inbuf,smb_vwv4);
6565 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6567 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6568 END_PROFILE(SMBlockingX);
6572 data = smb_buf(req->inbuf);
6574 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6575 /* we don't support these - and CANCEL_LOCK makes w2k
6576 and XP reboot so I don't really want to be
6577 compatible! (tridge) */
6578 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6579 END_PROFILE(SMBlockingX);
6583 /* Check if this is an oplock break on a file
6584 we have granted an oplock on.
6586 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6587 /* Client can insist on breaking to none. */
6588 bool break_to_none = (oplocklevel == 0);
6591 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6592 "for fnum = %d\n", (unsigned int)oplocklevel,
6596 * Make sure we have granted an exclusive or batch oplock on
6600 if (fsp->oplock_type == 0) {
6602 /* The Samba4 nbench simulator doesn't understand
6603 the difference between break to level2 and break
6604 to none from level2 - it sends oplock break
6605 replies in both cases. Don't keep logging an error
6606 message here - just ignore it. JRA. */
6608 DEBUG(5,("reply_lockingX: Error : oplock break from "
6609 "client for fnum = %d (oplock=%d) and no "
6610 "oplock granted on this file (%s).\n",
6611 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6613 /* if this is a pure oplock break request then don't
6615 if (num_locks == 0 && num_ulocks == 0) {
6616 END_PROFILE(SMBlockingX);
6619 END_PROFILE(SMBlockingX);
6620 reply_doserror(req, ERRDOS, ERRlock);
6625 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6627 result = remove_oplock(fsp);
6629 result = downgrade_oplock(fsp);
6633 DEBUG(0, ("reply_lockingX: error in removing "
6634 "oplock on file %s\n", fsp->fsp_name));
6635 /* Hmmm. Is this panic justified? */
6636 smb_panic("internal tdb error");
6639 reply_to_oplock_break_requests(fsp);
6641 /* if this is a pure oplock break request then don't send a
6643 if (num_locks == 0 && num_ulocks == 0) {
6644 /* Sanity check - ensure a pure oplock break is not a
6646 if(CVAL(req->inbuf,smb_vwv0) != 0xff)
6647 DEBUG(0,("reply_lockingX: Error : pure oplock "
6648 "break is a chained %d request !\n",
6649 (unsigned int)CVAL(req->inbuf,
6651 END_PROFILE(SMBlockingX);
6657 * We do this check *after* we have checked this is not a oplock break
6658 * response message. JRA.
6661 release_level_2_oplocks_on_change(fsp);
6663 if (smb_buflen(req->inbuf) <
6664 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6666 END_PROFILE(SMBlockingX);
6670 /* Data now points at the beginning of the list
6671 of smb_unlkrng structs */
6672 for(i = 0; i < (int)num_ulocks; i++) {
6673 lock_pid = get_lock_pid( data, i, large_file_format);
6674 count = get_lock_count( data, i, large_file_format);
6675 offset = get_lock_offset( data, i, large_file_format, &err);
6678 * There is no error code marked "stupid client bug".... :-).
6681 END_PROFILE(SMBlockingX);
6682 reply_doserror(req, ERRDOS, ERRnoaccess);
6686 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6687 "pid %u, file %s\n", (double)offset, (double)count,
6688 (unsigned int)lock_pid, fsp->fsp_name ));
6690 status = do_unlock(smbd_messaging_context(),
6697 if (NT_STATUS_V(status)) {
6698 END_PROFILE(SMBlockingX);
6699 reply_nterror(req, status);
6704 /* Setup the timeout in seconds. */
6706 if (!lp_blocking_locks(SNUM(conn))) {
6710 /* Now do any requested locks */
6711 data += ((large_file_format ? 20 : 10)*num_ulocks);
6713 /* Data now points at the beginning of the list
6714 of smb_lkrng structs */
6716 for(i = 0; i < (int)num_locks; i++) {
6717 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6718 READ_LOCK:WRITE_LOCK);
6719 lock_pid = get_lock_pid( data, i, large_file_format);
6720 count = get_lock_count( data, i, large_file_format);
6721 offset = get_lock_offset( data, i, large_file_format, &err);
6724 * There is no error code marked "stupid client bug".... :-).
6727 END_PROFILE(SMBlockingX);
6728 reply_doserror(req, ERRDOS, ERRnoaccess);
6732 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6733 "%u, file %s timeout = %d\n", (double)offset,
6734 (double)count, (unsigned int)lock_pid,
6735 fsp->fsp_name, (int)lock_timeout ));
6737 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6738 if (lp_blocking_locks(SNUM(conn))) {
6740 /* Schedule a message to ourselves to
6741 remove the blocking lock record and
6742 return the right error. */
6744 if (!blocking_lock_cancel(fsp,
6750 NT_STATUS_FILE_LOCK_CONFLICT)) {
6751 END_PROFILE(SMBlockingX);
6756 ERRcancelviolation));
6760 /* Remove a matching pending lock. */
6761 status = do_lock_cancel(fsp,
6767 bool blocking_lock = lock_timeout ? True : False;
6768 bool defer_lock = False;
6769 struct byte_range_lock *br_lck;
6770 uint32 block_smbpid;
6772 br_lck = do_lock(smbd_messaging_context(),
6783 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6784 /* Windows internal resolution for blocking locks seems
6785 to be about 200ms... Don't wait for less than that. JRA. */
6786 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6787 lock_timeout = lp_lock_spin_time();
6792 /* This heuristic seems to match W2K3 very well. If a
6793 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6794 it pretends we asked for a timeout of between 150 - 300 milliseconds as
6795 far as I can tell. Replacement for do_lock_spin(). JRA. */
6797 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6798 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6800 lock_timeout = lp_lock_spin_time();
6803 if (br_lck && defer_lock) {
6805 * A blocking lock was requested. Package up
6806 * this smb into a queued request and push it
6807 * onto the blocking lock queue.
6809 if(push_blocking_lock_request(br_lck,
6820 TALLOC_FREE(br_lck);
6821 END_PROFILE(SMBlockingX);
6826 TALLOC_FREE(br_lck);
6829 if (NT_STATUS_V(status)) {
6830 END_PROFILE(SMBlockingX);
6831 reply_nterror(req, status);
6836 /* If any of the above locks failed, then we must unlock
6837 all of the previous locks (X/Open spec). */
6839 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6843 * Ensure we don't do a remove on the lock that just failed,
6844 * as under POSIX rules, if we have a lock already there, we
6845 * will delete it (and we shouldn't) .....
6847 for(i--; i >= 0; i--) {
6848 lock_pid = get_lock_pid( data, i, large_file_format);
6849 count = get_lock_count( data, i, large_file_format);
6850 offset = get_lock_offset( data, i, large_file_format,
6854 * There is no error code marked "stupid client
6858 END_PROFILE(SMBlockingX);
6859 reply_doserror(req, ERRDOS, ERRnoaccess);
6863 do_unlock(smbd_messaging_context(),
6870 END_PROFILE(SMBlockingX);
6871 reply_nterror(req, status);
6875 reply_outbuf(req, 2, 0);
6877 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
6878 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
6880 END_PROFILE(SMBlockingX);
6885 #define DBGC_CLASS DBGC_ALL
6887 /****************************************************************************
6888 Reply to a SMBreadbmpx (read block multiplex) request.
6889 Always reply with an error, if someone has a platform really needs this,
6890 please contact vl@samba.org
6891 ****************************************************************************/
6893 void reply_readbmpx(connection_struct *conn, struct smb_request *req)
6895 START_PROFILE(SMBreadBmpx);
6896 reply_doserror(req, ERRSRV, ERRuseSTD);
6897 END_PROFILE(SMBreadBmpx);
6901 /****************************************************************************
6902 Reply to a SMBreadbs (read block multiplex secondary) request.
6903 Always reply with an error, if someone has a platform really needs this,
6904 please contact vl@samba.org
6905 ****************************************************************************/
6907 void reply_readbs(connection_struct *conn, struct smb_request *req)
6909 START_PROFILE(SMBreadBs);
6910 reply_doserror(req, ERRSRV, ERRuseSTD);
6911 END_PROFILE(SMBreadBs);
6915 /****************************************************************************
6916 Reply to a SMBsetattrE.
6917 ****************************************************************************/
6919 void reply_setattrE(connection_struct *conn, struct smb_request *req)
6921 struct timespec ts[2];
6924 START_PROFILE(SMBsetattrE);
6927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6928 END_PROFILE(SMBsetattrE);
6932 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
6934 if(!fsp || (fsp->conn != conn)) {
6935 reply_doserror(req, ERRDOS, ERRbadfid);
6936 END_PROFILE(SMBsetattrE);
6942 * Convert the DOS times into unix times. Ignore create
6943 * time as UNIX can't set this.
6946 ts[0] = convert_time_t_to_timespec(
6947 srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */
6948 ts[1] = convert_time_t_to_timespec(
6949 srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */
6951 reply_outbuf(req, 0, 0);
6954 * Patch from Ray Frush <frush@engr.colostate.edu>
6955 * Sometimes times are sent as zero - ignore them.
6958 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
6959 /* Ignore request */
6960 if( DEBUGLVL( 3 ) ) {
6961 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
6962 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
6964 END_PROFILE(SMBsetattrE);
6966 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
6967 /* set modify time = to access time if modify time was unset */
6971 /* Set the date on this file */
6972 /* Should we set pending modtime here ? JRA */
6973 if(file_ntimes(conn, fsp->fsp_name, ts)) {
6974 reply_doserror(req, ERRDOS, ERRnoaccess);
6975 END_PROFILE(SMBsetattrE);
6979 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
6981 (unsigned int)ts[0].tv_sec,
6982 (unsigned int)ts[1].tv_sec));
6984 END_PROFILE(SMBsetattrE);
6989 /* Back from the dead for OS/2..... JRA. */
6991 /****************************************************************************
6992 Reply to a SMBwritebmpx (write block multiplex primary) request.
6993 Always reply with an error, if someone has a platform really needs this,
6994 please contact vl@samba.org
6995 ****************************************************************************/
6997 void reply_writebmpx(connection_struct *conn, struct smb_request *req)
6999 START_PROFILE(SMBwriteBmpx);
7000 reply_doserror(req, ERRSRV, ERRuseSTD);
7001 END_PROFILE(SMBwriteBmpx);
7005 /****************************************************************************
7006 Reply to a SMBwritebs (write block multiplex secondary) request.
7007 Always reply with an error, if someone has a platform really needs this,
7008 please contact vl@samba.org
7009 ****************************************************************************/
7011 void reply_writebs(connection_struct *conn, struct smb_request *req)
7013 START_PROFILE(SMBwriteBs);
7014 reply_doserror(req, ERRSRV, ERRuseSTD);
7015 END_PROFILE(SMBwriteBs);
7019 /****************************************************************************
7020 Reply to a SMBgetattrE.
7021 ****************************************************************************/
7023 void reply_getattrE(connection_struct *conn, struct smb_request *req)
7025 SMB_STRUCT_STAT sbuf;
7029 START_PROFILE(SMBgetattrE);
7032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7033 END_PROFILE(SMBgetattrE);
7037 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
7039 if(!fsp || (fsp->conn != conn)) {
7040 reply_doserror(req, ERRDOS, ERRbadfid);
7041 END_PROFILE(SMBgetattrE);
7045 /* Do an fstat on this file */
7046 if(fsp_stat(fsp, &sbuf)) {
7047 reply_unixerror(req, ERRDOS, ERRnoaccess);
7048 END_PROFILE(SMBgetattrE);
7052 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7055 * Convert the times into dos times. Set create
7056 * date to be last modify date as UNIX doesn't save
7060 reply_outbuf(req, 11, 0);
7062 srv_put_dos_date2((char *)req->outbuf, smb_vwv0,
7063 get_create_time(&sbuf,
7064 lp_fake_dir_create_times(SNUM(conn))));
7065 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7066 /* Should we check pending modtime here ? JRA */
7067 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7070 SIVAL(req->outbuf, smb_vwv6, 0);
7071 SIVAL(req->outbuf, smb_vwv8, 0);
7073 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
7074 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7075 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7077 SSVAL(req->outbuf,smb_vwv10, mode);
7079 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7081 END_PROFILE(SMBgetattrE);