2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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;
33 unsigned int smb_echo_count = 0;
34 extern uint32 global_client_caps;
36 extern struct current_user current_user;
37 extern BOOL global_encrypted_passwords_negotiated;
39 /****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
41 path or anything including wildcards.
42 We're assuming here that '/' is not the second byte in any multibyte char
43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
45 ****************************************************************************/
47 /* Custom version for processing POSIX paths. */
48 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
50 static NTSTATUS check_path_syntax_internal(char *path,
52 BOOL *p_last_component_contains_wcard)
56 NTSTATUS ret = NT_STATUS_OK;
57 BOOL start_of_name_component = True;
59 *p_last_component_contains_wcard = False;
62 if (IS_PATH_SEP(*s,posix_path)) {
64 * Safe to assume is not the second part of a mb char
65 * as this is handled below.
67 /* Eat multiple '/' or '\\' */
68 while (IS_PATH_SEP(*s,posix_path)) {
71 if ((d != path) && (*s != '\0')) {
72 /* We only care about non-leading or trailing '/' or '\\' */
76 start_of_name_component = True;
78 *p_last_component_contains_wcard = False;
82 if (start_of_name_component) {
83 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
84 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
87 * No mb char starts with '.' so we're safe checking the directory separator here.
90 /* If we just added a '/' - delete it */
91 if ((d > path) && (*(d-1) == '/')) {
96 /* Are we at the start ? Can't go back further if so. */
98 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
101 /* Go back one level... */
102 /* We know this is safe as '/' cannot be part of a mb sequence. */
103 /* NOTE - if this assumption is invalid we are not in good shape... */
104 /* Decrement d first as d points to the *next* char to write into. */
105 for (d--; d > path; d--) {
109 s += 2; /* Else go past the .. */
110 /* We're still at the start of a name component, just the previous one. */
113 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
126 return NT_STATUS_OBJECT_NAME_INVALID;
134 *p_last_component_contains_wcard = True;
143 /* Get the size of the next MB character. */
144 next_codepoint(s,&siz);
162 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
164 return NT_STATUS_INVALID_PARAMETER;
167 start_of_name_component = False;
174 /****************************************************************************
175 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
176 No wildcards allowed.
177 ****************************************************************************/
179 NTSTATUS check_path_syntax(char *path)
182 return check_path_syntax_internal(path, False, &ignore);
185 /****************************************************************************
186 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
187 Wildcards allowed - p_contains_wcard returns true if the last component contained
189 ****************************************************************************/
191 NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
193 return check_path_syntax_internal(path, False, p_contains_wcard);
196 /****************************************************************************
197 Check the path for a POSIX client.
198 We're assuming here that '/' is not the second byte in any multibyte char
199 set (a safe assumption).
200 ****************************************************************************/
202 NTSTATUS check_path_syntax_posix(char *path)
205 return check_path_syntax_internal(path, True, &ignore);
208 /****************************************************************************
209 Pull a string and check the path allowing a wilcard - provide for error return.
210 ****************************************************************************/
212 size_t srvstr_get_path_wcard(char *inbuf, uint16 smb_flags2, char *dest,
213 const char *src, size_t dest_len, size_t src_len,
214 int flags, NTSTATUS *err, BOOL *contains_wcard)
218 SMB_ASSERT(dest_len == sizeof(pstring));
222 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
225 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
226 dest_len, src_len, flags);
229 *contains_wcard = False;
231 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
233 * For a DFS path the function parse_dfs_path()
234 * will do the path processing, just make a copy.
240 if (lp_posix_pathnames()) {
241 *err = check_path_syntax_posix(dest);
243 *err = check_path_syntax_wcard(dest, contains_wcard);
249 /****************************************************************************
250 Pull a string and check the path - provide for error return.
251 ****************************************************************************/
253 size_t srvstr_get_path(char *inbuf, uint16 smb_flags2, char *dest,
254 const char *src, size_t dest_len, size_t src_len,
255 int flags, NTSTATUS *err)
259 SMB_ASSERT(dest_len == sizeof(pstring));
263 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
266 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
267 dest_len, src_len, flags);
270 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
272 * For a DFS path the function parse_dfs_path()
273 * will do the path processing, just make a copy.
279 if (lp_posix_pathnames()) {
280 *err = check_path_syntax_posix(dest);
282 *err = check_path_syntax(dest);
288 /****************************************************************************
289 Reply to a special message.
290 ****************************************************************************/
292 int reply_special(char *inbuf,char *outbuf)
295 int msg_type = CVAL(inbuf,0);
296 int msg_flags = CVAL(inbuf,1);
300 static BOOL already_got_session = False;
304 memset(outbuf,'\0',smb_size);
306 smb_setlen(inbuf,outbuf,0);
309 case 0x81: /* session request */
311 if (already_got_session) {
312 exit_server_cleanly("multiple session request not permitted");
315 SCVAL(outbuf,0,0x82);
317 if (name_len(inbuf+4) > 50 ||
318 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
319 DEBUG(0,("Invalid name length in session request\n"));
322 name_extract(inbuf,4,name1);
323 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
324 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
327 set_local_machine_name(name1, True);
328 set_remote_machine_name(name2, True);
330 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
331 get_local_machine_name(), get_remote_machine_name(),
334 if (name_type == 'R') {
335 /* We are being asked for a pathworks session ---
337 SCVAL(outbuf, 0,0x83);
341 /* only add the client's machine name to the list
342 of possibly valid usernames if we are operating
343 in share mode security */
344 if (lp_security() == SEC_SHARE) {
345 add_session_user(get_remote_machine_name());
348 reload_services(True);
351 already_got_session = True;
354 case 0x89: /* session keepalive request
355 (some old clients produce this?) */
356 SCVAL(outbuf,0,SMBkeepalive);
360 case 0x82: /* positive session response */
361 case 0x83: /* negative session response */
362 case 0x84: /* retarget session response */
363 DEBUG(0,("Unexpected session response\n"));
366 case SMBkeepalive: /* session keepalive */
371 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
372 msg_type, msg_flags));
377 /****************************************************************************
379 conn POINTER CAN BE NULL HERE !
380 ****************************************************************************/
382 int reply_tcon(connection_struct *conn,
383 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
390 uint16 vuid = SVAL(inbuf,smb_uid);
394 DATA_BLOB password_blob;
396 START_PROFILE(SMBtcon);
398 *service_buf = *password = *dev = 0;
400 p = smb_buf(inbuf)+1;
401 p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), service_buf, p,
402 sizeof(service_buf), STR_TERMINATE) + 1;
403 pwlen = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), password, p,
404 sizeof(password), STR_TERMINATE) + 1;
406 p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dev, p, sizeof(dev),
409 p = strrchr_m(service_buf,'\\');
413 service = service_buf;
416 password_blob = data_blob(password, pwlen+1);
418 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
420 data_blob_clear_free(&password_blob);
423 END_PROFILE(SMBtcon);
424 return ERROR_NT(nt_status);
427 outsize = set_message(inbuf,outbuf,2,0,True);
428 SSVAL(outbuf,smb_vwv0,max_recv);
429 SSVAL(outbuf,smb_vwv1,conn->cnum);
430 SSVAL(outbuf,smb_tid,conn->cnum);
432 DEBUG(3,("tcon service=%s cnum=%d\n",
433 service, conn->cnum));
435 END_PROFILE(SMBtcon);
439 /****************************************************************************
440 Reply to a tcon and X.
441 conn POINTER CAN BE NULL HERE !
442 ****************************************************************************/
444 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
449 /* what the cleint thinks the device is */
450 fstring client_devicetype;
451 /* what the server tells the client the share represents */
452 const char *server_devicetype;
454 uint16 vuid = SVAL(inbuf,smb_uid);
455 int passlen = SVAL(inbuf,smb_vwv3);
458 uint16 tcon_flags = SVAL(inbuf,smb_vwv2);
460 START_PROFILE(SMBtconX);
462 *service = *client_devicetype = 0;
464 /* we might have to close an old one */
465 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
466 close_cnum(conn,vuid);
469 if (passlen > MAX_PASS_LEN) {
470 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
473 if (global_encrypted_passwords_negotiated) {
474 password = data_blob(smb_buf(inbuf),passlen);
475 if (lp_security() == SEC_SHARE) {
477 * Security = share always has a pad byte
478 * after the password.
480 p = smb_buf(inbuf) + passlen + 1;
482 p = smb_buf(inbuf) + passlen;
485 password = data_blob(smb_buf(inbuf),passlen+1);
486 /* Ensure correct termination */
487 password.data[passlen]=0;
488 p = smb_buf(inbuf) + passlen + 1;
491 p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), path, p,
492 sizeof(path), STR_TERMINATE);
495 * the service name can be either: \\server\share
496 * or share directly like on the DELL PowerVault 705
499 q = strchr_m(path+2,'\\');
501 END_PROFILE(SMBtconX);
502 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
504 fstrcpy(service,q+1);
507 fstrcpy(service,path);
509 p += srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), client_devicetype, p,
510 sizeof(client_devicetype), 6, STR_ASCII);
512 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
514 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
516 data_blob_clear_free(&password);
519 END_PROFILE(SMBtconX);
520 return ERROR_NT(nt_status);
524 server_devicetype = "IPC";
525 else if ( IS_PRINT(conn) )
526 server_devicetype = "LPT1:";
528 server_devicetype = "A:";
530 if (Protocol < PROTOCOL_NT1) {
531 set_message(inbuf,outbuf,2,0,True);
533 p += srvstr_push(outbuf, p, server_devicetype, -1,
534 STR_TERMINATE|STR_ASCII);
535 set_message_end(inbuf,outbuf,p);
537 /* NT sets the fstype of IPC$ to the null string */
538 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
540 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
541 /* Return permissions. */
545 set_message(inbuf,outbuf,7,0,True);
548 perm1 = FILE_ALL_ACCESS;
549 perm2 = FILE_ALL_ACCESS;
551 perm1 = CAN_WRITE(conn) ?
556 SIVAL(outbuf, smb_vwv3, perm1);
557 SIVAL(outbuf, smb_vwv5, perm2);
559 set_message(inbuf,outbuf,3,0,True);
563 p += srvstr_push(outbuf, p, server_devicetype, -1,
564 STR_TERMINATE|STR_ASCII);
565 p += srvstr_push(outbuf, p, fstype, -1,
568 set_message_end(inbuf,outbuf,p);
570 /* what does setting this bit do? It is set by NT4 and
571 may affect the ability to autorun mounted cdroms */
572 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
573 (lp_csc_policy(SNUM(conn)) << 2));
575 init_dfsroot(conn, inbuf, outbuf);
579 DEBUG(3,("tconX service=%s \n",
582 /* set the incoming and outgoing tid to the just created one */
583 SSVAL(inbuf,smb_tid,conn->cnum);
584 SSVAL(outbuf,smb_tid,conn->cnum);
586 END_PROFILE(SMBtconX);
587 return chain_reply(inbuf,outbuf,length,bufsize);
590 /****************************************************************************
591 Reply to an unknown type.
592 ****************************************************************************/
594 int reply_unknown(char *inbuf,char *outbuf)
597 type = CVAL(inbuf,smb_com);
599 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
600 smb_fn_name(type), type, type));
602 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
605 /****************************************************************************
607 conn POINTER CAN BE NULL HERE !
608 ****************************************************************************/
610 int reply_ioctl(connection_struct *conn,
611 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
613 uint16 device = SVAL(inbuf,smb_vwv1);
614 uint16 function = SVAL(inbuf,smb_vwv2);
615 uint32 ioctl_code = (device << 16) + function;
616 int replysize, outsize;
618 START_PROFILE(SMBioctl);
620 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
622 switch (ioctl_code) {
623 case IOCTL_QUERY_JOB_INFO:
627 END_PROFILE(SMBioctl);
628 return(ERROR_DOS(ERRSRV,ERRnosupport));
631 outsize = set_message(inbuf,outbuf,8,replysize+1,True);
632 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
633 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
634 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
635 p = smb_buf(outbuf) + 1; /* Allow for alignment */
637 switch (ioctl_code) {
638 case IOCTL_QUERY_JOB_INFO:
640 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
642 END_PROFILE(SMBioctl);
643 return(UNIXERROR(ERRDOS,ERRbadfid));
645 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
646 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
648 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
654 END_PROFILE(SMBioctl);
658 /****************************************************************************
659 Strange checkpath NTSTATUS mapping.
660 ****************************************************************************/
662 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
664 /* Strange DOS error code semantics only for checkpath... */
665 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
666 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
667 /* We need to map to ERRbadpath */
668 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
674 /****************************************************************************
675 Reply to a checkpath.
676 ****************************************************************************/
678 int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
682 SMB_STRUCT_STAT sbuf;
685 START_PROFILE(SMBcheckpath);
687 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), name, smb_buf(inbuf) + 1,
688 sizeof(name), 0, STR_TERMINATE, &status);
689 if (!NT_STATUS_IS_OK(status)) {
690 END_PROFILE(SMBcheckpath);
691 status = map_checkpath_error(inbuf, status);
692 return ERROR_NT(status);
695 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name);
696 if (!NT_STATUS_IS_OK(status)) {
697 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
698 END_PROFILE(SMBcheckpath);
699 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
704 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
706 status = unix_convert(conn, name, False, NULL, &sbuf);
707 if (!NT_STATUS_IS_OK(status)) {
711 status = check_name(conn, name);
712 if (!NT_STATUS_IS_OK(status)) {
713 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
717 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
718 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
719 status = map_nt_error_from_unix(errno);
723 if (!S_ISDIR(sbuf.st_mode)) {
724 END_PROFILE(SMBcheckpath);
725 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
728 outsize = set_message(inbuf,outbuf,0,0,False);
730 END_PROFILE(SMBcheckpath);
735 END_PROFILE(SMBcheckpath);
737 /* We special case this - as when a Windows machine
738 is parsing a path is steps through the components
739 one at a time - if a component fails it expects
740 ERRbadpath, not ERRbadfile.
742 status = map_checkpath_error(inbuf, status);
743 if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
745 * Windows returns different error codes if
746 * the parent directory is valid but not the
747 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
748 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
749 * if the path is invalid.
751 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
754 return ERROR_NT(status);
757 /****************************************************************************
759 ****************************************************************************/
761 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
765 SMB_STRUCT_STAT sbuf;
772 START_PROFILE(SMBgetatr);
774 p = smb_buf(inbuf) + 1;
775 p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
776 sizeof(fname), 0, STR_TERMINATE, &status);
777 if (!NT_STATUS_IS_OK(status)) {
778 END_PROFILE(SMBgetatr);
779 return ERROR_NT(status);
782 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
783 if (!NT_STATUS_IS_OK(status)) {
784 END_PROFILE(SMBgetatr);
785 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
786 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
788 return ERROR_NT(status);
791 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
792 under WfWg - weird! */
793 if (*fname == '\0') {
794 mode = aHIDDEN | aDIR;
795 if (!CAN_WRITE(conn)) {
801 status = unix_convert(conn, fname, False, NULL,&sbuf);
802 if (!NT_STATUS_IS_OK(status)) {
803 END_PROFILE(SMBgetatr);
804 return ERROR_NT(status);
806 status = check_name(conn, fname);
807 if (!NT_STATUS_IS_OK(status)) {
808 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
809 END_PROFILE(SMBgetatr);
810 return ERROR_NT(status);
812 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
813 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
814 return UNIXERROR(ERRDOS,ERRbadfile);
817 mode = dos_mode(conn,fname,&sbuf);
819 mtime = sbuf.st_mtime;
825 outsize = set_message(inbuf,outbuf,10,0,True);
827 SSVAL(outbuf,smb_vwv0,mode);
828 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
829 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
831 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
833 SIVAL(outbuf,smb_vwv3,(uint32)size);
835 if (Protocol >= PROTOCOL_NT1) {
836 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
839 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
841 END_PROFILE(SMBgetatr);
845 /****************************************************************************
847 ****************************************************************************/
849 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
855 SMB_STRUCT_STAT sbuf;
859 START_PROFILE(SMBsetatr);
861 p = smb_buf(inbuf) + 1;
862 p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
863 sizeof(fname), 0, STR_TERMINATE, &status);
864 if (!NT_STATUS_IS_OK(status)) {
865 END_PROFILE(SMBsetatr);
866 return ERROR_NT(status);
869 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
870 if (!NT_STATUS_IS_OK(status)) {
871 END_PROFILE(SMBsetatr);
872 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
873 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
875 return ERROR_NT(status);
878 status = unix_convert(conn, fname, False, NULL, &sbuf);
879 if (!NT_STATUS_IS_OK(status)) {
880 END_PROFILE(SMBsetatr);
881 return ERROR_NT(status);
884 status = check_name(conn, fname);
885 if (!NT_STATUS_IS_OK(status)) {
886 END_PROFILE(SMBsetatr);
887 return ERROR_NT(status);
890 if (fname[0] == '.' && fname[1] == '\0') {
892 * Not sure here is the right place to catch this
893 * condition. Might be moved to somewhere else later -- vl
895 END_PROFILE(SMBsetatr);
896 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
899 mode = SVAL(inbuf,smb_vwv0);
900 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
902 if (mode != FILE_ATTRIBUTE_NORMAL) {
903 if (VALID_STAT_OF_DIR(sbuf))
908 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
909 END_PROFILE(SMBsetatr);
910 return UNIXERROR(ERRDOS, ERRnoaccess);
914 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
915 END_PROFILE(SMBsetatr);
916 return UNIXERROR(ERRDOS, ERRnoaccess);
919 outsize = set_message(inbuf,outbuf,0,0,False);
921 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
923 END_PROFILE(SMBsetatr);
927 /****************************************************************************
929 ****************************************************************************/
931 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
934 SMB_BIG_UINT dfree,dsize,bsize;
935 START_PROFILE(SMBdskattr);
937 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
938 END_PROFILE(SMBdskattr);
939 return(UNIXERROR(ERRHRD,ERRgeneral));
942 outsize = set_message(inbuf,outbuf,5,0,True);
944 if (Protocol <= PROTOCOL_LANMAN2) {
945 double total_space, free_space;
946 /* we need to scale this to a number that DOS6 can handle. We
947 use floating point so we can handle large drives on systems
948 that don't have 64 bit integers
950 we end up displaying a maximum of 2G to DOS systems
952 total_space = dsize * (double)bsize;
953 free_space = dfree * (double)bsize;
955 dsize = (total_space+63*512) / (64*512);
956 dfree = (free_space+63*512) / (64*512);
958 if (dsize > 0xFFFF) dsize = 0xFFFF;
959 if (dfree > 0xFFFF) dfree = 0xFFFF;
961 SSVAL(outbuf,smb_vwv0,dsize);
962 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
963 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
964 SSVAL(outbuf,smb_vwv3,dfree);
966 SSVAL(outbuf,smb_vwv0,dsize);
967 SSVAL(outbuf,smb_vwv1,bsize/512);
968 SSVAL(outbuf,smb_vwv2,512);
969 SSVAL(outbuf,smb_vwv3,dfree);
972 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
974 END_PROFILE(SMBdskattr);
978 /****************************************************************************
980 Can be called from SMBsearch, SMBffirst or SMBfunique.
981 ****************************************************************************/
983 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
993 unsigned int numentries = 0;
994 unsigned int maxentries = 0;
995 BOOL finished = False;
1001 BOOL check_descend = False;
1002 BOOL expect_close = False;
1004 BOOL mask_contains_wcard = False;
1005 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1007 START_PROFILE(SMBsearch);
1009 if (lp_posix_pathnames()) {
1010 END_PROFILE(SMBsearch);
1011 return reply_unknown(inbuf, outbuf);
1014 *mask = *directory = *fname = 0;
1016 /* If we were called as SMBffirst then we must expect close. */
1017 if(CVAL(inbuf,smb_com) == SMBffirst) {
1018 expect_close = True;
1021 outsize = set_message(inbuf,outbuf,1,3,True);
1022 maxentries = SVAL(inbuf,smb_vwv0);
1023 dirtype = SVAL(inbuf,smb_vwv1);
1024 p = smb_buf(inbuf) + 1;
1025 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1026 sizeof(path), 0, STR_TERMINATE, &nt_status,
1027 &mask_contains_wcard);
1028 if (!NT_STATUS_IS_OK(nt_status)) {
1029 END_PROFILE(SMBsearch);
1030 return ERROR_NT(nt_status);
1033 nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
1034 if (!NT_STATUS_IS_OK(nt_status)) {
1035 END_PROFILE(SMBsearch);
1036 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1037 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1039 return ERROR_NT(nt_status);
1043 status_len = SVAL(p, 0);
1046 /* dirtype &= ~aDIR; */
1048 if (status_len == 0) {
1049 SMB_STRUCT_STAT sbuf;
1051 pstrcpy(directory,path);
1052 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1053 if (!NT_STATUS_IS_OK(nt_status)) {
1054 END_PROFILE(SMBsearch);
1055 return ERROR_NT(nt_status);
1058 nt_status = check_name(conn, directory);
1059 if (!NT_STATUS_IS_OK(nt_status)) {
1060 END_PROFILE(SMBsearch);
1061 return ERROR_NT(nt_status);
1064 p = strrchr_m(directory,'/');
1066 pstrcpy(mask,directory);
1067 pstrcpy(directory,".");
1073 if (*directory == '\0') {
1074 pstrcpy(directory,".");
1076 memset((char *)status,'\0',21);
1077 SCVAL(status,0,(dirtype & 0x1F));
1081 memcpy(status,p,21);
1082 status_dirtype = CVAL(status,0) & 0x1F;
1083 if (status_dirtype != (dirtype & 0x1F)) {
1084 dirtype = status_dirtype;
1087 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1088 if (!conn->dirptr) {
1091 string_set(&conn->dirpath,dptr_path(dptr_num));
1092 pstrcpy(mask, dptr_wcard(dptr_num));
1094 * For a 'continue' search we have no string. So
1095 * check from the initial saved string.
1097 mask_contains_wcard = ms_has_wild(mask);
1100 p = smb_buf(outbuf) + 3;
1102 if (status_len == 0) {
1103 nt_status = dptr_create(conn,
1107 SVAL(inbuf,smb_pid),
1109 mask_contains_wcard,
1112 if (!NT_STATUS_IS_OK(nt_status)) {
1113 return ERROR_NT(nt_status);
1115 dptr_num = dptr_dnum(conn->dirptr);
1117 dirtype = dptr_attr(dptr_num);
1120 DEBUG(4,("dptr_num is %d\n",dptr_num));
1122 if ((dirtype&0x1F) == aVOLID) {
1123 memcpy(p,status,21);
1124 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1125 0,aVOLID,0,!allow_long_path_components);
1126 dptr_fill(p+12,dptr_num);
1127 if (dptr_zero(p+12) && (status_len==0)) {
1132 p += DIR_STRUCT_SIZE;
1135 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1137 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1138 conn->dirpath,lp_dontdescend(SNUM(conn))));
1139 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1140 check_descend = True;
1143 for (i=numentries;(i<maxentries) && !finished;i++) {
1144 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1146 memcpy(p,status,21);
1147 make_dir_struct(p,mask,fname,size, mode,date,
1148 !allow_long_path_components);
1149 if (!dptr_fill(p+12,dptr_num)) {
1153 p += DIR_STRUCT_SIZE;
1160 /* If we were called as SMBffirst with smb_search_id == NULL
1161 and no entries were found then return error and close dirptr
1164 if (numentries == 0) {
1165 dptr_close(&dptr_num);
1166 } else if(expect_close && status_len == 0) {
1167 /* Close the dptr - we know it's gone */
1168 dptr_close(&dptr_num);
1171 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1172 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1173 dptr_close(&dptr_num);
1176 if ((numentries == 0) && !mask_contains_wcard) {
1177 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1180 SSVAL(outbuf,smb_vwv0,numentries);
1181 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1182 SCVAL(smb_buf(outbuf),0,5);
1183 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1185 /* The replies here are never long name. */
1186 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1187 if (!allow_long_path_components) {
1188 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1191 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1192 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1194 outsize += DIR_STRUCT_SIZE*numentries;
1195 smb_setlen(inbuf,outbuf,outsize - 4);
1197 if ((! *directory) && dptr_path(dptr_num))
1198 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1200 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1201 smb_fn_name(CVAL(inbuf,smb_com)),
1202 mask, directory, dirtype, numentries, maxentries ) );
1204 END_PROFILE(SMBsearch);
1208 /****************************************************************************
1209 Reply to a fclose (stop directory search).
1210 ****************************************************************************/
1212 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1221 BOOL path_contains_wcard = False;
1223 START_PROFILE(SMBfclose);
1225 if (lp_posix_pathnames()) {
1226 END_PROFILE(SMBfclose);
1227 return reply_unknown(inbuf, outbuf);
1230 outsize = set_message(inbuf,outbuf,1,0,True);
1231 p = smb_buf(inbuf) + 1;
1232 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1233 sizeof(path), 0, STR_TERMINATE, &err,
1234 &path_contains_wcard);
1235 if (!NT_STATUS_IS_OK(err)) {
1236 END_PROFILE(SMBfclose);
1237 return ERROR_NT(err);
1240 status_len = SVAL(p,0);
1243 if (status_len == 0) {
1244 END_PROFILE(SMBfclose);
1245 return ERROR_DOS(ERRSRV,ERRsrverror);
1248 memcpy(status,p,21);
1250 if(dptr_fetch(status+12,&dptr_num)) {
1251 /* Close the dptr - we know it's gone */
1252 dptr_close(&dptr_num);
1255 SSVAL(outbuf,smb_vwv0,0);
1257 DEBUG(3,("search close\n"));
1259 END_PROFILE(SMBfclose);
1263 /****************************************************************************
1265 ****************************************************************************/
1267 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1275 SMB_STRUCT_STAT sbuf;
1277 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1279 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1282 uint32 create_disposition;
1283 uint32 create_options = 0;
1285 struct smb_request req;
1287 START_PROFILE(SMBopen);
1289 init_smb_request(&req, (uint8 *)inbuf);
1291 deny_mode = SVAL(inbuf,smb_vwv0);
1293 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1294 sizeof(fname), 0, STR_TERMINATE, &status);
1295 if (!NT_STATUS_IS_OK(status)) {
1296 END_PROFILE(SMBopen);
1297 return ERROR_NT(status);
1300 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 END_PROFILE(SMBopen);
1303 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1304 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1306 return ERROR_NT(status);
1309 status = unix_convert(conn, fname, False, NULL, &sbuf);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 END_PROFILE(SMBopen);
1312 return ERROR_NT(status);
1315 status = check_name(conn, fname);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 END_PROFILE(SMBopen);
1318 return ERROR_NT(status);
1321 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1322 &access_mask, &share_mode, &create_disposition, &create_options)) {
1323 END_PROFILE(SMBopen);
1324 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1327 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1336 if (!NT_STATUS_IS_OK(status)) {
1337 END_PROFILE(SMBopen);
1338 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1339 /* We have re-scheduled this call. */
1342 return ERROR_NT(status);
1345 size = sbuf.st_size;
1346 fattr = dos_mode(conn,fname,&sbuf);
1347 mtime = sbuf.st_mtime;
1350 DEBUG(3,("attempt to open a directory %s\n",fname));
1351 close_file(fsp,ERROR_CLOSE);
1352 END_PROFILE(SMBopen);
1353 return ERROR_DOS(ERRDOS,ERRnoaccess);
1356 outsize = set_message(inbuf,outbuf,7,0,True);
1357 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1358 SSVAL(outbuf,smb_vwv1,fattr);
1359 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1360 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1362 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1364 SIVAL(outbuf,smb_vwv4,(uint32)size);
1365 SSVAL(outbuf,smb_vwv6,deny_mode);
1367 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1368 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1371 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1372 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1374 END_PROFILE(SMBopen);
1378 /****************************************************************************
1379 Reply to an open and X.
1380 ****************************************************************************/
1382 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1385 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1386 int deny_mode = SVAL(inbuf,smb_vwv3);
1387 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1388 /* Breakout the oplock request bits so we can set the
1389 reply bits separately. */
1390 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1391 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1392 int oplock_request = ex_oplock_request | core_oplock_request;
1394 int smb_sattr = SVAL(inbuf,smb_vwv4);
1395 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1397 int smb_ofun = SVAL(inbuf,smb_vwv8);
1400 SMB_STRUCT_STAT sbuf;
1404 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1405 ssize_t retval = -1;
1408 uint32 create_disposition;
1409 uint32 create_options = 0;
1410 struct smb_request req;
1412 START_PROFILE(SMBopenX);
1414 init_smb_request(&req, (uint8 *)inbuf);
1416 /* If it's an IPC, pass off the pipe handler. */
1418 if (lp_nt_pipe_support()) {
1419 END_PROFILE(SMBopenX);
1420 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1422 END_PROFILE(SMBopenX);
1423 return ERROR_DOS(ERRSRV,ERRaccess);
1427 /* XXXX we need to handle passed times, sattr and flags */
1428 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf),
1429 sizeof(fname), 0, STR_TERMINATE, &status);
1430 if (!NT_STATUS_IS_OK(status)) {
1431 END_PROFILE(SMBopenX);
1432 return ERROR_NT(status);
1435 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1436 if (!NT_STATUS_IS_OK(status)) {
1437 END_PROFILE(SMBopenX);
1438 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1439 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1441 return ERROR_NT(status);
1444 status = unix_convert(conn, fname, False, NULL, &sbuf);
1445 if (!NT_STATUS_IS_OK(status)) {
1446 END_PROFILE(SMBopenX);
1447 return ERROR_NT(status);
1450 status = check_name(conn, fname);
1451 if (!NT_STATUS_IS_OK(status)) {
1452 END_PROFILE(SMBopenX);
1453 return ERROR_NT(status);
1456 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1459 &create_disposition,
1461 END_PROFILE(SMBopenX);
1462 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1465 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1474 if (!NT_STATUS_IS_OK(status)) {
1475 END_PROFILE(SMBopenX);
1476 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1477 /* We have re-scheduled this call. */
1480 return ERROR_NT(status);
1483 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1484 if the file is truncated or created. */
1485 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1486 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1487 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1488 close_file(fsp,ERROR_CLOSE);
1489 END_PROFILE(SMBopenX);
1490 return ERROR_NT(NT_STATUS_DISK_FULL);
1492 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1494 close_file(fsp,ERROR_CLOSE);
1495 END_PROFILE(SMBopenX);
1496 return ERROR_NT(NT_STATUS_DISK_FULL);
1498 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1501 fattr = dos_mode(conn,fname,&sbuf);
1502 mtime = sbuf.st_mtime;
1504 close_file(fsp,ERROR_CLOSE);
1505 END_PROFILE(SMBopenX);
1506 return ERROR_DOS(ERRDOS,ERRnoaccess);
1509 /* If the caller set the extended oplock request bit
1510 and we granted one (by whatever means) - set the
1511 correct bit for extended oplock reply.
1514 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1515 smb_action |= EXTENDED_OPLOCK_GRANTED;
1518 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1519 smb_action |= EXTENDED_OPLOCK_GRANTED;
1522 /* If the caller set the core oplock request bit
1523 and we granted one (by whatever means) - set the
1524 correct bit for core oplock reply.
1527 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1528 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1531 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1532 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1535 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1536 set_message(inbuf,outbuf,19,0,True);
1538 set_message(inbuf,outbuf,15,0,True);
1540 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1541 SSVAL(outbuf,smb_vwv3,fattr);
1542 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1543 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1545 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1547 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1548 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1549 SSVAL(outbuf,smb_vwv11,smb_action);
1551 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1552 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1555 END_PROFILE(SMBopenX);
1556 return chain_reply(inbuf,outbuf,length,bufsize);
1559 /****************************************************************************
1560 Reply to a SMBulogoffX.
1561 conn POINTER CAN BE NULL HERE !
1562 ****************************************************************************/
1564 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1566 uint16 vuid = SVAL(inbuf,smb_uid);
1567 user_struct *vuser = get_valid_user_struct(vuid);
1568 START_PROFILE(SMBulogoffX);
1571 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1573 /* in user level security we are supposed to close any files
1574 open by this user */
1575 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1576 file_close_user(vuid);
1578 invalidate_vuid(vuid);
1580 set_message(inbuf,outbuf,2,0,True);
1582 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1584 END_PROFILE(SMBulogoffX);
1585 return chain_reply(inbuf,outbuf,length,bufsize);
1588 /****************************************************************************
1589 Reply to a mknew or a create.
1590 ****************************************************************************/
1592 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1597 uint32 fattr = SVAL(inbuf,smb_vwv0);
1598 struct timespec ts[2];
1600 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1601 SMB_STRUCT_STAT sbuf;
1603 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1604 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1605 uint32 create_disposition;
1606 uint32 create_options = 0;
1607 struct smb_request req;
1609 START_PROFILE(SMBcreate);
1611 init_smb_request(&req, (uint8 *)inbuf);
1613 com = SVAL(inbuf,smb_com);
1615 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1617 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1,
1618 sizeof(fname), 0, STR_TERMINATE, &status);
1619 if (!NT_STATUS_IS_OK(status)) {
1620 END_PROFILE(SMBcreate);
1621 return ERROR_NT(status);
1624 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1625 if (!NT_STATUS_IS_OK(status)) {
1626 END_PROFILE(SMBcreate);
1627 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1628 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1630 return ERROR_NT(status);
1633 status = unix_convert(conn, fname, False, NULL, &sbuf);
1634 if (!NT_STATUS_IS_OK(status)) {
1635 END_PROFILE(SMBcreate);
1636 return ERROR_NT(status);
1639 status = check_name(conn, fname);
1640 if (!NT_STATUS_IS_OK(status)) {
1641 END_PROFILE(SMBcreate);
1642 return ERROR_NT(status);
1645 if (fattr & aVOLID) {
1646 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1649 if(com == SMBmknew) {
1650 /* We should fail if file exists. */
1651 create_disposition = FILE_CREATE;
1653 /* Create if file doesn't exist, truncate if it does. */
1654 create_disposition = FILE_OVERWRITE_IF;
1657 /* Open file using ntcreate. */
1658 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1667 if (!NT_STATUS_IS_OK(status)) {
1668 END_PROFILE(SMBcreate);
1669 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1670 /* We have re-scheduled this call. */
1673 return ERROR_NT(status);
1676 ts[0] = get_atimespec(&sbuf); /* atime. */
1677 file_ntimes(conn, fname, ts);
1679 outsize = set_message(inbuf,outbuf,1,0,True);
1680 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1682 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1683 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1686 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1687 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1690 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1691 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1693 END_PROFILE(SMBcreate);
1697 /****************************************************************************
1698 Reply to a create temporary file.
1699 ****************************************************************************/
1701 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1705 uint32 fattr = SVAL(inbuf,smb_vwv0);
1707 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1709 SMB_STRUCT_STAT sbuf;
1712 unsigned int namelen;
1713 struct smb_request req;
1715 START_PROFILE(SMBctemp);
1717 init_smb_request(&req, (uint8 *)inbuf);
1719 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1720 sizeof(fname), 0, STR_TERMINATE, &status);
1721 if (!NT_STATUS_IS_OK(status)) {
1722 END_PROFILE(SMBctemp);
1723 return ERROR_NT(status);
1726 pstrcat(fname,"/TMXXXXXX");
1728 pstrcat(fname,"TMXXXXXX");
1731 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1732 if (!NT_STATUS_IS_OK(status)) {
1733 END_PROFILE(SMBctemp);
1734 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1735 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1737 return ERROR_NT(status);
1740 status = unix_convert(conn, fname, False, NULL, &sbuf);
1741 if (!NT_STATUS_IS_OK(status)) {
1742 END_PROFILE(SMBctemp);
1743 return ERROR_NT(status);
1746 status = check_name(conn, fname);
1747 if (!NT_STATUS_IS_OK(status)) {
1748 END_PROFILE(SMBctemp);
1749 return ERROR_NT(status);
1752 tmpfd = smb_mkstemp(fname);
1754 END_PROFILE(SMBctemp);
1755 return(UNIXERROR(ERRDOS,ERRnoaccess));
1758 SMB_VFS_STAT(conn,fname,&sbuf);
1760 /* We should fail if file does not exist. */
1761 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1762 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1763 FILE_SHARE_READ|FILE_SHARE_WRITE,
1770 /* close fd from smb_mkstemp() */
1773 if (!NT_STATUS_IS_OK(status)) {
1774 END_PROFILE(SMBctemp);
1775 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1776 /* We have re-scheduled this call. */
1779 return ERROR_NT(status);
1782 outsize = set_message(inbuf,outbuf,1,0,True);
1783 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1785 /* the returned filename is relative to the directory */
1786 s = strrchr_m(fname, '/');
1793 p = smb_buf(outbuf);
1795 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1796 thing in the byte section. JRA */
1797 SSVALS(p, 0, -1); /* what is this? not in spec */
1799 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1801 outsize = set_message_end(inbuf,outbuf, p);
1803 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1804 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1807 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1808 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1811 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1812 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1813 (unsigned int)sbuf.st_mode ) );
1815 END_PROFILE(SMBctemp);
1819 /*******************************************************************
1820 Check if a user is allowed to rename a file.
1821 ********************************************************************/
1823 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1824 uint16 dirtype, SMB_STRUCT_STAT *pst)
1828 if (!CAN_WRITE(conn)) {
1829 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1832 fmode = dos_mode(conn, fsp->fsp_name, pst);
1833 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1834 return NT_STATUS_NO_SUCH_FILE;
1837 if (S_ISDIR(pst->st_mode)) {
1838 return NT_STATUS_OK;
1841 if (fsp->access_mask & DELETE_ACCESS) {
1842 return NT_STATUS_OK;
1845 return NT_STATUS_ACCESS_DENIED;
1848 /*******************************************************************
1849 * unlink a file with all relevant access checks
1850 *******************************************************************/
1852 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
1853 char *fname, uint32 dirtype)
1855 SMB_STRUCT_STAT sbuf;
1858 uint32 dirtype_orig = dirtype;
1861 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
1863 if (!CAN_WRITE(conn)) {
1864 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1867 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1868 return map_nt_error_from_unix(errno);
1871 fattr = dos_mode(conn,fname,&sbuf);
1873 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1874 dirtype = aDIR|aARCH|aRONLY;
1877 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1879 return NT_STATUS_NO_SUCH_FILE;
1882 if (!dir_check_ftype(conn, fattr, dirtype)) {
1884 return NT_STATUS_FILE_IS_A_DIRECTORY;
1886 return NT_STATUS_NO_SUCH_FILE;
1889 if (dirtype_orig & 0x8000) {
1890 /* These will never be set for POSIX. */
1891 return NT_STATUS_NO_SUCH_FILE;
1895 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1896 return NT_STATUS_FILE_IS_A_DIRECTORY;
1899 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1900 return NT_STATUS_NO_SUCH_FILE;
1903 if (dirtype & 0xFF00) {
1904 /* These will never be set for POSIX. */
1905 return NT_STATUS_NO_SUCH_FILE;
1910 return NT_STATUS_NO_SUCH_FILE;
1913 /* Can't delete a directory. */
1915 return NT_STATUS_FILE_IS_A_DIRECTORY;
1920 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1921 return NT_STATUS_OBJECT_NAME_INVALID;
1922 #endif /* JRATEST */
1924 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1926 On a Windows share, a file with read-only dosmode can be opened with
1927 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1928 fails with NT_STATUS_CANNOT_DELETE error.
1930 This semantic causes a problem that a user can not
1931 rename a file with read-only dosmode on a Samba share
1932 from a Windows command prompt (i.e. cmd.exe, but can rename
1933 from Windows Explorer).
1936 if (!lp_delete_readonly(SNUM(conn))) {
1937 if (fattr & aRONLY) {
1938 return NT_STATUS_CANNOT_DELETE;
1942 /* On open checks the open itself will check the share mode, so
1943 don't do it here as we'll get it wrong. */
1945 status = open_file_ntcreate(conn, req, fname, &sbuf,
1950 FILE_ATTRIBUTE_NORMAL,
1951 req != NULL ? 0 : INTERNAL_OPEN_ONLY,
1954 if (!NT_STATUS_IS_OK(status)) {
1955 DEBUG(10, ("open_file_ntcreate failed: %s\n",
1956 nt_errstr(status)));
1960 /* The set is across all open files on this dev/inode pair. */
1961 if (!set_delete_on_close(fsp, True, ¤t_user.ut)) {
1962 close_file(fsp, NORMAL_CLOSE);
1963 return NT_STATUS_ACCESS_DENIED;
1966 return close_file(fsp,NORMAL_CLOSE);
1969 /****************************************************************************
1970 The guts of the unlink command, split out so it may be called by the NT SMB
1972 ****************************************************************************/
1974 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
1975 uint32 dirtype, char *name, BOOL has_wild)
1981 NTSTATUS status = NT_STATUS_OK;
1982 SMB_STRUCT_STAT sbuf;
1984 *directory = *mask = 0;
1986 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1987 if (!NT_STATUS_IS_OK(status)) {
1991 p = strrchr_m(name,'/');
1993 pstrcpy(directory,".");
1997 pstrcpy(directory,name);
2002 * We should only check the mangled cache
2003 * here if unix_convert failed. This means
2004 * that the path in 'mask' doesn't exist
2005 * on the file system and so we need to look
2006 * for a possible mangle. This patch from
2007 * Tine Smukavec <valentin.smukavec@hermes.si>.
2010 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
2011 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
2014 pstrcat(directory,"/");
2015 pstrcat(directory,mask);
2017 dirtype = FILE_ATTRIBUTE_NORMAL;
2020 status = check_name(conn, directory);
2021 if (!NT_STATUS_IS_OK(status)) {
2025 status = do_unlink(conn, req, directory, dirtype);
2026 if (!NT_STATUS_IS_OK(status)) {
2032 struct smb_Dir *dir_hnd = NULL;
2036 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2037 return NT_STATUS_OBJECT_NAME_INVALID;
2040 if (strequal(mask,"????????.???")) {
2044 status = check_name(conn, directory);
2045 if (!NT_STATUS_IS_OK(status)) {
2049 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2050 if (dir_hnd == NULL) {
2051 return map_nt_error_from_unix(errno);
2054 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2055 the pattern matches against the long name, otherwise the short name
2056 We don't implement this yet XXXX
2059 status = NT_STATUS_NO_SUCH_FILE;
2061 while ((dname = ReadDirName(dir_hnd, &offset))) {
2064 pstrcpy(fname,dname);
2066 if (!is_visible_file(conn, directory, dname, &st, True)) {
2070 /* Quick check for "." and ".." */
2071 if (fname[0] == '.') {
2072 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2077 if(!mask_match(fname, mask, conn->case_sensitive)) {
2081 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2083 status = check_name(conn, fname);
2084 if (!NT_STATUS_IS_OK(status)) {
2089 status = do_unlink(conn, req, fname, dirtype);
2090 if (!NT_STATUS_IS_OK(status)) {
2095 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2101 if (count == 0 && NT_STATUS_IS_OK(status)) {
2102 status = map_nt_error_from_unix(errno);
2108 /****************************************************************************
2110 ****************************************************************************/
2112 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2119 BOOL path_contains_wcard = False;
2120 struct smb_request req;
2122 START_PROFILE(SMBunlink);
2124 init_smb_request(&req, (uint8 *)inbuf);
2126 dirtype = SVAL(inbuf,smb_vwv0);
2128 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name,
2129 smb_buf(inbuf) + 1, sizeof(name), 0,
2130 STR_TERMINATE, &status, &path_contains_wcard);
2131 if (!NT_STATUS_IS_OK(status)) {
2132 END_PROFILE(SMBunlink);
2133 return ERROR_NT(status);
2136 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
2137 if (!NT_STATUS_IS_OK(status)) {
2138 END_PROFILE(SMBunlink);
2139 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2140 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
2142 return ERROR_NT(status);
2145 DEBUG(3,("reply_unlink : %s\n",name));
2147 status = unlink_internals(conn, &req, dirtype, name,
2148 path_contains_wcard);
2149 if (!NT_STATUS_IS_OK(status)) {
2150 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2151 /* We have re-scheduled this call. */
2154 return ERROR_NT(status);
2157 outsize = set_message(inbuf,outbuf,0,0,False);
2159 END_PROFILE(SMBunlink);
2163 /****************************************************************************
2165 ****************************************************************************/
2167 static void fail_readraw(void)
2170 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2172 exit_server_cleanly(errstr);
2175 /****************************************************************************
2176 Fake (read/write) sendfile. Returns -1 on read or write fail.
2177 ****************************************************************************/
2179 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
2181 size_t tosend = nread;
2183 while (tosend > 0) {
2187 if (tosend > bufsize) {
2192 ret = read_file(fsp,buf,startpos,cur_read);
2197 /* If we had a short read, fill with zeros. */
2198 if (ret < cur_read) {
2199 memset(buf, '\0', cur_read - ret);
2202 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2206 startpos += cur_read;
2209 return (ssize_t)nread;
2212 /****************************************************************************
2213 Use sendfile in readbraw.
2214 ****************************************************************************/
2216 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2217 ssize_t mincount, char *outbuf, int out_buffsize)
2221 #if defined(WITH_SENDFILE)
2223 * We can only use sendfile on a non-chained packet
2224 * but we can use on a non-oplocked file. tridge proved this
2225 * on a train in Germany :-). JRA.
2226 * reply_readbraw has already checked the length.
2229 if ( (chain_size == 0) && (nread > 0) &&
2230 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2233 _smb_setlen(outbuf,nread);
2234 header.data = (uint8 *)outbuf;
2238 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2239 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2240 if (errno == ENOSYS) {
2241 goto normal_readbraw;
2245 * Special hack for broken Linux with no working sendfile. If we
2246 * return EINTR we sent the header but not the rest of the data.
2247 * Fake this up by doing read/write calls.
2249 if (errno == EINTR) {
2250 /* Ensure we don't do this again. */
2251 set_use_sendfile(SNUM(conn), False);
2252 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2254 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2255 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2256 fsp->fsp_name, strerror(errno) ));
2257 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2262 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2263 fsp->fsp_name, strerror(errno) ));
2264 exit_server_cleanly("send_file_readbraw sendfile failed");
2274 ret = read_file(fsp,outbuf+4,startpos,nread);
2275 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2284 _smb_setlen(outbuf,ret);
2285 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2289 /****************************************************************************
2290 Reply to a readbraw (core+ protocol).
2291 ****************************************************************************/
2293 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2295 ssize_t maxcount,mincount;
2298 char *header = outbuf;
2300 START_PROFILE(SMBreadbraw);
2302 if (srv_is_signing_active()) {
2303 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2307 * Special check if an oplock break has been issued
2308 * and the readraw request croses on the wire, we must
2309 * return a zero length response here.
2312 fsp = file_fsp(inbuf,smb_vwv0);
2314 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2316 * fsp could be NULL here so use the value from the packet. JRA.
2318 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2319 _smb_setlen(header,0);
2320 if (write_data(smbd_server_fd(),header,4) != 4)
2322 END_PROFILE(SMBreadbraw);
2326 CHECK_FSP(fsp,conn);
2328 flush_write_cache(fsp, READRAW_FLUSH);
2330 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2331 if(CVAL(inbuf,smb_wct) == 10) {
2333 * This is a large offset (64 bit) read.
2335 #ifdef LARGE_SMB_OFF_T
2337 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2339 #else /* !LARGE_SMB_OFF_T */
2342 * Ensure we haven't been sent a >32 bit offset.
2345 if(IVAL(inbuf,smb_vwv8) != 0) {
2346 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2347 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2348 _smb_setlen(header,0);
2349 if (write_data(smbd_server_fd(),header,4) != 4)
2351 END_PROFILE(SMBreadbraw);
2355 #endif /* LARGE_SMB_OFF_T */
2358 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2359 _smb_setlen(header,0);
2360 if (write_data(smbd_server_fd(),header,4) != 4)
2362 END_PROFILE(SMBreadbraw);
2366 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2367 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2369 /* ensure we don't overrun the packet size */
2370 maxcount = MIN(65535,maxcount);
2372 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2376 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2380 if (startpos >= size) {
2383 nread = MIN(maxcount,(size - startpos));
2387 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2388 if (nread < mincount)
2392 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2393 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2395 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2397 DEBUG(5,("readbraw finished\n"));
2398 END_PROFILE(SMBreadbraw);
2403 #define DBGC_CLASS DBGC_LOCKING
2405 /****************************************************************************
2406 Reply to a lockread (core+ protocol).
2407 ****************************************************************************/
2409 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2417 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2418 struct byte_range_lock *br_lck = NULL;
2419 START_PROFILE(SMBlockread);
2421 CHECK_FSP(fsp,conn);
2422 if (!CHECK_READ(fsp,inbuf)) {
2423 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2426 release_level_2_oplocks_on_change(fsp);
2428 numtoread = SVAL(inbuf,smb_vwv1);
2429 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2431 outsize = set_message(inbuf,outbuf,5,3,True);
2432 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2433 data = smb_buf(outbuf) + 3;
2436 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2437 * protocol request that predates the read/write lock concept.
2438 * Thus instead of asking for a read lock here we need to ask
2439 * for a write lock. JRA.
2440 * Note that the requested lock size is unaffected by max_recv.
2443 br_lck = do_lock(smbd_messaging_context(),
2445 (uint32)SVAL(inbuf,smb_pid),
2446 (SMB_BIG_UINT)numtoread,
2447 (SMB_BIG_UINT)startpos,
2450 False, /* Non-blocking lock. */
2453 TALLOC_FREE(br_lck);
2455 if (NT_STATUS_V(status)) {
2456 END_PROFILE(SMBlockread);
2457 return ERROR_NT(status);
2461 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2464 if (numtoread > max_recv) {
2465 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2466 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2467 (unsigned int)numtoread, (unsigned int)max_recv ));
2468 numtoread = MIN(numtoread,max_recv);
2470 nread = read_file(fsp,data,startpos,numtoread);
2473 END_PROFILE(SMBlockread);
2474 return(UNIXERROR(ERRDOS,ERRnoaccess));
2478 SSVAL(outbuf,smb_vwv0,nread);
2479 SSVAL(outbuf,smb_vwv5,nread+3);
2480 SSVAL(smb_buf(outbuf),1,nread);
2482 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2483 fsp->fnum, (int)numtoread, (int)nread));
2485 END_PROFILE(SMBlockread);
2490 #define DBGC_CLASS DBGC_ALL
2492 /****************************************************************************
2494 ****************************************************************************/
2496 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2503 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2504 START_PROFILE(SMBread);
2506 CHECK_FSP(fsp,conn);
2507 if (!CHECK_READ(fsp,inbuf)) {
2508 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2511 numtoread = SVAL(inbuf,smb_vwv1);
2512 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2514 outsize = set_message(inbuf,outbuf,5,3,True);
2515 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2517 * The requested read size cannot be greater than max_recv. JRA.
2519 if (numtoread > max_recv) {
2520 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2521 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2522 (unsigned int)numtoread, (unsigned int)max_recv ));
2523 numtoread = MIN(numtoread,max_recv);
2526 data = smb_buf(outbuf) + 3;
2528 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2529 END_PROFILE(SMBread);
2530 return ERROR_DOS(ERRDOS,ERRlock);
2534 nread = read_file(fsp,data,startpos,numtoread);
2537 END_PROFILE(SMBread);
2538 return(UNIXERROR(ERRDOS,ERRnoaccess));
2542 SSVAL(outbuf,smb_vwv0,nread);
2543 SSVAL(outbuf,smb_vwv5,nread+3);
2544 SCVAL(smb_buf(outbuf),0,1);
2545 SSVAL(smb_buf(outbuf),1,nread);
2547 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2548 fsp->fnum, (int)numtoread, (int)nread ) );
2550 END_PROFILE(SMBread);
2554 /****************************************************************************
2556 ****************************************************************************/
2558 static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
2561 char *data = smb_buf(outbuf);
2563 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2564 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2565 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2566 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2567 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2568 SCVAL(outbuf,smb_vwv0,0xFF);
2569 outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
2570 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2571 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2575 /****************************************************************************
2576 Reply to a read and X - possibly using sendfile.
2577 ****************************************************************************/
2579 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2580 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2582 SMB_STRUCT_STAT sbuf;
2585 char *data = smb_buf(outbuf);
2587 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2588 return(UNIXERROR(ERRDOS,ERRnoaccess));
2591 if (startpos > sbuf.st_size) {
2593 } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
2594 smb_maxcnt = (sbuf.st_size - startpos);
2597 if (smb_maxcnt == 0) {
2601 #if defined(WITH_SENDFILE)
2603 * We can only use sendfile on a non-chained packet
2604 * but we can use on a non-oplocked file. tridge proved this
2605 * on a train in Germany :-). JRA.
2608 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2609 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2613 * Set up the packet header before send. We
2614 * assume here the sendfile will work (get the
2615 * correct amount of data).
2618 setup_readX_header(inbuf,outbuf,smb_maxcnt);
2619 set_message(inbuf,outbuf,12,smb_maxcnt,False);
2620 header.data = (uint8 *)outbuf;
2621 header.length = data - outbuf;
2624 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2625 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2626 if (errno == ENOSYS) {
2631 * Special hack for broken Linux with no working sendfile. If we
2632 * return EINTR we sent the header but not the rest of the data.
2633 * Fake this up by doing read/write calls.
2636 if (errno == EINTR) {
2637 /* Ensure we don't do this again. */
2638 set_use_sendfile(SNUM(conn), False);
2639 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2641 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2642 len_outbuf - (data-outbuf))) == -1) {
2643 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2644 fsp->fsp_name, strerror(errno) ));
2645 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2647 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2648 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2649 /* Returning -1 here means successful sendfile. */
2653 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2654 fsp->fsp_name, strerror(errno) ));
2655 exit_server_cleanly("send_file_readX sendfile failed");
2658 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2659 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2660 /* Returning -1 here means successful sendfile. */
2668 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
2669 int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
2670 /* Send out the header. */
2671 if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
2672 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2673 fsp->fsp_name, strerror(errno) ));
2674 exit_server_cleanly("send_file_readX sendfile failed");
2676 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2677 len_outbuf - (data-outbuf))) == -1) {
2678 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2679 fsp->fsp_name, strerror(errno) ));
2680 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2684 nread = read_file(fsp,data,startpos,smb_maxcnt);
2687 return(UNIXERROR(ERRDOS,ERRnoaccess));
2690 outsize = setup_readX_header(inbuf, outbuf,nread);
2692 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2693 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2695 /* Returning the number of bytes we want to send back - including header. */
2700 /****************************************************************************
2701 Reply to a read and X.
2702 ****************************************************************************/
2704 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2706 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2707 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2709 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2710 BOOL big_readX = False;
2712 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2715 START_PROFILE(SMBreadX);
2717 /* If it's an IPC, pass off the pipe handler. */
2719 END_PROFILE(SMBreadX);
2720 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2723 CHECK_FSP(fsp,conn);
2724 if (!CHECK_READ(fsp,inbuf)) {
2725 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2728 set_message(inbuf,outbuf,12,0,True);
2730 if (global_client_caps & CAP_LARGE_READX) {
2731 size_t upper_size = SVAL(inbuf,smb_vwv7);
2732 smb_maxcnt |= (upper_size<<16);
2733 if (upper_size > 1) {
2734 /* Can't do this on a chained packet. */
2735 if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
2736 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2738 /* We currently don't do this on signed or sealed data. */
2739 if (srv_is_signing_active() || srv_encryption_on()) {
2740 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2742 /* Is there room in the reply for this data ? */
2743 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
2744 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2750 if(CVAL(inbuf,smb_wct) == 12) {
2751 #ifdef LARGE_SMB_OFF_T
2753 * This is a large offset (64 bit) read.
2755 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2757 #else /* !LARGE_SMB_OFF_T */
2760 * Ensure we haven't been sent a >32 bit offset.
2763 if(IVAL(inbuf,smb_vwv10) != 0) {
2764 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2765 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2766 END_PROFILE(SMBreadX);
2767 return ERROR_DOS(ERRDOS,ERRbadaccess);
2770 #endif /* LARGE_SMB_OFF_T */
2774 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2775 END_PROFILE(SMBreadX);
2776 return ERROR_DOS(ERRDOS,ERRlock);
2779 if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2780 END_PROFILE(SMBreadX);
2784 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2785 /* Only call chain_reply if not an error. */
2786 if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2787 nread = chain_reply(inbuf,outbuf,length,bufsize);
2790 END_PROFILE(SMBreadX);
2794 /****************************************************************************
2795 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2796 ****************************************************************************/
2798 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2801 ssize_t total_written=0;
2802 size_t numtowrite=0;
2807 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2810 START_PROFILE(SMBwritebraw);
2812 if (srv_is_signing_active()) {
2813 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2816 CHECK_FSP(fsp,conn);
2817 if (!CHECK_WRITE(fsp)) {
2818 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2821 tcount = IVAL(inbuf,smb_vwv1);
2822 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2823 write_through = BITSETW(inbuf+smb_vwv7,0);
2825 /* We have to deal with slightly different formats depending
2826 on whether we are using the core+ or lanman1.0 protocol */
2828 if(Protocol <= PROTOCOL_COREPLUS) {
2829 numtowrite = SVAL(smb_buf(inbuf),-2);
2830 data = smb_buf(inbuf);
2832 numtowrite = SVAL(inbuf,smb_vwv10);
2833 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2836 /* force the error type */
2837 SCVAL(inbuf,smb_com,SMBwritec);
2838 SCVAL(outbuf,smb_com,SMBwritec);
2840 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2841 END_PROFILE(SMBwritebraw);
2842 return(ERROR_DOS(ERRDOS,ERRlock));
2846 nwritten = write_file(fsp,data,startpos,numtowrite);
2848 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2849 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2851 if (nwritten < (ssize_t)numtowrite) {
2852 END_PROFILE(SMBwritebraw);
2853 return(UNIXERROR(ERRHRD,ERRdiskfull));
2856 total_written = nwritten;
2858 /* Return a message to the redirector to tell it to send more bytes */
2859 SCVAL(outbuf,smb_com,SMBwritebraw);
2860 SSVALS(outbuf,smb_vwv0,-1);
2861 outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2863 if (!send_smb(smbd_server_fd(),outbuf))
2864 exit_server_cleanly("reply_writebraw: send_smb failed.");
2866 /* Now read the raw data into the buffer and write it */
2867 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2868 exit_server_cleanly("secondary writebraw failed");
2871 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2872 numtowrite = smb_len(inbuf);
2874 /* Set up outbuf to return the correct return */
2875 outsize = set_message(inbuf,outbuf,1,0,True);
2876 SCVAL(outbuf,smb_com,SMBwritec);
2878 if (numtowrite != 0) {
2880 if (numtowrite > BUFFER_SIZE) {
2881 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2882 (unsigned int)numtowrite ));
2883 exit_server_cleanly("secondary writebraw failed");
2886 if (tcount > nwritten+numtowrite) {
2887 DEBUG(3,("Client overestimated the write %d %d %d\n",
2888 (int)tcount,(int)nwritten,(int)numtowrite));
2891 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2892 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2894 exit_server_cleanly("secondary writebraw failed");
2897 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2898 if (nwritten == -1) {
2899 END_PROFILE(SMBwritebraw);
2900 return(UNIXERROR(ERRHRD,ERRdiskfull));
2903 if (nwritten < (ssize_t)numtowrite) {
2904 SCVAL(outbuf,smb_rcls,ERRHRD);
2905 SSVAL(outbuf,smb_err,ERRdiskfull);
2909 total_written += nwritten;
2912 SSVAL(outbuf,smb_vwv0,total_written);
2914 status = sync_file(conn, fsp, write_through);
2915 if (!NT_STATUS_IS_OK(status)) {
2916 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
2917 fsp->fsp_name, nt_errstr(status) ));
2918 END_PROFILE(SMBwritebraw);
2919 return ERROR_NT(status);
2922 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2923 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2925 /* we won't return a status if write through is not selected - this follows what WfWg does */
2926 END_PROFILE(SMBwritebraw);
2927 if (!write_through && total_written==tcount) {
2929 #if RABBIT_PELLET_FIX
2931 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2932 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2934 if (!send_keepalive(smbd_server_fd()))
2935 exit_server_cleanly("reply_writebraw: send of keepalive failed");
2944 #define DBGC_CLASS DBGC_LOCKING
2946 /****************************************************************************
2947 Reply to a writeunlock (core+).
2948 ****************************************************************************/
2950 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2951 int size, int dum_buffsize)
2953 ssize_t nwritten = -1;
2957 NTSTATUS status = NT_STATUS_OK;
2958 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2960 START_PROFILE(SMBwriteunlock);
2962 CHECK_FSP(fsp,conn);
2963 if (!CHECK_WRITE(fsp)) {
2964 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2967 numtowrite = SVAL(inbuf,smb_vwv1);
2968 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2969 data = smb_buf(inbuf) + 3;
2971 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2972 END_PROFILE(SMBwriteunlock);
2973 return ERROR_DOS(ERRDOS,ERRlock);
2976 /* The special X/Open SMB protocol handling of
2977 zero length writes is *NOT* done for
2979 if(numtowrite == 0) {
2982 nwritten = write_file(fsp,data,startpos,numtowrite);
2985 status = sync_file(conn, fsp, False /* write through */);
2986 if (!NT_STATUS_IS_OK(status)) {
2987 END_PROFILE(SMBwriteunlock);
2988 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
2989 fsp->fsp_name, nt_errstr(status) ));
2990 return ERROR_NT(status);
2993 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2994 END_PROFILE(SMBwriteunlock);
2995 return(UNIXERROR(ERRHRD,ERRdiskfull));
2999 status = do_unlock(smbd_messaging_context(),
3001 (uint32)SVAL(inbuf,smb_pid),
3002 (SMB_BIG_UINT)numtowrite,
3003 (SMB_BIG_UINT)startpos,
3006 if (NT_STATUS_V(status)) {
3007 END_PROFILE(SMBwriteunlock);
3008 return ERROR_NT(status);
3012 outsize = set_message(inbuf,outbuf,1,0,True);
3014 SSVAL(outbuf,smb_vwv0,nwritten);
3016 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3017 fsp->fnum, (int)numtowrite, (int)nwritten));
3019 END_PROFILE(SMBwriteunlock);
3024 #define DBGC_CLASS DBGC_ALL
3026 /****************************************************************************
3028 ****************************************************************************/
3030 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
3033 ssize_t nwritten = -1;
3036 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3039 START_PROFILE(SMBwrite);
3041 /* If it's an IPC, pass off the pipe handler. */
3043 END_PROFILE(SMBwrite);
3044 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3047 CHECK_FSP(fsp,conn);
3048 if (!CHECK_WRITE(fsp)) {
3049 END_PROFILE(SMBwrite);
3050 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3053 numtowrite = SVAL(inbuf,smb_vwv1);
3054 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3055 data = smb_buf(inbuf) + 3;
3057 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3058 END_PROFILE(SMBwrite);
3059 return ERROR_DOS(ERRDOS,ERRlock);
3063 * X/Open SMB protocol says that if smb_vwv1 is
3064 * zero then the file size should be extended or
3065 * truncated to the size given in smb_vwv[2-3].
3068 if(numtowrite == 0) {
3070 * This is actually an allocate call, and set EOF. JRA.
3072 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3074 END_PROFILE(SMBwrite);
3075 return ERROR_NT(NT_STATUS_DISK_FULL);
3077 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3079 END_PROFILE(SMBwrite);
3080 return ERROR_NT(NT_STATUS_DISK_FULL);
3083 nwritten = write_file(fsp,data,startpos,numtowrite);
3085 status = sync_file(conn, fsp, False);
3086 if (!NT_STATUS_IS_OK(status)) {
3087 END_PROFILE(SMBwrite);
3088 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3089 fsp->fsp_name, nt_errstr(status) ));
3090 return ERROR_NT(status);
3093 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3094 END_PROFILE(SMBwrite);
3095 return(UNIXERROR(ERRHRD,ERRdiskfull));
3098 outsize = set_message(inbuf,outbuf,1,0,True);
3100 SSVAL(outbuf,smb_vwv0,nwritten);
3102 if (nwritten < (ssize_t)numtowrite) {
3103 SCVAL(outbuf,smb_rcls,ERRHRD);
3104 SSVAL(outbuf,smb_err,ERRdiskfull);
3107 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3109 END_PROFILE(SMBwrite);
3113 /****************************************************************************
3114 Reply to a write and X.
3115 ****************************************************************************/
3117 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3119 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3120 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3121 size_t numtowrite = SVAL(inbuf,smb_vwv10);
3122 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3123 ssize_t nwritten = -1;
3124 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3125 unsigned int smblen = smb_len(inbuf);
3127 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3129 START_PROFILE(SMBwriteX);
3131 /* If it's an IPC, pass off the pipe handler. */
3133 END_PROFILE(SMBwriteX);
3134 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3137 CHECK_FSP(fsp,conn);
3138 if (!CHECK_WRITE(fsp)) {
3139 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3142 set_message(inbuf,outbuf,6,0,True);
3144 /* Deal with possible LARGE_WRITEX */
3146 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3149 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3150 END_PROFILE(SMBwriteX);
3151 return ERROR_DOS(ERRDOS,ERRbadmem);
3154 data = smb_base(inbuf) + smb_doff;
3156 if(CVAL(inbuf,smb_wct) == 14) {
3157 #ifdef LARGE_SMB_OFF_T
3159 * This is a large offset (64 bit) write.
3161 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3163 #else /* !LARGE_SMB_OFF_T */
3166 * Ensure we haven't been sent a >32 bit offset.
3169 if(IVAL(inbuf,smb_vwv12) != 0) {
3170 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3171 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3172 END_PROFILE(SMBwriteX);
3173 return ERROR_DOS(ERRDOS,ERRbadaccess);
3176 #endif /* LARGE_SMB_OFF_T */
3179 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3180 END_PROFILE(SMBwriteX);
3181 return ERROR_DOS(ERRDOS,ERRlock);
3184 /* X/Open SMB protocol says that, unlike SMBwrite
3185 if the length is zero then NO truncation is
3186 done, just a write of zero. To truncate a file,
3189 if(numtowrite == 0) {
3193 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3194 fsp,data,startpos,numtowrite)) {
3195 END_PROFILE(SMBwriteX);
3199 nwritten = write_file(fsp,data,startpos,numtowrite);
3202 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3203 END_PROFILE(SMBwriteX);
3204 return(UNIXERROR(ERRHRD,ERRdiskfull));
3207 SSVAL(outbuf,smb_vwv2,nwritten);
3209 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3211 if (nwritten < (ssize_t)numtowrite) {
3212 SCVAL(outbuf,smb_rcls,ERRHRD);
3213 SSVAL(outbuf,smb_err,ERRdiskfull);
3216 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3217 fsp->fnum, (int)numtowrite, (int)nwritten));
3219 status = sync_file(conn, fsp, write_through);
3220 if (!NT_STATUS_IS_OK(status)) {
3221 END_PROFILE(SMBwriteX);
3222 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3223 fsp->fsp_name, nt_errstr(status) ));
3224 return ERROR_NT(status);
3227 END_PROFILE(SMBwriteX);
3228 return chain_reply(inbuf,outbuf,length,bufsize);
3231 /****************************************************************************
3233 ****************************************************************************/
3235 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3241 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3242 START_PROFILE(SMBlseek);
3244 CHECK_FSP(fsp,conn);
3246 flush_write_cache(fsp, SEEK_FLUSH);
3248 mode = SVAL(inbuf,smb_vwv1) & 3;
3249 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3250 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3259 res = fsp->fh->pos + startpos;
3270 if (umode == SEEK_END) {
3271 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3272 if(errno == EINVAL) {
3273 SMB_OFF_T current_pos = startpos;
3274 SMB_STRUCT_STAT sbuf;
3276 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3277 END_PROFILE(SMBlseek);
3278 return(UNIXERROR(ERRDOS,ERRnoaccess));
3281 current_pos += sbuf.st_size;
3283 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3288 END_PROFILE(SMBlseek);
3289 return(UNIXERROR(ERRDOS,ERRnoaccess));
3295 outsize = set_message(inbuf,outbuf,2,0,True);
3296 SIVAL(outbuf,smb_vwv0,res);
3298 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3299 fsp->fnum, (double)startpos, (double)res, mode));
3301 END_PROFILE(SMBlseek);
3305 /****************************************************************************
3307 ****************************************************************************/
3309 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3311 int outsize = set_message(inbuf,outbuf,0,0,False);
3312 uint16 fnum = SVAL(inbuf,smb_vwv0);
3313 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3314 START_PROFILE(SMBflush);
3317 CHECK_FSP(fsp,conn);
3320 file_sync_all(conn);
3322 NTSTATUS status = sync_file(conn, fsp, True);
3323 if (!NT_STATUS_IS_OK(status)) {
3324 END_PROFILE(SMBflush);
3325 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3326 fsp->fsp_name, nt_errstr(status) ));
3327 return ERROR_NT(status);
3331 DEBUG(3,("flush\n"));
3332 END_PROFILE(SMBflush);
3336 /****************************************************************************
3338 conn POINTER CAN BE NULL HERE !
3339 ****************************************************************************/
3341 int reply_exit(connection_struct *conn,
3342 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3345 START_PROFILE(SMBexit);
3347 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3349 outsize = set_message(inbuf,outbuf,0,0,False);
3351 DEBUG(3,("exit\n"));
3353 END_PROFILE(SMBexit);
3357 /****************************************************************************
3358 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3359 ****************************************************************************/
3361 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3364 NTSTATUS status = NT_STATUS_OK;
3366 files_struct *fsp = NULL;
3367 START_PROFILE(SMBclose);
3369 outsize = set_message(inbuf,outbuf,0,0,False);
3371 /* If it's an IPC, pass off to the pipe handler. */
3373 END_PROFILE(SMBclose);
3374 return reply_pipe_close(conn, inbuf,outbuf);
3377 fsp = file_fsp(inbuf,smb_vwv0);
3380 * We can only use CHECK_FSP if we know it's not a directory.
3383 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3384 END_PROFILE(SMBclose);
3385 return ERROR_DOS(ERRDOS,ERRbadfid);
3388 if(fsp->is_directory) {
3390 * Special case - close NT SMB directory handle.
3392 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3393 status = close_file(fsp,NORMAL_CLOSE);
3396 * Close ordinary file.
3399 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3400 fsp->fh->fd, fsp->fnum,
3401 conn->num_files_open));
3404 * Take care of any time sent in the close.
3407 fsp_set_pending_modtime(fsp,
3408 convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
3411 * close_file() returns the unix errno if an error
3412 * was detected on close - normally this is due to
3413 * a disk full error. If not then it was probably an I/O error.
3416 status = close_file(fsp,NORMAL_CLOSE);
3419 if(!NT_STATUS_IS_OK(status)) {
3420 END_PROFILE(SMBclose);
3421 return ERROR_NT(status);
3424 END_PROFILE(SMBclose);
3428 /****************************************************************************
3429 Reply to a writeclose (Core+ protocol).
3430 ****************************************************************************/
3432 int reply_writeclose(connection_struct *conn,
3433 char *inbuf,char *outbuf, int size, int dum_buffsize)
3436 ssize_t nwritten = -1;
3438 NTSTATUS close_status = NT_STATUS_OK;
3441 struct timespec mtime;
3442 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3443 START_PROFILE(SMBwriteclose);
3445 CHECK_FSP(fsp,conn);
3446 if (!CHECK_WRITE(fsp)) {
3447 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3450 numtowrite = SVAL(inbuf,smb_vwv1);
3451 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3452 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3453 data = smb_buf(inbuf) + 1;
3455 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3456 END_PROFILE(SMBwriteclose);
3457 return ERROR_DOS(ERRDOS,ERRlock);
3460 nwritten = write_file(fsp,data,startpos,numtowrite);
3462 set_filetime(conn, fsp->fsp_name, mtime);
3465 * More insanity. W2K only closes the file if writelen > 0.
3470 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3472 close_status = close_file(fsp,NORMAL_CLOSE);
3475 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3476 fsp->fnum, (int)numtowrite, (int)nwritten,
3477 conn->num_files_open));
3479 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3480 END_PROFILE(SMBwriteclose);
3481 return(UNIXERROR(ERRHRD,ERRdiskfull));
3484 if(!NT_STATUS_IS_OK(close_status)) {
3485 END_PROFILE(SMBwriteclose);
3486 return ERROR_NT(close_status);
3489 outsize = set_message(inbuf,outbuf,1,0,True);
3491 SSVAL(outbuf,smb_vwv0,nwritten);
3492 END_PROFILE(SMBwriteclose);
3497 #define DBGC_CLASS DBGC_LOCKING
3499 /****************************************************************************
3501 ****************************************************************************/
3503 int reply_lock(connection_struct *conn,
3504 char *inbuf,char *outbuf, int length, int dum_buffsize)
3506 int outsize = set_message(inbuf,outbuf,0,0,False);
3507 SMB_BIG_UINT count,offset;
3509 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3510 struct byte_range_lock *br_lck = NULL;
3512 START_PROFILE(SMBlock);
3514 CHECK_FSP(fsp,conn);
3516 release_level_2_oplocks_on_change(fsp);
3518 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3519 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3521 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3522 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3524 br_lck = do_lock(smbd_messaging_context(),
3526 (uint32)SVAL(inbuf,smb_pid),
3531 False, /* Non-blocking lock. */
3535 TALLOC_FREE(br_lck);
3537 if (NT_STATUS_V(status)) {
3538 END_PROFILE(SMBlock);
3539 return ERROR_NT(status);
3542 END_PROFILE(SMBlock);
3546 /****************************************************************************
3548 ****************************************************************************/
3550 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3553 int outsize = set_message(inbuf,outbuf,0,0,False);
3554 SMB_BIG_UINT count,offset;
3556 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3557 START_PROFILE(SMBunlock);
3559 CHECK_FSP(fsp,conn);
3561 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3562 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3564 status = do_unlock(smbd_messaging_context(),
3566 (uint32)SVAL(inbuf,smb_pid),
3571 if (NT_STATUS_V(status)) {
3572 END_PROFILE(SMBunlock);
3573 return ERROR_NT(status);
3576 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3577 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3579 END_PROFILE(SMBunlock);
3584 #define DBGC_CLASS DBGC_ALL
3586 /****************************************************************************
3588 conn POINTER CAN BE NULL HERE !
3589 ****************************************************************************/
3591 int reply_tdis(connection_struct *conn,
3592 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3594 int outsize = set_message(inbuf,outbuf,0,0,False);
3596 START_PROFILE(SMBtdis);
3598 vuid = SVAL(inbuf,smb_uid);
3601 DEBUG(4,("Invalid connection in tdis\n"));
3602 END_PROFILE(SMBtdis);
3603 return ERROR_DOS(ERRSRV,ERRinvnid);
3608 close_cnum(conn,vuid);
3610 END_PROFILE(SMBtdis);
3614 /****************************************************************************
3616 conn POINTER CAN BE NULL HERE !
3617 ****************************************************************************/
3619 int reply_echo(connection_struct *conn,
3620 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3622 int smb_reverb = SVAL(inbuf,smb_vwv0);
3624 unsigned int data_len = smb_buflen(inbuf);
3625 int outsize = set_message(inbuf,outbuf,1,data_len,True);
3626 START_PROFILE(SMBecho);
3628 if (data_len > BUFFER_SIZE) {
3629 DEBUG(0,("reply_echo: data_len too large.\n"));
3630 END_PROFILE(SMBecho);
3634 /* copy any incoming data back out */
3636 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3638 if (smb_reverb > 100) {
3639 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3643 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3644 SSVAL(outbuf,smb_vwv0,seq_num);
3646 smb_setlen(inbuf,outbuf,outsize - 4);
3649 if (!send_smb(smbd_server_fd(),outbuf))
3650 exit_server_cleanly("reply_echo: send_smb failed.");
3653 DEBUG(3,("echo %d times\n", smb_reverb));
3657 END_PROFILE(SMBecho);
3661 /****************************************************************************
3662 Reply to a printopen.
3663 ****************************************************************************/
3665 int reply_printopen(connection_struct *conn,
3666 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3672 START_PROFILE(SMBsplopen);
3674 if (!CAN_PRINT(conn)) {
3675 END_PROFILE(SMBsplopen);
3676 return ERROR_DOS(ERRDOS,ERRnoaccess);
3679 /* Open for exclusive use, write only. */
3680 status = print_fsp_open(conn, NULL, &fsp);
3682 if (!NT_STATUS_IS_OK(status)) {
3683 END_PROFILE(SMBsplopen);
3684 return(ERROR_NT(status));
3687 outsize = set_message(inbuf,outbuf,1,0,True);
3688 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3690 DEBUG(3,("openprint fd=%d fnum=%d\n",
3691 fsp->fh->fd, fsp->fnum));
3693 END_PROFILE(SMBsplopen);
3697 /****************************************************************************
3698 Reply to a printclose.
3699 ****************************************************************************/
3701 int reply_printclose(connection_struct *conn,
3702 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3704 int outsize = set_message(inbuf,outbuf,0,0,False);
3705 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3707 START_PROFILE(SMBsplclose);
3709 CHECK_FSP(fsp,conn);
3711 if (!CAN_PRINT(conn)) {
3712 END_PROFILE(SMBsplclose);
3713 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3716 DEBUG(3,("printclose fd=%d fnum=%d\n",
3717 fsp->fh->fd,fsp->fnum));
3719 status = close_file(fsp,NORMAL_CLOSE);
3721 if(!NT_STATUS_IS_OK(status)) {
3722 END_PROFILE(SMBsplclose);
3723 return ERROR_NT(status);
3726 END_PROFILE(SMBsplclose);
3730 /****************************************************************************
3731 Reply to a printqueue.
3732 ****************************************************************************/
3734 int reply_printqueue(connection_struct *conn,
3735 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3737 int outsize = set_message(inbuf,outbuf,2,3,True);
3738 int max_count = SVAL(inbuf,smb_vwv0);
3739 int start_index = SVAL(inbuf,smb_vwv1);
3740 START_PROFILE(SMBsplretq);
3742 /* we used to allow the client to get the cnum wrong, but that
3743 is really quite gross and only worked when there was only
3744 one printer - I think we should now only accept it if they
3745 get it right (tridge) */
3746 if (!CAN_PRINT(conn)) {
3747 END_PROFILE(SMBsplretq);
3748 return ERROR_DOS(ERRDOS,ERRnoaccess);
3751 SSVAL(outbuf,smb_vwv0,0);
3752 SSVAL(outbuf,smb_vwv1,0);
3753 SCVAL(smb_buf(outbuf),0,1);
3754 SSVAL(smb_buf(outbuf),1,0);
3756 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3757 start_index, max_count));
3760 print_queue_struct *queue = NULL;
3761 print_status_struct status;
3762 char *p = smb_buf(outbuf) + 3;
3763 int count = print_queue_status(SNUM(conn), &queue, &status);
3764 int num_to_get = ABS(max_count);
3765 int first = (max_count>0?start_index:start_index+max_count+1);
3771 num_to_get = MIN(num_to_get,count-first);
3774 for (i=first;i<first+num_to_get;i++) {
3775 srv_put_dos_date2(p,0,queue[i].time);
3776 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3777 SSVAL(p,5, queue[i].job);
3778 SIVAL(p,7,queue[i].size);
3780 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3785 outsize = set_message(inbuf,outbuf,2,28*count+3,False);
3786 SSVAL(outbuf,smb_vwv0,count);
3787 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3788 SCVAL(smb_buf(outbuf),0,1);
3789 SSVAL(smb_buf(outbuf),1,28*count);
3794 DEBUG(3,("%d entries returned in queue\n",count));
3797 END_PROFILE(SMBsplretq);
3801 /****************************************************************************
3802 Reply to a printwrite.
3803 ****************************************************************************/
3805 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3808 int outsize = set_message(inbuf,outbuf,0,0,False);
3810 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3812 START_PROFILE(SMBsplwr);
3814 if (!CAN_PRINT(conn)) {
3815 END_PROFILE(SMBsplwr);
3816 return ERROR_DOS(ERRDOS,ERRnoaccess);
3819 CHECK_FSP(fsp,conn);
3820 if (!CHECK_WRITE(fsp)) {
3821 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3824 numtowrite = SVAL(smb_buf(inbuf),1);
3825 data = smb_buf(inbuf) + 3;
3827 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3828 END_PROFILE(SMBsplwr);
3829 return(UNIXERROR(ERRHRD,ERRdiskfull));
3832 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3834 END_PROFILE(SMBsplwr);
3838 /****************************************************************************
3840 ****************************************************************************/
3842 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3847 SMB_STRUCT_STAT sbuf;
3849 START_PROFILE(SMBmkdir);
3851 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
3852 smb_buf(inbuf) + 1, sizeof(directory), 0,
3853 STR_TERMINATE, &status);
3854 if (!NT_STATUS_IS_OK(status)) {
3855 END_PROFILE(SMBmkdir);
3856 return ERROR_NT(status);
3859 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
3860 if (!NT_STATUS_IS_OK(status)) {
3861 END_PROFILE(SMBmkdir);
3862 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3863 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3865 return ERROR_NT(status);
3868 status = unix_convert(conn, directory, False, NULL, &sbuf);
3869 if (!NT_STATUS_IS_OK(status)) {
3870 END_PROFILE(SMBmkdir);
3871 return ERROR_NT(status);
3874 status = check_name(conn, directory);
3875 if (!NT_STATUS_IS_OK(status)) {
3876 END_PROFILE(SMBmkdir);
3877 return ERROR_NT(status);
3880 status = create_directory(conn, directory);
3882 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3884 if (!NT_STATUS_IS_OK(status)) {
3886 if (!use_nt_status()
3887 && NT_STATUS_EQUAL(status,
3888 NT_STATUS_OBJECT_NAME_COLLISION)) {
3890 * Yes, in the DOS error code case we get a
3891 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3892 * samba4 torture test.
3894 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3897 END_PROFILE(SMBmkdir);
3898 return ERROR_NT(status);
3901 outsize = set_message(inbuf,outbuf,0,0,False);
3903 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3905 END_PROFILE(SMBmkdir);
3909 /****************************************************************************
3910 Static function used by reply_rmdir to delete an entire directory
3911 tree recursively. Return True on ok, False on fail.
3912 ****************************************************************************/
3914 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3916 const char *dname = NULL;
3919 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3924 while((dname = ReadDirName(dir_hnd, &offset))) {
3928 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3931 if (!is_visible_file(conn, directory, dname, &st, False))
3934 /* Construct the full name. */
3935 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3941 pstrcpy(fullname, directory);
3942 pstrcat(fullname, "/");
3943 pstrcat(fullname, dname);
3945 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3950 if(st.st_mode & S_IFDIR) {
3951 if(!recursive_rmdir(conn, fullname)) {
3955 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3959 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3968 /****************************************************************************
3969 The internals of the rmdir code - called elsewhere.
3970 ****************************************************************************/
3972 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
3977 /* Might be a symlink. */
3978 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
3979 return map_nt_error_from_unix(errno);
3982 if (S_ISLNK(st.st_mode)) {
3983 /* Is what it points to a directory ? */
3984 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
3985 return map_nt_error_from_unix(errno);
3987 if (!(S_ISDIR(st.st_mode))) {
3988 return NT_STATUS_NOT_A_DIRECTORY;
3990 ret = SMB_VFS_UNLINK(conn,directory);
3992 ret = SMB_VFS_RMDIR(conn,directory);
3995 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3996 FILE_NOTIFY_CHANGE_DIR_NAME,
3998 return NT_STATUS_OK;
4001 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4003 * Check to see if the only thing in this directory are
4004 * vetoed files/directories. If so then delete them and
4005 * retry. If we fail to delete any of them (and we *don't*
4006 * do a recursive delete) then fail the rmdir.
4010 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4012 if(dir_hnd == NULL) {
4017 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4018 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4020 if (!is_visible_file(conn, directory, dname, &st, False))
4022 if(!IS_VETO_PATH(conn, dname)) {
4029 /* We only have veto files/directories. Recursive delete. */
4031 RewindDir(dir_hnd,&dirpos);
4032 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4035 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4037 if (!is_visible_file(conn, directory, dname, &st, False))
4040 /* Construct the full name. */
4041 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4046 pstrcpy(fullname, directory);
4047 pstrcat(fullname, "/");
4048 pstrcat(fullname, dname);
4050 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4052 if(st.st_mode & S_IFDIR) {
4053 if(lp_recursive_veto_delete(SNUM(conn))) {
4054 if(!recursive_rmdir(conn, fullname))
4057 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4059 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4063 /* Retry the rmdir */
4064 ret = SMB_VFS_RMDIR(conn,directory);
4070 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4071 "%s\n", directory,strerror(errno)));
4072 return map_nt_error_from_unix(errno);
4075 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4076 FILE_NOTIFY_CHANGE_DIR_NAME,
4079 return NT_STATUS_OK;
4082 /****************************************************************************
4084 ****************************************************************************/
4086 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4090 SMB_STRUCT_STAT sbuf;
4092 START_PROFILE(SMBrmdir);
4094 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
4095 smb_buf(inbuf) + 1, sizeof(directory), 0,
4096 STR_TERMINATE, &status);
4097 if (!NT_STATUS_IS_OK(status)) {
4098 END_PROFILE(SMBrmdir);
4099 return ERROR_NT(status);
4102 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
4103 if (!NT_STATUS_IS_OK(status)) {
4104 END_PROFILE(SMBrmdir);
4105 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4106 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4108 return ERROR_NT(status);
4111 status = unix_convert(conn, directory, False, NULL, &sbuf);
4112 if (!NT_STATUS_IS_OK(status)) {
4113 END_PROFILE(SMBrmdir);
4114 return ERROR_NT(status);
4117 status = check_name(conn, directory);
4118 if (!NT_STATUS_IS_OK(status)) {
4119 END_PROFILE(SMBrmdir);
4120 return ERROR_NT(status);
4123 dptr_closepath(directory,SVAL(inbuf,smb_pid));
4124 status = rmdir_internals(conn, directory);
4125 if (!NT_STATUS_IS_OK(status)) {
4126 END_PROFILE(SMBrmdir);
4127 return ERROR_NT(status);
4130 outsize = set_message(inbuf,outbuf,0,0,False);
4132 DEBUG( 3, ( "rmdir %s\n", directory ) );
4134 END_PROFILE(SMBrmdir);
4138 /*******************************************************************
4139 Resolve wildcards in a filename rename.
4140 Note that name is in UNIX charset and thus potentially can be more
4141 than fstring buffer (255 bytes) especially in default UTF-8 case.
4142 Therefore, we use pstring inside and all calls should ensure that
4143 name2 is at least pstring-long (they do already)
4144 ********************************************************************/
4146 static BOOL resolve_wildcards(const char *name1, char *name2)
4148 pstring root1,root2;
4150 char *p,*p2, *pname1, *pname2;
4151 int available_space, actual_space;
4153 pname1 = strrchr_m(name1,'/');
4154 pname2 = strrchr_m(name2,'/');
4156 if (!pname1 || !pname2)
4159 pstrcpy(root1,pname1);
4160 pstrcpy(root2,pname2);
4161 p = strrchr_m(root1,'.');
4168 p = strrchr_m(root2,'.');
4182 } else if (*p2 == '*') {
4198 } else if (*p2 == '*') {
4208 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4211 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4212 if (actual_space >= available_space - 1) {
4213 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4214 actual_space - available_space));
4217 pstrcpy_base(pname2, root2, name2);
4223 /****************************************************************************
4224 Ensure open files have their names updated. Updated to notify other smbd's
4226 ****************************************************************************/
4228 static void rename_open_files(connection_struct *conn,
4229 struct share_mode_lock *lck,
4230 const char *newname)
4233 BOOL did_rename = False;
4235 for(fsp = file_find_di_first(lck->id); fsp;
4236 fsp = file_find_di_next(fsp)) {
4237 /* fsp_name is a relative path under the fsp. To change this for other
4238 sharepaths we need to manipulate relative paths. */
4239 /* TODO - create the absolute path and manipulate the newname
4240 relative to the sharepath. */
4241 if (fsp->conn != conn) {
4244 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4245 fsp->fnum, file_id_static_string(&fsp->file_id),
4246 fsp->fsp_name, newname ));
4247 string_set(&fsp->fsp_name, newname);
4252 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4253 file_id_static_string(&lck->id), newname ));
4256 /* Send messages to all smbd's (not ourself) that the name has changed. */
4257 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4261 /****************************************************************************
4262 We need to check if the source path is a parent directory of the destination
4263 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4264 refuse the rename with a sharing violation. Under UNIX the above call can
4265 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4266 probably need to check that the client is a Windows one before disallowing
4267 this as a UNIX client (one with UNIX extensions) can know the source is a
4268 symlink and make this decision intelligently. Found by an excellent bug
4269 report from <AndyLiebman@aol.com>.
4270 ****************************************************************************/
4272 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4274 const char *psrc = src;
4275 const char *pdst = dest;
4278 if (psrc[0] == '.' && psrc[1] == '/') {
4281 if (pdst[0] == '.' && pdst[1] == '/') {
4284 if ((slen = strlen(psrc)) > strlen(pdst)) {
4287 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4291 * Do the notify calls from a rename
4294 static void notify_rename(connection_struct *conn, BOOL is_dir,
4295 const char *oldpath, const char *newpath)
4297 char *olddir, *newdir;
4298 const char *oldname, *newname;
4301 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4302 : FILE_NOTIFY_CHANGE_FILE_NAME;
4304 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4305 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4306 TALLOC_FREE(olddir);
4310 if (strcmp(olddir, newdir) == 0) {
4311 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4312 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4315 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4316 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4318 TALLOC_FREE(olddir);
4319 TALLOC_FREE(newdir);
4321 /* this is a strange one. w2k3 gives an additional event for
4322 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4323 files, but not directories */
4325 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4326 FILE_NOTIFY_CHANGE_ATTRIBUTES
4327 |FILE_NOTIFY_CHANGE_CREATION,
4332 /****************************************************************************
4333 Rename an open file - given an fsp.
4334 ****************************************************************************/
4336 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4338 SMB_STRUCT_STAT sbuf, sbuf1;
4339 pstring newname_last_component;
4340 NTSTATUS status = NT_STATUS_OK;
4341 struct share_mode_lock *lck = NULL;
4346 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4348 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4350 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4354 status = check_name(conn, newname);
4355 if (!NT_STATUS_IS_OK(status)) {
4359 /* Ensure newname contains a '/' */
4360 if(strrchr_m(newname,'/') == 0) {
4363 pstrcpy(tmpstr, "./");
4364 pstrcat(tmpstr, newname);
4365 pstrcpy(newname, tmpstr);
4369 * Check for special case with case preserving and not
4370 * case sensitive. If the old last component differs from the original
4371 * last component only by case, then we should allow
4372 * the rename (user is trying to change the case of the
4376 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4377 strequal(newname, fsp->fsp_name)) {
4379 pstring newname_modified_last_component;
4382 * Get the last component of the modified name.
4383 * Note that we guarantee that newname contains a '/'
4386 p = strrchr_m(newname,'/');
4387 pstrcpy(newname_modified_last_component,p+1);
4389 if(strcsequal(newname_modified_last_component,
4390 newname_last_component) == False) {
4392 * Replace the modified last component with
4395 pstrcpy(p+1, newname_last_component);
4400 * If the src and dest names are identical - including case,
4401 * don't do the rename, just return success.
4404 if (strcsequal(fsp->fsp_name, newname)) {
4405 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4407 return NT_STATUS_OK;
4411 * Have vfs_object_exist also fill sbuf1
4413 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4415 if(!replace_if_exists && dst_exists) {
4416 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4417 fsp->fsp_name,newname));
4418 return NT_STATUS_OBJECT_NAME_COLLISION;
4421 if (dst_exists && file_find_di_first(file_id_sbuf(&sbuf1)) != NULL) {
4422 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4423 return NT_STATUS_ACCESS_DENIED;
4426 /* Ensure we have a valid stat struct for the source. */
4427 if (fsp->fh->fd != -1) {
4428 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4429 return map_nt_error_from_unix(errno);
4432 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4433 return map_nt_error_from_unix(errno);
4437 status = can_rename(conn, fsp, attrs, &sbuf);
4439 if (!NT_STATUS_IS_OK(status)) {
4440 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4441 nt_errstr(status), fsp->fsp_name,newname));
4442 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4443 status = NT_STATUS_ACCESS_DENIED;
4447 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4448 return NT_STATUS_ACCESS_DENIED;
4451 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4454 * We have the file open ourselves, so not being able to get the
4455 * corresponding share mode lock is a fatal error.
4458 SMB_ASSERT(lck != NULL);
4460 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4461 uint32 create_options = fsp->fh->private_options;
4463 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4464 fsp->fsp_name,newname));
4466 rename_open_files(conn, lck, newname);
4468 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4471 * A rename acts as a new file create w.r.t. allowing an initial delete
4472 * on close, probably because in Windows there is a new handle to the
4473 * new file. If initial delete on close was requested but not
4474 * originally set, we need to set it here. This is probably not 100% correct,
4475 * but will work for the CIFSFS client which in non-posix mode
4476 * depends on these semantics. JRA.
4479 set_allow_initial_delete_on_close(lck, fsp, True);
4481 if (create_options & FILE_DELETE_ON_CLOSE) {
4482 status = can_set_delete_on_close(fsp, True, 0);
4484 if (NT_STATUS_IS_OK(status)) {
4485 /* Note that here we set the *inital* delete on close flag,
4486 * not the regular one. The magic gets handled in close. */
4487 fsp->initial_delete_on_close = True;
4491 return NT_STATUS_OK;
4496 if (errno == ENOTDIR || errno == EISDIR) {
4497 status = NT_STATUS_OBJECT_NAME_COLLISION;
4499 status = map_nt_error_from_unix(errno);
4502 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4503 nt_errstr(status), fsp->fsp_name,newname));
4508 /****************************************************************************
4509 The guts of the rename command, split out so it may be called by the NT SMB
4511 ****************************************************************************/
4513 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
4517 BOOL replace_if_exists,
4523 pstring last_component_src;
4524 pstring last_component_dest;
4527 NTSTATUS status = NT_STATUS_OK;
4528 SMB_STRUCT_STAT sbuf1, sbuf2;
4529 struct smb_Dir *dir_hnd = NULL;
4534 *directory = *mask = 0;
4539 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4540 if (!NT_STATUS_IS_OK(status)) {
4544 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4545 if (!NT_STATUS_IS_OK(status)) {
4550 * Split the old name into directory and last component
4551 * strings. Note that unix_convert may have stripped off a
4552 * leading ./ from both name and newname if the rename is
4553 * at the root of the share. We need to make sure either both
4554 * name and newname contain a / character or neither of them do
4555 * as this is checked in resolve_wildcards().
4558 p = strrchr_m(name,'/');
4560 pstrcpy(directory,".");
4564 pstrcpy(directory,name);
4566 *p = '/'; /* Replace needed for exceptional test below. */
4570 * We should only check the mangled cache
4571 * here if unix_convert failed. This means
4572 * that the path in 'mask' doesn't exist
4573 * on the file system and so we need to look
4574 * for a possible mangle. This patch from
4575 * Tine Smukavec <valentin.smukavec@hermes.si>.
4578 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4579 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4582 if (!src_has_wild) {
4586 * No wildcards - just process the one file.
4588 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4590 /* Add a terminating '/' to the directory name. */
4591 pstrcat(directory,"/");
4592 pstrcat(directory,mask);
4594 /* Ensure newname contains a '/' also */
4595 if(strrchr_m(newname,'/') == 0) {
4598 pstrcpy(tmpstr, "./");
4599 pstrcat(tmpstr, newname);
4600 pstrcpy(newname, tmpstr);
4603 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4604 "case_preserve = %d, short case preserve = %d, "
4605 "directory = %s, newname = %s, "
4606 "last_component_dest = %s, is_8_3 = %d\n",
4607 conn->case_sensitive, conn->case_preserve,
4608 conn->short_case_preserve, directory,
4609 newname, last_component_dest, is_short_name));
4611 /* The dest name still may have wildcards. */
4612 if (dest_has_wild) {
4613 if (!resolve_wildcards(directory,newname)) {
4614 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4615 directory,newname));
4616 return NT_STATUS_NO_MEMORY;
4621 SMB_VFS_STAT(conn, directory, &sbuf1);
4623 status = S_ISDIR(sbuf1.st_mode) ?
4624 open_directory(conn, req, directory, &sbuf1,
4626 FILE_SHARE_READ|FILE_SHARE_WRITE,
4627 FILE_OPEN, 0, 0, NULL,
4629 : open_file_ntcreate(conn, req, directory, &sbuf1,
4631 FILE_SHARE_READ|FILE_SHARE_WRITE,
4632 FILE_OPEN, 0, 0, 0, NULL,
4635 if (!NT_STATUS_IS_OK(status)) {
4636 DEBUG(3, ("Could not open rename source %s: %s\n",
4637 directory, nt_errstr(status)));
4641 status = rename_internals_fsp(conn, fsp, newname, attrs,
4644 close_file(fsp, NORMAL_CLOSE);
4646 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4647 nt_errstr(status), directory,newname));
4653 * Wildcards - process each file that matches.
4655 if (strequal(mask,"????????.???")) {
4659 status = check_name(conn, directory);
4660 if (!NT_STATUS_IS_OK(status)) {
4664 dir_hnd = OpenDir(conn, directory, mask, attrs);
4665 if (dir_hnd == NULL) {
4666 return map_nt_error_from_unix(errno);
4669 status = NT_STATUS_NO_SUCH_FILE;
4671 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4672 * - gentest fix. JRA
4675 while ((dname = ReadDirName(dir_hnd, &offset))) {
4678 BOOL sysdir_entry = False;
4680 pstrcpy(fname,dname);
4682 /* Quick check for "." and ".." */
4683 if (fname[0] == '.') {
4684 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4686 sysdir_entry = True;
4693 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4697 if(!mask_match(fname, mask, conn->case_sensitive)) {
4702 status = NT_STATUS_OBJECT_NAME_INVALID;
4706 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4708 pstrcpy(destname,newname);
4710 if (!resolve_wildcards(fname,destname)) {
4711 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4717 SMB_VFS_STAT(conn, fname, &sbuf1);
4719 status = S_ISDIR(sbuf1.st_mode) ?
4720 open_directory(conn, req, fname, &sbuf1,
4722 FILE_SHARE_READ|FILE_SHARE_WRITE,
4723 FILE_OPEN, 0, 0, NULL,
4725 : open_file_ntcreate(conn, req, fname, &sbuf1,
4727 FILE_SHARE_READ|FILE_SHARE_WRITE,
4728 FILE_OPEN, 0, 0, 0, NULL,
4731 if (!NT_STATUS_IS_OK(status)) {
4732 DEBUG(3,("rename_internals: open_file_ntcreate "
4733 "returned %s rename %s -> %s\n",
4734 nt_errstr(status), directory, newname));
4738 status = rename_internals_fsp(conn, fsp, destname, attrs,
4741 close_file(fsp, NORMAL_CLOSE);
4743 if (!NT_STATUS_IS_OK(status)) {
4744 DEBUG(3, ("rename_internals_fsp returned %s for "
4745 "rename %s -> %s\n", nt_errstr(status),
4746 directory, newname));
4752 DEBUG(3,("rename_internals: doing rename on %s -> "
4753 "%s\n",fname,destname));
4757 if (count == 0 && NT_STATUS_IS_OK(status)) {
4758 status = map_nt_error_from_unix(errno);
4764 /****************************************************************************
4766 ****************************************************************************/
4768 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4775 uint32 attrs = SVAL(inbuf,smb_vwv0);
4777 BOOL src_has_wcard = False;
4778 BOOL dest_has_wcard = False;
4779 struct smb_request req;
4781 START_PROFILE(SMBmv);
4783 init_smb_request(&req, (uint8 *)inbuf);
4785 p = smb_buf(inbuf) + 1;
4786 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
4787 sizeof(name), 0, STR_TERMINATE, &status,
4789 if (!NT_STATUS_IS_OK(status)) {
4791 return ERROR_NT(status);
4794 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
4795 sizeof(newname), 0, STR_TERMINATE, &status,
4797 if (!NT_STATUS_IS_OK(status)) {
4799 return ERROR_NT(status);
4802 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
4803 if (!NT_STATUS_IS_OK(status)) {
4805 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4806 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4808 return ERROR_NT(status);
4811 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4812 if (!NT_STATUS_IS_OK(status)) {
4814 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4815 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4817 return ERROR_NT(status);
4820 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4822 status = rename_internals(conn, &req, name, newname, attrs, False,
4823 src_has_wcard, dest_has_wcard);
4824 if (!NT_STATUS_IS_OK(status)) {
4826 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4827 /* We have re-scheduled this call. */
4830 return ERROR_NT(status);
4833 outsize = set_message(inbuf,outbuf,0,0,False);
4839 /*******************************************************************
4840 Copy a file as part of a reply_copy.
4841 ******************************************************************/
4844 * TODO: check error codes on all callers
4847 NTSTATUS copy_file(connection_struct *conn,
4852 BOOL target_is_directory)
4854 SMB_STRUCT_STAT src_sbuf, sbuf2;
4856 files_struct *fsp1,*fsp2;
4859 uint32 new_create_disposition;
4862 pstrcpy(dest,dest1);
4863 if (target_is_directory) {
4864 char *p = strrchr_m(src,'/');
4874 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4875 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4878 if (!target_is_directory && count) {
4879 new_create_disposition = FILE_OPEN;
4881 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4882 NULL, NULL, &new_create_disposition, NULL)) {
4883 return NT_STATUS_INVALID_PARAMETER;
4887 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
4889 FILE_SHARE_READ|FILE_SHARE_WRITE,
4892 FILE_ATTRIBUTE_NORMAL,
4896 if (!NT_STATUS_IS_OK(status)) {
4900 dosattrs = dos_mode(conn, src, &src_sbuf);
4901 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4902 ZERO_STRUCTP(&sbuf2);
4905 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
4907 FILE_SHARE_READ|FILE_SHARE_WRITE,
4908 new_create_disposition,
4914 if (!NT_STATUS_IS_OK(status)) {
4915 close_file(fsp1,ERROR_CLOSE);
4919 if ((ofun&3) == 1) {
4920 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4921 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4923 * Stop the copy from occurring.
4926 src_sbuf.st_size = 0;
4930 if (src_sbuf.st_size) {
4931 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4934 close_file(fsp1,NORMAL_CLOSE);
4936 /* Ensure the modtime is set correctly on the destination file. */
4937 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
4940 * As we are opening fsp1 read-only we only expect
4941 * an error on close on fsp2 if we are out of space.
4942 * Thus we don't look at the error return from the
4945 status = close_file(fsp2,NORMAL_CLOSE);
4947 if (!NT_STATUS_IS_OK(status)) {
4951 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4952 return NT_STATUS_DISK_FULL;
4955 return NT_STATUS_OK;
4958 /****************************************************************************
4959 Reply to a file copy.
4960 ****************************************************************************/
4962 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4967 pstring mask,newname;
4970 int error = ERRnoaccess;
4972 int tid2 = SVAL(inbuf,smb_vwv0);
4973 int ofun = SVAL(inbuf,smb_vwv1);
4974 int flags = SVAL(inbuf,smb_vwv2);
4975 BOOL target_is_directory=False;
4976 BOOL source_has_wild = False;
4977 BOOL dest_has_wild = False;
4978 SMB_STRUCT_STAT sbuf1, sbuf2;
4980 START_PROFILE(SMBcopy);
4982 *directory = *mask = 0;
4985 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
4986 sizeof(name), 0, STR_TERMINATE, &status,
4988 if (!NT_STATUS_IS_OK(status)) {
4989 END_PROFILE(SMBcopy);
4990 return ERROR_NT(status);
4992 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
4993 sizeof(newname), 0, STR_TERMINATE, &status,
4995 if (!NT_STATUS_IS_OK(status)) {
4996 END_PROFILE(SMBcopy);
4997 return ERROR_NT(status);
5000 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5002 if (tid2 != conn->cnum) {
5003 /* can't currently handle inter share copies XXXX */
5004 DEBUG(3,("Rejecting inter-share copy\n"));
5005 END_PROFILE(SMBcopy);
5006 return ERROR_DOS(ERRSRV,ERRinvdevice);
5009 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5010 if (!NT_STATUS_IS_OK(status)) {
5011 END_PROFILE(SMBcopy);
5012 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5013 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5015 return ERROR_NT(status);
5018 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5019 if (!NT_STATUS_IS_OK(status)) {
5020 END_PROFILE(SMBcopy);
5021 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5022 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5024 return ERROR_NT(status);
5027 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5028 if (!NT_STATUS_IS_OK(status)) {
5029 END_PROFILE(SMBcopy);
5030 return ERROR_NT(status);
5033 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5034 if (!NT_STATUS_IS_OK(status)) {
5035 END_PROFILE(SMBcopy);
5036 return ERROR_NT(status);
5039 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5041 if ((flags&1) && target_is_directory) {
5042 END_PROFILE(SMBcopy);
5043 return ERROR_DOS(ERRDOS,ERRbadfile);
5046 if ((flags&2) && !target_is_directory) {
5047 END_PROFILE(SMBcopy);
5048 return ERROR_DOS(ERRDOS,ERRbadpath);
5051 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5052 /* wants a tree copy! XXXX */
5053 DEBUG(3,("Rejecting tree copy\n"));
5054 END_PROFILE(SMBcopy);
5055 return ERROR_DOS(ERRSRV,ERRerror);
5058 p = strrchr_m(name,'/');
5060 pstrcpy(directory,"./");
5064 pstrcpy(directory,name);
5069 * We should only check the mangled cache
5070 * here if unix_convert failed. This means
5071 * that the path in 'mask' doesn't exist
5072 * on the file system and so we need to look
5073 * for a possible mangle. This patch from
5074 * Tine Smukavec <valentin.smukavec@hermes.si>.
5077 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5078 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5081 if (!source_has_wild) {
5082 pstrcat(directory,"/");
5083 pstrcat(directory,mask);
5084 if (dest_has_wild) {
5085 if (!resolve_wildcards(directory,newname)) {
5086 END_PROFILE(SMBcopy);
5087 return ERROR_NT(NT_STATUS_NO_MEMORY);
5091 status = check_name(conn, directory);
5092 if (!NT_STATUS_IS_OK(status)) {
5093 return ERROR_NT(status);
5096 status = check_name(conn, newname);
5097 if (!NT_STATUS_IS_OK(status)) {
5098 return ERROR_NT(status);
5101 status = copy_file(conn,directory,newname,ofun,
5102 count,target_is_directory);
5104 if(!NT_STATUS_IS_OK(status)) {
5105 END_PROFILE(SMBcopy);
5106 return ERROR_NT(status);
5111 struct smb_Dir *dir_hnd = NULL;
5116 if (strequal(mask,"????????.???"))
5119 status = check_name(conn, directory);
5120 if (!NT_STATUS_IS_OK(status)) {
5121 return ERROR_NT(status);
5124 dir_hnd = OpenDir(conn, directory, mask, 0);
5125 if (dir_hnd == NULL) {
5126 status = map_nt_error_from_unix(errno);
5127 return ERROR_NT(status);
5132 while ((dname = ReadDirName(dir_hnd, &offset))) {
5134 pstrcpy(fname,dname);
5136 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5140 if(!mask_match(fname, mask, conn->case_sensitive)) {
5144 error = ERRnoaccess;
5145 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5146 pstrcpy(destname,newname);
5147 if (!resolve_wildcards(fname,destname)) {
5151 status = check_name(conn, fname);
5152 if (!NT_STATUS_IS_OK(status)) {
5153 return ERROR_NT(status);
5156 status = check_name(conn, destname);
5157 if (!NT_STATUS_IS_OK(status)) {
5158 return ERROR_NT(status);
5161 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5163 status = copy_file(conn,fname,destname,ofun,
5164 count,target_is_directory);
5165 if (NT_STATUS_IS_OK(status)) {
5174 /* Error on close... */
5176 END_PROFILE(SMBcopy);
5177 return(UNIXERROR(ERRHRD,ERRgeneral));
5180 END_PROFILE(SMBcopy);
5181 return ERROR_DOS(ERRDOS,error);
5184 outsize = set_message(inbuf,outbuf,1,0,True);
5185 SSVAL(outbuf,smb_vwv0,count);
5187 END_PROFILE(SMBcopy);
5191 /****************************************************************************
5193 ****************************************************************************/
5195 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5202 START_PROFILE(pathworks_setdir);
5205 if (!CAN_SETDIR(snum)) {
5206 END_PROFILE(pathworks_setdir);
5207 return ERROR_DOS(ERRDOS,ERRnoaccess);
5210 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
5211 smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
5213 if (!NT_STATUS_IS_OK(status)) {
5214 END_PROFILE(pathworks_setdir);
5215 return ERROR_NT(status);
5218 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5219 if (!NT_STATUS_IS_OK(status)) {
5220 END_PROFILE(pathworks_setdir);
5221 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5222 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5224 return ERROR_NT(status);
5227 if (strlen(newdir) != 0) {
5228 if (!vfs_directory_exist(conn,newdir,NULL)) {
5229 END_PROFILE(pathworks_setdir);
5230 return ERROR_DOS(ERRDOS,ERRbadpath);
5232 set_conn_connectpath(conn,newdir);
5235 outsize = set_message(inbuf,outbuf,0,0,False);
5236 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5238 DEBUG(3,("setdir %s\n", newdir));
5240 END_PROFILE(pathworks_setdir);
5245 #define DBGC_CLASS DBGC_LOCKING
5247 /****************************************************************************
5248 Get a lock pid, dealing with large count requests.
5249 ****************************************************************************/
5251 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5253 if(!large_file_format)
5254 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5256 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5259 /****************************************************************************
5260 Get a lock count, dealing with large count requests.
5261 ****************************************************************************/
5263 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5265 SMB_BIG_UINT count = 0;
5267 if(!large_file_format) {
5268 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5271 #if defined(HAVE_LONGLONG)
5272 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5273 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5274 #else /* HAVE_LONGLONG */
5277 * NT4.x seems to be broken in that it sends large file (64 bit)
5278 * lockingX calls even if the CAP_LARGE_FILES was *not*
5279 * negotiated. For boxes without large unsigned ints truncate the
5280 * lock count by dropping the top 32 bits.
5283 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5284 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5285 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5286 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5287 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5290 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5291 #endif /* HAVE_LONGLONG */
5297 #if !defined(HAVE_LONGLONG)
5298 /****************************************************************************
5299 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5300 ****************************************************************************/
5302 static uint32 map_lock_offset(uint32 high, uint32 low)
5306 uint32 highcopy = high;
5309 * Try and find out how many significant bits there are in high.
5312 for(i = 0; highcopy; i++)
5316 * We use 31 bits not 32 here as POSIX
5317 * lock offsets may not be negative.
5320 mask = (~0) << (31 - i);
5323 return 0; /* Fail. */
5329 #endif /* !defined(HAVE_LONGLONG) */
5331 /****************************************************************************
5332 Get a lock offset, dealing with large offset requests.
5333 ****************************************************************************/
5335 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5337 SMB_BIG_UINT offset = 0;
5341 if(!large_file_format) {
5342 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5345 #if defined(HAVE_LONGLONG)
5346 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5347 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5348 #else /* HAVE_LONGLONG */
5351 * NT4.x seems to be broken in that it sends large file (64 bit)
5352 * lockingX calls even if the CAP_LARGE_FILES was *not*
5353 * negotiated. For boxes without large unsigned ints mangle the
5354 * lock offset by mapping the top 32 bits onto the lower 32.
5357 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5358 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5359 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5362 if((new_low = map_lock_offset(high, low)) == 0) {
5364 return (SMB_BIG_UINT)-1;
5367 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5368 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5369 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5370 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5373 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5374 #endif /* HAVE_LONGLONG */
5380 /****************************************************************************
5381 Reply to a lockingX request.
5382 ****************************************************************************/
5384 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5385 int length, int bufsize)
5387 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5388 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5389 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5390 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5391 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5392 SMB_BIG_UINT count = 0, offset = 0;
5394 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5397 BOOL large_file_format =
5398 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5400 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5402 START_PROFILE(SMBlockingX);
5404 CHECK_FSP(fsp,conn);
5406 data = smb_buf(inbuf);
5408 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5409 /* we don't support these - and CANCEL_LOCK makes w2k
5410 and XP reboot so I don't really want to be
5411 compatible! (tridge) */
5412 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5415 /* Check if this is an oplock break on a file
5416 we have granted an oplock on.
5418 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5419 /* Client can insist on breaking to none. */
5420 BOOL break_to_none = (oplocklevel == 0);
5423 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5424 "for fnum = %d\n", (unsigned int)oplocklevel,
5428 * Make sure we have granted an exclusive or batch oplock on
5432 if (fsp->oplock_type == 0) {
5434 /* The Samba4 nbench simulator doesn't understand
5435 the difference between break to level2 and break
5436 to none from level2 - it sends oplock break
5437 replies in both cases. Don't keep logging an error
5438 message here - just ignore it. JRA. */
5440 DEBUG(5,("reply_lockingX: Error : oplock break from "
5441 "client for fnum = %d (oplock=%d) and no "
5442 "oplock granted on this file (%s).\n",
5443 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5445 /* if this is a pure oplock break request then don't
5447 if (num_locks == 0 && num_ulocks == 0) {
5448 END_PROFILE(SMBlockingX);
5451 END_PROFILE(SMBlockingX);
5452 return ERROR_DOS(ERRDOS,ERRlock);
5456 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5458 result = remove_oplock(fsp);
5460 result = downgrade_oplock(fsp);
5464 DEBUG(0, ("reply_lockingX: error in removing "
5465 "oplock on file %s\n", fsp->fsp_name));
5466 /* Hmmm. Is this panic justified? */
5467 smb_panic("internal tdb error");
5470 reply_to_oplock_break_requests(fsp);
5472 /* if this is a pure oplock break request then don't send a
5474 if (num_locks == 0 && num_ulocks == 0) {
5475 /* Sanity check - ensure a pure oplock break is not a
5477 if(CVAL(inbuf,smb_vwv0) != 0xff)
5478 DEBUG(0,("reply_lockingX: Error : pure oplock "
5479 "break is a chained %d request !\n",
5480 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5481 END_PROFILE(SMBlockingX);
5487 * We do this check *after* we have checked this is not a oplock break
5488 * response message. JRA.
5491 release_level_2_oplocks_on_change(fsp);
5493 /* Data now points at the beginning of the list
5494 of smb_unlkrng structs */
5495 for(i = 0; i < (int)num_ulocks; i++) {
5496 lock_pid = get_lock_pid( data, i, large_file_format);
5497 count = get_lock_count( data, i, large_file_format);
5498 offset = get_lock_offset( data, i, large_file_format, &err);
5501 * There is no error code marked "stupid client bug".... :-).
5504 END_PROFILE(SMBlockingX);
5505 return ERROR_DOS(ERRDOS,ERRnoaccess);
5508 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5509 "pid %u, file %s\n", (double)offset, (double)count,
5510 (unsigned int)lock_pid, fsp->fsp_name ));
5512 status = do_unlock(smbd_messaging_context(),
5519 if (NT_STATUS_V(status)) {
5520 END_PROFILE(SMBlockingX);
5521 return ERROR_NT(status);
5525 /* Setup the timeout in seconds. */
5527 if (!lp_blocking_locks(SNUM(conn))) {
5531 /* Now do any requested locks */
5532 data += ((large_file_format ? 20 : 10)*num_ulocks);
5534 /* Data now points at the beginning of the list
5535 of smb_lkrng structs */
5537 for(i = 0; i < (int)num_locks; i++) {
5538 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5539 READ_LOCK:WRITE_LOCK);
5540 lock_pid = get_lock_pid( data, i, large_file_format);
5541 count = get_lock_count( data, i, large_file_format);
5542 offset = get_lock_offset( data, i, large_file_format, &err);
5545 * There is no error code marked "stupid client bug".... :-).
5548 END_PROFILE(SMBlockingX);
5549 return ERROR_DOS(ERRDOS,ERRnoaccess);
5552 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5553 "%u, file %s timeout = %d\n", (double)offset,
5554 (double)count, (unsigned int)lock_pid,
5555 fsp->fsp_name, (int)lock_timeout ));
5557 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5558 if (lp_blocking_locks(SNUM(conn))) {
5560 /* Schedule a message to ourselves to
5561 remove the blocking lock record and
5562 return the right error. */
5564 if (!blocking_lock_cancel(fsp,
5570 NT_STATUS_FILE_LOCK_CONFLICT)) {
5571 END_PROFILE(SMBlockingX);
5572 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5575 /* Remove a matching pending lock. */
5576 status = do_lock_cancel(fsp,
5582 BOOL blocking_lock = lock_timeout ? True : False;
5583 BOOL defer_lock = False;
5584 struct byte_range_lock *br_lck;
5585 uint32 block_smbpid;
5587 br_lck = do_lock(smbd_messaging_context(),
5598 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5599 /* Windows internal resolution for blocking locks seems
5600 to be about 200ms... Don't wait for less than that. JRA. */
5601 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5602 lock_timeout = lp_lock_spin_time();
5607 /* This heuristic seems to match W2K3 very well. If a
5608 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5609 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5610 far as I can tell. Replacement for do_lock_spin(). JRA. */
5612 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5613 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5615 lock_timeout = lp_lock_spin_time();
5618 if (br_lck && defer_lock) {
5620 * A blocking lock was requested. Package up
5621 * this smb into a queued request and push it
5622 * onto the blocking lock queue.
5624 if(push_blocking_lock_request(br_lck,
5635 TALLOC_FREE(br_lck);
5636 END_PROFILE(SMBlockingX);
5641 TALLOC_FREE(br_lck);
5644 if (NT_STATUS_V(status)) {
5645 END_PROFILE(SMBlockingX);
5646 return ERROR_NT(status);
5650 /* If any of the above locks failed, then we must unlock
5651 all of the previous locks (X/Open spec). */
5653 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5657 * Ensure we don't do a remove on the lock that just failed,
5658 * as under POSIX rules, if we have a lock already there, we
5659 * will delete it (and we shouldn't) .....
5661 for(i--; i >= 0; i--) {
5662 lock_pid = get_lock_pid( data, i, large_file_format);
5663 count = get_lock_count( data, i, large_file_format);
5664 offset = get_lock_offset( data, i, large_file_format,
5668 * There is no error code marked "stupid client
5672 END_PROFILE(SMBlockingX);
5673 return ERROR_DOS(ERRDOS,ERRnoaccess);
5676 do_unlock(smbd_messaging_context(),
5683 END_PROFILE(SMBlockingX);
5684 return ERROR_NT(status);
5687 set_message(inbuf,outbuf,2,0,True);
5689 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5690 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5692 END_PROFILE(SMBlockingX);
5693 return chain_reply(inbuf,outbuf,length,bufsize);
5697 #define DBGC_CLASS DBGC_ALL
5699 /****************************************************************************
5700 Reply to a SMBreadbmpx (read block multiplex) request.
5701 ****************************************************************************/
5703 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5714 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5715 START_PROFILE(SMBreadBmpx);
5717 /* this function doesn't seem to work - disable by default */
5718 if (!lp_readbmpx()) {
5719 END_PROFILE(SMBreadBmpx);
5720 return ERROR_DOS(ERRSRV,ERRuseSTD);
5723 outsize = set_message(inbuf,outbuf,8,0,True);
5725 CHECK_FSP(fsp,conn);
5726 if (!CHECK_READ(fsp,inbuf)) {
5727 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5730 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5731 maxcount = SVAL(inbuf,smb_vwv3);
5733 data = smb_buf(outbuf);
5734 pad = ((long)data)%4;
5739 max_per_packet = bufsize-(outsize+pad);
5743 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5744 END_PROFILE(SMBreadBmpx);
5745 return ERROR_DOS(ERRDOS,ERRlock);
5749 size_t N = MIN(max_per_packet,tcount-total_read);
5751 nread = read_file(fsp,data,startpos,N);
5756 if (nread < (ssize_t)N)
5757 tcount = total_read + nread;
5759 set_message(inbuf,outbuf,8,nread+pad,False);
5760 SIVAL(outbuf,smb_vwv0,startpos);
5761 SSVAL(outbuf,smb_vwv2,tcount);
5762 SSVAL(outbuf,smb_vwv6,nread);
5763 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5766 if (!send_smb(smbd_server_fd(),outbuf))
5767 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5769 total_read += nread;
5771 } while (total_read < (ssize_t)tcount);
5773 END_PROFILE(SMBreadBmpx);
5777 /****************************************************************************
5778 Reply to a SMBsetattrE.
5779 ****************************************************************************/
5781 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5783 struct timespec ts[2];
5785 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5786 START_PROFILE(SMBsetattrE);
5788 outsize = set_message(inbuf,outbuf,0,0,False);
5790 if(!fsp || (fsp->conn != conn)) {
5791 END_PROFILE(SMBsetattrE);
5792 return ERROR_DOS(ERRDOS,ERRbadfid);
5796 * Convert the DOS times into unix times. Ignore create
5797 * time as UNIX can't set this.
5800 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5801 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5804 * Patch from Ray Frush <frush@engr.colostate.edu>
5805 * Sometimes times are sent as zero - ignore them.
5808 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5809 /* Ignore request */
5810 if( DEBUGLVL( 3 ) ) {
5811 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5812 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5814 END_PROFILE(SMBsetattrE);
5816 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5817 /* set modify time = to access time if modify time was unset */
5821 /* Set the date on this file */
5822 /* Should we set pending modtime here ? JRA */
5823 if(file_ntimes(conn, fsp->fsp_name, ts)) {
5824 END_PROFILE(SMBsetattrE);
5825 return ERROR_DOS(ERRDOS,ERRnoaccess);
5828 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5830 (unsigned int)ts[0].tv_sec,
5831 (unsigned int)ts[1].tv_sec));
5833 END_PROFILE(SMBsetattrE);
5838 /* Back from the dead for OS/2..... JRA. */
5840 /****************************************************************************
5841 Reply to a SMBwritebmpx (write block multiplex primary) request.
5842 ****************************************************************************/
5844 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5847 ssize_t nwritten = -1;
5854 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5856 START_PROFILE(SMBwriteBmpx);
5858 CHECK_FSP(fsp,conn);
5859 if (!CHECK_WRITE(fsp)) {
5860 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5862 if (HAS_CACHED_ERROR(fsp)) {
5863 return(CACHED_ERROR(fsp));
5866 tcount = SVAL(inbuf,smb_vwv1);
5867 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5868 write_through = BITSETW(inbuf+smb_vwv7,0);
5869 numtowrite = SVAL(inbuf,smb_vwv10);
5870 smb_doff = SVAL(inbuf,smb_vwv11);
5872 data = smb_base(inbuf) + smb_doff;
5874 /* If this fails we need to send an SMBwriteC response,
5875 not an SMBwritebmpx - set this up now so we don't forget */
5876 SCVAL(outbuf,smb_com,SMBwritec);
5878 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5879 END_PROFILE(SMBwriteBmpx);
5880 return(ERROR_DOS(ERRDOS,ERRlock));
5883 nwritten = write_file(fsp,data,startpos,numtowrite);
5885 status = sync_file(conn, fsp, write_through);
5886 if (!NT_STATUS_IS_OK(status)) {
5887 END_PROFILE(SMBwriteBmpx);
5888 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
5889 fsp->fsp_name, nt_errstr(status) ));
5890 return ERROR_NT(status);
5893 if(nwritten < (ssize_t)numtowrite) {
5894 END_PROFILE(SMBwriteBmpx);
5895 return(UNIXERROR(ERRHRD,ERRdiskfull));
5898 /* If the maximum to be written to this file
5899 is greater than what we just wrote then set
5900 up a secondary struct to be attached to this
5901 fd, we will use this to cache error messages etc. */
5903 if((ssize_t)tcount > nwritten) {
5904 write_bmpx_struct *wbms;
5905 if(fsp->wbmpx_ptr != NULL)
5906 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5908 wbms = SMB_MALLOC_P(write_bmpx_struct);
5910 DEBUG(0,("Out of memory in reply_readmpx\n"));
5911 END_PROFILE(SMBwriteBmpx);
5912 return(ERROR_DOS(ERRSRV,ERRnoresource));
5914 wbms->wr_mode = write_through;
5915 wbms->wr_discard = False; /* No errors yet */
5916 wbms->wr_total_written = nwritten;
5917 wbms->wr_errclass = 0;
5919 fsp->wbmpx_ptr = wbms;
5922 /* We are returning successfully, set the message type back to
5924 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5926 outsize = set_message(inbuf,outbuf,1,0,True);
5928 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5930 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5931 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5933 if (write_through && tcount==nwritten) {
5934 /* We need to send both a primary and a secondary response */
5935 smb_setlen(inbuf,outbuf,outsize - 4);
5937 if (!send_smb(smbd_server_fd(),outbuf))
5938 exit_server_cleanly("reply_writebmpx: send_smb failed.");
5940 /* Now the secondary */
5941 outsize = set_message(inbuf,outbuf,1,0,True);
5942 SCVAL(outbuf,smb_com,SMBwritec);
5943 SSVAL(outbuf,smb_vwv0,nwritten);
5946 END_PROFILE(SMBwriteBmpx);
5950 /****************************************************************************
5951 Reply to a SMBwritebs (write block multiplex secondary) request.
5952 ****************************************************************************/
5954 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5957 ssize_t nwritten = -1;
5964 write_bmpx_struct *wbms;
5965 BOOL send_response = False;
5966 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5968 START_PROFILE(SMBwriteBs);
5970 CHECK_FSP(fsp,conn);
5971 if (!CHECK_WRITE(fsp)) {
5972 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5975 tcount = SVAL(inbuf,smb_vwv1);
5976 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5977 numtowrite = SVAL(inbuf,smb_vwv6);
5978 smb_doff = SVAL(inbuf,smb_vwv7);
5980 data = smb_base(inbuf) + smb_doff;
5982 /* We need to send an SMBwriteC response, not an SMBwritebs */
5983 SCVAL(outbuf,smb_com,SMBwritec);
5985 /* This fd should have an auxiliary struct attached,
5986 check that it does */
5987 wbms = fsp->wbmpx_ptr;
5989 END_PROFILE(SMBwriteBs);
5993 /* If write through is set we can return errors, else we must cache them */
5994 write_through = wbms->wr_mode;
5996 /* Check for an earlier error */
5997 if(wbms->wr_discard) {
5998 END_PROFILE(SMBwriteBs);
5999 return -1; /* Just discard the packet */
6002 nwritten = write_file(fsp,data,startpos,numtowrite);
6004 status = sync_file(conn, fsp, write_through);
6006 if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6008 /* We are returning an error - we can delete the aux struct */
6011 fsp->wbmpx_ptr = NULL;
6012 END_PROFILE(SMBwriteBs);
6013 return(ERROR_DOS(ERRHRD,ERRdiskfull));
6015 wbms->wr_errclass = ERRHRD;
6016 wbms->wr_error = ERRdiskfull;
6017 wbms->wr_status = NT_STATUS_DISK_FULL;
6018 wbms->wr_discard = True;
6019 END_PROFILE(SMBwriteBs);
6023 /* Increment the total written, if this matches tcount
6024 we can discard the auxiliary struct (hurrah !) and return a writeC */
6025 wbms->wr_total_written += nwritten;
6026 if(wbms->wr_total_written >= tcount) {
6027 if (write_through) {
6028 outsize = set_message(inbuf,outbuf,1,0,True);
6029 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
6030 send_response = True;
6034 fsp->wbmpx_ptr = NULL;
6038 END_PROFILE(SMBwriteBs);
6042 END_PROFILE(SMBwriteBs);
6046 /****************************************************************************
6047 Reply to a SMBgetattrE.
6048 ****************************************************************************/
6050 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6052 SMB_STRUCT_STAT sbuf;
6055 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
6056 START_PROFILE(SMBgetattrE);
6058 outsize = set_message(inbuf,outbuf,11,0,True);
6060 if(!fsp || (fsp->conn != conn)) {
6061 END_PROFILE(SMBgetattrE);
6062 return ERROR_DOS(ERRDOS,ERRbadfid);
6065 /* Do an fstat on this file */
6066 if(fsp_stat(fsp, &sbuf)) {
6067 END_PROFILE(SMBgetattrE);
6068 return(UNIXERROR(ERRDOS,ERRnoaccess));
6071 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6074 * Convert the times into dos times. Set create
6075 * date to be last modify date as UNIX doesn't save
6079 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6080 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6081 /* Should we check pending modtime here ? JRA */
6082 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6085 SIVAL(outbuf,smb_vwv6,0);
6086 SIVAL(outbuf,smb_vwv8,0);
6088 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6089 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6090 SIVAL(outbuf,smb_vwv8,allocation_size);
6092 SSVAL(outbuf,smb_vwv10, mode);
6094 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6096 END_PROFILE(SMBgetattrE);