r23523: Gaa -- had renamed "name" to "path" and apparently not compiled after
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blobe2b7084f114ad146c3c045711214d291ad5e35fc
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, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
213 NTSTATUS *err, BOOL *contains_wcard)
215 size_t ret;
216 #ifdef DEVELOPER
217 SMB_ASSERT(dest_len == sizeof(pstring));
218 #endif
220 if (src_len == 0) {
221 ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags);
222 } else {
223 ret = srvstr_pull( inbuf, dest, src, dest_len, src_len, flags);
226 *contains_wcard = False;
228 if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
230 * For a DFS path the function parse_dfs_path()
231 * will do the path processing, just make a copy.
233 *err = NT_STATUS_OK;
234 return ret;
237 if (lp_posix_pathnames()) {
238 *err = check_path_syntax_posix(dest);
239 } else {
240 *err = check_path_syntax_wcard(dest, contains_wcard);
243 return ret;
246 /****************************************************************************
247 Pull a string and check the path - provide for error return.
248 ****************************************************************************/
250 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
252 size_t ret;
253 #ifdef DEVELOPER
254 SMB_ASSERT(dest_len == sizeof(pstring));
255 #endif
257 if (src_len == 0) {
258 ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags);
259 } else {
260 ret = srvstr_pull( inbuf, dest, src, dest_len, src_len, flags);
263 if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
265 * For a DFS path the function parse_dfs_path()
266 * will do the path processing, just make a copy.
268 *err = NT_STATUS_OK;
269 return ret;
272 if (lp_posix_pathnames()) {
273 *err = check_path_syntax_posix(dest);
274 } else {
275 *err = check_path_syntax(dest);
278 return ret;
281 /****************************************************************************
282 Reply to a special message.
283 ****************************************************************************/
285 int reply_special(char *inbuf,char *outbuf)
287 int outsize = 4;
288 int msg_type = CVAL(inbuf,0);
289 int msg_flags = CVAL(inbuf,1);
290 fstring name1,name2;
291 char name_type = 0;
293 static BOOL already_got_session = False;
295 *name1 = *name2 = 0;
297 memset(outbuf,'\0',smb_size);
299 smb_setlen(inbuf,outbuf,0);
301 switch (msg_type) {
302 case 0x81: /* session request */
304 if (already_got_session) {
305 exit_server_cleanly("multiple session request not permitted");
308 SCVAL(outbuf,0,0x82);
309 SCVAL(outbuf,3,0);
310 if (name_len(inbuf+4) > 50 ||
311 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
312 DEBUG(0,("Invalid name length in session request\n"));
313 return(0);
315 name_extract(inbuf,4,name1);
316 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
317 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
318 name1,name2));
320 set_local_machine_name(name1, True);
321 set_remote_machine_name(name2, True);
323 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
324 get_local_machine_name(), get_remote_machine_name(),
325 name_type));
327 if (name_type == 'R') {
328 /* We are being asked for a pathworks session ---
329 no thanks! */
330 SCVAL(outbuf, 0,0x83);
331 break;
334 /* only add the client's machine name to the list
335 of possibly valid usernames if we are operating
336 in share mode security */
337 if (lp_security() == SEC_SHARE) {
338 add_session_user(get_remote_machine_name());
341 reload_services(True);
342 reopen_logs();
344 already_got_session = True;
345 break;
347 case 0x89: /* session keepalive request
348 (some old clients produce this?) */
349 SCVAL(outbuf,0,SMBkeepalive);
350 SCVAL(outbuf,3,0);
351 break;
353 case 0x82: /* positive session response */
354 case 0x83: /* negative session response */
355 case 0x84: /* retarget session response */
356 DEBUG(0,("Unexpected session response\n"));
357 break;
359 case SMBkeepalive: /* session keepalive */
360 default:
361 return(0);
364 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
365 msg_type, msg_flags));
367 return(outsize);
370 /****************************************************************************
371 Reply to a tcon.
372 conn POINTER CAN BE NULL HERE !
373 ****************************************************************************/
375 int reply_tcon(connection_struct *conn,
376 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
378 const char *service;
379 pstring service_buf;
380 pstring password;
381 pstring dev;
382 int outsize = 0;
383 uint16 vuid = SVAL(inbuf,smb_uid);
384 int pwlen=0;
385 NTSTATUS nt_status;
386 char *p;
387 DATA_BLOB password_blob;
389 START_PROFILE(SMBtcon);
391 *service_buf = *password = *dev = 0;
393 p = smb_buf(inbuf)+1;
394 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
395 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
396 p += pwlen;
397 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
399 p = strrchr_m(service_buf,'\\');
400 if (p) {
401 service = p+1;
402 } else {
403 service = service_buf;
406 password_blob = data_blob(password, pwlen+1);
408 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
410 data_blob_clear_free(&password_blob);
412 if (!conn) {
413 END_PROFILE(SMBtcon);
414 return ERROR_NT(nt_status);
417 outsize = set_message(inbuf,outbuf,2,0,True);
418 SSVAL(outbuf,smb_vwv0,max_recv);
419 SSVAL(outbuf,smb_vwv1,conn->cnum);
420 SSVAL(outbuf,smb_tid,conn->cnum);
422 DEBUG(3,("tcon service=%s cnum=%d\n",
423 service, conn->cnum));
425 END_PROFILE(SMBtcon);
426 return(outsize);
429 /****************************************************************************
430 Reply to a tcon and X.
431 conn POINTER CAN BE NULL HERE !
432 ****************************************************************************/
434 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
436 fstring service;
437 DATA_BLOB password;
439 /* what the cleint thinks the device is */
440 fstring client_devicetype;
441 /* what the server tells the client the share represents */
442 const char *server_devicetype;
443 NTSTATUS nt_status;
444 uint16 vuid = SVAL(inbuf,smb_uid);
445 int passlen = SVAL(inbuf,smb_vwv3);
446 pstring path;
447 char *p, *q;
448 uint16 tcon_flags = SVAL(inbuf,smb_vwv2);
450 START_PROFILE(SMBtconX);
452 *service = *client_devicetype = 0;
454 /* we might have to close an old one */
455 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
456 close_cnum(conn,vuid);
459 if (passlen > MAX_PASS_LEN) {
460 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
463 if (global_encrypted_passwords_negotiated) {
464 password = data_blob(smb_buf(inbuf),passlen);
465 if (lp_security() == SEC_SHARE) {
467 * Security = share always has a pad byte
468 * after the password.
470 p = smb_buf(inbuf) + passlen + 1;
471 } else {
472 p = smb_buf(inbuf) + passlen;
474 } else {
475 password = data_blob(smb_buf(inbuf),passlen+1);
476 /* Ensure correct termination */
477 password.data[passlen]=0;
478 p = smb_buf(inbuf) + passlen + 1;
481 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
484 * the service name can be either: \\server\share
485 * or share directly like on the DELL PowerVault 705
487 if (*path=='\\') {
488 q = strchr_m(path+2,'\\');
489 if (!q) {
490 END_PROFILE(SMBtconX);
491 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
493 fstrcpy(service,q+1);
495 else
496 fstrcpy(service,path);
498 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
500 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
502 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
504 data_blob_clear_free(&password);
506 if (!conn) {
507 END_PROFILE(SMBtconX);
508 return ERROR_NT(nt_status);
511 if ( IS_IPC(conn) )
512 server_devicetype = "IPC";
513 else if ( IS_PRINT(conn) )
514 server_devicetype = "LPT1:";
515 else
516 server_devicetype = "A:";
518 if (Protocol < PROTOCOL_NT1) {
519 set_message(inbuf,outbuf,2,0,True);
520 p = smb_buf(outbuf);
521 p += srvstr_push(outbuf, p, server_devicetype, -1,
522 STR_TERMINATE|STR_ASCII);
523 set_message_end(inbuf,outbuf,p);
524 } else {
525 /* NT sets the fstype of IPC$ to the null string */
526 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
528 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
529 /* Return permissions. */
530 uint32 perm1 = 0;
531 uint32 perm2 = 0;
533 set_message(inbuf,outbuf,7,0,True);
535 if (IS_IPC(conn)) {
536 perm1 = FILE_ALL_ACCESS;
537 perm2 = FILE_ALL_ACCESS;
538 } else {
539 perm1 = CAN_WRITE(conn) ?
540 SHARE_ALL_ACCESS :
541 SHARE_READ_ONLY;
544 SIVAL(outbuf, smb_vwv3, perm1);
545 SIVAL(outbuf, smb_vwv5, perm2);
546 } else {
547 set_message(inbuf,outbuf,3,0,True);
550 p = smb_buf(outbuf);
551 p += srvstr_push(outbuf, p, server_devicetype, -1,
552 STR_TERMINATE|STR_ASCII);
553 p += srvstr_push(outbuf, p, fstype, -1,
554 STR_TERMINATE);
556 set_message_end(inbuf,outbuf,p);
558 /* what does setting this bit do? It is set by NT4 and
559 may affect the ability to autorun mounted cdroms */
560 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
561 (lp_csc_policy(SNUM(conn)) << 2));
563 init_dfsroot(conn, inbuf, outbuf);
567 DEBUG(3,("tconX service=%s \n",
568 service));
570 /* set the incoming and outgoing tid to the just created one */
571 SSVAL(inbuf,smb_tid,conn->cnum);
572 SSVAL(outbuf,smb_tid,conn->cnum);
574 END_PROFILE(SMBtconX);
575 return chain_reply(inbuf,outbuf,length,bufsize);
578 /****************************************************************************
579 Reply to an unknown type.
580 ****************************************************************************/
582 int reply_unknown(char *inbuf,char *outbuf)
584 int type;
585 type = CVAL(inbuf,smb_com);
587 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
588 smb_fn_name(type), type, type));
590 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
593 /****************************************************************************
594 Reply to an ioctl.
595 conn POINTER CAN BE NULL HERE !
596 ****************************************************************************/
598 int reply_ioctl(connection_struct *conn,
599 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
601 uint16 device = SVAL(inbuf,smb_vwv1);
602 uint16 function = SVAL(inbuf,smb_vwv2);
603 uint32 ioctl_code = (device << 16) + function;
604 int replysize, outsize;
605 char *p;
606 START_PROFILE(SMBioctl);
608 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
610 switch (ioctl_code) {
611 case IOCTL_QUERY_JOB_INFO:
612 replysize = 32;
613 break;
614 default:
615 END_PROFILE(SMBioctl);
616 return(ERROR_DOS(ERRSRV,ERRnosupport));
619 outsize = set_message(inbuf,outbuf,8,replysize+1,True);
620 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
621 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
622 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
623 p = smb_buf(outbuf) + 1; /* Allow for alignment */
625 switch (ioctl_code) {
626 case IOCTL_QUERY_JOB_INFO:
628 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
629 if (!fsp) {
630 END_PROFILE(SMBioctl);
631 return(UNIXERROR(ERRDOS,ERRbadfid));
633 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
634 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
635 if (conn) {
636 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
638 break;
642 END_PROFILE(SMBioctl);
643 return outsize;
646 /****************************************************************************
647 Strange checkpath NTSTATUS mapping.
648 ****************************************************************************/
650 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
652 /* Strange DOS error code semantics only for checkpath... */
653 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
654 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
655 /* We need to map to ERRbadpath */
656 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
659 return status;
662 /****************************************************************************
663 Reply to a checkpath.
664 ****************************************************************************/
666 int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
668 int outsize = 0;
669 pstring name;
670 SMB_STRUCT_STAT sbuf;
671 NTSTATUS status;
673 START_PROFILE(SMBcheckpath);
675 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
676 if (!NT_STATUS_IS_OK(status)) {
677 END_PROFILE(SMBcheckpath);
678 status = map_checkpath_error(inbuf, status);
679 return ERROR_NT(status);
682 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name);
683 if (!NT_STATUS_IS_OK(status)) {
684 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
685 END_PROFILE(SMBcheckpath);
686 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
688 goto path_err;
691 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
693 status = unix_convert(conn, name, False, NULL, &sbuf);
694 if (!NT_STATUS_IS_OK(status)) {
695 goto path_err;
698 status = check_name(conn, name);
699 if (!NT_STATUS_IS_OK(status)) {
700 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
701 goto path_err;
704 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
705 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
706 status = map_nt_error_from_unix(errno);
707 goto path_err;
710 if (!S_ISDIR(sbuf.st_mode)) {
711 END_PROFILE(SMBcheckpath);
712 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
715 outsize = set_message(inbuf,outbuf,0,0,False);
717 END_PROFILE(SMBcheckpath);
718 return outsize;
720 path_err:
722 END_PROFILE(SMBcheckpath);
724 /* We special case this - as when a Windows machine
725 is parsing a path is steps through the components
726 one at a time - if a component fails it expects
727 ERRbadpath, not ERRbadfile.
729 status = map_checkpath_error(inbuf, status);
730 if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
732 * Windows returns different error codes if
733 * the parent directory is valid but not the
734 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
735 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
736 * if the path is invalid.
738 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
741 return ERROR_NT(status);
744 /****************************************************************************
745 Reply to a getatr.
746 ****************************************************************************/
748 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
750 pstring fname;
751 int outsize = 0;
752 SMB_STRUCT_STAT sbuf;
753 int mode=0;
754 SMB_OFF_T size=0;
755 time_t mtime=0;
756 char *p;
757 NTSTATUS status;
759 START_PROFILE(SMBgetatr);
761 p = smb_buf(inbuf) + 1;
762 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
763 if (!NT_STATUS_IS_OK(status)) {
764 END_PROFILE(SMBgetatr);
765 return ERROR_NT(status);
768 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
769 if (!NT_STATUS_IS_OK(status)) {
770 END_PROFILE(SMBgetatr);
771 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
772 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
774 return ERROR_NT(status);
777 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
778 under WfWg - weird! */
779 if (*fname == '\0') {
780 mode = aHIDDEN | aDIR;
781 if (!CAN_WRITE(conn)) {
782 mode |= aRONLY;
784 size = 0;
785 mtime = 0;
786 } else {
787 status = unix_convert(conn, fname, False, NULL,&sbuf);
788 if (!NT_STATUS_IS_OK(status)) {
789 END_PROFILE(SMBgetatr);
790 return ERROR_NT(status);
792 status = check_name(conn, fname);
793 if (!NT_STATUS_IS_OK(status)) {
794 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
795 END_PROFILE(SMBgetatr);
796 return ERROR_NT(status);
798 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
799 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
800 return UNIXERROR(ERRDOS,ERRbadfile);
803 mode = dos_mode(conn,fname,&sbuf);
804 size = sbuf.st_size;
805 mtime = sbuf.st_mtime;
806 if (mode & aDIR) {
807 size = 0;
811 outsize = set_message(inbuf,outbuf,10,0,True);
813 SSVAL(outbuf,smb_vwv0,mode);
814 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
815 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
816 } else {
817 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
819 SIVAL(outbuf,smb_vwv3,(uint32)size);
821 if (Protocol >= PROTOCOL_NT1) {
822 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
825 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
827 END_PROFILE(SMBgetatr);
828 return(outsize);
831 /****************************************************************************
832 Reply to a setatr.
833 ****************************************************************************/
835 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
837 pstring fname;
838 int outsize = 0;
839 int mode;
840 time_t mtime;
841 SMB_STRUCT_STAT sbuf;
842 char *p;
843 NTSTATUS status;
845 START_PROFILE(SMBsetatr);
847 p = smb_buf(inbuf) + 1;
848 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
849 if (!NT_STATUS_IS_OK(status)) {
850 END_PROFILE(SMBsetatr);
851 return ERROR_NT(status);
854 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
855 if (!NT_STATUS_IS_OK(status)) {
856 END_PROFILE(SMBsetatr);
857 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
858 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
860 return ERROR_NT(status);
863 status = unix_convert(conn, fname, False, NULL, &sbuf);
864 if (!NT_STATUS_IS_OK(status)) {
865 END_PROFILE(SMBsetatr);
866 return ERROR_NT(status);
869 status = check_name(conn, fname);
870 if (!NT_STATUS_IS_OK(status)) {
871 END_PROFILE(SMBsetatr);
872 return ERROR_NT(status);
875 if (fname[0] == '.' && fname[1] == '\0') {
877 * Not sure here is the right place to catch this
878 * condition. Might be moved to somewhere else later -- vl
880 END_PROFILE(SMBsetatr);
881 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
884 mode = SVAL(inbuf,smb_vwv0);
885 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
887 if (mode != FILE_ATTRIBUTE_NORMAL) {
888 if (VALID_STAT_OF_DIR(sbuf))
889 mode |= aDIR;
890 else
891 mode &= ~aDIR;
893 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
894 END_PROFILE(SMBsetatr);
895 return UNIXERROR(ERRDOS, ERRnoaccess);
899 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
900 END_PROFILE(SMBsetatr);
901 return UNIXERROR(ERRDOS, ERRnoaccess);
904 outsize = set_message(inbuf,outbuf,0,0,False);
906 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
908 END_PROFILE(SMBsetatr);
909 return(outsize);
912 /****************************************************************************
913 Reply to a dskattr.
914 ****************************************************************************/
916 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
918 int outsize = 0;
919 SMB_BIG_UINT dfree,dsize,bsize;
920 START_PROFILE(SMBdskattr);
922 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
923 END_PROFILE(SMBdskattr);
924 return(UNIXERROR(ERRHRD,ERRgeneral));
927 outsize = set_message(inbuf,outbuf,5,0,True);
929 if (Protocol <= PROTOCOL_LANMAN2) {
930 double total_space, free_space;
931 /* we need to scale this to a number that DOS6 can handle. We
932 use floating point so we can handle large drives on systems
933 that don't have 64 bit integers
935 we end up displaying a maximum of 2G to DOS systems
937 total_space = dsize * (double)bsize;
938 free_space = dfree * (double)bsize;
940 dsize = (total_space+63*512) / (64*512);
941 dfree = (free_space+63*512) / (64*512);
943 if (dsize > 0xFFFF) dsize = 0xFFFF;
944 if (dfree > 0xFFFF) dfree = 0xFFFF;
946 SSVAL(outbuf,smb_vwv0,dsize);
947 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
948 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
949 SSVAL(outbuf,smb_vwv3,dfree);
950 } else {
951 SSVAL(outbuf,smb_vwv0,dsize);
952 SSVAL(outbuf,smb_vwv1,bsize/512);
953 SSVAL(outbuf,smb_vwv2,512);
954 SSVAL(outbuf,smb_vwv3,dfree);
957 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
959 END_PROFILE(SMBdskattr);
960 return(outsize);
963 /****************************************************************************
964 Reply to a search.
965 Can be called from SMBsearch, SMBffirst or SMBfunique.
966 ****************************************************************************/
968 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
970 pstring mask;
971 pstring directory;
972 pstring fname;
973 SMB_OFF_T size;
974 uint32 mode;
975 time_t date;
976 uint32 dirtype;
977 int outsize = 0;
978 unsigned int numentries = 0;
979 unsigned int maxentries = 0;
980 BOOL finished = False;
981 char *p;
982 int status_len;
983 pstring path;
984 char status[21];
985 int dptr_num= -1;
986 BOOL check_descend = False;
987 BOOL expect_close = False;
988 NTSTATUS nt_status;
989 BOOL mask_contains_wcard = False;
990 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
992 START_PROFILE(SMBsearch);
994 if (lp_posix_pathnames()) {
995 END_PROFILE(SMBsearch);
996 return reply_unknown(inbuf, outbuf);
999 *mask = *directory = *fname = 0;
1001 /* If we were called as SMBffirst then we must expect close. */
1002 if(CVAL(inbuf,smb_com) == SMBffirst) {
1003 expect_close = True;
1006 outsize = set_message(inbuf,outbuf,1,3,True);
1007 maxentries = SVAL(inbuf,smb_vwv0);
1008 dirtype = SVAL(inbuf,smb_vwv1);
1009 p = smb_buf(inbuf) + 1;
1010 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
1011 if (!NT_STATUS_IS_OK(nt_status)) {
1012 END_PROFILE(SMBsearch);
1013 return ERROR_NT(nt_status);
1016 nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
1017 if (!NT_STATUS_IS_OK(nt_status)) {
1018 END_PROFILE(SMBsearch);
1019 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1020 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1022 return ERROR_NT(nt_status);
1025 p++;
1026 status_len = SVAL(p, 0);
1027 p += 2;
1029 /* dirtype &= ~aDIR; */
1031 if (status_len == 0) {
1032 SMB_STRUCT_STAT sbuf;
1034 pstrcpy(directory,path);
1035 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1036 if (!NT_STATUS_IS_OK(nt_status)) {
1037 END_PROFILE(SMBsearch);
1038 return ERROR_NT(nt_status);
1041 nt_status = check_name(conn, directory);
1042 if (!NT_STATUS_IS_OK(nt_status)) {
1043 END_PROFILE(SMBsearch);
1044 return ERROR_NT(nt_status);
1047 p = strrchr_m(directory,'/');
1048 if (!p) {
1049 pstrcpy(mask,directory);
1050 pstrcpy(directory,".");
1051 } else {
1052 *p = 0;
1053 pstrcpy(mask,p+1);
1056 if (*directory == '\0') {
1057 pstrcpy(directory,".");
1059 memset((char *)status,'\0',21);
1060 SCVAL(status,0,(dirtype & 0x1F));
1061 } else {
1062 int status_dirtype;
1064 memcpy(status,p,21);
1065 status_dirtype = CVAL(status,0) & 0x1F;
1066 if (status_dirtype != (dirtype & 0x1F)) {
1067 dirtype = status_dirtype;
1070 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1071 if (!conn->dirptr) {
1072 goto SearchEmpty;
1074 string_set(&conn->dirpath,dptr_path(dptr_num));
1075 pstrcpy(mask, dptr_wcard(dptr_num));
1077 * For a 'continue' search we have no string. So
1078 * check from the initial saved string.
1080 mask_contains_wcard = ms_has_wild(mask);
1083 p = smb_buf(outbuf) + 3;
1085 if (status_len == 0) {
1086 nt_status = dptr_create(conn,
1087 directory,
1088 True,
1089 expect_close,
1090 SVAL(inbuf,smb_pid),
1091 mask,
1092 mask_contains_wcard,
1093 dirtype,
1094 &conn->dirptr);
1095 if (!NT_STATUS_IS_OK(nt_status)) {
1096 return ERROR_NT(nt_status);
1098 dptr_num = dptr_dnum(conn->dirptr);
1099 } else {
1100 dirtype = dptr_attr(dptr_num);
1103 DEBUG(4,("dptr_num is %d\n",dptr_num));
1105 if ((dirtype&0x1F) == aVOLID) {
1106 memcpy(p,status,21);
1107 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1108 0,aVOLID,0,!allow_long_path_components);
1109 dptr_fill(p+12,dptr_num);
1110 if (dptr_zero(p+12) && (status_len==0)) {
1111 numentries = 1;
1112 } else {
1113 numentries = 0;
1115 p += DIR_STRUCT_SIZE;
1116 } else {
1117 unsigned int i;
1118 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1120 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1121 conn->dirpath,lp_dontdescend(SNUM(conn))));
1122 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1123 check_descend = True;
1126 for (i=numentries;(i<maxentries) && !finished;i++) {
1127 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1128 if (!finished) {
1129 memcpy(p,status,21);
1130 make_dir_struct(p,mask,fname,size, mode,date,
1131 !allow_long_path_components);
1132 if (!dptr_fill(p+12,dptr_num)) {
1133 break;
1135 numentries++;
1136 p += DIR_STRUCT_SIZE;
1141 SearchEmpty:
1143 /* If we were called as SMBffirst with smb_search_id == NULL
1144 and no entries were found then return error and close dirptr
1145 (X/Open spec) */
1147 if (numentries == 0) {
1148 dptr_close(&dptr_num);
1149 } else if(expect_close && status_len == 0) {
1150 /* Close the dptr - we know it's gone */
1151 dptr_close(&dptr_num);
1154 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1155 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1156 dptr_close(&dptr_num);
1159 if ((numentries == 0) && !mask_contains_wcard) {
1160 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1163 SSVAL(outbuf,smb_vwv0,numentries);
1164 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1165 SCVAL(smb_buf(outbuf),0,5);
1166 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1168 /* The replies here are never long name. */
1169 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1170 if (!allow_long_path_components) {
1171 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1174 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1175 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1177 outsize += DIR_STRUCT_SIZE*numentries;
1178 smb_setlen(inbuf,outbuf,outsize - 4);
1180 if ((! *directory) && dptr_path(dptr_num))
1181 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1183 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1184 smb_fn_name(CVAL(inbuf,smb_com)),
1185 mask, directory, dirtype, numentries, maxentries ) );
1187 END_PROFILE(SMBsearch);
1188 return(outsize);
1191 /****************************************************************************
1192 Reply to a fclose (stop directory search).
1193 ****************************************************************************/
1195 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1197 int outsize = 0;
1198 int status_len;
1199 pstring path;
1200 char status[21];
1201 int dptr_num= -2;
1202 char *p;
1203 NTSTATUS err;
1204 BOOL path_contains_wcard = False;
1206 START_PROFILE(SMBfclose);
1208 if (lp_posix_pathnames()) {
1209 END_PROFILE(SMBfclose);
1210 return reply_unknown(inbuf, outbuf);
1213 outsize = set_message(inbuf,outbuf,1,0,True);
1214 p = smb_buf(inbuf) + 1;
1215 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1216 if (!NT_STATUS_IS_OK(err)) {
1217 END_PROFILE(SMBfclose);
1218 return ERROR_NT(err);
1220 p++;
1221 status_len = SVAL(p,0);
1222 p += 2;
1224 if (status_len == 0) {
1225 END_PROFILE(SMBfclose);
1226 return ERROR_DOS(ERRSRV,ERRsrverror);
1229 memcpy(status,p,21);
1231 if(dptr_fetch(status+12,&dptr_num)) {
1232 /* Close the dptr - we know it's gone */
1233 dptr_close(&dptr_num);
1236 SSVAL(outbuf,smb_vwv0,0);
1238 DEBUG(3,("search close\n"));
1240 END_PROFILE(SMBfclose);
1241 return(outsize);
1244 /****************************************************************************
1245 Reply to an open.
1246 ****************************************************************************/
1248 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1250 pstring fname;
1251 int outsize = 0;
1252 uint32 fattr=0;
1253 SMB_OFF_T size = 0;
1254 time_t mtime=0;
1255 int info;
1256 SMB_STRUCT_STAT sbuf;
1257 files_struct *fsp;
1258 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1259 int deny_mode;
1260 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1261 uint32 access_mask;
1262 uint32 share_mode;
1263 uint32 create_disposition;
1264 uint32 create_options = 0;
1265 NTSTATUS status;
1266 START_PROFILE(SMBopen);
1268 deny_mode = SVAL(inbuf,smb_vwv0);
1270 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1271 if (!NT_STATUS_IS_OK(status)) {
1272 END_PROFILE(SMBopen);
1273 return ERROR_NT(status);
1276 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1277 if (!NT_STATUS_IS_OK(status)) {
1278 END_PROFILE(SMBopen);
1279 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1280 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1282 return ERROR_NT(status);
1285 status = unix_convert(conn, fname, False, NULL, &sbuf);
1286 if (!NT_STATUS_IS_OK(status)) {
1287 END_PROFILE(SMBopen);
1288 return ERROR_NT(status);
1291 status = check_name(conn, fname);
1292 if (!NT_STATUS_IS_OK(status)) {
1293 END_PROFILE(SMBopen);
1294 return ERROR_NT(status);
1297 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1298 &access_mask, &share_mode, &create_disposition, &create_options)) {
1299 END_PROFILE(SMBopen);
1300 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1303 status = open_file_ntcreate(conn,fname,&sbuf,
1304 access_mask,
1305 share_mode,
1306 create_disposition,
1307 create_options,
1308 dos_attr,
1309 oplock_request,
1310 &info, &fsp);
1312 if (!NT_STATUS_IS_OK(status)) {
1313 END_PROFILE(SMBopen);
1314 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1315 /* We have re-scheduled this call. */
1316 return -1;
1318 return ERROR_NT(status);
1321 size = sbuf.st_size;
1322 fattr = dos_mode(conn,fname,&sbuf);
1323 mtime = sbuf.st_mtime;
1325 if (fattr & aDIR) {
1326 DEBUG(3,("attempt to open a directory %s\n",fname));
1327 close_file(fsp,ERROR_CLOSE);
1328 END_PROFILE(SMBopen);
1329 return ERROR_DOS(ERRDOS,ERRnoaccess);
1332 outsize = set_message(inbuf,outbuf,7,0,True);
1333 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1334 SSVAL(outbuf,smb_vwv1,fattr);
1335 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1336 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1337 } else {
1338 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1340 SIVAL(outbuf,smb_vwv4,(uint32)size);
1341 SSVAL(outbuf,smb_vwv6,deny_mode);
1343 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1344 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1347 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1348 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1350 END_PROFILE(SMBopen);
1351 return(outsize);
1354 /****************************************************************************
1355 Reply to an open and X.
1356 ****************************************************************************/
1358 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1360 pstring fname;
1361 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1362 int deny_mode = SVAL(inbuf,smb_vwv3);
1363 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1364 /* Breakout the oplock request bits so we can set the
1365 reply bits separately. */
1366 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1367 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1368 int oplock_request = ex_oplock_request | core_oplock_request;
1369 #if 0
1370 int smb_sattr = SVAL(inbuf,smb_vwv4);
1371 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1372 #endif
1373 int smb_ofun = SVAL(inbuf,smb_vwv8);
1374 uint32 fattr=0;
1375 int mtime=0;
1376 SMB_STRUCT_STAT sbuf;
1377 int smb_action = 0;
1378 files_struct *fsp;
1379 NTSTATUS status;
1380 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1381 ssize_t retval = -1;
1382 uint32 access_mask;
1383 uint32 share_mode;
1384 uint32 create_disposition;
1385 uint32 create_options = 0;
1387 START_PROFILE(SMBopenX);
1389 /* If it's an IPC, pass off the pipe handler. */
1390 if (IS_IPC(conn)) {
1391 if (lp_nt_pipe_support()) {
1392 END_PROFILE(SMBopenX);
1393 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1394 } else {
1395 END_PROFILE(SMBopenX);
1396 return ERROR_DOS(ERRSRV,ERRaccess);
1400 /* XXXX we need to handle passed times, sattr and flags */
1401 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1402 if (!NT_STATUS_IS_OK(status)) {
1403 END_PROFILE(SMBopenX);
1404 return ERROR_NT(status);
1407 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1408 if (!NT_STATUS_IS_OK(status)) {
1409 END_PROFILE(SMBopenX);
1410 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1411 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1413 return ERROR_NT(status);
1416 status = unix_convert(conn, fname, False, NULL, &sbuf);
1417 if (!NT_STATUS_IS_OK(status)) {
1418 END_PROFILE(SMBopenX);
1419 return ERROR_NT(status);
1422 status = check_name(conn, fname);
1423 if (!NT_STATUS_IS_OK(status)) {
1424 END_PROFILE(SMBopenX);
1425 return ERROR_NT(status);
1428 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1429 &access_mask,
1430 &share_mode,
1431 &create_disposition,
1432 &create_options)) {
1433 END_PROFILE(SMBopenX);
1434 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1437 status = open_file_ntcreate(conn,fname,&sbuf,
1438 access_mask,
1439 share_mode,
1440 create_disposition,
1441 create_options,
1442 smb_attr,
1443 oplock_request,
1444 &smb_action, &fsp);
1446 if (!NT_STATUS_IS_OK(status)) {
1447 END_PROFILE(SMBopenX);
1448 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1449 /* We have re-scheduled this call. */
1450 return -1;
1452 return ERROR_NT(status);
1455 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1456 if the file is truncated or created. */
1457 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1458 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1459 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1460 close_file(fsp,ERROR_CLOSE);
1461 END_PROFILE(SMBopenX);
1462 return ERROR_NT(NT_STATUS_DISK_FULL);
1464 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1465 if (retval < 0) {
1466 close_file(fsp,ERROR_CLOSE);
1467 END_PROFILE(SMBopenX);
1468 return ERROR_NT(NT_STATUS_DISK_FULL);
1470 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1473 fattr = dos_mode(conn,fname,&sbuf);
1474 mtime = sbuf.st_mtime;
1475 if (fattr & aDIR) {
1476 close_file(fsp,ERROR_CLOSE);
1477 END_PROFILE(SMBopenX);
1478 return ERROR_DOS(ERRDOS,ERRnoaccess);
1481 /* If the caller set the extended oplock request bit
1482 and we granted one (by whatever means) - set the
1483 correct bit for extended oplock reply.
1486 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1487 smb_action |= EXTENDED_OPLOCK_GRANTED;
1490 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1491 smb_action |= EXTENDED_OPLOCK_GRANTED;
1494 /* If the caller set the core oplock request bit
1495 and we granted one (by whatever means) - set the
1496 correct bit for core oplock reply.
1499 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1500 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1503 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1504 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1507 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1508 set_message(inbuf,outbuf,19,0,True);
1509 } else {
1510 set_message(inbuf,outbuf,15,0,True);
1512 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1513 SSVAL(outbuf,smb_vwv3,fattr);
1514 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1515 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1516 } else {
1517 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1519 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1520 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1521 SSVAL(outbuf,smb_vwv11,smb_action);
1523 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1524 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1527 END_PROFILE(SMBopenX);
1528 return chain_reply(inbuf,outbuf,length,bufsize);
1531 /****************************************************************************
1532 Reply to a SMBulogoffX.
1533 conn POINTER CAN BE NULL HERE !
1534 ****************************************************************************/
1536 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1538 uint16 vuid = SVAL(inbuf,smb_uid);
1539 user_struct *vuser = get_valid_user_struct(vuid);
1540 START_PROFILE(SMBulogoffX);
1542 if(vuser == 0)
1543 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1545 /* in user level security we are supposed to close any files
1546 open by this user */
1547 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1548 file_close_user(vuid);
1550 invalidate_vuid(vuid);
1552 set_message(inbuf,outbuf,2,0,True);
1554 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1556 END_PROFILE(SMBulogoffX);
1557 return chain_reply(inbuf,outbuf,length,bufsize);
1560 /****************************************************************************
1561 Reply to a mknew or a create.
1562 ****************************************************************************/
1564 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1566 pstring fname;
1567 int com;
1568 int outsize = 0;
1569 uint32 fattr = SVAL(inbuf,smb_vwv0);
1570 struct timespec ts[2];
1571 files_struct *fsp;
1572 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1573 SMB_STRUCT_STAT sbuf;
1574 NTSTATUS status;
1575 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1576 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1577 uint32 create_disposition;
1578 uint32 create_options = 0;
1580 START_PROFILE(SMBcreate);
1582 com = SVAL(inbuf,smb_com);
1584 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1586 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1587 if (!NT_STATUS_IS_OK(status)) {
1588 END_PROFILE(SMBcreate);
1589 return ERROR_NT(status);
1592 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1593 if (!NT_STATUS_IS_OK(status)) {
1594 END_PROFILE(SMBcreate);
1595 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1596 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1598 return ERROR_NT(status);
1601 status = unix_convert(conn, fname, False, NULL, &sbuf);
1602 if (!NT_STATUS_IS_OK(status)) {
1603 END_PROFILE(SMBcreate);
1604 return ERROR_NT(status);
1607 status = check_name(conn, fname);
1608 if (!NT_STATUS_IS_OK(status)) {
1609 END_PROFILE(SMBcreate);
1610 return ERROR_NT(status);
1613 if (fattr & aVOLID) {
1614 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1617 if(com == SMBmknew) {
1618 /* We should fail if file exists. */
1619 create_disposition = FILE_CREATE;
1620 } else {
1621 /* Create if file doesn't exist, truncate if it does. */
1622 create_disposition = FILE_OVERWRITE_IF;
1625 /* Open file using ntcreate. */
1626 status = open_file_ntcreate(conn,fname,&sbuf,
1627 access_mask,
1628 share_mode,
1629 create_disposition,
1630 create_options,
1631 fattr,
1632 oplock_request,
1633 NULL, &fsp);
1635 if (!NT_STATUS_IS_OK(status)) {
1636 END_PROFILE(SMBcreate);
1637 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1638 /* We have re-scheduled this call. */
1639 return -1;
1641 return ERROR_NT(status);
1644 ts[0] = get_atimespec(&sbuf); /* atime. */
1645 file_ntimes(conn, fname, ts);
1647 outsize = set_message(inbuf,outbuf,1,0,True);
1648 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1650 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1651 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1654 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1655 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1658 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1659 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1661 END_PROFILE(SMBcreate);
1662 return(outsize);
1665 /****************************************************************************
1666 Reply to a create temporary file.
1667 ****************************************************************************/
1669 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1671 pstring fname;
1672 int outsize = 0;
1673 uint32 fattr = SVAL(inbuf,smb_vwv0);
1674 files_struct *fsp;
1675 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1676 int tmpfd;
1677 SMB_STRUCT_STAT sbuf;
1678 char *p, *s;
1679 NTSTATUS status;
1680 unsigned int namelen;
1682 START_PROFILE(SMBctemp);
1684 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1685 if (!NT_STATUS_IS_OK(status)) {
1686 END_PROFILE(SMBctemp);
1687 return ERROR_NT(status);
1689 if (*fname) {
1690 pstrcat(fname,"/TMXXXXXX");
1691 } else {
1692 pstrcat(fname,"TMXXXXXX");
1695 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1696 if (!NT_STATUS_IS_OK(status)) {
1697 END_PROFILE(SMBctemp);
1698 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1699 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1701 return ERROR_NT(status);
1704 status = unix_convert(conn, fname, False, NULL, &sbuf);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 END_PROFILE(SMBctemp);
1707 return ERROR_NT(status);
1710 status = check_name(conn, fname);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 END_PROFILE(SMBctemp);
1713 return ERROR_NT(status);
1716 tmpfd = smb_mkstemp(fname);
1717 if (tmpfd == -1) {
1718 END_PROFILE(SMBctemp);
1719 return(UNIXERROR(ERRDOS,ERRnoaccess));
1722 SMB_VFS_STAT(conn,fname,&sbuf);
1724 /* We should fail if file does not exist. */
1725 status = open_file_ntcreate(conn,fname,&sbuf,
1726 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1727 FILE_SHARE_READ|FILE_SHARE_WRITE,
1728 FILE_OPEN,
1730 fattr,
1731 oplock_request,
1732 NULL, &fsp);
1734 /* close fd from smb_mkstemp() */
1735 close(tmpfd);
1737 if (!NT_STATUS_IS_OK(status)) {
1738 END_PROFILE(SMBctemp);
1739 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1740 /* We have re-scheduled this call. */
1741 return -1;
1743 return ERROR_NT(status);
1746 outsize = set_message(inbuf,outbuf,1,0,True);
1747 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1749 /* the returned filename is relative to the directory */
1750 s = strrchr_m(fname, '/');
1751 if (!s) {
1752 s = fname;
1753 } else {
1754 s++;
1757 p = smb_buf(outbuf);
1758 #if 0
1759 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1760 thing in the byte section. JRA */
1761 SSVALS(p, 0, -1); /* what is this? not in spec */
1762 #endif
1763 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1764 p += namelen;
1765 outsize = set_message_end(inbuf,outbuf, p);
1767 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1768 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1771 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1772 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1775 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1776 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1777 (unsigned int)sbuf.st_mode ) );
1779 END_PROFILE(SMBctemp);
1780 return(outsize);
1783 /*******************************************************************
1784 Check if a user is allowed to rename a file.
1785 ********************************************************************/
1787 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
1788 uint16 dirtype, SMB_STRUCT_STAT *pst)
1790 uint32 fmode;
1792 if (!CAN_WRITE(conn)) {
1793 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1796 fmode = dos_mode(conn, fsp->fsp_name, pst);
1797 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1798 return NT_STATUS_NO_SUCH_FILE;
1801 if (S_ISDIR(pst->st_mode)) {
1802 return NT_STATUS_OK;
1805 if (fsp->access_mask & DELETE_ACCESS) {
1806 return NT_STATUS_OK;
1809 return NT_STATUS_ACCESS_DENIED;
1812 /*******************************************************************
1813 * unlink a file with all relevant access checks
1814 *******************************************************************/
1816 static NTSTATUS do_unlink(connection_struct *conn, char *fname,
1817 uint32 dirtype, BOOL can_defer)
1819 SMB_STRUCT_STAT sbuf;
1820 uint32 fattr;
1821 files_struct *fsp;
1822 uint32 dirtype_orig = dirtype;
1823 NTSTATUS status;
1825 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
1827 if (!CAN_WRITE(conn)) {
1828 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1831 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1832 return map_nt_error_from_unix(errno);
1835 fattr = dos_mode(conn,fname,&sbuf);
1837 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1838 dirtype = aDIR|aARCH|aRONLY;
1841 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1842 if (!dirtype) {
1843 return NT_STATUS_NO_SUCH_FILE;
1846 if (!dir_check_ftype(conn, fattr, dirtype)) {
1847 if (fattr & aDIR) {
1848 return NT_STATUS_FILE_IS_A_DIRECTORY;
1850 return NT_STATUS_NO_SUCH_FILE;
1853 if (dirtype_orig & 0x8000) {
1854 /* These will never be set for POSIX. */
1855 return NT_STATUS_NO_SUCH_FILE;
1858 #if 0
1859 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1860 return NT_STATUS_FILE_IS_A_DIRECTORY;
1863 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1864 return NT_STATUS_NO_SUCH_FILE;
1867 if (dirtype & 0xFF00) {
1868 /* These will never be set for POSIX. */
1869 return NT_STATUS_NO_SUCH_FILE;
1872 dirtype &= 0xFF;
1873 if (!dirtype) {
1874 return NT_STATUS_NO_SUCH_FILE;
1877 /* Can't delete a directory. */
1878 if (fattr & aDIR) {
1879 return NT_STATUS_FILE_IS_A_DIRECTORY;
1881 #endif
1883 #if 0 /* JRATEST */
1884 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1885 return NT_STATUS_OBJECT_NAME_INVALID;
1886 #endif /* JRATEST */
1888 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1890 On a Windows share, a file with read-only dosmode can be opened with
1891 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1892 fails with NT_STATUS_CANNOT_DELETE error.
1894 This semantic causes a problem that a user can not
1895 rename a file with read-only dosmode on a Samba share
1896 from a Windows command prompt (i.e. cmd.exe, but can rename
1897 from Windows Explorer).
1900 if (!lp_delete_readonly(SNUM(conn))) {
1901 if (fattr & aRONLY) {
1902 return NT_STATUS_CANNOT_DELETE;
1906 /* On open checks the open itself will check the share mode, so
1907 don't do it here as we'll get it wrong. */
1909 status = open_file_ntcreate(conn, fname, &sbuf,
1910 DELETE_ACCESS,
1911 FILE_SHARE_NONE,
1912 FILE_OPEN,
1914 FILE_ATTRIBUTE_NORMAL,
1915 can_defer ? 0 : INTERNAL_OPEN_ONLY,
1916 NULL, &fsp);
1918 if (!NT_STATUS_IS_OK(status)) {
1919 DEBUG(10, ("open_file_ntcreate failed: %s\n",
1920 nt_errstr(status)));
1921 return status;
1924 /* The set is across all open files on this dev/inode pair. */
1925 if (!set_delete_on_close(fsp, True, &current_user.ut)) {
1926 close_file(fsp, NORMAL_CLOSE);
1927 return NT_STATUS_ACCESS_DENIED;
1930 return close_file(fsp,NORMAL_CLOSE);
1933 /****************************************************************************
1934 The guts of the unlink command, split out so it may be called by the NT SMB
1935 code.
1936 ****************************************************************************/
1938 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
1939 char *name, BOOL has_wild, BOOL can_defer)
1941 pstring directory;
1942 pstring mask;
1943 char *p;
1944 int count=0;
1945 NTSTATUS status = NT_STATUS_OK;
1946 SMB_STRUCT_STAT sbuf;
1948 *directory = *mask = 0;
1950 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1951 if (!NT_STATUS_IS_OK(status)) {
1952 return status;
1955 p = strrchr_m(name,'/');
1956 if (!p) {
1957 pstrcpy(directory,".");
1958 pstrcpy(mask,name);
1959 } else {
1960 *p = 0;
1961 pstrcpy(directory,name);
1962 pstrcpy(mask,p+1);
1966 * We should only check the mangled cache
1967 * here if unix_convert failed. This means
1968 * that the path in 'mask' doesn't exist
1969 * on the file system and so we need to look
1970 * for a possible mangle. This patch from
1971 * Tine Smukavec <valentin.smukavec@hermes.si>.
1974 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
1975 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
1977 if (!has_wild) {
1978 pstrcat(directory,"/");
1979 pstrcat(directory,mask);
1980 if (dirtype == 0) {
1981 dirtype = FILE_ATTRIBUTE_NORMAL;
1984 status = check_name(conn, directory);
1985 if (!NT_STATUS_IS_OK(status)) {
1986 return status;
1989 status = do_unlink(conn,directory,dirtype,can_defer);
1990 if (!NT_STATUS_IS_OK(status)) {
1991 return status;
1994 count++;
1995 } else {
1996 struct smb_Dir *dir_hnd = NULL;
1997 long offset = 0;
1998 const char *dname;
2000 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2001 return NT_STATUS_OBJECT_NAME_INVALID;
2004 if (strequal(mask,"????????.???")) {
2005 pstrcpy(mask,"*");
2008 status = check_name(conn, directory);
2009 if (!NT_STATUS_IS_OK(status)) {
2010 return status;
2013 dir_hnd = OpenDir(conn, directory, mask, dirtype);
2014 if (dir_hnd == NULL) {
2015 return map_nt_error_from_unix(errno);
2018 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2019 the pattern matches against the long name, otherwise the short name
2020 We don't implement this yet XXXX
2023 status = NT_STATUS_NO_SUCH_FILE;
2025 while ((dname = ReadDirName(dir_hnd, &offset))) {
2026 SMB_STRUCT_STAT st;
2027 pstring fname;
2028 pstrcpy(fname,dname);
2030 if (!is_visible_file(conn, directory, dname, &st, True)) {
2031 continue;
2034 /* Quick check for "." and ".." */
2035 if (fname[0] == '.') {
2036 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2037 continue;
2041 if(!mask_match(fname, mask, conn->case_sensitive)) {
2042 continue;
2045 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2047 status = check_name(conn, fname);
2048 if (!NT_STATUS_IS_OK(status)) {
2049 CloseDir(dir_hnd);
2050 return status;
2053 status = do_unlink(conn, fname, dirtype, can_defer);
2054 if (!NT_STATUS_IS_OK(status)) {
2055 continue;
2058 count++;
2059 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
2060 fname));
2062 CloseDir(dir_hnd);
2065 if (count == 0 && NT_STATUS_IS_OK(status)) {
2066 status = map_nt_error_from_unix(errno);
2069 return status;
2072 /****************************************************************************
2073 Reply to a unlink
2074 ****************************************************************************/
2076 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2077 int dum_buffsize)
2079 int outsize = 0;
2080 pstring name;
2081 uint32 dirtype;
2082 NTSTATUS status;
2083 BOOL path_contains_wcard = False;
2085 START_PROFILE(SMBunlink);
2087 dirtype = SVAL(inbuf,smb_vwv0);
2089 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
2090 if (!NT_STATUS_IS_OK(status)) {
2091 END_PROFILE(SMBunlink);
2092 return ERROR_NT(status);
2095 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
2096 if (!NT_STATUS_IS_OK(status)) {
2097 END_PROFILE(SMBunlink);
2098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2099 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
2101 return ERROR_NT(status);
2104 DEBUG(3,("reply_unlink : %s\n",name));
2106 status = unlink_internals(conn, dirtype, name, path_contains_wcard,
2107 True);
2108 if (!NT_STATUS_IS_OK(status)) {
2109 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2110 /* We have re-scheduled this call. */
2111 return -1;
2113 return ERROR_NT(status);
2116 outsize = set_message(inbuf,outbuf,0,0,False);
2118 END_PROFILE(SMBunlink);
2119 return outsize;
2122 /****************************************************************************
2123 Fail for readbraw.
2124 ****************************************************************************/
2126 static void fail_readraw(void)
2128 pstring errstr;
2129 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2130 strerror(errno) );
2131 exit_server_cleanly(errstr);
2134 /****************************************************************************
2135 Fake (read/write) sendfile. Returns -1 on read or write fail.
2136 ****************************************************************************/
2138 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
2140 size_t tosend = nread;
2142 while (tosend > 0) {
2143 ssize_t ret;
2144 size_t cur_read;
2146 if (tosend > bufsize) {
2147 cur_read = bufsize;
2148 } else {
2149 cur_read = tosend;
2151 ret = read_file(fsp,buf,startpos,cur_read);
2152 if (ret == -1) {
2153 return -1;
2156 /* If we had a short read, fill with zeros. */
2157 if (ret < cur_read) {
2158 memset(buf, '\0', cur_read - ret);
2161 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2162 return -1;
2164 tosend -= cur_read;
2165 startpos += cur_read;
2168 return (ssize_t)nread;
2171 /****************************************************************************
2172 Use sendfile in readbraw.
2173 ****************************************************************************/
2175 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2176 ssize_t mincount, char *outbuf, int out_buffsize)
2178 ssize_t ret=0;
2180 #if defined(WITH_SENDFILE)
2182 * We can only use sendfile on a non-chained packet
2183 * but we can use on a non-oplocked file. tridge proved this
2184 * on a train in Germany :-). JRA.
2185 * reply_readbraw has already checked the length.
2188 if ( (chain_size == 0) && (nread > 0) &&
2189 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2190 DATA_BLOB header;
2192 _smb_setlen(outbuf,nread);
2193 header.data = (uint8 *)outbuf;
2194 header.length = 4;
2195 header.free = NULL;
2197 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2198 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2199 if (errno == ENOSYS) {
2200 goto normal_readbraw;
2204 * Special hack for broken Linux with no working sendfile. If we
2205 * return EINTR we sent the header but not the rest of the data.
2206 * Fake this up by doing read/write calls.
2208 if (errno == EINTR) {
2209 /* Ensure we don't do this again. */
2210 set_use_sendfile(SNUM(conn), False);
2211 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2213 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2214 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2215 fsp->fsp_name, strerror(errno) ));
2216 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2218 return;
2221 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2222 fsp->fsp_name, strerror(errno) ));
2223 exit_server_cleanly("send_file_readbraw sendfile failed");
2226 return;
2228 #endif
2230 normal_readbraw:
2232 if (nread > 0) {
2233 ret = read_file(fsp,outbuf+4,startpos,nread);
2234 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2235 if (ret < mincount)
2236 ret = 0;
2237 #else
2238 if (ret < nread)
2239 ret = 0;
2240 #endif
2243 _smb_setlen(outbuf,ret);
2244 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2245 fail_readraw();
2248 /****************************************************************************
2249 Reply to a readbraw (core+ protocol).
2250 ****************************************************************************/
2252 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2254 ssize_t maxcount,mincount;
2255 size_t nread = 0;
2256 SMB_OFF_T startpos;
2257 char *header = outbuf;
2258 files_struct *fsp;
2259 START_PROFILE(SMBreadbraw);
2261 if (srv_is_signing_active()) {
2262 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2266 * Special check if an oplock break has been issued
2267 * and the readraw request croses on the wire, we must
2268 * return a zero length response here.
2271 fsp = file_fsp(inbuf,smb_vwv0);
2273 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2275 * fsp could be NULL here so use the value from the packet. JRA.
2277 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2278 _smb_setlen(header,0);
2279 if (write_data(smbd_server_fd(),header,4) != 4)
2280 fail_readraw();
2281 END_PROFILE(SMBreadbraw);
2282 return(-1);
2285 CHECK_FSP(fsp,conn);
2287 flush_write_cache(fsp, READRAW_FLUSH);
2289 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2290 if(CVAL(inbuf,smb_wct) == 10) {
2292 * This is a large offset (64 bit) read.
2294 #ifdef LARGE_SMB_OFF_T
2296 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2298 #else /* !LARGE_SMB_OFF_T */
2301 * Ensure we haven't been sent a >32 bit offset.
2304 if(IVAL(inbuf,smb_vwv8) != 0) {
2305 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2306 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2307 _smb_setlen(header,0);
2308 if (write_data(smbd_server_fd(),header,4) != 4)
2309 fail_readraw();
2310 END_PROFILE(SMBreadbraw);
2311 return(-1);
2314 #endif /* LARGE_SMB_OFF_T */
2316 if(startpos < 0) {
2317 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2318 _smb_setlen(header,0);
2319 if (write_data(smbd_server_fd(),header,4) != 4)
2320 fail_readraw();
2321 END_PROFILE(SMBreadbraw);
2322 return(-1);
2325 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2326 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2328 /* ensure we don't overrun the packet size */
2329 maxcount = MIN(65535,maxcount);
2331 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2332 SMB_STRUCT_STAT st;
2333 SMB_OFF_T size = 0;
2335 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2336 size = st.st_size;
2339 if (startpos >= size) {
2340 nread = 0;
2341 } else {
2342 nread = MIN(maxcount,(size - startpos));
2346 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2347 if (nread < mincount)
2348 nread = 0;
2349 #endif
2351 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2352 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2354 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2356 DEBUG(5,("readbraw finished\n"));
2357 END_PROFILE(SMBreadbraw);
2358 return -1;
2361 #undef DBGC_CLASS
2362 #define DBGC_CLASS DBGC_LOCKING
2364 /****************************************************************************
2365 Reply to a lockread (core+ protocol).
2366 ****************************************************************************/
2368 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2370 ssize_t nread = -1;
2371 char *data;
2372 int outsize = 0;
2373 SMB_OFF_T startpos;
2374 size_t numtoread;
2375 NTSTATUS status;
2376 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2377 struct byte_range_lock *br_lck = NULL;
2378 START_PROFILE(SMBlockread);
2380 CHECK_FSP(fsp,conn);
2381 if (!CHECK_READ(fsp,inbuf)) {
2382 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2385 release_level_2_oplocks_on_change(fsp);
2387 numtoread = SVAL(inbuf,smb_vwv1);
2388 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2390 outsize = set_message(inbuf,outbuf,5,3,True);
2391 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2392 data = smb_buf(outbuf) + 3;
2395 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2396 * protocol request that predates the read/write lock concept.
2397 * Thus instead of asking for a read lock here we need to ask
2398 * for a write lock. JRA.
2399 * Note that the requested lock size is unaffected by max_recv.
2402 br_lck = do_lock(smbd_messaging_context(),
2403 fsp,
2404 (uint32)SVAL(inbuf,smb_pid),
2405 (SMB_BIG_UINT)numtoread,
2406 (SMB_BIG_UINT)startpos,
2407 WRITE_LOCK,
2408 WINDOWS_LOCK,
2409 False, /* Non-blocking lock. */
2410 &status,
2411 NULL);
2412 TALLOC_FREE(br_lck);
2414 if (NT_STATUS_V(status)) {
2415 END_PROFILE(SMBlockread);
2416 return ERROR_NT(status);
2420 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2423 if (numtoread > max_recv) {
2424 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2425 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2426 (unsigned int)numtoread, (unsigned int)max_recv ));
2427 numtoread = MIN(numtoread,max_recv);
2429 nread = read_file(fsp,data,startpos,numtoread);
2431 if (nread < 0) {
2432 END_PROFILE(SMBlockread);
2433 return(UNIXERROR(ERRDOS,ERRnoaccess));
2436 outsize += nread;
2437 SSVAL(outbuf,smb_vwv0,nread);
2438 SSVAL(outbuf,smb_vwv5,nread+3);
2439 SSVAL(smb_buf(outbuf),1,nread);
2441 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2442 fsp->fnum, (int)numtoread, (int)nread));
2444 END_PROFILE(SMBlockread);
2445 return(outsize);
2448 #undef DBGC_CLASS
2449 #define DBGC_CLASS DBGC_ALL
2451 /****************************************************************************
2452 Reply to a read.
2453 ****************************************************************************/
2455 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2457 size_t numtoread;
2458 ssize_t nread = 0;
2459 char *data;
2460 SMB_OFF_T startpos;
2461 int outsize = 0;
2462 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2463 START_PROFILE(SMBread);
2465 CHECK_FSP(fsp,conn);
2466 if (!CHECK_READ(fsp,inbuf)) {
2467 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2470 numtoread = SVAL(inbuf,smb_vwv1);
2471 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2473 outsize = set_message(inbuf,outbuf,5,3,True);
2474 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2476 * The requested read size cannot be greater than max_recv. JRA.
2478 if (numtoread > max_recv) {
2479 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2480 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2481 (unsigned int)numtoread, (unsigned int)max_recv ));
2482 numtoread = MIN(numtoread,max_recv);
2485 data = smb_buf(outbuf) + 3;
2487 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2488 END_PROFILE(SMBread);
2489 return ERROR_DOS(ERRDOS,ERRlock);
2492 if (numtoread > 0)
2493 nread = read_file(fsp,data,startpos,numtoread);
2495 if (nread < 0) {
2496 END_PROFILE(SMBread);
2497 return(UNIXERROR(ERRDOS,ERRnoaccess));
2500 outsize += nread;
2501 SSVAL(outbuf,smb_vwv0,nread);
2502 SSVAL(outbuf,smb_vwv5,nread+3);
2503 SCVAL(smb_buf(outbuf),0,1);
2504 SSVAL(smb_buf(outbuf),1,nread);
2506 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2507 fsp->fnum, (int)numtoread, (int)nread ) );
2509 END_PROFILE(SMBread);
2510 return(outsize);
2513 /****************************************************************************
2514 Setup readX header.
2515 ****************************************************************************/
2517 static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
2519 int outsize;
2520 char *data = smb_buf(outbuf);
2522 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2523 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2524 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2525 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
2526 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2527 SCVAL(outbuf,smb_vwv0,0xFF);
2528 outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
2529 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
2530 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
2531 return outsize;
2534 /****************************************************************************
2535 Reply to a read and X - possibly using sendfile.
2536 ****************************************************************************/
2538 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2539 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2541 SMB_STRUCT_STAT sbuf;
2542 int outsize = 0;
2543 ssize_t nread = -1;
2544 char *data = smb_buf(outbuf);
2546 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2547 return(UNIXERROR(ERRDOS,ERRnoaccess));
2550 if (startpos > sbuf.st_size) {
2551 smb_maxcnt = 0;
2554 if (smb_maxcnt > (sbuf.st_size - startpos)) {
2555 smb_maxcnt = (sbuf.st_size - startpos);
2558 if (smb_maxcnt == 0) {
2559 goto normal_read;
2562 #if defined(WITH_SENDFILE)
2564 * We can only use sendfile on a non-chained packet
2565 * but we can use on a non-oplocked file. tridge proved this
2566 * on a train in Germany :-). JRA.
2569 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2570 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2571 DATA_BLOB header;
2574 * Set up the packet header before send. We
2575 * assume here the sendfile will work (get the
2576 * correct amount of data).
2579 setup_readX_header(inbuf,outbuf,smb_maxcnt);
2580 set_message(inbuf,outbuf,12,smb_maxcnt,False);
2581 header.data = (uint8 *)outbuf;
2582 header.length = data - outbuf;
2583 header.free = NULL;
2585 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2586 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2587 if (errno == ENOSYS) {
2588 goto normal_read;
2592 * Special hack for broken Linux with no working sendfile. If we
2593 * return EINTR we sent the header but not the rest of the data.
2594 * Fake this up by doing read/write calls.
2597 if (errno == EINTR) {
2598 /* Ensure we don't do this again. */
2599 set_use_sendfile(SNUM(conn), False);
2600 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2602 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2603 len_outbuf - (data-outbuf))) == -1) {
2604 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2605 fsp->fsp_name, strerror(errno) ));
2606 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2608 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2609 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2610 /* Returning -1 here means successful sendfile. */
2611 return -1;
2614 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2615 fsp->fsp_name, strerror(errno) ));
2616 exit_server_cleanly("send_file_readX sendfile failed");
2619 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2620 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2621 /* Returning -1 here means successful sendfile. */
2622 return -1;
2625 #endif
2627 normal_read:
2629 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
2630 int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
2631 /* Send out the header. */
2632 if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
2633 DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
2634 fsp->fsp_name, strerror(errno) ));
2635 exit_server_cleanly("send_file_readX sendfile failed");
2637 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2638 len_outbuf - (data-outbuf))) == -1) {
2639 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2640 fsp->fsp_name, strerror(errno) ));
2641 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2643 return -1;
2644 } else {
2645 nread = read_file(fsp,data,startpos,smb_maxcnt);
2647 if (nread < 0) {
2648 return(UNIXERROR(ERRDOS,ERRnoaccess));
2651 outsize = setup_readX_header(inbuf, outbuf,nread);
2653 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2654 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2656 /* Returning the number of bytes we want to send back - including header. */
2657 return outsize;
2661 /****************************************************************************
2662 Reply to a read and X.
2663 ****************************************************************************/
2665 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2667 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2668 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2669 ssize_t nread = -1;
2670 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2671 BOOL big_readX = False;
2672 #if 0
2673 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2674 #endif
2676 START_PROFILE(SMBreadX);
2678 /* If it's an IPC, pass off the pipe handler. */
2679 if (IS_IPC(conn)) {
2680 END_PROFILE(SMBreadX);
2681 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2684 CHECK_FSP(fsp,conn);
2685 if (!CHECK_READ(fsp,inbuf)) {
2686 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2689 set_message(inbuf,outbuf,12,0,True);
2691 if (global_client_caps & CAP_LARGE_READX) {
2692 size_t upper_size = SVAL(inbuf,smb_vwv7);
2693 smb_maxcnt |= (upper_size<<16);
2694 if (upper_size > 1) {
2695 /* Can't do this on a chained packet. */
2696 if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
2697 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2699 /* We currently don't do this on signed or sealed data. */
2700 if (srv_is_signing_active() || srv_encryption_on()) {
2701 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
2703 /* Is there room in the reply for this data ? */
2704 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
2705 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2707 big_readX = True;
2711 if(CVAL(inbuf,smb_wct) == 12) {
2712 #ifdef LARGE_SMB_OFF_T
2714 * This is a large offset (64 bit) read.
2716 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2718 #else /* !LARGE_SMB_OFF_T */
2721 * Ensure we haven't been sent a >32 bit offset.
2724 if(IVAL(inbuf,smb_vwv10) != 0) {
2725 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2726 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2727 END_PROFILE(SMBreadX);
2728 return ERROR_DOS(ERRDOS,ERRbadaccess);
2731 #endif /* LARGE_SMB_OFF_T */
2735 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2736 END_PROFILE(SMBreadX);
2737 return ERROR_DOS(ERRDOS,ERRlock);
2740 if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2741 END_PROFILE(SMBreadX);
2742 return -1;
2745 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2746 /* Only call chain_reply if not an error. */
2747 if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2748 nread = chain_reply(inbuf,outbuf,length,bufsize);
2751 END_PROFILE(SMBreadX);
2752 return nread;
2755 /****************************************************************************
2756 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2757 ****************************************************************************/
2759 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2761 ssize_t nwritten=0;
2762 ssize_t total_written=0;
2763 size_t numtowrite=0;
2764 size_t tcount;
2765 SMB_OFF_T startpos;
2766 char *data=NULL;
2767 BOOL write_through;
2768 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2769 int outsize = 0;
2770 NTSTATUS status;
2771 START_PROFILE(SMBwritebraw);
2773 if (srv_is_signing_active()) {
2774 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2777 CHECK_FSP(fsp,conn);
2778 if (!CHECK_WRITE(fsp)) {
2779 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2782 tcount = IVAL(inbuf,smb_vwv1);
2783 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2784 write_through = BITSETW(inbuf+smb_vwv7,0);
2786 /* We have to deal with slightly different formats depending
2787 on whether we are using the core+ or lanman1.0 protocol */
2789 if(Protocol <= PROTOCOL_COREPLUS) {
2790 numtowrite = SVAL(smb_buf(inbuf),-2);
2791 data = smb_buf(inbuf);
2792 } else {
2793 numtowrite = SVAL(inbuf,smb_vwv10);
2794 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2797 /* force the error type */
2798 SCVAL(inbuf,smb_com,SMBwritec);
2799 SCVAL(outbuf,smb_com,SMBwritec);
2801 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2802 END_PROFILE(SMBwritebraw);
2803 return(ERROR_DOS(ERRDOS,ERRlock));
2806 if (numtowrite>0)
2807 nwritten = write_file(fsp,data,startpos,numtowrite);
2809 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2810 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2812 if (nwritten < (ssize_t)numtowrite) {
2813 END_PROFILE(SMBwritebraw);
2814 return(UNIXERROR(ERRHRD,ERRdiskfull));
2817 total_written = nwritten;
2819 /* Return a message to the redirector to tell it to send more bytes */
2820 SCVAL(outbuf,smb_com,SMBwritebraw);
2821 SSVALS(outbuf,smb_vwv0,-1);
2822 outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2823 show_msg(outbuf);
2824 if (!send_smb(smbd_server_fd(),outbuf))
2825 exit_server_cleanly("reply_writebraw: send_smb failed.");
2827 /* Now read the raw data into the buffer and write it */
2828 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2829 exit_server_cleanly("secondary writebraw failed");
2832 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2833 numtowrite = smb_len(inbuf);
2835 /* Set up outbuf to return the correct return */
2836 outsize = set_message(inbuf,outbuf,1,0,True);
2837 SCVAL(outbuf,smb_com,SMBwritec);
2839 if (numtowrite != 0) {
2841 if (numtowrite > BUFFER_SIZE) {
2842 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2843 (unsigned int)numtowrite ));
2844 exit_server_cleanly("secondary writebraw failed");
2847 if (tcount > nwritten+numtowrite) {
2848 DEBUG(3,("Client overestimated the write %d %d %d\n",
2849 (int)tcount,(int)nwritten,(int)numtowrite));
2852 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2853 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2854 strerror(errno) ));
2855 exit_server_cleanly("secondary writebraw failed");
2858 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2859 if (nwritten == -1) {
2860 END_PROFILE(SMBwritebraw);
2861 return(UNIXERROR(ERRHRD,ERRdiskfull));
2864 if (nwritten < (ssize_t)numtowrite) {
2865 SCVAL(outbuf,smb_rcls,ERRHRD);
2866 SSVAL(outbuf,smb_err,ERRdiskfull);
2869 if (nwritten > 0)
2870 total_written += nwritten;
2873 SSVAL(outbuf,smb_vwv0,total_written);
2875 status = sync_file(conn, fsp, write_through);
2876 if (!NT_STATUS_IS_OK(status)) {
2877 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
2878 fsp->fsp_name, nt_errstr(status) ));
2879 END_PROFILE(SMBwritebraw);
2880 return ERROR_NT(status);
2883 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2884 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2886 /* we won't return a status if write through is not selected - this follows what WfWg does */
2887 END_PROFILE(SMBwritebraw);
2888 if (!write_through && total_written==tcount) {
2890 #if RABBIT_PELLET_FIX
2892 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2893 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2895 if (!send_keepalive(smbd_server_fd()))
2896 exit_server_cleanly("reply_writebraw: send of keepalive failed");
2897 #endif
2898 return(-1);
2901 return(outsize);
2904 #undef DBGC_CLASS
2905 #define DBGC_CLASS DBGC_LOCKING
2907 /****************************************************************************
2908 Reply to a writeunlock (core+).
2909 ****************************************************************************/
2911 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2912 int size, int dum_buffsize)
2914 ssize_t nwritten = -1;
2915 size_t numtowrite;
2916 SMB_OFF_T startpos;
2917 char *data;
2918 NTSTATUS status = NT_STATUS_OK;
2919 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2920 int outsize = 0;
2921 START_PROFILE(SMBwriteunlock);
2923 CHECK_FSP(fsp,conn);
2924 if (!CHECK_WRITE(fsp)) {
2925 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2928 numtowrite = SVAL(inbuf,smb_vwv1);
2929 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2930 data = smb_buf(inbuf) + 3;
2932 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2933 END_PROFILE(SMBwriteunlock);
2934 return ERROR_DOS(ERRDOS,ERRlock);
2937 /* The special X/Open SMB protocol handling of
2938 zero length writes is *NOT* done for
2939 this call */
2940 if(numtowrite == 0) {
2941 nwritten = 0;
2942 } else {
2943 nwritten = write_file(fsp,data,startpos,numtowrite);
2946 status = sync_file(conn, fsp, False /* write through */);
2947 if (!NT_STATUS_IS_OK(status)) {
2948 END_PROFILE(SMBwriteunlock);
2949 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
2950 fsp->fsp_name, nt_errstr(status) ));
2951 return ERROR_NT(status);
2954 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2955 END_PROFILE(SMBwriteunlock);
2956 return(UNIXERROR(ERRHRD,ERRdiskfull));
2959 if (numtowrite) {
2960 status = do_unlock(smbd_messaging_context(),
2961 fsp,
2962 (uint32)SVAL(inbuf,smb_pid),
2963 (SMB_BIG_UINT)numtowrite,
2964 (SMB_BIG_UINT)startpos,
2965 WINDOWS_LOCK);
2967 if (NT_STATUS_V(status)) {
2968 END_PROFILE(SMBwriteunlock);
2969 return ERROR_NT(status);
2973 outsize = set_message(inbuf,outbuf,1,0,True);
2975 SSVAL(outbuf,smb_vwv0,nwritten);
2977 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2978 fsp->fnum, (int)numtowrite, (int)nwritten));
2980 END_PROFILE(SMBwriteunlock);
2981 return outsize;
2984 #undef DBGC_CLASS
2985 #define DBGC_CLASS DBGC_ALL
2987 /****************************************************************************
2988 Reply to a write.
2989 ****************************************************************************/
2991 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2993 size_t numtowrite;
2994 ssize_t nwritten = -1;
2995 SMB_OFF_T startpos;
2996 char *data;
2997 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2998 int outsize = 0;
2999 NTSTATUS status;
3000 START_PROFILE(SMBwrite);
3002 /* If it's an IPC, pass off the pipe handler. */
3003 if (IS_IPC(conn)) {
3004 END_PROFILE(SMBwrite);
3005 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
3008 CHECK_FSP(fsp,conn);
3009 if (!CHECK_WRITE(fsp)) {
3010 END_PROFILE(SMBwrite);
3011 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3014 numtowrite = SVAL(inbuf,smb_vwv1);
3015 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3016 data = smb_buf(inbuf) + 3;
3018 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3019 END_PROFILE(SMBwrite);
3020 return ERROR_DOS(ERRDOS,ERRlock);
3024 * X/Open SMB protocol says that if smb_vwv1 is
3025 * zero then the file size should be extended or
3026 * truncated to the size given in smb_vwv[2-3].
3029 if(numtowrite == 0) {
3031 * This is actually an allocate call, and set EOF. JRA.
3033 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3034 if (nwritten < 0) {
3035 END_PROFILE(SMBwrite);
3036 return ERROR_NT(NT_STATUS_DISK_FULL);
3038 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3039 if (nwritten < 0) {
3040 END_PROFILE(SMBwrite);
3041 return ERROR_NT(NT_STATUS_DISK_FULL);
3043 } else
3044 nwritten = write_file(fsp,data,startpos,numtowrite);
3046 status = sync_file(conn, fsp, False);
3047 if (!NT_STATUS_IS_OK(status)) {
3048 END_PROFILE(SMBwrite);
3049 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3050 fsp->fsp_name, nt_errstr(status) ));
3051 return ERROR_NT(status);
3054 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3055 END_PROFILE(SMBwrite);
3056 return(UNIXERROR(ERRHRD,ERRdiskfull));
3059 outsize = set_message(inbuf,outbuf,1,0,True);
3061 SSVAL(outbuf,smb_vwv0,nwritten);
3063 if (nwritten < (ssize_t)numtowrite) {
3064 SCVAL(outbuf,smb_rcls,ERRHRD);
3065 SSVAL(outbuf,smb_err,ERRdiskfull);
3068 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3070 END_PROFILE(SMBwrite);
3071 return(outsize);
3074 /****************************************************************************
3075 Reply to a write and X.
3076 ****************************************************************************/
3078 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3080 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3081 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3082 size_t numtowrite = SVAL(inbuf,smb_vwv10);
3083 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3084 ssize_t nwritten = -1;
3085 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3086 unsigned int smblen = smb_len(inbuf);
3087 char *data;
3088 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3089 NTSTATUS status;
3090 START_PROFILE(SMBwriteX);
3092 /* If it's an IPC, pass off the pipe handler. */
3093 if (IS_IPC(conn)) {
3094 END_PROFILE(SMBwriteX);
3095 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3098 CHECK_FSP(fsp,conn);
3099 if (!CHECK_WRITE(fsp)) {
3100 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3103 set_message(inbuf,outbuf,6,0,True);
3105 /* Deal with possible LARGE_WRITEX */
3106 if (large_writeX) {
3107 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3110 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3111 END_PROFILE(SMBwriteX);
3112 return ERROR_DOS(ERRDOS,ERRbadmem);
3115 data = smb_base(inbuf) + smb_doff;
3117 if(CVAL(inbuf,smb_wct) == 14) {
3118 #ifdef LARGE_SMB_OFF_T
3120 * This is a large offset (64 bit) write.
3122 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3124 #else /* !LARGE_SMB_OFF_T */
3127 * Ensure we haven't been sent a >32 bit offset.
3130 if(IVAL(inbuf,smb_vwv12) != 0) {
3131 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3132 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3133 END_PROFILE(SMBwriteX);
3134 return ERROR_DOS(ERRDOS,ERRbadaccess);
3137 #endif /* LARGE_SMB_OFF_T */
3140 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3141 END_PROFILE(SMBwriteX);
3142 return ERROR_DOS(ERRDOS,ERRlock);
3145 /* X/Open SMB protocol says that, unlike SMBwrite
3146 if the length is zero then NO truncation is
3147 done, just a write of zero. To truncate a file,
3148 use SMBwrite. */
3150 if(numtowrite == 0) {
3151 nwritten = 0;
3152 } else {
3154 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3155 fsp,data,startpos,numtowrite)) {
3156 END_PROFILE(SMBwriteX);
3157 return -1;
3160 nwritten = write_file(fsp,data,startpos,numtowrite);
3163 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3164 END_PROFILE(SMBwriteX);
3165 return(UNIXERROR(ERRHRD,ERRdiskfull));
3168 SSVAL(outbuf,smb_vwv2,nwritten);
3169 if (large_writeX)
3170 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3172 if (nwritten < (ssize_t)numtowrite) {
3173 SCVAL(outbuf,smb_rcls,ERRHRD);
3174 SSVAL(outbuf,smb_err,ERRdiskfull);
3177 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3178 fsp->fnum, (int)numtowrite, (int)nwritten));
3180 status = sync_file(conn, fsp, write_through);
3181 if (!NT_STATUS_IS_OK(status)) {
3182 END_PROFILE(SMBwriteX);
3183 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3184 fsp->fsp_name, nt_errstr(status) ));
3185 return ERROR_NT(status);
3188 END_PROFILE(SMBwriteX);
3189 return chain_reply(inbuf,outbuf,length,bufsize);
3192 /****************************************************************************
3193 Reply to a lseek.
3194 ****************************************************************************/
3196 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3198 SMB_OFF_T startpos;
3199 SMB_OFF_T res= -1;
3200 int mode,umode;
3201 int outsize = 0;
3202 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3203 START_PROFILE(SMBlseek);
3205 CHECK_FSP(fsp,conn);
3207 flush_write_cache(fsp, SEEK_FLUSH);
3209 mode = SVAL(inbuf,smb_vwv1) & 3;
3210 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3211 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3213 switch (mode) {
3214 case 0:
3215 umode = SEEK_SET;
3216 res = startpos;
3217 break;
3218 case 1:
3219 umode = SEEK_CUR;
3220 res = fsp->fh->pos + startpos;
3221 break;
3222 case 2:
3223 umode = SEEK_END;
3224 break;
3225 default:
3226 umode = SEEK_SET;
3227 res = startpos;
3228 break;
3231 if (umode == SEEK_END) {
3232 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3233 if(errno == EINVAL) {
3234 SMB_OFF_T current_pos = startpos;
3235 SMB_STRUCT_STAT sbuf;
3237 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3238 END_PROFILE(SMBlseek);
3239 return(UNIXERROR(ERRDOS,ERRnoaccess));
3242 current_pos += sbuf.st_size;
3243 if(current_pos < 0)
3244 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3248 if(res == -1) {
3249 END_PROFILE(SMBlseek);
3250 return(UNIXERROR(ERRDOS,ERRnoaccess));
3254 fsp->fh->pos = res;
3256 outsize = set_message(inbuf,outbuf,2,0,True);
3257 SIVAL(outbuf,smb_vwv0,res);
3259 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3260 fsp->fnum, (double)startpos, (double)res, mode));
3262 END_PROFILE(SMBlseek);
3263 return(outsize);
3266 /****************************************************************************
3267 Reply to a flush.
3268 ****************************************************************************/
3270 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3272 int outsize = set_message(inbuf,outbuf,0,0,False);
3273 uint16 fnum = SVAL(inbuf,smb_vwv0);
3274 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3275 START_PROFILE(SMBflush);
3277 if (fnum != 0xFFFF)
3278 CHECK_FSP(fsp,conn);
3280 if (!fsp) {
3281 file_sync_all(conn);
3282 } else {
3283 NTSTATUS status = sync_file(conn, fsp, True);
3284 if (!NT_STATUS_IS_OK(status)) {
3285 END_PROFILE(SMBflush);
3286 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3287 fsp->fsp_name, nt_errstr(status) ));
3288 return ERROR_NT(status);
3292 DEBUG(3,("flush\n"));
3293 END_PROFILE(SMBflush);
3294 return(outsize);
3297 /****************************************************************************
3298 Reply to a exit.
3299 conn POINTER CAN BE NULL HERE !
3300 ****************************************************************************/
3302 int reply_exit(connection_struct *conn,
3303 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3305 int outsize;
3306 START_PROFILE(SMBexit);
3308 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3310 outsize = set_message(inbuf,outbuf,0,0,False);
3312 DEBUG(3,("exit\n"));
3314 END_PROFILE(SMBexit);
3315 return(outsize);
3318 /****************************************************************************
3319 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3320 ****************************************************************************/
3322 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3323 int dum_buffsize)
3325 NTSTATUS status = NT_STATUS_OK;
3326 int outsize = 0;
3327 files_struct *fsp = NULL;
3328 START_PROFILE(SMBclose);
3330 outsize = set_message(inbuf,outbuf,0,0,False);
3332 /* If it's an IPC, pass off to the pipe handler. */
3333 if (IS_IPC(conn)) {
3334 END_PROFILE(SMBclose);
3335 return reply_pipe_close(conn, inbuf,outbuf);
3338 fsp = file_fsp(inbuf,smb_vwv0);
3341 * We can only use CHECK_FSP if we know it's not a directory.
3344 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3345 END_PROFILE(SMBclose);
3346 return ERROR_DOS(ERRDOS,ERRbadfid);
3349 if(fsp->is_directory) {
3351 * Special case - close NT SMB directory handle.
3353 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3354 status = close_file(fsp,NORMAL_CLOSE);
3355 } else {
3357 * Close ordinary file.
3360 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3361 fsp->fh->fd, fsp->fnum,
3362 conn->num_files_open));
3365 * Take care of any time sent in the close.
3368 fsp_set_pending_modtime(fsp,
3369 convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
3372 * close_file() returns the unix errno if an error
3373 * was detected on close - normally this is due to
3374 * a disk full error. If not then it was probably an I/O error.
3377 status = close_file(fsp,NORMAL_CLOSE);
3380 if(!NT_STATUS_IS_OK(status)) {
3381 END_PROFILE(SMBclose);
3382 return ERROR_NT(status);
3385 END_PROFILE(SMBclose);
3386 return(outsize);
3389 /****************************************************************************
3390 Reply to a writeclose (Core+ protocol).
3391 ****************************************************************************/
3393 int reply_writeclose(connection_struct *conn,
3394 char *inbuf,char *outbuf, int size, int dum_buffsize)
3396 size_t numtowrite;
3397 ssize_t nwritten = -1;
3398 int outsize = 0;
3399 NTSTATUS close_status = NT_STATUS_OK;
3400 SMB_OFF_T startpos;
3401 char *data;
3402 struct timespec mtime;
3403 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3404 START_PROFILE(SMBwriteclose);
3406 CHECK_FSP(fsp,conn);
3407 if (!CHECK_WRITE(fsp)) {
3408 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3411 numtowrite = SVAL(inbuf,smb_vwv1);
3412 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3413 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3414 data = smb_buf(inbuf) + 1;
3416 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3417 END_PROFILE(SMBwriteclose);
3418 return ERROR_DOS(ERRDOS,ERRlock);
3421 nwritten = write_file(fsp,data,startpos,numtowrite);
3423 set_filetime(conn, fsp->fsp_name, mtime);
3426 * More insanity. W2K only closes the file if writelen > 0.
3427 * JRA.
3430 if (numtowrite) {
3431 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3432 fsp->fsp_name ));
3433 close_status = close_file(fsp,NORMAL_CLOSE);
3436 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3437 fsp->fnum, (int)numtowrite, (int)nwritten,
3438 conn->num_files_open));
3440 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3441 END_PROFILE(SMBwriteclose);
3442 return(UNIXERROR(ERRHRD,ERRdiskfull));
3445 if(!NT_STATUS_IS_OK(close_status)) {
3446 END_PROFILE(SMBwriteclose);
3447 return ERROR_NT(close_status);
3450 outsize = set_message(inbuf,outbuf,1,0,True);
3452 SSVAL(outbuf,smb_vwv0,nwritten);
3453 END_PROFILE(SMBwriteclose);
3454 return(outsize);
3457 #undef DBGC_CLASS
3458 #define DBGC_CLASS DBGC_LOCKING
3460 /****************************************************************************
3461 Reply to a lock.
3462 ****************************************************************************/
3464 int reply_lock(connection_struct *conn,
3465 char *inbuf,char *outbuf, int length, int dum_buffsize)
3467 int outsize = set_message(inbuf,outbuf,0,0,False);
3468 SMB_BIG_UINT count,offset;
3469 NTSTATUS status;
3470 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3471 struct byte_range_lock *br_lck = NULL;
3473 START_PROFILE(SMBlock);
3475 CHECK_FSP(fsp,conn);
3477 release_level_2_oplocks_on_change(fsp);
3479 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3480 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3482 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3483 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3485 br_lck = do_lock(smbd_messaging_context(),
3486 fsp,
3487 (uint32)SVAL(inbuf,smb_pid),
3488 count,
3489 offset,
3490 WRITE_LOCK,
3491 WINDOWS_LOCK,
3492 False, /* Non-blocking lock. */
3493 &status,
3494 NULL);
3496 TALLOC_FREE(br_lck);
3498 if (NT_STATUS_V(status)) {
3499 END_PROFILE(SMBlock);
3500 return ERROR_NT(status);
3503 END_PROFILE(SMBlock);
3504 return(outsize);
3507 /****************************************************************************
3508 Reply to a unlock.
3509 ****************************************************************************/
3511 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3512 int dum_buffsize)
3514 int outsize = set_message(inbuf,outbuf,0,0,False);
3515 SMB_BIG_UINT count,offset;
3516 NTSTATUS status;
3517 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3518 START_PROFILE(SMBunlock);
3520 CHECK_FSP(fsp,conn);
3522 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3523 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3525 status = do_unlock(smbd_messaging_context(),
3526 fsp,
3527 (uint32)SVAL(inbuf,smb_pid),
3528 count,
3529 offset,
3530 WINDOWS_LOCK);
3532 if (NT_STATUS_V(status)) {
3533 END_PROFILE(SMBunlock);
3534 return ERROR_NT(status);
3537 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3538 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3540 END_PROFILE(SMBunlock);
3541 return(outsize);
3544 #undef DBGC_CLASS
3545 #define DBGC_CLASS DBGC_ALL
3547 /****************************************************************************
3548 Reply to a tdis.
3549 conn POINTER CAN BE NULL HERE !
3550 ****************************************************************************/
3552 int reply_tdis(connection_struct *conn,
3553 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3555 int outsize = set_message(inbuf,outbuf,0,0,False);
3556 uint16 vuid;
3557 START_PROFILE(SMBtdis);
3559 vuid = SVAL(inbuf,smb_uid);
3561 if (!conn) {
3562 DEBUG(4,("Invalid connection in tdis\n"));
3563 END_PROFILE(SMBtdis);
3564 return ERROR_DOS(ERRSRV,ERRinvnid);
3567 conn->used = False;
3569 close_cnum(conn,vuid);
3571 END_PROFILE(SMBtdis);
3572 return outsize;
3575 /****************************************************************************
3576 Reply to a echo.
3577 conn POINTER CAN BE NULL HERE !
3578 ****************************************************************************/
3580 int reply_echo(connection_struct *conn,
3581 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3583 int smb_reverb = SVAL(inbuf,smb_vwv0);
3584 int seq_num;
3585 unsigned int data_len = smb_buflen(inbuf);
3586 int outsize = set_message(inbuf,outbuf,1,data_len,True);
3587 START_PROFILE(SMBecho);
3589 if (data_len > BUFFER_SIZE) {
3590 DEBUG(0,("reply_echo: data_len too large.\n"));
3591 END_PROFILE(SMBecho);
3592 return -1;
3595 /* copy any incoming data back out */
3596 if (data_len > 0)
3597 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3599 if (smb_reverb > 100) {
3600 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3601 smb_reverb = 100;
3604 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3605 SSVAL(outbuf,smb_vwv0,seq_num);
3607 smb_setlen(inbuf,outbuf,outsize - 4);
3609 show_msg(outbuf);
3610 if (!send_smb(smbd_server_fd(),outbuf))
3611 exit_server_cleanly("reply_echo: send_smb failed.");
3614 DEBUG(3,("echo %d times\n", smb_reverb));
3616 smb_echo_count++;
3618 END_PROFILE(SMBecho);
3619 return -1;
3622 /****************************************************************************
3623 Reply to a printopen.
3624 ****************************************************************************/
3626 int reply_printopen(connection_struct *conn,
3627 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3629 int outsize = 0;
3630 files_struct *fsp;
3631 NTSTATUS status;
3633 START_PROFILE(SMBsplopen);
3635 if (!CAN_PRINT(conn)) {
3636 END_PROFILE(SMBsplopen);
3637 return ERROR_DOS(ERRDOS,ERRnoaccess);
3640 /* Open for exclusive use, write only. */
3641 status = print_fsp_open(conn, NULL, &fsp);
3643 if (!NT_STATUS_IS_OK(status)) {
3644 END_PROFILE(SMBsplopen);
3645 return(ERROR_NT(status));
3648 outsize = set_message(inbuf,outbuf,1,0,True);
3649 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3651 DEBUG(3,("openprint fd=%d fnum=%d\n",
3652 fsp->fh->fd, fsp->fnum));
3654 END_PROFILE(SMBsplopen);
3655 return(outsize);
3658 /****************************************************************************
3659 Reply to a printclose.
3660 ****************************************************************************/
3662 int reply_printclose(connection_struct *conn,
3663 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3665 int outsize = set_message(inbuf,outbuf,0,0,False);
3666 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3667 NTSTATUS status;
3668 START_PROFILE(SMBsplclose);
3670 CHECK_FSP(fsp,conn);
3672 if (!CAN_PRINT(conn)) {
3673 END_PROFILE(SMBsplclose);
3674 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3677 DEBUG(3,("printclose fd=%d fnum=%d\n",
3678 fsp->fh->fd,fsp->fnum));
3680 status = close_file(fsp,NORMAL_CLOSE);
3682 if(!NT_STATUS_IS_OK(status)) {
3683 END_PROFILE(SMBsplclose);
3684 return ERROR_NT(status);
3687 END_PROFILE(SMBsplclose);
3688 return(outsize);
3691 /****************************************************************************
3692 Reply to a printqueue.
3693 ****************************************************************************/
3695 int reply_printqueue(connection_struct *conn,
3696 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3698 int outsize = set_message(inbuf,outbuf,2,3,True);
3699 int max_count = SVAL(inbuf,smb_vwv0);
3700 int start_index = SVAL(inbuf,smb_vwv1);
3701 START_PROFILE(SMBsplretq);
3703 /* we used to allow the client to get the cnum wrong, but that
3704 is really quite gross and only worked when there was only
3705 one printer - I think we should now only accept it if they
3706 get it right (tridge) */
3707 if (!CAN_PRINT(conn)) {
3708 END_PROFILE(SMBsplretq);
3709 return ERROR_DOS(ERRDOS,ERRnoaccess);
3712 SSVAL(outbuf,smb_vwv0,0);
3713 SSVAL(outbuf,smb_vwv1,0);
3714 SCVAL(smb_buf(outbuf),0,1);
3715 SSVAL(smb_buf(outbuf),1,0);
3717 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3718 start_index, max_count));
3721 print_queue_struct *queue = NULL;
3722 print_status_struct status;
3723 char *p = smb_buf(outbuf) + 3;
3724 int count = print_queue_status(SNUM(conn), &queue, &status);
3725 int num_to_get = ABS(max_count);
3726 int first = (max_count>0?start_index:start_index+max_count+1);
3727 int i;
3729 if (first >= count)
3730 num_to_get = 0;
3731 else
3732 num_to_get = MIN(num_to_get,count-first);
3735 for (i=first;i<first+num_to_get;i++) {
3736 srv_put_dos_date2(p,0,queue[i].time);
3737 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3738 SSVAL(p,5, queue[i].job);
3739 SIVAL(p,7,queue[i].size);
3740 SCVAL(p,11,0);
3741 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3742 p += 28;
3745 if (count > 0) {
3746 outsize = set_message(inbuf,outbuf,2,28*count+3,False);
3747 SSVAL(outbuf,smb_vwv0,count);
3748 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3749 SCVAL(smb_buf(outbuf),0,1);
3750 SSVAL(smb_buf(outbuf),1,28*count);
3753 SAFE_FREE(queue);
3755 DEBUG(3,("%d entries returned in queue\n",count));
3758 END_PROFILE(SMBsplretq);
3759 return(outsize);
3762 /****************************************************************************
3763 Reply to a printwrite.
3764 ****************************************************************************/
3766 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3768 int numtowrite;
3769 int outsize = set_message(inbuf,outbuf,0,0,False);
3770 char *data;
3771 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3773 START_PROFILE(SMBsplwr);
3775 if (!CAN_PRINT(conn)) {
3776 END_PROFILE(SMBsplwr);
3777 return ERROR_DOS(ERRDOS,ERRnoaccess);
3780 CHECK_FSP(fsp,conn);
3781 if (!CHECK_WRITE(fsp)) {
3782 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3785 numtowrite = SVAL(smb_buf(inbuf),1);
3786 data = smb_buf(inbuf) + 3;
3788 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3789 END_PROFILE(SMBsplwr);
3790 return(UNIXERROR(ERRHRD,ERRdiskfull));
3793 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3795 END_PROFILE(SMBsplwr);
3796 return(outsize);
3799 /****************************************************************************
3800 Reply to a mkdir.
3801 ****************************************************************************/
3803 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3805 pstring directory;
3806 int outsize;
3807 NTSTATUS status;
3808 SMB_STRUCT_STAT sbuf;
3810 START_PROFILE(SMBmkdir);
3812 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3813 if (!NT_STATUS_IS_OK(status)) {
3814 END_PROFILE(SMBmkdir);
3815 return ERROR_NT(status);
3818 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
3819 if (!NT_STATUS_IS_OK(status)) {
3820 END_PROFILE(SMBmkdir);
3821 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3822 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3824 return ERROR_NT(status);
3827 status = unix_convert(conn, directory, False, NULL, &sbuf);
3828 if (!NT_STATUS_IS_OK(status)) {
3829 END_PROFILE(SMBmkdir);
3830 return ERROR_NT(status);
3833 status = check_name(conn, directory);
3834 if (!NT_STATUS_IS_OK(status)) {
3835 END_PROFILE(SMBmkdir);
3836 return ERROR_NT(status);
3839 status = create_directory(conn, directory);
3841 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3843 if (!NT_STATUS_IS_OK(status)) {
3845 if (!use_nt_status()
3846 && NT_STATUS_EQUAL(status,
3847 NT_STATUS_OBJECT_NAME_COLLISION)) {
3849 * Yes, in the DOS error code case we get a
3850 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3851 * samba4 torture test.
3853 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3856 END_PROFILE(SMBmkdir);
3857 return ERROR_NT(status);
3860 outsize = set_message(inbuf,outbuf,0,0,False);
3862 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3864 END_PROFILE(SMBmkdir);
3865 return(outsize);
3868 /****************************************************************************
3869 Static function used by reply_rmdir to delete an entire directory
3870 tree recursively. Return True on ok, False on fail.
3871 ****************************************************************************/
3873 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3875 const char *dname = NULL;
3876 BOOL ret = True;
3877 long offset = 0;
3878 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3880 if(dir_hnd == NULL)
3881 return False;
3883 while((dname = ReadDirName(dir_hnd, &offset))) {
3884 pstring fullname;
3885 SMB_STRUCT_STAT st;
3887 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3888 continue;
3890 if (!is_visible_file(conn, directory, dname, &st, False))
3891 continue;
3893 /* Construct the full name. */
3894 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3895 errno = ENOMEM;
3896 ret = False;
3897 break;
3900 pstrcpy(fullname, directory);
3901 pstrcat(fullname, "/");
3902 pstrcat(fullname, dname);
3904 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3905 ret = False;
3906 break;
3909 if(st.st_mode & S_IFDIR) {
3910 if(!recursive_rmdir(conn, fullname)) {
3911 ret = False;
3912 break;
3914 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3915 ret = False;
3916 break;
3918 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3919 ret = False;
3920 break;
3923 CloseDir(dir_hnd);
3924 return ret;
3927 /****************************************************************************
3928 The internals of the rmdir code - called elsewhere.
3929 ****************************************************************************/
3931 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
3933 int ret;
3934 SMB_STRUCT_STAT st;
3936 /* Might be a symlink. */
3937 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
3938 return map_nt_error_from_unix(errno);
3941 if (S_ISLNK(st.st_mode)) {
3942 /* Is what it points to a directory ? */
3943 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
3944 return map_nt_error_from_unix(errno);
3946 if (!(S_ISDIR(st.st_mode))) {
3947 return NT_STATUS_NOT_A_DIRECTORY;
3949 ret = SMB_VFS_UNLINK(conn,directory);
3950 } else {
3951 ret = SMB_VFS_RMDIR(conn,directory);
3953 if (ret == 0) {
3954 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3955 FILE_NOTIFY_CHANGE_DIR_NAME,
3956 directory);
3957 return NT_STATUS_OK;
3960 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3962 * Check to see if the only thing in this directory are
3963 * vetoed files/directories. If so then delete them and
3964 * retry. If we fail to delete any of them (and we *don't*
3965 * do a recursive delete) then fail the rmdir.
3967 const char *dname;
3968 long dirpos = 0;
3969 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3971 if(dir_hnd == NULL) {
3972 errno = ENOTEMPTY;
3973 goto err;
3976 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3977 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3978 continue;
3979 if (!is_visible_file(conn, directory, dname, &st, False))
3980 continue;
3981 if(!IS_VETO_PATH(conn, dname)) {
3982 CloseDir(dir_hnd);
3983 errno = ENOTEMPTY;
3984 goto err;
3988 /* We only have veto files/directories. Recursive delete. */
3990 RewindDir(dir_hnd,&dirpos);
3991 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3992 pstring fullname;
3994 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3995 continue;
3996 if (!is_visible_file(conn, directory, dname, &st, False))
3997 continue;
3999 /* Construct the full name. */
4000 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4001 errno = ENOMEM;
4002 break;
4005 pstrcpy(fullname, directory);
4006 pstrcat(fullname, "/");
4007 pstrcat(fullname, dname);
4009 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4010 break;
4011 if(st.st_mode & S_IFDIR) {
4012 if(lp_recursive_veto_delete(SNUM(conn))) {
4013 if(!recursive_rmdir(conn, fullname))
4014 break;
4016 if(SMB_VFS_RMDIR(conn,fullname) != 0)
4017 break;
4018 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4019 break;
4021 CloseDir(dir_hnd);
4022 /* Retry the rmdir */
4023 ret = SMB_VFS_RMDIR(conn,directory);
4026 err:
4028 if (ret != 0) {
4029 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4030 "%s\n", directory,strerror(errno)));
4031 return map_nt_error_from_unix(errno);
4034 notify_fname(conn, NOTIFY_ACTION_REMOVED,
4035 FILE_NOTIFY_CHANGE_DIR_NAME,
4036 directory);
4038 return NT_STATUS_OK;
4041 /****************************************************************************
4042 Reply to a rmdir.
4043 ****************************************************************************/
4045 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4047 pstring directory;
4048 int outsize = 0;
4049 SMB_STRUCT_STAT sbuf;
4050 NTSTATUS status;
4051 START_PROFILE(SMBrmdir);
4053 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
4054 if (!NT_STATUS_IS_OK(status)) {
4055 END_PROFILE(SMBrmdir);
4056 return ERROR_NT(status);
4059 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
4060 if (!NT_STATUS_IS_OK(status)) {
4061 END_PROFILE(SMBrmdir);
4062 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4063 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4065 return ERROR_NT(status);
4068 status = unix_convert(conn, directory, False, NULL, &sbuf);
4069 if (!NT_STATUS_IS_OK(status)) {
4070 END_PROFILE(SMBrmdir);
4071 return ERROR_NT(status);
4074 status = check_name(conn, directory);
4075 if (!NT_STATUS_IS_OK(status)) {
4076 END_PROFILE(SMBrmdir);
4077 return ERROR_NT(status);
4080 dptr_closepath(directory,SVAL(inbuf,smb_pid));
4081 status = rmdir_internals(conn, directory);
4082 if (!NT_STATUS_IS_OK(status)) {
4083 END_PROFILE(SMBrmdir);
4084 return ERROR_NT(status);
4087 outsize = set_message(inbuf,outbuf,0,0,False);
4089 DEBUG( 3, ( "rmdir %s\n", directory ) );
4091 END_PROFILE(SMBrmdir);
4092 return(outsize);
4095 /*******************************************************************
4096 Resolve wildcards in a filename rename.
4097 Note that name is in UNIX charset and thus potentially can be more
4098 than fstring buffer (255 bytes) especially in default UTF-8 case.
4099 Therefore, we use pstring inside and all calls should ensure that
4100 name2 is at least pstring-long (they do already)
4101 ********************************************************************/
4103 static BOOL resolve_wildcards(const char *name1, char *name2)
4105 pstring root1,root2;
4106 pstring ext1,ext2;
4107 char *p,*p2, *pname1, *pname2;
4108 int available_space, actual_space;
4110 pname1 = strrchr_m(name1,'/');
4111 pname2 = strrchr_m(name2,'/');
4113 if (!pname1 || !pname2)
4114 return(False);
4116 pstrcpy(root1,pname1);
4117 pstrcpy(root2,pname2);
4118 p = strrchr_m(root1,'.');
4119 if (p) {
4120 *p = 0;
4121 pstrcpy(ext1,p+1);
4122 } else {
4123 pstrcpy(ext1,"");
4125 p = strrchr_m(root2,'.');
4126 if (p) {
4127 *p = 0;
4128 pstrcpy(ext2,p+1);
4129 } else {
4130 pstrcpy(ext2,"");
4133 p = root1;
4134 p2 = root2;
4135 while (*p2) {
4136 if (*p2 == '?') {
4137 *p2 = *p;
4138 p2++;
4139 } else if (*p2 == '*') {
4140 pstrcpy(p2, p);
4141 break;
4142 } else {
4143 p2++;
4145 if (*p)
4146 p++;
4149 p = ext1;
4150 p2 = ext2;
4151 while (*p2) {
4152 if (*p2 == '?') {
4153 *p2 = *p;
4154 p2++;
4155 } else if (*p2 == '*') {
4156 pstrcpy(p2, p);
4157 break;
4158 } else {
4159 p2++;
4161 if (*p)
4162 p++;
4165 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4167 if (ext2[0]) {
4168 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4169 if (actual_space >= available_space - 1) {
4170 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4171 actual_space - available_space));
4173 } else {
4174 pstrcpy_base(pname2, root2, name2);
4177 return(True);
4180 /****************************************************************************
4181 Ensure open files have their names updated. Updated to notify other smbd's
4182 asynchronously.
4183 ****************************************************************************/
4185 static void rename_open_files(connection_struct *conn,
4186 struct share_mode_lock *lck,
4187 const char *newname)
4189 files_struct *fsp;
4190 BOOL did_rename = False;
4192 for(fsp = file_find_di_first(lck->id); fsp;
4193 fsp = file_find_di_next(fsp)) {
4194 /* fsp_name is a relative path under the fsp. To change this for other
4195 sharepaths we need to manipulate relative paths. */
4196 /* TODO - create the absolute path and manipulate the newname
4197 relative to the sharepath. */
4198 if (fsp->conn != conn) {
4199 continue;
4201 DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
4202 fsp->fnum, file_id_static_string(&fsp->file_id),
4203 fsp->fsp_name, newname ));
4204 string_set(&fsp->fsp_name, newname);
4205 did_rename = True;
4208 if (!did_rename) {
4209 DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
4210 file_id_static_string(&lck->id), newname ));
4213 /* Send messages to all smbd's (not ourself) that the name has changed. */
4214 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
4215 newname);
4218 /****************************************************************************
4219 We need to check if the source path is a parent directory of the destination
4220 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4221 refuse the rename with a sharing violation. Under UNIX the above call can
4222 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4223 probably need to check that the client is a Windows one before disallowing
4224 this as a UNIX client (one with UNIX extensions) can know the source is a
4225 symlink and make this decision intelligently. Found by an excellent bug
4226 report from <AndyLiebman@aol.com>.
4227 ****************************************************************************/
4229 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4231 const char *psrc = src;
4232 const char *pdst = dest;
4233 size_t slen;
4235 if (psrc[0] == '.' && psrc[1] == '/') {
4236 psrc += 2;
4238 if (pdst[0] == '.' && pdst[1] == '/') {
4239 pdst += 2;
4241 if ((slen = strlen(psrc)) > strlen(pdst)) {
4242 return False;
4244 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4248 * Do the notify calls from a rename
4251 static void notify_rename(connection_struct *conn, BOOL is_dir,
4252 const char *oldpath, const char *newpath)
4254 char *olddir, *newdir;
4255 const char *oldname, *newname;
4256 uint32 mask;
4258 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4259 : FILE_NOTIFY_CHANGE_FILE_NAME;
4261 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4262 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4263 TALLOC_FREE(olddir);
4264 return;
4267 if (strcmp(olddir, newdir) == 0) {
4268 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4269 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4271 else {
4272 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4273 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4275 TALLOC_FREE(olddir);
4276 TALLOC_FREE(newdir);
4278 /* this is a strange one. w2k3 gives an additional event for
4279 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4280 files, but not directories */
4281 if (!is_dir) {
4282 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4283 FILE_NOTIFY_CHANGE_ATTRIBUTES
4284 |FILE_NOTIFY_CHANGE_CREATION,
4285 newpath);
4289 /****************************************************************************
4290 Rename an open file - given an fsp.
4291 ****************************************************************************/
4293 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4295 SMB_STRUCT_STAT sbuf, sbuf1;
4296 pstring newname_last_component;
4297 NTSTATUS status = NT_STATUS_OK;
4298 struct share_mode_lock *lck = NULL;
4299 BOOL dst_exists;
4301 ZERO_STRUCT(sbuf);
4303 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4305 /* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4307 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4308 return status;
4311 status = check_name(conn, newname);
4312 if (!NT_STATUS_IS_OK(status)) {
4313 return status;
4316 /* Ensure newname contains a '/' */
4317 if(strrchr_m(newname,'/') == 0) {
4318 pstring tmpstr;
4320 pstrcpy(tmpstr, "./");
4321 pstrcat(tmpstr, newname);
4322 pstrcpy(newname, tmpstr);
4326 * Check for special case with case preserving and not
4327 * case sensitive. If the old last component differs from the original
4328 * last component only by case, then we should allow
4329 * the rename (user is trying to change the case of the
4330 * filename).
4333 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4334 strequal(newname, fsp->fsp_name)) {
4335 char *p;
4336 pstring newname_modified_last_component;
4339 * Get the last component of the modified name.
4340 * Note that we guarantee that newname contains a '/'
4341 * character above.
4343 p = strrchr_m(newname,'/');
4344 pstrcpy(newname_modified_last_component,p+1);
4346 if(strcsequal(newname_modified_last_component,
4347 newname_last_component) == False) {
4349 * Replace the modified last component with
4350 * the original.
4352 pstrcpy(p+1, newname_last_component);
4357 * If the src and dest names are identical - including case,
4358 * don't do the rename, just return success.
4361 if (strcsequal(fsp->fsp_name, newname)) {
4362 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4363 newname));
4364 return NT_STATUS_OK;
4368 * Have vfs_object_exist also fill sbuf1
4370 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
4372 if(!replace_if_exists && dst_exists) {
4373 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4374 fsp->fsp_name,newname));
4375 return NT_STATUS_OBJECT_NAME_COLLISION;
4378 if (dst_exists && file_find_di_first(file_id_sbuf(&sbuf1)) != NULL) {
4379 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
4380 return NT_STATUS_ACCESS_DENIED;
4383 /* Ensure we have a valid stat struct for the source. */
4384 if (fsp->fh->fd != -1) {
4385 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4386 return map_nt_error_from_unix(errno);
4388 } else {
4389 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4390 return map_nt_error_from_unix(errno);
4394 status = can_rename(conn, fsp, attrs, &sbuf);
4396 if (!NT_STATUS_IS_OK(status)) {
4397 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4398 nt_errstr(status), fsp->fsp_name,newname));
4399 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4400 status = NT_STATUS_ACCESS_DENIED;
4401 return status;
4404 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4405 return NT_STATUS_ACCESS_DENIED;
4408 lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
4411 * We have the file open ourselves, so not being able to get the
4412 * corresponding share mode lock is a fatal error.
4415 SMB_ASSERT(lck != NULL);
4417 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4418 uint32 create_options = fsp->fh->private_options;
4420 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4421 fsp->fsp_name,newname));
4423 rename_open_files(conn, lck, newname);
4425 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
4428 * A rename acts as a new file create w.r.t. allowing an initial delete
4429 * on close, probably because in Windows there is a new handle to the
4430 * new file. If initial delete on close was requested but not
4431 * originally set, we need to set it here. This is probably not 100% correct,
4432 * but will work for the CIFSFS client which in non-posix mode
4433 * depends on these semantics. JRA.
4436 set_allow_initial_delete_on_close(lck, fsp, True);
4438 if (create_options & FILE_DELETE_ON_CLOSE) {
4439 status = can_set_delete_on_close(fsp, True, 0);
4441 if (NT_STATUS_IS_OK(status)) {
4442 /* Note that here we set the *inital* delete on close flag,
4443 * not the regular one. The magic gets handled in close. */
4444 fsp->initial_delete_on_close = True;
4447 TALLOC_FREE(lck);
4448 return NT_STATUS_OK;
4451 TALLOC_FREE(lck);
4453 if (errno == ENOTDIR || errno == EISDIR) {
4454 status = NT_STATUS_OBJECT_NAME_COLLISION;
4455 } else {
4456 status = map_nt_error_from_unix(errno);
4459 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4460 nt_errstr(status), fsp->fsp_name,newname));
4462 return status;
4465 /****************************************************************************
4466 The guts of the rename command, split out so it may be called by the NT SMB
4467 code.
4468 ****************************************************************************/
4470 NTSTATUS rename_internals(connection_struct *conn,
4471 pstring name,
4472 pstring newname,
4473 uint32 attrs,
4474 BOOL replace_if_exists,
4475 BOOL src_has_wild,
4476 BOOL dest_has_wild)
4478 pstring directory;
4479 pstring mask;
4480 pstring last_component_src;
4481 pstring last_component_dest;
4482 char *p;
4483 int count=0;
4484 NTSTATUS status = NT_STATUS_OK;
4485 SMB_STRUCT_STAT sbuf1, sbuf2;
4486 struct smb_Dir *dir_hnd = NULL;
4487 const char *dname;
4488 long offset = 0;
4489 pstring destname;
4491 *directory = *mask = 0;
4493 ZERO_STRUCT(sbuf1);
4494 ZERO_STRUCT(sbuf2);
4496 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4497 if (!NT_STATUS_IS_OK(status)) {
4498 return status;
4501 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4502 if (!NT_STATUS_IS_OK(status)) {
4503 return status;
4507 * Split the old name into directory and last component
4508 * strings. Note that unix_convert may have stripped off a
4509 * leading ./ from both name and newname if the rename is
4510 * at the root of the share. We need to make sure either both
4511 * name and newname contain a / character or neither of them do
4512 * as this is checked in resolve_wildcards().
4515 p = strrchr_m(name,'/');
4516 if (!p) {
4517 pstrcpy(directory,".");
4518 pstrcpy(mask,name);
4519 } else {
4520 *p = 0;
4521 pstrcpy(directory,name);
4522 pstrcpy(mask,p+1);
4523 *p = '/'; /* Replace needed for exceptional test below. */
4527 * We should only check the mangled cache
4528 * here if unix_convert failed. This means
4529 * that the path in 'mask' doesn't exist
4530 * on the file system and so we need to look
4531 * for a possible mangle. This patch from
4532 * Tine Smukavec <valentin.smukavec@hermes.si>.
4535 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4536 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4539 if (!src_has_wild) {
4540 files_struct *fsp;
4543 * No wildcards - just process the one file.
4545 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4547 /* Add a terminating '/' to the directory name. */
4548 pstrcat(directory,"/");
4549 pstrcat(directory,mask);
4551 /* Ensure newname contains a '/' also */
4552 if(strrchr_m(newname,'/') == 0) {
4553 pstring tmpstr;
4555 pstrcpy(tmpstr, "./");
4556 pstrcat(tmpstr, newname);
4557 pstrcpy(newname, tmpstr);
4560 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4561 "case_preserve = %d, short case preserve = %d, "
4562 "directory = %s, newname = %s, "
4563 "last_component_dest = %s, is_8_3 = %d\n",
4564 conn->case_sensitive, conn->case_preserve,
4565 conn->short_case_preserve, directory,
4566 newname, last_component_dest, is_short_name));
4568 /* The dest name still may have wildcards. */
4569 if (dest_has_wild) {
4570 if (!resolve_wildcards(directory,newname)) {
4571 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4572 directory,newname));
4573 return NT_STATUS_NO_MEMORY;
4577 ZERO_STRUCT(sbuf1);
4578 SMB_VFS_STAT(conn, directory, &sbuf1);
4580 status = S_ISDIR(sbuf1.st_mode) ?
4581 open_directory(conn, directory, &sbuf1,
4582 DELETE_ACCESS,
4583 FILE_SHARE_READ|FILE_SHARE_WRITE,
4584 FILE_OPEN, 0, 0, NULL,
4585 &fsp)
4586 : open_file_ntcreate(conn, directory, &sbuf1,
4587 DELETE_ACCESS,
4588 FILE_SHARE_READ|FILE_SHARE_WRITE,
4589 FILE_OPEN, 0, 0, 0, NULL,
4590 &fsp);
4592 if (!NT_STATUS_IS_OK(status)) {
4593 DEBUG(3, ("Could not open rename source %s: %s\n",
4594 directory, nt_errstr(status)));
4595 return status;
4598 status = rename_internals_fsp(conn, fsp, newname, attrs,
4599 replace_if_exists);
4601 close_file(fsp, NORMAL_CLOSE);
4603 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
4604 nt_errstr(status), directory,newname));
4606 return status;
4610 * Wildcards - process each file that matches.
4612 if (strequal(mask,"????????.???")) {
4613 pstrcpy(mask,"*");
4616 status = check_name(conn, directory);
4617 if (!NT_STATUS_IS_OK(status)) {
4618 return status;
4621 dir_hnd = OpenDir(conn, directory, mask, attrs);
4622 if (dir_hnd == NULL) {
4623 return map_nt_error_from_unix(errno);
4626 status = NT_STATUS_NO_SUCH_FILE;
4628 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4629 * - gentest fix. JRA
4632 while ((dname = ReadDirName(dir_hnd, &offset))) {
4633 files_struct *fsp;
4634 pstring fname;
4635 BOOL sysdir_entry = False;
4637 pstrcpy(fname,dname);
4639 /* Quick check for "." and ".." */
4640 if (fname[0] == '.') {
4641 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4642 if (attrs & aDIR) {
4643 sysdir_entry = True;
4644 } else {
4645 continue;
4650 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4651 continue;
4654 if(!mask_match(fname, mask, conn->case_sensitive)) {
4655 continue;
4658 if (sysdir_entry) {
4659 status = NT_STATUS_OBJECT_NAME_INVALID;
4660 break;
4663 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4665 pstrcpy(destname,newname);
4667 if (!resolve_wildcards(fname,destname)) {
4668 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4669 fname, destname));
4670 continue;
4673 ZERO_STRUCT(sbuf1);
4674 SMB_VFS_STAT(conn, fname, &sbuf1);
4676 status = S_ISDIR(sbuf1.st_mode) ?
4677 open_directory(conn, fname, &sbuf1,
4678 DELETE_ACCESS,
4679 FILE_SHARE_READ|FILE_SHARE_WRITE,
4680 FILE_OPEN, 0, 0, NULL,
4681 &fsp)
4682 : open_file_ntcreate(conn, fname, &sbuf1,
4683 DELETE_ACCESS,
4684 FILE_SHARE_READ|FILE_SHARE_WRITE,
4685 FILE_OPEN, 0, 0, 0, NULL,
4686 &fsp);
4688 if (!NT_STATUS_IS_OK(status)) {
4689 DEBUG(3,("rename_internals: open_file_ntcreate "
4690 "returned %s rename %s -> %s\n",
4691 nt_errstr(status), directory, newname));
4692 return status;
4695 status = rename_internals_fsp(conn, fsp, destname, attrs,
4696 replace_if_exists);
4698 close_file(fsp, NORMAL_CLOSE);
4700 if (!NT_STATUS_IS_OK(status)) {
4701 DEBUG(3, ("rename_internals_fsp returned %s for "
4702 "rename %s -> %s\n", nt_errstr(status),
4703 directory, newname));
4704 return status;
4707 count++;
4709 DEBUG(3,("rename_internals: doing rename on %s -> "
4710 "%s\n",fname,destname));
4712 CloseDir(dir_hnd);
4714 if (count == 0 && NT_STATUS_IS_OK(status)) {
4715 status = map_nt_error_from_unix(errno);
4718 return status;
4721 /****************************************************************************
4722 Reply to a mv.
4723 ****************************************************************************/
4725 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4726 int dum_buffsize)
4728 int outsize = 0;
4729 pstring name;
4730 pstring newname;
4731 char *p;
4732 uint32 attrs = SVAL(inbuf,smb_vwv0);
4733 NTSTATUS status;
4734 BOOL src_has_wcard = False;
4735 BOOL dest_has_wcard = False;
4737 START_PROFILE(SMBmv);
4739 p = smb_buf(inbuf) + 1;
4740 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
4741 if (!NT_STATUS_IS_OK(status)) {
4742 END_PROFILE(SMBmv);
4743 return ERROR_NT(status);
4745 p++;
4746 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
4747 if (!NT_STATUS_IS_OK(status)) {
4748 END_PROFILE(SMBmv);
4749 return ERROR_NT(status);
4752 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
4753 if (!NT_STATUS_IS_OK(status)) {
4754 END_PROFILE(SMBmv);
4755 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4756 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4758 return ERROR_NT(status);
4761 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4762 if (!NT_STATUS_IS_OK(status)) {
4763 END_PROFILE(SMBmv);
4764 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4765 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4767 return ERROR_NT(status);
4770 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4772 status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
4773 if (!NT_STATUS_IS_OK(status)) {
4774 END_PROFILE(SMBmv);
4775 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4776 /* We have re-scheduled this call. */
4777 return -1;
4779 return ERROR_NT(status);
4782 outsize = set_message(inbuf,outbuf,0,0,False);
4784 END_PROFILE(SMBmv);
4785 return(outsize);
4788 /*******************************************************************
4789 Copy a file as part of a reply_copy.
4790 ******************************************************************/
4793 * TODO: check error codes on all callers
4796 NTSTATUS copy_file(connection_struct *conn,
4797 char *src,
4798 char *dest1,
4799 int ofun,
4800 int count,
4801 BOOL target_is_directory)
4803 SMB_STRUCT_STAT src_sbuf, sbuf2;
4804 SMB_OFF_T ret=-1;
4805 files_struct *fsp1,*fsp2;
4806 pstring dest;
4807 uint32 dosattrs;
4808 uint32 new_create_disposition;
4809 NTSTATUS status;
4811 pstrcpy(dest,dest1);
4812 if (target_is_directory) {
4813 char *p = strrchr_m(src,'/');
4814 if (p) {
4815 p++;
4816 } else {
4817 p = src;
4819 pstrcat(dest,"/");
4820 pstrcat(dest,p);
4823 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4824 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4827 if (!target_is_directory && count) {
4828 new_create_disposition = FILE_OPEN;
4829 } else {
4830 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4831 NULL, NULL, &new_create_disposition, NULL)) {
4832 return NT_STATUS_INVALID_PARAMETER;
4836 status = open_file_ntcreate(conn,src,&src_sbuf,
4837 FILE_GENERIC_READ,
4838 FILE_SHARE_READ|FILE_SHARE_WRITE,
4839 FILE_OPEN,
4841 FILE_ATTRIBUTE_NORMAL,
4842 INTERNAL_OPEN_ONLY,
4843 NULL, &fsp1);
4845 if (!NT_STATUS_IS_OK(status)) {
4846 return status;
4849 dosattrs = dos_mode(conn, src, &src_sbuf);
4850 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4851 ZERO_STRUCTP(&sbuf2);
4854 status = open_file_ntcreate(conn,dest,&sbuf2,
4855 FILE_GENERIC_WRITE,
4856 FILE_SHARE_READ|FILE_SHARE_WRITE,
4857 new_create_disposition,
4859 dosattrs,
4860 INTERNAL_OPEN_ONLY,
4861 NULL, &fsp2);
4863 if (!NT_STATUS_IS_OK(status)) {
4864 close_file(fsp1,ERROR_CLOSE);
4865 return status;
4868 if ((ofun&3) == 1) {
4869 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4870 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4872 * Stop the copy from occurring.
4874 ret = -1;
4875 src_sbuf.st_size = 0;
4879 if (src_sbuf.st_size) {
4880 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4883 close_file(fsp1,NORMAL_CLOSE);
4885 /* Ensure the modtime is set correctly on the destination file. */
4886 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
4889 * As we are opening fsp1 read-only we only expect
4890 * an error on close on fsp2 if we are out of space.
4891 * Thus we don't look at the error return from the
4892 * close of fsp1.
4894 status = close_file(fsp2,NORMAL_CLOSE);
4896 if (!NT_STATUS_IS_OK(status)) {
4897 return status;
4900 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4901 return NT_STATUS_DISK_FULL;
4904 return NT_STATUS_OK;
4907 /****************************************************************************
4908 Reply to a file copy.
4909 ****************************************************************************/
4911 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4913 int outsize = 0;
4914 pstring name;
4915 pstring directory;
4916 pstring mask,newname;
4917 char *p;
4918 int count=0;
4919 int error = ERRnoaccess;
4920 int err = 0;
4921 int tid2 = SVAL(inbuf,smb_vwv0);
4922 int ofun = SVAL(inbuf,smb_vwv1);
4923 int flags = SVAL(inbuf,smb_vwv2);
4924 BOOL target_is_directory=False;
4925 BOOL source_has_wild = False;
4926 BOOL dest_has_wild = False;
4927 SMB_STRUCT_STAT sbuf1, sbuf2;
4928 NTSTATUS status;
4929 START_PROFILE(SMBcopy);
4931 *directory = *mask = 0;
4933 p = smb_buf(inbuf);
4934 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
4935 if (!NT_STATUS_IS_OK(status)) {
4936 END_PROFILE(SMBcopy);
4937 return ERROR_NT(status);
4939 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
4940 if (!NT_STATUS_IS_OK(status)) {
4941 END_PROFILE(SMBcopy);
4942 return ERROR_NT(status);
4945 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4947 if (tid2 != conn->cnum) {
4948 /* can't currently handle inter share copies XXXX */
4949 DEBUG(3,("Rejecting inter-share copy\n"));
4950 END_PROFILE(SMBcopy);
4951 return ERROR_DOS(ERRSRV,ERRinvdevice);
4954 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
4955 if (!NT_STATUS_IS_OK(status)) {
4956 END_PROFILE(SMBcopy);
4957 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4958 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4960 return ERROR_NT(status);
4963 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
4964 if (!NT_STATUS_IS_OK(status)) {
4965 END_PROFILE(SMBcopy);
4966 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4967 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4969 return ERROR_NT(status);
4972 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
4973 if (!NT_STATUS_IS_OK(status)) {
4974 END_PROFILE(SMBcopy);
4975 return ERROR_NT(status);
4978 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
4979 if (!NT_STATUS_IS_OK(status)) {
4980 END_PROFILE(SMBcopy);
4981 return ERROR_NT(status);
4984 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4986 if ((flags&1) && target_is_directory) {
4987 END_PROFILE(SMBcopy);
4988 return ERROR_DOS(ERRDOS,ERRbadfile);
4991 if ((flags&2) && !target_is_directory) {
4992 END_PROFILE(SMBcopy);
4993 return ERROR_DOS(ERRDOS,ERRbadpath);
4996 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4997 /* wants a tree copy! XXXX */
4998 DEBUG(3,("Rejecting tree copy\n"));
4999 END_PROFILE(SMBcopy);
5000 return ERROR_DOS(ERRSRV,ERRerror);
5003 p = strrchr_m(name,'/');
5004 if (!p) {
5005 pstrcpy(directory,"./");
5006 pstrcpy(mask,name);
5007 } else {
5008 *p = 0;
5009 pstrcpy(directory,name);
5010 pstrcpy(mask,p+1);
5014 * We should only check the mangled cache
5015 * here if unix_convert failed. This means
5016 * that the path in 'mask' doesn't exist
5017 * on the file system and so we need to look
5018 * for a possible mangle. This patch from
5019 * Tine Smukavec <valentin.smukavec@hermes.si>.
5022 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5023 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5026 if (!source_has_wild) {
5027 pstrcat(directory,"/");
5028 pstrcat(directory,mask);
5029 if (dest_has_wild) {
5030 if (!resolve_wildcards(directory,newname)) {
5031 END_PROFILE(SMBcopy);
5032 return ERROR_NT(NT_STATUS_NO_MEMORY);
5036 status = check_name(conn, directory);
5037 if (!NT_STATUS_IS_OK(status)) {
5038 return ERROR_NT(status);
5041 status = check_name(conn, newname);
5042 if (!NT_STATUS_IS_OK(status)) {
5043 return ERROR_NT(status);
5046 status = copy_file(conn,directory,newname,ofun,
5047 count,target_is_directory);
5049 if(!NT_STATUS_IS_OK(status)) {
5050 END_PROFILE(SMBcopy);
5051 return ERROR_NT(status);
5052 } else {
5053 count++;
5055 } else {
5056 struct smb_Dir *dir_hnd = NULL;
5057 const char *dname;
5058 long offset = 0;
5059 pstring destname;
5061 if (strequal(mask,"????????.???"))
5062 pstrcpy(mask,"*");
5064 status = check_name(conn, directory);
5065 if (!NT_STATUS_IS_OK(status)) {
5066 return ERROR_NT(status);
5069 dir_hnd = OpenDir(conn, directory, mask, 0);
5070 if (dir_hnd == NULL) {
5071 status = map_nt_error_from_unix(errno);
5072 return ERROR_NT(status);
5075 error = ERRbadfile;
5077 while ((dname = ReadDirName(dir_hnd, &offset))) {
5078 pstring fname;
5079 pstrcpy(fname,dname);
5081 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5082 continue;
5085 if(!mask_match(fname, mask, conn->case_sensitive)) {
5086 continue;
5089 error = ERRnoaccess;
5090 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5091 pstrcpy(destname,newname);
5092 if (!resolve_wildcards(fname,destname)) {
5093 continue;
5096 status = check_name(conn, fname);
5097 if (!NT_STATUS_IS_OK(status)) {
5098 return ERROR_NT(status);
5101 status = check_name(conn, destname);
5102 if (!NT_STATUS_IS_OK(status)) {
5103 return ERROR_NT(status);
5106 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5108 status = copy_file(conn,fname,destname,ofun,
5109 count,target_is_directory);
5110 if (NT_STATUS_IS_OK(status)) {
5111 count++;
5114 CloseDir(dir_hnd);
5117 if (count == 0) {
5118 if(err) {
5119 /* Error on close... */
5120 errno = err;
5121 END_PROFILE(SMBcopy);
5122 return(UNIXERROR(ERRHRD,ERRgeneral));
5125 END_PROFILE(SMBcopy);
5126 return ERROR_DOS(ERRDOS,error);
5129 outsize = set_message(inbuf,outbuf,1,0,True);
5130 SSVAL(outbuf,smb_vwv0,count);
5132 END_PROFILE(SMBcopy);
5133 return(outsize);
5136 /****************************************************************************
5137 Reply to a setdir.
5138 ****************************************************************************/
5140 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5142 int snum;
5143 int outsize = 0;
5144 pstring newdir;
5145 NTSTATUS status;
5147 START_PROFILE(pathworks_setdir);
5149 snum = SNUM(conn);
5150 if (!CAN_SETDIR(snum)) {
5151 END_PROFILE(pathworks_setdir);
5152 return ERROR_DOS(ERRDOS,ERRnoaccess);
5155 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
5156 if (!NT_STATUS_IS_OK(status)) {
5157 END_PROFILE(pathworks_setdir);
5158 return ERROR_NT(status);
5161 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5162 if (!NT_STATUS_IS_OK(status)) {
5163 END_PROFILE(pathworks_setdir);
5164 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5165 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5167 return ERROR_NT(status);
5170 if (strlen(newdir) != 0) {
5171 if (!vfs_directory_exist(conn,newdir,NULL)) {
5172 END_PROFILE(pathworks_setdir);
5173 return ERROR_DOS(ERRDOS,ERRbadpath);
5175 set_conn_connectpath(conn,newdir);
5178 outsize = set_message(inbuf,outbuf,0,0,False);
5179 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5181 DEBUG(3,("setdir %s\n", newdir));
5183 END_PROFILE(pathworks_setdir);
5184 return(outsize);
5187 #undef DBGC_CLASS
5188 #define DBGC_CLASS DBGC_LOCKING
5190 /****************************************************************************
5191 Get a lock pid, dealing with large count requests.
5192 ****************************************************************************/
5194 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5196 if(!large_file_format)
5197 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5198 else
5199 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5202 /****************************************************************************
5203 Get a lock count, dealing with large count requests.
5204 ****************************************************************************/
5206 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5208 SMB_BIG_UINT count = 0;
5210 if(!large_file_format) {
5211 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5212 } else {
5214 #if defined(HAVE_LONGLONG)
5215 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5216 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5217 #else /* HAVE_LONGLONG */
5220 * NT4.x seems to be broken in that it sends large file (64 bit)
5221 * lockingX calls even if the CAP_LARGE_FILES was *not*
5222 * negotiated. For boxes without large unsigned ints truncate the
5223 * lock count by dropping the top 32 bits.
5226 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5227 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5228 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5229 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5230 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5233 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5234 #endif /* HAVE_LONGLONG */
5237 return count;
5240 #if !defined(HAVE_LONGLONG)
5241 /****************************************************************************
5242 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5243 ****************************************************************************/
5245 static uint32 map_lock_offset(uint32 high, uint32 low)
5247 unsigned int i;
5248 uint32 mask = 0;
5249 uint32 highcopy = high;
5252 * Try and find out how many significant bits there are in high.
5255 for(i = 0; highcopy; i++)
5256 highcopy >>= 1;
5259 * We use 31 bits not 32 here as POSIX
5260 * lock offsets may not be negative.
5263 mask = (~0) << (31 - i);
5265 if(low & mask)
5266 return 0; /* Fail. */
5268 high <<= (31 - i);
5270 return (high|low);
5272 #endif /* !defined(HAVE_LONGLONG) */
5274 /****************************************************************************
5275 Get a lock offset, dealing with large offset requests.
5276 ****************************************************************************/
5278 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5280 SMB_BIG_UINT offset = 0;
5282 *err = False;
5284 if(!large_file_format) {
5285 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5286 } else {
5288 #if defined(HAVE_LONGLONG)
5289 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5290 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5291 #else /* HAVE_LONGLONG */
5294 * NT4.x seems to be broken in that it sends large file (64 bit)
5295 * lockingX calls even if the CAP_LARGE_FILES was *not*
5296 * negotiated. For boxes without large unsigned ints mangle the
5297 * lock offset by mapping the top 32 bits onto the lower 32.
5300 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5301 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5302 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5303 uint32 new_low = 0;
5305 if((new_low = map_lock_offset(high, low)) == 0) {
5306 *err = True;
5307 return (SMB_BIG_UINT)-1;
5310 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5311 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5312 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5313 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5316 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5317 #endif /* HAVE_LONGLONG */
5320 return offset;
5323 /****************************************************************************
5324 Reply to a lockingX request.
5325 ****************************************************************************/
5327 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5328 int length, int bufsize)
5330 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5331 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5332 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5333 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5334 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5335 SMB_BIG_UINT count = 0, offset = 0;
5336 uint32 lock_pid;
5337 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5338 int i;
5339 char *data;
5340 BOOL large_file_format =
5341 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5342 BOOL err;
5343 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5345 START_PROFILE(SMBlockingX);
5347 CHECK_FSP(fsp,conn);
5349 data = smb_buf(inbuf);
5351 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5352 /* we don't support these - and CANCEL_LOCK makes w2k
5353 and XP reboot so I don't really want to be
5354 compatible! (tridge) */
5355 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5358 /* Check if this is an oplock break on a file
5359 we have granted an oplock on.
5361 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5362 /* Client can insist on breaking to none. */
5363 BOOL break_to_none = (oplocklevel == 0);
5364 BOOL result;
5366 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5367 "for fnum = %d\n", (unsigned int)oplocklevel,
5368 fsp->fnum ));
5371 * Make sure we have granted an exclusive or batch oplock on
5372 * this file.
5375 if (fsp->oplock_type == 0) {
5377 /* The Samba4 nbench simulator doesn't understand
5378 the difference between break to level2 and break
5379 to none from level2 - it sends oplock break
5380 replies in both cases. Don't keep logging an error
5381 message here - just ignore it. JRA. */
5383 DEBUG(5,("reply_lockingX: Error : oplock break from "
5384 "client for fnum = %d (oplock=%d) and no "
5385 "oplock granted on this file (%s).\n",
5386 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5388 /* if this is a pure oplock break request then don't
5389 * send a reply */
5390 if (num_locks == 0 && num_ulocks == 0) {
5391 END_PROFILE(SMBlockingX);
5392 return -1;
5393 } else {
5394 END_PROFILE(SMBlockingX);
5395 return ERROR_DOS(ERRDOS,ERRlock);
5399 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5400 (break_to_none)) {
5401 result = remove_oplock(fsp);
5402 } else {
5403 result = downgrade_oplock(fsp);
5406 if (!result) {
5407 DEBUG(0, ("reply_lockingX: error in removing "
5408 "oplock on file %s\n", fsp->fsp_name));
5409 /* Hmmm. Is this panic justified? */
5410 smb_panic("internal tdb error");
5413 reply_to_oplock_break_requests(fsp);
5415 /* if this is a pure oplock break request then don't send a
5416 * reply */
5417 if (num_locks == 0 && num_ulocks == 0) {
5418 /* Sanity check - ensure a pure oplock break is not a
5419 chained request. */
5420 if(CVAL(inbuf,smb_vwv0) != 0xff)
5421 DEBUG(0,("reply_lockingX: Error : pure oplock "
5422 "break is a chained %d request !\n",
5423 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5424 END_PROFILE(SMBlockingX);
5425 return -1;
5430 * We do this check *after* we have checked this is not a oplock break
5431 * response message. JRA.
5434 release_level_2_oplocks_on_change(fsp);
5436 /* Data now points at the beginning of the list
5437 of smb_unlkrng structs */
5438 for(i = 0; i < (int)num_ulocks; i++) {
5439 lock_pid = get_lock_pid( data, i, large_file_format);
5440 count = get_lock_count( data, i, large_file_format);
5441 offset = get_lock_offset( data, i, large_file_format, &err);
5444 * There is no error code marked "stupid client bug".... :-).
5446 if(err) {
5447 END_PROFILE(SMBlockingX);
5448 return ERROR_DOS(ERRDOS,ERRnoaccess);
5451 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5452 "pid %u, file %s\n", (double)offset, (double)count,
5453 (unsigned int)lock_pid, fsp->fsp_name ));
5455 status = do_unlock(smbd_messaging_context(),
5456 fsp,
5457 lock_pid,
5458 count,
5459 offset,
5460 WINDOWS_LOCK);
5462 if (NT_STATUS_V(status)) {
5463 END_PROFILE(SMBlockingX);
5464 return ERROR_NT(status);
5468 /* Setup the timeout in seconds. */
5470 if (!lp_blocking_locks(SNUM(conn))) {
5471 lock_timeout = 0;
5474 /* Now do any requested locks */
5475 data += ((large_file_format ? 20 : 10)*num_ulocks);
5477 /* Data now points at the beginning of the list
5478 of smb_lkrng structs */
5480 for(i = 0; i < (int)num_locks; i++) {
5481 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5482 READ_LOCK:WRITE_LOCK);
5483 lock_pid = get_lock_pid( data, i, large_file_format);
5484 count = get_lock_count( data, i, large_file_format);
5485 offset = get_lock_offset( data, i, large_file_format, &err);
5488 * There is no error code marked "stupid client bug".... :-).
5490 if(err) {
5491 END_PROFILE(SMBlockingX);
5492 return ERROR_DOS(ERRDOS,ERRnoaccess);
5495 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5496 "%u, file %s timeout = %d\n", (double)offset,
5497 (double)count, (unsigned int)lock_pid,
5498 fsp->fsp_name, (int)lock_timeout ));
5500 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5501 if (lp_blocking_locks(SNUM(conn))) {
5503 /* Schedule a message to ourselves to
5504 remove the blocking lock record and
5505 return the right error. */
5507 if (!blocking_lock_cancel(fsp,
5508 lock_pid,
5509 offset,
5510 count,
5511 WINDOWS_LOCK,
5512 locktype,
5513 NT_STATUS_FILE_LOCK_CONFLICT)) {
5514 END_PROFILE(SMBlockingX);
5515 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5518 /* Remove a matching pending lock. */
5519 status = do_lock_cancel(fsp,
5520 lock_pid,
5521 count,
5522 offset,
5523 WINDOWS_LOCK);
5524 } else {
5525 BOOL blocking_lock = lock_timeout ? True : False;
5526 BOOL defer_lock = False;
5527 struct byte_range_lock *br_lck;
5528 uint32 block_smbpid;
5530 br_lck = do_lock(smbd_messaging_context(),
5531 fsp,
5532 lock_pid,
5533 count,
5534 offset,
5535 lock_type,
5536 WINDOWS_LOCK,
5537 blocking_lock,
5538 &status,
5539 &block_smbpid);
5541 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5542 /* Windows internal resolution for blocking locks seems
5543 to be about 200ms... Don't wait for less than that. JRA. */
5544 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5545 lock_timeout = lp_lock_spin_time();
5547 defer_lock = True;
5550 /* This heuristic seems to match W2K3 very well. If a
5551 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5552 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5553 far as I can tell. Replacement for do_lock_spin(). JRA. */
5555 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5556 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5557 defer_lock = True;
5558 lock_timeout = lp_lock_spin_time();
5561 if (br_lck && defer_lock) {
5563 * A blocking lock was requested. Package up
5564 * this smb into a queued request and push it
5565 * onto the blocking lock queue.
5567 if(push_blocking_lock_request(br_lck,
5568 inbuf, length,
5569 fsp,
5570 lock_timeout,
5572 lock_pid,
5573 lock_type,
5574 WINDOWS_LOCK,
5575 offset,
5576 count,
5577 block_smbpid)) {
5578 TALLOC_FREE(br_lck);
5579 END_PROFILE(SMBlockingX);
5580 return -1;
5584 TALLOC_FREE(br_lck);
5587 if (NT_STATUS_V(status)) {
5588 END_PROFILE(SMBlockingX);
5589 return ERROR_NT(status);
5593 /* If any of the above locks failed, then we must unlock
5594 all of the previous locks (X/Open spec). */
5596 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5597 (i != num_locks) &&
5598 (num_locks != 0)) {
5600 * Ensure we don't do a remove on the lock that just failed,
5601 * as under POSIX rules, if we have a lock already there, we
5602 * will delete it (and we shouldn't) .....
5604 for(i--; i >= 0; i--) {
5605 lock_pid = get_lock_pid( data, i, large_file_format);
5606 count = get_lock_count( data, i, large_file_format);
5607 offset = get_lock_offset( data, i, large_file_format,
5608 &err);
5611 * There is no error code marked "stupid client
5612 * bug".... :-).
5614 if(err) {
5615 END_PROFILE(SMBlockingX);
5616 return ERROR_DOS(ERRDOS,ERRnoaccess);
5619 do_unlock(smbd_messaging_context(),
5620 fsp,
5621 lock_pid,
5622 count,
5623 offset,
5624 WINDOWS_LOCK);
5626 END_PROFILE(SMBlockingX);
5627 return ERROR_NT(status);
5630 set_message(inbuf,outbuf,2,0,True);
5632 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5633 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5635 END_PROFILE(SMBlockingX);
5636 return chain_reply(inbuf,outbuf,length,bufsize);
5639 #undef DBGC_CLASS
5640 #define DBGC_CLASS DBGC_ALL
5642 /****************************************************************************
5643 Reply to a SMBreadbmpx (read block multiplex) request.
5644 ****************************************************************************/
5646 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5648 ssize_t nread = -1;
5649 ssize_t total_read;
5650 char *data;
5651 SMB_OFF_T startpos;
5652 int outsize;
5653 size_t maxcount;
5654 int max_per_packet;
5655 size_t tcount;
5656 int pad;
5657 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5658 START_PROFILE(SMBreadBmpx);
5660 /* this function doesn't seem to work - disable by default */
5661 if (!lp_readbmpx()) {
5662 END_PROFILE(SMBreadBmpx);
5663 return ERROR_DOS(ERRSRV,ERRuseSTD);
5666 outsize = set_message(inbuf,outbuf,8,0,True);
5668 CHECK_FSP(fsp,conn);
5669 if (!CHECK_READ(fsp,inbuf)) {
5670 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5673 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5674 maxcount = SVAL(inbuf,smb_vwv3);
5676 data = smb_buf(outbuf);
5677 pad = ((long)data)%4;
5678 if (pad)
5679 pad = 4 - pad;
5680 data += pad;
5682 max_per_packet = bufsize-(outsize+pad);
5683 tcount = maxcount;
5684 total_read = 0;
5686 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5687 END_PROFILE(SMBreadBmpx);
5688 return ERROR_DOS(ERRDOS,ERRlock);
5691 do {
5692 size_t N = MIN(max_per_packet,tcount-total_read);
5694 nread = read_file(fsp,data,startpos,N);
5696 if (nread <= 0)
5697 nread = 0;
5699 if (nread < (ssize_t)N)
5700 tcount = total_read + nread;
5702 set_message(inbuf,outbuf,8,nread+pad,False);
5703 SIVAL(outbuf,smb_vwv0,startpos);
5704 SSVAL(outbuf,smb_vwv2,tcount);
5705 SSVAL(outbuf,smb_vwv6,nread);
5706 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5708 show_msg(outbuf);
5709 if (!send_smb(smbd_server_fd(),outbuf))
5710 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5712 total_read += nread;
5713 startpos += nread;
5714 } while (total_read < (ssize_t)tcount);
5716 END_PROFILE(SMBreadBmpx);
5717 return(-1);
5720 /****************************************************************************
5721 Reply to a SMBsetattrE.
5722 ****************************************************************************/
5724 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5726 struct timespec ts[2];
5727 int outsize = 0;
5728 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5729 START_PROFILE(SMBsetattrE);
5731 outsize = set_message(inbuf,outbuf,0,0,False);
5733 if(!fsp || (fsp->conn != conn)) {
5734 END_PROFILE(SMBsetattrE);
5735 return ERROR_DOS(ERRDOS,ERRbadfid);
5739 * Convert the DOS times into unix times. Ignore create
5740 * time as UNIX can't set this.
5743 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5744 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5747 * Patch from Ray Frush <frush@engr.colostate.edu>
5748 * Sometimes times are sent as zero - ignore them.
5751 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5752 /* Ignore request */
5753 if( DEBUGLVL( 3 ) ) {
5754 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5755 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5757 END_PROFILE(SMBsetattrE);
5758 return(outsize);
5759 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5760 /* set modify time = to access time if modify time was unset */
5761 ts[1] = ts[0];
5764 /* Set the date on this file */
5765 /* Should we set pending modtime here ? JRA */
5766 if(file_ntimes(conn, fsp->fsp_name, ts)) {
5767 END_PROFILE(SMBsetattrE);
5768 return ERROR_DOS(ERRDOS,ERRnoaccess);
5771 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5772 fsp->fnum,
5773 (unsigned int)ts[0].tv_sec,
5774 (unsigned int)ts[1].tv_sec));
5776 END_PROFILE(SMBsetattrE);
5777 return(outsize);
5781 /* Back from the dead for OS/2..... JRA. */
5783 /****************************************************************************
5784 Reply to a SMBwritebmpx (write block multiplex primary) request.
5785 ****************************************************************************/
5787 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5789 size_t numtowrite;
5790 ssize_t nwritten = -1;
5791 int outsize = 0;
5792 SMB_OFF_T startpos;
5793 size_t tcount;
5794 BOOL write_through;
5795 int smb_doff;
5796 char *data;
5797 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5798 NTSTATUS status;
5799 START_PROFILE(SMBwriteBmpx);
5801 CHECK_FSP(fsp,conn);
5802 if (!CHECK_WRITE(fsp)) {
5803 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5805 if (HAS_CACHED_ERROR(fsp)) {
5806 return(CACHED_ERROR(fsp));
5809 tcount = SVAL(inbuf,smb_vwv1);
5810 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5811 write_through = BITSETW(inbuf+smb_vwv7,0);
5812 numtowrite = SVAL(inbuf,smb_vwv10);
5813 smb_doff = SVAL(inbuf,smb_vwv11);
5815 data = smb_base(inbuf) + smb_doff;
5817 /* If this fails we need to send an SMBwriteC response,
5818 not an SMBwritebmpx - set this up now so we don't forget */
5819 SCVAL(outbuf,smb_com,SMBwritec);
5821 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5822 END_PROFILE(SMBwriteBmpx);
5823 return(ERROR_DOS(ERRDOS,ERRlock));
5826 nwritten = write_file(fsp,data,startpos,numtowrite);
5828 status = sync_file(conn, fsp, write_through);
5829 if (!NT_STATUS_IS_OK(status)) {
5830 END_PROFILE(SMBwriteBmpx);
5831 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
5832 fsp->fsp_name, nt_errstr(status) ));
5833 return ERROR_NT(status);
5836 if(nwritten < (ssize_t)numtowrite) {
5837 END_PROFILE(SMBwriteBmpx);
5838 return(UNIXERROR(ERRHRD,ERRdiskfull));
5841 /* If the maximum to be written to this file
5842 is greater than what we just wrote then set
5843 up a secondary struct to be attached to this
5844 fd, we will use this to cache error messages etc. */
5846 if((ssize_t)tcount > nwritten) {
5847 write_bmpx_struct *wbms;
5848 if(fsp->wbmpx_ptr != NULL)
5849 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5850 else
5851 wbms = SMB_MALLOC_P(write_bmpx_struct);
5852 if(!wbms) {
5853 DEBUG(0,("Out of memory in reply_readmpx\n"));
5854 END_PROFILE(SMBwriteBmpx);
5855 return(ERROR_DOS(ERRSRV,ERRnoresource));
5857 wbms->wr_mode = write_through;
5858 wbms->wr_discard = False; /* No errors yet */
5859 wbms->wr_total_written = nwritten;
5860 wbms->wr_errclass = 0;
5861 wbms->wr_error = 0;
5862 fsp->wbmpx_ptr = wbms;
5865 /* We are returning successfully, set the message type back to
5866 SMBwritebmpx */
5867 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5869 outsize = set_message(inbuf,outbuf,1,0,True);
5871 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5873 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5874 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5876 if (write_through && tcount==nwritten) {
5877 /* We need to send both a primary and a secondary response */
5878 smb_setlen(inbuf,outbuf,outsize - 4);
5879 show_msg(outbuf);
5880 if (!send_smb(smbd_server_fd(),outbuf))
5881 exit_server_cleanly("reply_writebmpx: send_smb failed.");
5883 /* Now the secondary */
5884 outsize = set_message(inbuf,outbuf,1,0,True);
5885 SCVAL(outbuf,smb_com,SMBwritec);
5886 SSVAL(outbuf,smb_vwv0,nwritten);
5889 END_PROFILE(SMBwriteBmpx);
5890 return(outsize);
5893 /****************************************************************************
5894 Reply to a SMBwritebs (write block multiplex secondary) request.
5895 ****************************************************************************/
5897 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5899 size_t numtowrite;
5900 ssize_t nwritten = -1;
5901 int outsize = 0;
5902 SMB_OFF_T startpos;
5903 size_t tcount;
5904 BOOL write_through;
5905 int smb_doff;
5906 char *data;
5907 write_bmpx_struct *wbms;
5908 BOOL send_response = False;
5909 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5910 NTSTATUS status;
5911 START_PROFILE(SMBwriteBs);
5913 CHECK_FSP(fsp,conn);
5914 if (!CHECK_WRITE(fsp)) {
5915 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5918 tcount = SVAL(inbuf,smb_vwv1);
5919 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5920 numtowrite = SVAL(inbuf,smb_vwv6);
5921 smb_doff = SVAL(inbuf,smb_vwv7);
5923 data = smb_base(inbuf) + smb_doff;
5925 /* We need to send an SMBwriteC response, not an SMBwritebs */
5926 SCVAL(outbuf,smb_com,SMBwritec);
5928 /* This fd should have an auxiliary struct attached,
5929 check that it does */
5930 wbms = fsp->wbmpx_ptr;
5931 if(!wbms) {
5932 END_PROFILE(SMBwriteBs);
5933 return(-1);
5936 /* If write through is set we can return errors, else we must cache them */
5937 write_through = wbms->wr_mode;
5939 /* Check for an earlier error */
5940 if(wbms->wr_discard) {
5941 END_PROFILE(SMBwriteBs);
5942 return -1; /* Just discard the packet */
5945 nwritten = write_file(fsp,data,startpos,numtowrite);
5947 status = sync_file(conn, fsp, write_through);
5949 if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
5950 if(write_through) {
5951 /* We are returning an error - we can delete the aux struct */
5952 if (wbms)
5953 free((char *)wbms);
5954 fsp->wbmpx_ptr = NULL;
5955 END_PROFILE(SMBwriteBs);
5956 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5958 wbms->wr_errclass = ERRHRD;
5959 wbms->wr_error = ERRdiskfull;
5960 wbms->wr_status = NT_STATUS_DISK_FULL;
5961 wbms->wr_discard = True;
5962 END_PROFILE(SMBwriteBs);
5963 return -1;
5966 /* Increment the total written, if this matches tcount
5967 we can discard the auxiliary struct (hurrah !) and return a writeC */
5968 wbms->wr_total_written += nwritten;
5969 if(wbms->wr_total_written >= tcount) {
5970 if (write_through) {
5971 outsize = set_message(inbuf,outbuf,1,0,True);
5972 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5973 send_response = True;
5976 free((char *)wbms);
5977 fsp->wbmpx_ptr = NULL;
5980 if(send_response) {
5981 END_PROFILE(SMBwriteBs);
5982 return(outsize);
5985 END_PROFILE(SMBwriteBs);
5986 return(-1);
5989 /****************************************************************************
5990 Reply to a SMBgetattrE.
5991 ****************************************************************************/
5993 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5995 SMB_STRUCT_STAT sbuf;
5996 int outsize = 0;
5997 int mode;
5998 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5999 START_PROFILE(SMBgetattrE);
6001 outsize = set_message(inbuf,outbuf,11,0,True);
6003 if(!fsp || (fsp->conn != conn)) {
6004 END_PROFILE(SMBgetattrE);
6005 return ERROR_DOS(ERRDOS,ERRbadfid);
6008 /* Do an fstat on this file */
6009 if(fsp_stat(fsp, &sbuf)) {
6010 END_PROFILE(SMBgetattrE);
6011 return(UNIXERROR(ERRDOS,ERRnoaccess));
6014 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6017 * Convert the times into dos times. Set create
6018 * date to be last modify date as UNIX doesn't save
6019 * this.
6022 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6023 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6024 /* Should we check pending modtime here ? JRA */
6025 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6027 if (mode & aDIR) {
6028 SIVAL(outbuf,smb_vwv6,0);
6029 SIVAL(outbuf,smb_vwv8,0);
6030 } else {
6031 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6032 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6033 SIVAL(outbuf,smb_vwv8,allocation_size);
6035 SSVAL(outbuf,smb_vwv10, mode);
6037 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6039 END_PROFILE(SMBgetattrE);
6040 return(outsize);