r23731: Forgot one reference to inbuf
[Samba.git] / source / smbd / reply.c
blob6e41de4ec9af9ba4dc45b8ff3c990d0d6d1ea92f
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 static NTSTATUS check_path_syntax_internal(char *path,
51 BOOL posix_path,
52 BOOL *p_last_component_contains_wcard)
54 char *d = path;
55 const char *s = path;
56 NTSTATUS ret = NT_STATUS_OK;
57 BOOL start_of_name_component = True;
59 *p_last_component_contains_wcard = False;
61 while (*s) {
62 if (IS_PATH_SEP(*s,posix_path)) {
64 * Safe to assume is not the second part of a mb char
65 * as this is handled below.
67 /* Eat multiple '/' or '\\' */
68 while (IS_PATH_SEP(*s,posix_path)) {
69 s++;
71 if ((d != path) && (*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 > path) && (*(d-1) == '/')) {
92 *(d-1) = '\0';
93 d--;
96 /* Are we at the start ? Can't go back further if so. */
97 if (d <= path) {
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 > path; 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(char *path)
181 BOOL ignore;
182 return check_path_syntax_internal(path, False, &ignore);
185 /****************************************************************************
186 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
187 Wildcards allowed - p_contains_wcard returns true if the last component contained
188 a wildcard.
189 ****************************************************************************/
191 NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
193 return check_path_syntax_internal(path, False, p_contains_wcard);
196 /****************************************************************************
197 Check the path for a POSIX client.
198 We're assuming here that '/' is not the second byte in any multibyte char
199 set (a safe assumption).
200 ****************************************************************************/
202 NTSTATUS check_path_syntax_posix(char *path)
204 BOOL ignore;
205 return check_path_syntax_internal(path, True, &ignore);
208 /****************************************************************************
209 Pull a string and check the path allowing a wilcard - provide for error return.
210 ****************************************************************************/
212 size_t srvstr_get_path_wcard(char *inbuf, uint16 smb_flags2, char *dest,
213 const char *src, size_t dest_len, size_t src_len,
214 int flags, NTSTATUS *err, BOOL *contains_wcard)
216 size_t ret;
217 #ifdef DEVELOPER
218 SMB_ASSERT(dest_len == sizeof(pstring));
219 #endif
221 if (src_len == 0) {
222 ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
223 dest_len, flags);
224 } else {
225 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
226 dest_len, src_len, flags);
229 *contains_wcard = False;
231 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
233 * For a DFS path the function parse_dfs_path()
234 * will do the path processing, just make a copy.
236 *err = NT_STATUS_OK;
237 return ret;
240 if (lp_posix_pathnames()) {
241 *err = check_path_syntax_posix(dest);
242 } else {
243 *err = check_path_syntax_wcard(dest, 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, uint16 smb_flags2, char *dest,
254 const char *src, size_t dest_len, size_t src_len,
255 int flags, NTSTATUS *err)
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, smb_flags2, dest, src,
264 dest_len, flags);
265 } else {
266 ret = srvstr_pull(inbuf, smb_flags2, dest, src,
267 dest_len, src_len, flags);
270 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
272 * For a DFS path the function parse_dfs_path()
273 * will do the path processing, just make a copy.
275 *err = NT_STATUS_OK;
276 return ret;
279 if (lp_posix_pathnames()) {
280 *err = check_path_syntax_posix(dest);
281 } else {
282 *err = check_path_syntax(dest);
285 return ret;
288 /****************************************************************************
289 Reply to a special message.
290 ****************************************************************************/
292 int reply_special(char *inbuf,char *outbuf)
294 int outsize = 4;
295 int msg_type = CVAL(inbuf,0);
296 int msg_flags = CVAL(inbuf,1);
297 fstring name1,name2;
298 char name_type = 0;
300 static BOOL already_got_session = False;
302 *name1 = *name2 = 0;
304 memset(outbuf,'\0',smb_size);
306 smb_setlen(inbuf,outbuf,0);
308 switch (msg_type) {
309 case 0x81: /* session request */
311 if (already_got_session) {
312 exit_server_cleanly("multiple session request not permitted");
315 SCVAL(outbuf,0,0x82);
316 SCVAL(outbuf,3,0);
317 if (name_len(inbuf+4) > 50 ||
318 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
319 DEBUG(0,("Invalid name length in session request\n"));
320 return(0);
322 name_extract(inbuf,4,name1);
323 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
324 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
325 name1,name2));
327 set_local_machine_name(name1, True);
328 set_remote_machine_name(name2, True);
330 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
331 get_local_machine_name(), get_remote_machine_name(),
332 name_type));
334 if (name_type == 'R') {
335 /* We are being asked for a pathworks session ---
336 no thanks! */
337 SCVAL(outbuf, 0,0x83);
338 break;
341 /* only add the client's machine name to the list
342 of possibly valid usernames if we are operating
343 in share mode security */
344 if (lp_security() == SEC_SHARE) {
345 add_session_user(get_remote_machine_name());
348 reload_services(True);
349 reopen_logs();
351 already_got_session = True;
352 break;
354 case 0x89: /* session keepalive request
355 (some old clients produce this?) */
356 SCVAL(outbuf,0,SMBkeepalive);
357 SCVAL(outbuf,3,0);
358 break;
360 case 0x82: /* positive session response */
361 case 0x83: /* negative session response */
362 case 0x84: /* retarget session response */
363 DEBUG(0,("Unexpected session response\n"));
364 break;
366 case SMBkeepalive: /* session keepalive */
367 default:
368 return(0);
371 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
372 msg_type, msg_flags));
374 return(outsize);
377 /****************************************************************************
378 Reply to a tcon.
379 conn POINTER CAN BE NULL HERE !
380 ****************************************************************************/
382 int reply_tcon(connection_struct *conn,
383 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
385 const char *service;
386 pstring service_buf;
387 pstring password;
388 pstring dev;
389 int outsize = 0;
390 uint16 vuid = SVAL(inbuf,smb_uid);
391 int pwlen=0;
392 NTSTATUS nt_status;
393 char *p;
394 DATA_BLOB password_blob;
396 START_PROFILE(SMBtcon);
398 *service_buf = *password = *dev = 0;
400 p = smb_buf(inbuf)+1;
401 p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), service_buf, p,
402 sizeof(service_buf), STR_TERMINATE) + 1;
403 pwlen = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), password, p,
404 sizeof(password), STR_TERMINATE) + 1;
405 p += pwlen;
406 p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dev, p, sizeof(dev),
407 STR_TERMINATE) + 1;
409 p = strrchr_m(service_buf,'\\');
410 if (p) {
411 service = p+1;
412 } else {
413 service = service_buf;
416 password_blob = data_blob(password, pwlen+1);
418 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
420 data_blob_clear_free(&password_blob);
422 if (!conn) {
423 END_PROFILE(SMBtcon);
424 return ERROR_NT(nt_status);
427 outsize = set_message(inbuf,outbuf,2,0,True);
428 SSVAL(outbuf,smb_vwv0,max_recv);
429 SSVAL(outbuf,smb_vwv1,conn->cnum);
430 SSVAL(outbuf,smb_tid,conn->cnum);
432 DEBUG(3,("tcon service=%s cnum=%d\n",
433 service, conn->cnum));
435 END_PROFILE(SMBtcon);
436 return(outsize);
439 /****************************************************************************
440 Reply to a tcon and X.
441 conn POINTER CAN BE NULL HERE !
442 ****************************************************************************/
444 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
446 fstring service;
447 DATA_BLOB password;
449 /* what the cleint thinks the device is */
450 fstring client_devicetype;
451 /* what the server tells the client the share represents */
452 const char *server_devicetype;
453 NTSTATUS nt_status;
454 uint16 vuid = SVAL(inbuf,smb_uid);
455 int passlen = SVAL(inbuf,smb_vwv3);
456 pstring path;
457 char *p, *q;
458 uint16 tcon_flags = SVAL(inbuf,smb_vwv2);
460 START_PROFILE(SMBtconX);
462 *service = *client_devicetype = 0;
464 /* we might have to close an old one */
465 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
466 close_cnum(conn,vuid);
469 if (passlen > MAX_PASS_LEN) {
470 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
473 if (global_encrypted_passwords_negotiated) {
474 password = data_blob(smb_buf(inbuf),passlen);
475 if (lp_security() == SEC_SHARE) {
477 * Security = share always has a pad byte
478 * after the password.
480 p = smb_buf(inbuf) + passlen + 1;
481 } else {
482 p = smb_buf(inbuf) + passlen;
484 } else {
485 password = data_blob(smb_buf(inbuf),passlen+1);
486 /* Ensure correct termination */
487 password.data[passlen]=0;
488 p = smb_buf(inbuf) + passlen + 1;
491 p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), path, p,
492 sizeof(path), STR_TERMINATE);
495 * the service name can be either: \\server\share
496 * or share directly like on the DELL PowerVault 705
498 if (*path=='\\') {
499 q = strchr_m(path+2,'\\');
500 if (!q) {
501 END_PROFILE(SMBtconX);
502 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
504 fstrcpy(service,q+1);
506 else
507 fstrcpy(service,path);
509 p += srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), client_devicetype, p,
510 sizeof(client_devicetype), 6, STR_ASCII);
512 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
514 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
516 data_blob_clear_free(&password);
518 if (!conn) {
519 END_PROFILE(SMBtconX);
520 return ERROR_NT(nt_status);
523 if ( IS_IPC(conn) )
524 server_devicetype = "IPC";
525 else if ( IS_PRINT(conn) )
526 server_devicetype = "LPT1:";
527 else
528 server_devicetype = "A:";
530 if (Protocol < PROTOCOL_NT1) {
531 set_message(inbuf,outbuf,2,0,True);
532 p = smb_buf(outbuf);
533 p += srvstr_push(outbuf, p, server_devicetype, -1,
534 STR_TERMINATE|STR_ASCII);
535 set_message_end(inbuf,outbuf,p);
536 } else {
537 /* NT sets the fstype of IPC$ to the null string */
538 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
540 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
541 /* Return permissions. */
542 uint32 perm1 = 0;
543 uint32 perm2 = 0;
545 set_message(inbuf,outbuf,7,0,True);
547 if (IS_IPC(conn)) {
548 perm1 = FILE_ALL_ACCESS;
549 perm2 = FILE_ALL_ACCESS;
550 } else {
551 perm1 = CAN_WRITE(conn) ?
552 SHARE_ALL_ACCESS :
553 SHARE_READ_ONLY;
556 SIVAL(outbuf, smb_vwv3, perm1);
557 SIVAL(outbuf, smb_vwv5, perm2);
558 } else {
559 set_message(inbuf,outbuf,3,0,True);
562 p = smb_buf(outbuf);
563 p += srvstr_push(outbuf, p, server_devicetype, -1,
564 STR_TERMINATE|STR_ASCII);
565 p += srvstr_push(outbuf, p, fstype, -1,
566 STR_TERMINATE);
568 set_message_end(inbuf,outbuf,p);
570 /* what does setting this bit do? It is set by NT4 and
571 may affect the ability to autorun mounted cdroms */
572 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
573 (lp_csc_policy(SNUM(conn)) << 2));
575 init_dfsroot(conn, inbuf, outbuf);
579 DEBUG(3,("tconX service=%s \n",
580 service));
582 /* set the incoming and outgoing tid to the just created one */
583 SSVAL(inbuf,smb_tid,conn->cnum);
584 SSVAL(outbuf,smb_tid,conn->cnum);
586 END_PROFILE(SMBtconX);
587 return chain_reply(inbuf,outbuf,length,bufsize);
590 /****************************************************************************
591 Reply to an unknown type.
592 ****************************************************************************/
594 int reply_unknown(char *inbuf,char *outbuf)
596 int type;
597 type = CVAL(inbuf,smb_com);
599 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
600 smb_fn_name(type), type, type));
602 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
605 /****************************************************************************
606 Reply to an ioctl.
607 conn POINTER CAN BE NULL HERE !
608 ****************************************************************************/
610 int reply_ioctl(connection_struct *conn,
611 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
613 uint16 device = SVAL(inbuf,smb_vwv1);
614 uint16 function = SVAL(inbuf,smb_vwv2);
615 uint32 ioctl_code = (device << 16) + function;
616 int replysize, outsize;
617 char *p;
618 START_PROFILE(SMBioctl);
620 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
622 switch (ioctl_code) {
623 case IOCTL_QUERY_JOB_INFO:
624 replysize = 32;
625 break;
626 default:
627 END_PROFILE(SMBioctl);
628 return(ERROR_DOS(ERRSRV,ERRnosupport));
631 outsize = set_message(inbuf,outbuf,8,replysize+1,True);
632 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
633 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
634 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
635 p = smb_buf(outbuf) + 1; /* Allow for alignment */
637 switch (ioctl_code) {
638 case IOCTL_QUERY_JOB_INFO:
640 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
641 if (!fsp) {
642 END_PROFILE(SMBioctl);
643 return(UNIXERROR(ERRDOS,ERRbadfid));
645 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
646 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
647 if (conn) {
648 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
650 break;
654 END_PROFILE(SMBioctl);
655 return outsize;
658 /****************************************************************************
659 Strange checkpath NTSTATUS mapping.
660 ****************************************************************************/
662 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
664 /* Strange DOS error code semantics only for checkpath... */
665 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
666 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
667 /* We need to map to ERRbadpath */
668 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
671 return status;
674 /****************************************************************************
675 Reply to a checkpath.
676 ****************************************************************************/
678 int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
680 int outsize = 0;
681 pstring name;
682 SMB_STRUCT_STAT sbuf;
683 NTSTATUS status;
685 START_PROFILE(SMBcheckpath);
687 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), name, smb_buf(inbuf) + 1,
688 sizeof(name), 0, STR_TERMINATE, &status);
689 if (!NT_STATUS_IS_OK(status)) {
690 END_PROFILE(SMBcheckpath);
691 status = map_checkpath_error(inbuf, status);
692 return ERROR_NT(status);
695 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name);
696 if (!NT_STATUS_IS_OK(status)) {
697 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
698 END_PROFILE(SMBcheckpath);
699 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
701 goto path_err;
704 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
706 status = unix_convert(conn, name, False, NULL, &sbuf);
707 if (!NT_STATUS_IS_OK(status)) {
708 goto path_err;
711 status = check_name(conn, name);
712 if (!NT_STATUS_IS_OK(status)) {
713 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
714 goto path_err;
717 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
718 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
719 status = map_nt_error_from_unix(errno);
720 goto path_err;
723 if (!S_ISDIR(sbuf.st_mode)) {
724 END_PROFILE(SMBcheckpath);
725 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
728 outsize = set_message(inbuf,outbuf,0,0,False);
730 END_PROFILE(SMBcheckpath);
731 return outsize;
733 path_err:
735 END_PROFILE(SMBcheckpath);
737 /* We special case this - as when a Windows machine
738 is parsing a path is steps through the components
739 one at a time - if a component fails it expects
740 ERRbadpath, not ERRbadfile.
742 status = map_checkpath_error(inbuf, status);
743 if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
745 * Windows returns different error codes if
746 * the parent directory is valid but not the
747 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
748 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
749 * if the path is invalid.
751 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
754 return ERROR_NT(status);
757 /****************************************************************************
758 Reply to a getatr.
759 ****************************************************************************/
761 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
763 pstring fname;
764 int outsize = 0;
765 SMB_STRUCT_STAT sbuf;
766 int mode=0;
767 SMB_OFF_T size=0;
768 time_t mtime=0;
769 char *p;
770 NTSTATUS status;
772 START_PROFILE(SMBgetatr);
774 p = smb_buf(inbuf) + 1;
775 p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
776 sizeof(fname), 0, STR_TERMINATE, &status);
777 if (!NT_STATUS_IS_OK(status)) {
778 END_PROFILE(SMBgetatr);
779 return ERROR_NT(status);
782 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
783 if (!NT_STATUS_IS_OK(status)) {
784 END_PROFILE(SMBgetatr);
785 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
786 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
788 return ERROR_NT(status);
791 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
792 under WfWg - weird! */
793 if (*fname == '\0') {
794 mode = aHIDDEN | aDIR;
795 if (!CAN_WRITE(conn)) {
796 mode |= aRONLY;
798 size = 0;
799 mtime = 0;
800 } else {
801 status = unix_convert(conn, fname, False, NULL,&sbuf);
802 if (!NT_STATUS_IS_OK(status)) {
803 END_PROFILE(SMBgetatr);
804 return ERROR_NT(status);
806 status = check_name(conn, fname);
807 if (!NT_STATUS_IS_OK(status)) {
808 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
809 END_PROFILE(SMBgetatr);
810 return ERROR_NT(status);
812 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
813 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
814 return UNIXERROR(ERRDOS,ERRbadfile);
817 mode = dos_mode(conn,fname,&sbuf);
818 size = sbuf.st_size;
819 mtime = sbuf.st_mtime;
820 if (mode & aDIR) {
821 size = 0;
825 outsize = set_message(inbuf,outbuf,10,0,True);
827 SSVAL(outbuf,smb_vwv0,mode);
828 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
829 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
830 } else {
831 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
833 SIVAL(outbuf,smb_vwv3,(uint32)size);
835 if (Protocol >= PROTOCOL_NT1) {
836 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
839 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
841 END_PROFILE(SMBgetatr);
842 return(outsize);
845 /****************************************************************************
846 Reply to a setatr.
847 ****************************************************************************/
849 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
851 pstring fname;
852 int outsize = 0;
853 int mode;
854 time_t mtime;
855 SMB_STRUCT_STAT sbuf;
856 char *p;
857 NTSTATUS status;
859 START_PROFILE(SMBsetatr);
861 p = smb_buf(inbuf) + 1;
862 p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
863 sizeof(fname), 0, STR_TERMINATE, &status);
864 if (!NT_STATUS_IS_OK(status)) {
865 END_PROFILE(SMBsetatr);
866 return ERROR_NT(status);
869 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
870 if (!NT_STATUS_IS_OK(status)) {
871 END_PROFILE(SMBsetatr);
872 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
873 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
875 return ERROR_NT(status);
878 status = unix_convert(conn, fname, False, NULL, &sbuf);
879 if (!NT_STATUS_IS_OK(status)) {
880 END_PROFILE(SMBsetatr);
881 return ERROR_NT(status);
884 status = check_name(conn, fname);
885 if (!NT_STATUS_IS_OK(status)) {
886 END_PROFILE(SMBsetatr);
887 return ERROR_NT(status);
890 if (fname[0] == '.' && fname[1] == '\0') {
892 * Not sure here is the right place to catch this
893 * condition. Might be moved to somewhere else later -- vl
895 END_PROFILE(SMBsetatr);
896 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
899 mode = SVAL(inbuf,smb_vwv0);
900 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
902 if (mode != FILE_ATTRIBUTE_NORMAL) {
903 if (VALID_STAT_OF_DIR(sbuf))
904 mode |= aDIR;
905 else
906 mode &= ~aDIR;
908 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
909 END_PROFILE(SMBsetatr);
910 return UNIXERROR(ERRDOS, ERRnoaccess);
914 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
915 END_PROFILE(SMBsetatr);
916 return UNIXERROR(ERRDOS, ERRnoaccess);
919 outsize = set_message(inbuf,outbuf,0,0,False);
921 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
923 END_PROFILE(SMBsetatr);
924 return(outsize);
927 /****************************************************************************
928 Reply to a dskattr.
929 ****************************************************************************/
931 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
933 int outsize = 0;
934 SMB_BIG_UINT dfree,dsize,bsize;
935 START_PROFILE(SMBdskattr);
937 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
938 END_PROFILE(SMBdskattr);
939 return(UNIXERROR(ERRHRD,ERRgeneral));
942 outsize = set_message(inbuf,outbuf,5,0,True);
944 if (Protocol <= PROTOCOL_LANMAN2) {
945 double total_space, free_space;
946 /* we need to scale this to a number that DOS6 can handle. We
947 use floating point so we can handle large drives on systems
948 that don't have 64 bit integers
950 we end up displaying a maximum of 2G to DOS systems
952 total_space = dsize * (double)bsize;
953 free_space = dfree * (double)bsize;
955 dsize = (total_space+63*512) / (64*512);
956 dfree = (free_space+63*512) / (64*512);
958 if (dsize > 0xFFFF) dsize = 0xFFFF;
959 if (dfree > 0xFFFF) dfree = 0xFFFF;
961 SSVAL(outbuf,smb_vwv0,dsize);
962 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
963 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
964 SSVAL(outbuf,smb_vwv3,dfree);
965 } else {
966 SSVAL(outbuf,smb_vwv0,dsize);
967 SSVAL(outbuf,smb_vwv1,bsize/512);
968 SSVAL(outbuf,smb_vwv2,512);
969 SSVAL(outbuf,smb_vwv3,dfree);
972 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
974 END_PROFILE(SMBdskattr);
975 return(outsize);
978 /****************************************************************************
979 Reply to a search.
980 Can be called from SMBsearch, SMBffirst or SMBfunique.
981 ****************************************************************************/
983 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
985 pstring mask;
986 pstring directory;
987 pstring fname;
988 SMB_OFF_T size;
989 uint32 mode;
990 time_t date;
991 uint32 dirtype;
992 int outsize = 0;
993 unsigned int numentries = 0;
994 unsigned int maxentries = 0;
995 BOOL finished = False;
996 char *p;
997 int status_len;
998 pstring path;
999 char status[21];
1000 int dptr_num= -1;
1001 BOOL check_descend = False;
1002 BOOL expect_close = False;
1003 NTSTATUS nt_status;
1004 BOOL mask_contains_wcard = False;
1005 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1007 START_PROFILE(SMBsearch);
1009 if (lp_posix_pathnames()) {
1010 END_PROFILE(SMBsearch);
1011 return reply_unknown(inbuf, outbuf);
1014 *mask = *directory = *fname = 0;
1016 /* If we were called as SMBffirst then we must expect close. */
1017 if(CVAL(inbuf,smb_com) == SMBffirst) {
1018 expect_close = True;
1021 outsize = set_message(inbuf,outbuf,1,3,True);
1022 maxentries = SVAL(inbuf,smb_vwv0);
1023 dirtype = SVAL(inbuf,smb_vwv1);
1024 p = smb_buf(inbuf) + 1;
1025 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1026 sizeof(path), 0, STR_TERMINATE, &nt_status,
1027 &mask_contains_wcard);
1028 if (!NT_STATUS_IS_OK(nt_status)) {
1029 END_PROFILE(SMBsearch);
1030 return ERROR_NT(nt_status);
1033 nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
1034 if (!NT_STATUS_IS_OK(nt_status)) {
1035 END_PROFILE(SMBsearch);
1036 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1037 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1039 return ERROR_NT(nt_status);
1042 p++;
1043 status_len = SVAL(p, 0);
1044 p += 2;
1046 /* dirtype &= ~aDIR; */
1048 if (status_len == 0) {
1049 SMB_STRUCT_STAT sbuf;
1051 pstrcpy(directory,path);
1052 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1053 if (!NT_STATUS_IS_OK(nt_status)) {
1054 END_PROFILE(SMBsearch);
1055 return ERROR_NT(nt_status);
1058 nt_status = check_name(conn, directory);
1059 if (!NT_STATUS_IS_OK(nt_status)) {
1060 END_PROFILE(SMBsearch);
1061 return ERROR_NT(nt_status);
1064 p = strrchr_m(directory,'/');
1065 if (!p) {
1066 pstrcpy(mask,directory);
1067 pstrcpy(directory,".");
1068 } else {
1069 *p = 0;
1070 pstrcpy(mask,p+1);
1073 if (*directory == '\0') {
1074 pstrcpy(directory,".");
1076 memset((char *)status,'\0',21);
1077 SCVAL(status,0,(dirtype & 0x1F));
1078 } else {
1079 int status_dirtype;
1081 memcpy(status,p,21);
1082 status_dirtype = CVAL(status,0) & 0x1F;
1083 if (status_dirtype != (dirtype & 0x1F)) {
1084 dirtype = status_dirtype;
1087 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1088 if (!conn->dirptr) {
1089 goto SearchEmpty;
1091 string_set(&conn->dirpath,dptr_path(dptr_num));
1092 pstrcpy(mask, dptr_wcard(dptr_num));
1094 * For a 'continue' search we have no string. So
1095 * check from the initial saved string.
1097 mask_contains_wcard = ms_has_wild(mask);
1100 p = smb_buf(outbuf) + 3;
1102 if (status_len == 0) {
1103 nt_status = dptr_create(conn,
1104 directory,
1105 True,
1106 expect_close,
1107 SVAL(inbuf,smb_pid),
1108 mask,
1109 mask_contains_wcard,
1110 dirtype,
1111 &conn->dirptr);
1112 if (!NT_STATUS_IS_OK(nt_status)) {
1113 return ERROR_NT(nt_status);
1115 dptr_num = dptr_dnum(conn->dirptr);
1116 } else {
1117 dirtype = dptr_attr(dptr_num);
1120 DEBUG(4,("dptr_num is %d\n",dptr_num));
1122 if ((dirtype&0x1F) == aVOLID) {
1123 memcpy(p,status,21);
1124 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1125 0,aVOLID,0,!allow_long_path_components);
1126 dptr_fill(p+12,dptr_num);
1127 if (dptr_zero(p+12) && (status_len==0)) {
1128 numentries = 1;
1129 } else {
1130 numentries = 0;
1132 p += DIR_STRUCT_SIZE;
1133 } else {
1134 unsigned int i;
1135 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1137 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1138 conn->dirpath,lp_dontdescend(SNUM(conn))));
1139 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1140 check_descend = True;
1143 for (i=numentries;(i<maxentries) && !finished;i++) {
1144 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1145 if (!finished) {
1146 memcpy(p,status,21);
1147 make_dir_struct(p,mask,fname,size, mode,date,
1148 !allow_long_path_components);
1149 if (!dptr_fill(p+12,dptr_num)) {
1150 break;
1152 numentries++;
1153 p += DIR_STRUCT_SIZE;
1158 SearchEmpty:
1160 /* If we were called as SMBffirst with smb_search_id == NULL
1161 and no entries were found then return error and close dirptr
1162 (X/Open spec) */
1164 if (numentries == 0) {
1165 dptr_close(&dptr_num);
1166 } else if(expect_close && status_len == 0) {
1167 /* Close the dptr - we know it's gone */
1168 dptr_close(&dptr_num);
1171 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1172 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1173 dptr_close(&dptr_num);
1176 if ((numentries == 0) && !mask_contains_wcard) {
1177 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1180 SSVAL(outbuf,smb_vwv0,numentries);
1181 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1182 SCVAL(smb_buf(outbuf),0,5);
1183 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1185 /* The replies here are never long name. */
1186 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1187 if (!allow_long_path_components) {
1188 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1191 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1192 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1194 outsize += DIR_STRUCT_SIZE*numentries;
1195 smb_setlen(inbuf,outbuf,outsize - 4);
1197 if ((! *directory) && dptr_path(dptr_num))
1198 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1200 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1201 smb_fn_name(CVAL(inbuf,smb_com)),
1202 mask, directory, dirtype, numentries, maxentries ) );
1204 END_PROFILE(SMBsearch);
1205 return(outsize);
1208 /****************************************************************************
1209 Reply to a fclose (stop directory search).
1210 ****************************************************************************/
1212 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1214 int outsize = 0;
1215 int status_len;
1216 pstring path;
1217 char status[21];
1218 int dptr_num= -2;
1219 char *p;
1220 NTSTATUS err;
1221 BOOL path_contains_wcard = False;
1223 START_PROFILE(SMBfclose);
1225 if (lp_posix_pathnames()) {
1226 END_PROFILE(SMBfclose);
1227 return reply_unknown(inbuf, outbuf);
1230 outsize = set_message(inbuf,outbuf,1,0,True);
1231 p = smb_buf(inbuf) + 1;
1232 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
1233 sizeof(path), 0, STR_TERMINATE, &err,
1234 &path_contains_wcard);
1235 if (!NT_STATUS_IS_OK(err)) {
1236 END_PROFILE(SMBfclose);
1237 return ERROR_NT(err);
1239 p++;
1240 status_len = SVAL(p,0);
1241 p += 2;
1243 if (status_len == 0) {
1244 END_PROFILE(SMBfclose);
1245 return ERROR_DOS(ERRSRV,ERRsrverror);
1248 memcpy(status,p,21);
1250 if(dptr_fetch(status+12,&dptr_num)) {
1251 /* Close the dptr - we know it's gone */
1252 dptr_close(&dptr_num);
1255 SSVAL(outbuf,smb_vwv0,0);
1257 DEBUG(3,("search close\n"));
1259 END_PROFILE(SMBfclose);
1260 return(outsize);
1263 /****************************************************************************
1264 Reply to an open.
1265 ****************************************************************************/
1267 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1269 pstring fname;
1270 int outsize = 0;
1271 uint32 fattr=0;
1272 SMB_OFF_T size = 0;
1273 time_t mtime=0;
1274 int info;
1275 SMB_STRUCT_STAT sbuf;
1276 files_struct *fsp;
1277 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1278 int deny_mode;
1279 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1280 uint32 access_mask;
1281 uint32 share_mode;
1282 uint32 create_disposition;
1283 uint32 create_options = 0;
1284 NTSTATUS status;
1285 struct smb_request req;
1287 START_PROFILE(SMBopen);
1289 init_smb_request(&req, (uint8 *)inbuf);
1291 deny_mode = SVAL(inbuf,smb_vwv0);
1293 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1294 sizeof(fname), 0, STR_TERMINATE, &status);
1295 if (!NT_STATUS_IS_OK(status)) {
1296 END_PROFILE(SMBopen);
1297 return ERROR_NT(status);
1300 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 END_PROFILE(SMBopen);
1303 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1304 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1306 return ERROR_NT(status);
1309 status = unix_convert(conn, fname, False, NULL, &sbuf);
1310 if (!NT_STATUS_IS_OK(status)) {
1311 END_PROFILE(SMBopen);
1312 return ERROR_NT(status);
1315 status = check_name(conn, fname);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 END_PROFILE(SMBopen);
1318 return ERROR_NT(status);
1321 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1322 &access_mask, &share_mode, &create_disposition, &create_options)) {
1323 END_PROFILE(SMBopen);
1324 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1327 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1328 access_mask,
1329 share_mode,
1330 create_disposition,
1331 create_options,
1332 dos_attr,
1333 oplock_request,
1334 &info, &fsp);
1336 if (!NT_STATUS_IS_OK(status)) {
1337 END_PROFILE(SMBopen);
1338 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1339 /* We have re-scheduled this call. */
1340 return -1;
1342 return ERROR_NT(status);
1345 size = sbuf.st_size;
1346 fattr = dos_mode(conn,fname,&sbuf);
1347 mtime = sbuf.st_mtime;
1349 if (fattr & aDIR) {
1350 DEBUG(3,("attempt to open a directory %s\n",fname));
1351 close_file(fsp,ERROR_CLOSE);
1352 END_PROFILE(SMBopen);
1353 return ERROR_DOS(ERRDOS,ERRnoaccess);
1356 outsize = set_message(inbuf,outbuf,7,0,True);
1357 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1358 SSVAL(outbuf,smb_vwv1,fattr);
1359 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1360 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1361 } else {
1362 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1364 SIVAL(outbuf,smb_vwv4,(uint32)size);
1365 SSVAL(outbuf,smb_vwv6,deny_mode);
1367 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1368 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1371 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1372 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1374 END_PROFILE(SMBopen);
1375 return(outsize);
1378 /****************************************************************************
1379 Reply to an open and X.
1380 ****************************************************************************/
1382 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1384 pstring fname;
1385 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1386 int deny_mode = SVAL(inbuf,smb_vwv3);
1387 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1388 /* Breakout the oplock request bits so we can set the
1389 reply bits separately. */
1390 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1391 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1392 int oplock_request = ex_oplock_request | core_oplock_request;
1393 #if 0
1394 int smb_sattr = SVAL(inbuf,smb_vwv4);
1395 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1396 #endif
1397 int smb_ofun = SVAL(inbuf,smb_vwv8);
1398 uint32 fattr=0;
1399 int mtime=0;
1400 SMB_STRUCT_STAT sbuf;
1401 int smb_action = 0;
1402 files_struct *fsp;
1403 NTSTATUS status;
1404 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1405 ssize_t retval = -1;
1406 uint32 access_mask;
1407 uint32 share_mode;
1408 uint32 create_disposition;
1409 uint32 create_options = 0;
1410 struct smb_request req;
1412 START_PROFILE(SMBopenX);
1414 init_smb_request(&req, (uint8 *)inbuf);
1416 /* If it's an IPC, pass off the pipe handler. */
1417 if (IS_IPC(conn)) {
1418 if (lp_nt_pipe_support()) {
1419 END_PROFILE(SMBopenX);
1420 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1421 } else {
1422 END_PROFILE(SMBopenX);
1423 return ERROR_DOS(ERRSRV,ERRaccess);
1427 /* XXXX we need to handle passed times, sattr and flags */
1428 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf),
1429 sizeof(fname), 0, STR_TERMINATE, &status);
1430 if (!NT_STATUS_IS_OK(status)) {
1431 END_PROFILE(SMBopenX);
1432 return ERROR_NT(status);
1435 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1436 if (!NT_STATUS_IS_OK(status)) {
1437 END_PROFILE(SMBopenX);
1438 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1439 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1441 return ERROR_NT(status);
1444 status = unix_convert(conn, fname, False, NULL, &sbuf);
1445 if (!NT_STATUS_IS_OK(status)) {
1446 END_PROFILE(SMBopenX);
1447 return ERROR_NT(status);
1450 status = check_name(conn, fname);
1451 if (!NT_STATUS_IS_OK(status)) {
1452 END_PROFILE(SMBopenX);
1453 return ERROR_NT(status);
1456 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1457 &access_mask,
1458 &share_mode,
1459 &create_disposition,
1460 &create_options)) {
1461 END_PROFILE(SMBopenX);
1462 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1465 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1466 access_mask,
1467 share_mode,
1468 create_disposition,
1469 create_options,
1470 smb_attr,
1471 oplock_request,
1472 &smb_action, &fsp);
1474 if (!NT_STATUS_IS_OK(status)) {
1475 END_PROFILE(SMBopenX);
1476 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1477 /* We have re-scheduled this call. */
1478 return -1;
1480 return ERROR_NT(status);
1483 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1484 if the file is truncated or created. */
1485 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1486 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1487 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1488 close_file(fsp,ERROR_CLOSE);
1489 END_PROFILE(SMBopenX);
1490 return ERROR_NT(NT_STATUS_DISK_FULL);
1492 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1493 if (retval < 0) {
1494 close_file(fsp,ERROR_CLOSE);
1495 END_PROFILE(SMBopenX);
1496 return ERROR_NT(NT_STATUS_DISK_FULL);
1498 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1501 fattr = dos_mode(conn,fname,&sbuf);
1502 mtime = sbuf.st_mtime;
1503 if (fattr & aDIR) {
1504 close_file(fsp,ERROR_CLOSE);
1505 END_PROFILE(SMBopenX);
1506 return ERROR_DOS(ERRDOS,ERRnoaccess);
1509 /* If the caller set the extended oplock request bit
1510 and we granted one (by whatever means) - set the
1511 correct bit for extended oplock reply.
1514 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1515 smb_action |= EXTENDED_OPLOCK_GRANTED;
1518 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1519 smb_action |= EXTENDED_OPLOCK_GRANTED;
1522 /* If the caller set the core oplock request bit
1523 and we granted one (by whatever means) - set the
1524 correct bit for core oplock reply.
1527 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1528 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1531 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1532 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1535 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1536 set_message(inbuf,outbuf,19,0,True);
1537 } else {
1538 set_message(inbuf,outbuf,15,0,True);
1540 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1541 SSVAL(outbuf,smb_vwv3,fattr);
1542 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1543 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1544 } else {
1545 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1547 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1548 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1549 SSVAL(outbuf,smb_vwv11,smb_action);
1551 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1552 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1555 END_PROFILE(SMBopenX);
1556 return chain_reply(inbuf,outbuf,length,bufsize);
1559 /****************************************************************************
1560 Reply to a SMBulogoffX.
1561 conn POINTER CAN BE NULL HERE !
1562 ****************************************************************************/
1564 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1566 uint16 vuid = SVAL(inbuf,smb_uid);
1567 user_struct *vuser = get_valid_user_struct(vuid);
1568 START_PROFILE(SMBulogoffX);
1570 if(vuser == 0)
1571 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1573 /* in user level security we are supposed to close any files
1574 open by this user */
1575 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1576 file_close_user(vuid);
1578 invalidate_vuid(vuid);
1580 set_message(inbuf,outbuf,2,0,True);
1582 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1584 END_PROFILE(SMBulogoffX);
1585 return chain_reply(inbuf,outbuf,length,bufsize);
1588 /****************************************************************************
1589 Reply to a mknew or a create.
1590 ****************************************************************************/
1592 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1594 pstring fname;
1595 int com;
1596 int outsize = 0;
1597 uint32 fattr = SVAL(inbuf,smb_vwv0);
1598 struct timespec ts[2];
1599 files_struct *fsp;
1600 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1601 SMB_STRUCT_STAT sbuf;
1602 NTSTATUS status;
1603 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1604 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1605 uint32 create_disposition;
1606 uint32 create_options = 0;
1607 struct smb_request req;
1609 START_PROFILE(SMBcreate);
1611 init_smb_request(&req, (uint8 *)inbuf);
1613 com = SVAL(inbuf,smb_com);
1615 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1617 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1,
1618 sizeof(fname), 0, STR_TERMINATE, &status);
1619 if (!NT_STATUS_IS_OK(status)) {
1620 END_PROFILE(SMBcreate);
1621 return ERROR_NT(status);
1624 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1625 if (!NT_STATUS_IS_OK(status)) {
1626 END_PROFILE(SMBcreate);
1627 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1628 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1630 return ERROR_NT(status);
1633 status = unix_convert(conn, fname, False, NULL, &sbuf);
1634 if (!NT_STATUS_IS_OK(status)) {
1635 END_PROFILE(SMBcreate);
1636 return ERROR_NT(status);
1639 status = check_name(conn, fname);
1640 if (!NT_STATUS_IS_OK(status)) {
1641 END_PROFILE(SMBcreate);
1642 return ERROR_NT(status);
1645 if (fattr & aVOLID) {
1646 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1649 if(com == SMBmknew) {
1650 /* We should fail if file exists. */
1651 create_disposition = FILE_CREATE;
1652 } else {
1653 /* Create if file doesn't exist, truncate if it does. */
1654 create_disposition = FILE_OVERWRITE_IF;
1657 /* Open file using ntcreate. */
1658 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1659 access_mask,
1660 share_mode,
1661 create_disposition,
1662 create_options,
1663 fattr,
1664 oplock_request,
1665 NULL, &fsp);
1667 if (!NT_STATUS_IS_OK(status)) {
1668 END_PROFILE(SMBcreate);
1669 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1670 /* We have re-scheduled this call. */
1671 return -1;
1673 return ERROR_NT(status);
1676 ts[0] = get_atimespec(&sbuf); /* atime. */
1677 file_ntimes(conn, fname, ts);
1679 outsize = set_message(inbuf,outbuf,1,0,True);
1680 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1682 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1683 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1686 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1687 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1690 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1691 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1693 END_PROFILE(SMBcreate);
1694 return(outsize);
1697 /****************************************************************************
1698 Reply to a create temporary file.
1699 ****************************************************************************/
1701 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1703 pstring fname;
1704 int outsize = 0;
1705 uint32 fattr = SVAL(inbuf,smb_vwv0);
1706 files_struct *fsp;
1707 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1708 int tmpfd;
1709 SMB_STRUCT_STAT sbuf;
1710 char *p, *s;
1711 NTSTATUS status;
1712 unsigned int namelen;
1713 struct smb_request req;
1715 START_PROFILE(SMBctemp);
1717 init_smb_request(&req, (uint8 *)inbuf);
1719 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
1720 sizeof(fname), 0, STR_TERMINATE, &status);
1721 if (!NT_STATUS_IS_OK(status)) {
1722 END_PROFILE(SMBctemp);
1723 return ERROR_NT(status);
1725 if (*fname) {
1726 pstrcat(fname,"/TMXXXXXX");
1727 } else {
1728 pstrcat(fname,"TMXXXXXX");
1731 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1732 if (!NT_STATUS_IS_OK(status)) {
1733 END_PROFILE(SMBctemp);
1734 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1735 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1737 return ERROR_NT(status);
1740 status = unix_convert(conn, fname, False, NULL, &sbuf);
1741 if (!NT_STATUS_IS_OK(status)) {
1742 END_PROFILE(SMBctemp);
1743 return ERROR_NT(status);
1746 status = check_name(conn, fname);
1747 if (!NT_STATUS_IS_OK(status)) {
1748 END_PROFILE(SMBctemp);
1749 return ERROR_NT(status);
1752 tmpfd = smb_mkstemp(fname);
1753 if (tmpfd == -1) {
1754 END_PROFILE(SMBctemp);
1755 return(UNIXERROR(ERRDOS,ERRnoaccess));
1758 SMB_VFS_STAT(conn,fname,&sbuf);
1760 /* We should fail if file does not exist. */
1761 status = open_file_ntcreate(conn, &req, fname, &sbuf,
1762 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1763 FILE_SHARE_READ|FILE_SHARE_WRITE,
1764 FILE_OPEN,
1766 fattr,
1767 oplock_request,
1768 NULL, &fsp);
1770 /* close fd from smb_mkstemp() */
1771 close(tmpfd);
1773 if (!NT_STATUS_IS_OK(status)) {
1774 END_PROFILE(SMBctemp);
1775 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1776 /* We have re-scheduled this call. */
1777 return -1;
1779 return ERROR_NT(status);
1782 outsize = set_message(inbuf,outbuf,1,0,True);
1783 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1785 /* the returned filename is relative to the directory */
1786 s = strrchr_m(fname, '/');
1787 if (!s) {
1788 s = fname;
1789 } else {
1790 s++;
1793 p = smb_buf(outbuf);
1794 #if 0
1795 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1796 thing in the byte section. JRA */
1797 SSVALS(p, 0, -1); /* what is this? not in spec */
1798 #endif
1799 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1800 p += namelen;
1801 outsize = set_message_end(inbuf,outbuf, p);
1803 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1804 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1807 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1808 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1811 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1812 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1813 (unsigned int)sbuf.st_mode ) );
1815 END_PROFILE(SMBctemp);
1816 return(outsize);
1819 /*******************************************************************
1820 Check if a user is allowed to rename a file.
1821 ********************************************************************/
1823 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1824 uint16 dirtype, SMB_STRUCT_STAT *pst)
1826 uint32 fmode;
1828 if (!CAN_WRITE(conn)) {
1829 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1832 fmode = dos_mode(conn, fsp->fsp_name, pst);
1833 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1834 return NT_STATUS_NO_SUCH_FILE;
1837 if (S_ISDIR(pst->st_mode)) {
1838 return NT_STATUS_OK;
1841 if (fsp->access_mask & DELETE_ACCESS) {
1842 return NT_STATUS_OK;
1845 return NT_STATUS_ACCESS_DENIED;
1848 /*******************************************************************
1849 * unlink a file with all relevant access checks
1850 *******************************************************************/
1852 static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
1853 char *fname, uint32 dirtype)
1855 SMB_STRUCT_STAT sbuf;
1856 uint32 fattr;
1857 files_struct *fsp;
1858 uint32 dirtype_orig = dirtype;
1859 NTSTATUS status;
1861 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
1863 if (!CAN_WRITE(conn)) {
1864 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1867 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1868 return map_nt_error_from_unix(errno);
1871 fattr = dos_mode(conn,fname,&sbuf);
1873 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1874 dirtype = aDIR|aARCH|aRONLY;
1877 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1878 if (!dirtype) {
1879 return NT_STATUS_NO_SUCH_FILE;
1882 if (!dir_check_ftype(conn, fattr, dirtype)) {
1883 if (fattr & aDIR) {
1884 return NT_STATUS_FILE_IS_A_DIRECTORY;
1886 return NT_STATUS_NO_SUCH_FILE;
1889 if (dirtype_orig & 0x8000) {
1890 /* These will never be set for POSIX. */
1891 return NT_STATUS_NO_SUCH_FILE;
1894 #if 0
1895 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1896 return NT_STATUS_FILE_IS_A_DIRECTORY;
1899 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1900 return NT_STATUS_NO_SUCH_FILE;
1903 if (dirtype & 0xFF00) {
1904 /* These will never be set for POSIX. */
1905 return NT_STATUS_NO_SUCH_FILE;
1908 dirtype &= 0xFF;
1909 if (!dirtype) {
1910 return NT_STATUS_NO_SUCH_FILE;
1913 /* Can't delete a directory. */
1914 if (fattr & aDIR) {
1915 return NT_STATUS_FILE_IS_A_DIRECTORY;
1917 #endif
1919 #if 0 /* JRATEST */
1920 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1921 return NT_STATUS_OBJECT_NAME_INVALID;
1922 #endif /* JRATEST */
1924 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1926 On a Windows share, a file with read-only dosmode can be opened with
1927 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1928 fails with NT_STATUS_CANNOT_DELETE error.
1930 This semantic causes a problem that a user can not
1931 rename a file with read-only dosmode on a Samba share
1932 from a Windows command prompt (i.e. cmd.exe, but can rename
1933 from Windows Explorer).
1936 if (!lp_delete_readonly(SNUM(conn))) {
1937 if (fattr & aRONLY) {
1938 return NT_STATUS_CANNOT_DELETE;
1942 /* On open checks the open itself will check the share mode, so
1943 don't do it here as we'll get it wrong. */
1945 status = open_file_ntcreate(conn, req, fname, &sbuf,
1946 DELETE_ACCESS,
1947 FILE_SHARE_NONE,
1948 FILE_OPEN,
1950 FILE_ATTRIBUTE_NORMAL,
1951 req != NULL ? 0 : INTERNAL_OPEN_ONLY,
1952 NULL, &fsp);
1954 if (!NT_STATUS_IS_OK(status)) {
1955 DEBUG(10, ("open_file_ntcreate failed: %s\n",
1956 nt_errstr(status)));
1957 return status;
1960 /* The set is across all open files on this dev/inode pair. */
1961 if (!set_delete_on_close(fsp, True, &current_user.ut)) {
1962 close_file(fsp, NORMAL_CLOSE);
1963 return NT_STATUS_ACCESS_DENIED;
1966 return close_file(fsp,NORMAL_CLOSE);
1969 /****************************************************************************
1970 The guts of the unlink command, split out so it may be called by the NT SMB
1971 code.
1972 ****************************************************************************/
1974 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
1975 uint32 dirtype, char *name, BOOL has_wild)
1977 pstring directory;
1978 pstring mask;
1979 char *p;
1980 int count=0;
1981 NTSTATUS status = NT_STATUS_OK;
1982 SMB_STRUCT_STAT sbuf;
1984 *directory = *mask = 0;
1986 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1987 if (!NT_STATUS_IS_OK(status)) {
1988 return status;
1991 p = strrchr_m(name,'/');
1992 if (!p) {
1993 pstrcpy(directory,".");
1994 pstrcpy(mask,name);
1995 } else {
1996 *p = 0;
1997 pstrcpy(directory,name);
1998 pstrcpy(mask,p+1);
2002 * We should only check the mangled cache
2003 * here if unix_convert failed. This means
2004 * that the path in 'mask' doesn't exist
2005 * on the file system and so we need to look
2006 * for a possible mangle. This patch from
2007 * Tine Smukavec <valentin.smukavec@hermes.si>.
2010 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
2011 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
2013 if (!has_wild) {
2014 pstrcat(directory,"/");
2015 pstrcat(directory,mask);
2016 if (dirtype == 0) {
2017 dirtype = FILE_ATTRIBUTE_NORMAL;
2020 status = check_name(conn, directory);
2021 if (!NT_STATUS_IS_OK(status)) {
2022 return status;
2025 status = do_unlink(conn, req, directory, dirtype);
2026 if (!NT_STATUS_IS_OK(status)) {
2027 return status;
2030 count++;
2031 } else {
2032 struct smb_Dir *dir_hnd = NULL;
2033 long offset = 0;
2034 const char *dname;
2036 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2037 return NT_STATUS_OBJECT_NAME_INVALID;
2040 if (strequal(mask,"????????.???")) {
2041 pstrcpy(mask,"*");
2044 status = check_name(conn, directory);
2045 if (!NT_STATUS_IS_OK(status)) {
2046 return status;
2049 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2050 if (dir_hnd == NULL) {
2051 return map_nt_error_from_unix(errno);
2054 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2055 the pattern matches against the long name, otherwise the short name
2056 We don't implement this yet XXXX
2059 status = NT_STATUS_NO_SUCH_FILE;
2061 while ((dname = ReadDirName(dir_hnd, &offset))) {
2062 SMB_STRUCT_STAT st;
2063 pstring fname;
2064 pstrcpy(fname,dname);
2066 if (!is_visible_file(conn, directory, dname, &st, True)) {
2067 continue;
2070 /* Quick check for "." and ".." */
2071 if (fname[0] == '.') {
2072 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2073 continue;
2077 if(!mask_match(fname, mask, conn->case_sensitive)) {
2078 continue;
2081 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2083 status = check_name(conn, fname);
2084 if (!NT_STATUS_IS_OK(status)) {
2085 CloseDir(dir_hnd);
2086 return status;
2089 status = do_unlink(conn, req, fname, dirtype);
2090 if (!NT_STATUS_IS_OK(status)) {
2091 continue;
2094 count++;
2095 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2096 fname));
2098 CloseDir(dir_hnd);
2101 if (count == 0 && NT_STATUS_IS_OK(status)) {
2102 status = map_nt_error_from_unix(errno);
2105 return status;
2108 /****************************************************************************
2109 Reply to a unlink
2110 ****************************************************************************/
2112 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2113 int dum_buffsize)
2115 int outsize = 0;
2116 pstring name;
2117 uint32 dirtype;
2118 NTSTATUS status;
2119 BOOL path_contains_wcard = False;
2120 struct smb_request req;
2122 START_PROFILE(SMBunlink);
2124 init_smb_request(&req, (uint8 *)inbuf);
2126 dirtype = SVAL(inbuf,smb_vwv0);
2128 srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name,
2129 smb_buf(inbuf) + 1, sizeof(name), 0,
2130 STR_TERMINATE, &status, &path_contains_wcard);
2131 if (!NT_STATUS_IS_OK(status)) {
2132 END_PROFILE(SMBunlink);
2133 return ERROR_NT(status);
2136 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
2137 if (!NT_STATUS_IS_OK(status)) {
2138 END_PROFILE(SMBunlink);
2139 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2140 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
2142 return ERROR_NT(status);
2145 DEBUG(3,("reply_unlink : %s\n",name));
2147 status = unlink_internals(conn, &req, dirtype, name,
2148 path_contains_wcard);
2149 if (!NT_STATUS_IS_OK(status)) {
2150 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2151 /* We have re-scheduled this call. */
2152 return -1;
2154 return ERROR_NT(status);
2157 outsize = set_message(inbuf,outbuf,0,0,False);
2159 END_PROFILE(SMBunlink);
2160 return outsize;
2163 /****************************************************************************
2164 Fail for readbraw.
2165 ****************************************************************************/
2167 static void fail_readraw(void)
2169 pstring errstr;
2170 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2171 strerror(errno) );
2172 exit_server_cleanly(errstr);
2175 /****************************************************************************
2176 Fake (read/write) sendfile. Returns -1 on read or write fail.
2177 ****************************************************************************/
2179 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
2181 size_t tosend = nread;
2183 while (tosend > 0) {
2184 ssize_t ret;
2185 size_t cur_read;
2187 if (tosend > bufsize) {
2188 cur_read = bufsize;
2189 } else {
2190 cur_read = tosend;
2192 ret = read_file(fsp,buf,startpos,cur_read);
2193 if (ret == -1) {
2194 return -1;
2197 /* If we had a short read, fill with zeros. */
2198 if (ret < cur_read) {
2199 memset(buf, '\0', cur_read - ret);
2202 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2203 return -1;
2205 tosend -= cur_read;
2206 startpos += cur_read;
2209 return (ssize_t)nread;
2212 /****************************************************************************
2213 Use sendfile in readbraw.
2214 ****************************************************************************/
2216 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2217 ssize_t mincount, char *outbuf, int out_buffsize)
2219 ssize_t ret=0;
2221 #if defined(WITH_SENDFILE)
2223 * We can only use sendfile on a non-chained packet
2224 * but we can use on a non-oplocked file. tridge proved this
2225 * on a train in Germany :-). JRA.
2226 * reply_readbraw has already checked the length.
2229 if ( (chain_size == 0) && (nread > 0) &&
2230 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2231 DATA_BLOB header;
2233 _smb_setlen(outbuf,nread);
2234 header.data = (uint8 *)outbuf;
2235 header.length = 4;
2236 header.free = NULL;
2238 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2239 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2240 if (errno == ENOSYS) {
2241 goto normal_readbraw;
2245 * Special hack for broken Linux with no working sendfile. If we
2246 * return EINTR we sent the header but not the rest of the data.
2247 * Fake this up by doing read/write calls.
2249 if (errno == EINTR) {
2250 /* Ensure we don't do this again. */
2251 set_use_sendfile(SNUM(conn), False);
2252 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2254 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2255 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2256 fsp->fsp_name, strerror(errno) ));
2257 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2259 return;
2262 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2263 fsp->fsp_name, strerror(errno) ));
2264 exit_server_cleanly("send_file_readbraw sendfile failed");
2267 return;
2269 #endif
2271 normal_readbraw:
2273 if (nread > 0) {
2274 ret = read_file(fsp,outbuf+4,startpos,nread);
2275 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2276 if (ret < mincount)
2277 ret = 0;
2278 #else
2279 if (ret < nread)
2280 ret = 0;
2281 #endif
2284 _smb_setlen(outbuf,ret);
2285 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2286 fail_readraw();
2289 /****************************************************************************
2290 Reply to a readbraw (core+ protocol).
2291 ****************************************************************************/
2293 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2295 ssize_t maxcount,mincount;
2296 size_t nread = 0;
2297 SMB_OFF_T startpos;
2298 char *header = outbuf;
2299 files_struct *fsp;
2300 START_PROFILE(SMBreadbraw);
2302 if (srv_is_signing_active()) {
2303 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2307 * Special check if an oplock break has been issued
2308 * and the readraw request croses on the wire, we must
2309 * return a zero length response here.
2312 fsp = file_fsp(inbuf,smb_vwv0);
2314 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2316 * fsp could be NULL here so use the value from the packet. JRA.
2318 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2319 _smb_setlen(header,0);
2320 if (write_data(smbd_server_fd(),header,4) != 4)
2321 fail_readraw();
2322 END_PROFILE(SMBreadbraw);
2323 return(-1);
2326 CHECK_FSP(fsp,conn);
2328 flush_write_cache(fsp, READRAW_FLUSH);
2330 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2331 if(CVAL(inbuf,smb_wct) == 10) {
2333 * This is a large offset (64 bit) read.
2335 #ifdef LARGE_SMB_OFF_T
2337 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2339 #else /* !LARGE_SMB_OFF_T */
2342 * Ensure we haven't been sent a >32 bit offset.
2345 if(IVAL(inbuf,smb_vwv8) != 0) {
2346 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2347 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2348 _smb_setlen(header,0);
2349 if (write_data(smbd_server_fd(),header,4) != 4)
2350 fail_readraw();
2351 END_PROFILE(SMBreadbraw);
2352 return(-1);
2355 #endif /* LARGE_SMB_OFF_T */
2357 if(startpos < 0) {
2358 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2359 _smb_setlen(header,0);
2360 if (write_data(smbd_server_fd(),header,4) != 4)
2361 fail_readraw();
2362 END_PROFILE(SMBreadbraw);
2363 return(-1);
2366 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2367 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2369 /* ensure we don't overrun the packet size */
2370 maxcount = MIN(65535,maxcount);
2372 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2373 SMB_STRUCT_STAT st;
2374 SMB_OFF_T size = 0;
2376 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2377 size = st.st_size;
2380 if (startpos >= size) {
2381 nread = 0;
2382 } else {
2383 nread = MIN(maxcount,(size - startpos));
2387 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2388 if (nread < mincount)
2389 nread = 0;
2390 #endif
2392 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2393 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2395 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2397 DEBUG(5,("readbraw finished\n"));
2398 END_PROFILE(SMBreadbraw);
2399 return -1;
2402 #undef DBGC_CLASS
2403 #define DBGC_CLASS DBGC_LOCKING
2405 /****************************************************************************
2406 Reply to a lockread (core+ protocol).
2407 ****************************************************************************/
2409 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2411 ssize_t nread = -1;
2412 char *data;
2413 int outsize = 0;
2414 SMB_OFF_T startpos;
2415 size_t numtoread;
2416 NTSTATUS status;
2417 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2418 struct byte_range_lock *br_lck = NULL;
2419 START_PROFILE(SMBlockread);
2421 CHECK_FSP(fsp,conn);
2422 if (!CHECK_READ(fsp,inbuf)) {
2423 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2426 release_level_2_oplocks_on_change(fsp);
2428 numtoread = SVAL(inbuf,smb_vwv1);
2429 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2431 outsize = set_message(inbuf,outbuf,5,3,True);
2432 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2433 data = smb_buf(outbuf) + 3;
2436 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2437 * protocol request that predates the read/write lock concept.
2438 * Thus instead of asking for a read lock here we need to ask
2439 * for a write lock. JRA.
2440 * Note that the requested lock size is unaffected by max_recv.
2443 br_lck = do_lock(smbd_messaging_context(),
2444 fsp,
2445 (uint32)SVAL(inbuf,smb_pid),
2446 (SMB_BIG_UINT)numtoread,
2447 (SMB_BIG_UINT)startpos,
2448 WRITE_LOCK,
2449 WINDOWS_LOCK,
2450 False, /* Non-blocking lock. */
2451 &status,
2452 NULL);
2453 TALLOC_FREE(br_lck);
2455 if (NT_STATUS_V(status)) {
2456 END_PROFILE(SMBlockread);
2457 return ERROR_NT(status);
2461 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2464 if (numtoread > max_recv) {
2465 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2466 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2467 (unsigned int)numtoread, (unsigned int)max_recv ));
2468 numtoread = MIN(numtoread,max_recv);
2470 nread = read_file(fsp,data,startpos,numtoread);
2472 if (nread < 0) {
2473 END_PROFILE(SMBlockread);
2474 return(UNIXERROR(ERRDOS,ERRnoaccess));
2477 outsize += nread;
2478 SSVAL(outbuf,smb_vwv0,nread);
2479 SSVAL(outbuf,smb_vwv5,nread+3);
2480 SSVAL(smb_buf(outbuf),1,nread);
2482 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2483 fsp->fnum, (int)numtoread, (int)nread));
2485 END_PROFILE(SMBlockread);
2486 return(outsize);
2489 #undef DBGC_CLASS
2490 #define DBGC_CLASS DBGC_ALL
2492 /****************************************************************************
2493 Reply to a read.
2494 ****************************************************************************/
2496 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2498 size_t numtoread;
2499 ssize_t nread = 0;
2500 char *data;
2501 SMB_OFF_T startpos;
2502 int outsize = 0;
2503 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2504 START_PROFILE(SMBread);
2506 CHECK_FSP(fsp,conn);
2507 if (!CHECK_READ(fsp,inbuf)) {
2508 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2511 numtoread = SVAL(inbuf,smb_vwv1);
2512 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2514 outsize = set_message(inbuf,outbuf,5,3,True);
2515 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2517 * The requested read size cannot be greater than max_recv. JRA.
2519 if (numtoread > max_recv) {
2520 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2521 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2522 (unsigned int)numtoread, (unsigned int)max_recv ));
2523 numtoread = MIN(numtoread,max_recv);
2526 data = smb_buf(outbuf) + 3;
2528 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2529 END_PROFILE(SMBread);
2530 return ERROR_DOS(ERRDOS,ERRlock);
2533 if (numtoread > 0)
2534 nread = read_file(fsp,data,startpos,numtoread);
2536 if (nread < 0) {
2537 END_PROFILE(SMBread);
2538 return(UNIXERROR(ERRDOS,ERRnoaccess));
2541 outsize += nread;
2542 SSVAL(outbuf,smb_vwv0,nread);
2543 SSVAL(outbuf,smb_vwv5,nread+3);
2544 SCVAL(smb_buf(outbuf),0,1);
2545 SSVAL(smb_buf(outbuf),1,nread);
2547 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2548 fsp->fnum, (int)numtoread, (int)nread ) );
2550 END_PROFILE(SMBread);
2551 return(outsize);
2554 /****************************************************************************
2555 Setup readX header.
2556 ****************************************************************************/
2558 static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
2560 int outsize;
2561 char *data = smb_buf(outbuf);
2563 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2564 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2565 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2566 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2567 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2568 SCVAL(outbuf,smb_vwv0,0xFF);
2569 outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
2570 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2571 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2572 return outsize;
2575 /****************************************************************************
2576 Reply to a read and X - possibly using sendfile.
2577 ****************************************************************************/
2579 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2580 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2582 SMB_STRUCT_STAT sbuf;
2583 int outsize = 0;
2584 ssize_t nread = -1;
2585 char *data = smb_buf(outbuf);
2587 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2588 return(UNIXERROR(ERRDOS,ERRnoaccess));
2591 if (startpos > sbuf.st_size) {
2592 smb_maxcnt = 0;
2595 if (smb_maxcnt > (sbuf.st_size - startpos)) {
2596 smb_maxcnt = (sbuf.st_size - startpos);
2599 if (smb_maxcnt == 0) {
2600 goto normal_read;
2603 #if defined(WITH_SENDFILE)
2605 * We can only use sendfile on a non-chained packet
2606 * but we can use on a non-oplocked file. tridge proved this
2607 * on a train in Germany :-). JRA.
2610 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2611 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2612 DATA_BLOB header;
2615 * Set up the packet header before send. We
2616 * assume here the sendfile will work (get the
2617 * correct amount of data).
2620 setup_readX_header(inbuf,outbuf,smb_maxcnt);
2621 set_message(inbuf,outbuf,12,smb_maxcnt,False);
2622 header.data = (uint8 *)outbuf;
2623 header.length = data - outbuf;
2624 header.free = NULL;
2626 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2627 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2628 if (errno == ENOSYS) {
2629 goto normal_read;
2633 * Special hack for broken Linux with no working sendfile. If we
2634 * return EINTR we sent the header but not the rest of the data.
2635 * Fake this up by doing read/write calls.
2638 if (errno == EINTR) {
2639 /* Ensure we don't do this again. */
2640 set_use_sendfile(SNUM(conn), False);
2641 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2643 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2644 len_outbuf - (data-outbuf))) == -1) {
2645 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2646 fsp->fsp_name, strerror(errno) ));
2647 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2649 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2650 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2651 /* Returning -1 here means successful sendfile. */
2652 return -1;
2655 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2656 fsp->fsp_name, strerror(errno) ));
2657 exit_server_cleanly("send_file_readX sendfile failed");
2660 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2661 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2662 /* Returning -1 here means successful sendfile. */
2663 return -1;
2666 #endif
2668 normal_read:
2670 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
2671 int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
2672 /* Send out the header. */
2673 if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
2674 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2675 fsp->fsp_name, strerror(errno) ));
2676 exit_server_cleanly("send_file_readX sendfile failed");
2678 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2679 len_outbuf - (data-outbuf))) == -1) {
2680 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2681 fsp->fsp_name, strerror(errno) ));
2682 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2684 return -1;
2685 } else {
2686 nread = read_file(fsp,data,startpos,smb_maxcnt);
2688 if (nread < 0) {
2689 return(UNIXERROR(ERRDOS,ERRnoaccess));
2692 outsize = setup_readX_header(inbuf, outbuf,nread);
2694 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2695 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2697 /* Returning the number of bytes we want to send back - including header. */
2698 return outsize;
2702 /****************************************************************************
2703 Reply to a read and X.
2704 ****************************************************************************/
2706 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2708 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2709 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2710 ssize_t nread = -1;
2711 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2712 BOOL big_readX = False;
2713 #if 0
2714 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2715 #endif
2717 START_PROFILE(SMBreadX);
2719 /* If it's an IPC, pass off the pipe handler. */
2720 if (IS_IPC(conn)) {
2721 END_PROFILE(SMBreadX);
2722 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2725 CHECK_FSP(fsp,conn);
2726 if (!CHECK_READ(fsp,inbuf)) {
2727 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2730 set_message(inbuf,outbuf,12,0,True);
2732 if (global_client_caps & CAP_LARGE_READX) {
2733 size_t upper_size = SVAL(inbuf,smb_vwv7);
2734 smb_maxcnt |= (upper_size<<16);
2735 if (upper_size > 1) {
2736 /* Can't do this on a chained packet. */
2737 if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
2738 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2740 /* We currently don't do this on signed or sealed data. */
2741 if (srv_is_signing_active() || srv_encryption_on()) {
2742 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2744 /* Is there room in the reply for this data ? */
2745 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
2746 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2748 big_readX = True;
2752 if(CVAL(inbuf,smb_wct) == 12) {
2753 #ifdef LARGE_SMB_OFF_T
2755 * This is a large offset (64 bit) read.
2757 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2759 #else /* !LARGE_SMB_OFF_T */
2762 * Ensure we haven't been sent a >32 bit offset.
2765 if(IVAL(inbuf,smb_vwv10) != 0) {
2766 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2767 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2768 END_PROFILE(SMBreadX);
2769 return ERROR_DOS(ERRDOS,ERRbadaccess);
2772 #endif /* LARGE_SMB_OFF_T */
2776 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2777 END_PROFILE(SMBreadX);
2778 return ERROR_DOS(ERRDOS,ERRlock);
2781 if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2782 END_PROFILE(SMBreadX);
2783 return -1;
2786 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2787 /* Only call chain_reply if not an error. */
2788 if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2789 nread = chain_reply(inbuf,outbuf,length,bufsize);
2792 END_PROFILE(SMBreadX);
2793 return nread;
2796 /****************************************************************************
2797 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2798 ****************************************************************************/
2800 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2802 ssize_t nwritten=0;
2803 ssize_t total_written=0;
2804 size_t numtowrite=0;
2805 size_t tcount;
2806 SMB_OFF_T startpos;
2807 char *data=NULL;
2808 BOOL write_through;
2809 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2810 int outsize = 0;
2811 NTSTATUS status;
2812 START_PROFILE(SMBwritebraw);
2814 if (srv_is_signing_active()) {
2815 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2818 CHECK_FSP(fsp,conn);
2819 if (!CHECK_WRITE(fsp)) {
2820 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2823 tcount = IVAL(inbuf,smb_vwv1);
2824 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2825 write_through = BITSETW(inbuf+smb_vwv7,0);
2827 /* We have to deal with slightly different formats depending
2828 on whether we are using the core+ or lanman1.0 protocol */
2830 if(Protocol <= PROTOCOL_COREPLUS) {
2831 numtowrite = SVAL(smb_buf(inbuf),-2);
2832 data = smb_buf(inbuf);
2833 } else {
2834 numtowrite = SVAL(inbuf,smb_vwv10);
2835 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2838 /* force the error type */
2839 SCVAL(inbuf,smb_com,SMBwritec);
2840 SCVAL(outbuf,smb_com,SMBwritec);
2842 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2843 END_PROFILE(SMBwritebraw);
2844 return(ERROR_DOS(ERRDOS,ERRlock));
2847 if (numtowrite>0)
2848 nwritten = write_file(fsp,data,startpos,numtowrite);
2850 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2851 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2853 if (nwritten < (ssize_t)numtowrite) {
2854 END_PROFILE(SMBwritebraw);
2855 return(UNIXERROR(ERRHRD,ERRdiskfull));
2858 total_written = nwritten;
2860 /* Return a message to the redirector to tell it to send more bytes */
2861 SCVAL(outbuf,smb_com,SMBwritebraw);
2862 SSVALS(outbuf,smb_vwv0,-1);
2863 outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2864 show_msg(outbuf);
2865 if (!send_smb(smbd_server_fd(),outbuf))
2866 exit_server_cleanly("reply_writebraw: send_smb failed.");
2868 /* Now read the raw data into the buffer and write it */
2869 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2870 exit_server_cleanly("secondary writebraw failed");
2873 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2874 numtowrite = smb_len(inbuf);
2876 /* Set up outbuf to return the correct return */
2877 outsize = set_message(inbuf,outbuf,1,0,True);
2878 SCVAL(outbuf,smb_com,SMBwritec);
2880 if (numtowrite != 0) {
2882 if (numtowrite > BUFFER_SIZE) {
2883 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2884 (unsigned int)numtowrite ));
2885 exit_server_cleanly("secondary writebraw failed");
2888 if (tcount > nwritten+numtowrite) {
2889 DEBUG(3,("Client overestimated the write %d %d %d\n",
2890 (int)tcount,(int)nwritten,(int)numtowrite));
2893 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2894 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2895 strerror(errno) ));
2896 exit_server_cleanly("secondary writebraw failed");
2899 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2900 if (nwritten == -1) {
2901 END_PROFILE(SMBwritebraw);
2902 return(UNIXERROR(ERRHRD,ERRdiskfull));
2905 if (nwritten < (ssize_t)numtowrite) {
2906 SCVAL(outbuf,smb_rcls,ERRHRD);
2907 SSVAL(outbuf,smb_err,ERRdiskfull);
2910 if (nwritten > 0)
2911 total_written += nwritten;
2914 SSVAL(outbuf,smb_vwv0,total_written);
2916 status = sync_file(conn, fsp, write_through);
2917 if (!NT_STATUS_IS_OK(status)) {
2918 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
2919 fsp->fsp_name, nt_errstr(status) ));
2920 END_PROFILE(SMBwritebraw);
2921 return ERROR_NT(status);
2924 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2925 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2927 /* we won't return a status if write through is not selected - this follows what WfWg does */
2928 END_PROFILE(SMBwritebraw);
2929 if (!write_through && total_written==tcount) {
2931 #if RABBIT_PELLET_FIX
2933 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2934 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2936 if (!send_keepalive(smbd_server_fd()))
2937 exit_server_cleanly("reply_writebraw: send of keepalive failed");
2938 #endif
2939 return(-1);
2942 return(outsize);
2945 #undef DBGC_CLASS
2946 #define DBGC_CLASS DBGC_LOCKING
2948 /****************************************************************************
2949 Reply to a writeunlock (core+).
2950 ****************************************************************************/
2952 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2953 int size, int dum_buffsize)
2955 ssize_t nwritten = -1;
2956 size_t numtowrite;
2957 SMB_OFF_T startpos;
2958 char *data;
2959 NTSTATUS status = NT_STATUS_OK;
2960 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2961 int outsize = 0;
2962 START_PROFILE(SMBwriteunlock);
2964 CHECK_FSP(fsp,conn);
2965 if (!CHECK_WRITE(fsp)) {
2966 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2969 numtowrite = SVAL(inbuf,smb_vwv1);
2970 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2971 data = smb_buf(inbuf) + 3;
2973 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2974 END_PROFILE(SMBwriteunlock);
2975 return ERROR_DOS(ERRDOS,ERRlock);
2978 /* The special X/Open SMB protocol handling of
2979 zero length writes is *NOT* done for
2980 this call */
2981 if(numtowrite == 0) {
2982 nwritten = 0;
2983 } else {
2984 nwritten = write_file(fsp,data,startpos,numtowrite);
2987 status = sync_file(conn, fsp, False /* write through */);
2988 if (!NT_STATUS_IS_OK(status)) {
2989 END_PROFILE(SMBwriteunlock);
2990 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
2991 fsp->fsp_name, nt_errstr(status) ));
2992 return ERROR_NT(status);
2995 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2996 END_PROFILE(SMBwriteunlock);
2997 return(UNIXERROR(ERRHRD,ERRdiskfull));
3000 if (numtowrite) {
3001 status = do_unlock(smbd_messaging_context(),
3002 fsp,
3003 (uint32)SVAL(inbuf,smb_pid),
3004 (SMB_BIG_UINT)numtowrite,
3005 (SMB_BIG_UINT)startpos,
3006 WINDOWS_LOCK);
3008 if (NT_STATUS_V(status)) {
3009 END_PROFILE(SMBwriteunlock);
3010 return ERROR_NT(status);
3014 outsize = set_message(inbuf,outbuf,1,0,True);
3016 SSVAL(outbuf,smb_vwv0,nwritten);
3018 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
3019 fsp->fnum, (int)numtowrite, (int)nwritten));
3021 END_PROFILE(SMBwriteunlock);
3022 return outsize;
3025 #undef DBGC_CLASS
3026 #define DBGC_CLASS DBGC_ALL
3028 /****************************************************************************
3029 Reply to a write.
3030 ****************************************************************************/
3032 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
3034 size_t numtowrite;
3035 ssize_t nwritten = -1;
3036 SMB_OFF_T startpos;
3037 char *data;
3038 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3039 int outsize = 0;
3040 NTSTATUS status;
3041 START_PROFILE(SMBwrite);
3043 /* If it's an IPC, pass off the pipe handler. */
3044 if (IS_IPC(conn)) {
3045 END_PROFILE(SMBwrite);
3046 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3049 CHECK_FSP(fsp,conn);
3050 if (!CHECK_WRITE(fsp)) {
3051 END_PROFILE(SMBwrite);
3052 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3055 numtowrite = SVAL(inbuf,smb_vwv1);
3056 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3057 data = smb_buf(inbuf) + 3;
3059 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3060 END_PROFILE(SMBwrite);
3061 return ERROR_DOS(ERRDOS,ERRlock);
3065 * X/Open SMB protocol says that if smb_vwv1 is
3066 * zero then the file size should be extended or
3067 * truncated to the size given in smb_vwv[2-3].
3070 if(numtowrite == 0) {
3072 * This is actually an allocate call, and set EOF. JRA.
3074 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3075 if (nwritten < 0) {
3076 END_PROFILE(SMBwrite);
3077 return ERROR_NT(NT_STATUS_DISK_FULL);
3079 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3080 if (nwritten < 0) {
3081 END_PROFILE(SMBwrite);
3082 return ERROR_NT(NT_STATUS_DISK_FULL);
3084 } else
3085 nwritten = write_file(fsp,data,startpos,numtowrite);
3087 status = sync_file(conn, fsp, False);
3088 if (!NT_STATUS_IS_OK(status)) {
3089 END_PROFILE(SMBwrite);
3090 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3091 fsp->fsp_name, nt_errstr(status) ));
3092 return ERROR_NT(status);
3095 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3096 END_PROFILE(SMBwrite);
3097 return(UNIXERROR(ERRHRD,ERRdiskfull));
3100 outsize = set_message(inbuf,outbuf,1,0,True);
3102 SSVAL(outbuf,smb_vwv0,nwritten);
3104 if (nwritten < (ssize_t)numtowrite) {
3105 SCVAL(outbuf,smb_rcls,ERRHRD);
3106 SSVAL(outbuf,smb_err,ERRdiskfull);
3109 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3111 END_PROFILE(SMBwrite);
3112 return(outsize);
3115 /****************************************************************************
3116 Reply to a write and X.
3117 ****************************************************************************/
3119 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3121 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3122 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3123 size_t numtowrite = SVAL(inbuf,smb_vwv10);
3124 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3125 ssize_t nwritten = -1;
3126 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3127 unsigned int smblen = smb_len(inbuf);
3128 char *data;
3129 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3130 NTSTATUS status;
3131 START_PROFILE(SMBwriteX);
3133 /* If it's an IPC, pass off the pipe handler. */
3134 if (IS_IPC(conn)) {
3135 END_PROFILE(SMBwriteX);
3136 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3139 CHECK_FSP(fsp,conn);
3140 if (!CHECK_WRITE(fsp)) {
3141 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3144 set_message(inbuf,outbuf,6,0,True);
3146 /* Deal with possible LARGE_WRITEX */
3147 if (large_writeX) {
3148 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3151 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3152 END_PROFILE(SMBwriteX);
3153 return ERROR_DOS(ERRDOS,ERRbadmem);
3156 data = smb_base(inbuf) + smb_doff;
3158 if(CVAL(inbuf,smb_wct) == 14) {
3159 #ifdef LARGE_SMB_OFF_T
3161 * This is a large offset (64 bit) write.
3163 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3165 #else /* !LARGE_SMB_OFF_T */
3168 * Ensure we haven't been sent a >32 bit offset.
3171 if(IVAL(inbuf,smb_vwv12) != 0) {
3172 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3173 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3174 END_PROFILE(SMBwriteX);
3175 return ERROR_DOS(ERRDOS,ERRbadaccess);
3178 #endif /* LARGE_SMB_OFF_T */
3181 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3182 END_PROFILE(SMBwriteX);
3183 return ERROR_DOS(ERRDOS,ERRlock);
3186 /* X/Open SMB protocol says that, unlike SMBwrite
3187 if the length is zero then NO truncation is
3188 done, just a write of zero. To truncate a file,
3189 use SMBwrite. */
3191 if(numtowrite == 0) {
3192 nwritten = 0;
3193 } else {
3195 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3196 fsp,data,startpos,numtowrite)) {
3197 END_PROFILE(SMBwriteX);
3198 return -1;
3201 nwritten = write_file(fsp,data,startpos,numtowrite);
3204 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3205 END_PROFILE(SMBwriteX);
3206 return(UNIXERROR(ERRHRD,ERRdiskfull));
3209 SSVAL(outbuf,smb_vwv2,nwritten);
3210 if (large_writeX)
3211 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3213 if (nwritten < (ssize_t)numtowrite) {
3214 SCVAL(outbuf,smb_rcls,ERRHRD);
3215 SSVAL(outbuf,smb_err,ERRdiskfull);
3218 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3219 fsp->fnum, (int)numtowrite, (int)nwritten));
3221 status = sync_file(conn, fsp, write_through);
3222 if (!NT_STATUS_IS_OK(status)) {
3223 END_PROFILE(SMBwriteX);
3224 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3225 fsp->fsp_name, nt_errstr(status) ));
3226 return ERROR_NT(status);
3229 END_PROFILE(SMBwriteX);
3230 return chain_reply(inbuf,outbuf,length,bufsize);
3233 /****************************************************************************
3234 Reply to a lseek.
3235 ****************************************************************************/
3237 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3239 SMB_OFF_T startpos;
3240 SMB_OFF_T res= -1;
3241 int mode,umode;
3242 int outsize = 0;
3243 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3244 START_PROFILE(SMBlseek);
3246 CHECK_FSP(fsp,conn);
3248 flush_write_cache(fsp, SEEK_FLUSH);
3250 mode = SVAL(inbuf,smb_vwv1) & 3;
3251 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3252 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3254 switch (mode) {
3255 case 0:
3256 umode = SEEK_SET;
3257 res = startpos;
3258 break;
3259 case 1:
3260 umode = SEEK_CUR;
3261 res = fsp->fh->pos + startpos;
3262 break;
3263 case 2:
3264 umode = SEEK_END;
3265 break;
3266 default:
3267 umode = SEEK_SET;
3268 res = startpos;
3269 break;
3272 if (umode == SEEK_END) {
3273 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3274 if(errno == EINVAL) {
3275 SMB_OFF_T current_pos = startpos;
3276 SMB_STRUCT_STAT sbuf;
3278 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3279 END_PROFILE(SMBlseek);
3280 return(UNIXERROR(ERRDOS,ERRnoaccess));
3283 current_pos += sbuf.st_size;
3284 if(current_pos < 0)
3285 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3289 if(res == -1) {
3290 END_PROFILE(SMBlseek);
3291 return(UNIXERROR(ERRDOS,ERRnoaccess));
3295 fsp->fh->pos = res;
3297 outsize = set_message(inbuf,outbuf,2,0,True);
3298 SIVAL(outbuf,smb_vwv0,res);
3300 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3301 fsp->fnum, (double)startpos, (double)res, mode));
3303 END_PROFILE(SMBlseek);
3304 return(outsize);
3307 /****************************************************************************
3308 Reply to a flush.
3309 ****************************************************************************/
3311 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3313 int outsize = set_message(inbuf,outbuf,0,0,False);
3314 uint16 fnum = SVAL(inbuf,smb_vwv0);
3315 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3316 START_PROFILE(SMBflush);
3318 if (fnum != 0xFFFF)
3319 CHECK_FSP(fsp,conn);
3321 if (!fsp) {
3322 file_sync_all(conn);
3323 } else {
3324 NTSTATUS status = sync_file(conn, fsp, True);
3325 if (!NT_STATUS_IS_OK(status)) {
3326 END_PROFILE(SMBflush);
3327 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3328 fsp->fsp_name, nt_errstr(status) ));
3329 return ERROR_NT(status);
3333 DEBUG(3,("flush\n"));
3334 END_PROFILE(SMBflush);
3335 return(outsize);
3338 /****************************************************************************
3339 Reply to a exit.
3340 conn POINTER CAN BE NULL HERE !
3341 ****************************************************************************/
3343 int reply_exit(connection_struct *conn,
3344 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3346 int outsize;
3347 START_PROFILE(SMBexit);
3349 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3351 outsize = set_message(inbuf,outbuf,0,0,False);
3353 DEBUG(3,("exit\n"));
3355 END_PROFILE(SMBexit);
3356 return(outsize);
3359 /****************************************************************************
3360 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3361 ****************************************************************************/
3363 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3364 int dum_buffsize)
3366 NTSTATUS status = NT_STATUS_OK;
3367 int outsize = 0;
3368 files_struct *fsp = NULL;
3369 START_PROFILE(SMBclose);
3371 outsize = set_message(inbuf,outbuf,0,0,False);
3373 /* If it's an IPC, pass off to the pipe handler. */
3374 if (IS_IPC(conn)) {
3375 END_PROFILE(SMBclose);
3376 return reply_pipe_close(conn, inbuf,outbuf);
3379 fsp = file_fsp(inbuf,smb_vwv0);
3382 * We can only use CHECK_FSP if we know it's not a directory.
3385 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3386 END_PROFILE(SMBclose);
3387 return ERROR_DOS(ERRDOS,ERRbadfid);
3390 if(fsp->is_directory) {
3392 * Special case - close NT SMB directory handle.
3394 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3395 status = close_file(fsp,NORMAL_CLOSE);
3396 } else {
3398 * Close ordinary file.
3401 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3402 fsp->fh->fd, fsp->fnum,
3403 conn->num_files_open));
3406 * Take care of any time sent in the close.
3409 fsp_set_pending_modtime(fsp,
3410 convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
3413 * close_file() returns the unix errno if an error
3414 * was detected on close - normally this is due to
3415 * a disk full error. If not then it was probably an I/O error.
3418 status = close_file(fsp,NORMAL_CLOSE);
3421 if(!NT_STATUS_IS_OK(status)) {
3422 END_PROFILE(SMBclose);
3423 return ERROR_NT(status);
3426 END_PROFILE(SMBclose);
3427 return(outsize);
3430 /****************************************************************************
3431 Reply to a writeclose (Core+ protocol).
3432 ****************************************************************************/
3434 int reply_writeclose(connection_struct *conn,
3435 char *inbuf,char *outbuf, int size, int dum_buffsize)
3437 size_t numtowrite;
3438 ssize_t nwritten = -1;
3439 int outsize = 0;
3440 NTSTATUS close_status = NT_STATUS_OK;
3441 SMB_OFF_T startpos;
3442 char *data;
3443 struct timespec mtime;
3444 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3445 START_PROFILE(SMBwriteclose);
3447 CHECK_FSP(fsp,conn);
3448 if (!CHECK_WRITE(fsp)) {
3449 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3452 numtowrite = SVAL(inbuf,smb_vwv1);
3453 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3454 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3455 data = smb_buf(inbuf) + 1;
3457 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3458 END_PROFILE(SMBwriteclose);
3459 return ERROR_DOS(ERRDOS,ERRlock);
3462 nwritten = write_file(fsp,data,startpos,numtowrite);
3464 set_filetime(conn, fsp->fsp_name, mtime);
3467 * More insanity. W2K only closes the file if writelen > 0.
3468 * JRA.
3471 if (numtowrite) {
3472 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3473 fsp->fsp_name ));
3474 close_status = close_file(fsp,NORMAL_CLOSE);
3477 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3478 fsp->fnum, (int)numtowrite, (int)nwritten,
3479 conn->num_files_open));
3481 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3482 END_PROFILE(SMBwriteclose);
3483 return(UNIXERROR(ERRHRD,ERRdiskfull));
3486 if(!NT_STATUS_IS_OK(close_status)) {
3487 END_PROFILE(SMBwriteclose);
3488 return ERROR_NT(close_status);
3491 outsize = set_message(inbuf,outbuf,1,0,True);
3493 SSVAL(outbuf,smb_vwv0,nwritten);
3494 END_PROFILE(SMBwriteclose);
3495 return(outsize);
3498 #undef DBGC_CLASS
3499 #define DBGC_CLASS DBGC_LOCKING
3501 /****************************************************************************
3502 Reply to a lock.
3503 ****************************************************************************/
3505 int reply_lock(connection_struct *conn,
3506 char *inbuf,char *outbuf, int length, int dum_buffsize)
3508 int outsize = set_message(inbuf,outbuf,0,0,False);
3509 SMB_BIG_UINT count,offset;
3510 NTSTATUS status;
3511 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3512 struct byte_range_lock *br_lck = NULL;
3514 START_PROFILE(SMBlock);
3516 CHECK_FSP(fsp,conn);
3518 release_level_2_oplocks_on_change(fsp);
3520 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3521 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3523 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3524 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3526 br_lck = do_lock(smbd_messaging_context(),
3527 fsp,
3528 (uint32)SVAL(inbuf,smb_pid),
3529 count,
3530 offset,
3531 WRITE_LOCK,
3532 WINDOWS_LOCK,
3533 False, /* Non-blocking lock. */
3534 &status,
3535 NULL);
3537 TALLOC_FREE(br_lck);
3539 if (NT_STATUS_V(status)) {
3540 END_PROFILE(SMBlock);
3541 return ERROR_NT(status);
3544 END_PROFILE(SMBlock);
3545 return(outsize);
3548 /****************************************************************************
3549 Reply to a unlock.
3550 ****************************************************************************/
3552 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3553 int dum_buffsize)
3555 int outsize = set_message(inbuf,outbuf,0,0,False);
3556 SMB_BIG_UINT count,offset;
3557 NTSTATUS status;
3558 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3559 START_PROFILE(SMBunlock);
3561 CHECK_FSP(fsp,conn);
3563 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3564 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3566 status = do_unlock(smbd_messaging_context(),
3567 fsp,
3568 (uint32)SVAL(inbuf,smb_pid),
3569 count,
3570 offset,
3571 WINDOWS_LOCK);
3573 if (NT_STATUS_V(status)) {
3574 END_PROFILE(SMBunlock);
3575 return ERROR_NT(status);
3578 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3579 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3581 END_PROFILE(SMBunlock);
3582 return(outsize);
3585 #undef DBGC_CLASS
3586 #define DBGC_CLASS DBGC_ALL
3588 /****************************************************************************
3589 Reply to a tdis.
3590 conn POINTER CAN BE NULL HERE !
3591 ****************************************************************************/
3593 int reply_tdis(connection_struct *conn,
3594 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3596 int outsize = set_message(inbuf,outbuf,0,0,False);
3597 uint16 vuid;
3598 START_PROFILE(SMBtdis);
3600 vuid = SVAL(inbuf,smb_uid);
3602 if (!conn) {
3603 DEBUG(4,("Invalid connection in tdis\n"));
3604 END_PROFILE(SMBtdis);
3605 return ERROR_DOS(ERRSRV,ERRinvnid);
3608 conn->used = False;
3610 close_cnum(conn,vuid);
3612 END_PROFILE(SMBtdis);
3613 return outsize;
3616 /****************************************************************************
3617 Reply to a echo.
3618 conn POINTER CAN BE NULL HERE !
3619 ****************************************************************************/
3621 int reply_echo(connection_struct *conn,
3622 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3624 int smb_reverb = SVAL(inbuf,smb_vwv0);
3625 int seq_num;
3626 unsigned int data_len = smb_buflen(inbuf);
3627 int outsize = set_message(inbuf,outbuf,1,data_len,True);
3628 START_PROFILE(SMBecho);
3630 if (data_len > BUFFER_SIZE) {
3631 DEBUG(0,("reply_echo: data_len too large.\n"));
3632 END_PROFILE(SMBecho);
3633 return -1;
3636 /* copy any incoming data back out */
3637 if (data_len > 0)
3638 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3640 if (smb_reverb > 100) {
3641 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3642 smb_reverb = 100;
3645 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3646 SSVAL(outbuf,smb_vwv0,seq_num);
3648 smb_setlen(inbuf,outbuf,outsize - 4);
3650 show_msg(outbuf);
3651 if (!send_smb(smbd_server_fd(),outbuf))
3652 exit_server_cleanly("reply_echo: send_smb failed.");
3655 DEBUG(3,("echo %d times\n", smb_reverb));
3657 smb_echo_count++;
3659 END_PROFILE(SMBecho);
3660 return -1;
3663 /****************************************************************************
3664 Reply to a printopen.
3665 ****************************************************************************/
3667 int reply_printopen(connection_struct *conn,
3668 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3670 int outsize = 0;
3671 files_struct *fsp;
3672 NTSTATUS status;
3674 START_PROFILE(SMBsplopen);
3676 if (!CAN_PRINT(conn)) {
3677 END_PROFILE(SMBsplopen);
3678 return ERROR_DOS(ERRDOS,ERRnoaccess);
3681 /* Open for exclusive use, write only. */
3682 status = print_fsp_open(conn, NULL, &fsp);
3684 if (!NT_STATUS_IS_OK(status)) {
3685 END_PROFILE(SMBsplopen);
3686 return(ERROR_NT(status));
3689 outsize = set_message(inbuf,outbuf,1,0,True);
3690 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3692 DEBUG(3,("openprint fd=%d fnum=%d\n",
3693 fsp->fh->fd, fsp->fnum));
3695 END_PROFILE(SMBsplopen);
3696 return(outsize);
3699 /****************************************************************************
3700 Reply to a printclose.
3701 ****************************************************************************/
3703 int reply_printclose(connection_struct *conn,
3704 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3706 int outsize = set_message(inbuf,outbuf,0,0,False);
3707 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3708 NTSTATUS status;
3709 START_PROFILE(SMBsplclose);
3711 CHECK_FSP(fsp,conn);
3713 if (!CAN_PRINT(conn)) {
3714 END_PROFILE(SMBsplclose);
3715 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3718 DEBUG(3,("printclose fd=%d fnum=%d\n",
3719 fsp->fh->fd,fsp->fnum));
3721 status = close_file(fsp,NORMAL_CLOSE);
3723 if(!NT_STATUS_IS_OK(status)) {
3724 END_PROFILE(SMBsplclose);
3725 return ERROR_NT(status);
3728 END_PROFILE(SMBsplclose);
3729 return(outsize);
3732 /****************************************************************************
3733 Reply to a printqueue.
3734 ****************************************************************************/
3736 int reply_printqueue(connection_struct *conn,
3737 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3739 int outsize = set_message(inbuf,outbuf,2,3,True);
3740 int max_count = SVAL(inbuf,smb_vwv0);
3741 int start_index = SVAL(inbuf,smb_vwv1);
3742 START_PROFILE(SMBsplretq);
3744 /* we used to allow the client to get the cnum wrong, but that
3745 is really quite gross and only worked when there was only
3746 one printer - I think we should now only accept it if they
3747 get it right (tridge) */
3748 if (!CAN_PRINT(conn)) {
3749 END_PROFILE(SMBsplretq);
3750 return ERROR_DOS(ERRDOS,ERRnoaccess);
3753 SSVAL(outbuf,smb_vwv0,0);
3754 SSVAL(outbuf,smb_vwv1,0);
3755 SCVAL(smb_buf(outbuf),0,1);
3756 SSVAL(smb_buf(outbuf),1,0);
3758 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3759 start_index, max_count));
3762 print_queue_struct *queue = NULL;
3763 print_status_struct status;
3764 char *p = smb_buf(outbuf) + 3;
3765 int count = print_queue_status(SNUM(conn), &queue, &status);
3766 int num_to_get = ABS(max_count);
3767 int first = (max_count>0?start_index:start_index+max_count+1);
3768 int i;
3770 if (first >= count)
3771 num_to_get = 0;
3772 else
3773 num_to_get = MIN(num_to_get,count-first);
3776 for (i=first;i<first+num_to_get;i++) {
3777 srv_put_dos_date2(p,0,queue[i].time);
3778 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3779 SSVAL(p,5, queue[i].job);
3780 SIVAL(p,7,queue[i].size);
3781 SCVAL(p,11,0);
3782 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3783 p += 28;
3786 if (count > 0) {
3787 outsize = set_message(inbuf,outbuf,2,28*count+3,False);
3788 SSVAL(outbuf,smb_vwv0,count);
3789 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3790 SCVAL(smb_buf(outbuf),0,1);
3791 SSVAL(smb_buf(outbuf),1,28*count);
3794 SAFE_FREE(queue);
3796 DEBUG(3,("%d entries returned in queue\n",count));
3799 END_PROFILE(SMBsplretq);
3800 return(outsize);
3803 /****************************************************************************
3804 Reply to a printwrite.
3805 ****************************************************************************/
3807 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3809 int numtowrite;
3810 int outsize = set_message(inbuf,outbuf,0,0,False);
3811 char *data;
3812 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3814 START_PROFILE(SMBsplwr);
3816 if (!CAN_PRINT(conn)) {
3817 END_PROFILE(SMBsplwr);
3818 return ERROR_DOS(ERRDOS,ERRnoaccess);
3821 CHECK_FSP(fsp,conn);
3822 if (!CHECK_WRITE(fsp)) {
3823 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3826 numtowrite = SVAL(smb_buf(inbuf),1);
3827 data = smb_buf(inbuf) + 3;
3829 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3830 END_PROFILE(SMBsplwr);
3831 return(UNIXERROR(ERRHRD,ERRdiskfull));
3834 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3836 END_PROFILE(SMBsplwr);
3837 return(outsize);
3840 /****************************************************************************
3841 Reply to a mkdir.
3842 ****************************************************************************/
3844 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3846 pstring directory;
3847 int outsize;
3848 NTSTATUS status;
3849 SMB_STRUCT_STAT sbuf;
3851 START_PROFILE(SMBmkdir);
3853 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
3854 smb_buf(inbuf) + 1, sizeof(directory), 0,
3855 STR_TERMINATE, &status);
3856 if (!NT_STATUS_IS_OK(status)) {
3857 END_PROFILE(SMBmkdir);
3858 return ERROR_NT(status);
3861 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
3862 if (!NT_STATUS_IS_OK(status)) {
3863 END_PROFILE(SMBmkdir);
3864 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3865 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3867 return ERROR_NT(status);
3870 status = unix_convert(conn, directory, False, NULL, &sbuf);
3871 if (!NT_STATUS_IS_OK(status)) {
3872 END_PROFILE(SMBmkdir);
3873 return ERROR_NT(status);
3876 status = check_name(conn, directory);
3877 if (!NT_STATUS_IS_OK(status)) {
3878 END_PROFILE(SMBmkdir);
3879 return ERROR_NT(status);
3882 status = create_directory(conn, directory);
3884 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3886 if (!NT_STATUS_IS_OK(status)) {
3888 if (!use_nt_status()
3889 && NT_STATUS_EQUAL(status,
3890 NT_STATUS_OBJECT_NAME_COLLISION)) {
3892 * Yes, in the DOS error code case we get a
3893 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3894 * samba4 torture test.
3896 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3899 END_PROFILE(SMBmkdir);
3900 return ERROR_NT(status);
3903 outsize = set_message(inbuf,outbuf,0,0,False);
3905 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3907 END_PROFILE(SMBmkdir);
3908 return(outsize);
3911 /****************************************************************************
3912 Static function used by reply_rmdir to delete an entire directory
3913 tree recursively. Return True on ok, False on fail.
3914 ****************************************************************************/
3916 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3918 const char *dname = NULL;
3919 BOOL ret = True;
3920 long offset = 0;
3921 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3923 if(dir_hnd == NULL)
3924 return False;
3926 while((dname = ReadDirName(dir_hnd, &offset))) {
3927 pstring fullname;
3928 SMB_STRUCT_STAT st;
3930 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3931 continue;
3933 if (!is_visible_file(conn, directory, dname, &st, False))
3934 continue;
3936 /* Construct the full name. */
3937 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3938 errno = ENOMEM;
3939 ret = False;
3940 break;
3943 pstrcpy(fullname, directory);
3944 pstrcat(fullname, "/");
3945 pstrcat(fullname, dname);
3947 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3948 ret = False;
3949 break;
3952 if(st.st_mode & S_IFDIR) {
3953 if(!recursive_rmdir(conn, fullname)) {
3954 ret = False;
3955 break;
3957 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3958 ret = False;
3959 break;
3961 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3962 ret = False;
3963 break;
3966 CloseDir(dir_hnd);
3967 return ret;
3970 /****************************************************************************
3971 The internals of the rmdir code - called elsewhere.
3972 ****************************************************************************/
3974 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
3976 int ret;
3977 SMB_STRUCT_STAT st;
3979 /* Might be a symlink. */
3980 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
3981 return map_nt_error_from_unix(errno);
3984 if (S_ISLNK(st.st_mode)) {
3985 /* Is what it points to a directory ? */
3986 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
3987 return map_nt_error_from_unix(errno);
3989 if (!(S_ISDIR(st.st_mode))) {
3990 return NT_STATUS_NOT_A_DIRECTORY;
3992 ret = SMB_VFS_UNLINK(conn,directory);
3993 } else {
3994 ret = SMB_VFS_RMDIR(conn,directory);
3996 if (ret == 0) {
3997 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3998 FILE_NOTIFY_CHANGE_DIR_NAME,
3999 directory);
4000 return NT_STATUS_OK;
4003 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4005 * Check to see if the only thing in this directory are
4006 * vetoed files/directories. If so then delete them and
4007 * retry. If we fail to delete any of them (and we *don't*
4008 * do a recursive delete) then fail the rmdir.
4010 const char *dname;
4011 long dirpos = 0;
4012 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4014 if(dir_hnd == NULL) {
4015 errno = ENOTEMPTY;
4016 goto err;
4019 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4020 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4021 continue;
4022 if (!is_visible_file(conn, directory, dname, &st, False))
4023 continue;
4024 if(!IS_VETO_PATH(conn, dname)) {
4025 CloseDir(dir_hnd);
4026 errno = ENOTEMPTY;
4027 goto err;
4031 /* We only have veto files/directories. Recursive delete. */
4033 RewindDir(dir_hnd,&dirpos);
4034 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4035 pstring fullname;
4037 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4038 continue;
4039 if (!is_visible_file(conn, directory, dname, &st, False))
4040 continue;
4042 /* Construct the full name. */
4043 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4044 errno = ENOMEM;
4045 break;
4048 pstrcpy(fullname, directory);
4049 pstrcat(fullname, "/");
4050 pstrcat(fullname, dname);
4052 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4053 break;
4054 if(st.st_mode & S_IFDIR) {
4055 if(lp_recursive_veto_delete(SNUM(conn))) {
4056 if(!recursive_rmdir(conn, fullname))
4057 break;
4059 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4060 break;
4061 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4062 break;
4064 CloseDir(dir_hnd);
4065 /* Retry the rmdir */
4066 ret = SMB_VFS_RMDIR(conn,directory);
4069 err:
4071 if (ret != 0) {
4072 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4073 "%s\n", directory,strerror(errno)));
4074 return map_nt_error_from_unix(errno);
4077 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4078 FILE_NOTIFY_CHANGE_DIR_NAME,
4079 directory);
4081 return NT_STATUS_OK;
4084 /****************************************************************************
4085 Reply to a rmdir.
4086 ****************************************************************************/
4088 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4090 pstring directory;
4091 int outsize = 0;
4092 SMB_STRUCT_STAT sbuf;
4093 NTSTATUS status;
4094 START_PROFILE(SMBrmdir);
4096 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
4097 smb_buf(inbuf) + 1, sizeof(directory), 0,
4098 STR_TERMINATE, &status);
4099 if (!NT_STATUS_IS_OK(status)) {
4100 END_PROFILE(SMBrmdir);
4101 return ERROR_NT(status);
4104 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
4105 if (!NT_STATUS_IS_OK(status)) {
4106 END_PROFILE(SMBrmdir);
4107 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4108 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4110 return ERROR_NT(status);
4113 status = unix_convert(conn, directory, False, NULL, &sbuf);
4114 if (!NT_STATUS_IS_OK(status)) {
4115 END_PROFILE(SMBrmdir);
4116 return ERROR_NT(status);
4119 status = check_name(conn, directory);
4120 if (!NT_STATUS_IS_OK(status)) {
4121 END_PROFILE(SMBrmdir);
4122 return ERROR_NT(status);
4125 dptr_closepath(directory,SVAL(inbuf,smb_pid));
4126 status = rmdir_internals(conn, directory);
4127 if (!NT_STATUS_IS_OK(status)) {
4128 END_PROFILE(SMBrmdir);
4129 return ERROR_NT(status);
4132 outsize = set_message(inbuf,outbuf,0,0,False);
4134 DEBUG( 3, ( "rmdir %s\n", directory ) );
4136 END_PROFILE(SMBrmdir);
4137 return(outsize);
4140 /*******************************************************************
4141 Resolve wildcards in a filename rename.
4142 Note that name is in UNIX charset and thus potentially can be more
4143 than fstring buffer (255 bytes) especially in default UTF-8 case.
4144 Therefore, we use pstring inside and all calls should ensure that
4145 name2 is at least pstring-long (they do already)
4146 ********************************************************************/
4148 static BOOL resolve_wildcards(const char *name1, char *name2)
4150 pstring root1,root2;
4151 pstring ext1,ext2;
4152 char *p,*p2, *pname1, *pname2;
4153 int available_space, actual_space;
4155 pname1 = strrchr_m(name1,'/');
4156 pname2 = strrchr_m(name2,'/');
4158 if (!pname1 || !pname2)
4159 return(False);
4161 pstrcpy(root1,pname1);
4162 pstrcpy(root2,pname2);
4163 p = strrchr_m(root1,'.');
4164 if (p) {
4165 *p = 0;
4166 pstrcpy(ext1,p+1);
4167 } else {
4168 pstrcpy(ext1,"");
4170 p = strrchr_m(root2,'.');
4171 if (p) {
4172 *p = 0;
4173 pstrcpy(ext2,p+1);
4174 } else {
4175 pstrcpy(ext2,"");
4178 p = root1;
4179 p2 = root2;
4180 while (*p2) {
4181 if (*p2 == '?') {
4182 *p2 = *p;
4183 p2++;
4184 } else if (*p2 == '*') {
4185 pstrcpy(p2, p);
4186 break;
4187 } else {
4188 p2++;
4190 if (*p)
4191 p++;
4194 p = ext1;
4195 p2 = ext2;
4196 while (*p2) {
4197 if (*p2 == '?') {
4198 *p2 = *p;
4199 p2++;
4200 } else if (*p2 == '*') {
4201 pstrcpy(p2, p);
4202 break;
4203 } else {
4204 p2++;
4206 if (*p)
4207 p++;
4210 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4212 if (ext2[0]) {
4213 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4214 if (actual_space >= available_space - 1) {
4215 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4216 actual_space - available_space));
4218 } else {
4219 pstrcpy_base(pname2, root2, name2);
4222 return(True);
4225 /****************************************************************************
4226 Ensure open files have their names updated. Updated to notify other smbd's
4227 asynchronously.
4228 ****************************************************************************/
4230 static void rename_open_files(connection_struct *conn,
4231 struct share_mode_lock *lck,
4232 const char *newname)
4234 files_struct *fsp;
4235 BOOL did_rename = False;
4237 for(fsp = file_find_di_first(lck->id); fsp;
4238 fsp = file_find_di_next(fsp)) {
4239 /* fsp_name is a relative path under the fsp. To change this for other
4240 sharepaths we need to manipulate relative paths. */
4241 /* TODO - create the absolute path and manipulate the newname
4242 relative to the sharepath. */
4243 if (fsp->conn != conn) {
4244 continue;
4246 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4247 fsp->fnum, file_id_static_string(&fsp->file_id),
4248 fsp->fsp_name, newname ));
4249 string_set(&fsp->fsp_name, newname);
4250 did_rename = True;
4253 if (!did_rename) {
4254 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4255 file_id_static_string(&lck->id), newname ));
4258 /* Send messages to all smbd's (not ourself) that the name has changed. */
4259 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4260 newname);
4263 /****************************************************************************
4264 We need to check if the source path is a parent directory of the destination
4265 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4266 refuse the rename with a sharing violation. Under UNIX the above call can
4267 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4268 probably need to check that the client is a Windows one before disallowing
4269 this as a UNIX client (one with UNIX extensions) can know the source is a
4270 symlink and make this decision intelligently. Found by an excellent bug
4271 report from <AndyLiebman@aol.com>.
4272 ****************************************************************************/
4274 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4276 const char *psrc = src;
4277 const char *pdst = dest;
4278 size_t slen;
4280 if (psrc[0] == '.' && psrc[1] == '/') {
4281 psrc += 2;
4283 if (pdst[0] == '.' && pdst[1] == '/') {
4284 pdst += 2;
4286 if ((slen = strlen(psrc)) > strlen(pdst)) {
4287 return False;
4289 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4293 * Do the notify calls from a rename
4296 static void notify_rename(connection_struct *conn, BOOL is_dir,
4297 const char *oldpath, const char *newpath)
4299 char *olddir, *newdir;
4300 const char *oldname, *newname;
4301 uint32 mask;
4303 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4304 : FILE_NOTIFY_CHANGE_FILE_NAME;
4306 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4307 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4308 TALLOC_FREE(olddir);
4309 return;
4312 if (strcmp(olddir, newdir) == 0) {
4313 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4314 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4316 else {
4317 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4318 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4320 TALLOC_FREE(olddir);
4321 TALLOC_FREE(newdir);
4323 /* this is a strange one. w2k3 gives an additional event for
4324 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4325 files, but not directories */
4326 if (!is_dir) {
4327 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4328 FILE_NOTIFY_CHANGE_ATTRIBUTES
4329 |FILE_NOTIFY_CHANGE_CREATION,
4330 newpath);
4334 /****************************************************************************
4335 Rename an open file - given an fsp.
4336 ****************************************************************************/
4338 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4340 SMB_STRUCT_STAT sbuf, sbuf1;
4341 pstring newname_last_component;
4342 NTSTATUS status = NT_STATUS_OK;
4343 struct share_mode_lock *lck = NULL;
4344 BOOL dst_exists;
4346 ZERO_STRUCT(sbuf);
4348 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4350 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4352 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4353 return status;
4356 status = check_name(conn, newname);
4357 if (!NT_STATUS_IS_OK(status)) {
4358 return status;
4361 /* Ensure newname contains a '/' */
4362 if(strrchr_m(newname,'/') == 0) {
4363 pstring tmpstr;
4365 pstrcpy(tmpstr, "./");
4366 pstrcat(tmpstr, newname);
4367 pstrcpy(newname, tmpstr);
4371 * Check for special case with case preserving and not
4372 * case sensitive. If the old last component differs from the original
4373 * last component only by case, then we should allow
4374 * the rename (user is trying to change the case of the
4375 * filename).
4378 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4379 strequal(newname, fsp->fsp_name)) {
4380 char *p;
4381 pstring newname_modified_last_component;
4384 * Get the last component of the modified name.
4385 * Note that we guarantee that newname contains a '/'
4386 * character above.
4388 p = strrchr_m(newname,'/');
4389 pstrcpy(newname_modified_last_component,p+1);
4391 if(strcsequal(newname_modified_last_component,
4392 newname_last_component) == False) {
4394 * Replace the modified last component with
4395 * the original.
4397 pstrcpy(p+1, newname_last_component);
4402 * If the src and dest names are identical - including case,
4403 * don't do the rename, just return success.
4406 if (strcsequal(fsp->fsp_name, newname)) {
4407 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4408 newname));
4409 return NT_STATUS_OK;
4413 * Have vfs_object_exist also fill sbuf1
4415 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4417 if(!replace_if_exists && dst_exists) {
4418 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4419 fsp->fsp_name,newname));
4420 return NT_STATUS_OBJECT_NAME_COLLISION;
4423 if (dst_exists && file_find_di_first(file_id_sbuf(&sbuf1)) != NULL) {
4424 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4425 return NT_STATUS_ACCESS_DENIED;
4428 /* Ensure we have a valid stat struct for the source. */
4429 if (fsp->fh->fd != -1) {
4430 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4431 return map_nt_error_from_unix(errno);
4433 } else {
4434 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4435 return map_nt_error_from_unix(errno);
4439 status = can_rename(conn, fsp, attrs, &sbuf);
4441 if (!NT_STATUS_IS_OK(status)) {
4442 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4443 nt_errstr(status), fsp->fsp_name,newname));
4444 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4445 status = NT_STATUS_ACCESS_DENIED;
4446 return status;
4449 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4450 return NT_STATUS_ACCESS_DENIED;
4453 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4456 * We have the file open ourselves, so not being able to get the
4457 * corresponding share mode lock is a fatal error.
4460 SMB_ASSERT(lck != NULL);
4462 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4463 uint32 create_options = fsp->fh->private_options;
4465 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4466 fsp->fsp_name,newname));
4468 rename_open_files(conn, lck, newname);
4470 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4473 * A rename acts as a new file create w.r.t. allowing an initial delete
4474 * on close, probably because in Windows there is a new handle to the
4475 * new file. If initial delete on close was requested but not
4476 * originally set, we need to set it here. This is probably not 100% correct,
4477 * but will work for the CIFSFS client which in non-posix mode
4478 * depends on these semantics. JRA.
4481 set_allow_initial_delete_on_close(lck, fsp, True);
4483 if (create_options & FILE_DELETE_ON_CLOSE) {
4484 status = can_set_delete_on_close(fsp, True, 0);
4486 if (NT_STATUS_IS_OK(status)) {
4487 /* Note that here we set the *inital* delete on close flag,
4488 * not the regular one. The magic gets handled in close. */
4489 fsp->initial_delete_on_close = True;
4492 TALLOC_FREE(lck);
4493 return NT_STATUS_OK;
4496 TALLOC_FREE(lck);
4498 if (errno == ENOTDIR || errno == EISDIR) {
4499 status = NT_STATUS_OBJECT_NAME_COLLISION;
4500 } else {
4501 status = map_nt_error_from_unix(errno);
4504 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4505 nt_errstr(status), fsp->fsp_name,newname));
4507 return status;
4510 /****************************************************************************
4511 The guts of the rename command, split out so it may be called by the NT SMB
4512 code.
4513 ****************************************************************************/
4515 NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
4516 pstring name,
4517 pstring newname,
4518 uint32 attrs,
4519 BOOL replace_if_exists,
4520 BOOL src_has_wild,
4521 BOOL dest_has_wild)
4523 pstring directory;
4524 pstring mask;
4525 pstring last_component_src;
4526 pstring last_component_dest;
4527 char *p;
4528 int count=0;
4529 NTSTATUS status = NT_STATUS_OK;
4530 SMB_STRUCT_STAT sbuf1, sbuf2;
4531 struct smb_Dir *dir_hnd = NULL;
4532 const char *dname;
4533 long offset = 0;
4534 pstring destname;
4536 *directory = *mask = 0;
4538 ZERO_STRUCT(sbuf1);
4539 ZERO_STRUCT(sbuf2);
4541 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4542 if (!NT_STATUS_IS_OK(status)) {
4543 return status;
4546 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4547 if (!NT_STATUS_IS_OK(status)) {
4548 return status;
4552 * Split the old name into directory and last component
4553 * strings. Note that unix_convert may have stripped off a
4554 * leading ./ from both name and newname if the rename is
4555 * at the root of the share. We need to make sure either both
4556 * name and newname contain a / character or neither of them do
4557 * as this is checked in resolve_wildcards().
4560 p = strrchr_m(name,'/');
4561 if (!p) {
4562 pstrcpy(directory,".");
4563 pstrcpy(mask,name);
4564 } else {
4565 *p = 0;
4566 pstrcpy(directory,name);
4567 pstrcpy(mask,p+1);
4568 *p = '/'; /* Replace needed for exceptional test below. */
4572 * We should only check the mangled cache
4573 * here if unix_convert failed. This means
4574 * that the path in 'mask' doesn't exist
4575 * on the file system and so we need to look
4576 * for a possible mangle. This patch from
4577 * Tine Smukavec <valentin.smukavec@hermes.si>.
4580 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4581 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4584 if (!src_has_wild) {
4585 files_struct *fsp;
4588 * No wildcards - just process the one file.
4590 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4592 /* Add a terminating '/' to the directory name. */
4593 pstrcat(directory,"/");
4594 pstrcat(directory,mask);
4596 /* Ensure newname contains a '/' also */
4597 if(strrchr_m(newname,'/') == 0) {
4598 pstring tmpstr;
4600 pstrcpy(tmpstr, "./");
4601 pstrcat(tmpstr, newname);
4602 pstrcpy(newname, tmpstr);
4605 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4606 "case_preserve = %d, short case preserve = %d, "
4607 "directory = %s, newname = %s, "
4608 "last_component_dest = %s, is_8_3 = %d\n",
4609 conn->case_sensitive, conn->case_preserve,
4610 conn->short_case_preserve, directory,
4611 newname, last_component_dest, is_short_name));
4613 /* The dest name still may have wildcards. */
4614 if (dest_has_wild) {
4615 if (!resolve_wildcards(directory,newname)) {
4616 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4617 directory,newname));
4618 return NT_STATUS_NO_MEMORY;
4622 ZERO_STRUCT(sbuf1);
4623 SMB_VFS_STAT(conn, directory, &sbuf1);
4625 status = S_ISDIR(sbuf1.st_mode) ?
4626 open_directory(conn, req, directory, &sbuf1,
4627 DELETE_ACCESS,
4628 FILE_SHARE_READ|FILE_SHARE_WRITE,
4629 FILE_OPEN, 0, 0, NULL,
4630 &fsp)
4631 : open_file_ntcreate(conn, req, directory, &sbuf1,
4632 DELETE_ACCESS,
4633 FILE_SHARE_READ|FILE_SHARE_WRITE,
4634 FILE_OPEN, 0, 0, 0, NULL,
4635 &fsp);
4637 if (!NT_STATUS_IS_OK(status)) {
4638 DEBUG(3, ("Could not open rename source %s: %s\n",
4639 directory, nt_errstr(status)));
4640 return status;
4643 status = rename_internals_fsp(conn, fsp, newname, attrs,
4644 replace_if_exists);
4646 close_file(fsp, NORMAL_CLOSE);
4648 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4649 nt_errstr(status), directory,newname));
4651 return status;
4655 * Wildcards - process each file that matches.
4657 if (strequal(mask,"????????.???")) {
4658 pstrcpy(mask,"*");
4661 status = check_name(conn, directory);
4662 if (!NT_STATUS_IS_OK(status)) {
4663 return status;
4666 dir_hnd = OpenDir(conn, directory, mask, attrs);
4667 if (dir_hnd == NULL) {
4668 return map_nt_error_from_unix(errno);
4671 status = NT_STATUS_NO_SUCH_FILE;
4673 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4674 * - gentest fix. JRA
4677 while ((dname = ReadDirName(dir_hnd, &offset))) {
4678 files_struct *fsp;
4679 pstring fname;
4680 BOOL sysdir_entry = False;
4682 pstrcpy(fname,dname);
4684 /* Quick check for "." and ".." */
4685 if (fname[0] == '.') {
4686 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4687 if (attrs & aDIR) {
4688 sysdir_entry = True;
4689 } else {
4690 continue;
4695 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4696 continue;
4699 if(!mask_match(fname, mask, conn->case_sensitive)) {
4700 continue;
4703 if (sysdir_entry) {
4704 status = NT_STATUS_OBJECT_NAME_INVALID;
4705 break;
4708 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4710 pstrcpy(destname,newname);
4712 if (!resolve_wildcards(fname,destname)) {
4713 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4714 fname, destname));
4715 continue;
4718 ZERO_STRUCT(sbuf1);
4719 SMB_VFS_STAT(conn, fname, &sbuf1);
4721 status = S_ISDIR(sbuf1.st_mode) ?
4722 open_directory(conn, req, fname, &sbuf1,
4723 DELETE_ACCESS,
4724 FILE_SHARE_READ|FILE_SHARE_WRITE,
4725 FILE_OPEN, 0, 0, NULL,
4726 &fsp)
4727 : open_file_ntcreate(conn, req, fname, &sbuf1,
4728 DELETE_ACCESS,
4729 FILE_SHARE_READ|FILE_SHARE_WRITE,
4730 FILE_OPEN, 0, 0, 0, NULL,
4731 &fsp);
4733 if (!NT_STATUS_IS_OK(status)) {
4734 DEBUG(3,("rename_internals: open_file_ntcreate "
4735 "returned %s rename %s -> %s\n",
4736 nt_errstr(status), directory, newname));
4737 break;
4740 status = rename_internals_fsp(conn, fsp, destname, attrs,
4741 replace_if_exists);
4743 close_file(fsp, NORMAL_CLOSE);
4745 if (!NT_STATUS_IS_OK(status)) {
4746 DEBUG(3, ("rename_internals_fsp returned %s for "
4747 "rename %s -> %s\n", nt_errstr(status),
4748 directory, newname));
4749 break;
4752 count++;
4754 DEBUG(3,("rename_internals: doing rename on %s -> "
4755 "%s\n",fname,destname));
4757 CloseDir(dir_hnd);
4759 if (count == 0 && NT_STATUS_IS_OK(status)) {
4760 status = map_nt_error_from_unix(errno);
4763 return status;
4766 /****************************************************************************
4767 Reply to a mv.
4768 ****************************************************************************/
4770 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4771 int dum_buffsize)
4773 int outsize = 0;
4774 pstring name;
4775 pstring newname;
4776 char *p;
4777 uint32 attrs = SVAL(inbuf,smb_vwv0);
4778 NTSTATUS status;
4779 BOOL src_has_wcard = False;
4780 BOOL dest_has_wcard = False;
4781 struct smb_request req;
4783 START_PROFILE(SMBmv);
4785 init_smb_request(&req, (uint8 *)inbuf);
4787 p = smb_buf(inbuf) + 1;
4788 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
4789 sizeof(name), 0, STR_TERMINATE, &status,
4790 &src_has_wcard);
4791 if (!NT_STATUS_IS_OK(status)) {
4792 END_PROFILE(SMBmv);
4793 return ERROR_NT(status);
4795 p++;
4796 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
4797 sizeof(newname), 0, STR_TERMINATE, &status,
4798 &dest_has_wcard);
4799 if (!NT_STATUS_IS_OK(status)) {
4800 END_PROFILE(SMBmv);
4801 return ERROR_NT(status);
4804 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
4805 if (!NT_STATUS_IS_OK(status)) {
4806 END_PROFILE(SMBmv);
4807 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4808 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4810 return ERROR_NT(status);
4813 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4814 if (!NT_STATUS_IS_OK(status)) {
4815 END_PROFILE(SMBmv);
4816 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4817 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4819 return ERROR_NT(status);
4822 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4824 status = rename_internals(conn, &req, name, newname, attrs, False,
4825 src_has_wcard, dest_has_wcard);
4826 if (!NT_STATUS_IS_OK(status)) {
4827 END_PROFILE(SMBmv);
4828 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4829 /* We have re-scheduled this call. */
4830 return -1;
4832 return ERROR_NT(status);
4835 outsize = set_message(inbuf,outbuf,0,0,False);
4837 END_PROFILE(SMBmv);
4838 return(outsize);
4841 /*******************************************************************
4842 Copy a file as part of a reply_copy.
4843 ******************************************************************/
4846 * TODO: check error codes on all callers
4849 NTSTATUS copy_file(connection_struct *conn,
4850 char *src,
4851 char *dest1,
4852 int ofun,
4853 int count,
4854 BOOL target_is_directory)
4856 SMB_STRUCT_STAT src_sbuf, sbuf2;
4857 SMB_OFF_T ret=-1;
4858 files_struct *fsp1,*fsp2;
4859 pstring dest;
4860 uint32 dosattrs;
4861 uint32 new_create_disposition;
4862 NTSTATUS status;
4864 pstrcpy(dest,dest1);
4865 if (target_is_directory) {
4866 char *p = strrchr_m(src,'/');
4867 if (p) {
4868 p++;
4869 } else {
4870 p = src;
4872 pstrcat(dest,"/");
4873 pstrcat(dest,p);
4876 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4877 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4880 if (!target_is_directory && count) {
4881 new_create_disposition = FILE_OPEN;
4882 } else {
4883 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4884 NULL, NULL, &new_create_disposition, NULL)) {
4885 return NT_STATUS_INVALID_PARAMETER;
4889 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
4890 FILE_GENERIC_READ,
4891 FILE_SHARE_READ|FILE_SHARE_WRITE,
4892 FILE_OPEN,
4894 FILE_ATTRIBUTE_NORMAL,
4895 INTERNAL_OPEN_ONLY,
4896 NULL, &fsp1);
4898 if (!NT_STATUS_IS_OK(status)) {
4899 return status;
4902 dosattrs = dos_mode(conn, src, &src_sbuf);
4903 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4904 ZERO_STRUCTP(&sbuf2);
4907 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
4908 FILE_GENERIC_WRITE,
4909 FILE_SHARE_READ|FILE_SHARE_WRITE,
4910 new_create_disposition,
4912 dosattrs,
4913 INTERNAL_OPEN_ONLY,
4914 NULL, &fsp2);
4916 if (!NT_STATUS_IS_OK(status)) {
4917 close_file(fsp1,ERROR_CLOSE);
4918 return status;
4921 if ((ofun&3) == 1) {
4922 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4923 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4925 * Stop the copy from occurring.
4927 ret = -1;
4928 src_sbuf.st_size = 0;
4932 if (src_sbuf.st_size) {
4933 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4936 close_file(fsp1,NORMAL_CLOSE);
4938 /* Ensure the modtime is set correctly on the destination file. */
4939 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
4942 * As we are opening fsp1 read-only we only expect
4943 * an error on close on fsp2 if we are out of space.
4944 * Thus we don't look at the error return from the
4945 * close of fsp1.
4947 status = close_file(fsp2,NORMAL_CLOSE);
4949 if (!NT_STATUS_IS_OK(status)) {
4950 return status;
4953 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4954 return NT_STATUS_DISK_FULL;
4957 return NT_STATUS_OK;
4960 /****************************************************************************
4961 Reply to a file copy.
4962 ****************************************************************************/
4964 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4966 int outsize = 0;
4967 pstring name;
4968 pstring directory;
4969 pstring mask,newname;
4970 char *p;
4971 int count=0;
4972 int error = ERRnoaccess;
4973 int err = 0;
4974 int tid2 = SVAL(inbuf,smb_vwv0);
4975 int ofun = SVAL(inbuf,smb_vwv1);
4976 int flags = SVAL(inbuf,smb_vwv2);
4977 BOOL target_is_directory=False;
4978 BOOL source_has_wild = False;
4979 BOOL dest_has_wild = False;
4980 SMB_STRUCT_STAT sbuf1, sbuf2;
4981 NTSTATUS status;
4982 START_PROFILE(SMBcopy);
4984 *directory = *mask = 0;
4986 p = smb_buf(inbuf);
4987 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
4988 sizeof(name), 0, STR_TERMINATE, &status,
4989 &source_has_wild);
4990 if (!NT_STATUS_IS_OK(status)) {
4991 END_PROFILE(SMBcopy);
4992 return ERROR_NT(status);
4994 p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
4995 sizeof(newname), 0, STR_TERMINATE, &status,
4996 &dest_has_wild);
4997 if (!NT_STATUS_IS_OK(status)) {
4998 END_PROFILE(SMBcopy);
4999 return ERROR_NT(status);
5002 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5004 if (tid2 != conn->cnum) {
5005 /* can't currently handle inter share copies XXXX */
5006 DEBUG(3,("Rejecting inter-share copy\n"));
5007 END_PROFILE(SMBcopy);
5008 return ERROR_DOS(ERRSRV,ERRinvdevice);
5011 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5012 if (!NT_STATUS_IS_OK(status)) {
5013 END_PROFILE(SMBcopy);
5014 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5015 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5017 return ERROR_NT(status);
5020 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5021 if (!NT_STATUS_IS_OK(status)) {
5022 END_PROFILE(SMBcopy);
5023 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5024 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5026 return ERROR_NT(status);
5029 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5030 if (!NT_STATUS_IS_OK(status)) {
5031 END_PROFILE(SMBcopy);
5032 return ERROR_NT(status);
5035 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5036 if (!NT_STATUS_IS_OK(status)) {
5037 END_PROFILE(SMBcopy);
5038 return ERROR_NT(status);
5041 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5043 if ((flags&1) && target_is_directory) {
5044 END_PROFILE(SMBcopy);
5045 return ERROR_DOS(ERRDOS,ERRbadfile);
5048 if ((flags&2) && !target_is_directory) {
5049 END_PROFILE(SMBcopy);
5050 return ERROR_DOS(ERRDOS,ERRbadpath);
5053 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5054 /* wants a tree copy! XXXX */
5055 DEBUG(3,("Rejecting tree copy\n"));
5056 END_PROFILE(SMBcopy);
5057 return ERROR_DOS(ERRSRV,ERRerror);
5060 p = strrchr_m(name,'/');
5061 if (!p) {
5062 pstrcpy(directory,"./");
5063 pstrcpy(mask,name);
5064 } else {
5065 *p = 0;
5066 pstrcpy(directory,name);
5067 pstrcpy(mask,p+1);
5071 * We should only check the mangled cache
5072 * here if unix_convert failed. This means
5073 * that the path in 'mask' doesn't exist
5074 * on the file system and so we need to look
5075 * for a possible mangle. This patch from
5076 * Tine Smukavec <valentin.smukavec@hermes.si>.
5079 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5080 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5083 if (!source_has_wild) {
5084 pstrcat(directory,"/");
5085 pstrcat(directory,mask);
5086 if (dest_has_wild) {
5087 if (!resolve_wildcards(directory,newname)) {
5088 END_PROFILE(SMBcopy);
5089 return ERROR_NT(NT_STATUS_NO_MEMORY);
5093 status = check_name(conn, directory);
5094 if (!NT_STATUS_IS_OK(status)) {
5095 return ERROR_NT(status);
5098 status = check_name(conn, newname);
5099 if (!NT_STATUS_IS_OK(status)) {
5100 return ERROR_NT(status);
5103 status = copy_file(conn,directory,newname,ofun,
5104 count,target_is_directory);
5106 if(!NT_STATUS_IS_OK(status)) {
5107 END_PROFILE(SMBcopy);
5108 return ERROR_NT(status);
5109 } else {
5110 count++;
5112 } else {
5113 struct smb_Dir *dir_hnd = NULL;
5114 const char *dname;
5115 long offset = 0;
5116 pstring destname;
5118 if (strequal(mask,"????????.???"))
5119 pstrcpy(mask,"*");
5121 status = check_name(conn, directory);
5122 if (!NT_STATUS_IS_OK(status)) {
5123 return ERROR_NT(status);
5126 dir_hnd = OpenDir(conn, directory, mask, 0);
5127 if (dir_hnd == NULL) {
5128 status = map_nt_error_from_unix(errno);
5129 return ERROR_NT(status);
5132 error = ERRbadfile;
5134 while ((dname = ReadDirName(dir_hnd, &offset))) {
5135 pstring fname;
5136 pstrcpy(fname,dname);
5138 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5139 continue;
5142 if(!mask_match(fname, mask, conn->case_sensitive)) {
5143 continue;
5146 error = ERRnoaccess;
5147 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5148 pstrcpy(destname,newname);
5149 if (!resolve_wildcards(fname,destname)) {
5150 continue;
5153 status = check_name(conn, fname);
5154 if (!NT_STATUS_IS_OK(status)) {
5155 return ERROR_NT(status);
5158 status = check_name(conn, destname);
5159 if (!NT_STATUS_IS_OK(status)) {
5160 return ERROR_NT(status);
5163 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5165 status = copy_file(conn,fname,destname,ofun,
5166 count,target_is_directory);
5167 if (NT_STATUS_IS_OK(status)) {
5168 count++;
5171 CloseDir(dir_hnd);
5174 if (count == 0) {
5175 if(err) {
5176 /* Error on close... */
5177 errno = err;
5178 END_PROFILE(SMBcopy);
5179 return(UNIXERROR(ERRHRD,ERRgeneral));
5182 END_PROFILE(SMBcopy);
5183 return ERROR_DOS(ERRDOS,error);
5186 outsize = set_message(inbuf,outbuf,1,0,True);
5187 SSVAL(outbuf,smb_vwv0,count);
5189 END_PROFILE(SMBcopy);
5190 return(outsize);
5193 /****************************************************************************
5194 Reply to a setdir.
5195 ****************************************************************************/
5197 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5199 int snum;
5200 int outsize = 0;
5201 pstring newdir;
5202 NTSTATUS status;
5204 START_PROFILE(pathworks_setdir);
5206 snum = SNUM(conn);
5207 if (!CAN_SETDIR(snum)) {
5208 END_PROFILE(pathworks_setdir);
5209 return ERROR_DOS(ERRDOS,ERRnoaccess);
5212 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
5213 smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
5214 &status);
5215 if (!NT_STATUS_IS_OK(status)) {
5216 END_PROFILE(pathworks_setdir);
5217 return ERROR_NT(status);
5220 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5221 if (!NT_STATUS_IS_OK(status)) {
5222 END_PROFILE(pathworks_setdir);
5223 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5224 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5226 return ERROR_NT(status);
5229 if (strlen(newdir) != 0) {
5230 if (!vfs_directory_exist(conn,newdir,NULL)) {
5231 END_PROFILE(pathworks_setdir);
5232 return ERROR_DOS(ERRDOS,ERRbadpath);
5234 set_conn_connectpath(conn,newdir);
5237 outsize = set_message(inbuf,outbuf,0,0,False);
5238 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5240 DEBUG(3,("setdir %s\n", newdir));
5242 END_PROFILE(pathworks_setdir);
5243 return(outsize);
5246 #undef DBGC_CLASS
5247 #define DBGC_CLASS DBGC_LOCKING
5249 /****************************************************************************
5250 Get a lock pid, dealing with large count requests.
5251 ****************************************************************************/
5253 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5255 if(!large_file_format)
5256 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5257 else
5258 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5261 /****************************************************************************
5262 Get a lock count, dealing with large count requests.
5263 ****************************************************************************/
5265 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5267 SMB_BIG_UINT count = 0;
5269 if(!large_file_format) {
5270 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5271 } else {
5273 #if defined(HAVE_LONGLONG)
5274 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5275 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5276 #else /* HAVE_LONGLONG */
5279 * NT4.x seems to be broken in that it sends large file (64 bit)
5280 * lockingX calls even if the CAP_LARGE_FILES was *not*
5281 * negotiated. For boxes without large unsigned ints truncate the
5282 * lock count by dropping the top 32 bits.
5285 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5286 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5287 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5288 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5289 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5292 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5293 #endif /* HAVE_LONGLONG */
5296 return count;
5299 #if !defined(HAVE_LONGLONG)
5300 /****************************************************************************
5301 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5302 ****************************************************************************/
5304 static uint32 map_lock_offset(uint32 high, uint32 low)
5306 unsigned int i;
5307 uint32 mask = 0;
5308 uint32 highcopy = high;
5311 * Try and find out how many significant bits there are in high.
5314 for(i = 0; highcopy; i++)
5315 highcopy >>= 1;
5318 * We use 31 bits not 32 here as POSIX
5319 * lock offsets may not be negative.
5322 mask = (~0) << (31 - i);
5324 if(low & mask)
5325 return 0; /* Fail. */
5327 high <<= (31 - i);
5329 return (high|low);
5331 #endif /* !defined(HAVE_LONGLONG) */
5333 /****************************************************************************
5334 Get a lock offset, dealing with large offset requests.
5335 ****************************************************************************/
5337 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5339 SMB_BIG_UINT offset = 0;
5341 *err = False;
5343 if(!large_file_format) {
5344 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5345 } else {
5347 #if defined(HAVE_LONGLONG)
5348 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5349 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5350 #else /* HAVE_LONGLONG */
5353 * NT4.x seems to be broken in that it sends large file (64 bit)
5354 * lockingX calls even if the CAP_LARGE_FILES was *not*
5355 * negotiated. For boxes without large unsigned ints mangle the
5356 * lock offset by mapping the top 32 bits onto the lower 32.
5359 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5360 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5361 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5362 uint32 new_low = 0;
5364 if((new_low = map_lock_offset(high, low)) == 0) {
5365 *err = True;
5366 return (SMB_BIG_UINT)-1;
5369 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5370 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5371 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5372 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5375 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5376 #endif /* HAVE_LONGLONG */
5379 return offset;
5382 /****************************************************************************
5383 Reply to a lockingX request.
5384 ****************************************************************************/
5386 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5387 int length, int bufsize)
5389 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5390 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5391 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5392 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5393 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5394 SMB_BIG_UINT count = 0, offset = 0;
5395 uint32 lock_pid;
5396 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5397 int i;
5398 char *data;
5399 BOOL large_file_format =
5400 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5401 BOOL err;
5402 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5404 START_PROFILE(SMBlockingX);
5406 CHECK_FSP(fsp,conn);
5408 data = smb_buf(inbuf);
5410 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5411 /* we don't support these - and CANCEL_LOCK makes w2k
5412 and XP reboot so I don't really want to be
5413 compatible! (tridge) */
5414 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5417 /* Check if this is an oplock break on a file
5418 we have granted an oplock on.
5420 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5421 /* Client can insist on breaking to none. */
5422 BOOL break_to_none = (oplocklevel == 0);
5423 BOOL result;
5425 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5426 "for fnum = %d\n", (unsigned int)oplocklevel,
5427 fsp->fnum ));
5430 * Make sure we have granted an exclusive or batch oplock on
5431 * this file.
5434 if (fsp->oplock_type == 0) {
5436 /* The Samba4 nbench simulator doesn't understand
5437 the difference between break to level2 and break
5438 to none from level2 - it sends oplock break
5439 replies in both cases. Don't keep logging an error
5440 message here - just ignore it. JRA. */
5442 DEBUG(5,("reply_lockingX: Error : oplock break from "
5443 "client for fnum = %d (oplock=%d) and no "
5444 "oplock granted on this file (%s).\n",
5445 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5447 /* if this is a pure oplock break request then don't
5448 * send a reply */
5449 if (num_locks == 0 && num_ulocks == 0) {
5450 END_PROFILE(SMBlockingX);
5451 return -1;
5452 } else {
5453 END_PROFILE(SMBlockingX);
5454 return ERROR_DOS(ERRDOS,ERRlock);
5458 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5459 (break_to_none)) {
5460 result = remove_oplock(fsp);
5461 } else {
5462 result = downgrade_oplock(fsp);
5465 if (!result) {
5466 DEBUG(0, ("reply_lockingX: error in removing "
5467 "oplock on file %s\n", fsp->fsp_name));
5468 /* Hmmm. Is this panic justified? */
5469 smb_panic("internal tdb error");
5472 reply_to_oplock_break_requests(fsp);
5474 /* if this is a pure oplock break request then don't send a
5475 * reply */
5476 if (num_locks == 0 && num_ulocks == 0) {
5477 /* Sanity check - ensure a pure oplock break is not a
5478 chained request. */
5479 if(CVAL(inbuf,smb_vwv0) != 0xff)
5480 DEBUG(0,("reply_lockingX: Error : pure oplock "
5481 "break is a chained %d request !\n",
5482 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5483 END_PROFILE(SMBlockingX);
5484 return -1;
5489 * We do this check *after* we have checked this is not a oplock break
5490 * response message. JRA.
5493 release_level_2_oplocks_on_change(fsp);
5495 /* Data now points at the beginning of the list
5496 of smb_unlkrng structs */
5497 for(i = 0; i < (int)num_ulocks; i++) {
5498 lock_pid = get_lock_pid( data, i, large_file_format);
5499 count = get_lock_count( data, i, large_file_format);
5500 offset = get_lock_offset( data, i, large_file_format, &err);
5503 * There is no error code marked "stupid client bug".... :-).
5505 if(err) {
5506 END_PROFILE(SMBlockingX);
5507 return ERROR_DOS(ERRDOS,ERRnoaccess);
5510 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5511 "pid %u, file %s\n", (double)offset, (double)count,
5512 (unsigned int)lock_pid, fsp->fsp_name ));
5514 status = do_unlock(smbd_messaging_context(),
5515 fsp,
5516 lock_pid,
5517 count,
5518 offset,
5519 WINDOWS_LOCK);
5521 if (NT_STATUS_V(status)) {
5522 END_PROFILE(SMBlockingX);
5523 return ERROR_NT(status);
5527 /* Setup the timeout in seconds. */
5529 if (!lp_blocking_locks(SNUM(conn))) {
5530 lock_timeout = 0;
5533 /* Now do any requested locks */
5534 data += ((large_file_format ? 20 : 10)*num_ulocks);
5536 /* Data now points at the beginning of the list
5537 of smb_lkrng structs */
5539 for(i = 0; i < (int)num_locks; i++) {
5540 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5541 READ_LOCK:WRITE_LOCK);
5542 lock_pid = get_lock_pid( data, i, large_file_format);
5543 count = get_lock_count( data, i, large_file_format);
5544 offset = get_lock_offset( data, i, large_file_format, &err);
5547 * There is no error code marked "stupid client bug".... :-).
5549 if(err) {
5550 END_PROFILE(SMBlockingX);
5551 return ERROR_DOS(ERRDOS,ERRnoaccess);
5554 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5555 "%u, file %s timeout = %d\n", (double)offset,
5556 (double)count, (unsigned int)lock_pid,
5557 fsp->fsp_name, (int)lock_timeout ));
5559 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5560 if (lp_blocking_locks(SNUM(conn))) {
5562 /* Schedule a message to ourselves to
5563 remove the blocking lock record and
5564 return the right error. */
5566 if (!blocking_lock_cancel(fsp,
5567 lock_pid,
5568 offset,
5569 count,
5570 WINDOWS_LOCK,
5571 locktype,
5572 NT_STATUS_FILE_LOCK_CONFLICT)) {
5573 END_PROFILE(SMBlockingX);
5574 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5577 /* Remove a matching pending lock. */
5578 status = do_lock_cancel(fsp,
5579 lock_pid,
5580 count,
5581 offset,
5582 WINDOWS_LOCK);
5583 } else {
5584 BOOL blocking_lock = lock_timeout ? True : False;
5585 BOOL defer_lock = False;
5586 struct byte_range_lock *br_lck;
5587 uint32 block_smbpid;
5589 br_lck = do_lock(smbd_messaging_context(),
5590 fsp,
5591 lock_pid,
5592 count,
5593 offset,
5594 lock_type,
5595 WINDOWS_LOCK,
5596 blocking_lock,
5597 &status,
5598 &block_smbpid);
5600 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5601 /* Windows internal resolution for blocking locks seems
5602 to be about 200ms... Don't wait for less than that. JRA. */
5603 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5604 lock_timeout = lp_lock_spin_time();
5606 defer_lock = True;
5609 /* This heuristic seems to match W2K3 very well. If a
5610 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5611 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5612 far as I can tell. Replacement for do_lock_spin(). JRA. */
5614 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5615 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5616 defer_lock = True;
5617 lock_timeout = lp_lock_spin_time();
5620 if (br_lck && defer_lock) {
5622 * A blocking lock was requested. Package up
5623 * this smb into a queued request and push it
5624 * onto the blocking lock queue.
5626 if(push_blocking_lock_request(br_lck,
5627 inbuf, length,
5628 fsp,
5629 lock_timeout,
5631 lock_pid,
5632 lock_type,
5633 WINDOWS_LOCK,
5634 offset,
5635 count,
5636 block_smbpid)) {
5637 TALLOC_FREE(br_lck);
5638 END_PROFILE(SMBlockingX);
5639 return -1;
5643 TALLOC_FREE(br_lck);
5646 if (NT_STATUS_V(status)) {
5647 END_PROFILE(SMBlockingX);
5648 return ERROR_NT(status);
5652 /* If any of the above locks failed, then we must unlock
5653 all of the previous locks (X/Open spec). */
5655 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5656 (i != num_locks) &&
5657 (num_locks != 0)) {
5659 * Ensure we don't do a remove on the lock that just failed,
5660 * as under POSIX rules, if we have a lock already there, we
5661 * will delete it (and we shouldn't) .....
5663 for(i--; i >= 0; i--) {
5664 lock_pid = get_lock_pid( data, i, large_file_format);
5665 count = get_lock_count( data, i, large_file_format);
5666 offset = get_lock_offset( data, i, large_file_format,
5667 &err);
5670 * There is no error code marked "stupid client
5671 * bug".... :-).
5673 if(err) {
5674 END_PROFILE(SMBlockingX);
5675 return ERROR_DOS(ERRDOS,ERRnoaccess);
5678 do_unlock(smbd_messaging_context(),
5679 fsp,
5680 lock_pid,
5681 count,
5682 offset,
5683 WINDOWS_LOCK);
5685 END_PROFILE(SMBlockingX);
5686 return ERROR_NT(status);
5689 set_message(inbuf,outbuf,2,0,True);
5691 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5692 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5694 END_PROFILE(SMBlockingX);
5695 return chain_reply(inbuf,outbuf,length,bufsize);
5698 #undef DBGC_CLASS
5699 #define DBGC_CLASS DBGC_ALL
5701 /****************************************************************************
5702 Reply to a SMBreadbmpx (read block multiplex) request.
5703 ****************************************************************************/
5705 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5707 ssize_t nread = -1;
5708 ssize_t total_read;
5709 char *data;
5710 SMB_OFF_T startpos;
5711 int outsize;
5712 size_t maxcount;
5713 int max_per_packet;
5714 size_t tcount;
5715 int pad;
5716 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5717 START_PROFILE(SMBreadBmpx);
5719 /* this function doesn't seem to work - disable by default */
5720 if (!lp_readbmpx()) {
5721 END_PROFILE(SMBreadBmpx);
5722 return ERROR_DOS(ERRSRV,ERRuseSTD);
5725 outsize = set_message(inbuf,outbuf,8,0,True);
5727 CHECK_FSP(fsp,conn);
5728 if (!CHECK_READ(fsp,inbuf)) {
5729 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5732 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5733 maxcount = SVAL(inbuf,smb_vwv3);
5735 data = smb_buf(outbuf);
5736 pad = ((long)data)%4;
5737 if (pad)
5738 pad = 4 - pad;
5739 data += pad;
5741 max_per_packet = bufsize-(outsize+pad);
5742 tcount = maxcount;
5743 total_read = 0;
5745 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5746 END_PROFILE(SMBreadBmpx);
5747 return ERROR_DOS(ERRDOS,ERRlock);
5750 do {
5751 size_t N = MIN(max_per_packet,tcount-total_read);
5753 nread = read_file(fsp,data,startpos,N);
5755 if (nread <= 0)
5756 nread = 0;
5758 if (nread < (ssize_t)N)
5759 tcount = total_read + nread;
5761 set_message(inbuf,outbuf,8,nread+pad,False);
5762 SIVAL(outbuf,smb_vwv0,startpos);
5763 SSVAL(outbuf,smb_vwv2,tcount);
5764 SSVAL(outbuf,smb_vwv6,nread);
5765 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5767 show_msg(outbuf);
5768 if (!send_smb(smbd_server_fd(),outbuf))
5769 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5771 total_read += nread;
5772 startpos += nread;
5773 } while (total_read < (ssize_t)tcount);
5775 END_PROFILE(SMBreadBmpx);
5776 return(-1);
5779 /****************************************************************************
5780 Reply to a SMBsetattrE.
5781 ****************************************************************************/
5783 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5785 struct timespec ts[2];
5786 int outsize = 0;
5787 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5788 START_PROFILE(SMBsetattrE);
5790 outsize = set_message(inbuf,outbuf,0,0,False);
5792 if(!fsp || (fsp->conn != conn)) {
5793 END_PROFILE(SMBsetattrE);
5794 return ERROR_DOS(ERRDOS,ERRbadfid);
5798 * Convert the DOS times into unix times. Ignore create
5799 * time as UNIX can't set this.
5802 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5803 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5806 * Patch from Ray Frush <frush@engr.colostate.edu>
5807 * Sometimes times are sent as zero - ignore them.
5810 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5811 /* Ignore request */
5812 if( DEBUGLVL( 3 ) ) {
5813 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5814 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5816 END_PROFILE(SMBsetattrE);
5817 return(outsize);
5818 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5819 /* set modify time = to access time if modify time was unset */
5820 ts[1] = ts[0];
5823 /* Set the date on this file */
5824 /* Should we set pending modtime here ? JRA */
5825 if(file_ntimes(conn, fsp->fsp_name, ts)) {
5826 END_PROFILE(SMBsetattrE);
5827 return ERROR_DOS(ERRDOS,ERRnoaccess);
5830 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5831 fsp->fnum,
5832 (unsigned int)ts[0].tv_sec,
5833 (unsigned int)ts[1].tv_sec));
5835 END_PROFILE(SMBsetattrE);
5836 return(outsize);
5840 /* Back from the dead for OS/2..... JRA. */
5842 /****************************************************************************
5843 Reply to a SMBwritebmpx (write block multiplex primary) request.
5844 ****************************************************************************/
5846 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5848 size_t numtowrite;
5849 ssize_t nwritten = -1;
5850 int outsize = 0;
5851 SMB_OFF_T startpos;
5852 size_t tcount;
5853 BOOL write_through;
5854 int smb_doff;
5855 char *data;
5856 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5857 NTSTATUS status;
5858 START_PROFILE(SMBwriteBmpx);
5860 CHECK_FSP(fsp,conn);
5861 if (!CHECK_WRITE(fsp)) {
5862 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5864 if (HAS_CACHED_ERROR(fsp)) {
5865 return(CACHED_ERROR(fsp));
5868 tcount = SVAL(inbuf,smb_vwv1);
5869 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5870 write_through = BITSETW(inbuf+smb_vwv7,0);
5871 numtowrite = SVAL(inbuf,smb_vwv10);
5872 smb_doff = SVAL(inbuf,smb_vwv11);
5874 data = smb_base(inbuf) + smb_doff;
5876 /* If this fails we need to send an SMBwriteC response,
5877 not an SMBwritebmpx - set this up now so we don't forget */
5878 SCVAL(outbuf,smb_com,SMBwritec);
5880 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5881 END_PROFILE(SMBwriteBmpx);
5882 return(ERROR_DOS(ERRDOS,ERRlock));
5885 nwritten = write_file(fsp,data,startpos,numtowrite);
5887 status = sync_file(conn, fsp, write_through);
5888 if (!NT_STATUS_IS_OK(status)) {
5889 END_PROFILE(SMBwriteBmpx);
5890 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
5891 fsp->fsp_name, nt_errstr(status) ));
5892 return ERROR_NT(status);
5895 if(nwritten < (ssize_t)numtowrite) {
5896 END_PROFILE(SMBwriteBmpx);
5897 return(UNIXERROR(ERRHRD,ERRdiskfull));
5900 /* If the maximum to be written to this file
5901 is greater than what we just wrote then set
5902 up a secondary struct to be attached to this
5903 fd, we will use this to cache error messages etc. */
5905 if((ssize_t)tcount > nwritten) {
5906 write_bmpx_struct *wbms;
5907 if(fsp->wbmpx_ptr != NULL)
5908 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5909 else
5910 wbms = SMB_MALLOC_P(write_bmpx_struct);
5911 if(!wbms) {
5912 DEBUG(0,("Out of memory in reply_readmpx\n"));
5913 END_PROFILE(SMBwriteBmpx);
5914 return(ERROR_DOS(ERRSRV,ERRnoresource));
5916 wbms->wr_mode = write_through;
5917 wbms->wr_discard = False; /* No errors yet */
5918 wbms->wr_total_written = nwritten;
5919 wbms->wr_errclass = 0;
5920 wbms->wr_error = 0;
5921 fsp->wbmpx_ptr = wbms;
5924 /* We are returning successfully, set the message type back to
5925 SMBwritebmpx */
5926 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5928 outsize = set_message(inbuf,outbuf,1,0,True);
5930 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5932 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5933 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5935 if (write_through && tcount==nwritten) {
5936 /* We need to send both a primary and a secondary response */
5937 smb_setlen(inbuf,outbuf,outsize - 4);
5938 show_msg(outbuf);
5939 if (!send_smb(smbd_server_fd(),outbuf))
5940 exit_server_cleanly("reply_writebmpx: send_smb failed.");
5942 /* Now the secondary */
5943 outsize = set_message(inbuf,outbuf,1,0,True);
5944 SCVAL(outbuf,smb_com,SMBwritec);
5945 SSVAL(outbuf,smb_vwv0,nwritten);
5948 END_PROFILE(SMBwriteBmpx);
5949 return(outsize);
5952 /****************************************************************************
5953 Reply to a SMBwritebs (write block multiplex secondary) request.
5954 ****************************************************************************/
5956 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5958 size_t numtowrite;
5959 ssize_t nwritten = -1;
5960 int outsize = 0;
5961 SMB_OFF_T startpos;
5962 size_t tcount;
5963 BOOL write_through;
5964 int smb_doff;
5965 char *data;
5966 write_bmpx_struct *wbms;
5967 BOOL send_response = False;
5968 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5969 NTSTATUS status;
5970 START_PROFILE(SMBwriteBs);
5972 CHECK_FSP(fsp,conn);
5973 if (!CHECK_WRITE(fsp)) {
5974 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5977 tcount = SVAL(inbuf,smb_vwv1);
5978 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5979 numtowrite = SVAL(inbuf,smb_vwv6);
5980 smb_doff = SVAL(inbuf,smb_vwv7);
5982 data = smb_base(inbuf) + smb_doff;
5984 /* We need to send an SMBwriteC response, not an SMBwritebs */
5985 SCVAL(outbuf,smb_com,SMBwritec);
5987 /* This fd should have an auxiliary struct attached,
5988 check that it does */
5989 wbms = fsp->wbmpx_ptr;
5990 if(!wbms) {
5991 END_PROFILE(SMBwriteBs);
5992 return(-1);
5995 /* If write through is set we can return errors, else we must cache them */
5996 write_through = wbms->wr_mode;
5998 /* Check for an earlier error */
5999 if(wbms->wr_discard) {
6000 END_PROFILE(SMBwriteBs);
6001 return -1; /* Just discard the packet */
6004 nwritten = write_file(fsp,data,startpos,numtowrite);
6006 status = sync_file(conn, fsp, write_through);
6008 if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6009 if(write_through) {
6010 /* We are returning an error - we can delete the aux struct */
6011 if (wbms)
6012 free((char *)wbms);
6013 fsp->wbmpx_ptr = NULL;
6014 END_PROFILE(SMBwriteBs);
6015 return(ERROR_DOS(ERRHRD,ERRdiskfull));
6017 wbms->wr_errclass = ERRHRD;
6018 wbms->wr_error = ERRdiskfull;
6019 wbms->wr_status = NT_STATUS_DISK_FULL;
6020 wbms->wr_discard = True;
6021 END_PROFILE(SMBwriteBs);
6022 return -1;
6025 /* Increment the total written, if this matches tcount
6026 we can discard the auxiliary struct (hurrah !) and return a writeC */
6027 wbms->wr_total_written += nwritten;
6028 if(wbms->wr_total_written >= tcount) {
6029 if (write_through) {
6030 outsize = set_message(inbuf,outbuf,1,0,True);
6031 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
6032 send_response = True;
6035 free((char *)wbms);
6036 fsp->wbmpx_ptr = NULL;
6039 if(send_response) {
6040 END_PROFILE(SMBwriteBs);
6041 return(outsize);
6044 END_PROFILE(SMBwriteBs);
6045 return(-1);
6048 /****************************************************************************
6049 Reply to a SMBgetattrE.
6050 ****************************************************************************/
6052 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6054 SMB_STRUCT_STAT sbuf;
6055 int outsize = 0;
6056 int mode;
6057 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
6058 START_PROFILE(SMBgetattrE);
6060 outsize = set_message(inbuf,outbuf,11,0,True);
6062 if(!fsp || (fsp->conn != conn)) {
6063 END_PROFILE(SMBgetattrE);
6064 return ERROR_DOS(ERRDOS,ERRbadfid);
6067 /* Do an fstat on this file */
6068 if(fsp_stat(fsp, &sbuf)) {
6069 END_PROFILE(SMBgetattrE);
6070 return(UNIXERROR(ERRDOS,ERRnoaccess));
6073 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6076 * Convert the times into dos times. Set create
6077 * date to be last modify date as UNIX doesn't save
6078 * this.
6081 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6082 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6083 /* Should we check pending modtime here ? JRA */
6084 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6086 if (mode & aDIR) {
6087 SIVAL(outbuf,smb_vwv6,0);
6088 SIVAL(outbuf,smb_vwv8,0);
6089 } else {
6090 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6091 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6092 SIVAL(outbuf,smb_vwv8,allocation_size);
6094 SSVAL(outbuf,smb_vwv10, mode);
6096 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6098 END_PROFILE(SMBgetattrE);
6099 return(outsize);