2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
32 unsigned int smb_echo_count = 0;
33 extern uint32 global_client_caps;
35 extern struct current_user current_user;
36 extern BOOL global_encrypted_passwords_negotiated;
38 /****************************************************************************
39 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
40 path or anything including wildcards.
41 We're assuming here that '/' is not the second byte in any multibyte char
42 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44 ****************************************************************************/
46 /* Custom version for processing POSIX paths. */
47 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
49 static NTSTATUS check_path_syntax_internal(char *path,
51 BOOL *p_last_component_contains_wcard)
55 NTSTATUS ret = NT_STATUS_OK;
56 BOOL start_of_name_component = True;
58 *p_last_component_contains_wcard = False;
61 if (IS_PATH_SEP(*s,posix_path)) {
63 * Safe to assume is not the second part of a mb char
64 * as this is handled below.
66 /* Eat multiple '/' or '\\' */
67 while (IS_PATH_SEP(*s,posix_path)) {
70 if ((d != path) && (*s != '\0')) {
71 /* We only care about non-leading or trailing '/' or '\\' */
75 start_of_name_component = True;
77 *p_last_component_contains_wcard = False;
81 if (start_of_name_component) {
82 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
83 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
86 * No mb char starts with '.' so we're safe checking the directory separator here.
89 /* If we just added a '/' - delete it */
90 if ((d > path) && (*(d-1) == '/')) {
95 /* Are we at the start ? Can't go back further if so. */
97 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
100 /* Go back one level... */
101 /* We know this is safe as '/' cannot be part of a mb sequence. */
102 /* NOTE - if this assumption is invalid we are not in good shape... */
103 /* Decrement d first as d points to the *next* char to write into. */
104 for (d--; d > path; d--) {
108 s += 2; /* Else go past the .. */
109 /* We're still at the start of a name component, just the previous one. */
112 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
125 return NT_STATUS_OBJECT_NAME_INVALID;
133 *p_last_component_contains_wcard = True;
142 /* Get the size of the next MB character. */
143 next_codepoint(s,&siz);
161 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
163 return NT_STATUS_INVALID_PARAMETER;
166 start_of_name_component = False;
173 /****************************************************************************
174 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
175 No wildcards allowed.
176 ****************************************************************************/
178 NTSTATUS check_path_syntax(char *path)
181 return check_path_syntax_internal(path, False, &ignore);
184 /****************************************************************************
185 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
186 Wildcards allowed - p_contains_wcard returns true if the last component contained
188 ****************************************************************************/
190 NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
192 return check_path_syntax_internal(path, False, p_contains_wcard);
195 /****************************************************************************
196 Check the path for a POSIX client.
197 We're assuming here that '/' is not the second byte in any multibyte char
198 set (a safe assumption).
199 ****************************************************************************/
201 NTSTATUS check_path_syntax_posix(char *path)
204 return check_path_syntax_internal(path, True, &ignore);
207 /****************************************************************************
208 Pull a string and check the path allowing a wilcard - provide for error return.
209 ****************************************************************************/
211 size_t srvstr_get_path_wcard(const char *inbuf, uint16 smb_flags2, char *dest,
212 const char *src, size_t dest_len, size_t src_len,
213 int flags, NTSTATUS *err, BOOL *contains_wcard)
217 SMB_ASSERT(dest_len == sizeof(pstring));
221 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
224 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
225 dest_len, src_len, flags);
228 *contains_wcard = False;
230 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
232 * For a DFS path the function parse_dfs_path()
233 * will do the path processing, just make a copy.
239 if (lp_posix_pathnames()) {
240 *err = check_path_syntax_posix(dest);
242 *err = check_path_syntax_wcard(dest, contains_wcard);
248 /****************************************************************************
249 Pull a string and check the path - provide for error return.
250 ****************************************************************************/
252 size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest,
253 const char *src, size_t dest_len, size_t src_len,
254 int flags, NTSTATUS *err)
258 SMB_ASSERT(dest_len == sizeof(pstring));
262 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
265 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
266 dest_len, src_len, flags);
269 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
271 * For a DFS path the function parse_dfs_path()
272 * will do the path processing, just make a copy.
278 if (lp_posix_pathnames()) {
279 *err = check_path_syntax_posix(dest);
281 *err = check_path_syntax(dest);
287 /****************************************************************************
288 Check if we have a correct fsp pointing to a file. Replacement for the
290 ****************************************************************************/
292 BOOL check_fsp(connection_struct *conn, struct smb_request *req,
293 files_struct *fsp, struct current_user *user)
295 if (!(fsp) || !(conn)) {
296 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
299 if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) {
300 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
303 if ((fsp)->is_directory) {
304 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
307 if ((fsp)->fh->fd == -1) {
308 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
311 (fsp)->num_smb_operations++;
315 /****************************************************************************
316 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
317 ****************************************************************************/
319 BOOL fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
320 files_struct *fsp, struct current_user *user)
322 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
323 && (current_user.vuid==(fsp)->vuid)) {
327 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
331 /****************************************************************************
332 Reply to a (netbios-level) special message.
333 ****************************************************************************/
335 void reply_special(char *inbuf)
337 int msg_type = CVAL(inbuf,0);
338 int msg_flags = CVAL(inbuf,1);
343 * We only really use 4 bytes of the outbuf, but for the smb_setlen
344 * calculation & friends (send_smb uses that) we need the full smb
347 char outbuf[smb_size];
349 static BOOL already_got_session = False;
353 memset(outbuf, '\0', sizeof(outbuf));
355 smb_setlen(inbuf,outbuf,0);
358 case 0x81: /* session request */
360 if (already_got_session) {
361 exit_server_cleanly("multiple session request not permitted");
364 SCVAL(outbuf,0,0x82);
366 if (name_len(inbuf+4) > 50 ||
367 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
368 DEBUG(0,("Invalid name length in session request\n"));
371 name_extract(inbuf,4,name1);
372 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
373 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
376 set_local_machine_name(name1, True);
377 set_remote_machine_name(name2, True);
379 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
380 get_local_machine_name(), get_remote_machine_name(),
383 if (name_type == 'R') {
384 /* We are being asked for a pathworks session ---
386 SCVAL(outbuf, 0,0x83);
390 /* only add the client's machine name to the list
391 of possibly valid usernames if we are operating
392 in share mode security */
393 if (lp_security() == SEC_SHARE) {
394 add_session_user(get_remote_machine_name());
397 reload_services(True);
400 already_got_session = True;
403 case 0x89: /* session keepalive request
404 (some old clients produce this?) */
405 SCVAL(outbuf,0,SMBkeepalive);
409 case 0x82: /* positive session response */
410 case 0x83: /* negative session response */
411 case 0x84: /* retarget session response */
412 DEBUG(0,("Unexpected session response\n"));
415 case SMBkeepalive: /* session keepalive */
420 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
421 msg_type, msg_flags));
423 send_smb(smbd_server_fd(), outbuf);
427 /****************************************************************************
429 conn POINTER CAN BE NULL HERE !
430 ****************************************************************************/
432 int reply_tcon(connection_struct *conn,
433 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
437 char *service_buf = NULL;
438 char *password = NULL;
441 uint16 vuid = SVAL(inbuf,smb_uid);
445 DATA_BLOB password_blob;
447 START_PROFILE(SMBtcon);
449 ctx = talloc_init("reply_tcon");
451 END_PROFILE(SMBtcon);
452 return ERROR_NT(NT_STATUS_NO_MEMORY);
455 p = smb_buf(inbuf)+1;
456 p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
457 &service_buf, p, STR_TERMINATE) + 1;
458 pwlen = srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
459 &password, p, STR_TERMINATE) + 1;
461 p += srvstr_pull_buf_talloc(ctx, inbuf, SVAL(inbuf, smb_flg2),
462 &dev, p, STR_TERMINATE) + 1;
464 if (service_buf == NULL || password == NULL || dev == NULL) {
466 END_PROFILE(SMBtcon);
467 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
469 p = strrchr_m(service_buf,'\\');
473 service = service_buf;
476 password_blob = data_blob(password, pwlen+1);
478 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
480 data_blob_clear_free(&password_blob);
484 END_PROFILE(SMBtcon);
485 return ERROR_NT(nt_status);
488 outsize = set_message(inbuf,outbuf,2,0,True);
489 SSVAL(outbuf,smb_vwv0,max_recv);
490 SSVAL(outbuf,smb_vwv1,conn->cnum);
491 SSVAL(outbuf,smb_tid,conn->cnum);
493 DEBUG(3,("tcon service=%s cnum=%d\n",
494 service, conn->cnum));
496 END_PROFILE(SMBtcon);
501 /****************************************************************************
502 Reply to a tcon and X.
503 conn POINTER CAN BE NULL HERE !
504 ****************************************************************************/
506 void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)
508 char *service = NULL;
511 TALLOC_CTX *ctx = NULL;
512 /* what the cleint thinks the device is */
513 char *client_devicetype = NULL;
514 /* what the server tells the client the share represents */
515 const char *server_devicetype;
522 START_PROFILE(SMBtconX);
525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
526 END_PROFILE(SMBtconX);
530 passlen = SVAL(req->inbuf,smb_vwv3);
531 tcon_flags = SVAL(req->inbuf,smb_vwv2);
533 /* we might have to close an old one */
534 if ((tcon_flags & 0x1) && conn) {
535 close_cnum(conn,req->vuid);
538 if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
539 reply_doserror(req, ERRDOS, ERRbuftoosmall);
540 END_PROFILE(SMBtconX);
544 if (global_encrypted_passwords_negotiated) {
545 password = data_blob(smb_buf(req->inbuf),passlen);
546 if (lp_security() == SEC_SHARE) {
548 * Security = share always has a pad byte
549 * after the password.
551 p = smb_buf(req->inbuf) + passlen + 1;
553 p = smb_buf(req->inbuf) + passlen;
556 password = data_blob(smb_buf(req->inbuf),passlen+1);
557 /* Ensure correct termination */
558 password.data[passlen]=0;
559 p = smb_buf(req->inbuf) + passlen + 1;
562 ctx = talloc_init("reply_tcon_and_X");
564 data_blob_clear_free(&password);
565 reply_nterror(req, NT_STATUS_NO_MEMORY);
566 END_PROFILE(SMBtconX);
569 p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
573 data_blob_clear_free(&password);
575 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
576 END_PROFILE(SMBtconX);
581 * the service name can be either: \\server\share
582 * or share directly like on the DELL PowerVault 705
585 q = strchr_m(path+2,'\\');
587 data_blob_clear_free(&password);
589 reply_doserror(req, ERRDOS, ERRnosuchshare);
590 END_PROFILE(SMBtconX);
598 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
599 &client_devicetype, p,
600 MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
602 if (client_devicetype == NULL) {
603 data_blob_clear_free(&password);
605 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
606 END_PROFILE(SMBtconX);
610 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
612 conn = make_connection(service, password, client_devicetype,
613 req->vuid, &nt_status);
615 data_blob_clear_free(&password);
619 reply_nterror(req, nt_status);
620 END_PROFILE(SMBtconX);
625 server_devicetype = "IPC";
626 else if ( IS_PRINT(conn) )
627 server_devicetype = "LPT1:";
629 server_devicetype = "A:";
631 if (Protocol < PROTOCOL_NT1) {
632 reply_outbuf(req, 2, 0);
633 if (message_push_string(&req->outbuf, server_devicetype,
634 STR_TERMINATE|STR_ASCII) == -1) {
636 reply_nterror(req, NT_STATUS_NO_MEMORY);
637 END_PROFILE(SMBtconX);
641 /* NT sets the fstype of IPC$ to the null string */
642 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
644 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
645 /* Return permissions. */
649 reply_outbuf(req, 7, 0);
652 perm1 = FILE_ALL_ACCESS;
653 perm2 = FILE_ALL_ACCESS;
655 perm1 = CAN_WRITE(conn) ?
660 SIVAL(req->outbuf, smb_vwv3, perm1);
661 SIVAL(req->outbuf, smb_vwv5, perm2);
663 reply_outbuf(req, 3, 0);
666 if ((message_push_string(&req->outbuf, server_devicetype,
667 STR_TERMINATE|STR_ASCII) == -1)
668 || (message_push_string(&req->outbuf, fstype,
669 STR_TERMINATE) == -1)) {
671 reply_nterror(req, NT_STATUS_NO_MEMORY);
672 END_PROFILE(SMBtconX);
676 /* what does setting this bit do? It is set by NT4 and
677 may affect the ability to autorun mounted cdroms */
678 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
679 (lp_csc_policy(SNUM(conn)) << 2));
681 init_dfsroot(conn, req->inbuf, req->outbuf);
685 DEBUG(3,("tconX service=%s \n",
688 /* set the incoming and outgoing tid to the just created one */
689 SSVAL(req->inbuf,smb_tid,conn->cnum);
690 SSVAL(req->outbuf,smb_tid,conn->cnum);
693 END_PROFILE(SMBtconX);
695 chain_reply_new(req);
699 /****************************************************************************
700 Reply to an unknown type.
701 ****************************************************************************/
703 int reply_unknown(char *inbuf,char *outbuf)
706 type = CVAL(inbuf,smb_com);
708 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
709 smb_fn_name(type), type, type));
711 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
714 void reply_unknown_new(struct smb_request *req, uint8 type)
716 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
717 smb_fn_name(type), type, type));
718 reply_doserror(req, ERRSRV, ERRunknownsmb);
722 /****************************************************************************
724 conn POINTER CAN BE NULL HERE !
725 ****************************************************************************/
727 void reply_ioctl(connection_struct *conn, struct smb_request *req)
735 START_PROFILE(SMBioctl);
738 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
739 END_PROFILE(SMBioctl);
743 device = SVAL(req->inbuf,smb_vwv1);
744 function = SVAL(req->inbuf,smb_vwv2);
745 ioctl_code = (device << 16) + function;
747 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
749 switch (ioctl_code) {
750 case IOCTL_QUERY_JOB_INFO:
754 reply_doserror(req, ERRSRV, ERRnosupport);
755 END_PROFILE(SMBioctl);
759 reply_outbuf(req, 8, replysize+1);
760 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
761 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
762 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
763 p = smb_buf(req->outbuf) + 1; /* Allow for alignment */
765 switch (ioctl_code) {
766 case IOCTL_QUERY_JOB_INFO:
768 files_struct *fsp = file_fsp(SVAL(req->inbuf,
771 reply_doserror(req, ERRDOS, ERRbadfid);
772 END_PROFILE(SMBioctl);
775 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
776 srvstr_push((char *)req->outbuf, req->flags2, p+2,
778 STR_TERMINATE|STR_ASCII);
780 srvstr_push((char *)req->outbuf, req->flags2,
781 p+18, lp_servicename(SNUM(conn)),
782 13, STR_TERMINATE|STR_ASCII);
791 END_PROFILE(SMBioctl);
795 /****************************************************************************
796 Strange checkpath NTSTATUS mapping.
797 ****************************************************************************/
799 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
801 /* Strange DOS error code semantics only for checkpath... */
802 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
803 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
804 /* We need to map to ERRbadpath */
805 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
811 /****************************************************************************
812 Reply to a checkpath.
813 ****************************************************************************/
815 void reply_checkpath(connection_struct *conn, struct smb_request *req)
818 SMB_STRUCT_STAT sbuf;
821 START_PROFILE(SMBcheckpath);
823 srvstr_get_path((char *)req->inbuf, req->flags2, name,
824 smb_buf(req->inbuf) + 1, sizeof(name), 0,
825 STR_TERMINATE, &status);
826 if (!NT_STATUS_IS_OK(status)) {
827 status = map_checkpath_error((char *)req->inbuf, status);
828 reply_nterror(req, status);
829 END_PROFILE(SMBcheckpath);
833 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name);
834 if (!NT_STATUS_IS_OK(status)) {
835 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
836 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
838 END_PROFILE(SMBcheckpath);
844 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
846 status = unix_convert(conn, name, False, NULL, &sbuf);
847 if (!NT_STATUS_IS_OK(status)) {
851 status = check_name(conn, name);
852 if (!NT_STATUS_IS_OK(status)) {
853 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
857 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
858 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
859 status = map_nt_error_from_unix(errno);
863 if (!S_ISDIR(sbuf.st_mode)) {
864 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
866 END_PROFILE(SMBcheckpath);
870 reply_outbuf(req, 0, 0);
872 END_PROFILE(SMBcheckpath);
877 END_PROFILE(SMBcheckpath);
879 /* We special case this - as when a Windows machine
880 is parsing a path is steps through the components
881 one at a time - if a component fails it expects
882 ERRbadpath, not ERRbadfile.
884 status = map_checkpath_error((char *)req->inbuf, status);
885 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
887 * Windows returns different error codes if
888 * the parent directory is valid but not the
889 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
890 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
891 * if the path is invalid.
893 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
898 reply_nterror(req, status);
901 /****************************************************************************
903 ****************************************************************************/
905 void reply_getatr(connection_struct *conn, struct smb_request *req)
908 SMB_STRUCT_STAT sbuf;
915 START_PROFILE(SMBgetatr);
917 p = smb_buf(req->inbuf) + 1;
918 p += srvstr_get_path((char *)req->inbuf, req->flags2, fname, p,
919 sizeof(fname), 0, STR_TERMINATE, &status);
920 if (!NT_STATUS_IS_OK(status)) {
921 reply_nterror(req, status);
922 END_PROFILE(SMBgetatr);
926 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
928 if (!NT_STATUS_IS_OK(status)) {
929 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
930 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
932 END_PROFILE(SMBgetatr);
935 reply_nterror(req, status);
936 END_PROFILE(SMBgetatr);
940 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
941 under WfWg - weird! */
942 if (*fname == '\0') {
943 mode = aHIDDEN | aDIR;
944 if (!CAN_WRITE(conn)) {
950 status = unix_convert(conn, fname, False, NULL,&sbuf);
951 if (!NT_STATUS_IS_OK(status)) {
952 reply_nterror(req, status);
953 END_PROFILE(SMBgetatr);
956 status = check_name(conn, fname);
957 if (!NT_STATUS_IS_OK(status)) {
958 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
959 reply_nterror(req, status);
960 END_PROFILE(SMBgetatr);
963 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
964 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
965 reply_unixerror(req, ERRDOS,ERRbadfile);
966 END_PROFILE(SMBgetatr);
970 mode = dos_mode(conn,fname,&sbuf);
972 mtime = sbuf.st_mtime;
978 reply_outbuf(req, 10, 0);
980 SSVAL(req->outbuf,smb_vwv0,mode);
981 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
982 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
984 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
986 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
988 if (Protocol >= PROTOCOL_NT1) {
989 SSVAL(req->outbuf, smb_flg2,
990 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
993 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
995 END_PROFILE(SMBgetatr);
999 /****************************************************************************
1001 ****************************************************************************/
1003 void reply_setatr(connection_struct *conn, struct smb_request *req)
1008 SMB_STRUCT_STAT sbuf;
1012 START_PROFILE(SMBsetatr);
1015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1019 p = smb_buf(req->inbuf) + 1;
1020 p += srvstr_get_path((char *)req->inbuf, req->flags2, fname, p,
1021 sizeof(fname), 0, STR_TERMINATE, &status);
1022 if (!NT_STATUS_IS_OK(status)) {
1023 reply_nterror(req, status);
1024 END_PROFILE(SMBsetatr);
1028 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1030 if (!NT_STATUS_IS_OK(status)) {
1031 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1032 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1033 ERRSRV, ERRbadpath);
1034 END_PROFILE(SMBsetatr);
1037 reply_nterror(req, status);
1038 END_PROFILE(SMBsetatr);
1042 status = unix_convert(conn, fname, False, NULL, &sbuf);
1043 if (!NT_STATUS_IS_OK(status)) {
1044 reply_nterror(req, status);
1045 END_PROFILE(SMBsetatr);
1049 status = check_name(conn, fname);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 reply_nterror(req, status);
1052 END_PROFILE(SMBsetatr);
1056 if (fname[0] == '.' && fname[1] == '\0') {
1058 * Not sure here is the right place to catch this
1059 * condition. Might be moved to somewhere else later -- vl
1061 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1062 END_PROFILE(SMBsetatr);
1066 mode = SVAL(req->inbuf,smb_vwv0);
1067 mtime = srv_make_unix_date3(req->inbuf+smb_vwv1);
1069 if (mode != FILE_ATTRIBUTE_NORMAL) {
1070 if (VALID_STAT_OF_DIR(sbuf))
1075 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
1076 reply_unixerror(req, ERRDOS, ERRnoaccess);
1077 END_PROFILE(SMBsetatr);
1082 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
1083 reply_unixerror(req, ERRDOS, ERRnoaccess);
1084 END_PROFILE(SMBsetatr);
1088 reply_outbuf(req, 0, 0);
1090 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1092 END_PROFILE(SMBsetatr);
1096 /****************************************************************************
1098 ****************************************************************************/
1100 void reply_dskattr(connection_struct *conn, struct smb_request *req)
1102 SMB_BIG_UINT dfree,dsize,bsize;
1103 START_PROFILE(SMBdskattr);
1105 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1106 reply_unixerror(req, ERRHRD, ERRgeneral);
1107 END_PROFILE(SMBdskattr);
1111 reply_outbuf(req, 5, 0);
1113 if (Protocol <= PROTOCOL_LANMAN2) {
1114 double total_space, free_space;
1115 /* we need to scale this to a number that DOS6 can handle. We
1116 use floating point so we can handle large drives on systems
1117 that don't have 64 bit integers
1119 we end up displaying a maximum of 2G to DOS systems
1121 total_space = dsize * (double)bsize;
1122 free_space = dfree * (double)bsize;
1124 dsize = (total_space+63*512) / (64*512);
1125 dfree = (free_space+63*512) / (64*512);
1127 if (dsize > 0xFFFF) dsize = 0xFFFF;
1128 if (dfree > 0xFFFF) dfree = 0xFFFF;
1130 SSVAL(req->outbuf,smb_vwv0,dsize);
1131 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1132 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1133 SSVAL(req->outbuf,smb_vwv3,dfree);
1135 SSVAL(req->outbuf,smb_vwv0,dsize);
1136 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1137 SSVAL(req->outbuf,smb_vwv2,512);
1138 SSVAL(req->outbuf,smb_vwv3,dfree);
1141 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1143 END_PROFILE(SMBdskattr);
1147 /****************************************************************************
1149 Can be called from SMBsearch, SMBffirst or SMBfunique.
1150 ****************************************************************************/
1152 void reply_search(connection_struct *conn, struct smb_request *req)
1161 unsigned int numentries = 0;
1162 unsigned int maxentries = 0;
1163 BOOL finished = False;
1169 BOOL check_descend = False;
1170 BOOL expect_close = False;
1172 BOOL mask_contains_wcard = False;
1173 BOOL allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1175 START_PROFILE(SMBsearch);
1178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1179 END_PROFILE(SMBsearch);
1183 if (lp_posix_pathnames()) {
1184 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1185 END_PROFILE(SMBsearch);
1189 *mask = *directory = *fname = 0;
1191 /* If we were called as SMBffirst then we must expect close. */
1192 if(CVAL(req->inbuf,smb_com) == SMBffirst) {
1193 expect_close = True;
1196 reply_outbuf(req, 1, 3);
1197 maxentries = SVAL(req->inbuf,smb_vwv0);
1198 dirtype = SVAL(req->inbuf,smb_vwv1);
1199 p = smb_buf(req->inbuf) + 1;
1200 p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path, p,
1201 sizeof(path), 0, STR_TERMINATE, &nt_status,
1202 &mask_contains_wcard);
1203 if (!NT_STATUS_IS_OK(nt_status)) {
1204 reply_nterror(req, nt_status);
1205 END_PROFILE(SMBsearch);
1209 nt_status = resolve_dfspath_wcard(conn,
1210 req->flags2 & FLAGS2_DFS_PATHNAMES,
1211 path, &mask_contains_wcard);
1212 if (!NT_STATUS_IS_OK(nt_status)) {
1213 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1214 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1215 ERRSRV, ERRbadpath);
1216 END_PROFILE(SMBsearch);
1219 reply_nterror(req, nt_status);
1220 END_PROFILE(SMBsearch);
1225 status_len = SVAL(p, 0);
1228 /* dirtype &= ~aDIR; */
1230 if (status_len == 0) {
1231 SMB_STRUCT_STAT sbuf;
1233 pstrcpy(directory,path);
1234 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1235 if (!NT_STATUS_IS_OK(nt_status)) {
1236 reply_nterror(req, nt_status);
1237 END_PROFILE(SMBsearch);
1241 nt_status = check_name(conn, directory);
1242 if (!NT_STATUS_IS_OK(nt_status)) {
1243 reply_nterror(req, nt_status);
1244 END_PROFILE(SMBsearch);
1248 p = strrchr_m(directory,'/');
1250 pstrcpy(mask,directory);
1251 pstrcpy(directory,".");
1257 if (*directory == '\0') {
1258 pstrcpy(directory,".");
1260 memset((char *)status,'\0',21);
1261 SCVAL(status,0,(dirtype & 0x1F));
1265 memcpy(status,p,21);
1266 status_dirtype = CVAL(status,0) & 0x1F;
1267 if (status_dirtype != (dirtype & 0x1F)) {
1268 dirtype = status_dirtype;
1271 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1272 if (!conn->dirptr) {
1275 string_set(&conn->dirpath,dptr_path(dptr_num));
1276 pstrcpy(mask, dptr_wcard(dptr_num));
1278 * For a 'continue' search we have no string. So
1279 * check from the initial saved string.
1281 mask_contains_wcard = ms_has_wild(mask);
1284 if (status_len == 0) {
1285 nt_status = dptr_create(conn,
1291 mask_contains_wcard,
1294 if (!NT_STATUS_IS_OK(nt_status)) {
1295 reply_nterror(req, nt_status);
1296 END_PROFILE(SMBsearch);
1299 dptr_num = dptr_dnum(conn->dirptr);
1301 dirtype = dptr_attr(dptr_num);
1304 DEBUG(4,("dptr_num is %d\n",dptr_num));
1306 if ((dirtype&0x1F) == aVOLID) {
1307 char buf[DIR_STRUCT_SIZE];
1308 memcpy(buf,status,21);
1309 make_dir_struct(buf,"???????????",volume_label(SNUM(conn)),
1310 0,aVOLID,0,!allow_long_path_components);
1311 dptr_fill(buf+12,dptr_num);
1312 if (dptr_zero(buf+12) && (status_len==0)) {
1317 if (message_push_blob(&req->outbuf,
1318 data_blob_const(buf, sizeof(buf)))
1320 reply_nterror(req, NT_STATUS_NO_MEMORY);
1321 END_PROFILE(SMBsearch);
1329 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1332 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1333 conn->dirpath,lp_dontdescend(SNUM(conn))));
1334 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1335 check_descend = True;
1338 for (i=numentries;(i<maxentries) && !finished;i++) {
1339 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1341 char buf[DIR_STRUCT_SIZE];
1342 memcpy(buf,status,21);
1343 make_dir_struct(buf,mask,fname,size, mode,date,
1344 !allow_long_path_components);
1345 if (!dptr_fill(buf+12,dptr_num)) {
1348 if (message_push_blob(&req->outbuf,
1349 data_blob_const(buf, sizeof(buf)))
1351 reply_nterror(req, NT_STATUS_NO_MEMORY);
1352 END_PROFILE(SMBsearch);
1362 /* If we were called as SMBffirst with smb_search_id == NULL
1363 and no entries were found then return error and close dirptr
1366 if (numentries == 0) {
1367 dptr_close(&dptr_num);
1368 } else if(expect_close && status_len == 0) {
1369 /* Close the dptr - we know it's gone */
1370 dptr_close(&dptr_num);
1373 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1374 if(dptr_num >= 0 && CVAL(req->inbuf,smb_com) == SMBfunique) {
1375 dptr_close(&dptr_num);
1378 if ((numentries == 0) && !mask_contains_wcard) {
1379 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1380 END_PROFILE(SMBsearch);
1384 SSVAL(req->outbuf,smb_vwv0,numentries);
1385 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1386 SCVAL(smb_buf(req->outbuf),0,5);
1387 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1389 /* The replies here are never long name. */
1390 SSVAL(req->outbuf, smb_flg2,
1391 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1392 if (!allow_long_path_components) {
1393 SSVAL(req->outbuf, smb_flg2,
1394 SVAL(req->outbuf, smb_flg2)
1395 & (~FLAGS2_LONG_PATH_COMPONENTS));
1398 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1399 SSVAL(req->outbuf, smb_flg2,
1400 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1402 if ((! *directory) && dptr_path(dptr_num))
1403 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1405 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1406 smb_fn_name(CVAL(req->inbuf,smb_com)),
1407 mask, directory, dirtype, numentries, maxentries ) );
1409 END_PROFILE(SMBsearch);
1413 /****************************************************************************
1414 Reply to a fclose (stop directory search).
1415 ****************************************************************************/
1417 void reply_fclose(connection_struct *conn, struct smb_request *req)
1425 BOOL path_contains_wcard = False;
1427 START_PROFILE(SMBfclose);
1429 if (lp_posix_pathnames()) {
1430 reply_unknown_new(req, CVAL(req->inbuf, smb_com));
1431 END_PROFILE(SMBfclose);
1435 p = smb_buf(req->inbuf) + 1;
1436 p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path, p,
1437 sizeof(path), 0, STR_TERMINATE, &err,
1438 &path_contains_wcard);
1439 if (!NT_STATUS_IS_OK(err)) {
1440 reply_nterror(req, err);
1441 END_PROFILE(SMBfclose);
1445 status_len = SVAL(p,0);
1448 if (status_len == 0) {
1449 reply_doserror(req, ERRSRV, ERRsrverror);
1450 END_PROFILE(SMBfclose);
1454 memcpy(status,p,21);
1456 if(dptr_fetch(status+12,&dptr_num)) {
1457 /* Close the dptr - we know it's gone */
1458 dptr_close(&dptr_num);
1461 reply_outbuf(req, 1, 0);
1462 SSVAL(req->outbuf,smb_vwv0,0);
1464 DEBUG(3,("search close\n"));
1466 END_PROFILE(SMBfclose);
1470 /****************************************************************************
1472 ****************************************************************************/
1474 void reply_open(connection_struct *conn, struct smb_request *req)
1481 SMB_STRUCT_STAT sbuf;
1488 uint32 create_disposition;
1489 uint32 create_options = 0;
1492 START_PROFILE(SMBopen);
1495 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1496 END_PROFILE(SMBopen);
1500 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1501 deny_mode = SVAL(req->inbuf,smb_vwv0);
1502 dos_attr = SVAL(req->inbuf,smb_vwv1);
1504 srvstr_get_path((char *)req->inbuf, req->flags2, fname,
1505 smb_buf(req->inbuf)+1, sizeof(fname), 0,
1506 STR_TERMINATE, &status);
1507 if (!NT_STATUS_IS_OK(status)) {
1508 reply_nterror(req, status);
1509 END_PROFILE(SMBopen);
1513 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1515 if (!NT_STATUS_IS_OK(status)) {
1516 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1517 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1518 ERRSRV, ERRbadpath);
1519 END_PROFILE(SMBopen);
1522 reply_nterror(req, status);
1523 END_PROFILE(SMBopen);
1527 status = unix_convert(conn, fname, False, NULL, &sbuf);
1528 if (!NT_STATUS_IS_OK(status)) {
1529 reply_nterror(req, status);
1530 END_PROFILE(SMBopen);
1534 status = check_name(conn, fname);
1535 if (!NT_STATUS_IS_OK(status)) {
1536 reply_nterror(req, status);
1537 END_PROFILE(SMBopen);
1541 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1542 &access_mask, &share_mode, &create_disposition, &create_options)) {
1543 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1544 END_PROFILE(SMBopen);
1548 status = open_file_ntcreate(conn, req, fname, &sbuf,
1557 if (!NT_STATUS_IS_OK(status)) {
1558 if (open_was_deferred(req->mid)) {
1559 /* We have re-scheduled this call. */
1560 END_PROFILE(SMBopen);
1563 reply_nterror(req, status);
1564 END_PROFILE(SMBopen);
1568 size = sbuf.st_size;
1569 fattr = dos_mode(conn,fname,&sbuf);
1570 mtime = sbuf.st_mtime;
1573 DEBUG(3,("attempt to open a directory %s\n",fname));
1574 close_file(fsp,ERROR_CLOSE);
1575 reply_doserror(req, ERRDOS,ERRnoaccess);
1576 END_PROFILE(SMBopen);
1580 reply_outbuf(req, 7, 0);
1581 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1582 SSVAL(req->outbuf,smb_vwv1,fattr);
1583 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1584 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1586 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1588 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1589 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1591 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1592 SCVAL(req->outbuf,smb_flg,
1593 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1596 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1597 SCVAL(req->outbuf,smb_flg,
1598 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1600 END_PROFILE(SMBopen);
1604 /****************************************************************************
1605 Reply to an open and X.
1606 ****************************************************************************/
1608 void reply_open_and_X(connection_struct *conn, struct smb_request *req)
1614 /* Breakout the oplock request bits so we can set the
1615 reply bits separately. */
1616 int ex_oplock_request;
1617 int core_oplock_request;
1620 int smb_sattr = SVAL(req->inbuf,smb_vwv4);
1621 uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
1626 SMB_STRUCT_STAT sbuf;
1630 SMB_BIG_UINT allocation_size;
1631 ssize_t retval = -1;
1634 uint32 create_disposition;
1635 uint32 create_options = 0;
1637 START_PROFILE(SMBopenX);
1639 if (req->wct < 15) {
1640 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1641 END_PROFILE(SMBopenX);
1645 open_flags = SVAL(req->inbuf,smb_vwv2);
1646 deny_mode = SVAL(req->inbuf,smb_vwv3);
1647 smb_attr = SVAL(req->inbuf,smb_vwv5);
1648 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1649 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1650 oplock_request = ex_oplock_request | core_oplock_request;
1651 smb_ofun = SVAL(req->inbuf,smb_vwv8);
1652 allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
1654 /* If it's an IPC, pass off the pipe handler. */
1656 if (lp_nt_pipe_support()) {
1657 reply_open_pipe_and_X(conn, req);
1659 reply_doserror(req, ERRSRV, ERRaccess);
1661 END_PROFILE(SMBopenX);
1665 /* XXXX we need to handle passed times, sattr and flags */
1666 srvstr_get_path((char *)req->inbuf, req->flags2, fname,
1667 smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE,
1669 if (!NT_STATUS_IS_OK(status)) {
1670 reply_nterror(req, status);
1671 END_PROFILE(SMBopenX);
1675 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1677 if (!NT_STATUS_IS_OK(status)) {
1678 END_PROFILE(SMBopenX);
1679 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1680 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1681 ERRSRV, ERRbadpath);
1684 reply_nterror(req, status);
1688 status = unix_convert(conn, fname, False, NULL, &sbuf);
1689 if (!NT_STATUS_IS_OK(status)) {
1690 reply_nterror(req, status);
1691 END_PROFILE(SMBopenX);
1695 status = check_name(conn, fname);
1696 if (!NT_STATUS_IS_OK(status)) {
1697 reply_nterror(req, status);
1698 END_PROFILE(SMBopenX);
1702 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1705 &create_disposition,
1707 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1708 END_PROFILE(SMBopenX);
1712 status = open_file_ntcreate(conn, req, fname, &sbuf,
1721 if (!NT_STATUS_IS_OK(status)) {
1722 END_PROFILE(SMBopenX);
1723 if (open_was_deferred(req->mid)) {
1724 /* We have re-scheduled this call. */
1727 reply_nterror(req, status);
1731 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1732 if the file is truncated or created. */
1733 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1734 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1735 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1736 close_file(fsp,ERROR_CLOSE);
1737 reply_nterror(req, NT_STATUS_DISK_FULL);
1738 END_PROFILE(SMBopenX);
1741 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1743 close_file(fsp,ERROR_CLOSE);
1744 reply_nterror(req, NT_STATUS_DISK_FULL);
1745 END_PROFILE(SMBopenX);
1748 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1751 fattr = dos_mode(conn,fname,&sbuf);
1752 mtime = sbuf.st_mtime;
1754 close_file(fsp,ERROR_CLOSE);
1755 reply_doserror(req, ERRDOS, ERRnoaccess);
1756 END_PROFILE(SMBopenX);
1760 /* If the caller set the extended oplock request bit
1761 and we granted one (by whatever means) - set the
1762 correct bit for extended oplock reply.
1765 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1766 smb_action |= EXTENDED_OPLOCK_GRANTED;
1769 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1770 smb_action |= EXTENDED_OPLOCK_GRANTED;
1773 /* If the caller set the core oplock request bit
1774 and we granted one (by whatever means) - set the
1775 correct bit for core oplock reply.
1778 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1779 reply_outbuf(req, 19, 0);
1781 reply_outbuf(req, 15, 0);
1784 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1785 SCVAL(req->outbuf, smb_flg,
1786 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1789 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1790 SCVAL(req->outbuf, smb_flg,
1791 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1794 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1795 SSVAL(req->outbuf,smb_vwv3,fattr);
1796 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1797 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1799 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1801 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1802 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1803 SSVAL(req->outbuf,smb_vwv11,smb_action);
1805 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1806 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1809 END_PROFILE(SMBopenX);
1810 chain_reply_new(req);
1814 /****************************************************************************
1815 Reply to a SMBulogoffX.
1816 conn POINTER CAN BE NULL HERE !
1817 ****************************************************************************/
1819 void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
1823 START_PROFILE(SMBulogoffX);
1825 vuser = get_valid_user_struct(req->vuid);
1828 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
1832 /* in user level security we are supposed to close any files
1833 open by this user */
1834 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
1835 file_close_user(req->vuid);
1838 invalidate_vuid(req->vuid);
1840 reply_outbuf(req, 2, 0);
1842 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
1844 END_PROFILE(SMBulogoffX);
1845 chain_reply_new(req);
1848 /****************************************************************************
1849 Reply to a mknew or a create.
1850 ****************************************************************************/
1852 void reply_mknew(connection_struct *conn, struct smb_request *req)
1857 struct timespec ts[2];
1859 int oplock_request = 0;
1860 SMB_STRUCT_STAT sbuf;
1862 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1863 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1864 uint32 create_disposition;
1865 uint32 create_options = 0;
1867 START_PROFILE(SMBcreate);
1870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1871 END_PROFILE(SMBcreate);
1875 fattr = SVAL(req->inbuf,smb_vwv0);
1876 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1877 com = SVAL(req->inbuf,smb_com);
1879 ts[1] =convert_time_t_to_timespec(
1880 srv_make_unix_date3(req->inbuf + smb_vwv1));
1883 srvstr_get_path((char *)req->inbuf, req->flags2, fname,
1884 smb_buf(req->inbuf) + 1, sizeof(fname), 0,
1885 STR_TERMINATE, &status);
1886 if (!NT_STATUS_IS_OK(status)) {
1887 reply_nterror(req, status);
1888 END_PROFILE(SMBcreate);
1892 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
1894 if (!NT_STATUS_IS_OK(status)) {
1895 END_PROFILE(SMBcreate);
1896 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1897 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1898 ERRSRV, ERRbadpath);
1901 reply_nterror(req, status);
1905 status = unix_convert(conn, fname, False, NULL, &sbuf);
1906 if (!NT_STATUS_IS_OK(status)) {
1907 reply_nterror(req, status);
1908 END_PROFILE(SMBcreate);
1912 status = check_name(conn, fname);
1913 if (!NT_STATUS_IS_OK(status)) {
1914 reply_nterror(req, status);
1915 END_PROFILE(SMBcreate);
1919 if (fattr & aVOLID) {
1920 DEBUG(0,("Attempt to create file (%s) with volid set - "
1921 "please report this\n", fname));
1924 if(com == SMBmknew) {
1925 /* We should fail if file exists. */
1926 create_disposition = FILE_CREATE;
1928 /* Create if file doesn't exist, truncate if it does. */
1929 create_disposition = FILE_OVERWRITE_IF;
1932 /* Open file using ntcreate. */
1933 status = open_file_ntcreate(conn, req, fname, &sbuf,
1942 if (!NT_STATUS_IS_OK(status)) {
1943 END_PROFILE(SMBcreate);
1944 if (open_was_deferred(req->mid)) {
1945 /* We have re-scheduled this call. */
1948 reply_nterror(req, status);
1952 ts[0] = get_atimespec(&sbuf); /* atime. */
1953 file_ntimes(conn, fname, ts);
1955 reply_outbuf(req, 1, 0);
1957 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1959 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1960 SCVAL(req->outbuf,smb_flg,
1961 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1964 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1965 SCVAL(req->outbuf,smb_flg,
1966 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1969 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1970 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
1971 fname, fsp->fh->fd, (unsigned int)fattr ) );
1973 END_PROFILE(SMBcreate);
1977 /****************************************************************************
1978 Reply to a create temporary file.
1979 ****************************************************************************/
1981 void reply_ctemp(connection_struct *conn, struct smb_request *req)
1988 SMB_STRUCT_STAT sbuf;
1992 START_PROFILE(SMBctemp);
1995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1996 END_PROFILE(SMBctemp);
2000 fattr = SVAL(req->inbuf,smb_vwv0);
2001 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2003 srvstr_get_path((char *)req->inbuf, req->flags2, fname,
2004 smb_buf(req->inbuf)+1, sizeof(fname), 0, STR_TERMINATE,
2006 if (!NT_STATUS_IS_OK(status)) {
2007 reply_nterror(req, status);
2008 END_PROFILE(SMBctemp);
2012 pstrcat(fname,"/TMXXXXXX");
2014 pstrcat(fname,"TMXXXXXX");
2017 status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
2019 if (!NT_STATUS_IS_OK(status)) {
2020 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2021 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2022 ERRSRV, ERRbadpath);
2023 END_PROFILE(SMBctemp);
2026 reply_nterror(req, status);
2027 END_PROFILE(SMBctemp);
2031 status = unix_convert(conn, fname, False, NULL, &sbuf);
2032 if (!NT_STATUS_IS_OK(status)) {
2033 reply_nterror(req, status);
2034 END_PROFILE(SMBctemp);
2038 status = check_name(conn, fname);
2039 if (!NT_STATUS_IS_OK(status)) {
2040 reply_nterror(req, status);
2041 END_PROFILE(SMBctemp);
2045 tmpfd = smb_mkstemp(fname);
2047 reply_unixerror(req, ERRDOS, ERRnoaccess);
2048 END_PROFILE(SMBctemp);
2052 SMB_VFS_STAT(conn,fname,&sbuf);
2054 /* We should fail if file does not exist. */
2055 status = open_file_ntcreate(conn, req, fname, &sbuf,
2056 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
2057 FILE_SHARE_READ|FILE_SHARE_WRITE,
2064 /* close fd from smb_mkstemp() */
2067 if (!NT_STATUS_IS_OK(status)) {
2068 if (open_was_deferred(req->mid)) {
2069 /* We have re-scheduled this call. */
2070 END_PROFILE(SMBctemp);
2073 reply_nterror(req, status);
2074 END_PROFILE(SMBctemp);
2078 reply_outbuf(req, 1, 0);
2079 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2081 /* the returned filename is relative to the directory */
2082 s = strrchr_m(fname, '/');
2090 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2091 thing in the byte section. JRA */
2092 SSVALS(p, 0, -1); /* what is this? not in spec */
2094 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2096 reply_nterror(req, NT_STATUS_NO_MEMORY);
2097 END_PROFILE(SMBctemp);
2101 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2102 SCVAL(req->outbuf, smb_flg,
2103 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2106 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2107 SCVAL(req->outbuf, smb_flg,
2108 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2111 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
2112 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
2113 (unsigned int)sbuf.st_mode ) );
2115 END_PROFILE(SMBctemp);
2119 /*******************************************************************
2120 Check if a user is allowed to rename a file.
2121 ********************************************************************/
2123 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2124 uint16 dirtype, SMB_STRUCT_STAT *pst)
2128 if (!CAN_WRITE(conn)) {
2129 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2132 fmode = dos_mode(conn, fsp->fsp_name, pst);
2133 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2134 return NT_STATUS_NO_SUCH_FILE;
2137 if (S_ISDIR(pst->st_mode)) {
2138 return NT_STATUS_OK;
2141 if (fsp->access_mask & DELETE_ACCESS) {
2142 return NT_STATUS_OK;
2145 return NT_STATUS_ACCESS_DENIED;
2148 /*******************************************************************
2149 * unlink a file with all relevant access checks
2150 *******************************************************************/
2152 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
2153 char *fname, uint32 dirtype)
2155 SMB_STRUCT_STAT sbuf;
2158 uint32 dirtype_orig = dirtype;
2161 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2163 if (!CAN_WRITE(conn)) {
2164 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2167 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2168 return map_nt_error_from_unix(errno);
2171 fattr = dos_mode(conn,fname,&sbuf);
2173 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2174 dirtype = aDIR|aARCH|aRONLY;
2177 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2179 return NT_STATUS_NO_SUCH_FILE;
2182 if (!dir_check_ftype(conn, fattr, dirtype)) {
2184 return NT_STATUS_FILE_IS_A_DIRECTORY;
2186 return NT_STATUS_NO_SUCH_FILE;
2189 if (dirtype_orig & 0x8000) {
2190 /* These will never be set for POSIX. */
2191 return NT_STATUS_NO_SUCH_FILE;
2195 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2196 return NT_STATUS_FILE_IS_A_DIRECTORY;
2199 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2200 return NT_STATUS_NO_SUCH_FILE;
2203 if (dirtype & 0xFF00) {
2204 /* These will never be set for POSIX. */
2205 return NT_STATUS_NO_SUCH_FILE;
2210 return NT_STATUS_NO_SUCH_FILE;
2213 /* Can't delete a directory. */
2215 return NT_STATUS_FILE_IS_A_DIRECTORY;
2220 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2221 return NT_STATUS_OBJECT_NAME_INVALID;
2222 #endif /* JRATEST */
2224 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2226 On a Windows share, a file with read-only dosmode can be opened with
2227 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2228 fails with NT_STATUS_CANNOT_DELETE error.
2230 This semantic causes a problem that a user can not
2231 rename a file with read-only dosmode on a Samba share
2232 from a Windows command prompt (i.e. cmd.exe, but can rename
2233 from Windows Explorer).
2236 if (!lp_delete_readonly(SNUM(conn))) {
2237 if (fattr & aRONLY) {
2238 return NT_STATUS_CANNOT_DELETE;
2242 /* On open checks the open itself will check the share mode, so
2243 don't do it here as we'll get it wrong. */
2245 status = open_file_ntcreate(conn, req, fname, &sbuf,
2250 FILE_ATTRIBUTE_NORMAL,
2251 req != NULL ? 0 : INTERNAL_OPEN_ONLY,
2254 if (!NT_STATUS_IS_OK(status)) {
2255 DEBUG(10, ("open_file_ntcreate failed: %s\n",
2256 nt_errstr(status)));
2260 /* The set is across all open files on this dev/inode pair. */
2261 if (!set_delete_on_close(fsp, True, ¤t_user.ut)) {
2262 close_file(fsp, NORMAL_CLOSE);
2263 return NT_STATUS_ACCESS_DENIED;
2266 return close_file(fsp,NORMAL_CLOSE);
2269 /****************************************************************************
2270 The guts of the unlink command, split out so it may be called by the NT SMB
2272 ****************************************************************************/
2274 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2275 uint32 dirtype, char *name, BOOL has_wild)
2281 NTSTATUS status = NT_STATUS_OK;
2282 SMB_STRUCT_STAT sbuf;
2284 *directory = *mask = 0;
2286 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
2287 if (!NT_STATUS_IS_OK(status)) {
2291 p = strrchr_m(name,'/');
2293 pstrcpy(directory,".");
2297 pstrcpy(directory,name);
2302 * We should only check the mangled cache
2303 * here if unix_convert failed. This means
2304 * that the path in 'mask' doesn't exist
2305 * on the file system and so we need to look
2306 * for a possible mangle. This patch from
2307 * Tine Smukavec <valentin.smukavec@hermes.si>.
2310 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
2311 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
2314 pstrcat(directory,"/");
2315 pstrcat(directory,mask);
2317 dirtype = FILE_ATTRIBUTE_NORMAL;
2320 status = check_name(conn, directory);
2321 if (!NT_STATUS_IS_OK(status)) {
2325 status = do_unlink(conn, req, directory, dirtype);
2326 if (!NT_STATUS_IS_OK(status)) {
2332 struct smb_Dir *dir_hnd = NULL;
2336 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2337 return NT_STATUS_OBJECT_NAME_INVALID;
2340 if (strequal(mask,"????????.???")) {
2344 status = check_name(conn, directory);
2345 if (!NT_STATUS_IS_OK(status)) {
2349 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2350 if (dir_hnd == NULL) {
2351 return map_nt_error_from_unix(errno);
2354 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2355 the pattern matches against the long name, otherwise the short name
2356 We don't implement this yet XXXX
2359 status = NT_STATUS_NO_SUCH_FILE;
2361 while ((dname = ReadDirName(dir_hnd, &offset))) {
2364 pstrcpy(fname,dname);
2366 if (!is_visible_file(conn, directory, dname, &st, True)) {
2370 /* Quick check for "." and ".." */
2371 if (fname[0] == '.') {
2372 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2377 if(!mask_match(fname, mask, conn->case_sensitive)) {
2381 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2383 status = check_name(conn, fname);
2384 if (!NT_STATUS_IS_OK(status)) {
2389 status = do_unlink(conn, req, fname, dirtype);
2390 if (!NT_STATUS_IS_OK(status)) {
2395 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2401 if (count == 0 && NT_STATUS_IS_OK(status)) {
2402 status = map_nt_error_from_unix(errno);
2408 /****************************************************************************
2410 ****************************************************************************/
2412 void reply_unlink(connection_struct *conn, struct smb_request *req)
2417 BOOL path_contains_wcard = False;
2419 START_PROFILE(SMBunlink);
2422 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2423 END_PROFILE(SMBunlink);
2427 dirtype = SVAL(req->inbuf,smb_vwv0);
2429 srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name,
2430 smb_buf(req->inbuf) + 1, sizeof(name), 0,
2431 STR_TERMINATE, &status, &path_contains_wcard);
2432 if (!NT_STATUS_IS_OK(status)) {
2433 reply_nterror(req, status);
2434 END_PROFILE(SMBunlink);
2438 status = resolve_dfspath_wcard(conn,
2439 req->flags2 & FLAGS2_DFS_PATHNAMES,
2440 name, &path_contains_wcard);
2441 if (!NT_STATUS_IS_OK(status)) {
2442 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2443 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2444 ERRSRV, ERRbadpath);
2445 END_PROFILE(SMBunlink);
2448 reply_nterror(req, status);
2449 END_PROFILE(SMBunlink);
2453 DEBUG(3,("reply_unlink : %s\n",name));
2455 status = unlink_internals(conn, req, dirtype, name,
2456 path_contains_wcard);
2457 if (!NT_STATUS_IS_OK(status)) {
2458 if (open_was_deferred(req->mid)) {
2459 /* We have re-scheduled this call. */
2460 END_PROFILE(SMBunlink);
2463 reply_nterror(req, status);
2464 END_PROFILE(SMBunlink);
2468 reply_outbuf(req, 0, 0);
2469 END_PROFILE(SMBunlink);
2474 /****************************************************************************
2476 ****************************************************************************/
2478 static void fail_readraw(void)
2481 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2483 exit_server_cleanly(errstr);
2486 /****************************************************************************
2487 Fake (read/write) sendfile. Returns -1 on read or write fail.
2488 ****************************************************************************/
2490 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2494 size_t tosend = nread;
2501 bufsize = MIN(nread, 65536);
2503 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2507 while (tosend > 0) {
2511 if (tosend > bufsize) {
2516 ret = read_file(fsp,buf,startpos,cur_read);
2522 /* If we had a short read, fill with zeros. */
2523 if (ret < cur_read) {
2524 memset(buf, '\0', cur_read - ret);
2527 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2532 startpos += cur_read;
2536 return (ssize_t)nread;
2539 /****************************************************************************
2540 Return a readbraw error (4 bytes of zero).
2541 ****************************************************************************/
2543 static void reply_readbraw_error(void)
2547 if (write_data(smbd_server_fd(),header,4) != 4) {
2552 /****************************************************************************
2553 Use sendfile in readbraw.
2554 ****************************************************************************/
2556 void send_file_readbraw(connection_struct *conn,
2562 char *outbuf = NULL;
2565 #if defined(WITH_SENDFILE)
2567 * We can only use sendfile on a non-chained packet
2568 * but we can use on a non-oplocked file. tridge proved this
2569 * on a train in Germany :-). JRA.
2570 * reply_readbraw has already checked the length.
2573 if ( (chain_size == 0) && (nread > 0) &&
2574 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2576 DATA_BLOB header_blob;
2578 _smb_setlen(header,nread);
2579 header_blob = data_blob_const(header, 4);
2581 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd,
2582 &header_blob, startpos, nread) == -1) {
2583 /* Returning ENOSYS means no data at all was sent.
2584 * Do this as a normal read. */
2585 if (errno == ENOSYS) {
2586 goto normal_readbraw;
2590 * Special hack for broken Linux with no working sendfile. If we
2591 * return EINTR we sent the header but not the rest of the data.
2592 * Fake this up by doing read/write calls.
2594 if (errno == EINTR) {
2595 /* Ensure we don't do this again. */
2596 set_use_sendfile(SNUM(conn), False);
2597 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2599 if (fake_sendfile(fsp, startpos, nread) == -1) {
2600 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2601 fsp->fsp_name, strerror(errno) ));
2602 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2607 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2608 fsp->fsp_name, strerror(errno) ));
2609 exit_server_cleanly("send_file_readbraw sendfile failed");
2618 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2620 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2621 (unsigned)(nread+4)));
2622 reply_readbraw_error();
2627 ret = read_file(fsp,outbuf+4,startpos,nread);
2628 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2637 _smb_setlen(outbuf,ret);
2638 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2641 TALLOC_FREE(outbuf);
2644 /****************************************************************************
2645 Reply to a readbraw (core+ protocol).
2646 ****************************************************************************/
2648 void reply_readbraw(connection_struct *conn, struct smb_request *req)
2650 ssize_t maxcount,mincount;
2657 START_PROFILE(SMBreadbraw);
2659 if (srv_is_signing_active()) {
2660 exit_server_cleanly("reply_readbraw: SMB signing is active - "
2661 "raw reads/writes are disallowed.");
2665 reply_readbraw_error();
2666 END_PROFILE(SMBreadbraw);
2671 * Special check if an oplock break has been issued
2672 * and the readraw request croses on the wire, we must
2673 * return a zero length response here.
2676 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2679 * We have to do a check_fsp by hand here, as
2680 * we must always return 4 zero bytes on error,
2684 if (!fsp || !conn || conn != fsp->conn ||
2685 current_user.vuid != fsp->vuid ||
2686 fsp->is_directory || fsp->fh->fd == -1) {
2688 * fsp could be NULL here so use the value from the packet. JRA.
2690 DEBUG(3,("reply_readbraw: fnum %d not valid "
2692 (int)SVAL(req->inbuf,smb_vwv0)));
2693 reply_readbraw_error();
2694 END_PROFILE(SMBreadbraw);
2698 /* Do a "by hand" version of CHECK_READ. */
2699 if (!(fsp->can_read ||
2700 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2701 (fsp->access_mask & FILE_EXECUTE)))) {
2702 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2703 (int)SVAL(req->inbuf,smb_vwv0)));
2704 reply_readbraw_error();
2705 END_PROFILE(SMBreadbraw);
2709 flush_write_cache(fsp, READRAW_FLUSH);
2711 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1);
2712 if(req->wct == 10) {
2714 * This is a large offset (64 bit) read.
2716 #ifdef LARGE_SMB_OFF_T
2718 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv8)) << 32);
2720 #else /* !LARGE_SMB_OFF_T */
2723 * Ensure we haven't been sent a >32 bit offset.
2726 if(IVAL(req->inbuf,smb_vwv8) != 0) {
2727 DEBUG(0,("reply_readbraw: large offset "
2728 "(%x << 32) used and we don't support "
2729 "64 bit offsets.\n",
2730 (unsigned int)IVAL(req->inbuf,smb_vwv8) ));
2731 reply_readbraw_error();
2732 END_PROFILE(SMBreadbraw);
2736 #endif /* LARGE_SMB_OFF_T */
2739 DEBUG(0,("reply_readbraw: negative 64 bit "
2740 "readraw offset (%.0f) !\n",
2741 (double)startpos ));
2742 reply_readbraw_error();
2743 END_PROFILE(SMBreadbraw);
2748 maxcount = (SVAL(req->inbuf,smb_vwv3) & 0xFFFF);
2749 mincount = (SVAL(req->inbuf,smb_vwv4) & 0xFFFF);
2751 /* ensure we don't overrun the packet size */
2752 maxcount = MIN(65535,maxcount);
2754 if (is_locked(fsp,(uint32)req->smbpid,
2755 (SMB_BIG_UINT)maxcount,
2756 (SMB_BIG_UINT)startpos,
2758 reply_readbraw_error();
2759 END_PROFILE(SMBreadbraw);
2763 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2767 if (startpos >= size) {
2770 nread = MIN(maxcount,(size - startpos));
2773 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2774 if (nread < mincount)
2778 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
2779 "min=%lu nread=%lu\n",
2780 fsp->fnum, (double)startpos,
2781 (unsigned long)maxcount,
2782 (unsigned long)mincount,
2783 (unsigned long)nread ) );
2785 send_file_readbraw(conn, fsp, startpos, nread, mincount);
2787 DEBUG(5,("reply_readbraw finished\n"));
2788 END_PROFILE(SMBreadbraw);
2792 #define DBGC_CLASS DBGC_LOCKING
2794 /****************************************************************************
2795 Reply to a lockread (core+ protocol).
2796 ****************************************************************************/
2798 void reply_lockread(connection_struct *conn, struct smb_request *req)
2806 struct byte_range_lock *br_lck = NULL;
2808 START_PROFILE(SMBlockread);
2811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2812 END_PROFILE(SMBlockread);
2816 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2818 if (!check_fsp(conn, req, fsp, ¤t_user)) {
2819 END_PROFILE(SMBlockread);
2823 if (!CHECK_READ(fsp,req->inbuf)) {
2824 reply_doserror(req, ERRDOS, ERRbadaccess);
2825 END_PROFILE(SMBlockread);
2829 release_level_2_oplocks_on_change(fsp);
2831 numtoread = SVAL(req->inbuf,smb_vwv1);
2832 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
2834 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
2836 reply_outbuf(req, 5, numtoread + 3);
2838 data = smb_buf(req->outbuf) + 3;
2841 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2842 * protocol request that predates the read/write lock concept.
2843 * Thus instead of asking for a read lock here we need to ask
2844 * for a write lock. JRA.
2845 * Note that the requested lock size is unaffected by max_recv.
2848 br_lck = do_lock(smbd_messaging_context(),
2851 (SMB_BIG_UINT)numtoread,
2852 (SMB_BIG_UINT)startpos,
2855 False, /* Non-blocking lock. */
2858 TALLOC_FREE(br_lck);
2860 if (NT_STATUS_V(status)) {
2861 reply_nterror(req, status);
2862 END_PROFILE(SMBlockread);
2867 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2870 if (numtoread > max_recv) {
2871 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2872 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2873 (unsigned int)numtoread, (unsigned int)max_recv ));
2874 numtoread = MIN(numtoread,max_recv);
2876 nread = read_file(fsp,data,startpos,numtoread);
2879 reply_unixerror(req, ERRDOS, ERRnoaccess);
2880 END_PROFILE(SMBlockread);
2884 set_message(NULL, (char *)req->outbuf, 5, nread+3, False);
2886 SSVAL(req->outbuf,smb_vwv0,nread);
2887 SSVAL(req->outbuf,smb_vwv5,nread+3);
2888 SSVAL(smb_buf(req->outbuf),1,nread);
2890 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2891 fsp->fnum, (int)numtoread, (int)nread));
2893 END_PROFILE(SMBlockread);
2898 #define DBGC_CLASS DBGC_ALL
2900 /****************************************************************************
2902 ****************************************************************************/
2904 void reply_read(connection_struct *conn, struct smb_request *req)
2913 START_PROFILE(SMBread);
2916 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2917 END_PROFILE(SMBread);
2921 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
2923 if (!check_fsp(conn, req, fsp, ¤t_user)) {
2924 END_PROFILE(SMBread);
2928 if (!CHECK_READ(fsp,req->inbuf)) {
2929 reply_doserror(req, ERRDOS, ERRbadaccess);
2930 END_PROFILE(SMBread);
2934 numtoread = SVAL(req->inbuf,smb_vwv1);
2935 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
2937 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2940 * The requested read size cannot be greater than max_recv. JRA.
2942 if (numtoread > max_recv) {
2943 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2944 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2945 (unsigned int)numtoread, (unsigned int)max_recv ));
2946 numtoread = MIN(numtoread,max_recv);
2949 reply_outbuf(req, 5, numtoread+3);
2951 data = smb_buf(req->outbuf) + 3;
2953 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtoread,
2954 (SMB_BIG_UINT)startpos, READ_LOCK)) {
2955 reply_doserror(req, ERRDOS,ERRlock);
2956 END_PROFILE(SMBread);
2961 nread = read_file(fsp,data,startpos,numtoread);
2964 reply_unixerror(req, ERRDOS,ERRnoaccess);
2965 END_PROFILE(SMBread);
2969 set_message(NULL, (char *)req->outbuf, 5, nread+3, False);
2971 SSVAL(req->outbuf,smb_vwv0,nread);
2972 SSVAL(req->outbuf,smb_vwv5,nread+3);
2973 SCVAL(smb_buf(req->outbuf),0,1);
2974 SSVAL(smb_buf(req->outbuf),1,nread);
2976 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2977 fsp->fnum, (int)numtoread, (int)nread ) );
2979 END_PROFILE(SMBread);
2983 /****************************************************************************
2985 ****************************************************************************/
2987 static int setup_readX_header(const uint8 *inbuf, uint8 *outbuf,
2993 outsize = set_message((char *)inbuf, (char *)outbuf,12,smb_maxcnt,
2995 data = smb_buf(outbuf);
2997 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2998 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2999 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
3000 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3001 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
3002 SCVAL(outbuf,smb_vwv0,0xFF);
3003 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3004 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3008 /****************************************************************************
3009 Reply to a read and X - possibly using sendfile.
3010 ****************************************************************************/
3012 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3013 files_struct *fsp, SMB_OFF_T startpos,
3016 SMB_STRUCT_STAT sbuf;
3019 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3020 reply_unixerror(req, ERRDOS, ERRnoaccess);
3024 if (startpos > sbuf.st_size) {
3026 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
3027 smb_maxcnt = (sbuf.st_size - startpos);
3030 if (smb_maxcnt == 0) {
3034 #if defined(WITH_SENDFILE)
3036 * We can only use sendfile on a non-chained packet
3037 * but we can use on a non-oplocked file. tridge proved this
3038 * on a train in Germany :-). JRA.
3041 if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
3042 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
3043 uint8 headerbuf[smb_size + 12 * 2];
3047 * Set up the packet header before send. We
3048 * assume here the sendfile will work (get the
3049 * correct amount of data).
3052 header = data_blob_const(headerbuf, sizeof(headerbuf));
3054 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3055 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
3057 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
3058 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
3059 if (errno == ENOSYS) {
3064 * Special hack for broken Linux with no working sendfile. If we
3065 * return EINTR we sent the header but not the rest of the data.
3066 * Fake this up by doing read/write calls.
3069 if (errno == EINTR) {
3070 /* Ensure we don't do this again. */
3071 set_use_sendfile(SNUM(conn), False);
3072 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3073 nread = fake_sendfile(fsp, startpos,
3076 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3077 fsp->fsp_name, strerror(errno) ));
3078 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3080 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3081 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3082 /* No outbuf here means successful sendfile. */
3083 TALLOC_FREE(req->outbuf);
3087 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
3088 fsp->fsp_name, strerror(errno) ));
3089 exit_server_cleanly("send_file_readX sendfile failed");
3092 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3093 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3094 /* No outbuf here means successful sendfile. */
3095 TALLOC_FREE(req->outbuf);
3103 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3104 uint8 headerbuf[smb_size + 2*12];
3106 construct_reply_common((char *)req->inbuf, (char *)headerbuf);
3107 setup_readX_header(req->inbuf, headerbuf, smb_maxcnt);
3109 /* Send out the header. */
3110 if (write_data(smbd_server_fd(), (char *)headerbuf,
3111 sizeof(headerbuf)) != sizeof(headerbuf)) {
3112 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
3113 fsp->fsp_name, strerror(errno) ));
3114 exit_server_cleanly("send_file_readX sendfile failed");
3116 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3118 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
3119 fsp->fsp_name, strerror(errno) ));
3120 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3122 TALLOC_FREE(req->outbuf);
3125 reply_outbuf(req, 12, smb_maxcnt);
3127 nread = read_file(fsp, smb_buf(req->outbuf), startpos,
3130 reply_unixerror(req, ERRDOS, ERRnoaccess);
3134 setup_readX_header(req->inbuf, req->outbuf, nread);
3136 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3137 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3139 chain_reply_new(req);
3145 /****************************************************************************
3146 Reply to a read and X.
3147 ****************************************************************************/
3149 void reply_read_and_X(connection_struct *conn, struct smb_request *req)
3154 BOOL big_readX = False;
3156 size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
3159 START_PROFILE(SMBreadX);
3161 if ((req->wct != 10) && (req->wct != 12)) {
3162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3166 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3167 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3168 smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
3170 /* If it's an IPC, pass off the pipe handler. */
3172 reply_pipe_read_and_X(req);
3173 END_PROFILE(SMBreadX);
3177 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3178 END_PROFILE(SMBreadX);
3182 if (!CHECK_READ(fsp,req->inbuf)) {
3183 reply_doserror(req, ERRDOS,ERRbadaccess);
3184 END_PROFILE(SMBreadX);
3188 if (global_client_caps & CAP_LARGE_READX) {
3189 size_t upper_size = SVAL(req->inbuf,smb_vwv7);
3190 smb_maxcnt |= (upper_size<<16);
3191 if (upper_size > 1) {
3192 /* Can't do this on a chained packet. */
3193 if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
3194 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3195 END_PROFILE(SMBreadX);
3198 /* We currently don't do this on signed or sealed data. */
3199 if (srv_is_signing_active() || srv_encryption_on()) {
3200 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3201 END_PROFILE(SMBreadX);
3204 /* Is there room in the reply for this data ? */
3205 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3207 NT_STATUS_INVALID_PARAMETER);
3208 END_PROFILE(SMBreadX);
3215 if (req->wct == 12) {
3216 #ifdef LARGE_SMB_OFF_T
3218 * This is a large offset (64 bit) read.
3220 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
3222 #else /* !LARGE_SMB_OFF_T */
3225 * Ensure we haven't been sent a >32 bit offset.
3228 if(IVAL(req->inbuf,smb_vwv10) != 0) {
3229 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3230 "used and we don't support 64 bit offsets.\n",
3231 (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
3232 END_PROFILE(SMBreadX);
3233 reply_doserror(req, ERRDOS, ERRbadaccess);
3237 #endif /* LARGE_SMB_OFF_T */
3241 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
3242 (SMB_BIG_UINT)startpos, READ_LOCK)) {
3243 END_PROFILE(SMBreadX);
3244 reply_doserror(req, ERRDOS, ERRlock);
3249 && schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3250 END_PROFILE(SMBreadX);
3251 reply_post_legacy(req, -1);
3255 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3257 END_PROFILE(SMBreadX);
3261 /****************************************************************************
3262 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3263 ****************************************************************************/
3265 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3268 ssize_t total_written=0;
3269 size_t numtowrite=0;
3274 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
3277 START_PROFILE(SMBwritebraw);
3279 if (srv_is_signing_active()) {
3280 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
3283 CHECK_FSP(fsp,conn);
3284 if (!CHECK_WRITE(fsp)) {
3285 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3288 tcount = IVAL(inbuf,smb_vwv1);
3289 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3290 write_through = BITSETW(inbuf+smb_vwv7,0);
3292 /* We have to deal with slightly different formats depending
3293 on whether we are using the core+ or lanman1.0 protocol */
3295 if(Protocol <= PROTOCOL_COREPLUS) {
3296 numtowrite = SVAL(smb_buf(inbuf),-2);
3297 data = smb_buf(inbuf);
3299 numtowrite = SVAL(inbuf,smb_vwv10);
3300 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
3303 /* force the error type */
3304 SCVAL(inbuf,smb_com,SMBwritec);
3305 SCVAL(outbuf,smb_com,SMBwritec);
3307 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3308 END_PROFILE(SMBwritebraw);
3309 return(ERROR_DOS(ERRDOS,ERRlock));
3313 nwritten = write_file(fsp,data,startpos,numtowrite);
3315 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
3316 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
3318 if (nwritten < (ssize_t)numtowrite) {
3319 END_PROFILE(SMBwritebraw);
3320 return(UNIXERROR(ERRHRD,ERRdiskfull));
3323 total_written = nwritten;
3325 /* Return a message to the redirector to tell it to send more bytes */
3326 SCVAL(outbuf,smb_com,SMBwritebraw);
3327 SSVALS(outbuf,smb_vwv0,-1);
3328 outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3330 if (!send_smb(smbd_server_fd(),outbuf))
3331 exit_server_cleanly("reply_writebraw: send_smb failed.");
3333 /* Now read the raw data into the buffer and write it */
3334 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
3335 exit_server_cleanly("secondary writebraw failed");
3338 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
3339 numtowrite = smb_len(inbuf);
3341 /* Set up outbuf to return the correct return */
3342 outsize = set_message(inbuf,outbuf,1,0,True);
3343 SCVAL(outbuf,smb_com,SMBwritec);
3345 if (numtowrite != 0) {
3347 if (numtowrite > BUFFER_SIZE) {
3348 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
3349 (unsigned int)numtowrite ));
3350 exit_server_cleanly("secondary writebraw failed");
3353 if (tcount > nwritten+numtowrite) {
3354 DEBUG(3,("Client overestimated the write %d %d %d\n",
3355 (int)tcount,(int)nwritten,(int)numtowrite));
3358 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
3359 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
3361 exit_server_cleanly("secondary writebraw failed");
3364 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
3365 if (nwritten == -1) {
3366 END_PROFILE(SMBwritebraw);
3367 return(UNIXERROR(ERRHRD,ERRdiskfull));
3370 if (nwritten < (ssize_t)numtowrite) {
3371 SCVAL(outbuf,smb_rcls,ERRHRD);
3372 SSVAL(outbuf,smb_err,ERRdiskfull);
3376 total_written += nwritten;
3379 SSVAL(outbuf,smb_vwv0,total_written);
3381 status = sync_file(conn, fsp, write_through);
3382 if (!NT_STATUS_IS_OK(status)) {
3383 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3384 fsp->fsp_name, nt_errstr(status) ));
3385 END_PROFILE(SMBwritebraw);
3386 return ERROR_NT(status);
3389 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
3390 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
3392 /* we won't return a status if write through is not selected - this follows what WfWg does */
3393 END_PROFILE(SMBwritebraw);
3394 if (!write_through && total_written==tcount) {
3396 #if RABBIT_PELLET_FIX
3398 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3399 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
3401 if (!send_keepalive(smbd_server_fd()))
3402 exit_server_cleanly("reply_writebraw: send of keepalive failed");
3411 #define DBGC_CLASS DBGC_LOCKING
3413 /****************************************************************************
3414 Reply to a writeunlock (core+).
3415 ****************************************************************************/
3417 void reply_writeunlock(connection_struct *conn, struct smb_request *req)
3419 ssize_t nwritten = -1;
3423 NTSTATUS status = NT_STATUS_OK;
3426 START_PROFILE(SMBwriteunlock);
3429 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3430 END_PROFILE(SMBwriteunlock);
3434 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3436 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3437 END_PROFILE(SMBwriteunlock);
3441 if (!CHECK_WRITE(fsp)) {
3442 reply_doserror(req, ERRDOS,ERRbadaccess);
3443 END_PROFILE(SMBwriteunlock);
3447 numtowrite = SVAL(req->inbuf,smb_vwv1);
3448 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3449 data = smb_buf(req->inbuf) + 3;
3452 && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3453 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3454 reply_doserror(req, ERRDOS, ERRlock);
3455 END_PROFILE(SMBwriteunlock);
3459 /* The special X/Open SMB protocol handling of
3460 zero length writes is *NOT* done for
3462 if(numtowrite == 0) {
3465 nwritten = write_file(fsp,data,startpos,numtowrite);
3468 status = sync_file(conn, fsp, False /* write through */);
3469 if (!NT_STATUS_IS_OK(status)) {
3470 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3471 fsp->fsp_name, nt_errstr(status) ));
3472 reply_nterror(req, status);
3473 END_PROFILE(SMBwriteunlock);
3477 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3478 reply_unixerror(req, ERRHRD, ERRdiskfull);
3479 END_PROFILE(SMBwriteunlock);
3484 status = do_unlock(smbd_messaging_context(),
3487 (SMB_BIG_UINT)numtowrite,
3488 (SMB_BIG_UINT)startpos,
3491 if (NT_STATUS_V(status)) {
3492 reply_nterror(req, status);
3493 END_PROFILE(SMBwriteunlock);
3498 reply_outbuf(req, 1, 0);
3500 SSVAL(req->outbuf,smb_vwv0,nwritten);
3502 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3503 fsp->fnum, (int)numtowrite, (int)nwritten));
3505 END_PROFILE(SMBwriteunlock);
3510 #define DBGC_CLASS DBGC_ALL
3512 /****************************************************************************
3514 ****************************************************************************/
3516 void reply_write(connection_struct *conn, struct smb_request *req)
3519 ssize_t nwritten = -1;
3525 START_PROFILE(SMBwrite);
3528 END_PROFILE(SMBwrite);
3529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3533 /* If it's an IPC, pass off the pipe handler. */
3535 reply_pipe_write(req);
3536 END_PROFILE(SMBwrite);
3540 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3542 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3546 if (!CHECK_WRITE(fsp)) {
3547 reply_doserror(req, ERRDOS, ERRbadaccess);
3548 END_PROFILE(SMBwrite);
3552 numtowrite = SVAL(req->inbuf,smb_vwv1);
3553 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
3554 data = smb_buf(req->inbuf) + 3;
3556 if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
3557 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3558 reply_doserror(req, ERRDOS, ERRlock);
3559 END_PROFILE(SMBwrite);
3564 * X/Open SMB protocol says that if smb_vwv1 is
3565 * zero then the file size should be extended or
3566 * truncated to the size given in smb_vwv[2-3].
3569 if(numtowrite == 0) {
3571 * This is actually an allocate call, and set EOF. JRA.
3573 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3575 reply_nterror(req, NT_STATUS_DISK_FULL);
3576 END_PROFILE(SMBwrite);
3579 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3581 reply_nterror(req, NT_STATUS_DISK_FULL);
3582 END_PROFILE(SMBwrite);
3586 nwritten = write_file(fsp,data,startpos,numtowrite);
3588 status = sync_file(conn, fsp, False);
3589 if (!NT_STATUS_IS_OK(status)) {
3590 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3591 fsp->fsp_name, nt_errstr(status) ));
3592 reply_nterror(req, status);
3593 END_PROFILE(SMBwrite);
3597 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3598 reply_unixerror(req, ERRHRD, ERRdiskfull);
3599 END_PROFILE(SMBwrite);
3603 reply_outbuf(req, 1, 0);
3605 SSVAL(req->outbuf,smb_vwv0,nwritten);
3607 if (nwritten < (ssize_t)numtowrite) {
3608 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3609 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3612 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3614 END_PROFILE(SMBwrite);
3618 /****************************************************************************
3619 Reply to a write and X.
3620 ****************************************************************************/
3622 void reply_write_and_X(connection_struct *conn, struct smb_request *req)
3629 unsigned int smb_doff;
3630 unsigned int smblen;
3635 START_PROFILE(SMBwriteX);
3637 if ((req->wct != 12) && (req->wct != 14)) {
3638 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3639 END_PROFILE(SMBwriteX);
3643 numtowrite = SVAL(req->inbuf,smb_vwv10);
3644 smb_doff = SVAL(req->inbuf,smb_vwv11);
3645 smblen = smb_len(req->inbuf);
3646 large_writeX = ((req->wct == 14) && (smblen > 0xFFFF));
3648 /* Deal with possible LARGE_WRITEX */
3650 numtowrite |= ((((size_t)SVAL(req->inbuf,smb_vwv9)) & 1 )<<16);
3653 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3654 reply_doserror(req, ERRDOS, ERRbadmem);
3655 END_PROFILE(SMBwriteX);
3659 /* If it's an IPC, pass off the pipe handler. */
3661 reply_pipe_write_and_X(req);
3662 END_PROFILE(SMBwriteX);
3666 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
3667 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
3668 write_through = BITSETW(req->inbuf+smb_vwv7,0);
3670 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3671 END_PROFILE(SMBwriteX);
3675 if (!CHECK_WRITE(fsp)) {
3676 reply_doserror(req, ERRDOS, ERRbadaccess);
3677 END_PROFILE(SMBwriteX);
3681 data = smb_base(req->inbuf) + smb_doff;
3683 if(req->wct == 14) {
3684 #ifdef LARGE_SMB_OFF_T
3686 * This is a large offset (64 bit) write.
3688 startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
3690 #else /* !LARGE_SMB_OFF_T */
3693 * Ensure we haven't been sent a >32 bit offset.
3696 if(IVAL(req->inbuf,smb_vwv12) != 0) {
3697 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
3698 "used and we don't support 64 bit offsets.\n",
3699 (unsigned int)IVAL(inbuf,smb_vwv12) ));
3700 reply_doserror(req, ERRDOS, ERRbadaccess);
3701 END_PROFILE(SMBwriteX);
3705 #endif /* LARGE_SMB_OFF_T */
3708 if (is_locked(fsp,(uint32)req->smbpid,
3709 (SMB_BIG_UINT)numtowrite,
3710 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3711 reply_doserror(req, ERRDOS, ERRlock);
3712 END_PROFILE(SMBwriteX);
3716 /* X/Open SMB protocol says that, unlike SMBwrite
3717 if the length is zero then NO truncation is
3718 done, just a write of zero. To truncate a file,
3721 if(numtowrite == 0) {
3725 if (schedule_aio_write_and_X(conn, req, fsp, data, startpos,
3727 END_PROFILE(SMBwriteX);
3731 nwritten = write_file(fsp,data,startpos,numtowrite);
3734 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3735 reply_unixerror(req, ERRHRD, ERRdiskfull);
3736 END_PROFILE(SMBwriteX);
3740 reply_outbuf(req, 6, 0);
3741 SSVAL(req->outbuf,smb_vwv2,nwritten);
3743 SSVAL(req->outbuf,smb_vwv4,(nwritten>>16)&1);
3745 if (nwritten < (ssize_t)numtowrite) {
3746 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3747 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3750 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3751 fsp->fnum, (int)numtowrite, (int)nwritten));
3753 status = sync_file(conn, fsp, write_through);
3754 if (!NT_STATUS_IS_OK(status)) {
3755 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3756 fsp->fsp_name, nt_errstr(status) ));
3757 reply_nterror(req, status);
3758 END_PROFILE(SMBwriteX);
3762 END_PROFILE(SMBwriteX);
3763 chain_reply_new(req);
3767 /****************************************************************************
3769 ****************************************************************************/
3771 void reply_lseek(connection_struct *conn, struct smb_request *req)
3778 START_PROFILE(SMBlseek);
3781 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3782 END_PROFILE(SMBlseek);
3786 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3788 if (!check_fsp(conn, req, fsp, ¤t_user)) {
3792 flush_write_cache(fsp, SEEK_FLUSH);
3794 mode = SVAL(req->inbuf,smb_vwv1) & 3;
3795 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3796 startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2);
3805 res = fsp->fh->pos + startpos;
3816 if (umode == SEEK_END) {
3817 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3818 if(errno == EINVAL) {
3819 SMB_OFF_T current_pos = startpos;
3820 SMB_STRUCT_STAT sbuf;
3822 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3823 reply_unixerror(req, ERRDOS,
3825 END_PROFILE(SMBlseek);
3829 current_pos += sbuf.st_size;
3831 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3836 reply_unixerror(req, ERRDOS, ERRnoaccess);
3837 END_PROFILE(SMBlseek);
3844 reply_outbuf(req, 2, 0);
3845 SIVAL(req->outbuf,smb_vwv0,res);
3847 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3848 fsp->fnum, (double)startpos, (double)res, mode));
3850 END_PROFILE(SMBlseek);
3854 /****************************************************************************
3856 ****************************************************************************/
3858 void reply_flush(connection_struct *conn, struct smb_request *req)
3863 START_PROFILE(SMBflush);
3866 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3870 fnum = SVAL(req->inbuf,smb_vwv0);
3871 fsp = file_fsp(fnum);
3873 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, ¤t_user)) {
3878 file_sync_all(conn);
3880 NTSTATUS status = sync_file(conn, fsp, True);
3881 if (!NT_STATUS_IS_OK(status)) {
3882 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3883 fsp->fsp_name, nt_errstr(status) ));
3884 reply_nterror(req, status);
3885 END_PROFILE(SMBflush);
3890 reply_outbuf(req, 0, 0);
3892 DEBUG(3,("flush\n"));
3893 END_PROFILE(SMBflush);
3897 /****************************************************************************
3899 conn POINTER CAN BE NULL HERE !
3900 ****************************************************************************/
3902 void reply_exit(connection_struct *conn, struct smb_request *req)
3904 START_PROFILE(SMBexit);
3906 file_close_pid(req->smbpid, req->vuid);
3908 reply_outbuf(req, 0, 0);
3910 DEBUG(3,("exit\n"));
3912 END_PROFILE(SMBexit);
3916 /****************************************************************************
3917 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3918 ****************************************************************************/
3920 void reply_close(connection_struct *conn, struct smb_request *req)
3922 NTSTATUS status = NT_STATUS_OK;
3923 files_struct *fsp = NULL;
3924 START_PROFILE(SMBclose);
3927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3928 END_PROFILE(SMBclose);
3932 /* If it's an IPC, pass off to the pipe handler. */
3934 reply_pipe_close(conn, req);
3935 END_PROFILE(SMBclose);
3939 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
3942 * We can only use CHECK_FSP if we know it's not a directory.
3945 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3946 reply_doserror(req, ERRDOS, ERRbadfid);
3947 END_PROFILE(SMBclose);
3951 if(fsp->is_directory) {
3953 * Special case - close NT SMB directory handle.
3955 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3956 status = close_file(fsp,NORMAL_CLOSE);
3959 * Close ordinary file.
3962 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3963 fsp->fh->fd, fsp->fnum,
3964 conn->num_files_open));
3967 * Take care of any time sent in the close.
3970 fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
3971 srv_make_unix_date3(
3972 req->inbuf+smb_vwv1)));
3975 * close_file() returns the unix errno if an error
3976 * was detected on close - normally this is due to
3977 * a disk full error. If not then it was probably an I/O error.
3980 status = close_file(fsp,NORMAL_CLOSE);
3983 if (!NT_STATUS_IS_OK(status)) {
3984 reply_nterror(req, status);
3985 END_PROFILE(SMBclose);
3989 reply_outbuf(req, 0, 0);
3990 END_PROFILE(SMBclose);
3994 /****************************************************************************
3995 Reply to a writeclose (Core+ protocol).
3996 ****************************************************************************/
3998 void reply_writeclose(connection_struct *conn, struct smb_request *req)
4001 ssize_t nwritten = -1;
4002 NTSTATUS close_status = NT_STATUS_OK;
4005 struct timespec mtime;
4008 START_PROFILE(SMBwriteclose);
4011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4012 END_PROFILE(SMBwriteclose);
4016 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4018 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4019 END_PROFILE(SMBwriteclose);
4022 if (!CHECK_WRITE(fsp)) {
4023 reply_doserror(req, ERRDOS,ERRbadaccess);
4024 END_PROFILE(SMBwriteclose);
4028 numtowrite = SVAL(req->inbuf,smb_vwv1);
4029 startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
4030 mtime = convert_time_t_to_timespec(srv_make_unix_date3(
4031 req->inbuf+smb_vwv4));
4032 data = smb_buf(req->inbuf) + 1;
4035 && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
4036 (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
4037 reply_doserror(req, ERRDOS,ERRlock);
4038 END_PROFILE(SMBwriteclose);
4042 nwritten = write_file(fsp,data,startpos,numtowrite);
4044 set_filetime(conn, fsp->fsp_name, mtime);
4047 * More insanity. W2K only closes the file if writelen > 0.
4052 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
4054 close_status = close_file(fsp,NORMAL_CLOSE);
4057 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4058 fsp->fnum, (int)numtowrite, (int)nwritten,
4059 conn->num_files_open));
4061 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4062 reply_doserror(req, ERRHRD, ERRdiskfull);
4063 END_PROFILE(SMBwriteclose);
4067 if(!NT_STATUS_IS_OK(close_status)) {
4068 reply_nterror(req, close_status);
4069 END_PROFILE(SMBwriteclose);
4073 reply_outbuf(req, 1, 0);
4075 SSVAL(req->outbuf,smb_vwv0,nwritten);
4076 END_PROFILE(SMBwriteclose);
4081 #define DBGC_CLASS DBGC_LOCKING
4083 /****************************************************************************
4085 ****************************************************************************/
4087 void reply_lock(connection_struct *conn, struct smb_request *req)
4089 SMB_BIG_UINT count,offset;
4092 struct byte_range_lock *br_lck = NULL;
4094 START_PROFILE(SMBlock);
4097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4098 END_PROFILE(SMBlock);
4102 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4104 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4105 END_PROFILE(SMBlock);
4109 release_level_2_oplocks_on_change(fsp);
4111 count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4112 offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4114 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4115 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4117 br_lck = do_lock(smbd_messaging_context(),
4124 False, /* Non-blocking lock. */
4128 TALLOC_FREE(br_lck);
4130 if (NT_STATUS_V(status)) {
4131 reply_nterror(req, status);
4132 END_PROFILE(SMBlock);
4136 reply_outbuf(req, 0, 0);
4138 END_PROFILE(SMBlock);
4142 /****************************************************************************
4144 ****************************************************************************/
4146 void reply_unlock(connection_struct *conn, struct smb_request *req)
4148 SMB_BIG_UINT count,offset;
4152 START_PROFILE(SMBunlock);
4155 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4156 END_PROFILE(SMBunlock);
4160 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4162 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4163 END_PROFILE(SMBunlock);
4167 count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
4168 offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
4170 status = do_unlock(smbd_messaging_context(),
4177 if (NT_STATUS_V(status)) {
4178 reply_nterror(req, status);
4179 END_PROFILE(SMBunlock);
4183 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4184 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4186 reply_outbuf(req, 0, 0);
4188 END_PROFILE(SMBunlock);
4193 #define DBGC_CLASS DBGC_ALL
4195 /****************************************************************************
4197 conn POINTER CAN BE NULL HERE !
4198 ****************************************************************************/
4200 void reply_tdis(connection_struct *conn, struct smb_request *req)
4202 START_PROFILE(SMBtdis);
4205 DEBUG(4,("Invalid connection in tdis\n"));
4206 reply_doserror(req, ERRSRV, ERRinvnid);
4207 END_PROFILE(SMBtdis);
4213 close_cnum(conn,req->vuid);
4215 reply_outbuf(req, 0, 0);
4216 END_PROFILE(SMBtdis);
4220 /****************************************************************************
4222 conn POINTER CAN BE NULL HERE !
4223 ****************************************************************************/
4225 void reply_echo(connection_struct *conn, struct smb_request *req)
4229 unsigned int data_len = smb_buflen(req->inbuf);
4231 START_PROFILE(SMBecho);
4234 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4235 END_PROFILE(SMBecho);
4239 if (data_len > BUFFER_SIZE) {
4240 DEBUG(0,("reply_echo: data_len too large.\n"));
4241 reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
4242 END_PROFILE(SMBecho);
4246 smb_reverb = SVAL(req->inbuf,smb_vwv0);
4248 reply_outbuf(req, 1, data_len);
4250 /* copy any incoming data back out */
4252 memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
4255 if (smb_reverb > 100) {
4256 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4260 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
4261 SSVAL(req->outbuf,smb_vwv0,seq_num);
4263 show_msg((char *)req->outbuf);
4264 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
4265 exit_server_cleanly("reply_echo: send_smb failed.");
4268 DEBUG(3,("echo %d times\n", smb_reverb));
4270 TALLOC_FREE(req->outbuf);
4274 END_PROFILE(SMBecho);
4278 /****************************************************************************
4279 Reply to a printopen.
4280 ****************************************************************************/
4282 void reply_printopen(connection_struct *conn, struct smb_request *req)
4287 START_PROFILE(SMBsplopen);
4290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4291 END_PROFILE(SMBsplopen);
4295 if (!CAN_PRINT(conn)) {
4296 reply_doserror(req, ERRDOS, ERRnoaccess);
4297 END_PROFILE(SMBsplopen);
4301 /* Open for exclusive use, write only. */
4302 status = print_fsp_open(conn, NULL, &fsp);
4304 if (!NT_STATUS_IS_OK(status)) {
4305 reply_nterror(req, status);
4306 END_PROFILE(SMBsplopen);
4310 reply_outbuf(req, 1, 0);
4311 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
4313 DEBUG(3,("openprint fd=%d fnum=%d\n",
4314 fsp->fh->fd, fsp->fnum));
4316 END_PROFILE(SMBsplopen);
4320 /****************************************************************************
4321 Reply to a printclose.
4322 ****************************************************************************/
4324 void reply_printclose(connection_struct *conn, struct smb_request *req)
4329 START_PROFILE(SMBsplclose);
4332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4333 END_PROFILE(SMBsplclose);
4337 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4339 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4340 END_PROFILE(SMBsplclose);
4344 if (!CAN_PRINT(conn)) {
4345 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
4346 END_PROFILE(SMBsplclose);
4350 DEBUG(3,("printclose fd=%d fnum=%d\n",
4351 fsp->fh->fd,fsp->fnum));
4353 status = close_file(fsp,NORMAL_CLOSE);
4355 if(!NT_STATUS_IS_OK(status)) {
4356 reply_nterror(req, status);
4357 END_PROFILE(SMBsplclose);
4361 END_PROFILE(SMBsplclose);
4365 /****************************************************************************
4366 Reply to a printqueue.
4367 ****************************************************************************/
4369 void reply_printqueue(connection_struct *conn, struct smb_request *req)
4374 START_PROFILE(SMBsplretq);
4377 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4378 END_PROFILE(SMBsplretq);
4382 max_count = SVAL(req->inbuf,smb_vwv0);
4383 start_index = SVAL(req->inbuf,smb_vwv1);
4385 /* we used to allow the client to get the cnum wrong, but that
4386 is really quite gross and only worked when there was only
4387 one printer - I think we should now only accept it if they
4388 get it right (tridge) */
4389 if (!CAN_PRINT(conn)) {
4390 reply_doserror(req, ERRDOS, ERRnoaccess);
4391 END_PROFILE(SMBsplretq);
4395 reply_outbuf(req, 2, 3);
4396 SSVAL(req->outbuf,smb_vwv0,0);
4397 SSVAL(req->outbuf,smb_vwv1,0);
4398 SCVAL(smb_buf(req->outbuf),0,1);
4399 SSVAL(smb_buf(req->outbuf),1,0);
4401 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
4402 start_index, max_count));
4405 print_queue_struct *queue = NULL;
4406 print_status_struct status;
4407 int count = print_queue_status(SNUM(conn), &queue, &status);
4408 int num_to_get = ABS(max_count);
4409 int first = (max_count>0?start_index:start_index+max_count+1);
4415 num_to_get = MIN(num_to_get,count-first);
4418 for (i=first;i<first+num_to_get;i++) {
4422 srv_put_dos_date2(p,0,queue[i].time);
4423 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
4424 SSVAL(p,5, queue[i].job);
4425 SIVAL(p,7,queue[i].size);
4427 srvstr_push(blob, req->flags2, p+12,
4428 queue[i].fs_user, 16, STR_ASCII);
4430 if (message_push_blob(
4433 blob, sizeof(blob))) == -1) {
4434 reply_nterror(req, NT_STATUS_NO_MEMORY);
4435 END_PROFILE(SMBsplretq);
4441 SSVAL(req->outbuf,smb_vwv0,count);
4442 SSVAL(req->outbuf,smb_vwv1,
4443 (max_count>0?first+count:first-1));
4444 SCVAL(smb_buf(req->outbuf),0,1);
4445 SSVAL(smb_buf(req->outbuf),1,28*count);
4450 DEBUG(3,("%d entries returned in queue\n",count));
4453 END_PROFILE(SMBsplretq);
4457 /****************************************************************************
4458 Reply to a printwrite.
4459 ****************************************************************************/
4461 void reply_printwrite(connection_struct *conn, struct smb_request *req)
4467 START_PROFILE(SMBsplwr);
4470 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4471 END_PROFILE(SMBsplwr);
4475 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
4477 if (!check_fsp(conn, req, fsp, ¤t_user)) {
4478 END_PROFILE(SMBsplwr);
4482 if (!CAN_PRINT(conn)) {
4483 reply_doserror(req, ERRDOS, ERRnoaccess);
4484 END_PROFILE(SMBsplwr);
4488 if (!CHECK_WRITE(fsp)) {
4489 reply_doserror(req, ERRDOS, ERRbadaccess);
4490 END_PROFILE(SMBsplwr);
4494 numtowrite = SVAL(smb_buf(req->inbuf),1);
4496 if (smb_buflen(req->inbuf) < numtowrite + 3) {
4497 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4498 END_PROFILE(SMBsplwr);
4502 data = smb_buf(req->inbuf) + 3;
4504 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
4505 reply_unixerror(req, ERRHRD, ERRdiskfull);
4506 END_PROFILE(SMBsplwr);
4510 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
4512 END_PROFILE(SMBsplwr);
4516 /****************************************************************************
4518 ****************************************************************************/
4520 void reply_mkdir(connection_struct *conn, struct smb_request *req)
4524 SMB_STRUCT_STAT sbuf;
4526 START_PROFILE(SMBmkdir);
4528 srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4529 smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4530 STR_TERMINATE, &status);
4531 if (!NT_STATUS_IS_OK(status)) {
4532 reply_nterror(req, status);
4533 END_PROFILE(SMBmkdir);
4537 status = resolve_dfspath(conn,
4538 req->flags2 & FLAGS2_DFS_PATHNAMES,
4540 if (!NT_STATUS_IS_OK(status)) {
4541 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4542 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4543 ERRSRV, ERRbadpath);
4544 END_PROFILE(SMBmkdir);
4547 reply_nterror(req, status);
4548 END_PROFILE(SMBmkdir);
4552 status = unix_convert(conn, directory, False, NULL, &sbuf);
4553 if (!NT_STATUS_IS_OK(status)) {
4554 reply_nterror(req, status);
4555 END_PROFILE(SMBmkdir);
4559 status = check_name(conn, directory);
4560 if (!NT_STATUS_IS_OK(status)) {
4561 reply_nterror(req, status);
4562 END_PROFILE(SMBmkdir);
4566 status = create_directory(conn, directory);
4568 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
4570 if (!NT_STATUS_IS_OK(status)) {
4572 if (!use_nt_status()
4573 && NT_STATUS_EQUAL(status,
4574 NT_STATUS_OBJECT_NAME_COLLISION)) {
4576 * Yes, in the DOS error code case we get a
4577 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
4578 * samba4 torture test.
4580 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
4583 reply_nterror(req, status);
4584 END_PROFILE(SMBmkdir);
4588 reply_outbuf(req, 0, 0);
4590 DEBUG( 3, ( "mkdir %s\n", directory ) );
4592 END_PROFILE(SMBmkdir);
4596 /****************************************************************************
4597 Static function used by reply_rmdir to delete an entire directory
4598 tree recursively. Return True on ok, False on fail.
4599 ****************************************************************************/
4601 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
4603 const char *dname = NULL;
4606 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4611 while((dname = ReadDirName(dir_hnd, &offset))) {
4615 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4618 if (!is_visible_file(conn, directory, dname, &st, False))
4621 /* Construct the full name. */
4622 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4628 pstrcpy(fullname, directory);
4629 pstrcat(fullname, "/");
4630 pstrcat(fullname, dname);
4632 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
4637 if(st.st_mode & S_IFDIR) {
4638 if(!recursive_rmdir(conn, fullname)) {
4642 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4646 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4655 /****************************************************************************
4656 The internals of the rmdir code - called elsewhere.
4657 ****************************************************************************/
4659 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4664 /* Might be a symlink. */
4665 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4666 return map_nt_error_from_unix(errno);
4669 if (S_ISLNK(st.st_mode)) {
4670 /* Is what it points to a directory ? */
4671 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4672 return map_nt_error_from_unix(errno);
4674 if (!(S_ISDIR(st.st_mode))) {
4675 return NT_STATUS_NOT_A_DIRECTORY;
4677 ret = SMB_VFS_UNLINK(conn,directory);
4679 ret = SMB_VFS_RMDIR(conn,directory);
4682 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4683 FILE_NOTIFY_CHANGE_DIR_NAME,
4685 return NT_STATUS_OK;
4688 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4690 * Check to see if the only thing in this directory are
4691 * vetoed files/directories. If so then delete them and
4692 * retry. If we fail to delete any of them (and we *don't*
4693 * do a recursive delete) then fail the rmdir.
4697 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4699 if(dir_hnd == NULL) {
4704 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4705 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4707 if (!is_visible_file(conn, directory, dname, &st, False))
4709 if(!IS_VETO_PATH(conn, dname)) {
4716 /* We only have veto files/directories. Recursive delete. */
4718 RewindDir(dir_hnd,&dirpos);
4719 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4722 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4724 if (!is_visible_file(conn, directory, dname, &st, False))
4727 /* Construct the full name. */
4728 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4733 pstrcpy(fullname, directory);
4734 pstrcat(fullname, "/");
4735 pstrcat(fullname, dname);
4737 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4739 if(st.st_mode & S_IFDIR) {
4740 if(lp_recursive_veto_delete(SNUM(conn))) {
4741 if(!recursive_rmdir(conn, fullname))
4744 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4746 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4750 /* Retry the rmdir */
4751 ret = SMB_VFS_RMDIR(conn,directory);
4757 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4758 "%s\n", directory,strerror(errno)));
4759 return map_nt_error_from_unix(errno);
4762 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4763 FILE_NOTIFY_CHANGE_DIR_NAME,
4766 return NT_STATUS_OK;
4769 /****************************************************************************
4771 ****************************************************************************/
4773 void reply_rmdir(connection_struct *conn, struct smb_request *req)
4776 SMB_STRUCT_STAT sbuf;
4778 START_PROFILE(SMBrmdir);
4780 srvstr_get_path((char *)req->inbuf, req->flags2, directory,
4781 smb_buf(req->inbuf) + 1, sizeof(directory), 0,
4782 STR_TERMINATE, &status);
4783 if (!NT_STATUS_IS_OK(status)) {
4784 reply_nterror(req, status);
4785 END_PROFILE(SMBrmdir);
4789 status = resolve_dfspath(conn,
4790 req->flags2 & FLAGS2_DFS_PATHNAMES,
4792 if (!NT_STATUS_IS_OK(status)) {
4793 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4794 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
4795 ERRSRV, ERRbadpath);
4796 END_PROFILE(SMBrmdir);
4799 reply_nterror(req, status);
4800 END_PROFILE(SMBrmdir);
4804 status = unix_convert(conn, directory, False, NULL, &sbuf);
4805 if (!NT_STATUS_IS_OK(status)) {
4806 reply_nterror(req, status);
4807 END_PROFILE(SMBrmdir);
4811 status = check_name(conn, directory);
4812 if (!NT_STATUS_IS_OK(status)) {
4813 reply_nterror(req, status);
4814 END_PROFILE(SMBrmdir);
4818 dptr_closepath(directory, req->smbpid);
4819 status = rmdir_internals(conn, directory);
4820 if (!NT_STATUS_IS_OK(status)) {
4821 reply_nterror(req, status);
4822 END_PROFILE(SMBrmdir);
4826 reply_outbuf(req, 0, 0);
4828 DEBUG( 3, ( "rmdir %s\n", directory ) );
4830 END_PROFILE(SMBrmdir);
4834 /*******************************************************************
4835 Resolve wildcards in a filename rename.
4836 Note that name is in UNIX charset and thus potentially can be more
4837 than fstring buffer (255 bytes) especially in default UTF-8 case.
4838 Therefore, we use pstring inside and all calls should ensure that
4839 name2 is at least pstring-long (they do already)
4840 ********************************************************************/
4842 static BOOL resolve_wildcards(const char *name1, char *name2)
4844 pstring root1,root2;
4846 char *p,*p2, *pname1, *pname2;
4847 int available_space, actual_space;
4849 pname1 = strrchr_m(name1,'/');
4850 pname2 = strrchr_m(name2,'/');
4852 if (!pname1 || !pname2)
4855 pstrcpy(root1,pname1);
4856 pstrcpy(root2,pname2);
4857 p = strrchr_m(root1,'.');
4864 p = strrchr_m(root2,'.');
4878 } else if (*p2 == '*') {
4894 } else if (*p2 == '*') {
4904 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4907 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4908 if (actual_space >= available_space - 1) {
4909 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4910 actual_space - available_space));
4913 pstrcpy_base(pname2, root2, name2);
4919 /****************************************************************************
4920 Ensure open files have their names updated. Updated to notify other smbd's
4922 ****************************************************************************/
4924 static void rename_open_files(connection_struct *conn,
4925 struct share_mode_lock *lck,
4926 const char *newname)
4929 BOOL did_rename = False;
4931 for(fsp = file_find_di_first(lck->id); fsp;
4932 fsp = file_find_di_next(fsp)) {
4933 /* fsp_name is a relative path under the fsp. To change this for other
4934 sharepaths we need to manipulate relative paths. */
4935 /* TODO - create the absolute path and manipulate the newname
4936 relative to the sharepath. */
4937 if (fsp->conn != conn) {
4940 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4941 fsp->fnum, file_id_static_string(&fsp->file_id),
4942 fsp->fsp_name, newname ));
4943 string_set(&fsp->fsp_name, newname);
4948 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4949 file_id_static_string(&lck->id), newname ));
4952 /* Send messages to all smbd's (not ourself) that the name has changed. */
4953 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4957 /****************************************************************************
4958 We need to check if the source path is a parent directory of the destination
4959 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4960 refuse the rename with a sharing violation. Under UNIX the above call can
4961 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4962 probably need to check that the client is a Windows one before disallowing
4963 this as a UNIX client (one with UNIX extensions) can know the source is a
4964 symlink and make this decision intelligently. Found by an excellent bug
4965 report from <AndyLiebman@aol.com>.
4966 ****************************************************************************/
4968 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4970 const char *psrc = src;
4971 const char *pdst = dest;
4974 if (psrc[0] == '.' && psrc[1] == '/') {
4977 if (pdst[0] == '.' && pdst[1] == '/') {
4980 if ((slen = strlen(psrc)) > strlen(pdst)) {
4983 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4987 * Do the notify calls from a rename
4990 static void notify_rename(connection_struct *conn, BOOL is_dir,
4991 const char *oldpath, const char *newpath)
4993 char *olddir, *newdir;
4994 const char *oldname, *newname;
4997 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4998 : FILE_NOTIFY_CHANGE_FILE_NAME;
5000 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
5001 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
5002 TALLOC_FREE(olddir);
5006 if (strcmp(olddir, newdir) == 0) {
5007 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
5008 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
5011 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
5012 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
5014 TALLOC_FREE(olddir);
5015 TALLOC_FREE(newdir);
5017 /* this is a strange one. w2k3 gives an additional event for
5018 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5019 files, but not directories */
5021 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5022 FILE_NOTIFY_CHANGE_ATTRIBUTES
5023 |FILE_NOTIFY_CHANGE_CREATION,
5028 /****************************************************************************
5029 Rename an open file - given an fsp.
5030 ****************************************************************************/
5032 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
5034 SMB_STRUCT_STAT sbuf, sbuf1;
5035 pstring newname_last_component;
5036 NTSTATUS status = NT_STATUS_OK;
5037 struct share_mode_lock *lck = NULL;
5042 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
5044 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
5046 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
5050 status = check_name(conn, newname);
5051 if (!NT_STATUS_IS_OK(status)) {
5055 /* Ensure newname contains a '/' */
5056 if(strrchr_m(newname,'/') == 0) {
5059 pstrcpy(tmpstr, "./");
5060 pstrcat(tmpstr, newname);
5061 pstrcpy(newname, tmpstr);
5065 * Check for special case with case preserving and not
5066 * case sensitive. If the old last component differs from the original
5067 * last component only by case, then we should allow
5068 * the rename (user is trying to change the case of the
5072 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5073 strequal(newname, fsp->fsp_name)) {
5075 pstring newname_modified_last_component;
5078 * Get the last component of the modified name.
5079 * Note that we guarantee that newname contains a '/'
5082 p = strrchr_m(newname,'/');
5083 pstrcpy(newname_modified_last_component,p+1);
5085 if(strcsequal(newname_modified_last_component,
5086 newname_last_component) == False) {
5088 * Replace the modified last component with
5091 pstrcpy(p+1, newname_last_component);
5096 * If the src and dest names are identical - including case,
5097 * don't do the rename, just return success.
5100 if (strcsequal(fsp->fsp_name, newname)) {
5101 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5103 return NT_STATUS_OK;
5107 * Have vfs_object_exist also fill sbuf1
5109 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5111 if(!replace_if_exists && dst_exists) {
5112 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5113 fsp->fsp_name,newname));
5114 return NT_STATUS_OBJECT_NAME_COLLISION;
5118 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5119 files_struct *dst_fsp = file_find_di_first(fileid);
5121 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5122 return NT_STATUS_ACCESS_DENIED;
5126 /* Ensure we have a valid stat struct for the source. */
5127 if (fsp->fh->fd != -1) {
5128 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
5129 return map_nt_error_from_unix(errno);
5132 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5133 return map_nt_error_from_unix(errno);
5137 status = can_rename(conn, fsp, attrs, &sbuf);
5139 if (!NT_STATUS_IS_OK(status)) {
5140 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5141 nt_errstr(status), fsp->fsp_name,newname));
5142 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5143 status = NT_STATUS_ACCESS_DENIED;
5147 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5148 return NT_STATUS_ACCESS_DENIED;
5151 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
5154 * We have the file open ourselves, so not being able to get the
5155 * corresponding share mode lock is a fatal error.
5158 SMB_ASSERT(lck != NULL);
5160 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5161 uint32 create_options = fsp->fh->private_options;
5163 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5164 fsp->fsp_name,newname));
5166 rename_open_files(conn, lck, newname);
5168 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5171 * A rename acts as a new file create w.r.t. allowing an initial delete
5172 * on close, probably because in Windows there is a new handle to the
5173 * new file. If initial delete on close was requested but not
5174 * originally set, we need to set it here. This is probably not 100% correct,
5175 * but will work for the CIFSFS client which in non-posix mode
5176 * depends on these semantics. JRA.
5179 set_allow_initial_delete_on_close(lck, fsp, True);
5181 if (create_options & FILE_DELETE_ON_CLOSE) {
5182 status = can_set_delete_on_close(fsp, True, 0);
5184 if (NT_STATUS_IS_OK(status)) {
5185 /* Note that here we set the *inital* delete on close flag,
5186 * not the regular one. The magic gets handled in close. */
5187 fsp->initial_delete_on_close = True;
5191 return NT_STATUS_OK;
5196 if (errno == ENOTDIR || errno == EISDIR) {
5197 status = NT_STATUS_OBJECT_NAME_COLLISION;
5199 status = map_nt_error_from_unix(errno);
5202 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5203 nt_errstr(status), fsp->fsp_name,newname));
5208 /****************************************************************************
5209 The guts of the rename command, split out so it may be called by the NT SMB
5211 ****************************************************************************/
5213 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
5217 BOOL replace_if_exists,
5223 pstring last_component_src;
5224 pstring last_component_dest;
5227 NTSTATUS status = NT_STATUS_OK;
5228 SMB_STRUCT_STAT sbuf1, sbuf2;
5229 struct smb_Dir *dir_hnd = NULL;
5234 *directory = *mask = 0;
5239 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
5240 if (!NT_STATUS_IS_OK(status)) {
5244 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
5245 if (!NT_STATUS_IS_OK(status)) {
5250 * Split the old name into directory and last component
5251 * strings. Note that unix_convert may have stripped off a
5252 * leading ./ from both name and newname if the rename is
5253 * at the root of the share. We need to make sure either both
5254 * name and newname contain a / character or neither of them do
5255 * as this is checked in resolve_wildcards().
5258 p = strrchr_m(name,'/');
5260 pstrcpy(directory,".");
5264 pstrcpy(directory,name);
5266 *p = '/'; /* Replace needed for exceptional test below. */
5270 * We should only check the mangled cache
5271 * here if unix_convert failed. This means
5272 * that the path in 'mask' doesn't exist
5273 * on the file system and so we need to look
5274 * for a possible mangle. This patch from
5275 * Tine Smukavec <valentin.smukavec@hermes.si>.
5278 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5279 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5282 if (!src_has_wild) {
5286 * No wildcards - just process the one file.
5288 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
5290 /* Add a terminating '/' to the directory name. */
5291 pstrcat(directory,"/");
5292 pstrcat(directory,mask);
5294 /* Ensure newname contains a '/' also */
5295 if(strrchr_m(newname,'/') == 0) {
5298 pstrcpy(tmpstr, "./");
5299 pstrcat(tmpstr, newname);
5300 pstrcpy(newname, tmpstr);
5303 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5304 "case_preserve = %d, short case preserve = %d, "
5305 "directory = %s, newname = %s, "
5306 "last_component_dest = %s, is_8_3 = %d\n",
5307 conn->case_sensitive, conn->case_preserve,
5308 conn->short_case_preserve, directory,
5309 newname, last_component_dest, is_short_name));
5311 /* The dest name still may have wildcards. */
5312 if (dest_has_wild) {
5313 if (!resolve_wildcards(directory,newname)) {
5314 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
5315 directory,newname));
5316 return NT_STATUS_NO_MEMORY;
5321 SMB_VFS_STAT(conn, directory, &sbuf1);
5323 status = S_ISDIR(sbuf1.st_mode) ?
5324 open_directory(conn, req, directory, &sbuf1,
5326 FILE_SHARE_READ|FILE_SHARE_WRITE,
5327 FILE_OPEN, 0, 0, NULL,
5329 : open_file_ntcreate(conn, req, directory, &sbuf1,
5331 FILE_SHARE_READ|FILE_SHARE_WRITE,
5332 FILE_OPEN, 0, 0, 0, NULL,
5335 if (!NT_STATUS_IS_OK(status)) {
5336 DEBUG(3, ("Could not open rename source %s: %s\n",
5337 directory, nt_errstr(status)));
5341 status = rename_internals_fsp(conn, fsp, newname, attrs,
5344 close_file(fsp, NORMAL_CLOSE);
5346 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5347 nt_errstr(status), directory,newname));
5353 * Wildcards - process each file that matches.
5355 if (strequal(mask,"????????.???")) {
5359 status = check_name(conn, directory);
5360 if (!NT_STATUS_IS_OK(status)) {
5364 dir_hnd = OpenDir(conn, directory, mask, attrs);
5365 if (dir_hnd == NULL) {
5366 return map_nt_error_from_unix(errno);
5369 status = NT_STATUS_NO_SUCH_FILE;
5371 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5372 * - gentest fix. JRA
5375 while ((dname = ReadDirName(dir_hnd, &offset))) {
5378 BOOL sysdir_entry = False;
5380 pstrcpy(fname,dname);
5382 /* Quick check for "." and ".." */
5383 if (fname[0] == '.') {
5384 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
5386 sysdir_entry = True;
5393 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5397 if(!mask_match(fname, mask, conn->case_sensitive)) {
5402 status = NT_STATUS_OBJECT_NAME_INVALID;
5406 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
5408 pstrcpy(destname,newname);
5410 if (!resolve_wildcards(fname,destname)) {
5411 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5417 SMB_VFS_STAT(conn, fname, &sbuf1);
5419 status = S_ISDIR(sbuf1.st_mode) ?
5420 open_directory(conn, req, fname, &sbuf1,
5422 FILE_SHARE_READ|FILE_SHARE_WRITE,
5423 FILE_OPEN, 0, 0, NULL,
5425 : open_file_ntcreate(conn, req, fname, &sbuf1,
5427 FILE_SHARE_READ|FILE_SHARE_WRITE,
5428 FILE_OPEN, 0, 0, 0, NULL,
5431 if (!NT_STATUS_IS_OK(status)) {
5432 DEBUG(3,("rename_internals: open_file_ntcreate "
5433 "returned %s rename %s -> %s\n",
5434 nt_errstr(status), directory, newname));
5438 status = rename_internals_fsp(conn, fsp, destname, attrs,
5441 close_file(fsp, NORMAL_CLOSE);
5443 if (!NT_STATUS_IS_OK(status)) {
5444 DEBUG(3, ("rename_internals_fsp returned %s for "
5445 "rename %s -> %s\n", nt_errstr(status),
5446 directory, newname));
5452 DEBUG(3,("rename_internals: doing rename on %s -> "
5453 "%s\n",fname,destname));
5457 if (count == 0 && NT_STATUS_IS_OK(status)) {
5458 status = map_nt_error_from_unix(errno);
5464 /****************************************************************************
5466 ****************************************************************************/
5468 void reply_mv(connection_struct *conn, struct smb_request *req)
5475 BOOL src_has_wcard = False;
5476 BOOL dest_has_wcard = False;
5478 START_PROFILE(SMBmv);
5481 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5486 attrs = SVAL(req->inbuf,smb_vwv0);
5488 p = smb_buf(req->inbuf) + 1;
5489 p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, p,
5490 sizeof(name), 0, STR_TERMINATE, &status,
5492 if (!NT_STATUS_IS_OK(status)) {
5493 reply_nterror(req, status);
5498 p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p,
5499 sizeof(newname), 0, STR_TERMINATE, &status,
5501 if (!NT_STATUS_IS_OK(status)) {
5502 reply_nterror(req, status);
5507 status = resolve_dfspath_wcard(conn,
5508 req->flags2 & FLAGS2_DFS_PATHNAMES,
5509 name, &src_has_wcard);
5510 if (!NT_STATUS_IS_OK(status)) {
5511 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5512 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5513 ERRSRV, ERRbadpath);
5517 reply_nterror(req, status);
5522 status = resolve_dfspath_wcard(conn,
5523 req->flags2 & FLAGS2_DFS_PATHNAMES,
5524 newname, &dest_has_wcard);
5525 if (!NT_STATUS_IS_OK(status)) {
5526 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5527 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5528 ERRSRV, ERRbadpath);
5532 reply_nterror(req, status);
5537 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
5539 status = rename_internals(conn, req, name, newname, attrs, False,
5540 src_has_wcard, dest_has_wcard);
5541 if (!NT_STATUS_IS_OK(status)) {
5542 if (open_was_deferred(req->mid)) {
5543 /* We have re-scheduled this call. */
5547 reply_nterror(req, status);
5552 reply_outbuf(req, 0, 0);
5558 /*******************************************************************
5559 Copy a file as part of a reply_copy.
5560 ******************************************************************/
5563 * TODO: check error codes on all callers
5566 NTSTATUS copy_file(connection_struct *conn,
5571 BOOL target_is_directory)
5573 SMB_STRUCT_STAT src_sbuf, sbuf2;
5575 files_struct *fsp1,*fsp2;
5578 uint32 new_create_disposition;
5581 pstrcpy(dest,dest1);
5582 if (target_is_directory) {
5583 char *p = strrchr_m(src,'/');
5593 if (!vfs_file_exist(conn,src,&src_sbuf)) {
5594 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5597 if (!target_is_directory && count) {
5598 new_create_disposition = FILE_OPEN;
5600 if (!map_open_params_to_ntcreate(dest1,0,ofun,
5601 NULL, NULL, &new_create_disposition, NULL)) {
5602 return NT_STATUS_INVALID_PARAMETER;
5606 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
5608 FILE_SHARE_READ|FILE_SHARE_WRITE,
5611 FILE_ATTRIBUTE_NORMAL,
5615 if (!NT_STATUS_IS_OK(status)) {
5619 dosattrs = dos_mode(conn, src, &src_sbuf);
5620 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
5621 ZERO_STRUCTP(&sbuf2);
5624 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
5626 FILE_SHARE_READ|FILE_SHARE_WRITE,
5627 new_create_disposition,
5633 if (!NT_STATUS_IS_OK(status)) {
5634 close_file(fsp1,ERROR_CLOSE);
5638 if ((ofun&3) == 1) {
5639 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
5640 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
5642 * Stop the copy from occurring.
5645 src_sbuf.st_size = 0;
5649 if (src_sbuf.st_size) {
5650 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
5653 close_file(fsp1,NORMAL_CLOSE);
5655 /* Ensure the modtime is set correctly on the destination file. */
5656 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
5659 * As we are opening fsp1 read-only we only expect
5660 * an error on close on fsp2 if we are out of space.
5661 * Thus we don't look at the error return from the
5664 status = close_file(fsp2,NORMAL_CLOSE);
5666 if (!NT_STATUS_IS_OK(status)) {
5670 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
5671 return NT_STATUS_DISK_FULL;
5674 return NT_STATUS_OK;
5677 /****************************************************************************
5678 Reply to a file copy.
5679 ****************************************************************************/
5681 void reply_copy(connection_struct *conn, struct smb_request *req)
5685 pstring mask,newname;
5688 int error = ERRnoaccess;
5693 BOOL target_is_directory=False;
5694 BOOL source_has_wild = False;
5695 BOOL dest_has_wild = False;
5696 SMB_STRUCT_STAT sbuf1, sbuf2;
5699 START_PROFILE(SMBcopy);
5702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5703 END_PROFILE(SMBcopy);
5707 tid2 = SVAL(req->inbuf,smb_vwv0);
5708 ofun = SVAL(req->inbuf,smb_vwv1);
5709 flags = SVAL(req->inbuf,smb_vwv2);
5711 *directory = *mask = 0;
5713 p = smb_buf(req->inbuf);
5714 p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, p,
5715 sizeof(name), 0, STR_TERMINATE, &status,
5717 if (!NT_STATUS_IS_OK(status)) {
5718 reply_nterror(req, status);
5719 END_PROFILE(SMBcopy);
5722 p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p,
5723 sizeof(newname), 0, STR_TERMINATE, &status,
5725 if (!NT_STATUS_IS_OK(status)) {
5726 reply_nterror(req, status);
5727 END_PROFILE(SMBcopy);
5731 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5733 if (tid2 != conn->cnum) {
5734 /* can't currently handle inter share copies XXXX */
5735 DEBUG(3,("Rejecting inter-share copy\n"));
5736 reply_doserror(req, ERRSRV, ERRinvdevice);
5737 END_PROFILE(SMBcopy);
5741 status = resolve_dfspath_wcard(conn,
5742 req->flags2 & FLAGS2_DFS_PATHNAMES,
5743 name, &source_has_wild);
5744 if (!NT_STATUS_IS_OK(status)) {
5745 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5746 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5747 ERRSRV, ERRbadpath);
5748 END_PROFILE(SMBcopy);
5751 reply_nterror(req, status);
5752 END_PROFILE(SMBcopy);
5756 status = resolve_dfspath_wcard(conn,
5757 req->flags2 & FLAGS2_DFS_PATHNAMES,
5758 newname, &dest_has_wild);
5759 if (!NT_STATUS_IS_OK(status)) {
5760 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5761 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5762 ERRSRV, ERRbadpath);
5763 END_PROFILE(SMBcopy);
5766 reply_nterror(req, status);
5767 END_PROFILE(SMBcopy);
5771 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5772 if (!NT_STATUS_IS_OK(status)) {
5773 reply_nterror(req, status);
5774 END_PROFILE(SMBcopy);
5778 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5779 if (!NT_STATUS_IS_OK(status)) {
5780 reply_nterror(req, status);
5781 END_PROFILE(SMBcopy);
5785 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5787 if ((flags&1) && target_is_directory) {
5788 reply_doserror(req, ERRDOS, ERRbadfile);
5789 END_PROFILE(SMBcopy);
5793 if ((flags&2) && !target_is_directory) {
5794 reply_doserror(req, ERRDOS, ERRbadpath);
5795 END_PROFILE(SMBcopy);
5799 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5800 /* wants a tree copy! XXXX */
5801 DEBUG(3,("Rejecting tree copy\n"));
5802 reply_doserror(req, ERRSRV, ERRerror);
5803 END_PROFILE(SMBcopy);
5807 p = strrchr_m(name,'/');
5809 pstrcpy(directory,"./");
5813 pstrcpy(directory,name);
5818 * We should only check the mangled cache
5819 * here if unix_convert failed. This means
5820 * that the path in 'mask' doesn't exist
5821 * on the file system and so we need to look
5822 * for a possible mangle. This patch from
5823 * Tine Smukavec <valentin.smukavec@hermes.si>.
5826 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5827 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5830 if (!source_has_wild) {
5831 pstrcat(directory,"/");
5832 pstrcat(directory,mask);
5833 if (dest_has_wild) {
5834 if (!resolve_wildcards(directory,newname)) {
5835 reply_nterror(req, NT_STATUS_NO_MEMORY);
5836 END_PROFILE(SMBcopy);
5841 status = check_name(conn, directory);
5842 if (!NT_STATUS_IS_OK(status)) {
5843 reply_nterror(req, status);
5844 END_PROFILE(SMBcopy);
5848 status = check_name(conn, newname);
5849 if (!NT_STATUS_IS_OK(status)) {
5850 reply_nterror(req, status);
5851 END_PROFILE(SMBcopy);
5855 status = copy_file(conn,directory,newname,ofun,
5856 count,target_is_directory);
5858 if(!NT_STATUS_IS_OK(status)) {
5859 reply_nterror(req, status);
5860 END_PROFILE(SMBcopy);
5866 struct smb_Dir *dir_hnd = NULL;
5871 if (strequal(mask,"????????.???"))
5874 status = check_name(conn, directory);
5875 if (!NT_STATUS_IS_OK(status)) {
5876 reply_nterror(req, status);
5877 END_PROFILE(SMBcopy);
5881 dir_hnd = OpenDir(conn, directory, mask, 0);
5882 if (dir_hnd == NULL) {
5883 status = map_nt_error_from_unix(errno);
5884 reply_nterror(req, status);
5885 END_PROFILE(SMBcopy);
5891 while ((dname = ReadDirName(dir_hnd, &offset))) {
5893 pstrcpy(fname,dname);
5895 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5899 if(!mask_match(fname, mask, conn->case_sensitive)) {
5903 error = ERRnoaccess;
5904 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5905 pstrcpy(destname,newname);
5906 if (!resolve_wildcards(fname,destname)) {
5910 status = check_name(conn, fname);
5911 if (!NT_STATUS_IS_OK(status)) {
5912 reply_nterror(req, status);
5913 END_PROFILE(SMBcopy);
5917 status = check_name(conn, destname);
5918 if (!NT_STATUS_IS_OK(status)) {
5919 reply_nterror(req, status);
5920 END_PROFILE(SMBcopy);
5924 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5926 status = copy_file(conn,fname,destname,ofun,
5927 count,target_is_directory);
5928 if (NT_STATUS_IS_OK(status)) {
5937 /* Error on close... */
5939 reply_unixerror(req, ERRHRD, ERRgeneral);
5940 END_PROFILE(SMBcopy);
5944 reply_doserror(req, ERRDOS, error);
5945 END_PROFILE(SMBcopy);
5949 reply_outbuf(req, 1, 0);
5950 SSVAL(req->outbuf,smb_vwv0,count);
5952 END_PROFILE(SMBcopy);
5957 #define DBGC_CLASS DBGC_LOCKING
5959 /****************************************************************************
5960 Get a lock pid, dealing with large count requests.
5961 ****************************************************************************/
5963 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5965 if(!large_file_format)
5966 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5968 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5971 /****************************************************************************
5972 Get a lock count, dealing with large count requests.
5973 ****************************************************************************/
5975 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5977 SMB_BIG_UINT count = 0;
5979 if(!large_file_format) {
5980 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5983 #if defined(HAVE_LONGLONG)
5984 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5985 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5986 #else /* HAVE_LONGLONG */
5989 * NT4.x seems to be broken in that it sends large file (64 bit)
5990 * lockingX calls even if the CAP_LARGE_FILES was *not*
5991 * negotiated. For boxes without large unsigned ints truncate the
5992 * lock count by dropping the top 32 bits.
5995 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5996 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5997 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5998 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5999 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6002 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6003 #endif /* HAVE_LONGLONG */
6009 #if !defined(HAVE_LONGLONG)
6010 /****************************************************************************
6011 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6012 ****************************************************************************/
6014 static uint32 map_lock_offset(uint32 high, uint32 low)
6018 uint32 highcopy = high;
6021 * Try and find out how many significant bits there are in high.
6024 for(i = 0; highcopy; i++)
6028 * We use 31 bits not 32 here as POSIX
6029 * lock offsets may not be negative.
6032 mask = (~0) << (31 - i);
6035 return 0; /* Fail. */
6041 #endif /* !defined(HAVE_LONGLONG) */
6043 /****************************************************************************
6044 Get a lock offset, dealing with large offset requests.
6045 ****************************************************************************/
6047 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
6049 SMB_BIG_UINT offset = 0;
6053 if(!large_file_format) {
6054 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6057 #if defined(HAVE_LONGLONG)
6058 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6059 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6060 #else /* HAVE_LONGLONG */
6063 * NT4.x seems to be broken in that it sends large file (64 bit)
6064 * lockingX calls even if the CAP_LARGE_FILES was *not*
6065 * negotiated. For boxes without large unsigned ints mangle the
6066 * lock offset by mapping the top 32 bits onto the lower 32.
6069 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6070 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6071 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6074 if((new_low = map_lock_offset(high, low)) == 0) {
6076 return (SMB_BIG_UINT)-1;
6079 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6080 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6081 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6082 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6085 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6086 #endif /* HAVE_LONGLONG */
6092 /****************************************************************************
6093 Reply to a lockingX request.
6094 ****************************************************************************/
6096 void reply_lockingX(connection_struct *conn, struct smb_request *req)
6099 unsigned char locktype;
6100 unsigned char oplocklevel;
6103 SMB_BIG_UINT count = 0, offset = 0;
6108 BOOL large_file_format;
6110 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6112 START_PROFILE(SMBlockingX);
6115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6116 END_PROFILE(SMBlockingX);
6120 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
6121 locktype = CVAL(req->inbuf,smb_vwv3);
6122 oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
6123 num_ulocks = SVAL(req->inbuf,smb_vwv6);
6124 num_locks = SVAL(req->inbuf,smb_vwv7);
6125 lock_timeout = IVAL(req->inbuf,smb_vwv4);
6126 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6128 if (!check_fsp(conn, req, fsp, ¤t_user)) {
6129 END_PROFILE(SMBlockingX);
6133 data = smb_buf(req->inbuf);
6135 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6136 /* we don't support these - and CANCEL_LOCK makes w2k
6137 and XP reboot so I don't really want to be
6138 compatible! (tridge) */
6139 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6140 END_PROFILE(SMBlockingX);
6144 /* Check if this is an oplock break on a file
6145 we have granted an oplock on.
6147 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6148 /* Client can insist on breaking to none. */
6149 BOOL break_to_none = (oplocklevel == 0);
6152 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6153 "for fnum = %d\n", (unsigned int)oplocklevel,
6157 * Make sure we have granted an exclusive or batch oplock on
6161 if (fsp->oplock_type == 0) {
6163 /* The Samba4 nbench simulator doesn't understand
6164 the difference between break to level2 and break
6165 to none from level2 - it sends oplock break
6166 replies in both cases. Don't keep logging an error
6167 message here - just ignore it. JRA. */
6169 DEBUG(5,("reply_lockingX: Error : oplock break from "
6170 "client for fnum = %d (oplock=%d) and no "
6171 "oplock granted on this file (%s).\n",
6172 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6174 /* if this is a pure oplock break request then don't
6176 if (num_locks == 0 && num_ulocks == 0) {
6177 END_PROFILE(SMBlockingX);
6178 reply_post_legacy(req, -1);
6181 END_PROFILE(SMBlockingX);
6182 reply_doserror(req, ERRDOS, ERRlock);
6187 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6189 result = remove_oplock(fsp);
6191 result = downgrade_oplock(fsp);
6195 DEBUG(0, ("reply_lockingX: error in removing "
6196 "oplock on file %s\n", fsp->fsp_name));
6197 /* Hmmm. Is this panic justified? */
6198 smb_panic("internal tdb error");
6201 reply_to_oplock_break_requests(fsp);
6203 /* if this is a pure oplock break request then don't send a
6205 if (num_locks == 0 && num_ulocks == 0) {
6206 /* Sanity check - ensure a pure oplock break is not a
6208 if(CVAL(req->inbuf,smb_vwv0) != 0xff)
6209 DEBUG(0,("reply_lockingX: Error : pure oplock "
6210 "break is a chained %d request !\n",
6211 (unsigned int)CVAL(req->inbuf,
6213 END_PROFILE(SMBlockingX);
6219 * We do this check *after* we have checked this is not a oplock break
6220 * response message. JRA.
6223 release_level_2_oplocks_on_change(fsp);
6225 if (smb_buflen(req->inbuf) <
6226 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6227 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6228 END_PROFILE(SMBlockingX);
6232 /* Data now points at the beginning of the list
6233 of smb_unlkrng structs */
6234 for(i = 0; i < (int)num_ulocks; i++) {
6235 lock_pid = get_lock_pid( data, i, large_file_format);
6236 count = get_lock_count( data, i, large_file_format);
6237 offset = get_lock_offset( data, i, large_file_format, &err);
6240 * There is no error code marked "stupid client bug".... :-).
6243 END_PROFILE(SMBlockingX);
6244 reply_doserror(req, ERRDOS, ERRnoaccess);
6248 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6249 "pid %u, file %s\n", (double)offset, (double)count,
6250 (unsigned int)lock_pid, fsp->fsp_name ));
6252 status = do_unlock(smbd_messaging_context(),
6259 if (NT_STATUS_V(status)) {
6260 END_PROFILE(SMBlockingX);
6261 reply_nterror(req, status);
6266 /* Setup the timeout in seconds. */
6268 if (!lp_blocking_locks(SNUM(conn))) {
6272 /* Now do any requested locks */
6273 data += ((large_file_format ? 20 : 10)*num_ulocks);
6275 /* Data now points at the beginning of the list
6276 of smb_lkrng structs */
6278 for(i = 0; i < (int)num_locks; i++) {
6279 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6280 READ_LOCK:WRITE_LOCK);
6281 lock_pid = get_lock_pid( data, i, large_file_format);
6282 count = get_lock_count( data, i, large_file_format);
6283 offset = get_lock_offset( data, i, large_file_format, &err);
6286 * There is no error code marked "stupid client bug".... :-).
6289 END_PROFILE(SMBlockingX);
6290 reply_doserror(req, ERRDOS, ERRnoaccess);
6294 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6295 "%u, file %s timeout = %d\n", (double)offset,
6296 (double)count, (unsigned int)lock_pid,
6297 fsp->fsp_name, (int)lock_timeout ));
6299 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6300 if (lp_blocking_locks(SNUM(conn))) {
6302 /* Schedule a message to ourselves to
6303 remove the blocking lock record and
6304 return the right error. */
6306 if (!blocking_lock_cancel(fsp,
6312 NT_STATUS_FILE_LOCK_CONFLICT)) {
6313 END_PROFILE(SMBlockingX);
6318 ERRcancelviolation));
6322 /* Remove a matching pending lock. */
6323 status = do_lock_cancel(fsp,
6329 BOOL blocking_lock = lock_timeout ? True : False;
6330 BOOL defer_lock = False;
6331 struct byte_range_lock *br_lck;
6332 uint32 block_smbpid;
6334 br_lck = do_lock(smbd_messaging_context(),
6345 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6346 /* Windows internal resolution for blocking locks seems
6347 to be about 200ms... Don't wait for less than that. JRA. */
6348 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6349 lock_timeout = lp_lock_spin_time();
6354 /* This heuristic seems to match W2K3 very well. If a
6355 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6356 it pretends we asked for a timeout of between 150 - 300 milliseconds as
6357 far as I can tell. Replacement for do_lock_spin(). JRA. */
6359 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6360 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6362 lock_timeout = lp_lock_spin_time();
6365 if (br_lck && defer_lock) {
6367 * A blocking lock was requested. Package up
6368 * this smb into a queued request and push it
6369 * onto the blocking lock queue.
6371 if(push_blocking_lock_request(br_lck,
6373 smb_len(req->inbuf)+4,
6383 TALLOC_FREE(br_lck);
6384 END_PROFILE(SMBlockingX);
6385 reply_post_legacy(req, -1);
6390 TALLOC_FREE(br_lck);
6393 if (NT_STATUS_V(status)) {
6394 END_PROFILE(SMBlockingX);
6395 reply_nterror(req, status);
6400 /* If any of the above locks failed, then we must unlock
6401 all of the previous locks (X/Open spec). */
6403 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6407 * Ensure we don't do a remove on the lock that just failed,
6408 * as under POSIX rules, if we have a lock already there, we
6409 * will delete it (and we shouldn't) .....
6411 for(i--; i >= 0; i--) {
6412 lock_pid = get_lock_pid( data, i, large_file_format);
6413 count = get_lock_count( data, i, large_file_format);
6414 offset = get_lock_offset( data, i, large_file_format,
6418 * There is no error code marked "stupid client
6422 END_PROFILE(SMBlockingX);
6423 reply_doserror(req, ERRDOS, ERRnoaccess);
6427 do_unlock(smbd_messaging_context(),
6434 END_PROFILE(SMBlockingX);
6435 reply_nterror(req, status);
6439 reply_outbuf(req, 2, 0);
6441 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
6442 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
6444 END_PROFILE(SMBlockingX);
6445 chain_reply_new(req);
6449 #define DBGC_CLASS DBGC_ALL
6451 /****************************************************************************
6452 Reply to a SMBreadbmpx (read block multiplex) request.
6453 ****************************************************************************/
6455 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
6466 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6467 START_PROFILE(SMBreadBmpx);
6469 /* this function doesn't seem to work - disable by default */
6470 if (!lp_readbmpx()) {
6471 END_PROFILE(SMBreadBmpx);
6472 return ERROR_DOS(ERRSRV,ERRuseSTD);
6475 outsize = set_message(inbuf,outbuf,8,0,True);
6477 CHECK_FSP(fsp,conn);
6478 if (!CHECK_READ(fsp,inbuf)) {
6479 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6482 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
6483 maxcount = SVAL(inbuf,smb_vwv3);
6485 data = smb_buf(outbuf);
6486 pad = ((long)data)%4;
6491 max_per_packet = bufsize-(outsize+pad);
6495 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
6496 END_PROFILE(SMBreadBmpx);
6497 return ERROR_DOS(ERRDOS,ERRlock);
6501 size_t N = MIN(max_per_packet,tcount-total_read);
6503 nread = read_file(fsp,data,startpos,N);
6508 if (nread < (ssize_t)N)
6509 tcount = total_read + nread;
6511 set_message(inbuf,outbuf,8,nread+pad,False);
6512 SIVAL(outbuf,smb_vwv0,startpos);
6513 SSVAL(outbuf,smb_vwv2,tcount);
6514 SSVAL(outbuf,smb_vwv6,nread);
6515 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
6518 if (!send_smb(smbd_server_fd(),outbuf))
6519 exit_server_cleanly("reply_readbmpx: send_smb failed.");
6521 total_read += nread;
6523 } while (total_read < (ssize_t)tcount);
6525 END_PROFILE(SMBreadBmpx);
6529 /****************************************************************************
6530 Reply to a SMBsetattrE.
6531 ****************************************************************************/
6533 void reply_setattrE(connection_struct *conn, struct smb_request *req)
6535 struct timespec ts[2];
6538 START_PROFILE(SMBsetattrE);
6541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6542 END_PROFILE(SMBsetattrE);
6546 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
6548 if(!fsp || (fsp->conn != conn)) {
6549 reply_doserror(req, ERRDOS, ERRbadfid);
6550 END_PROFILE(SMBsetattrE);
6556 * Convert the DOS times into unix times. Ignore create
6557 * time as UNIX can't set this.
6560 ts[0] = convert_time_t_to_timespec(
6561 srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */
6562 ts[1] = convert_time_t_to_timespec(
6563 srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */
6565 reply_outbuf(req, 0, 0);
6568 * Patch from Ray Frush <frush@engr.colostate.edu>
6569 * Sometimes times are sent as zero - ignore them.
6572 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
6573 /* Ignore request */
6574 if( DEBUGLVL( 3 ) ) {
6575 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
6576 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
6578 END_PROFILE(SMBsetattrE);
6580 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
6581 /* set modify time = to access time if modify time was unset */
6585 /* Set the date on this file */
6586 /* Should we set pending modtime here ? JRA */
6587 if(file_ntimes(conn, fsp->fsp_name, ts)) {
6588 reply_doserror(req, ERRDOS, ERRnoaccess);
6589 END_PROFILE(SMBsetattrE);
6593 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
6595 (unsigned int)ts[0].tv_sec,
6596 (unsigned int)ts[1].tv_sec));
6598 END_PROFILE(SMBsetattrE);
6603 /* Back from the dead for OS/2..... JRA. */
6605 /****************************************************************************
6606 Reply to a SMBwritebmpx (write block multiplex primary) request.
6607 ****************************************************************************/
6609 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6612 ssize_t nwritten = -1;
6619 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6621 START_PROFILE(SMBwriteBmpx);
6623 CHECK_FSP(fsp,conn);
6624 if (!CHECK_WRITE(fsp)) {
6625 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6627 if (HAS_CACHED_ERROR(fsp)) {
6628 return(CACHED_ERROR(fsp));
6631 tcount = SVAL(inbuf,smb_vwv1);
6632 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
6633 write_through = BITSETW(inbuf+smb_vwv7,0);
6634 numtowrite = SVAL(inbuf,smb_vwv10);
6635 smb_doff = SVAL(inbuf,smb_vwv11);
6637 data = smb_base(inbuf) + smb_doff;
6639 /* If this fails we need to send an SMBwriteC response,
6640 not an SMBwritebmpx - set this up now so we don't forget */
6641 SCVAL(outbuf,smb_com,SMBwritec);
6643 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
6644 END_PROFILE(SMBwriteBmpx);
6645 return(ERROR_DOS(ERRDOS,ERRlock));
6648 nwritten = write_file(fsp,data,startpos,numtowrite);
6650 status = sync_file(conn, fsp, write_through);
6651 if (!NT_STATUS_IS_OK(status)) {
6652 END_PROFILE(SMBwriteBmpx);
6653 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
6654 fsp->fsp_name, nt_errstr(status) ));
6655 return ERROR_NT(status);
6658 if(nwritten < (ssize_t)numtowrite) {
6659 END_PROFILE(SMBwriteBmpx);
6660 return(UNIXERROR(ERRHRD,ERRdiskfull));
6663 /* If the maximum to be written to this file
6664 is greater than what we just wrote then set
6665 up a secondary struct to be attached to this
6666 fd, we will use this to cache error messages etc. */
6668 if((ssize_t)tcount > nwritten) {
6669 write_bmpx_struct *wbms;
6670 if(fsp->wbmpx_ptr != NULL)
6671 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
6673 wbms = SMB_MALLOC_P(write_bmpx_struct);
6675 DEBUG(0,("Out of memory in reply_readmpx\n"));
6676 END_PROFILE(SMBwriteBmpx);
6677 return(ERROR_DOS(ERRSRV,ERRnoresource));
6679 wbms->wr_mode = write_through;
6680 wbms->wr_discard = False; /* No errors yet */
6681 wbms->wr_total_written = nwritten;
6682 wbms->wr_errclass = 0;
6684 fsp->wbmpx_ptr = wbms;
6687 /* We are returning successfully, set the message type back to
6689 SCVAL(outbuf,smb_com,SMBwriteBmpx);
6691 outsize = set_message(inbuf,outbuf,1,0,True);
6693 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
6695 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
6696 fsp->fnum, (int)numtowrite, (int)nwritten ) );
6698 if (write_through && tcount==nwritten) {
6699 /* We need to send both a primary and a secondary response */
6700 smb_setlen(inbuf,outbuf,outsize - 4);
6702 if (!send_smb(smbd_server_fd(),outbuf))
6703 exit_server_cleanly("reply_writebmpx: send_smb failed.");
6705 /* Now the secondary */
6706 outsize = set_message(inbuf,outbuf,1,0,True);
6707 SCVAL(outbuf,smb_com,SMBwritec);
6708 SSVAL(outbuf,smb_vwv0,nwritten);
6711 END_PROFILE(SMBwriteBmpx);
6715 /****************************************************************************
6716 Reply to a SMBwritebs (write block multiplex secondary) request.
6717 ****************************************************************************/
6719 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
6722 ssize_t nwritten = -1;
6729 write_bmpx_struct *wbms;
6730 BOOL send_response = False;
6731 files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0));
6733 START_PROFILE(SMBwriteBs);
6735 CHECK_FSP(fsp,conn);
6736 if (!CHECK_WRITE(fsp)) {
6737 return(ERROR_DOS(ERRDOS,ERRbadaccess));
6740 tcount = SVAL(inbuf,smb_vwv1);
6741 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6742 numtowrite = SVAL(inbuf,smb_vwv6);
6743 smb_doff = SVAL(inbuf,smb_vwv7);
6745 data = smb_base(inbuf) + smb_doff;
6747 /* We need to send an SMBwriteC response, not an SMBwritebs */
6748 SCVAL(outbuf,smb_com,SMBwritec);
6750 /* This fd should have an auxiliary struct attached,
6751 check that it does */
6752 wbms = fsp->wbmpx_ptr;
6754 END_PROFILE(SMBwriteBs);
6758 /* If write through is set we can return errors, else we must cache them */
6759 write_through = wbms->wr_mode;
6761 /* Check for an earlier error */
6762 if(wbms->wr_discard) {
6763 END_PROFILE(SMBwriteBs);
6764 return -1; /* Just discard the packet */
6767 nwritten = write_file(fsp,data,startpos,numtowrite);
6769 status = sync_file(conn, fsp, write_through);
6771 if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6773 /* We are returning an error - we can delete the aux struct */
6776 fsp->wbmpx_ptr = NULL;
6777 END_PROFILE(SMBwriteBs);
6778 return(ERROR_DOS(ERRHRD,ERRdiskfull));
6780 wbms->wr_errclass = ERRHRD;
6781 wbms->wr_error = ERRdiskfull;
6782 wbms->wr_status = NT_STATUS_DISK_FULL;
6783 wbms->wr_discard = True;
6784 END_PROFILE(SMBwriteBs);
6788 /* Increment the total written, if this matches tcount
6789 we can discard the auxiliary struct (hurrah !) and return a writeC */
6790 wbms->wr_total_written += nwritten;
6791 if(wbms->wr_total_written >= tcount) {
6792 if (write_through) {
6793 outsize = set_message(inbuf,outbuf,1,0,True);
6794 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
6795 send_response = True;
6799 fsp->wbmpx_ptr = NULL;
6803 END_PROFILE(SMBwriteBs);
6807 END_PROFILE(SMBwriteBs);
6811 /****************************************************************************
6812 Reply to a SMBgetattrE.
6813 ****************************************************************************/
6815 void reply_getattrE(connection_struct *conn, struct smb_request *req)
6817 SMB_STRUCT_STAT sbuf;
6821 START_PROFILE(SMBgetattrE);
6824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6825 END_PROFILE(SMBgetattrE);
6829 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
6831 if(!fsp || (fsp->conn != conn)) {
6832 reply_doserror(req, ERRDOS, ERRbadfid);
6833 END_PROFILE(SMBgetattrE);
6837 /* Do an fstat on this file */
6838 if(fsp_stat(fsp, &sbuf)) {
6839 reply_unixerror(req, ERRDOS, ERRnoaccess);
6840 END_PROFILE(SMBgetattrE);
6844 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6847 * Convert the times into dos times. Set create
6848 * date to be last modify date as UNIX doesn't save
6852 reply_outbuf(req, 11, 0);
6854 srv_put_dos_date2((char *)req->outbuf, smb_vwv0,
6855 get_create_time(&sbuf,
6856 lp_fake_dir_create_times(SNUM(conn))));
6857 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
6858 /* Should we check pending modtime here ? JRA */
6859 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
6862 SIVAL(req->outbuf, smb_vwv6, 0);
6863 SIVAL(req->outbuf, smb_vwv8, 0);
6865 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6866 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
6867 SIVAL(req->outbuf, smb_vwv8, allocation_size);
6869 SSVAL(req->outbuf,smb_vwv10, mode);
6871 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6873 END_PROFILE(SMBgetattrE);