[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / smbd / reply.c
blob55f62a26f7c317802170053b0964b4addfd2e395
1 /*
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 2 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
27 #include "includes.h"
29 /* look in server.c for some explanation of these variables */
30 extern enum protocol_types Protocol;
31 extern int max_send;
32 extern int max_recv;
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
44 set.
45 ****************************************************************************/
47 /* Custom version for processing POSIX paths. */
48 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
50 NTSTATUS check_path_syntax_internal(pstring destname,
51 const pstring srcname,
52 BOOL posix_path,
53 BOOL *p_last_component_contains_wcard)
55 char *d = destname;
56 const char *s = srcname;
57 NTSTATUS ret = NT_STATUS_OK;
58 BOOL start_of_name_component = True;
60 *p_last_component_contains_wcard = False;
62 while (*s) {
63 if (IS_PATH_SEP(*s,posix_path)) {
65 * Safe to assume is not the second part of a mb char as this is handled below.
67 /* Eat multiple '/' or '\\' */
68 while (IS_PATH_SEP(*s,posix_path)) {
69 s++;
71 if ((d != destname) && (*s != '\0')) {
72 /* We only care about non-leading or trailing '/' or '\\' */
73 *d++ = '/';
76 start_of_name_component = True;
77 /* New component. */
78 *p_last_component_contains_wcard = False;
79 continue;
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 > destname) && (*(d-1) == '/')) {
92 *(d-1) = '\0';
93 d--;
96 /* Are we at the start ? Can't go back further if so. */
97 if (d <= destname) {
98 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
99 break;
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 > destname; d--) {
106 if (*d == '/')
107 break;
109 s += 2; /* Else go past the .. */
110 /* We're still at the start of a name component, just the previous one. */
111 continue;
113 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
114 if (posix_path) {
115 /* Eat the '.' */
116 s++;
117 continue;
123 if (!(*s & 0x80)) {
124 if (!posix_path) {
125 if (*s <= 0x1f) {
126 return NT_STATUS_OBJECT_NAME_INVALID;
128 switch (*s) {
129 case '*':
130 case '?':
131 case '<':
132 case '>':
133 case '"':
134 *p_last_component_contains_wcard = True;
135 break;
136 default:
137 break;
140 *d++ = *s++;
141 } else {
142 size_t siz;
143 /* Get the size of the next MB character. */
144 next_codepoint(s,&siz);
145 switch(siz) {
146 case 5:
147 *d++ = *s++;
148 /*fall through*/
149 case 4:
150 *d++ = *s++;
151 /*fall through*/
152 case 3:
153 *d++ = *s++;
154 /*fall through*/
155 case 2:
156 *d++ = *s++;
157 /*fall through*/
158 case 1:
159 *d++ = *s++;
160 break;
161 default:
162 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
163 *d = '\0';
164 return NT_STATUS_INVALID_PARAMETER;
167 start_of_name_component = False;
170 *d = '\0';
171 return ret;
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(pstring destname, const pstring srcname)
181 BOOL ignore;
182 return check_path_syntax_internal(destname, srcname, 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
188 a wildcard.
189 ****************************************************************************/
191 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
193 return check_path_syntax_internal(destname, srcname, 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(pstring destname, const pstring srcname)
204 BOOL ignore;
205 return check_path_syntax_internal(destname, srcname, 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, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
213 NTSTATUS *err, BOOL *contains_wcard)
215 pstring tmppath;
216 char *tmppath_ptr = tmppath;
217 size_t ret;
218 #ifdef DEVELOPER
219 SMB_ASSERT(dest_len == sizeof(pstring));
220 #endif
222 if (src_len == 0) {
223 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
224 } else {
225 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
228 *contains_wcard = False;
230 if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
232 * For a DFS path the function parse_dfs_path()
233 * will do the path processing, just make a copy.
235 pstrcpy(dest, tmppath);
236 *err = NT_STATUS_OK;
237 return ret;
240 if (lp_posix_pathnames()) {
241 *err = check_path_syntax_posix(dest, tmppath);
242 } else {
243 *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
246 return ret;
249 /****************************************************************************
250 Pull a string and check the path - provide for error return.
251 ****************************************************************************/
253 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
255 pstring tmppath;
256 char *tmppath_ptr = tmppath;
257 size_t ret;
258 #ifdef DEVELOPER
259 SMB_ASSERT(dest_len == sizeof(pstring));
260 #endif
262 if (src_len == 0) {
263 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
264 } else {
265 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
268 if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
270 * For a DFS path the function parse_dfs_path()
271 * will do the path processing, just make a copy.
273 pstrcpy(dest, tmppath);
274 *err = NT_STATUS_OK;
275 return ret;
278 if (lp_posix_pathnames()) {
279 *err = check_path_syntax_posix(dest, tmppath);
280 } else {
281 *err = check_path_syntax(dest, tmppath);
284 return ret;
287 /****************************************************************************
288 Reply to a special message.
289 ****************************************************************************/
291 int reply_special(char *inbuf,char *outbuf)
293 int outsize = 4;
294 int msg_type = CVAL(inbuf,0);
295 int msg_flags = CVAL(inbuf,1);
296 fstring name1,name2;
297 char name_type = 0;
299 static BOOL already_got_session = False;
301 *name1 = *name2 = 0;
303 memset(outbuf,'\0',smb_size);
305 smb_setlen(outbuf,0);
307 switch (msg_type) {
308 case 0x81: /* session request */
310 if (already_got_session) {
311 exit_server_cleanly("multiple session request not permitted");
314 SCVAL(outbuf,0,0x82);
315 SCVAL(outbuf,3,0);
316 if (name_len(inbuf+4) > 50 ||
317 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
318 DEBUG(0,("Invalid name length in session request\n"));
319 return(0);
321 name_extract(inbuf,4,name1);
322 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
323 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
324 name1,name2));
326 set_local_machine_name(name1, True);
327 set_remote_machine_name(name2, True);
329 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
330 get_local_machine_name(), get_remote_machine_name(),
331 name_type));
333 if (name_type == 'R') {
334 /* We are being asked for a pathworks session ---
335 no thanks! */
336 SCVAL(outbuf, 0,0x83);
337 break;
340 /* only add the client's machine name to the list
341 of possibly valid usernames if we are operating
342 in share mode security */
343 if (lp_security() == SEC_SHARE) {
344 add_session_user(get_remote_machine_name());
347 reload_services(True);
348 reopen_logs();
350 already_got_session = True;
351 break;
353 case 0x89: /* session keepalive request
354 (some old clients produce this?) */
355 SCVAL(outbuf,0,SMBkeepalive);
356 SCVAL(outbuf,3,0);
357 break;
359 case 0x82: /* positive session response */
360 case 0x83: /* negative session response */
361 case 0x84: /* retarget session response */
362 DEBUG(0,("Unexpected session response\n"));
363 break;
365 case SMBkeepalive: /* session keepalive */
366 default:
367 return(0);
370 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
371 msg_type, msg_flags));
373 return(outsize);
376 /****************************************************************************
377 Reply to a tcon.
378 conn POINTER CAN BE NULL HERE !
379 ****************************************************************************/
381 int reply_tcon(connection_struct *conn,
382 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
384 const char *service;
385 pstring service_buf;
386 pstring password;
387 pstring dev;
388 int outsize = 0;
389 uint16 vuid = SVAL(inbuf,smb_uid);
390 int pwlen=0;
391 NTSTATUS nt_status;
392 char *p;
393 DATA_BLOB password_blob;
395 START_PROFILE(SMBtcon);
397 *service_buf = *password = *dev = 0;
399 p = smb_buf(inbuf)+1;
400 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
401 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
402 p += pwlen;
403 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
405 p = strrchr_m(service_buf,'\\');
406 if (p) {
407 service = p+1;
408 } else {
409 service = service_buf;
412 password_blob = data_blob(password, pwlen+1);
414 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
416 data_blob_clear_free(&password_blob);
418 if (!conn) {
419 END_PROFILE(SMBtcon);
420 return ERROR_NT(nt_status);
423 outsize = set_message(outbuf,2,0,True);
424 SSVAL(outbuf,smb_vwv0,max_recv);
425 SSVAL(outbuf,smb_vwv1,conn->cnum);
426 SSVAL(outbuf,smb_tid,conn->cnum);
428 DEBUG(3,("tcon service=%s cnum=%d\n",
429 service, conn->cnum));
431 END_PROFILE(SMBtcon);
432 return(outsize);
435 /****************************************************************************
436 Reply to a tcon and X.
437 conn POINTER CAN BE NULL HERE !
438 ****************************************************************************/
440 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
442 fstring service;
443 DATA_BLOB password;
445 /* what the cleint thinks the device is */
446 fstring client_devicetype;
447 /* what the server tells the client the share represents */
448 const char *server_devicetype;
449 NTSTATUS nt_status;
450 uint16 vuid = SVAL(inbuf,smb_uid);
451 int passlen = SVAL(inbuf,smb_vwv3);
452 pstring path;
453 char *p, *q;
454 uint16 tcon_flags = SVAL(inbuf,smb_vwv2);
456 START_PROFILE(SMBtconX);
458 *service = *client_devicetype = 0;
460 /* we might have to close an old one */
461 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
462 close_cnum(conn,vuid);
465 if (passlen > MAX_PASS_LEN) {
466 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
469 if (global_encrypted_passwords_negotiated) {
470 password = data_blob(smb_buf(inbuf),passlen);
471 if (lp_security() == SEC_SHARE) {
473 * Security = share always has a pad byte
474 * after the password.
476 p = smb_buf(inbuf) + passlen + 1;
477 } else {
478 p = smb_buf(inbuf) + passlen;
480 } else {
481 password = data_blob(smb_buf(inbuf),passlen+1);
482 /* Ensure correct termination */
483 password.data[passlen]=0;
484 p = smb_buf(inbuf) + passlen + 1;
487 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
490 * the service name can be either: \\server\share
491 * or share directly like on the DELL PowerVault 705
493 if (*path=='\\') {
494 q = strchr_m(path+2,'\\');
495 if (!q) {
496 END_PROFILE(SMBtconX);
497 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
499 fstrcpy(service,q+1);
501 else
502 fstrcpy(service,path);
504 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
506 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
508 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
510 data_blob_clear_free(&password);
512 if (!conn) {
513 END_PROFILE(SMBtconX);
514 return ERROR_NT(nt_status);
517 if ( IS_IPC(conn) )
518 server_devicetype = "IPC";
519 else if ( IS_PRINT(conn) )
520 server_devicetype = "LPT1:";
521 else
522 server_devicetype = "A:";
524 if (Protocol < PROTOCOL_NT1) {
525 set_message(outbuf,2,0,True);
526 p = smb_buf(outbuf);
527 p += srvstr_push(outbuf, p, server_devicetype, -1,
528 STR_TERMINATE|STR_ASCII);
529 set_message_end(outbuf,p);
530 } else {
531 /* NT sets the fstype of IPC$ to the null string */
532 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
534 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
535 /* Return permissions. */
536 uint32 perm1 = 0;
537 uint32 perm2 = 0;
539 set_message(outbuf,7,0,True);
541 if (IS_IPC(conn)) {
542 perm1 = FILE_ALL_ACCESS;
543 perm2 = FILE_ALL_ACCESS;
544 } else {
545 perm1 = CAN_WRITE(conn) ?
546 SHARE_ALL_ACCESS :
547 SHARE_READ_ONLY;
550 SIVAL(outbuf, smb_vwv3, perm1);
551 SIVAL(outbuf, smb_vwv5, perm2);
552 } else {
553 set_message(outbuf,3,0,True);
556 p = smb_buf(outbuf);
557 p += srvstr_push(outbuf, p, server_devicetype, -1,
558 STR_TERMINATE|STR_ASCII);
559 p += srvstr_push(outbuf, p, fstype, -1,
560 STR_TERMINATE);
562 set_message_end(outbuf,p);
564 /* what does setting this bit do? It is set by NT4 and
565 may affect the ability to autorun mounted cdroms */
566 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
567 (lp_csc_policy(SNUM(conn)) << 2));
569 init_dfsroot(conn, inbuf, outbuf);
573 DEBUG(3,("tconX service=%s \n",
574 service));
576 /* set the incoming and outgoing tid to the just created one */
577 SSVAL(inbuf,smb_tid,conn->cnum);
578 SSVAL(outbuf,smb_tid,conn->cnum);
580 END_PROFILE(SMBtconX);
581 return chain_reply(inbuf,outbuf,length,bufsize);
584 /****************************************************************************
585 Reply to an unknown type.
586 ****************************************************************************/
588 int reply_unknown(char *inbuf,char *outbuf)
590 int type;
591 type = CVAL(inbuf,smb_com);
593 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
594 smb_fn_name(type), type, type));
596 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
599 /****************************************************************************
600 Reply to an ioctl.
601 conn POINTER CAN BE NULL HERE !
602 ****************************************************************************/
604 int reply_ioctl(connection_struct *conn,
605 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
607 uint16 device = SVAL(inbuf,smb_vwv1);
608 uint16 function = SVAL(inbuf,smb_vwv2);
609 uint32 ioctl_code = (device << 16) + function;
610 int replysize, outsize;
611 char *p;
612 START_PROFILE(SMBioctl);
614 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
616 switch (ioctl_code) {
617 case IOCTL_QUERY_JOB_INFO:
618 replysize = 32;
619 break;
620 default:
621 END_PROFILE(SMBioctl);
622 return(ERROR_DOS(ERRSRV,ERRnosupport));
625 outsize = set_message(outbuf,8,replysize+1,True);
626 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
627 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
628 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
629 p = smb_buf(outbuf) + 1; /* Allow for alignment */
631 switch (ioctl_code) {
632 case IOCTL_QUERY_JOB_INFO:
634 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
635 if (!fsp) {
636 END_PROFILE(SMBioctl);
637 return(UNIXERROR(ERRDOS,ERRbadfid));
639 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
640 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
641 if (conn) {
642 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
644 break;
648 END_PROFILE(SMBioctl);
649 return outsize;
652 /****************************************************************************
653 Strange checkpath NTSTATUS mapping.
654 ****************************************************************************/
656 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
658 /* Strange DOS error code semantics only for checkpath... */
659 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
660 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
661 /* We need to map to ERRbadpath */
662 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
665 return status;
668 /****************************************************************************
669 Reply to a checkpath.
670 ****************************************************************************/
672 int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
674 int outsize = 0;
675 pstring name;
676 SMB_STRUCT_STAT sbuf;
677 NTSTATUS status;
679 START_PROFILE(SMBcheckpath);
681 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
682 if (!NT_STATUS_IS_OK(status)) {
683 END_PROFILE(SMBcheckpath);
684 status = map_checkpath_error(inbuf, status);
685 return ERROR_NT(status);
688 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name);
689 if (!NT_STATUS_IS_OK(status)) {
690 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
691 END_PROFILE(SMBcheckpath);
692 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
694 goto path_err;
697 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
699 status = unix_convert(conn, name, False, NULL, &sbuf);
700 if (!NT_STATUS_IS_OK(status)) {
701 goto path_err;
704 status = check_name(conn, name);
705 if (!NT_STATUS_IS_OK(status)) {
706 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
707 goto path_err;
710 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
711 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
712 status = map_nt_error_from_unix(errno);
713 goto path_err;
716 if (!S_ISDIR(sbuf.st_mode)) {
717 END_PROFILE(SMBcheckpath);
718 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
721 outsize = set_message(outbuf,0,0,False);
723 END_PROFILE(SMBcheckpath);
724 return outsize;
726 path_err:
728 END_PROFILE(SMBcheckpath);
730 /* We special case this - as when a Windows machine
731 is parsing a path is steps through the components
732 one at a time - if a component fails it expects
733 ERRbadpath, not ERRbadfile.
735 status = map_checkpath_error(inbuf, status);
736 if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
738 * Windows returns different error codes if
739 * the parent directory is valid but not the
740 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
741 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
742 * if the path is invalid.
744 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
747 return ERROR_NT(status);
750 /****************************************************************************
751 Reply to a getatr.
752 ****************************************************************************/
754 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
756 pstring fname;
757 int outsize = 0;
758 SMB_STRUCT_STAT sbuf;
759 int mode=0;
760 SMB_OFF_T size=0;
761 time_t mtime=0;
762 char *p;
763 NTSTATUS status;
765 START_PROFILE(SMBgetatr);
767 p = smb_buf(inbuf) + 1;
768 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
769 if (!NT_STATUS_IS_OK(status)) {
770 END_PROFILE(SMBgetatr);
771 return ERROR_NT(status);
774 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
775 if (!NT_STATUS_IS_OK(status)) {
776 END_PROFILE(SMBgetatr);
777 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
778 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
780 return ERROR_NT(status);
783 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
784 under WfWg - weird! */
785 if (*fname == '\0') {
786 mode = aHIDDEN | aDIR;
787 if (!CAN_WRITE(conn)) {
788 mode |= aRONLY;
790 size = 0;
791 mtime = 0;
792 } else {
793 status = unix_convert(conn, fname, False, NULL,&sbuf);
794 if (!NT_STATUS_IS_OK(status)) {
795 END_PROFILE(SMBgetatr);
796 return ERROR_NT(status);
798 status = check_name(conn, fname);
799 if (!NT_STATUS_IS_OK(status)) {
800 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
801 END_PROFILE(SMBgetatr);
802 return ERROR_NT(status);
804 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
805 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
806 return UNIXERROR(ERRDOS,ERRbadfile);
809 mode = dos_mode(conn,fname,&sbuf);
810 size = sbuf.st_size;
811 mtime = sbuf.st_mtime;
812 if (mode & aDIR) {
813 size = 0;
817 outsize = set_message(outbuf,10,0,True);
819 SSVAL(outbuf,smb_vwv0,mode);
820 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
821 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
822 } else {
823 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
825 SIVAL(outbuf,smb_vwv3,(uint32)size);
827 if (Protocol >= PROTOCOL_NT1) {
828 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
831 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
833 END_PROFILE(SMBgetatr);
834 return(outsize);
837 /****************************************************************************
838 Reply to a setatr.
839 ****************************************************************************/
841 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
843 pstring fname;
844 int outsize = 0;
845 int mode;
846 time_t mtime;
847 SMB_STRUCT_STAT sbuf;
848 char *p;
849 NTSTATUS status;
851 START_PROFILE(SMBsetatr);
853 p = smb_buf(inbuf) + 1;
854 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
855 if (!NT_STATUS_IS_OK(status)) {
856 END_PROFILE(SMBsetatr);
857 return ERROR_NT(status);
860 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
861 if (!NT_STATUS_IS_OK(status)) {
862 END_PROFILE(SMBsetatr);
863 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
864 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
866 return ERROR_NT(status);
869 status = unix_convert(conn, fname, False, NULL, &sbuf);
870 if (!NT_STATUS_IS_OK(status)) {
871 END_PROFILE(SMBsetatr);
872 return ERROR_NT(status);
875 status = check_name(conn, fname);
876 if (!NT_STATUS_IS_OK(status)) {
877 END_PROFILE(SMBsetatr);
878 return ERROR_NT(status);
881 if (fname[0] == '.' && fname[1] == '\0') {
883 * Not sure here is the right place to catch this
884 * condition. Might be moved to somewhere else later -- vl
886 END_PROFILE(SMBsetatr);
887 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
890 mode = SVAL(inbuf,smb_vwv0);
891 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
893 if (mode != FILE_ATTRIBUTE_NORMAL) {
894 if (VALID_STAT_OF_DIR(sbuf))
895 mode |= aDIR;
896 else
897 mode &= ~aDIR;
899 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
900 END_PROFILE(SMBsetatr);
901 return UNIXERROR(ERRDOS, ERRnoaccess);
905 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
906 END_PROFILE(SMBsetatr);
907 return UNIXERROR(ERRDOS, ERRnoaccess);
910 outsize = set_message(outbuf,0,0,False);
912 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
914 END_PROFILE(SMBsetatr);
915 return(outsize);
918 /****************************************************************************
919 Reply to a dskattr.
920 ****************************************************************************/
922 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
924 int outsize = 0;
925 SMB_BIG_UINT dfree,dsize,bsize;
926 START_PROFILE(SMBdskattr);
928 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
929 END_PROFILE(SMBdskattr);
930 return(UNIXERROR(ERRHRD,ERRgeneral));
933 outsize = set_message(outbuf,5,0,True);
935 if (Protocol <= PROTOCOL_LANMAN2) {
936 double total_space, free_space;
937 /* we need to scale this to a number that DOS6 can handle. We
938 use floating point so we can handle large drives on systems
939 that don't have 64 bit integers
941 we end up displaying a maximum of 2G to DOS systems
943 total_space = dsize * (double)bsize;
944 free_space = dfree * (double)bsize;
946 dsize = (total_space+63*512) / (64*512);
947 dfree = (free_space+63*512) / (64*512);
949 if (dsize > 0xFFFF) dsize = 0xFFFF;
950 if (dfree > 0xFFFF) dfree = 0xFFFF;
952 SSVAL(outbuf,smb_vwv0,dsize);
953 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
954 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
955 SSVAL(outbuf,smb_vwv3,dfree);
956 } else {
957 SSVAL(outbuf,smb_vwv0,dsize);
958 SSVAL(outbuf,smb_vwv1,bsize/512);
959 SSVAL(outbuf,smb_vwv2,512);
960 SSVAL(outbuf,smb_vwv3,dfree);
963 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
965 END_PROFILE(SMBdskattr);
966 return(outsize);
969 /****************************************************************************
970 Reply to a search.
971 Can be called from SMBsearch, SMBffirst or SMBfunique.
972 ****************************************************************************/
974 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
976 pstring mask;
977 pstring directory;
978 pstring fname;
979 SMB_OFF_T size;
980 uint32 mode;
981 time_t date;
982 uint32 dirtype;
983 int outsize = 0;
984 unsigned int numentries = 0;
985 unsigned int maxentries = 0;
986 BOOL finished = False;
987 char *p;
988 int status_len;
989 pstring path;
990 char status[21];
991 int dptr_num= -1;
992 BOOL check_descend = False;
993 BOOL expect_close = False;
994 NTSTATUS nt_status;
995 BOOL mask_contains_wcard = False;
996 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
998 START_PROFILE(SMBsearch);
1000 if (lp_posix_pathnames()) {
1001 END_PROFILE(SMBsearch);
1002 return reply_unknown(inbuf, outbuf);
1005 *mask = *directory = *fname = 0;
1007 /* If we were called as SMBffirst then we must expect close. */
1008 if(CVAL(inbuf,smb_com) == SMBffirst) {
1009 expect_close = True;
1012 outsize = set_message(outbuf,1,3,True);
1013 maxentries = SVAL(inbuf,smb_vwv0);
1014 dirtype = SVAL(inbuf,smb_vwv1);
1015 p = smb_buf(inbuf) + 1;
1016 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
1017 if (!NT_STATUS_IS_OK(nt_status)) {
1018 END_PROFILE(SMBsearch);
1019 return ERROR_NT(nt_status);
1022 nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
1023 if (!NT_STATUS_IS_OK(nt_status)) {
1024 END_PROFILE(SMBsearch);
1025 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1026 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1028 return ERROR_NT(nt_status);
1031 p++;
1032 status_len = SVAL(p, 0);
1033 p += 2;
1035 /* dirtype &= ~aDIR; */
1037 if (status_len == 0) {
1038 SMB_STRUCT_STAT sbuf;
1040 pstrcpy(directory,path);
1041 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1042 if (!NT_STATUS_IS_OK(nt_status)) {
1043 END_PROFILE(SMBsearch);
1044 return ERROR_NT(nt_status);
1047 nt_status = check_name(conn, directory);
1048 if (!NT_STATUS_IS_OK(nt_status)) {
1049 END_PROFILE(SMBsearch);
1050 return ERROR_NT(nt_status);
1053 p = strrchr_m(directory,'/');
1054 if (!p) {
1055 pstrcpy(mask,directory);
1056 pstrcpy(directory,".");
1057 } else {
1058 *p = 0;
1059 pstrcpy(mask,p+1);
1062 if (*directory == '\0') {
1063 pstrcpy(directory,".");
1065 memset((char *)status,'\0',21);
1066 SCVAL(status,0,(dirtype & 0x1F));
1067 } else {
1068 int status_dirtype;
1070 memcpy(status,p,21);
1071 status_dirtype = CVAL(status,0) & 0x1F;
1072 if (status_dirtype != (dirtype & 0x1F)) {
1073 dirtype = status_dirtype;
1076 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1077 if (!conn->dirptr) {
1078 goto SearchEmpty;
1080 string_set(&conn->dirpath,dptr_path(dptr_num));
1081 pstrcpy(mask, dptr_wcard(dptr_num));
1083 * For a 'continue' search we have no string. So
1084 * check from the initial saved string.
1086 mask_contains_wcard = ms_has_wild(mask);
1089 p = smb_buf(outbuf) + 3;
1091 if (status_len == 0) {
1092 nt_status = dptr_create(conn,
1093 directory,
1094 True,
1095 expect_close,
1096 SVAL(inbuf,smb_pid),
1097 mask,
1098 mask_contains_wcard,
1099 dirtype,
1100 &conn->dirptr);
1101 if (!NT_STATUS_IS_OK(nt_status)) {
1102 return ERROR_NT(nt_status);
1104 dptr_num = dptr_dnum(conn->dirptr);
1105 } else {
1106 dirtype = dptr_attr(dptr_num);
1109 DEBUG(4,("dptr_num is %d\n",dptr_num));
1111 if ((dirtype&0x1F) == aVOLID) {
1112 memcpy(p,status,21);
1113 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1114 0,aVOLID,0,!allow_long_path_components);
1115 dptr_fill(p+12,dptr_num);
1116 if (dptr_zero(p+12) && (status_len==0)) {
1117 numentries = 1;
1118 } else {
1119 numentries = 0;
1121 p += DIR_STRUCT_SIZE;
1122 } else {
1123 unsigned int i;
1124 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1126 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1127 conn->dirpath,lp_dontdescend(SNUM(conn))));
1128 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1129 check_descend = True;
1132 for (i=numentries;(i<maxentries) && !finished;i++) {
1133 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1134 if (!finished) {
1135 memcpy(p,status,21);
1136 make_dir_struct(p,mask,fname,size, mode,date,
1137 !allow_long_path_components);
1138 if (!dptr_fill(p+12,dptr_num)) {
1139 break;
1141 numentries++;
1142 p += DIR_STRUCT_SIZE;
1147 SearchEmpty:
1149 /* If we were called as SMBffirst with smb_search_id == NULL
1150 and no entries were found then return error and close dirptr
1151 (X/Open spec) */
1153 if (numentries == 0) {
1154 dptr_close(&dptr_num);
1155 } else if(expect_close && status_len == 0) {
1156 /* Close the dptr - we know it's gone */
1157 dptr_close(&dptr_num);
1160 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1161 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1162 dptr_close(&dptr_num);
1165 if ((numentries == 0) && !mask_contains_wcard) {
1166 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1169 SSVAL(outbuf,smb_vwv0,numentries);
1170 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1171 SCVAL(smb_buf(outbuf),0,5);
1172 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1174 /* The replies here are never long name. */
1175 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1176 if (!allow_long_path_components) {
1177 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1180 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1181 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1183 outsize += DIR_STRUCT_SIZE*numentries;
1184 smb_setlen(outbuf,outsize - 4);
1186 if ((! *directory) && dptr_path(dptr_num))
1187 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1189 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1190 smb_fn_name(CVAL(inbuf,smb_com)),
1191 mask, directory, dirtype, numentries, maxentries ) );
1193 END_PROFILE(SMBsearch);
1194 return(outsize);
1197 /****************************************************************************
1198 Reply to a fclose (stop directory search).
1199 ****************************************************************************/
1201 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1203 int outsize = 0;
1204 int status_len;
1205 pstring path;
1206 char status[21];
1207 int dptr_num= -2;
1208 char *p;
1209 NTSTATUS err;
1210 BOOL path_contains_wcard = False;
1212 START_PROFILE(SMBfclose);
1214 if (lp_posix_pathnames()) {
1215 END_PROFILE(SMBfclose);
1216 return reply_unknown(inbuf, outbuf);
1219 outsize = set_message(outbuf,1,0,True);
1220 p = smb_buf(inbuf) + 1;
1221 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1222 if (!NT_STATUS_IS_OK(err)) {
1223 END_PROFILE(SMBfclose);
1224 return ERROR_NT(err);
1226 p++;
1227 status_len = SVAL(p,0);
1228 p += 2;
1230 if (status_len == 0) {
1231 END_PROFILE(SMBfclose);
1232 return ERROR_DOS(ERRSRV,ERRsrverror);
1235 memcpy(status,p,21);
1237 if(dptr_fetch(status+12,&dptr_num)) {
1238 /* Close the dptr - we know it's gone */
1239 dptr_close(&dptr_num);
1242 SSVAL(outbuf,smb_vwv0,0);
1244 DEBUG(3,("search close\n"));
1246 END_PROFILE(SMBfclose);
1247 return(outsize);
1250 /****************************************************************************
1251 Reply to an open.
1252 ****************************************************************************/
1254 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1256 pstring fname;
1257 int outsize = 0;
1258 uint32 fattr=0;
1259 SMB_OFF_T size = 0;
1260 time_t mtime=0;
1261 int info;
1262 SMB_STRUCT_STAT sbuf;
1263 files_struct *fsp;
1264 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1265 int deny_mode;
1266 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1267 uint32 access_mask;
1268 uint32 share_mode;
1269 uint32 create_disposition;
1270 uint32 create_options = 0;
1271 NTSTATUS status;
1272 START_PROFILE(SMBopen);
1274 deny_mode = SVAL(inbuf,smb_vwv0);
1276 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1277 if (!NT_STATUS_IS_OK(status)) {
1278 END_PROFILE(SMBopen);
1279 return ERROR_NT(status);
1282 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1283 if (!NT_STATUS_IS_OK(status)) {
1284 END_PROFILE(SMBopen);
1285 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1286 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1288 return ERROR_NT(status);
1291 status = unix_convert(conn, fname, False, NULL, &sbuf);
1292 if (!NT_STATUS_IS_OK(status)) {
1293 END_PROFILE(SMBopen);
1294 return ERROR_NT(status);
1297 status = check_name(conn, fname);
1298 if (!NT_STATUS_IS_OK(status)) {
1299 END_PROFILE(SMBopen);
1300 return ERROR_NT(status);
1303 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1304 &access_mask, &share_mode, &create_disposition, &create_options)) {
1305 END_PROFILE(SMBopen);
1306 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1309 status = open_file_ntcreate(conn,fname,&sbuf,
1310 access_mask,
1311 share_mode,
1312 create_disposition,
1313 create_options,
1314 dos_attr,
1315 oplock_request,
1316 &info, &fsp);
1318 if (!NT_STATUS_IS_OK(status)) {
1319 END_PROFILE(SMBopen);
1320 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1321 /* We have re-scheduled this call. */
1322 return -1;
1324 return ERROR_OPEN(status);
1327 size = sbuf.st_size;
1328 fattr = dos_mode(conn,fname,&sbuf);
1329 mtime = sbuf.st_mtime;
1331 if (fattr & aDIR) {
1332 DEBUG(3,("attempt to open a directory %s\n",fname));
1333 close_file(fsp,ERROR_CLOSE);
1334 END_PROFILE(SMBopen);
1335 return ERROR_DOS(ERRDOS,ERRnoaccess);
1338 outsize = set_message(outbuf,7,0,True);
1339 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1340 SSVAL(outbuf,smb_vwv1,fattr);
1341 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1342 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1343 } else {
1344 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1346 SIVAL(outbuf,smb_vwv4,(uint32)size);
1347 SSVAL(outbuf,smb_vwv6,deny_mode);
1349 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1350 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1353 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1354 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1356 END_PROFILE(SMBopen);
1357 return(outsize);
1360 /****************************************************************************
1361 Reply to an open and X.
1362 ****************************************************************************/
1364 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1366 pstring fname;
1367 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1368 int deny_mode = SVAL(inbuf,smb_vwv3);
1369 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1370 /* Breakout the oplock request bits so we can set the
1371 reply bits separately. */
1372 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1373 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1374 int oplock_request = ex_oplock_request | core_oplock_request;
1375 #if 0
1376 int smb_sattr = SVAL(inbuf,smb_vwv4);
1377 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1378 #endif
1379 int smb_ofun = SVAL(inbuf,smb_vwv8);
1380 uint32 fattr=0;
1381 int mtime=0;
1382 SMB_STRUCT_STAT sbuf;
1383 int smb_action = 0;
1384 files_struct *fsp;
1385 NTSTATUS status;
1386 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1387 ssize_t retval = -1;
1388 uint32 access_mask;
1389 uint32 share_mode;
1390 uint32 create_disposition;
1391 uint32 create_options = 0;
1393 START_PROFILE(SMBopenX);
1395 /* If it's an IPC, pass off the pipe handler. */
1396 if (IS_IPC(conn)) {
1397 if (lp_nt_pipe_support()) {
1398 END_PROFILE(SMBopenX);
1399 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1400 } else {
1401 END_PROFILE(SMBopenX);
1402 return ERROR_DOS(ERRSRV,ERRaccess);
1406 /* XXXX we need to handle passed times, sattr and flags */
1407 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1408 if (!NT_STATUS_IS_OK(status)) {
1409 END_PROFILE(SMBopenX);
1410 return ERROR_NT(status);
1413 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1414 if (!NT_STATUS_IS_OK(status)) {
1415 END_PROFILE(SMBopenX);
1416 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1417 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1419 return ERROR_NT(status);
1422 status = unix_convert(conn, fname, False, NULL, &sbuf);
1423 if (!NT_STATUS_IS_OK(status)) {
1424 END_PROFILE(SMBopenX);
1425 return ERROR_NT(status);
1428 status = check_name(conn, fname);
1429 if (!NT_STATUS_IS_OK(status)) {
1430 END_PROFILE(SMBopenX);
1431 return ERROR_NT(status);
1434 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1435 &access_mask,
1436 &share_mode,
1437 &create_disposition,
1438 &create_options)) {
1439 END_PROFILE(SMBopenX);
1440 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1443 status = open_file_ntcreate(conn,fname,&sbuf,
1444 access_mask,
1445 share_mode,
1446 create_disposition,
1447 create_options,
1448 smb_attr,
1449 oplock_request,
1450 &smb_action, &fsp);
1452 if (!NT_STATUS_IS_OK(status)) {
1453 END_PROFILE(SMBopenX);
1454 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1455 /* We have re-scheduled this call. */
1456 return -1;
1458 return ERROR_OPEN(status);
1461 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1462 if the file is truncated or created. */
1463 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1464 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1465 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1466 close_file(fsp,ERROR_CLOSE);
1467 END_PROFILE(SMBopenX);
1468 return ERROR_NT(NT_STATUS_DISK_FULL);
1470 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1471 if (retval < 0) {
1472 close_file(fsp,ERROR_CLOSE);
1473 END_PROFILE(SMBopenX);
1474 return ERROR_NT(NT_STATUS_DISK_FULL);
1476 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1479 fattr = dos_mode(conn,fname,&sbuf);
1480 mtime = sbuf.st_mtime;
1481 if (fattr & aDIR) {
1482 close_file(fsp,ERROR_CLOSE);
1483 END_PROFILE(SMBopenX);
1484 return ERROR_DOS(ERRDOS,ERRnoaccess);
1487 /* If the caller set the extended oplock request bit
1488 and we granted one (by whatever means) - set the
1489 correct bit for extended oplock reply.
1492 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1493 smb_action |= EXTENDED_OPLOCK_GRANTED;
1496 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1497 smb_action |= EXTENDED_OPLOCK_GRANTED;
1500 /* If the caller set the core oplock request bit
1501 and we granted one (by whatever means) - set the
1502 correct bit for core oplock reply.
1505 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1506 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1509 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1510 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1513 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1514 set_message(outbuf,19,0,True);
1515 } else {
1516 set_message(outbuf,15,0,True);
1518 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1519 SSVAL(outbuf,smb_vwv3,fattr);
1520 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1521 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1522 } else {
1523 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1525 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1526 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1527 SSVAL(outbuf,smb_vwv11,smb_action);
1529 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1530 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1533 END_PROFILE(SMBopenX);
1534 return chain_reply(inbuf,outbuf,length,bufsize);
1537 /****************************************************************************
1538 Reply to a SMBulogoffX.
1539 conn POINTER CAN BE NULL HERE !
1540 ****************************************************************************/
1542 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1544 uint16 vuid = SVAL(inbuf,smb_uid);
1545 user_struct *vuser = get_valid_user_struct(vuid);
1546 START_PROFILE(SMBulogoffX);
1548 if(vuser == 0)
1549 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1551 /* in user level security we are supposed to close any files
1552 open by this user */
1553 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1554 file_close_user(vuid);
1556 invalidate_vuid(vuid);
1558 set_message(outbuf,2,0,True);
1560 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1562 END_PROFILE(SMBulogoffX);
1563 return chain_reply(inbuf,outbuf,length,bufsize);
1566 /****************************************************************************
1567 Reply to a mknew or a create.
1568 ****************************************************************************/
1570 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1572 pstring fname;
1573 int com;
1574 int outsize = 0;
1575 uint32 fattr = SVAL(inbuf,smb_vwv0);
1576 struct timespec ts[2];
1577 files_struct *fsp;
1578 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1579 SMB_STRUCT_STAT sbuf;
1580 NTSTATUS status;
1581 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1582 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1583 uint32 create_disposition;
1584 uint32 create_options = 0;
1586 START_PROFILE(SMBcreate);
1588 com = SVAL(inbuf,smb_com);
1590 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1592 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1593 if (!NT_STATUS_IS_OK(status)) {
1594 END_PROFILE(SMBcreate);
1595 return ERROR_NT(status);
1598 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1599 if (!NT_STATUS_IS_OK(status)) {
1600 END_PROFILE(SMBcreate);
1601 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1602 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1604 return ERROR_NT(status);
1607 status = unix_convert(conn, fname, False, NULL, &sbuf);
1608 if (!NT_STATUS_IS_OK(status)) {
1609 END_PROFILE(SMBcreate);
1610 return ERROR_NT(status);
1613 status = check_name(conn, fname);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 END_PROFILE(SMBcreate);
1616 return ERROR_NT(status);
1619 if (fattr & aVOLID) {
1620 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1623 if(com == SMBmknew) {
1624 /* We should fail if file exists. */
1625 create_disposition = FILE_CREATE;
1626 } else {
1627 /* Create if file doesn't exist, truncate if it does. */
1628 create_disposition = FILE_OVERWRITE_IF;
1631 /* Open file using ntcreate. */
1632 status = open_file_ntcreate(conn,fname,&sbuf,
1633 access_mask,
1634 share_mode,
1635 create_disposition,
1636 create_options,
1637 fattr,
1638 oplock_request,
1639 NULL, &fsp);
1641 if (!NT_STATUS_IS_OK(status)) {
1642 END_PROFILE(SMBcreate);
1643 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1644 /* We have re-scheduled this call. */
1645 return -1;
1647 return ERROR_OPEN(status);
1650 ts[0] = get_atimespec(&sbuf); /* atime. */
1651 file_ntimes(conn, fname, ts);
1653 outsize = set_message(outbuf,1,0,True);
1654 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1656 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1657 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1660 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1661 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1664 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1665 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1667 END_PROFILE(SMBcreate);
1668 return(outsize);
1671 /****************************************************************************
1672 Reply to a create temporary file.
1673 ****************************************************************************/
1675 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1677 pstring fname;
1678 int outsize = 0;
1679 uint32 fattr = SVAL(inbuf,smb_vwv0);
1680 files_struct *fsp;
1681 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1682 int tmpfd;
1683 SMB_STRUCT_STAT sbuf;
1684 char *p, *s;
1685 NTSTATUS status;
1686 unsigned int namelen;
1688 START_PROFILE(SMBctemp);
1690 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1691 if (!NT_STATUS_IS_OK(status)) {
1692 END_PROFILE(SMBctemp);
1693 return ERROR_NT(status);
1695 if (*fname) {
1696 pstrcat(fname,"/TMXXXXXX");
1697 } else {
1698 pstrcat(fname,"TMXXXXXX");
1701 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1702 if (!NT_STATUS_IS_OK(status)) {
1703 END_PROFILE(SMBctemp);
1704 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1705 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1707 return ERROR_NT(status);
1710 status = unix_convert(conn, fname, False, NULL, &sbuf);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 END_PROFILE(SMBctemp);
1713 return ERROR_NT(status);
1716 status = check_name(conn, fname);
1717 if (!NT_STATUS_IS_OK(status)) {
1718 END_PROFILE(SMBctemp);
1719 return ERROR_NT(status);
1722 tmpfd = smb_mkstemp(fname);
1723 if (tmpfd == -1) {
1724 END_PROFILE(SMBctemp);
1725 return(UNIXERROR(ERRDOS,ERRnoaccess));
1728 SMB_VFS_STAT(conn,fname,&sbuf);
1730 /* We should fail if file does not exist. */
1731 status = open_file_ntcreate(conn,fname,&sbuf,
1732 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1733 FILE_SHARE_READ|FILE_SHARE_WRITE,
1734 FILE_OPEN,
1736 fattr,
1737 oplock_request,
1738 NULL, &fsp);
1740 /* close fd from smb_mkstemp() */
1741 close(tmpfd);
1743 if (!NT_STATUS_IS_OK(status)) {
1744 END_PROFILE(SMBctemp);
1745 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1746 /* We have re-scheduled this call. */
1747 return -1;
1749 return ERROR_OPEN(status);
1752 outsize = set_message(outbuf,1,0,True);
1753 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1755 /* the returned filename is relative to the directory */
1756 s = strrchr_m(fname, '/');
1757 if (!s) {
1758 s = fname;
1759 } else {
1760 s++;
1763 p = smb_buf(outbuf);
1764 #if 0
1765 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1766 thing in the byte section. JRA */
1767 SSVALS(p, 0, -1); /* what is this? not in spec */
1768 #endif
1769 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1770 p += namelen;
1771 outsize = set_message_end(outbuf, p);
1773 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1774 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1777 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1778 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1781 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1782 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1783 (unsigned int)sbuf.st_mode ) );
1785 END_PROFILE(SMBctemp);
1786 return(outsize);
1789 /*******************************************************************
1790 Check if a user is allowed to rename a file.
1791 ********************************************************************/
1793 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst, BOOL self_open)
1795 files_struct *fsp;
1796 uint32 fmode;
1797 NTSTATUS status;
1799 if (!CAN_WRITE(conn)) {
1800 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1803 fmode = dos_mode(conn,fname,pst);
1804 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1805 return NT_STATUS_NO_SUCH_FILE;
1808 if (S_ISDIR(pst->st_mode)) {
1809 return NT_STATUS_OK;
1812 status = open_file_ntcreate(conn, fname, pst,
1813 DELETE_ACCESS,
1814 /* If we're checking our fsp don't deny for delete. */
1815 self_open ?
1816 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE :
1817 FILE_SHARE_READ|FILE_SHARE_WRITE,
1818 FILE_OPEN,
1820 FILE_ATTRIBUTE_NORMAL,
1822 NULL, &fsp);
1824 if (!NT_STATUS_IS_OK(status)) {
1825 return status;
1827 close_file(fsp,NORMAL_CLOSE);
1828 return NT_STATUS_OK;
1831 /*******************************************************************
1832 Check if a user is allowed to delete a file.
1833 ********************************************************************/
1835 static NTSTATUS can_delete(connection_struct *conn, char *fname,
1836 uint32 dirtype, BOOL can_defer)
1838 SMB_STRUCT_STAT sbuf;
1839 uint32 fattr;
1840 files_struct *fsp;
1841 uint32 dirtype_orig = dirtype;
1842 NTSTATUS status;
1844 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1846 if (!CAN_WRITE(conn)) {
1847 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1850 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1851 return map_nt_error_from_unix(errno);
1854 fattr = dos_mode(conn,fname,&sbuf);
1856 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1857 dirtype = aDIR|aARCH|aRONLY;
1860 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1861 if (!dirtype) {
1862 return NT_STATUS_NO_SUCH_FILE;
1865 if (!dir_check_ftype(conn, fattr, dirtype)) {
1866 if (fattr & aDIR) {
1867 return NT_STATUS_FILE_IS_A_DIRECTORY;
1869 return NT_STATUS_NO_SUCH_FILE;
1872 if (dirtype_orig & 0x8000) {
1873 /* These will never be set for POSIX. */
1874 return NT_STATUS_NO_SUCH_FILE;
1877 #if 0
1878 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1879 return NT_STATUS_FILE_IS_A_DIRECTORY;
1882 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1883 return NT_STATUS_NO_SUCH_FILE;
1886 if (dirtype & 0xFF00) {
1887 /* These will never be set for POSIX. */
1888 return NT_STATUS_NO_SUCH_FILE;
1891 dirtype &= 0xFF;
1892 if (!dirtype) {
1893 return NT_STATUS_NO_SUCH_FILE;
1896 /* Can't delete a directory. */
1897 if (fattr & aDIR) {
1898 return NT_STATUS_FILE_IS_A_DIRECTORY;
1900 #endif
1902 #if 0 /* JRATEST */
1903 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1904 return NT_STATUS_OBJECT_NAME_INVALID;
1905 #endif /* JRATEST */
1907 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1909 On a Windows share, a file with read-only dosmode can be opened with
1910 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1911 fails with NT_STATUS_CANNOT_DELETE error.
1913 This semantic causes a problem that a user can not
1914 rename a file with read-only dosmode on a Samba share
1915 from a Windows command prompt (i.e. cmd.exe, but can rename
1916 from Windows Explorer).
1919 if (!lp_delete_readonly(SNUM(conn))) {
1920 if (fattr & aRONLY) {
1921 return NT_STATUS_CANNOT_DELETE;
1925 /* On open checks the open itself will check the share mode, so
1926 don't do it here as we'll get it wrong. */
1928 status = open_file_ntcreate(conn, fname, &sbuf,
1929 DELETE_ACCESS,
1930 FILE_SHARE_NONE,
1931 FILE_OPEN,
1933 FILE_ATTRIBUTE_NORMAL,
1934 can_defer ? 0 : INTERNAL_OPEN_ONLY,
1935 NULL, &fsp);
1937 if (NT_STATUS_IS_OK(status)) {
1938 close_file(fsp,NORMAL_CLOSE);
1940 return status;
1943 /****************************************************************************
1944 The guts of the unlink command, split out so it may be called by the NT SMB
1945 code.
1946 ****************************************************************************/
1948 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
1949 char *name, BOOL has_wild, BOOL can_defer)
1951 pstring directory;
1952 pstring mask;
1953 char *p;
1954 int count=0;
1955 NTSTATUS status = NT_STATUS_OK;
1956 SMB_STRUCT_STAT sbuf;
1958 *directory = *mask = 0;
1960 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1961 if (!NT_STATUS_IS_OK(status)) {
1962 return status;
1965 p = strrchr_m(name,'/');
1966 if (!p) {
1967 pstrcpy(directory,".");
1968 pstrcpy(mask,name);
1969 } else {
1970 *p = 0;
1971 pstrcpy(directory,name);
1972 pstrcpy(mask,p+1);
1976 * We should only check the mangled cache
1977 * here if unix_convert failed. This means
1978 * that the path in 'mask' doesn't exist
1979 * on the file system and so we need to look
1980 * for a possible mangle. This patch from
1981 * Tine Smukavec <valentin.smukavec@hermes.si>.
1984 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
1985 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
1987 if (!has_wild) {
1988 pstrcat(directory,"/");
1989 pstrcat(directory,mask);
1990 if (dirtype == 0) {
1991 dirtype = FILE_ATTRIBUTE_NORMAL;
1994 status = check_name(conn, directory);
1995 if (!NT_STATUS_IS_OK(status)) {
1996 return status;
1999 status = can_delete(conn,directory,dirtype,can_defer);
2000 if (!NT_STATUS_IS_OK(status)) {
2001 return status;
2004 if (SMB_VFS_UNLINK(conn,directory) == 0) {
2005 count++;
2006 notify_fname(conn, NOTIFY_ACTION_REMOVED,
2007 FILE_NOTIFY_CHANGE_FILE_NAME,
2008 directory);
2010 } else {
2011 struct smb_Dir *dir_hnd = NULL;
2012 long offset = 0;
2013 const char *dname;
2015 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2016 return NT_STATUS_OBJECT_NAME_INVALID;
2019 if (strequal(mask,"????????.???")) {
2020 pstrcpy(mask,"*");
2023 status = check_name(conn, directory);
2024 if (!NT_STATUS_IS_OK(status)) {
2025 return status;
2028 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2029 if (dir_hnd == NULL) {
2030 return map_nt_error_from_unix(errno);
2033 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2034 the pattern matches against the long name, otherwise the short name
2035 We don't implement this yet XXXX
2038 status = NT_STATUS_NO_SUCH_FILE;
2040 while ((dname = ReadDirName(dir_hnd, &offset))) {
2041 SMB_STRUCT_STAT st;
2042 pstring fname;
2043 pstrcpy(fname,dname);
2045 if (!is_visible_file(conn, directory, dname, &st, True)) {
2046 continue;
2049 /* Quick check for "." and ".." */
2050 if (fname[0] == '.') {
2051 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2052 continue;
2056 if(!mask_match(fname, mask, conn->case_sensitive)) {
2057 continue;
2060 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2062 status = check_name(conn, fname);
2063 if (!NT_STATUS_IS_OK(status)) {
2064 CloseDir(dir_hnd);
2065 return status;
2068 status = can_delete(conn, fname, dirtype, can_defer);
2069 if (!NT_STATUS_IS_OK(status)) {
2070 continue;
2072 if (SMB_VFS_UNLINK(conn,fname) == 0) {
2073 count++;
2074 DEBUG(3,("unlink_internals: succesful unlink "
2075 "[%s]\n",fname));
2076 notify_fname(conn, NOTIFY_ACTION_REMOVED,
2077 FILE_NOTIFY_CHANGE_FILE_NAME,
2078 fname);
2082 CloseDir(dir_hnd);
2085 if (count == 0 && NT_STATUS_IS_OK(status)) {
2086 status = map_nt_error_from_unix(errno);
2089 return status;
2092 /****************************************************************************
2093 Reply to a unlink
2094 ****************************************************************************/
2096 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2097 int dum_buffsize)
2099 int outsize = 0;
2100 pstring name;
2101 uint32 dirtype;
2102 NTSTATUS status;
2103 BOOL path_contains_wcard = False;
2105 START_PROFILE(SMBunlink);
2107 dirtype = SVAL(inbuf,smb_vwv0);
2109 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
2110 if (!NT_STATUS_IS_OK(status)) {
2111 END_PROFILE(SMBunlink);
2112 return ERROR_NT(status);
2115 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
2116 if (!NT_STATUS_IS_OK(status)) {
2117 END_PROFILE(SMBunlink);
2118 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2119 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
2121 return ERROR_NT(status);
2124 DEBUG(3,("reply_unlink : %s\n",name));
2126 status = unlink_internals(conn, dirtype, name, path_contains_wcard,
2127 True);
2128 if (!NT_STATUS_IS_OK(status)) {
2129 END_PROFILE(SMBunlink);
2130 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2131 /* We have re-scheduled this call. */
2132 return -1;
2134 return ERROR_NT(status);
2137 outsize = set_message(outbuf,0,0,False);
2139 END_PROFILE(SMBunlink);
2140 return outsize;
2143 /****************************************************************************
2144 Fail for readbraw.
2145 ****************************************************************************/
2147 static void fail_readraw(void)
2149 pstring errstr;
2150 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2151 strerror(errno) );
2152 exit_server_cleanly(errstr);
2155 #if defined(WITH_SENDFILE)
2156 /****************************************************************************
2157 Fake (read/write) sendfile. Returns -1 on read or write fail.
2158 ****************************************************************************/
2160 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2162 ssize_t ret=0;
2164 /* Paranioa check... */
2165 if (nread > bufsize) {
2166 fail_readraw();
2169 if (nread > 0) {
2170 ret = read_file(fsp,buf,startpos,nread);
2171 if (ret == -1) {
2172 return -1;
2176 /* If we had a short read, fill with zeros. */
2177 if (ret < nread) {
2178 memset(buf, '\0', nread - ret);
2181 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2182 return -1;
2185 return (ssize_t)nread;
2187 #endif
2189 /****************************************************************************
2190 Use sendfile in readbraw.
2191 ****************************************************************************/
2193 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2194 ssize_t mincount, char *outbuf, int out_buffsize)
2196 ssize_t ret=0;
2198 #if defined(WITH_SENDFILE)
2200 * We can only use sendfile on a non-chained packet
2201 * but we can use on a non-oplocked file. tridge proved this
2202 * on a train in Germany :-). JRA.
2203 * reply_readbraw has already checked the length.
2206 if ( (chain_size == 0) && (nread > 0) &&
2207 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2208 DATA_BLOB header;
2210 _smb_setlen(outbuf,nread);
2211 header.data = (uint8 *)outbuf;
2212 header.length = 4;
2213 header.free = NULL;
2215 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2216 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2217 if (errno == ENOSYS) {
2218 goto normal_readbraw;
2222 * Special hack for broken Linux with no working sendfile. If we
2223 * return EINTR we sent the header but not the rest of the data.
2224 * Fake this up by doing read/write calls.
2226 if (errno == EINTR) {
2227 /* Ensure we don't do this again. */
2228 set_use_sendfile(SNUM(conn), False);
2229 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2231 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2232 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2233 fsp->fsp_name, strerror(errno) ));
2234 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2236 return;
2239 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2240 fsp->fsp_name, strerror(errno) ));
2241 exit_server_cleanly("send_file_readbraw sendfile failed");
2244 return;
2247 normal_readbraw:
2249 #endif
2251 if (nread > 0) {
2252 ret = read_file(fsp,outbuf+4,startpos,nread);
2253 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2254 if (ret < mincount)
2255 ret = 0;
2256 #else
2257 if (ret < nread)
2258 ret = 0;
2259 #endif
2262 _smb_setlen(outbuf,ret);
2263 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2264 fail_readraw();
2267 /****************************************************************************
2268 Reply to a readbraw (core+ protocol).
2269 ****************************************************************************/
2271 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2273 ssize_t maxcount,mincount;
2274 size_t nread = 0;
2275 SMB_OFF_T startpos;
2276 char *header = outbuf;
2277 files_struct *fsp;
2278 START_PROFILE(SMBreadbraw);
2280 if (srv_is_signing_active()) {
2281 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2285 * Special check if an oplock break has been issued
2286 * and the readraw request croses on the wire, we must
2287 * return a zero length response here.
2290 fsp = file_fsp(inbuf,smb_vwv0);
2292 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2294 * fsp could be NULL here so use the value from the packet. JRA.
2296 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2297 _smb_setlen(header,0);
2298 if (write_data(smbd_server_fd(),header,4) != 4)
2299 fail_readraw();
2300 END_PROFILE(SMBreadbraw);
2301 return(-1);
2304 CHECK_FSP(fsp,conn);
2306 flush_write_cache(fsp, READRAW_FLUSH);
2308 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2309 if(CVAL(inbuf,smb_wct) == 10) {
2311 * This is a large offset (64 bit) read.
2313 #ifdef LARGE_SMB_OFF_T
2315 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2317 #else /* !LARGE_SMB_OFF_T */
2320 * Ensure we haven't been sent a >32 bit offset.
2323 if(IVAL(inbuf,smb_vwv8) != 0) {
2324 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2325 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2326 _smb_setlen(header,0);
2327 if (write_data(smbd_server_fd(),header,4) != 4)
2328 fail_readraw();
2329 END_PROFILE(SMBreadbraw);
2330 return(-1);
2333 #endif /* LARGE_SMB_OFF_T */
2335 if(startpos < 0) {
2336 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2337 _smb_setlen(header,0);
2338 if (write_data(smbd_server_fd(),header,4) != 4)
2339 fail_readraw();
2340 END_PROFILE(SMBreadbraw);
2341 return(-1);
2344 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2345 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2347 /* ensure we don't overrun the packet size */
2348 maxcount = MIN(65535,maxcount);
2350 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2351 SMB_STRUCT_STAT st;
2352 SMB_OFF_T size = 0;
2354 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2355 size = st.st_size;
2358 if (startpos >= size) {
2359 nread = 0;
2360 } else {
2361 nread = MIN(maxcount,(size - startpos));
2365 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2366 if (nread < mincount)
2367 nread = 0;
2368 #endif
2370 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2371 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2373 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2375 DEBUG(5,("readbraw finished\n"));
2376 END_PROFILE(SMBreadbraw);
2377 return -1;
2380 #undef DBGC_CLASS
2381 #define DBGC_CLASS DBGC_LOCKING
2383 /****************************************************************************
2384 Reply to a lockread (core+ protocol).
2385 ****************************************************************************/
2387 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2389 ssize_t nread = -1;
2390 char *data;
2391 int outsize = 0;
2392 SMB_OFF_T startpos;
2393 size_t numtoread;
2394 NTSTATUS status;
2395 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2396 struct byte_range_lock *br_lck = NULL;
2397 START_PROFILE(SMBlockread);
2399 CHECK_FSP(fsp,conn);
2400 if (!CHECK_READ(fsp,inbuf)) {
2401 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2404 release_level_2_oplocks_on_change(fsp);
2406 numtoread = SVAL(inbuf,smb_vwv1);
2407 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2409 outsize = set_message(outbuf,5,3,True);
2410 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2411 data = smb_buf(outbuf) + 3;
2414 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2415 * protocol request that predates the read/write lock concept.
2416 * Thus instead of asking for a read lock here we need to ask
2417 * for a write lock. JRA.
2418 * Note that the requested lock size is unaffected by max_recv.
2421 br_lck = do_lock(fsp,
2422 (uint32)SVAL(inbuf,smb_pid),
2423 (SMB_BIG_UINT)numtoread,
2424 (SMB_BIG_UINT)startpos,
2425 WRITE_LOCK,
2426 WINDOWS_LOCK,
2427 False, /* Non-blocking lock. */
2428 &status,
2429 NULL);
2430 TALLOC_FREE(br_lck);
2432 if (NT_STATUS_V(status)) {
2433 END_PROFILE(SMBlockread);
2434 return ERROR_NT(status);
2438 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2441 if (numtoread > max_recv) {
2442 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2443 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2444 (unsigned int)numtoread, (unsigned int)max_recv ));
2445 numtoread = MIN(numtoread,max_recv);
2447 nread = read_file(fsp,data,startpos,numtoread);
2449 if (nread < 0) {
2450 END_PROFILE(SMBlockread);
2451 return(UNIXERROR(ERRDOS,ERRnoaccess));
2454 outsize += nread;
2455 SSVAL(outbuf,smb_vwv0,nread);
2456 SSVAL(outbuf,smb_vwv5,nread+3);
2457 SSVAL(smb_buf(outbuf),1,nread);
2459 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2460 fsp->fnum, (int)numtoread, (int)nread));
2462 END_PROFILE(SMBlockread);
2463 return(outsize);
2466 #undef DBGC_CLASS
2467 #define DBGC_CLASS DBGC_ALL
2469 /****************************************************************************
2470 Reply to a read.
2471 ****************************************************************************/
2473 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2475 size_t numtoread;
2476 ssize_t nread = 0;
2477 char *data;
2478 SMB_OFF_T startpos;
2479 int outsize = 0;
2480 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2481 START_PROFILE(SMBread);
2483 CHECK_FSP(fsp,conn);
2484 if (!CHECK_READ(fsp,inbuf)) {
2485 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2488 numtoread = SVAL(inbuf,smb_vwv1);
2489 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2491 outsize = set_message(outbuf,5,3,True);
2492 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2494 * The requested read size cannot be greater than max_recv. JRA.
2496 if (numtoread > max_recv) {
2497 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2498 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2499 (unsigned int)numtoread, (unsigned int)max_recv ));
2500 numtoread = MIN(numtoread,max_recv);
2503 data = smb_buf(outbuf) + 3;
2505 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2506 END_PROFILE(SMBread);
2507 return ERROR_DOS(ERRDOS,ERRlock);
2510 if (numtoread > 0)
2511 nread = read_file(fsp,data,startpos,numtoread);
2513 if (nread < 0) {
2514 END_PROFILE(SMBread);
2515 return(UNIXERROR(ERRDOS,ERRnoaccess));
2518 outsize += nread;
2519 SSVAL(outbuf,smb_vwv0,nread);
2520 SSVAL(outbuf,smb_vwv5,nread+3);
2521 SCVAL(smb_buf(outbuf),0,1);
2522 SSVAL(smb_buf(outbuf),1,nread);
2524 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2525 fsp->fnum, (int)numtoread, (int)nread ) );
2527 END_PROFILE(SMBread);
2528 return(outsize);
2531 /****************************************************************************
2532 Reply to a read and X - possibly using sendfile.
2533 ****************************************************************************/
2535 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2536 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2538 int outsize = 0;
2539 ssize_t nread = -1;
2540 char *data = smb_buf(outbuf);
2542 #if defined(WITH_SENDFILE)
2544 * We can only use sendfile on a non-chained packet
2545 * but we can use on a non-oplocked file. tridge proved this
2546 * on a train in Germany :-). JRA.
2549 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2550 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2551 SMB_STRUCT_STAT sbuf;
2552 DATA_BLOB header;
2554 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2555 return(UNIXERROR(ERRDOS,ERRnoaccess));
2557 if (startpos > sbuf.st_size)
2558 goto normal_read;
2560 if (smb_maxcnt > (sbuf.st_size - startpos))
2561 smb_maxcnt = (sbuf.st_size - startpos);
2563 if (smb_maxcnt == 0)
2564 goto normal_read;
2567 * Set up the packet header before send. We
2568 * assume here the sendfile will work (get the
2569 * correct amount of data).
2572 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2573 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2574 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2575 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2576 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2577 SCVAL(outbuf,smb_vwv0,0xFF);
2578 set_message(outbuf,12,smb_maxcnt,False);
2579 header.data = (uint8 *)outbuf;
2580 header.length = data - outbuf;
2581 header.free = NULL;
2583 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2584 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2585 if (errno == ENOSYS) {
2586 goto normal_read;
2590 * Special hack for broken Linux with no working sendfile. If we
2591 * return EINTR we sent the header but not the rest of the data.
2592 * Fake this up by doing read/write calls.
2595 if (errno == EINTR) {
2596 /* Ensure we don't do this again. */
2597 set_use_sendfile(SNUM(conn), False);
2598 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2600 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2601 len_outbuf - (data-outbuf))) == -1) {
2602 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2603 fsp->fsp_name, strerror(errno) ));
2604 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2606 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2607 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2608 /* Returning -1 here means successful sendfile. */
2609 return -1;
2612 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2613 fsp->fsp_name, strerror(errno) ));
2614 exit_server_cleanly("send_file_readX sendfile failed");
2617 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2618 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2619 /* Returning -1 here means successful sendfile. */
2620 return -1;
2623 normal_read:
2625 #endif
2627 nread = read_file(fsp,data,startpos,smb_maxcnt);
2629 if (nread < 0) {
2630 return(UNIXERROR(ERRDOS,ERRnoaccess));
2633 outsize = set_message(outbuf,12,nread,False);
2634 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2635 SSVAL(outbuf,smb_vwv5,nread);
2636 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2637 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2638 SSVAL(smb_buf(outbuf),-2,nread);
2640 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2641 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2643 /* Returning the number of bytes we want to send back - including header. */
2644 return outsize;
2647 /****************************************************************************
2648 Reply to a read and X.
2649 ****************************************************************************/
2651 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2653 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2654 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2655 ssize_t nread = -1;
2656 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2657 #if 0
2658 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2659 #endif
2661 START_PROFILE(SMBreadX);
2663 /* If it's an IPC, pass off the pipe handler. */
2664 if (IS_IPC(conn)) {
2665 END_PROFILE(SMBreadX);
2666 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2669 CHECK_FSP(fsp,conn);
2670 if (!CHECK_READ(fsp,inbuf)) {
2671 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2674 set_message(outbuf,12,0,True);
2676 if (global_client_caps & CAP_LARGE_READX) {
2677 if (SVAL(inbuf,smb_vwv7) == 1) {
2678 smb_maxcnt |= (1<<16);
2680 if (smb_maxcnt > BUFFER_SIZE) {
2681 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2682 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2683 END_PROFILE(SMBreadX);
2684 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2688 if(CVAL(inbuf,smb_wct) == 12) {
2689 #ifdef LARGE_SMB_OFF_T
2691 * This is a large offset (64 bit) read.
2693 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2695 #else /* !LARGE_SMB_OFF_T */
2698 * Ensure we haven't been sent a >32 bit offset.
2701 if(IVAL(inbuf,smb_vwv10) != 0) {
2702 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2703 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2704 END_PROFILE(SMBreadX);
2705 return ERROR_DOS(ERRDOS,ERRbadaccess);
2708 #endif /* LARGE_SMB_OFF_T */
2712 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2713 END_PROFILE(SMBreadX);
2714 return ERROR_DOS(ERRDOS,ERRlock);
2717 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2718 END_PROFILE(SMBreadX);
2719 return -1;
2722 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2723 /* Only call chain_reply if not an error. */
2724 if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2725 nread = chain_reply(inbuf,outbuf,length,bufsize);
2728 END_PROFILE(SMBreadX);
2729 return nread;
2732 /****************************************************************************
2733 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2734 ****************************************************************************/
2736 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2738 ssize_t nwritten=0;
2739 ssize_t total_written=0;
2740 size_t numtowrite=0;
2741 size_t tcount;
2742 SMB_OFF_T startpos;
2743 char *data=NULL;
2744 BOOL write_through;
2745 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2746 int outsize = 0;
2747 NTSTATUS status;
2748 START_PROFILE(SMBwritebraw);
2750 if (srv_is_signing_active()) {
2751 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2754 CHECK_FSP(fsp,conn);
2755 if (!CHECK_WRITE(fsp)) {
2756 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2759 tcount = IVAL(inbuf,smb_vwv1);
2760 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2761 write_through = BITSETW(inbuf+smb_vwv7,0);
2763 /* We have to deal with slightly different formats depending
2764 on whether we are using the core+ or lanman1.0 protocol */
2766 if(Protocol <= PROTOCOL_COREPLUS) {
2767 numtowrite = SVAL(smb_buf(inbuf),-2);
2768 data = smb_buf(inbuf);
2769 } else {
2770 numtowrite = SVAL(inbuf,smb_vwv10);
2771 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2774 /* force the error type */
2775 SCVAL(inbuf,smb_com,SMBwritec);
2776 SCVAL(outbuf,smb_com,SMBwritec);
2778 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2779 END_PROFILE(SMBwritebraw);
2780 return(ERROR_DOS(ERRDOS,ERRlock));
2783 if (numtowrite>0)
2784 nwritten = write_file(fsp,data,startpos,numtowrite);
2786 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2787 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2789 if (nwritten < (ssize_t)numtowrite) {
2790 END_PROFILE(SMBwritebraw);
2791 return(UNIXERROR(ERRHRD,ERRdiskfull));
2794 total_written = nwritten;
2796 /* Return a message to the redirector to tell it to send more bytes */
2797 SCVAL(outbuf,smb_com,SMBwritebraw);
2798 SSVALS(outbuf,smb_vwv0,-1);
2799 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2800 show_msg(outbuf);
2801 if (!send_smb(smbd_server_fd(),outbuf))
2802 exit_server_cleanly("reply_writebraw: send_smb failed.");
2804 /* Now read the raw data into the buffer and write it */
2805 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2806 exit_server_cleanly("secondary writebraw failed");
2809 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2810 numtowrite = smb_len(inbuf);
2812 /* Set up outbuf to return the correct return */
2813 outsize = set_message(outbuf,1,0,True);
2814 SCVAL(outbuf,smb_com,SMBwritec);
2816 if (numtowrite != 0) {
2818 if (numtowrite > BUFFER_SIZE) {
2819 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2820 (unsigned int)numtowrite ));
2821 exit_server_cleanly("secondary writebraw failed");
2824 if (tcount > nwritten+numtowrite) {
2825 DEBUG(3,("Client overestimated the write %d %d %d\n",
2826 (int)tcount,(int)nwritten,(int)numtowrite));
2829 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2830 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2831 strerror(errno) ));
2832 exit_server_cleanly("secondary writebraw failed");
2835 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2836 if (nwritten == -1) {
2837 END_PROFILE(SMBwritebraw);
2838 return(UNIXERROR(ERRHRD,ERRdiskfull));
2841 if (nwritten < (ssize_t)numtowrite) {
2842 SCVAL(outbuf,smb_rcls,ERRHRD);
2843 SSVAL(outbuf,smb_err,ERRdiskfull);
2846 if (nwritten > 0)
2847 total_written += nwritten;
2850 SSVAL(outbuf,smb_vwv0,total_written);
2852 status = sync_file(conn, fsp, write_through);
2853 if (!NT_STATUS_IS_OK(status)) {
2854 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
2855 fsp->fsp_name, nt_errstr(status) ));
2856 END_PROFILE(SMBwritebraw);
2857 return ERROR_NT(status);
2860 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2861 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2863 /* we won't return a status if write through is not selected - this follows what WfWg does */
2864 END_PROFILE(SMBwritebraw);
2865 if (!write_through && total_written==tcount) {
2867 #if RABBIT_PELLET_FIX
2869 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2870 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2872 if (!send_keepalive(smbd_server_fd()))
2873 exit_server_cleanly("reply_writebraw: send of keepalive failed");
2874 #endif
2875 return(-1);
2878 return(outsize);
2881 #undef DBGC_CLASS
2882 #define DBGC_CLASS DBGC_LOCKING
2884 /****************************************************************************
2885 Reply to a writeunlock (core+).
2886 ****************************************************************************/
2888 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2889 int size, int dum_buffsize)
2891 ssize_t nwritten = -1;
2892 size_t numtowrite;
2893 SMB_OFF_T startpos;
2894 char *data;
2895 NTSTATUS status = NT_STATUS_OK;
2896 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2897 int outsize = 0;
2898 START_PROFILE(SMBwriteunlock);
2900 CHECK_FSP(fsp,conn);
2901 if (!CHECK_WRITE(fsp)) {
2902 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2905 numtowrite = SVAL(inbuf,smb_vwv1);
2906 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2907 data = smb_buf(inbuf) + 3;
2909 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2910 END_PROFILE(SMBwriteunlock);
2911 return ERROR_DOS(ERRDOS,ERRlock);
2914 /* The special X/Open SMB protocol handling of
2915 zero length writes is *NOT* done for
2916 this call */
2917 if(numtowrite == 0) {
2918 nwritten = 0;
2919 } else {
2920 nwritten = write_file(fsp,data,startpos,numtowrite);
2923 status = sync_file(conn, fsp, False /* write through */);
2924 if (!NT_STATUS_IS_OK(status)) {
2925 END_PROFILE(SMBwriteunlock);
2926 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
2927 fsp->fsp_name, nt_errstr(status) ));
2928 return ERROR_NT(status);
2931 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2932 END_PROFILE(SMBwriteunlock);
2933 return(UNIXERROR(ERRHRD,ERRdiskfull));
2936 if (numtowrite) {
2937 status = do_unlock(fsp,
2938 (uint32)SVAL(inbuf,smb_pid),
2939 (SMB_BIG_UINT)numtowrite,
2940 (SMB_BIG_UINT)startpos,
2941 WINDOWS_LOCK);
2943 if (NT_STATUS_V(status)) {
2944 END_PROFILE(SMBwriteunlock);
2945 return ERROR_NT(status);
2949 outsize = set_message(outbuf,1,0,True);
2951 SSVAL(outbuf,smb_vwv0,nwritten);
2953 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2954 fsp->fnum, (int)numtowrite, (int)nwritten));
2956 END_PROFILE(SMBwriteunlock);
2957 return outsize;
2960 #undef DBGC_CLASS
2961 #define DBGC_CLASS DBGC_ALL
2963 /****************************************************************************
2964 Reply to a write.
2965 ****************************************************************************/
2967 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2969 size_t numtowrite;
2970 ssize_t nwritten = -1;
2971 SMB_OFF_T startpos;
2972 char *data;
2973 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2974 int outsize = 0;
2975 NTSTATUS status;
2976 START_PROFILE(SMBwrite);
2978 /* If it's an IPC, pass off the pipe handler. */
2979 if (IS_IPC(conn)) {
2980 END_PROFILE(SMBwrite);
2981 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2984 CHECK_FSP(fsp,conn);
2985 if (!CHECK_WRITE(fsp)) {
2986 END_PROFILE(SMBwrite);
2987 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2990 numtowrite = SVAL(inbuf,smb_vwv1);
2991 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2992 data = smb_buf(inbuf) + 3;
2994 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2995 END_PROFILE(SMBwrite);
2996 return ERROR_DOS(ERRDOS,ERRlock);
3000 * X/Open SMB protocol says that if smb_vwv1 is
3001 * zero then the file size should be extended or
3002 * truncated to the size given in smb_vwv[2-3].
3005 if(numtowrite == 0) {
3007 * This is actually an allocate call, and set EOF. JRA.
3009 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3010 if (nwritten < 0) {
3011 END_PROFILE(SMBwrite);
3012 return ERROR_NT(NT_STATUS_DISK_FULL);
3014 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3015 if (nwritten < 0) {
3016 END_PROFILE(SMBwrite);
3017 return ERROR_NT(NT_STATUS_DISK_FULL);
3019 } else
3020 nwritten = write_file(fsp,data,startpos,numtowrite);
3022 status = sync_file(conn, fsp, False);
3023 if (!NT_STATUS_IS_OK(status)) {
3024 END_PROFILE(SMBwrite);
3025 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3026 fsp->fsp_name, nt_errstr(status) ));
3027 return ERROR_NT(status);
3030 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3031 END_PROFILE(SMBwrite);
3032 return(UNIXERROR(ERRHRD,ERRdiskfull));
3035 outsize = set_message(outbuf,1,0,True);
3037 SSVAL(outbuf,smb_vwv0,nwritten);
3039 if (nwritten < (ssize_t)numtowrite) {
3040 SCVAL(outbuf,smb_rcls,ERRHRD);
3041 SSVAL(outbuf,smb_err,ERRdiskfull);
3044 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3046 END_PROFILE(SMBwrite);
3047 return(outsize);
3050 /****************************************************************************
3051 Reply to a write and X.
3052 ****************************************************************************/
3054 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3056 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3057 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3058 size_t numtowrite = SVAL(inbuf,smb_vwv10);
3059 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3060 ssize_t nwritten = -1;
3061 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3062 unsigned int smblen = smb_len(inbuf);
3063 char *data;
3064 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3065 NTSTATUS status;
3066 START_PROFILE(SMBwriteX);
3068 /* If it's an IPC, pass off the pipe handler. */
3069 if (IS_IPC(conn)) {
3070 END_PROFILE(SMBwriteX);
3071 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3074 CHECK_FSP(fsp,conn);
3075 if (!CHECK_WRITE(fsp)) {
3076 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3079 set_message(outbuf,6,0,True);
3081 /* Deal with possible LARGE_WRITEX */
3082 if (large_writeX) {
3083 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3086 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3087 END_PROFILE(SMBwriteX);
3088 return ERROR_DOS(ERRDOS,ERRbadmem);
3091 data = smb_base(inbuf) + smb_doff;
3093 if(CVAL(inbuf,smb_wct) == 14) {
3094 #ifdef LARGE_SMB_OFF_T
3096 * This is a large offset (64 bit) write.
3098 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3100 #else /* !LARGE_SMB_OFF_T */
3103 * Ensure we haven't been sent a >32 bit offset.
3106 if(IVAL(inbuf,smb_vwv12) != 0) {
3107 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3108 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3109 END_PROFILE(SMBwriteX);
3110 return ERROR_DOS(ERRDOS,ERRbadaccess);
3113 #endif /* LARGE_SMB_OFF_T */
3116 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3117 END_PROFILE(SMBwriteX);
3118 return ERROR_DOS(ERRDOS,ERRlock);
3121 /* X/Open SMB protocol says that, unlike SMBwrite
3122 if the length is zero then NO truncation is
3123 done, just a write of zero. To truncate a file,
3124 use SMBwrite. */
3126 if(numtowrite == 0) {
3127 nwritten = 0;
3128 } else {
3130 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3131 fsp,data,startpos,numtowrite)) {
3132 END_PROFILE(SMBwriteX);
3133 return -1;
3136 nwritten = write_file(fsp,data,startpos,numtowrite);
3139 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3140 END_PROFILE(SMBwriteX);
3141 return(UNIXERROR(ERRHRD,ERRdiskfull));
3144 SSVAL(outbuf,smb_vwv2,nwritten);
3145 if (large_writeX)
3146 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3148 if (nwritten < (ssize_t)numtowrite) {
3149 SCVAL(outbuf,smb_rcls,ERRHRD);
3150 SSVAL(outbuf,smb_err,ERRdiskfull);
3153 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3154 fsp->fnum, (int)numtowrite, (int)nwritten));
3156 status = sync_file(conn, fsp, write_through);
3157 if (!NT_STATUS_IS_OK(status)) {
3158 END_PROFILE(SMBwriteX);
3159 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3160 fsp->fsp_name, nt_errstr(status) ));
3161 return ERROR_NT(status);
3164 END_PROFILE(SMBwriteX);
3165 return chain_reply(inbuf,outbuf,length,bufsize);
3168 /****************************************************************************
3169 Reply to a lseek.
3170 ****************************************************************************/
3172 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3174 SMB_OFF_T startpos;
3175 SMB_OFF_T res= -1;
3176 int mode,umode;
3177 int outsize = 0;
3178 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3179 START_PROFILE(SMBlseek);
3181 CHECK_FSP(fsp,conn);
3183 flush_write_cache(fsp, SEEK_FLUSH);
3185 mode = SVAL(inbuf,smb_vwv1) & 3;
3186 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3187 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3189 switch (mode) {
3190 case 0:
3191 umode = SEEK_SET;
3192 res = startpos;
3193 break;
3194 case 1:
3195 umode = SEEK_CUR;
3196 res = fsp->fh->pos + startpos;
3197 break;
3198 case 2:
3199 umode = SEEK_END;
3200 break;
3201 default:
3202 umode = SEEK_SET;
3203 res = startpos;
3204 break;
3207 if (umode == SEEK_END) {
3208 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3209 if(errno == EINVAL) {
3210 SMB_OFF_T current_pos = startpos;
3211 SMB_STRUCT_STAT sbuf;
3213 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3214 END_PROFILE(SMBlseek);
3215 return(UNIXERROR(ERRDOS,ERRnoaccess));
3218 current_pos += sbuf.st_size;
3219 if(current_pos < 0)
3220 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3224 if(res == -1) {
3225 END_PROFILE(SMBlseek);
3226 return(UNIXERROR(ERRDOS,ERRnoaccess));
3230 fsp->fh->pos = res;
3232 outsize = set_message(outbuf,2,0,True);
3233 SIVAL(outbuf,smb_vwv0,res);
3235 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3236 fsp->fnum, (double)startpos, (double)res, mode));
3238 END_PROFILE(SMBlseek);
3239 return(outsize);
3242 /****************************************************************************
3243 Reply to a flush.
3244 ****************************************************************************/
3246 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3248 int outsize = set_message(outbuf,0,0,False);
3249 uint16 fnum = SVAL(inbuf,smb_vwv0);
3250 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3251 START_PROFILE(SMBflush);
3253 if (fnum != 0xFFFF)
3254 CHECK_FSP(fsp,conn);
3256 if (!fsp) {
3257 file_sync_all(conn);
3258 } else {
3259 NTSTATUS status = sync_file(conn, fsp, True);
3260 if (!NT_STATUS_IS_OK(status)) {
3261 END_PROFILE(SMBflush);
3262 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3263 fsp->fsp_name, nt_errstr(status) ));
3264 return ERROR_NT(status);
3268 DEBUG(3,("flush\n"));
3269 END_PROFILE(SMBflush);
3270 return(outsize);
3273 /****************************************************************************
3274 Reply to a exit.
3275 conn POINTER CAN BE NULL HERE !
3276 ****************************************************************************/
3278 int reply_exit(connection_struct *conn,
3279 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3281 int outsize;
3282 START_PROFILE(SMBexit);
3284 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3286 outsize = set_message(outbuf,0,0,False);
3288 DEBUG(3,("exit\n"));
3290 END_PROFILE(SMBexit);
3291 return(outsize);
3294 /****************************************************************************
3295 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3296 ****************************************************************************/
3298 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3299 int dum_buffsize)
3301 NTSTATUS status = NT_STATUS_OK;
3302 int outsize = 0;
3303 files_struct *fsp = NULL;
3304 START_PROFILE(SMBclose);
3306 outsize = set_message(outbuf,0,0,False);
3308 /* If it's an IPC, pass off to the pipe handler. */
3309 if (IS_IPC(conn)) {
3310 END_PROFILE(SMBclose);
3311 return reply_pipe_close(conn, inbuf,outbuf);
3314 fsp = file_fsp(inbuf,smb_vwv0);
3317 * We can only use CHECK_FSP if we know it's not a directory.
3320 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3321 END_PROFILE(SMBclose);
3322 return ERROR_DOS(ERRDOS,ERRbadfid);
3325 if(fsp->is_directory) {
3327 * Special case - close NT SMB directory handle.
3329 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3330 status = close_file(fsp,NORMAL_CLOSE);
3331 } else {
3333 * Close ordinary file.
3336 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3337 fsp->fh->fd, fsp->fnum,
3338 conn->num_files_open));
3341 * Take care of any time sent in the close.
3344 fsp_set_pending_modtime(fsp,
3345 convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
3348 * close_file() returns the unix errno if an error
3349 * was detected on close - normally this is due to
3350 * a disk full error. If not then it was probably an I/O error.
3353 status = close_file(fsp,NORMAL_CLOSE);
3356 if(!NT_STATUS_IS_OK(status)) {
3357 END_PROFILE(SMBclose);
3358 return ERROR_NT(status);
3361 END_PROFILE(SMBclose);
3362 return(outsize);
3365 /****************************************************************************
3366 Reply to a writeclose (Core+ protocol).
3367 ****************************************************************************/
3369 int reply_writeclose(connection_struct *conn,
3370 char *inbuf,char *outbuf, int size, int dum_buffsize)
3372 size_t numtowrite;
3373 ssize_t nwritten = -1;
3374 int outsize = 0;
3375 NTSTATUS close_status = NT_STATUS_OK;
3376 SMB_OFF_T startpos;
3377 char *data;
3378 struct timespec mtime;
3379 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3380 START_PROFILE(SMBwriteclose);
3382 CHECK_FSP(fsp,conn);
3383 if (!CHECK_WRITE(fsp)) {
3384 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3387 numtowrite = SVAL(inbuf,smb_vwv1);
3388 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3389 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3390 data = smb_buf(inbuf) + 1;
3392 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3393 END_PROFILE(SMBwriteclose);
3394 return ERROR_DOS(ERRDOS,ERRlock);
3397 nwritten = write_file(fsp,data,startpos,numtowrite);
3399 set_filetime(conn, fsp->fsp_name, mtime);
3402 * More insanity. W2K only closes the file if writelen > 0.
3403 * JRA.
3406 if (numtowrite) {
3407 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3408 fsp->fsp_name ));
3409 close_status = close_file(fsp,NORMAL_CLOSE);
3412 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3413 fsp->fnum, (int)numtowrite, (int)nwritten,
3414 conn->num_files_open));
3416 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3417 END_PROFILE(SMBwriteclose);
3418 return(UNIXERROR(ERRHRD,ERRdiskfull));
3421 if(!NT_STATUS_IS_OK(close_status)) {
3422 END_PROFILE(SMBwriteclose);
3423 return ERROR_NT(close_status);
3426 outsize = set_message(outbuf,1,0,True);
3428 SSVAL(outbuf,smb_vwv0,nwritten);
3429 END_PROFILE(SMBwriteclose);
3430 return(outsize);
3433 #undef DBGC_CLASS
3434 #define DBGC_CLASS DBGC_LOCKING
3436 /****************************************************************************
3437 Reply to a lock.
3438 ****************************************************************************/
3440 int reply_lock(connection_struct *conn,
3441 char *inbuf,char *outbuf, int length, int dum_buffsize)
3443 int outsize = set_message(outbuf,0,0,False);
3444 SMB_BIG_UINT count,offset;
3445 NTSTATUS status;
3446 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3447 struct byte_range_lock *br_lck = NULL;
3449 START_PROFILE(SMBlock);
3451 CHECK_FSP(fsp,conn);
3453 release_level_2_oplocks_on_change(fsp);
3455 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3456 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3458 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3459 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3461 br_lck = do_lock(fsp,
3462 (uint32)SVAL(inbuf,smb_pid),
3463 count,
3464 offset,
3465 WRITE_LOCK,
3466 WINDOWS_LOCK,
3467 False, /* Non-blocking lock. */
3468 &status,
3469 NULL);
3471 TALLOC_FREE(br_lck);
3473 if (NT_STATUS_V(status)) {
3474 END_PROFILE(SMBlock);
3475 return ERROR_NT(status);
3478 END_PROFILE(SMBlock);
3479 return(outsize);
3482 /****************************************************************************
3483 Reply to a unlock.
3484 ****************************************************************************/
3486 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3487 int dum_buffsize)
3489 int outsize = set_message(outbuf,0,0,False);
3490 SMB_BIG_UINT count,offset;
3491 NTSTATUS status;
3492 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3493 START_PROFILE(SMBunlock);
3495 CHECK_FSP(fsp,conn);
3497 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3498 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3500 status = do_unlock(fsp,
3501 (uint32)SVAL(inbuf,smb_pid),
3502 count,
3503 offset,
3504 WINDOWS_LOCK);
3506 if (NT_STATUS_V(status)) {
3507 END_PROFILE(SMBunlock);
3508 return ERROR_NT(status);
3511 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3512 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3514 END_PROFILE(SMBunlock);
3515 return(outsize);
3518 #undef DBGC_CLASS
3519 #define DBGC_CLASS DBGC_ALL
3521 /****************************************************************************
3522 Reply to a tdis.
3523 conn POINTER CAN BE NULL HERE !
3524 ****************************************************************************/
3526 int reply_tdis(connection_struct *conn,
3527 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3529 int outsize = set_message(outbuf,0,0,False);
3530 uint16 vuid;
3531 START_PROFILE(SMBtdis);
3533 vuid = SVAL(inbuf,smb_uid);
3535 if (!conn) {
3536 DEBUG(4,("Invalid connection in tdis\n"));
3537 END_PROFILE(SMBtdis);
3538 return ERROR_DOS(ERRSRV,ERRinvnid);
3541 conn->used = False;
3543 close_cnum(conn,vuid);
3545 END_PROFILE(SMBtdis);
3546 return outsize;
3549 /****************************************************************************
3550 Reply to a echo.
3551 conn POINTER CAN BE NULL HERE !
3552 ****************************************************************************/
3554 int reply_echo(connection_struct *conn,
3555 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3557 int smb_reverb = SVAL(inbuf,smb_vwv0);
3558 int seq_num;
3559 unsigned int data_len = smb_buflen(inbuf);
3560 int outsize = set_message(outbuf,1,data_len,True);
3561 START_PROFILE(SMBecho);
3563 if (data_len > BUFFER_SIZE) {
3564 DEBUG(0,("reply_echo: data_len too large.\n"));
3565 END_PROFILE(SMBecho);
3566 return -1;
3569 /* copy any incoming data back out */
3570 if (data_len > 0)
3571 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3573 if (smb_reverb > 100) {
3574 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3575 smb_reverb = 100;
3578 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3579 SSVAL(outbuf,smb_vwv0,seq_num);
3581 smb_setlen(outbuf,outsize - 4);
3583 show_msg(outbuf);
3584 if (!send_smb(smbd_server_fd(),outbuf))
3585 exit_server_cleanly("reply_echo: send_smb failed.");
3588 DEBUG(3,("echo %d times\n", smb_reverb));
3590 smb_echo_count++;
3592 END_PROFILE(SMBecho);
3593 return -1;
3596 /****************************************************************************
3597 Reply to a printopen.
3598 ****************************************************************************/
3600 int reply_printopen(connection_struct *conn,
3601 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3603 int outsize = 0;
3604 files_struct *fsp;
3605 NTSTATUS status;
3607 START_PROFILE(SMBsplopen);
3609 if (!CAN_PRINT(conn)) {
3610 END_PROFILE(SMBsplopen);
3611 return ERROR_DOS(ERRDOS,ERRnoaccess);
3614 /* Open for exclusive use, write only. */
3615 status = print_fsp_open(conn, NULL, &fsp);
3617 if (!NT_STATUS_IS_OK(status)) {
3618 END_PROFILE(SMBsplopen);
3619 return(ERROR_NT(status));
3622 outsize = set_message(outbuf,1,0,True);
3623 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3625 DEBUG(3,("openprint fd=%d fnum=%d\n",
3626 fsp->fh->fd, fsp->fnum));
3628 END_PROFILE(SMBsplopen);
3629 return(outsize);
3632 /****************************************************************************
3633 Reply to a printclose.
3634 ****************************************************************************/
3636 int reply_printclose(connection_struct *conn,
3637 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3639 int outsize = set_message(outbuf,0,0,False);
3640 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3641 NTSTATUS status;
3642 START_PROFILE(SMBsplclose);
3644 CHECK_FSP(fsp,conn);
3646 if (!CAN_PRINT(conn)) {
3647 END_PROFILE(SMBsplclose);
3648 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3651 DEBUG(3,("printclose fd=%d fnum=%d\n",
3652 fsp->fh->fd,fsp->fnum));
3654 status = close_file(fsp,NORMAL_CLOSE);
3656 if(!NT_STATUS_IS_OK(status)) {
3657 END_PROFILE(SMBsplclose);
3658 return ERROR_NT(status);
3661 END_PROFILE(SMBsplclose);
3662 return(outsize);
3665 /****************************************************************************
3666 Reply to a printqueue.
3667 ****************************************************************************/
3669 int reply_printqueue(connection_struct *conn,
3670 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3672 int outsize = set_message(outbuf,2,3,True);
3673 int max_count = SVAL(inbuf,smb_vwv0);
3674 int start_index = SVAL(inbuf,smb_vwv1);
3675 START_PROFILE(SMBsplretq);
3677 /* we used to allow the client to get the cnum wrong, but that
3678 is really quite gross and only worked when there was only
3679 one printer - I think we should now only accept it if they
3680 get it right (tridge) */
3681 if (!CAN_PRINT(conn)) {
3682 END_PROFILE(SMBsplretq);
3683 return ERROR_DOS(ERRDOS,ERRnoaccess);
3686 SSVAL(outbuf,smb_vwv0,0);
3687 SSVAL(outbuf,smb_vwv1,0);
3688 SCVAL(smb_buf(outbuf),0,1);
3689 SSVAL(smb_buf(outbuf),1,0);
3691 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3692 start_index, max_count));
3695 print_queue_struct *queue = NULL;
3696 print_status_struct status;
3697 char *p = smb_buf(outbuf) + 3;
3698 int count = print_queue_status(SNUM(conn), &queue, &status);
3699 int num_to_get = ABS(max_count);
3700 int first = (max_count>0?start_index:start_index+max_count+1);
3701 int i;
3703 if (first >= count)
3704 num_to_get = 0;
3705 else
3706 num_to_get = MIN(num_to_get,count-first);
3709 for (i=first;i<first+num_to_get;i++) {
3710 srv_put_dos_date2(p,0,queue[i].time);
3711 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3712 SSVAL(p,5, queue[i].job);
3713 SIVAL(p,7,queue[i].size);
3714 SCVAL(p,11,0);
3715 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3716 p += 28;
3719 if (count > 0) {
3720 outsize = set_message(outbuf,2,28*count+3,False);
3721 SSVAL(outbuf,smb_vwv0,count);
3722 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3723 SCVAL(smb_buf(outbuf),0,1);
3724 SSVAL(smb_buf(outbuf),1,28*count);
3727 SAFE_FREE(queue);
3729 DEBUG(3,("%d entries returned in queue\n",count));
3732 END_PROFILE(SMBsplretq);
3733 return(outsize);
3736 /****************************************************************************
3737 Reply to a printwrite.
3738 ****************************************************************************/
3740 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3742 int numtowrite;
3743 int outsize = set_message(outbuf,0,0,False);
3744 char *data;
3745 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3747 START_PROFILE(SMBsplwr);
3749 if (!CAN_PRINT(conn)) {
3750 END_PROFILE(SMBsplwr);
3751 return ERROR_DOS(ERRDOS,ERRnoaccess);
3754 CHECK_FSP(fsp,conn);
3755 if (!CHECK_WRITE(fsp)) {
3756 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3759 numtowrite = SVAL(smb_buf(inbuf),1);
3760 data = smb_buf(inbuf) + 3;
3762 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3763 END_PROFILE(SMBsplwr);
3764 return(UNIXERROR(ERRHRD,ERRdiskfull));
3767 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3769 END_PROFILE(SMBsplwr);
3770 return(outsize);
3773 /****************************************************************************
3774 Reply to a mkdir.
3775 ****************************************************************************/
3777 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3779 pstring directory;
3780 int outsize;
3781 NTSTATUS status;
3782 SMB_STRUCT_STAT sbuf;
3784 START_PROFILE(SMBmkdir);
3786 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3787 if (!NT_STATUS_IS_OK(status)) {
3788 END_PROFILE(SMBmkdir);
3789 return ERROR_NT(status);
3792 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
3793 if (!NT_STATUS_IS_OK(status)) {
3794 END_PROFILE(SMBmkdir);
3795 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3796 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3798 return ERROR_NT(status);
3801 status = unix_convert(conn, directory, False, NULL, &sbuf);
3802 if (!NT_STATUS_IS_OK(status)) {
3803 END_PROFILE(SMBmkdir);
3804 return ERROR_NT(status);
3807 status = check_name(conn, directory);
3808 if (!NT_STATUS_IS_OK(status)) {
3809 END_PROFILE(SMBmkdir);
3810 return ERROR_NT(status);
3813 status = create_directory(conn, directory);
3815 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3817 if (!NT_STATUS_IS_OK(status)) {
3819 if (!use_nt_status()
3820 && NT_STATUS_EQUAL(status,
3821 NT_STATUS_OBJECT_NAME_COLLISION)) {
3823 * Yes, in the DOS error code case we get a
3824 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3825 * samba4 torture test.
3827 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3830 END_PROFILE(SMBmkdir);
3831 return ERROR_NT(status);
3834 outsize = set_message(outbuf,0,0,False);
3836 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3838 END_PROFILE(SMBmkdir);
3839 return(outsize);
3842 /****************************************************************************
3843 Static function used by reply_rmdir to delete an entire directory
3844 tree recursively. Return True on ok, False on fail.
3845 ****************************************************************************/
3847 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3849 const char *dname = NULL;
3850 BOOL ret = True;
3851 long offset = 0;
3852 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3854 if(dir_hnd == NULL)
3855 return False;
3857 while((dname = ReadDirName(dir_hnd, &offset))) {
3858 pstring fullname;
3859 SMB_STRUCT_STAT st;
3861 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3862 continue;
3864 if (!is_visible_file(conn, directory, dname, &st, False))
3865 continue;
3867 /* Construct the full name. */
3868 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3869 errno = ENOMEM;
3870 ret = False;
3871 break;
3874 pstrcpy(fullname, directory);
3875 pstrcat(fullname, "/");
3876 pstrcat(fullname, dname);
3878 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3879 ret = False;
3880 break;
3883 if(st.st_mode & S_IFDIR) {
3884 if(!recursive_rmdir(conn, fullname)) {
3885 ret = False;
3886 break;
3888 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3889 ret = False;
3890 break;
3892 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3893 ret = False;
3894 break;
3897 CloseDir(dir_hnd);
3898 return ret;
3901 /****************************************************************************
3902 The internals of the rmdir code - called elsewhere.
3903 ****************************************************************************/
3905 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
3907 int ret;
3908 SMB_STRUCT_STAT st;
3910 /* Might be a symlink. */
3911 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
3912 return map_nt_error_from_unix(errno);
3915 if (S_ISLNK(st.st_mode)) {
3916 /* Is what it points to a directory ? */
3917 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
3918 return map_nt_error_from_unix(errno);
3920 if (!(S_ISDIR(st.st_mode))) {
3921 return NT_STATUS_NOT_A_DIRECTORY;
3923 ret = SMB_VFS_UNLINK(conn,directory);
3924 } else {
3925 ret = SMB_VFS_RMDIR(conn,directory);
3927 if (ret == 0) {
3928 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3929 FILE_NOTIFY_CHANGE_DIR_NAME,
3930 directory);
3931 return NT_STATUS_OK;
3934 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3936 * Check to see if the only thing in this directory are
3937 * vetoed files/directories. If so then delete them and
3938 * retry. If we fail to delete any of them (and we *don't*
3939 * do a recursive delete) then fail the rmdir.
3941 const char *dname;
3942 long dirpos = 0;
3943 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3945 if(dir_hnd == NULL) {
3946 errno = ENOTEMPTY;
3947 goto err;
3950 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3951 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3952 continue;
3953 if (!is_visible_file(conn, directory, dname, &st, False))
3954 continue;
3955 if(!IS_VETO_PATH(conn, dname)) {
3956 CloseDir(dir_hnd);
3957 errno = ENOTEMPTY;
3958 goto err;
3962 /* We only have veto files/directories. Recursive delete. */
3964 RewindDir(dir_hnd,&dirpos);
3965 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3966 pstring fullname;
3968 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3969 continue;
3970 if (!is_visible_file(conn, directory, dname, &st, False))
3971 continue;
3973 /* Construct the full name. */
3974 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3975 errno = ENOMEM;
3976 break;
3979 pstrcpy(fullname, directory);
3980 pstrcat(fullname, "/");
3981 pstrcat(fullname, dname);
3983 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3984 break;
3985 if(st.st_mode & S_IFDIR) {
3986 if(lp_recursive_veto_delete(SNUM(conn))) {
3987 if(!recursive_rmdir(conn, fullname))
3988 break;
3990 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3991 break;
3992 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3993 break;
3995 CloseDir(dir_hnd);
3996 /* Retry the rmdir */
3997 ret = SMB_VFS_RMDIR(conn,directory);
4000 err:
4002 if (ret != 0) {
4003 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4004 "%s\n", directory,strerror(errno)));
4005 return map_nt_error_from_unix(errno);
4008 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4009 FILE_NOTIFY_CHANGE_DIR_NAME,
4010 directory);
4012 return NT_STATUS_OK;
4015 /****************************************************************************
4016 Reply to a rmdir.
4017 ****************************************************************************/
4019 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4021 pstring directory;
4022 int outsize = 0;
4023 SMB_STRUCT_STAT sbuf;
4024 NTSTATUS status;
4025 START_PROFILE(SMBrmdir);
4027 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
4028 if (!NT_STATUS_IS_OK(status)) {
4029 END_PROFILE(SMBrmdir);
4030 return ERROR_NT(status);
4033 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
4034 if (!NT_STATUS_IS_OK(status)) {
4035 END_PROFILE(SMBrmdir);
4036 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4037 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4039 return ERROR_NT(status);
4042 status = unix_convert(conn, directory, False, NULL, &sbuf);
4043 if (!NT_STATUS_IS_OK(status)) {
4044 END_PROFILE(SMBrmdir);
4045 return ERROR_NT(status);
4048 status = check_name(conn, directory);
4049 if (!NT_STATUS_IS_OK(status)) {
4050 END_PROFILE(SMBrmdir);
4051 return ERROR_NT(status);
4054 dptr_closepath(directory,SVAL(inbuf,smb_pid));
4055 status = rmdir_internals(conn, directory);
4056 if (!NT_STATUS_IS_OK(status)) {
4057 END_PROFILE(SMBrmdir);
4058 return ERROR_NT(status);
4061 outsize = set_message(outbuf,0,0,False);
4063 DEBUG( 3, ( "rmdir %s\n", directory ) );
4065 END_PROFILE(SMBrmdir);
4066 return(outsize);
4069 /*******************************************************************
4070 Resolve wildcards in a filename rename.
4071 Note that name is in UNIX charset and thus potentially can be more
4072 than fstring buffer (255 bytes) especially in default UTF-8 case.
4073 Therefore, we use pstring inside and all calls should ensure that
4074 name2 is at least pstring-long (they do already)
4075 ********************************************************************/
4077 static BOOL resolve_wildcards(const char *name1, char *name2)
4079 pstring root1,root2;
4080 pstring ext1,ext2;
4081 char *p,*p2, *pname1, *pname2;
4082 int available_space, actual_space;
4084 pname1 = strrchr_m(name1,'/');
4085 pname2 = strrchr_m(name2,'/');
4087 if (!pname1 || !pname2)
4088 return(False);
4090 pstrcpy(root1,pname1);
4091 pstrcpy(root2,pname2);
4092 p = strrchr_m(root1,'.');
4093 if (p) {
4094 *p = 0;
4095 pstrcpy(ext1,p+1);
4096 } else {
4097 pstrcpy(ext1,"");
4099 p = strrchr_m(root2,'.');
4100 if (p) {
4101 *p = 0;
4102 pstrcpy(ext2,p+1);
4103 } else {
4104 pstrcpy(ext2,"");
4107 p = root1;
4108 p2 = root2;
4109 while (*p2) {
4110 if (*p2 == '?') {
4111 *p2 = *p;
4112 p2++;
4113 } else if (*p2 == '*') {
4114 pstrcpy(p2, p);
4115 break;
4116 } else {
4117 p2++;
4119 if (*p)
4120 p++;
4123 p = ext1;
4124 p2 = ext2;
4125 while (*p2) {
4126 if (*p2 == '?') {
4127 *p2 = *p;
4128 p2++;
4129 } else if (*p2 == '*') {
4130 pstrcpy(p2, p);
4131 break;
4132 } else {
4133 p2++;
4135 if (*p)
4136 p++;
4139 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4141 if (ext2[0]) {
4142 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4143 if (actual_space >= available_space - 1) {
4144 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4145 actual_space - available_space));
4147 } else {
4148 pstrcpy_base(pname2, root2, name2);
4151 return(True);
4154 /****************************************************************************
4155 Ensure open files have their names updated. Updated to notify other smbd's
4156 asynchronously.
4157 ****************************************************************************/
4159 static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
4160 SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
4162 files_struct *fsp;
4163 BOOL did_rename = False;
4165 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
4166 /* fsp_name is a relative path under the fsp. To change this for other
4167 sharepaths we need to manipulate relative paths. */
4168 /* TODO - create the absolute path and manipulate the newname
4169 relative to the sharepath. */
4170 if (fsp->conn != conn) {
4171 continue;
4173 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
4174 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
4175 fsp->fsp_name, newname ));
4176 string_set(&fsp->fsp_name, newname);
4177 did_rename = True;
4180 if (!did_rename) {
4181 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
4182 (unsigned int)dev, (double)inode, newname ));
4185 /* Send messages to all smbd's (not ourself) that the name has changed. */
4186 rename_share_filename(lck, conn->connectpath, newname);
4189 /****************************************************************************
4190 We need to check if the source path is a parent directory of the destination
4191 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4192 refuse the rename with a sharing violation. Under UNIX the above call can
4193 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4194 probably need to check that the client is a Windows one before disallowing
4195 this as a UNIX client (one with UNIX extensions) can know the source is a
4196 symlink and make this decision intelligently. Found by an excellent bug
4197 report from <AndyLiebman@aol.com>.
4198 ****************************************************************************/
4200 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4202 const char *psrc = src;
4203 const char *pdst = dest;
4204 size_t slen;
4206 if (psrc[0] == '.' && psrc[1] == '/') {
4207 psrc += 2;
4209 if (pdst[0] == '.' && pdst[1] == '/') {
4210 pdst += 2;
4212 if ((slen = strlen(psrc)) > strlen(pdst)) {
4213 return False;
4215 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4218 /****************************************************************************
4219 Rename an open file - given an fsp.
4220 ****************************************************************************/
4222 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4224 SMB_STRUCT_STAT sbuf;
4225 pstring newname_last_component;
4226 NTSTATUS status = NT_STATUS_OK;
4227 BOOL dest_exists;
4228 struct share_mode_lock *lck = NULL;
4230 ZERO_STRUCT(sbuf);
4232 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4234 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4236 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4237 return status;
4240 status = check_name(conn, newname);
4241 if (!NT_STATUS_IS_OK(status)) {
4242 return status;
4245 /* Ensure newname contains a '/' */
4246 if(strrchr_m(newname,'/') == 0) {
4247 pstring tmpstr;
4249 pstrcpy(tmpstr, "./");
4250 pstrcat(tmpstr, newname);
4251 pstrcpy(newname, tmpstr);
4255 * Check for special case with case preserving and not
4256 * case sensitive. If the old last component differs from the original
4257 * last component only by case, then we should allow
4258 * the rename (user is trying to change the case of the
4259 * filename).
4262 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4263 strequal(newname, fsp->fsp_name)) {
4264 char *p;
4265 pstring newname_modified_last_component;
4268 * Get the last component of the modified name.
4269 * Note that we guarantee that newname contains a '/'
4270 * character above.
4272 p = strrchr_m(newname,'/');
4273 pstrcpy(newname_modified_last_component,p+1);
4275 if(strcsequal(newname_modified_last_component,
4276 newname_last_component) == False) {
4278 * Replace the modified last component with
4279 * the original.
4281 pstrcpy(p+1, newname_last_component);
4286 * If the src and dest names are identical - including case,
4287 * don't do the rename, just return success.
4290 if (strcsequal(fsp->fsp_name, newname)) {
4291 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4292 newname));
4293 return NT_STATUS_OK;
4296 dest_exists = vfs_object_exist(conn,newname,NULL);
4298 if(!replace_if_exists && dest_exists) {
4299 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4300 fsp->fsp_name,newname));
4301 return NT_STATUS_OBJECT_NAME_COLLISION;
4304 /* Ensure we have a valid stat struct for the source. */
4305 if (fsp->fh->fd != -1) {
4306 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4307 return map_nt_error_from_unix(errno);
4309 } else {
4310 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4311 return map_nt_error_from_unix(errno);
4315 status = can_rename(conn,fsp->fsp_name,attrs,&sbuf,True);
4317 if (!NT_STATUS_IS_OK(status)) {
4318 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4319 nt_errstr(status), fsp->fsp_name,newname));
4320 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4321 status = NT_STATUS_ACCESS_DENIED;
4322 return status;
4325 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4326 return NT_STATUS_ACCESS_DENIED;
4329 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
4331 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4332 uint32 create_options = fsp->fh->private_options;
4334 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4335 fsp->fsp_name,newname));
4337 rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
4340 * A rename acts as a new file create w.r.t. allowing an initial delete
4341 * on close, probably because in Windows there is a new handle to the
4342 * new file. If initial delete on close was requested but not
4343 * originally set, we need to set it here. This is probably not 100% correct,
4344 * but will work for the CIFSFS client which in non-posix mode
4345 * depends on these semantics. JRA.
4348 set_allow_initial_delete_on_close(lck, fsp, True);
4350 if (create_options & FILE_DELETE_ON_CLOSE) {
4351 status = can_set_delete_on_close(fsp, True, 0);
4353 if (NT_STATUS_IS_OK(status)) {
4354 /* Note that here we set the *inital* delete on close flag,
4355 * not the regular one. The magic gets handled in close. */
4356 fsp->initial_delete_on_close = True;
4359 TALLOC_FREE(lck);
4360 return NT_STATUS_OK;
4363 TALLOC_FREE(lck);
4365 if (errno == ENOTDIR || errno == EISDIR) {
4366 status = NT_STATUS_OBJECT_NAME_COLLISION;
4367 } else {
4368 status = map_nt_error_from_unix(errno);
4371 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4372 nt_errstr(status), fsp->fsp_name,newname));
4374 return status;
4378 * Do the notify calls from a rename
4381 static void notify_rename(connection_struct *conn, BOOL is_dir,
4382 const char *oldpath, const char *newpath)
4384 char *olddir, *newdir;
4385 const char *oldname, *newname;
4386 uint32 mask;
4388 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4389 : FILE_NOTIFY_CHANGE_FILE_NAME;
4391 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4392 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4393 TALLOC_FREE(olddir);
4394 return;
4397 if (strcmp(olddir, newdir) == 0) {
4398 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4399 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4401 else {
4402 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4403 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4405 TALLOC_FREE(olddir);
4406 TALLOC_FREE(newdir);
4408 /* this is a strange one. w2k3 gives an additional event for
4409 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4410 files, but not directories */
4411 if (!is_dir) {
4412 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4413 FILE_NOTIFY_CHANGE_ATTRIBUTES
4414 |FILE_NOTIFY_CHANGE_CREATION,
4415 newpath);
4419 /****************************************************************************
4420 The guts of the rename command, split out so it may be called by the NT SMB
4421 code.
4422 ****************************************************************************/
4424 NTSTATUS rename_internals(connection_struct *conn,
4425 pstring name,
4426 pstring newname,
4427 uint32 attrs,
4428 BOOL replace_if_exists,
4429 BOOL src_has_wild,
4430 BOOL dest_has_wild)
4432 pstring directory;
4433 pstring mask;
4434 pstring last_component_src;
4435 pstring last_component_dest;
4436 char *p;
4437 int count=0;
4438 NTSTATUS status = NT_STATUS_OK;
4439 SMB_STRUCT_STAT sbuf1, sbuf2;
4440 struct share_mode_lock *lck = NULL;
4441 struct smb_Dir *dir_hnd = NULL;
4442 const char *dname;
4443 long offset = 0;
4444 pstring destname;
4446 *directory = *mask = 0;
4448 ZERO_STRUCT(sbuf1);
4449 ZERO_STRUCT(sbuf2);
4451 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4452 if (!NT_STATUS_IS_OK(status)) {
4453 return status;
4456 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4457 if (!NT_STATUS_IS_OK(status)) {
4458 return status;
4462 * Split the old name into directory and last component
4463 * strings. Note that unix_convert may have stripped off a
4464 * leading ./ from both name and newname if the rename is
4465 * at the root of the share. We need to make sure either both
4466 * name and newname contain a / character or neither of them do
4467 * as this is checked in resolve_wildcards().
4470 p = strrchr_m(name,'/');
4471 if (!p) {
4472 pstrcpy(directory,".");
4473 pstrcpy(mask,name);
4474 } else {
4475 *p = 0;
4476 pstrcpy(directory,name);
4477 pstrcpy(mask,p+1);
4478 *p = '/'; /* Replace needed for exceptional test below. */
4482 * We should only check the mangled cache
4483 * here if unix_convert failed. This means
4484 * that the path in 'mask' doesn't exist
4485 * on the file system and so we need to look
4486 * for a possible mangle. This patch from
4487 * Tine Smukavec <valentin.smukavec@hermes.si>.
4490 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4491 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4494 if (!src_has_wild) {
4496 * No wildcards - just process the one file.
4498 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4500 /* Add a terminating '/' to the directory name. */
4501 pstrcat(directory,"/");
4502 pstrcat(directory,mask);
4504 /* Ensure newname contains a '/' also */
4505 if(strrchr_m(newname,'/') == 0) {
4506 pstring tmpstr;
4508 pstrcpy(tmpstr, "./");
4509 pstrcat(tmpstr, newname);
4510 pstrcpy(newname, tmpstr);
4513 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4514 "case_preserve = %d, short case preserve = %d, "
4515 "directory = %s, newname = %s, "
4516 "last_component_dest = %s, is_8_3 = %d\n",
4517 conn->case_sensitive, conn->case_preserve,
4518 conn->short_case_preserve, directory,
4519 newname, last_component_dest, is_short_name));
4521 /* Ensure the source name is valid for us to access. */
4522 status = check_name(conn, directory);
4523 if (!NT_STATUS_IS_OK(status)) {
4524 return status;
4527 /* The dest name still may have wildcards. */
4528 if (dest_has_wild) {
4529 if (!resolve_wildcards(directory,newname)) {
4530 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4531 directory,newname));
4532 return NT_STATUS_NO_MEMORY;
4537 * Check for special case with case preserving and not
4538 * case sensitive, if directory and newname are identical,
4539 * and the old last component differs from the original
4540 * last component only by case, then we should allow
4541 * the rename (user is trying to change the case of the
4542 * filename).
4544 if((conn->case_sensitive == False) &&
4545 (((conn->case_preserve == True) &&
4546 (is_short_name == False)) ||
4547 ((conn->short_case_preserve == True) &&
4548 (is_short_name == True))) &&
4549 strcsequal(directory, newname)) {
4550 pstring modified_last_component;
4553 * Get the last component of the modified name.
4554 * Note that we guarantee that newname contains a '/'
4555 * character above.
4557 p = strrchr_m(newname,'/');
4558 pstrcpy(modified_last_component,p+1);
4560 if(strcsequal(modified_last_component,
4561 last_component_dest) == False) {
4563 * Replace the modified last component with
4564 * the original.
4566 pstrcpy(p+1, last_component_dest);
4570 /* Ensure the dest name is valid for us to access. */
4571 status = check_name(conn, newname);
4572 if (!NT_STATUS_IS_OK(status)) {
4573 return status;
4577 * The source object must exist.
4580 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4581 DEBUG(3, ("rename_internals: source doesn't exist "
4582 "doing rename %s -> %s\n",
4583 directory,newname));
4585 if (errno == ENOTDIR || errno == EISDIR
4586 || errno == ENOENT) {
4588 * Must return different errors depending on
4589 * whether the parent directory existed or
4590 * not.
4593 p = strrchr_m(directory, '/');
4594 if (!p)
4595 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4596 *p = '\0';
4597 if (vfs_object_exist(conn, directory, NULL))
4598 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4599 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4601 status = map_nt_error_from_unix(errno);
4602 DEBUG(3, ("rename_internals: Error %s rename %s -> "
4603 "%s\n", nt_errstr(status), directory,
4604 newname));
4606 return status;
4609 status = can_rename(conn,directory,attrs,&sbuf1,False);
4611 if (!NT_STATUS_IS_OK(status)) {
4612 DEBUG(3,("rename_internals: Error %s rename %s -> "
4613 "%s\n", nt_errstr(status), directory,
4614 newname));
4615 return status;
4619 * If the src and dest names are identical - including case,
4620 * don't do the rename, just return success.
4623 if (strcsequal(directory, newname)) {
4624 DEBUG(3, ("rename_internals: identical names in "
4625 "rename %s - returning success\n",
4626 directory));
4627 return NT_STATUS_OK;
4630 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4631 DEBUG(3,("rename_internals: dest exists doing "
4632 "rename %s -> %s\n", directory, newname));
4633 return NT_STATUS_OBJECT_NAME_COLLISION;
4636 if (rename_path_prefix_equal(directory, newname)) {
4637 return NT_STATUS_SHARING_VIOLATION;
4640 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
4641 NULL, NULL);
4643 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4644 DEBUG(3,("rename_internals: succeeded doing rename "
4645 "on %s -> %s\n", directory, newname));
4646 rename_open_files(conn, lck, sbuf1.st_dev,
4647 sbuf1.st_ino, newname);
4648 TALLOC_FREE(lck);
4649 notify_rename(conn, S_ISDIR(sbuf1.st_mode),
4650 directory, newname);
4651 return NT_STATUS_OK;
4654 TALLOC_FREE(lck);
4655 if (errno == ENOTDIR || errno == EISDIR) {
4656 status = NT_STATUS_OBJECT_NAME_COLLISION;
4657 } else {
4658 status = map_nt_error_from_unix(errno);
4661 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4662 nt_errstr(status), directory,newname));
4664 return status;
4668 * Wildcards - process each file that matches.
4670 if (strequal(mask,"????????.???")) {
4671 pstrcpy(mask,"*");
4674 status = check_name(conn, directory);
4675 if (!NT_STATUS_IS_OK(status)) {
4676 return status;
4679 dir_hnd = OpenDir(conn, directory, mask, attrs);
4680 if (dir_hnd == NULL) {
4681 return map_nt_error_from_unix(errno);
4684 status = NT_STATUS_NO_SUCH_FILE;
4686 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4687 * - gentest fix. JRA
4690 while ((dname = ReadDirName(dir_hnd, &offset))) {
4691 pstring fname;
4692 BOOL sysdir_entry = False;
4694 pstrcpy(fname,dname);
4696 /* Quick check for "." and ".." */
4697 if (fname[0] == '.') {
4698 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4699 if (attrs & aDIR) {
4700 sysdir_entry = True;
4701 } else {
4702 continue;
4707 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4708 continue;
4711 if(!mask_match(fname, mask, conn->case_sensitive)) {
4712 continue;
4715 if (sysdir_entry) {
4716 status = NT_STATUS_OBJECT_NAME_INVALID;
4717 break;
4720 status = NT_STATUS_ACCESS_DENIED;
4721 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4723 /* Ensure the source name is valid for us to access. */
4724 status = check_name(conn, fname);
4725 if (!NT_STATUS_IS_OK(status)) {
4726 return status;
4729 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4730 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4731 DEBUG(6, ("rename %s failed. Error %s\n",
4732 fname, nt_errstr(status)));
4733 continue;
4735 status = can_rename(conn,fname,attrs,&sbuf1,False);
4736 if (!NT_STATUS_IS_OK(status)) {
4737 DEBUG(6, ("rename %s refused\n", fname));
4738 continue;
4740 pstrcpy(destname,newname);
4742 if (!resolve_wildcards(fname,destname)) {
4743 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4744 fname, destname));
4745 continue;
4748 /* Ensure the dest name is valid for us to access. */
4749 status = check_name(conn, destname);
4750 if (!NT_STATUS_IS_OK(status)) {
4751 return status;
4754 if (strcsequal(fname,destname)) {
4755 DEBUG(3,("rename_internals: identical names "
4756 "in wildcard rename %s - success\n",
4757 fname));
4758 count++;
4759 status = NT_STATUS_OK;
4760 continue;
4763 if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
4764 DEBUG(6,("file_exist %s\n", destname));
4765 status = NT_STATUS_OBJECT_NAME_COLLISION;
4766 continue;
4769 if (rename_path_prefix_equal(fname, destname)) {
4770 return NT_STATUS_SHARING_VIOLATION;
4773 lck = get_share_mode_lock(NULL, sbuf1.st_dev,
4774 sbuf1.st_ino, NULL, NULL);
4776 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4777 rename_open_files(conn, lck, sbuf1.st_dev,
4778 sbuf1.st_ino, newname);
4779 count++;
4780 status = NT_STATUS_OK;
4782 TALLOC_FREE(lck);
4783 DEBUG(3,("rename_internals: doing rename on %s -> "
4784 "%s\n",fname,destname));
4786 CloseDir(dir_hnd);
4788 if (count == 0 && NT_STATUS_IS_OK(status)) {
4789 status = map_nt_error_from_unix(errno);
4792 return status;
4795 /****************************************************************************
4796 Reply to a mv.
4797 ****************************************************************************/
4799 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4800 int dum_buffsize)
4802 int outsize = 0;
4803 pstring name;
4804 pstring newname;
4805 char *p;
4806 uint32 attrs = SVAL(inbuf,smb_vwv0);
4807 NTSTATUS status;
4808 BOOL src_has_wcard = False;
4809 BOOL dest_has_wcard = False;
4811 START_PROFILE(SMBmv);
4813 p = smb_buf(inbuf) + 1;
4814 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
4815 if (!NT_STATUS_IS_OK(status)) {
4816 END_PROFILE(SMBmv);
4817 return ERROR_NT(status);
4819 p++;
4820 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
4821 if (!NT_STATUS_IS_OK(status)) {
4822 END_PROFILE(SMBmv);
4823 return ERROR_NT(status);
4826 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
4827 if (!NT_STATUS_IS_OK(status)) {
4828 END_PROFILE(SMBmv);
4829 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4830 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4832 return ERROR_NT(status);
4835 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4836 if (!NT_STATUS_IS_OK(status)) {
4837 END_PROFILE(SMBmv);
4838 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4839 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4841 return ERROR_NT(status);
4844 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4846 status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
4847 if (!NT_STATUS_IS_OK(status)) {
4848 END_PROFILE(SMBmv);
4849 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4850 /* We have re-scheduled this call. */
4851 return -1;
4853 return ERROR_NT(status);
4856 outsize = set_message(outbuf,0,0,False);
4858 END_PROFILE(SMBmv);
4859 return(outsize);
4862 /*******************************************************************
4863 Copy a file as part of a reply_copy.
4864 ******************************************************************/
4867 * TODO: check error codes on all callers
4870 NTSTATUS copy_file(connection_struct *conn,
4871 char *src,
4872 char *dest1,
4873 int ofun,
4874 int count,
4875 BOOL target_is_directory)
4877 SMB_STRUCT_STAT src_sbuf, sbuf2;
4878 SMB_OFF_T ret=-1;
4879 files_struct *fsp1,*fsp2;
4880 pstring dest;
4881 uint32 dosattrs;
4882 uint32 new_create_disposition;
4883 NTSTATUS status;
4885 pstrcpy(dest,dest1);
4886 if (target_is_directory) {
4887 char *p = strrchr_m(src,'/');
4888 if (p) {
4889 p++;
4890 } else {
4891 p = src;
4893 pstrcat(dest,"/");
4894 pstrcat(dest,p);
4897 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4898 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4901 if (!target_is_directory && count) {
4902 new_create_disposition = FILE_OPEN;
4903 } else {
4904 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4905 NULL, NULL, &new_create_disposition, NULL)) {
4906 return NT_STATUS_INVALID_PARAMETER;
4910 status = open_file_ntcreate(conn,src,&src_sbuf,
4911 FILE_GENERIC_READ,
4912 FILE_SHARE_READ|FILE_SHARE_WRITE,
4913 FILE_OPEN,
4915 FILE_ATTRIBUTE_NORMAL,
4916 INTERNAL_OPEN_ONLY,
4917 NULL, &fsp1);
4919 if (!NT_STATUS_IS_OK(status)) {
4920 return status;
4923 dosattrs = dos_mode(conn, src, &src_sbuf);
4924 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4925 ZERO_STRUCTP(&sbuf2);
4928 status = open_file_ntcreate(conn,dest,&sbuf2,
4929 FILE_GENERIC_WRITE,
4930 FILE_SHARE_READ|FILE_SHARE_WRITE,
4931 new_create_disposition,
4933 dosattrs,
4934 INTERNAL_OPEN_ONLY,
4935 NULL, &fsp2);
4937 if (!NT_STATUS_IS_OK(status)) {
4938 close_file(fsp1,ERROR_CLOSE);
4939 return status;
4942 if ((ofun&3) == 1) {
4943 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4944 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4946 * Stop the copy from occurring.
4948 ret = -1;
4949 src_sbuf.st_size = 0;
4953 if (src_sbuf.st_size) {
4954 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4957 close_file(fsp1,NORMAL_CLOSE);
4959 /* Ensure the modtime is set correctly on the destination file. */
4960 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
4963 * As we are opening fsp1 read-only we only expect
4964 * an error on close on fsp2 if we are out of space.
4965 * Thus we don't look at the error return from the
4966 * close of fsp1.
4968 status = close_file(fsp2,NORMAL_CLOSE);
4970 if (!NT_STATUS_IS_OK(status)) {
4971 return status;
4974 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4975 return NT_STATUS_DISK_FULL;
4978 return NT_STATUS_OK;
4981 /****************************************************************************
4982 Reply to a file copy.
4983 ****************************************************************************/
4985 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4987 int outsize = 0;
4988 pstring name;
4989 pstring directory;
4990 pstring mask,newname;
4991 char *p;
4992 int count=0;
4993 int error = ERRnoaccess;
4994 int err = 0;
4995 int tid2 = SVAL(inbuf,smb_vwv0);
4996 int ofun = SVAL(inbuf,smb_vwv1);
4997 int flags = SVAL(inbuf,smb_vwv2);
4998 BOOL target_is_directory=False;
4999 BOOL source_has_wild = False;
5000 BOOL dest_has_wild = False;
5001 SMB_STRUCT_STAT sbuf1, sbuf2;
5002 NTSTATUS status;
5003 START_PROFILE(SMBcopy);
5005 *directory = *mask = 0;
5007 p = smb_buf(inbuf);
5008 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
5009 if (!NT_STATUS_IS_OK(status)) {
5010 END_PROFILE(SMBcopy);
5011 return ERROR_NT(status);
5013 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
5014 if (!NT_STATUS_IS_OK(status)) {
5015 END_PROFILE(SMBcopy);
5016 return ERROR_NT(status);
5019 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5021 if (tid2 != conn->cnum) {
5022 /* can't currently handle inter share copies XXXX */
5023 DEBUG(3,("Rejecting inter-share copy\n"));
5024 END_PROFILE(SMBcopy);
5025 return ERROR_DOS(ERRSRV,ERRinvdevice);
5028 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5029 if (!NT_STATUS_IS_OK(status)) {
5030 END_PROFILE(SMBcopy);
5031 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5032 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5034 return ERROR_NT(status);
5037 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5038 if (!NT_STATUS_IS_OK(status)) {
5039 END_PROFILE(SMBcopy);
5040 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5041 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5043 return ERROR_NT(status);
5046 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5047 if (!NT_STATUS_IS_OK(status)) {
5048 END_PROFILE(SMBcopy);
5049 return ERROR_NT(status);
5052 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5053 if (!NT_STATUS_IS_OK(status)) {
5054 END_PROFILE(SMBcopy);
5055 return ERROR_NT(status);
5058 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5060 if ((flags&1) && target_is_directory) {
5061 END_PROFILE(SMBcopy);
5062 return ERROR_DOS(ERRDOS,ERRbadfile);
5065 if ((flags&2) && !target_is_directory) {
5066 END_PROFILE(SMBcopy);
5067 return ERROR_DOS(ERRDOS,ERRbadpath);
5070 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5071 /* wants a tree copy! XXXX */
5072 DEBUG(3,("Rejecting tree copy\n"));
5073 END_PROFILE(SMBcopy);
5074 return ERROR_DOS(ERRSRV,ERRerror);
5077 p = strrchr_m(name,'/');
5078 if (!p) {
5079 pstrcpy(directory,"./");
5080 pstrcpy(mask,name);
5081 } else {
5082 *p = 0;
5083 pstrcpy(directory,name);
5084 pstrcpy(mask,p+1);
5088 * We should only check the mangled cache
5089 * here if unix_convert failed. This means
5090 * that the path in 'mask' doesn't exist
5091 * on the file system and so we need to look
5092 * for a possible mangle. This patch from
5093 * Tine Smukavec <valentin.smukavec@hermes.si>.
5096 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5097 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5100 if (!source_has_wild) {
5101 pstrcat(directory,"/");
5102 pstrcat(directory,mask);
5103 if (dest_has_wild) {
5104 if (!resolve_wildcards(directory,newname)) {
5105 END_PROFILE(SMBcopy);
5106 return ERROR_NT(NT_STATUS_NO_MEMORY);
5110 status = check_name(conn, directory);
5111 if (!NT_STATUS_IS_OK(status)) {
5112 return ERROR_NT(status);
5115 status = check_name(conn, newname);
5116 if (!NT_STATUS_IS_OK(status)) {
5117 return ERROR_NT(status);
5120 status = copy_file(conn,directory,newname,ofun,
5121 count,target_is_directory);
5123 if(!NT_STATUS_IS_OK(status)) {
5124 END_PROFILE(SMBcopy);
5125 return ERROR_NT(status);
5126 } else {
5127 count++;
5129 } else {
5130 struct smb_Dir *dir_hnd = NULL;
5131 const char *dname;
5132 long offset = 0;
5133 pstring destname;
5135 if (strequal(mask,"????????.???"))
5136 pstrcpy(mask,"*");
5138 status = check_name(conn, directory);
5139 if (!NT_STATUS_IS_OK(status)) {
5140 return ERROR_NT(status);
5143 dir_hnd = OpenDir(conn, directory, mask, 0);
5144 if (dir_hnd == NULL) {
5145 status = map_nt_error_from_unix(errno);
5146 return ERROR_NT(status);
5149 error = ERRbadfile;
5151 while ((dname = ReadDirName(dir_hnd, &offset))) {
5152 pstring fname;
5153 pstrcpy(fname,dname);
5155 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5156 continue;
5159 if(!mask_match(fname, mask, conn->case_sensitive)) {
5160 continue;
5163 error = ERRnoaccess;
5164 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5165 pstrcpy(destname,newname);
5166 if (!resolve_wildcards(fname,destname)) {
5167 continue;
5170 status = check_name(conn, fname);
5171 if (!NT_STATUS_IS_OK(status)) {
5172 return ERROR_NT(status);
5175 status = check_name(conn, destname);
5176 if (!NT_STATUS_IS_OK(status)) {
5177 return ERROR_NT(status);
5180 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5182 status = copy_file(conn,fname,destname,ofun,
5183 count,target_is_directory);
5184 if (NT_STATUS_IS_OK(status)) {
5185 count++;
5188 CloseDir(dir_hnd);
5191 if (count == 0) {
5192 if(err) {
5193 /* Error on close... */
5194 errno = err;
5195 END_PROFILE(SMBcopy);
5196 return(UNIXERROR(ERRHRD,ERRgeneral));
5199 END_PROFILE(SMBcopy);
5200 return ERROR_DOS(ERRDOS,error);
5203 outsize = set_message(outbuf,1,0,True);
5204 SSVAL(outbuf,smb_vwv0,count);
5206 END_PROFILE(SMBcopy);
5207 return(outsize);
5210 /****************************************************************************
5211 Reply to a setdir.
5212 ****************************************************************************/
5214 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5216 int snum;
5217 int outsize = 0;
5218 pstring newdir;
5219 NTSTATUS status;
5221 START_PROFILE(pathworks_setdir);
5223 snum = SNUM(conn);
5224 if (!CAN_SETDIR(snum)) {
5225 END_PROFILE(pathworks_setdir);
5226 return ERROR_DOS(ERRDOS,ERRnoaccess);
5229 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
5230 if (!NT_STATUS_IS_OK(status)) {
5231 END_PROFILE(pathworks_setdir);
5232 return ERROR_NT(status);
5235 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5236 if (!NT_STATUS_IS_OK(status)) {
5237 END_PROFILE(pathworks_setdir);
5238 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5239 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5241 return ERROR_NT(status);
5244 if (strlen(newdir) != 0) {
5245 if (!vfs_directory_exist(conn,newdir,NULL)) {
5246 END_PROFILE(pathworks_setdir);
5247 return ERROR_DOS(ERRDOS,ERRbadpath);
5249 set_conn_connectpath(conn,newdir);
5252 outsize = set_message(outbuf,0,0,False);
5253 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5255 DEBUG(3,("setdir %s\n", newdir));
5257 END_PROFILE(pathworks_setdir);
5258 return(outsize);
5261 #undef DBGC_CLASS
5262 #define DBGC_CLASS DBGC_LOCKING
5264 /****************************************************************************
5265 Get a lock pid, dealing with large count requests.
5266 ****************************************************************************/
5268 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5270 if(!large_file_format)
5271 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5272 else
5273 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5276 /****************************************************************************
5277 Get a lock count, dealing with large count requests.
5278 ****************************************************************************/
5280 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5282 SMB_BIG_UINT count = 0;
5284 if(!large_file_format) {
5285 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5286 } else {
5288 #if defined(HAVE_LONGLONG)
5289 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5290 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5291 #else /* HAVE_LONGLONG */
5294 * NT4.x seems to be broken in that it sends large file (64 bit)
5295 * lockingX calls even if the CAP_LARGE_FILES was *not*
5296 * negotiated. For boxes without large unsigned ints truncate the
5297 * lock count by dropping the top 32 bits.
5300 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5301 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5302 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5303 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5304 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5307 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5308 #endif /* HAVE_LONGLONG */
5311 return count;
5314 #if !defined(HAVE_LONGLONG)
5315 /****************************************************************************
5316 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5317 ****************************************************************************/
5319 static uint32 map_lock_offset(uint32 high, uint32 low)
5321 unsigned int i;
5322 uint32 mask = 0;
5323 uint32 highcopy = high;
5326 * Try and find out how many significant bits there are in high.
5329 for(i = 0; highcopy; i++)
5330 highcopy >>= 1;
5333 * We use 31 bits not 32 here as POSIX
5334 * lock offsets may not be negative.
5337 mask = (~0) << (31 - i);
5339 if(low & mask)
5340 return 0; /* Fail. */
5342 high <<= (31 - i);
5344 return (high|low);
5346 #endif /* !defined(HAVE_LONGLONG) */
5348 /****************************************************************************
5349 Get a lock offset, dealing with large offset requests.
5350 ****************************************************************************/
5352 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5354 SMB_BIG_UINT offset = 0;
5356 *err = False;
5358 if(!large_file_format) {
5359 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5360 } else {
5362 #if defined(HAVE_LONGLONG)
5363 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5364 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5365 #else /* HAVE_LONGLONG */
5368 * NT4.x seems to be broken in that it sends large file (64 bit)
5369 * lockingX calls even if the CAP_LARGE_FILES was *not*
5370 * negotiated. For boxes without large unsigned ints mangle the
5371 * lock offset by mapping the top 32 bits onto the lower 32.
5374 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5375 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5376 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5377 uint32 new_low = 0;
5379 if((new_low = map_lock_offset(high, low)) == 0) {
5380 *err = True;
5381 return (SMB_BIG_UINT)-1;
5384 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5385 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5386 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5387 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5390 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5391 #endif /* HAVE_LONGLONG */
5394 return offset;
5397 /****************************************************************************
5398 Reply to a lockingX request.
5399 ****************************************************************************/
5401 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5402 int length, int bufsize)
5404 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5405 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5406 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5407 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5408 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5409 SMB_BIG_UINT count = 0, offset = 0;
5410 uint32 lock_pid;
5411 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5412 int i;
5413 char *data;
5414 BOOL large_file_format =
5415 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5416 BOOL err;
5417 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5419 START_PROFILE(SMBlockingX);
5421 CHECK_FSP(fsp,conn);
5423 data = smb_buf(inbuf);
5425 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5426 /* we don't support these - and CANCEL_LOCK makes w2k
5427 and XP reboot so I don't really want to be
5428 compatible! (tridge) */
5429 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5432 /* Check if this is an oplock break on a file
5433 we have granted an oplock on.
5435 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5436 /* Client can insist on breaking to none. */
5437 BOOL break_to_none = (oplocklevel == 0);
5438 BOOL result;
5440 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5441 "for fnum = %d\n", (unsigned int)oplocklevel,
5442 fsp->fnum ));
5445 * Make sure we have granted an exclusive or batch oplock on
5446 * this file.
5449 if (fsp->oplock_type == 0) {
5451 /* The Samba4 nbench simulator doesn't understand
5452 the difference between break to level2 and break
5453 to none from level2 - it sends oplock break
5454 replies in both cases. Don't keep logging an error
5455 message here - just ignore it. JRA. */
5457 DEBUG(5,("reply_lockingX: Error : oplock break from "
5458 "client for fnum = %d (oplock=%d) and no "
5459 "oplock granted on this file (%s).\n",
5460 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5462 /* if this is a pure oplock break request then don't
5463 * send a reply */
5464 if (num_locks == 0 && num_ulocks == 0) {
5465 END_PROFILE(SMBlockingX);
5466 return -1;
5467 } else {
5468 END_PROFILE(SMBlockingX);
5469 return ERROR_DOS(ERRDOS,ERRlock);
5473 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5474 (break_to_none)) {
5475 result = remove_oplock(fsp);
5476 } else {
5477 result = downgrade_oplock(fsp);
5480 if (!result) {
5481 DEBUG(0, ("reply_lockingX: error in removing "
5482 "oplock on file %s\n", fsp->fsp_name));
5483 /* Hmmm. Is this panic justified? */
5484 smb_panic("internal tdb error");
5487 reply_to_oplock_break_requests(fsp);
5489 /* if this is a pure oplock break request then don't send a
5490 * reply */
5491 if (num_locks == 0 && num_ulocks == 0) {
5492 /* Sanity check - ensure a pure oplock break is not a
5493 chained request. */
5494 if(CVAL(inbuf,smb_vwv0) != 0xff)
5495 DEBUG(0,("reply_lockingX: Error : pure oplock "
5496 "break is a chained %d request !\n",
5497 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5498 END_PROFILE(SMBlockingX);
5499 return -1;
5504 * We do this check *after* we have checked this is not a oplock break
5505 * response message. JRA.
5508 release_level_2_oplocks_on_change(fsp);
5510 /* Data now points at the beginning of the list
5511 of smb_unlkrng structs */
5512 for(i = 0; i < (int)num_ulocks; i++) {
5513 lock_pid = get_lock_pid( data, i, large_file_format);
5514 count = get_lock_count( data, i, large_file_format);
5515 offset = get_lock_offset( data, i, large_file_format, &err);
5518 * There is no error code marked "stupid client bug".... :-).
5520 if(err) {
5521 END_PROFILE(SMBlockingX);
5522 return ERROR_DOS(ERRDOS,ERRnoaccess);
5525 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5526 "pid %u, file %s\n", (double)offset, (double)count,
5527 (unsigned int)lock_pid, fsp->fsp_name ));
5529 status = do_unlock(fsp,
5530 lock_pid,
5531 count,
5532 offset,
5533 WINDOWS_LOCK);
5535 if (NT_STATUS_V(status)) {
5536 END_PROFILE(SMBlockingX);
5537 return ERROR_NT(status);
5541 /* Setup the timeout in seconds. */
5543 if (!lp_blocking_locks(SNUM(conn))) {
5544 lock_timeout = 0;
5547 /* Now do any requested locks */
5548 data += ((large_file_format ? 20 : 10)*num_ulocks);
5550 /* Data now points at the beginning of the list
5551 of smb_lkrng structs */
5553 for(i = 0; i < (int)num_locks; i++) {
5554 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5555 READ_LOCK:WRITE_LOCK);
5556 lock_pid = get_lock_pid( data, i, large_file_format);
5557 count = get_lock_count( data, i, large_file_format);
5558 offset = get_lock_offset( data, i, large_file_format, &err);
5561 * There is no error code marked "stupid client bug".... :-).
5563 if(err) {
5564 END_PROFILE(SMBlockingX);
5565 return ERROR_DOS(ERRDOS,ERRnoaccess);
5568 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5569 "%u, file %s timeout = %d\n", (double)offset,
5570 (double)count, (unsigned int)lock_pid,
5571 fsp->fsp_name, (int)lock_timeout ));
5573 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5574 if (lp_blocking_locks(SNUM(conn))) {
5576 /* Schedule a message to ourselves to
5577 remove the blocking lock record and
5578 return the right error. */
5580 if (!blocking_lock_cancel(fsp,
5581 lock_pid,
5582 offset,
5583 count,
5584 WINDOWS_LOCK,
5585 locktype,
5586 NT_STATUS_FILE_LOCK_CONFLICT)) {
5587 END_PROFILE(SMBlockingX);
5588 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5591 /* Remove a matching pending lock. */
5592 status = do_lock_cancel(fsp,
5593 lock_pid,
5594 count,
5595 offset,
5596 WINDOWS_LOCK);
5597 } else {
5598 BOOL blocking_lock = lock_timeout ? True : False;
5599 BOOL defer_lock = False;
5600 struct byte_range_lock *br_lck;
5601 uint32 block_smbpid;
5603 br_lck = do_lock(fsp,
5604 lock_pid,
5605 count,
5606 offset,
5607 lock_type,
5608 WINDOWS_LOCK,
5609 blocking_lock,
5610 &status,
5611 &block_smbpid);
5613 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5614 /* Windows internal resolution for blocking locks seems
5615 to be about 200ms... Don't wait for less than that. JRA. */
5616 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5617 lock_timeout = lp_lock_spin_time();
5619 defer_lock = True;
5622 /* This heuristic seems to match W2K3 very well. If a
5623 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5624 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5625 far as I can tell. Replacement for do_lock_spin(). JRA. */
5627 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5628 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5629 defer_lock = True;
5630 lock_timeout = lp_lock_spin_time();
5633 if (br_lck && defer_lock) {
5635 * A blocking lock was requested. Package up
5636 * this smb into a queued request and push it
5637 * onto the blocking lock queue.
5639 if(push_blocking_lock_request(br_lck,
5640 inbuf, length,
5641 fsp,
5642 lock_timeout,
5644 lock_pid,
5645 lock_type,
5646 WINDOWS_LOCK,
5647 offset,
5648 count,
5649 block_smbpid)) {
5650 TALLOC_FREE(br_lck);
5651 END_PROFILE(SMBlockingX);
5652 return -1;
5656 TALLOC_FREE(br_lck);
5659 if (NT_STATUS_V(status)) {
5660 END_PROFILE(SMBlockingX);
5661 return ERROR_NT(status);
5665 /* If any of the above locks failed, then we must unlock
5666 all of the previous locks (X/Open spec). */
5668 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5669 (i != num_locks) &&
5670 (num_locks != 0)) {
5672 * Ensure we don't do a remove on the lock that just failed,
5673 * as under POSIX rules, if we have a lock already there, we
5674 * will delete it (and we shouldn't) .....
5676 for(i--; i >= 0; i--) {
5677 lock_pid = get_lock_pid( data, i, large_file_format);
5678 count = get_lock_count( data, i, large_file_format);
5679 offset = get_lock_offset( data, i, large_file_format,
5680 &err);
5683 * There is no error code marked "stupid client
5684 * bug".... :-).
5686 if(err) {
5687 END_PROFILE(SMBlockingX);
5688 return ERROR_DOS(ERRDOS,ERRnoaccess);
5691 do_unlock(fsp,
5692 lock_pid,
5693 count,
5694 offset,
5695 WINDOWS_LOCK);
5697 END_PROFILE(SMBlockingX);
5698 return ERROR_NT(status);
5701 set_message(outbuf,2,0,True);
5703 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5704 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5706 END_PROFILE(SMBlockingX);
5707 return chain_reply(inbuf,outbuf,length,bufsize);
5710 #undef DBGC_CLASS
5711 #define DBGC_CLASS DBGC_ALL
5713 /****************************************************************************
5714 Reply to a SMBreadbmpx (read block multiplex) request.
5715 ****************************************************************************/
5717 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5719 ssize_t nread = -1;
5720 ssize_t total_read;
5721 char *data;
5722 SMB_OFF_T startpos;
5723 int outsize;
5724 size_t maxcount;
5725 int max_per_packet;
5726 size_t tcount;
5727 int pad;
5728 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5729 START_PROFILE(SMBreadBmpx);
5731 /* this function doesn't seem to work - disable by default */
5732 if (!lp_readbmpx()) {
5733 END_PROFILE(SMBreadBmpx);
5734 return ERROR_DOS(ERRSRV,ERRuseSTD);
5737 outsize = set_message(outbuf,8,0,True);
5739 CHECK_FSP(fsp,conn);
5740 if (!CHECK_READ(fsp,inbuf)) {
5741 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5744 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5745 maxcount = SVAL(inbuf,smb_vwv3);
5747 data = smb_buf(outbuf);
5748 pad = ((long)data)%4;
5749 if (pad)
5750 pad = 4 - pad;
5751 data += pad;
5753 max_per_packet = bufsize-(outsize+pad);
5754 tcount = maxcount;
5755 total_read = 0;
5757 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5758 END_PROFILE(SMBreadBmpx);
5759 return ERROR_DOS(ERRDOS,ERRlock);
5762 do {
5763 size_t N = MIN(max_per_packet,tcount-total_read);
5765 nread = read_file(fsp,data,startpos,N);
5767 if (nread <= 0)
5768 nread = 0;
5770 if (nread < (ssize_t)N)
5771 tcount = total_read + nread;
5773 set_message(outbuf,8,nread+pad,False);
5774 SIVAL(outbuf,smb_vwv0,startpos);
5775 SSVAL(outbuf,smb_vwv2,tcount);
5776 SSVAL(outbuf,smb_vwv6,nread);
5777 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5779 show_msg(outbuf);
5780 if (!send_smb(smbd_server_fd(),outbuf))
5781 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5783 total_read += nread;
5784 startpos += nread;
5785 } while (total_read < (ssize_t)tcount);
5787 END_PROFILE(SMBreadBmpx);
5788 return(-1);
5791 /****************************************************************************
5792 Reply to a SMBsetattrE.
5793 ****************************************************************************/
5795 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5797 struct timespec ts[2];
5798 int outsize = 0;
5799 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5800 START_PROFILE(SMBsetattrE);
5802 outsize = set_message(outbuf,0,0,False);
5804 if(!fsp || (fsp->conn != conn)) {
5805 END_PROFILE(SMBsetattrE);
5806 return ERROR_DOS(ERRDOS,ERRbadfid);
5810 * Convert the DOS times into unix times. Ignore create
5811 * time as UNIX can't set this.
5814 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5815 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5818 * Patch from Ray Frush <frush@engr.colostate.edu>
5819 * Sometimes times are sent as zero - ignore them.
5822 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5823 /* Ignore request */
5824 if( DEBUGLVL( 3 ) ) {
5825 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5826 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5828 END_PROFILE(SMBsetattrE);
5829 return(outsize);
5830 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5831 /* set modify time = to access time if modify time was unset */
5832 ts[1] = ts[0];
5835 /* Set the date on this file */
5836 /* Should we set pending modtime here ? JRA */
5837 if(file_ntimes(conn, fsp->fsp_name, ts)) {
5838 END_PROFILE(SMBsetattrE);
5839 return ERROR_DOS(ERRDOS,ERRnoaccess);
5842 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5843 fsp->fnum,
5844 (unsigned int)ts[0].tv_sec,
5845 (unsigned int)ts[1].tv_sec));
5847 END_PROFILE(SMBsetattrE);
5848 return(outsize);
5852 /* Back from the dead for OS/2..... JRA. */
5854 /****************************************************************************
5855 Reply to a SMBwritebmpx (write block multiplex primary) request.
5856 ****************************************************************************/
5858 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5860 size_t numtowrite;
5861 ssize_t nwritten = -1;
5862 int outsize = 0;
5863 SMB_OFF_T startpos;
5864 size_t tcount;
5865 BOOL write_through;
5866 int smb_doff;
5867 char *data;
5868 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5869 NTSTATUS status;
5870 START_PROFILE(SMBwriteBmpx);
5872 CHECK_FSP(fsp,conn);
5873 if (!CHECK_WRITE(fsp)) {
5874 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5876 if (HAS_CACHED_ERROR(fsp)) {
5877 return(CACHED_ERROR(fsp));
5880 tcount = SVAL(inbuf,smb_vwv1);
5881 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5882 write_through = BITSETW(inbuf+smb_vwv7,0);
5883 numtowrite = SVAL(inbuf,smb_vwv10);
5884 smb_doff = SVAL(inbuf,smb_vwv11);
5886 data = smb_base(inbuf) + smb_doff;
5888 /* If this fails we need to send an SMBwriteC response,
5889 not an SMBwritebmpx - set this up now so we don't forget */
5890 SCVAL(outbuf,smb_com,SMBwritec);
5892 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5893 END_PROFILE(SMBwriteBmpx);
5894 return(ERROR_DOS(ERRDOS,ERRlock));
5897 nwritten = write_file(fsp,data,startpos,numtowrite);
5899 status = sync_file(conn, fsp, write_through);
5900 if (!NT_STATUS_IS_OK(status)) {
5901 END_PROFILE(SMBwriteBmpx);
5902 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
5903 fsp->fsp_name, nt_errstr(status) ));
5904 return ERROR_NT(status);
5907 if(nwritten < (ssize_t)numtowrite) {
5908 END_PROFILE(SMBwriteBmpx);
5909 return(UNIXERROR(ERRHRD,ERRdiskfull));
5912 /* If the maximum to be written to this file
5913 is greater than what we just wrote then set
5914 up a secondary struct to be attached to this
5915 fd, we will use this to cache error messages etc. */
5917 if((ssize_t)tcount > nwritten) {
5918 write_bmpx_struct *wbms;
5919 if(fsp->wbmpx_ptr != NULL)
5920 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5921 else
5922 wbms = SMB_MALLOC_P(write_bmpx_struct);
5923 if(!wbms) {
5924 DEBUG(0,("Out of memory in reply_readmpx\n"));
5925 END_PROFILE(SMBwriteBmpx);
5926 return(ERROR_DOS(ERRSRV,ERRnoresource));
5928 wbms->wr_mode = write_through;
5929 wbms->wr_discard = False; /* No errors yet */
5930 wbms->wr_total_written = nwritten;
5931 wbms->wr_errclass = 0;
5932 wbms->wr_error = 0;
5933 fsp->wbmpx_ptr = wbms;
5936 /* We are returning successfully, set the message type back to
5937 SMBwritebmpx */
5938 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5940 outsize = set_message(outbuf,1,0,True);
5942 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5944 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5945 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5947 if (write_through && tcount==nwritten) {
5948 /* We need to send both a primary and a secondary response */
5949 smb_setlen(outbuf,outsize - 4);
5950 show_msg(outbuf);
5951 if (!send_smb(smbd_server_fd(),outbuf))
5952 exit_server_cleanly("reply_writebmpx: send_smb failed.");
5954 /* Now the secondary */
5955 outsize = set_message(outbuf,1,0,True);
5956 SCVAL(outbuf,smb_com,SMBwritec);
5957 SSVAL(outbuf,smb_vwv0,nwritten);
5960 END_PROFILE(SMBwriteBmpx);
5961 return(outsize);
5964 /****************************************************************************
5965 Reply to a SMBwritebs (write block multiplex secondary) request.
5966 ****************************************************************************/
5968 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5970 size_t numtowrite;
5971 ssize_t nwritten = -1;
5972 int outsize = 0;
5973 SMB_OFF_T startpos;
5974 size_t tcount;
5975 BOOL write_through;
5976 int smb_doff;
5977 char *data;
5978 write_bmpx_struct *wbms;
5979 BOOL send_response = False;
5980 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5981 NTSTATUS status;
5982 START_PROFILE(SMBwriteBs);
5984 CHECK_FSP(fsp,conn);
5985 if (!CHECK_WRITE(fsp)) {
5986 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5989 tcount = SVAL(inbuf,smb_vwv1);
5990 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5991 numtowrite = SVAL(inbuf,smb_vwv6);
5992 smb_doff = SVAL(inbuf,smb_vwv7);
5994 data = smb_base(inbuf) + smb_doff;
5996 /* We need to send an SMBwriteC response, not an SMBwritebs */
5997 SCVAL(outbuf,smb_com,SMBwritec);
5999 /* This fd should have an auxiliary struct attached,
6000 check that it does */
6001 wbms = fsp->wbmpx_ptr;
6002 if(!wbms) {
6003 END_PROFILE(SMBwriteBs);
6004 return(-1);
6007 /* If write through is set we can return errors, else we must cache them */
6008 write_through = wbms->wr_mode;
6010 /* Check for an earlier error */
6011 if(wbms->wr_discard) {
6012 END_PROFILE(SMBwriteBs);
6013 return -1; /* Just discard the packet */
6016 nwritten = write_file(fsp,data,startpos,numtowrite);
6018 status = sync_file(conn, fsp, write_through);
6020 if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6021 if(write_through) {
6022 /* We are returning an error - we can delete the aux struct */
6023 if (wbms)
6024 free((char *)wbms);
6025 fsp->wbmpx_ptr = NULL;
6026 END_PROFILE(SMBwriteBs);
6027 return(ERROR_DOS(ERRHRD,ERRdiskfull));
6029 wbms->wr_errclass = ERRHRD;
6030 wbms->wr_error = ERRdiskfull;
6031 wbms->wr_status = NT_STATUS_DISK_FULL;
6032 wbms->wr_discard = True;
6033 END_PROFILE(SMBwriteBs);
6034 return -1;
6037 /* Increment the total written, if this matches tcount
6038 we can discard the auxiliary struct (hurrah !) and return a writeC */
6039 wbms->wr_total_written += nwritten;
6040 if(wbms->wr_total_written >= tcount) {
6041 if (write_through) {
6042 outsize = set_message(outbuf,1,0,True);
6043 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
6044 send_response = True;
6047 free((char *)wbms);
6048 fsp->wbmpx_ptr = NULL;
6051 if(send_response) {
6052 END_PROFILE(SMBwriteBs);
6053 return(outsize);
6056 END_PROFILE(SMBwriteBs);
6057 return(-1);
6060 /****************************************************************************
6061 Reply to a SMBgetattrE.
6062 ****************************************************************************/
6064 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6066 SMB_STRUCT_STAT sbuf;
6067 int outsize = 0;
6068 int mode;
6069 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
6070 START_PROFILE(SMBgetattrE);
6072 outsize = set_message(outbuf,11,0,True);
6074 if(!fsp || (fsp->conn != conn)) {
6075 END_PROFILE(SMBgetattrE);
6076 return ERROR_DOS(ERRDOS,ERRbadfid);
6079 /* Do an fstat on this file */
6080 if(fsp_stat(fsp, &sbuf)) {
6081 END_PROFILE(SMBgetattrE);
6082 return(UNIXERROR(ERRDOS,ERRnoaccess));
6085 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6088 * Convert the times into dos times. Set create
6089 * date to be last modify date as UNIX doesn't save
6090 * this.
6093 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6094 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6095 /* Should we check pending modtime here ? JRA */
6096 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6098 if (mode & aDIR) {
6099 SIVAL(outbuf,smb_vwv6,0);
6100 SIVAL(outbuf,smb_vwv8,0);
6101 } else {
6102 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6103 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6104 SIVAL(outbuf,smb_vwv8,allocation_size);
6106 SSVAL(outbuf,smb_vwv10, mode);
6108 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6110 END_PROFILE(SMBgetattrE);
6111 return(outsize);