r21754: Volker is completely correct. There's no need for
[Samba/bb.git] / source / smbd / reply.c
blobf85f635d6b5f302eae1a756d63914f7dea331d03
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 NTSTATUS check_path_syntax_internal(pstring destname,
48 const pstring srcname,
49 BOOL windows_path,
50 BOOL *p_last_component_contains_wcard)
52 char *d = destname;
53 const char *s = srcname;
54 NTSTATUS ret = NT_STATUS_OK;
55 BOOL start_of_name_component = True;
57 *p_last_component_contains_wcard = False;
59 while (*s) {
60 if (IS_DIRECTORY_SEP(*s)) {
62 * Safe to assume is not the second part of a mb char
63 * as this is handled below.
65 /* Eat multiple '/' or '\\' */
66 while (IS_DIRECTORY_SEP(*s)) {
67 s++;
69 if ((d != destname) && (*s != '\0')) {
70 /* We only care about non-leading or trailing '/' or '\\' */
71 *d++ = '/';
74 start_of_name_component = True;
75 /* New component. */
76 *p_last_component_contains_wcard = False;
77 continue;
80 if (start_of_name_component) {
81 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
82 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
85 * No mb char starts with '.' so we're safe checking the directory separator here.
88 /* If we just added a '/' - delete it */
89 if ((d > destname) && (*(d-1) == '/')) {
90 *(d-1) = '\0';
91 d--;
94 /* Are we at the start ? Can't go back further if so. */
95 if (d <= destname) {
96 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
97 break;
99 /* Go back one level... */
100 /* We know this is safe as '/' cannot be part of a mb sequence. */
101 /* NOTE - if this assumption is invalid we are not in good shape... */
102 /* Decrement d first as d points to the *next* char to write into. */
103 for (d--; d > destname; d--) {
104 if (*d == '/')
105 break;
107 s += 2; /* Else go past the .. */
108 /* We're still at the start of a name component, just the previous one. */
109 continue;
111 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
112 if (!windows_path) {
113 /* Eat the '.' */
114 s++;
115 continue;
121 if (!(*s & 0x80)) {
122 if (windows_path) {
123 if (*s <= 0x1f) {
124 return NT_STATUS_OBJECT_NAME_INVALID;
126 switch (*s) {
127 case '*':
128 case '?':
129 case '<':
130 case '>':
131 case '"':
132 *p_last_component_contains_wcard = True;
133 break;
134 default:
135 break;
138 *d++ = *s++;
139 } else {
140 size_t siz;
141 /* Get the size of the next MB character. */
142 next_codepoint(s,&siz);
143 switch(siz) {
144 case 5:
145 *d++ = *s++;
146 /*fall through*/
147 case 4:
148 *d++ = *s++;
149 /*fall through*/
150 case 3:
151 *d++ = *s++;
152 /*fall through*/
153 case 2:
154 *d++ = *s++;
155 /*fall through*/
156 case 1:
157 *d++ = *s++;
158 break;
159 default:
160 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
161 *d = '\0';
162 return NT_STATUS_INVALID_PARAMETER;
165 start_of_name_component = False;
168 *d = '\0';
169 return ret;
172 /****************************************************************************
173 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
174 No wildcards allowed.
175 ****************************************************************************/
177 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
179 BOOL ignore;
180 return check_path_syntax_internal(destname, srcname, True, &ignore);
183 /****************************************************************************
184 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
185 Wildcards allowed - p_contains_wcard returns true if the last component contained
186 a wildcard.
187 ****************************************************************************/
189 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
191 return check_path_syntax_internal(destname, srcname, True, p_contains_wcard);
194 /****************************************************************************
195 Check the path for a POSIX client.
196 We're assuming here that '/' is not the second byte in any multibyte char
197 set (a safe assumption).
198 ****************************************************************************/
200 static NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
202 BOOL ignore;
203 return check_path_syntax_internal(destname, srcname, False, &ignore);
206 /****************************************************************************
207 Pull a string and check the path allowing a wilcard - provide for error return.
208 ****************************************************************************/
210 size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
211 NTSTATUS *err, BOOL *contains_wcard)
213 pstring tmppath;
214 char *tmppath_ptr = tmppath;
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, tmppath_ptr, src, dest_len, flags);
222 } else {
223 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
226 *contains_wcard = False;
228 if (lp_posix_pathnames()) {
229 *err = check_path_syntax_posix(dest, tmppath);
230 } else {
231 *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
234 return ret;
237 /****************************************************************************
238 Pull a string and check the path - provide for error return.
239 ****************************************************************************/
241 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
243 pstring tmppath;
244 char *tmppath_ptr = tmppath;
245 size_t ret;
246 #ifdef DEVELOPER
247 SMB_ASSERT(dest_len == sizeof(pstring));
248 #endif
250 if (src_len == 0) {
251 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
252 } else {
253 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
255 if (lp_posix_pathnames()) {
256 *err = check_path_syntax_posix(dest, tmppath);
257 } else {
258 *err = check_path_syntax(dest, tmppath);
261 return ret;
264 /****************************************************************************
265 Reply to a special message.
266 ****************************************************************************/
268 int reply_special(char *inbuf,char *outbuf)
270 int outsize = 4;
271 int msg_type = CVAL(inbuf,0);
272 int msg_flags = CVAL(inbuf,1);
273 fstring name1,name2;
274 char name_type = 0;
276 static BOOL already_got_session = False;
278 *name1 = *name2 = 0;
280 memset(outbuf,'\0',smb_size);
282 smb_setlen(outbuf,0);
284 switch (msg_type) {
285 case 0x81: /* session request */
287 if (already_got_session) {
288 exit_server_cleanly("multiple session request not permitted");
291 SCVAL(outbuf,0,0x82);
292 SCVAL(outbuf,3,0);
293 if (name_len(inbuf+4) > 50 ||
294 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
295 DEBUG(0,("Invalid name length in session request\n"));
296 return(0);
298 name_extract(inbuf,4,name1);
299 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
300 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
301 name1,name2));
303 set_local_machine_name(name1, True);
304 set_remote_machine_name(name2, True);
306 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
307 get_local_machine_name(), get_remote_machine_name(),
308 name_type));
310 if (name_type == 'R') {
311 /* We are being asked for a pathworks session ---
312 no thanks! */
313 SCVAL(outbuf, 0,0x83);
314 break;
317 /* only add the client's machine name to the list
318 of possibly valid usernames if we are operating
319 in share mode security */
320 if (lp_security() == SEC_SHARE) {
321 add_session_user(get_remote_machine_name());
324 reload_services(True);
325 reopen_logs();
327 already_got_session = True;
328 break;
330 case 0x89: /* session keepalive request
331 (some old clients produce this?) */
332 SCVAL(outbuf,0,SMBkeepalive);
333 SCVAL(outbuf,3,0);
334 break;
336 case 0x82: /* positive session response */
337 case 0x83: /* negative session response */
338 case 0x84: /* retarget session response */
339 DEBUG(0,("Unexpected session response\n"));
340 break;
342 case SMBkeepalive: /* session keepalive */
343 default:
344 return(0);
347 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
348 msg_type, msg_flags));
350 return(outsize);
353 /****************************************************************************
354 Reply to a tcon.
355 conn POINTER CAN BE NULL HERE !
356 ****************************************************************************/
358 int reply_tcon(connection_struct *conn,
359 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
361 const char *service;
362 pstring service_buf;
363 pstring password;
364 pstring dev;
365 int outsize = 0;
366 uint16 vuid = SVAL(inbuf,smb_uid);
367 int pwlen=0;
368 NTSTATUS nt_status;
369 char *p;
370 DATA_BLOB password_blob;
372 START_PROFILE(SMBtcon);
374 *service_buf = *password = *dev = 0;
376 p = smb_buf(inbuf)+1;
377 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
378 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
379 p += pwlen;
380 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
382 p = strrchr_m(service_buf,'\\');
383 if (p) {
384 service = p+1;
385 } else {
386 service = service_buf;
389 password_blob = data_blob(password, pwlen+1);
391 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
393 data_blob_clear_free(&password_blob);
395 if (!conn) {
396 END_PROFILE(SMBtcon);
397 return ERROR_NT(nt_status);
400 outsize = set_message(outbuf,2,0,True);
401 SSVAL(outbuf,smb_vwv0,max_recv);
402 SSVAL(outbuf,smb_vwv1,conn->cnum);
403 SSVAL(outbuf,smb_tid,conn->cnum);
405 DEBUG(3,("tcon service=%s cnum=%d\n",
406 service, conn->cnum));
408 END_PROFILE(SMBtcon);
409 return(outsize);
412 /****************************************************************************
413 Reply to a tcon and X.
414 conn POINTER CAN BE NULL HERE !
415 ****************************************************************************/
417 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
419 fstring service;
420 DATA_BLOB password;
422 /* what the cleint thinks the device is */
423 fstring client_devicetype;
424 /* what the server tells the client the share represents */
425 const char *server_devicetype;
426 NTSTATUS nt_status;
427 uint16 vuid = SVAL(inbuf,smb_uid);
428 int passlen = SVAL(inbuf,smb_vwv3);
429 pstring path;
430 char *p, *q;
432 START_PROFILE(SMBtconX);
434 *service = *client_devicetype = 0;
436 /* we might have to close an old one */
437 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
438 close_cnum(conn,vuid);
441 if (passlen > MAX_PASS_LEN) {
442 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
445 if (global_encrypted_passwords_negotiated) {
446 password = data_blob(smb_buf(inbuf),passlen);
447 } else {
448 password = data_blob(smb_buf(inbuf),passlen+1);
449 /* Ensure correct termination */
450 password.data[passlen]=0;
453 p = smb_buf(inbuf) + passlen;
454 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
457 * the service name can be either: \\server\share
458 * or share directly like on the DELL PowerVault 705
460 if (*path=='\\') {
461 q = strchr_m(path+2,'\\');
462 if (!q) {
463 END_PROFILE(SMBtconX);
464 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
466 fstrcpy(service,q+1);
468 else
469 fstrcpy(service,path);
471 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
473 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
475 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
477 data_blob_clear_free(&password);
479 if (!conn) {
480 END_PROFILE(SMBtconX);
481 return ERROR_NT(nt_status);
484 if ( IS_IPC(conn) )
485 server_devicetype = "IPC";
486 else if ( IS_PRINT(conn) )
487 server_devicetype = "LPT1:";
488 else
489 server_devicetype = "A:";
491 if (Protocol < PROTOCOL_NT1) {
492 set_message(outbuf,2,0,True);
493 p = smb_buf(outbuf);
494 p += srvstr_push(outbuf, p, server_devicetype, -1,
495 STR_TERMINATE|STR_ASCII);
496 set_message_end(outbuf,p);
497 } else {
498 /* NT sets the fstype of IPC$ to the null string */
499 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
501 set_message(outbuf,3,0,True);
503 p = smb_buf(outbuf);
504 p += srvstr_push(outbuf, p, server_devicetype, -1,
505 STR_TERMINATE|STR_ASCII);
506 p += srvstr_push(outbuf, p, fstype, -1,
507 STR_TERMINATE);
509 set_message_end(outbuf,p);
511 /* what does setting this bit do? It is set by NT4 and
512 may affect the ability to autorun mounted cdroms */
513 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
514 (lp_csc_policy(SNUM(conn)) << 2));
516 init_dfsroot(conn, inbuf, outbuf);
520 DEBUG(3,("tconX service=%s \n",
521 service));
523 /* set the incoming and outgoing tid to the just created one */
524 SSVAL(inbuf,smb_tid,conn->cnum);
525 SSVAL(outbuf,smb_tid,conn->cnum);
527 END_PROFILE(SMBtconX);
528 return chain_reply(inbuf,outbuf,length,bufsize);
531 /****************************************************************************
532 Reply to an unknown type.
533 ****************************************************************************/
535 int reply_unknown(char *inbuf,char *outbuf)
537 int type;
538 type = CVAL(inbuf,smb_com);
540 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
541 smb_fn_name(type), type, type));
543 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
546 /****************************************************************************
547 Reply to an ioctl.
548 conn POINTER CAN BE NULL HERE !
549 ****************************************************************************/
551 int reply_ioctl(connection_struct *conn,
552 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
554 uint16 device = SVAL(inbuf,smb_vwv1);
555 uint16 function = SVAL(inbuf,smb_vwv2);
556 uint32 ioctl_code = (device << 16) + function;
557 int replysize, outsize;
558 char *p;
559 START_PROFILE(SMBioctl);
561 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
563 switch (ioctl_code) {
564 case IOCTL_QUERY_JOB_INFO:
565 replysize = 32;
566 break;
567 default:
568 END_PROFILE(SMBioctl);
569 return(ERROR_DOS(ERRSRV,ERRnosupport));
572 outsize = set_message(outbuf,8,replysize+1,True);
573 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
574 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
575 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
576 p = smb_buf(outbuf) + 1; /* Allow for alignment */
578 switch (ioctl_code) {
579 case IOCTL_QUERY_JOB_INFO:
581 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
582 if (!fsp) {
583 END_PROFILE(SMBioctl);
584 return(UNIXERROR(ERRDOS,ERRbadfid));
586 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
587 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
588 if (conn) {
589 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
591 break;
595 END_PROFILE(SMBioctl);
596 return outsize;
599 /****************************************************************************
600 Strange checkpath NTSTATUS mapping.
601 ****************************************************************************/
603 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
605 /* Strange DOS error code semantics only for checkpath... */
606 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
607 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
608 /* We need to map to ERRbadpath */
609 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
612 return status;
615 /****************************************************************************
616 Reply to a checkpath.
617 ****************************************************************************/
619 int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
621 int outsize = 0;
622 pstring name;
623 SMB_STRUCT_STAT sbuf;
624 NTSTATUS status;
626 START_PROFILE(SMBcheckpath);
628 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
629 if (!NT_STATUS_IS_OK(status)) {
630 END_PROFILE(SMBcheckpath);
631 status = map_checkpath_error(inbuf, status);
632 return ERROR_NT(status);
635 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) {
636 END_PROFILE(SMBcheckpath);
637 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
640 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
642 status = unix_convert(conn, name, False, NULL, &sbuf);
643 if (!NT_STATUS_IS_OK(status)) {
644 goto path_err;
647 status = check_name(conn, name);
648 if (!NT_STATUS_IS_OK(status)) {
649 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
650 goto path_err;
653 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
654 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
655 status = map_nt_error_from_unix(errno);
656 goto path_err;
659 if (!S_ISDIR(sbuf.st_mode)) {
660 END_PROFILE(SMBcheckpath);
661 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
664 outsize = set_message(outbuf,0,0,False);
666 END_PROFILE(SMBcheckpath);
667 return outsize;
669 path_err:
671 END_PROFILE(SMBcheckpath);
673 /* We special case this - as when a Windows machine
674 is parsing a path is steps through the components
675 one at a time - if a component fails it expects
676 ERRbadpath, not ERRbadfile.
678 status = map_checkpath_error(inbuf, status);
679 if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
681 * Windows returns different error codes if
682 * the parent directory is valid but not the
683 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
684 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
685 * if the path is invalid.
687 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
690 return ERROR_NT(status);
693 /****************************************************************************
694 Reply to a getatr.
695 ****************************************************************************/
697 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
699 pstring fname;
700 int outsize = 0;
701 SMB_STRUCT_STAT sbuf;
702 int mode=0;
703 SMB_OFF_T size=0;
704 time_t mtime=0;
705 char *p;
706 NTSTATUS status;
708 START_PROFILE(SMBgetatr);
710 p = smb_buf(inbuf) + 1;
711 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
712 if (!NT_STATUS_IS_OK(status)) {
713 END_PROFILE(SMBgetatr);
714 return ERROR_NT(status);
717 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
718 END_PROFILE(SMBgetatr);
719 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
722 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
723 under WfWg - weird! */
724 if (*fname == '\0') {
725 mode = aHIDDEN | aDIR;
726 if (!CAN_WRITE(conn)) {
727 mode |= aRONLY;
729 size = 0;
730 mtime = 0;
731 } else {
732 status = unix_convert(conn, fname, False, NULL,&sbuf);
733 if (!NT_STATUS_IS_OK(status)) {
734 END_PROFILE(SMBgetatr);
735 return ERROR_NT(status);
737 status = check_name(conn, fname);
738 if (!NT_STATUS_IS_OK(status)) {
739 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
740 END_PROFILE(SMBgetatr);
741 return ERROR_NT(status);
743 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
744 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
745 return UNIXERROR(ERRDOS,ERRbadfile);
748 mode = dos_mode(conn,fname,&sbuf);
749 size = sbuf.st_size;
750 mtime = sbuf.st_mtime;
751 if (mode & aDIR) {
752 size = 0;
756 outsize = set_message(outbuf,10,0,True);
758 SSVAL(outbuf,smb_vwv0,mode);
759 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
760 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
761 } else {
762 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
764 SIVAL(outbuf,smb_vwv3,(uint32)size);
766 if (Protocol >= PROTOCOL_NT1) {
767 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
770 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
772 END_PROFILE(SMBgetatr);
773 return(outsize);
776 /****************************************************************************
777 Reply to a setatr.
778 ****************************************************************************/
780 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
782 pstring fname;
783 int outsize = 0;
784 int mode;
785 time_t mtime;
786 SMB_STRUCT_STAT sbuf;
787 char *p;
788 NTSTATUS status;
790 START_PROFILE(SMBsetatr);
792 p = smb_buf(inbuf) + 1;
793 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
794 if (!NT_STATUS_IS_OK(status)) {
795 END_PROFILE(SMBsetatr);
796 return ERROR_NT(status);
799 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
800 END_PROFILE(SMBsetatr);
801 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
804 status = unix_convert(conn, fname, False, NULL, &sbuf);
805 if (!NT_STATUS_IS_OK(status)) {
806 END_PROFILE(SMBsetatr);
807 return ERROR_NT(status);
810 status = check_name(conn, fname);
811 if (!NT_STATUS_IS_OK(status)) {
812 END_PROFILE(SMBsetatr);
813 return ERROR_NT(status);
816 if (fname[0] == '.' && fname[1] == '\0') {
818 * Not sure here is the right place to catch this
819 * condition. Might be moved to somewhere else later -- vl
821 END_PROFILE(SMBsetatr);
822 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
825 mode = SVAL(inbuf,smb_vwv0);
826 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
828 if (mode != FILE_ATTRIBUTE_NORMAL) {
829 if (VALID_STAT_OF_DIR(sbuf))
830 mode |= aDIR;
831 else
832 mode &= ~aDIR;
834 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
835 END_PROFILE(SMBsetatr);
836 return UNIXERROR(ERRDOS, ERRnoaccess);
840 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
841 END_PROFILE(SMBsetatr);
842 return UNIXERROR(ERRDOS, ERRnoaccess);
845 outsize = set_message(outbuf,0,0,False);
847 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
849 END_PROFILE(SMBsetatr);
850 return(outsize);
853 /****************************************************************************
854 Reply to a dskattr.
855 ****************************************************************************/
857 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
859 int outsize = 0;
860 SMB_BIG_UINT dfree,dsize,bsize;
861 START_PROFILE(SMBdskattr);
863 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
864 END_PROFILE(SMBdskattr);
865 return(UNIXERROR(ERRHRD,ERRgeneral));
868 outsize = set_message(outbuf,5,0,True);
870 if (Protocol <= PROTOCOL_LANMAN2) {
871 double total_space, free_space;
872 /* we need to scale this to a number that DOS6 can handle. We
873 use floating point so we can handle large drives on systems
874 that don't have 64 bit integers
876 we end up displaying a maximum of 2G to DOS systems
878 total_space = dsize * (double)bsize;
879 free_space = dfree * (double)bsize;
881 dsize = (total_space+63*512) / (64*512);
882 dfree = (free_space+63*512) / (64*512);
884 if (dsize > 0xFFFF) dsize = 0xFFFF;
885 if (dfree > 0xFFFF) dfree = 0xFFFF;
887 SSVAL(outbuf,smb_vwv0,dsize);
888 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
889 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
890 SSVAL(outbuf,smb_vwv3,dfree);
891 } else {
892 SSVAL(outbuf,smb_vwv0,dsize);
893 SSVAL(outbuf,smb_vwv1,bsize/512);
894 SSVAL(outbuf,smb_vwv2,512);
895 SSVAL(outbuf,smb_vwv3,dfree);
898 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
900 END_PROFILE(SMBdskattr);
901 return(outsize);
904 /****************************************************************************
905 Reply to a search.
906 Can be called from SMBsearch, SMBffirst or SMBfunique.
907 ****************************************************************************/
909 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
911 pstring mask;
912 pstring directory;
913 pstring fname;
914 SMB_OFF_T size;
915 uint32 mode;
916 time_t date;
917 uint32 dirtype;
918 int outsize = 0;
919 unsigned int numentries = 0;
920 unsigned int maxentries = 0;
921 BOOL finished = False;
922 char *p;
923 int status_len;
924 pstring path;
925 char status[21];
926 int dptr_num= -1;
927 BOOL check_descend = False;
928 BOOL expect_close = False;
929 NTSTATUS nt_status;
930 BOOL mask_contains_wcard = False;
931 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
933 START_PROFILE(SMBsearch);
935 if (lp_posix_pathnames()) {
936 END_PROFILE(SMBsearch);
937 return reply_unknown(inbuf, outbuf);
940 *mask = *directory = *fname = 0;
942 /* If we were called as SMBffirst then we must expect close. */
943 if(CVAL(inbuf,smb_com) == SMBffirst) {
944 expect_close = True;
947 outsize = set_message(outbuf,1,3,True);
948 maxentries = SVAL(inbuf,smb_vwv0);
949 dirtype = SVAL(inbuf,smb_vwv1);
950 p = smb_buf(inbuf) + 1;
951 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
952 if (!NT_STATUS_IS_OK(nt_status)) {
953 END_PROFILE(SMBsearch);
954 return ERROR_NT(nt_status);
957 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path)) {
958 END_PROFILE(SMBsearch);
959 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
962 p++;
963 status_len = SVAL(p, 0);
964 p += 2;
966 /* dirtype &= ~aDIR; */
968 if (status_len == 0) {
969 SMB_STRUCT_STAT sbuf;
970 pstring dir2;
972 pstrcpy(directory,path);
973 pstrcpy(dir2,path);
974 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
975 if (!NT_STATUS_IS_OK(nt_status)) {
976 END_PROFILE(SMBsearch);
977 return ERROR_NT(nt_status);
979 unix_format(dir2);
981 nt_status = check_name(conn, directory);
982 if (!NT_STATUS_IS_OK(nt_status)) {
983 END_PROFILE(SMBsearch);
984 return ERROR_NT(nt_status);
987 p = strrchr_m(dir2,'/');
988 if (p == NULL) {
989 pstrcpy(mask,dir2);
990 *dir2 = 0;
991 } else {
992 *p = 0;
993 pstrcpy(mask,p+1);
996 p = strrchr_m(directory,'/');
997 if (!p) {
998 *directory = 0;
999 } else {
1000 *p = 0;
1003 if (strlen(directory) == 0) {
1004 pstrcpy(directory,".");
1006 memset((char *)status,'\0',21);
1007 SCVAL(status,0,(dirtype & 0x1F));
1008 } else {
1009 int status_dirtype;
1011 memcpy(status,p,21);
1012 status_dirtype = CVAL(status,0) & 0x1F;
1013 if (status_dirtype != (dirtype & 0x1F)) {
1014 dirtype = status_dirtype;
1017 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1018 if (!conn->dirptr) {
1019 goto SearchEmpty;
1021 string_set(&conn->dirpath,dptr_path(dptr_num));
1022 pstrcpy(mask, dptr_wcard(dptr_num));
1025 p = smb_buf(outbuf) + 3;
1027 if (status_len == 0) {
1028 nt_status = dptr_create(conn,
1029 directory,
1030 True,
1031 expect_close,
1032 SVAL(inbuf,smb_pid),
1033 mask,
1034 mask_contains_wcard,
1035 dirtype,
1036 &conn->dirptr);
1037 if (!NT_STATUS_IS_OK(nt_status)) {
1038 return ERROR_NT(nt_status);
1040 dptr_num = dptr_dnum(conn->dirptr);
1041 } else {
1042 dirtype = dptr_attr(dptr_num);
1045 DEBUG(4,("dptr_num is %d\n",dptr_num));
1047 if ((dirtype&0x1F) == aVOLID) {
1048 memcpy(p,status,21);
1049 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1050 0,aVOLID,0,!allow_long_path_components);
1051 dptr_fill(p+12,dptr_num);
1052 if (dptr_zero(p+12) && (status_len==0)) {
1053 numentries = 1;
1054 } else {
1055 numentries = 0;
1057 p += DIR_STRUCT_SIZE;
1058 } else {
1059 unsigned int i;
1060 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1062 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1063 conn->dirpath,lp_dontdescend(SNUM(conn))));
1064 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1065 check_descend = True;
1068 for (i=numentries;(i<maxentries) && !finished;i++) {
1069 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1070 if (!finished) {
1071 memcpy(p,status,21);
1072 make_dir_struct(p,mask,fname,size, mode,date,
1073 !allow_long_path_components);
1074 if (!dptr_fill(p+12,dptr_num)) {
1075 break;
1077 numentries++;
1078 p += DIR_STRUCT_SIZE;
1083 SearchEmpty:
1085 /* If we were called as SMBffirst with smb_search_id == NULL
1086 and no entries were found then return error and close dirptr
1087 (X/Open spec) */
1089 if (numentries == 0) {
1090 dptr_close(&dptr_num);
1091 } else if(expect_close && status_len == 0) {
1092 /* Close the dptr - we know it's gone */
1093 dptr_close(&dptr_num);
1096 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1097 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1098 dptr_close(&dptr_num);
1101 if ((numentries == 0) && !mask_contains_wcard) {
1102 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1105 SSVAL(outbuf,smb_vwv0,numentries);
1106 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1107 SCVAL(smb_buf(outbuf),0,5);
1108 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1110 /* The replies here are never long name. */
1111 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1112 if (!allow_long_path_components) {
1113 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1116 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1117 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1119 outsize += DIR_STRUCT_SIZE*numentries;
1120 smb_setlen(outbuf,outsize - 4);
1122 if ((! *directory) && dptr_path(dptr_num))
1123 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1125 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1126 smb_fn_name(CVAL(inbuf,smb_com)),
1127 mask, directory, dirtype, numentries, maxentries ) );
1129 END_PROFILE(SMBsearch);
1130 return(outsize);
1133 /****************************************************************************
1134 Reply to a fclose (stop directory search).
1135 ****************************************************************************/
1137 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1139 int outsize = 0;
1140 int status_len;
1141 pstring path;
1142 char status[21];
1143 int dptr_num= -2;
1144 char *p;
1145 NTSTATUS err;
1146 BOOL path_contains_wcard = False;
1148 START_PROFILE(SMBfclose);
1150 if (lp_posix_pathnames()) {
1151 END_PROFILE(SMBfclose);
1152 return reply_unknown(inbuf, outbuf);
1155 outsize = set_message(outbuf,1,0,True);
1156 p = smb_buf(inbuf) + 1;
1157 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1158 if (!NT_STATUS_IS_OK(err)) {
1159 END_PROFILE(SMBfclose);
1160 return ERROR_NT(err);
1162 p++;
1163 status_len = SVAL(p,0);
1164 p += 2;
1166 if (status_len == 0) {
1167 END_PROFILE(SMBfclose);
1168 return ERROR_DOS(ERRSRV,ERRsrverror);
1171 memcpy(status,p,21);
1173 if(dptr_fetch(status+12,&dptr_num)) {
1174 /* Close the dptr - we know it's gone */
1175 dptr_close(&dptr_num);
1178 SSVAL(outbuf,smb_vwv0,0);
1180 DEBUG(3,("search close\n"));
1182 END_PROFILE(SMBfclose);
1183 return(outsize);
1186 /****************************************************************************
1187 Reply to an open.
1188 ****************************************************************************/
1190 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1192 pstring fname;
1193 int outsize = 0;
1194 uint32 fattr=0;
1195 SMB_OFF_T size = 0;
1196 time_t mtime=0;
1197 int info;
1198 SMB_STRUCT_STAT sbuf;
1199 files_struct *fsp;
1200 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1201 int deny_mode;
1202 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1203 uint32 access_mask;
1204 uint32 share_mode;
1205 uint32 create_disposition;
1206 uint32 create_options = 0;
1207 NTSTATUS status;
1208 START_PROFILE(SMBopen);
1210 deny_mode = SVAL(inbuf,smb_vwv0);
1212 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1213 if (!NT_STATUS_IS_OK(status)) {
1214 END_PROFILE(SMBopen);
1215 return ERROR_NT(status);
1218 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
1219 END_PROFILE(SMBopen);
1220 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1223 status = unix_convert(conn, fname, False, NULL, &sbuf);
1224 if (!NT_STATUS_IS_OK(status)) {
1225 END_PROFILE(SMBopen);
1226 return ERROR_NT(status);
1229 status = check_name(conn, fname);
1230 if (!NT_STATUS_IS_OK(status)) {
1231 END_PROFILE(SMBopen);
1232 return ERROR_NT(status);
1235 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1236 &access_mask, &share_mode, &create_disposition, &create_options)) {
1237 END_PROFILE(SMBopen);
1238 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1241 status = open_file_ntcreate(conn,fname,&sbuf,
1242 access_mask,
1243 share_mode,
1244 create_disposition,
1245 create_options,
1246 dos_attr,
1247 oplock_request,
1248 &info, &fsp);
1250 if (!NT_STATUS_IS_OK(status)) {
1251 END_PROFILE(SMBopen);
1252 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1253 /* We have re-scheduled this call. */
1254 return -1;
1256 return ERROR_NT(status);
1259 size = sbuf.st_size;
1260 fattr = dos_mode(conn,fname,&sbuf);
1261 mtime = sbuf.st_mtime;
1263 if (fattr & aDIR) {
1264 DEBUG(3,("attempt to open a directory %s\n",fname));
1265 close_file(fsp,ERROR_CLOSE);
1266 END_PROFILE(SMBopen);
1267 return ERROR_DOS(ERRDOS,ERRnoaccess);
1270 outsize = set_message(outbuf,7,0,True);
1271 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1272 SSVAL(outbuf,smb_vwv1,fattr);
1273 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1274 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1275 } else {
1276 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1278 SIVAL(outbuf,smb_vwv4,(uint32)size);
1279 SSVAL(outbuf,smb_vwv6,deny_mode);
1281 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1282 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1285 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1286 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1288 END_PROFILE(SMBopen);
1289 return(outsize);
1292 /****************************************************************************
1293 Reply to an open and X.
1294 ****************************************************************************/
1296 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1298 pstring fname;
1299 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1300 int deny_mode = SVAL(inbuf,smb_vwv3);
1301 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1302 /* Breakout the oplock request bits so we can set the
1303 reply bits separately. */
1304 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1305 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1306 int oplock_request = ex_oplock_request | core_oplock_request;
1307 #if 0
1308 int smb_sattr = SVAL(inbuf,smb_vwv4);
1309 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1310 #endif
1311 int smb_ofun = SVAL(inbuf,smb_vwv8);
1312 uint32 fattr=0;
1313 int mtime=0;
1314 SMB_STRUCT_STAT sbuf;
1315 int smb_action = 0;
1316 files_struct *fsp;
1317 NTSTATUS status;
1318 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1319 ssize_t retval = -1;
1320 uint32 access_mask;
1321 uint32 share_mode;
1322 uint32 create_disposition;
1323 uint32 create_options = 0;
1325 START_PROFILE(SMBopenX);
1327 /* If it's an IPC, pass off the pipe handler. */
1328 if (IS_IPC(conn)) {
1329 if (lp_nt_pipe_support()) {
1330 END_PROFILE(SMBopenX);
1331 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1332 } else {
1333 END_PROFILE(SMBopenX);
1334 return ERROR_DOS(ERRSRV,ERRaccess);
1338 /* XXXX we need to handle passed times, sattr and flags */
1339 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1340 if (!NT_STATUS_IS_OK(status)) {
1341 END_PROFILE(SMBopenX);
1342 return ERROR_NT(status);
1345 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
1346 END_PROFILE(SMBopenX);
1347 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1350 status = unix_convert(conn, fname, False, NULL, &sbuf);
1351 if (!NT_STATUS_IS_OK(status)) {
1352 END_PROFILE(SMBopenX);
1353 return ERROR_NT(status);
1356 status = check_name(conn, fname);
1357 if (!NT_STATUS_IS_OK(status)) {
1358 END_PROFILE(SMBopenX);
1359 return ERROR_NT(status);
1362 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1363 &access_mask,
1364 &share_mode,
1365 &create_disposition,
1366 &create_options)) {
1367 END_PROFILE(SMBopenX);
1368 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1371 status = open_file_ntcreate(conn,fname,&sbuf,
1372 access_mask,
1373 share_mode,
1374 create_disposition,
1375 create_options,
1376 smb_attr,
1377 oplock_request,
1378 &smb_action, &fsp);
1380 if (!NT_STATUS_IS_OK(status)) {
1381 END_PROFILE(SMBopenX);
1382 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1383 /* We have re-scheduled this call. */
1384 return -1;
1386 return ERROR_NT(status);
1389 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1390 if the file is truncated or created. */
1391 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1392 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1393 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1394 close_file(fsp,ERROR_CLOSE);
1395 END_PROFILE(SMBopenX);
1396 return ERROR_NT(NT_STATUS_DISK_FULL);
1398 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1399 if (retval < 0) {
1400 close_file(fsp,ERROR_CLOSE);
1401 END_PROFILE(SMBopenX);
1402 return ERROR_NT(NT_STATUS_DISK_FULL);
1404 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1407 fattr = dos_mode(conn,fname,&sbuf);
1408 mtime = sbuf.st_mtime;
1409 if (fattr & aDIR) {
1410 close_file(fsp,ERROR_CLOSE);
1411 END_PROFILE(SMBopenX);
1412 return ERROR_DOS(ERRDOS,ERRnoaccess);
1415 /* If the caller set the extended oplock request bit
1416 and we granted one (by whatever means) - set the
1417 correct bit for extended oplock reply.
1420 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1421 smb_action |= EXTENDED_OPLOCK_GRANTED;
1424 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1425 smb_action |= EXTENDED_OPLOCK_GRANTED;
1428 /* If the caller set the core oplock request bit
1429 and we granted one (by whatever means) - set the
1430 correct bit for core oplock reply.
1433 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1434 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1437 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1438 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1441 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1442 set_message(outbuf,19,0,True);
1443 } else {
1444 set_message(outbuf,15,0,True);
1446 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1447 SSVAL(outbuf,smb_vwv3,fattr);
1448 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1449 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1450 } else {
1451 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1453 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1454 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1455 SSVAL(outbuf,smb_vwv11,smb_action);
1457 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1458 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1461 END_PROFILE(SMBopenX);
1462 return chain_reply(inbuf,outbuf,length,bufsize);
1465 /****************************************************************************
1466 Reply to a SMBulogoffX.
1467 conn POINTER CAN BE NULL HERE !
1468 ****************************************************************************/
1470 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1472 uint16 vuid = SVAL(inbuf,smb_uid);
1473 user_struct *vuser = get_valid_user_struct(vuid);
1474 START_PROFILE(SMBulogoffX);
1476 if(vuser == 0)
1477 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1479 /* in user level security we are supposed to close any files
1480 open by this user */
1481 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1482 file_close_user(vuid);
1484 invalidate_vuid(vuid);
1486 set_message(outbuf,2,0,True);
1488 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1490 END_PROFILE(SMBulogoffX);
1491 return chain_reply(inbuf,outbuf,length,bufsize);
1494 /****************************************************************************
1495 Reply to a mknew or a create.
1496 ****************************************************************************/
1498 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1500 pstring fname;
1501 int com;
1502 int outsize = 0;
1503 uint32 fattr = SVAL(inbuf,smb_vwv0);
1504 struct timespec ts[2];
1505 files_struct *fsp;
1506 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1507 SMB_STRUCT_STAT sbuf;
1508 NTSTATUS status;
1509 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1510 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1511 uint32 create_disposition;
1512 uint32 create_options = 0;
1514 START_PROFILE(SMBcreate);
1516 com = SVAL(inbuf,smb_com);
1518 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1520 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1521 if (!NT_STATUS_IS_OK(status)) {
1522 END_PROFILE(SMBcreate);
1523 return ERROR_NT(status);
1526 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
1527 END_PROFILE(SMBcreate);
1528 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1531 status = unix_convert(conn, fname, False, NULL, &sbuf);
1532 if (!NT_STATUS_IS_OK(status)) {
1533 END_PROFILE(SMBcreate);
1534 return ERROR_NT(status);
1537 status = check_name(conn, fname);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 END_PROFILE(SMBcreate);
1540 return ERROR_NT(status);
1543 if (fattr & aVOLID) {
1544 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1547 if(com == SMBmknew) {
1548 /* We should fail if file exists. */
1549 create_disposition = FILE_CREATE;
1550 } else {
1551 /* Create if file doesn't exist, truncate if it does. */
1552 create_disposition = FILE_OVERWRITE_IF;
1555 /* Open file using ntcreate. */
1556 status = open_file_ntcreate(conn,fname,&sbuf,
1557 access_mask,
1558 share_mode,
1559 create_disposition,
1560 create_options,
1561 fattr,
1562 oplock_request,
1563 NULL, &fsp);
1565 if (!NT_STATUS_IS_OK(status)) {
1566 END_PROFILE(SMBcreate);
1567 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1568 /* We have re-scheduled this call. */
1569 return -1;
1571 return ERROR_NT(status);
1574 ts[0] = get_atimespec(&sbuf); /* atime. */
1575 file_ntimes(conn, fname, ts);
1577 outsize = set_message(outbuf,1,0,True);
1578 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1580 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1581 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1584 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1585 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1588 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1589 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1591 END_PROFILE(SMBcreate);
1592 return(outsize);
1595 /****************************************************************************
1596 Reply to a create temporary file.
1597 ****************************************************************************/
1599 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1601 pstring fname;
1602 int outsize = 0;
1603 uint32 fattr = SVAL(inbuf,smb_vwv0);
1604 files_struct *fsp;
1605 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1606 int tmpfd;
1607 SMB_STRUCT_STAT sbuf;
1608 char *p, *s;
1609 NTSTATUS status;
1610 unsigned int namelen;
1612 START_PROFILE(SMBctemp);
1614 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1615 if (!NT_STATUS_IS_OK(status)) {
1616 END_PROFILE(SMBctemp);
1617 return ERROR_NT(status);
1619 if (*fname) {
1620 pstrcat(fname,"/TMXXXXXX");
1621 } else {
1622 pstrcat(fname,"TMXXXXXX");
1625 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
1626 END_PROFILE(SMBctemp);
1627 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1630 status = unix_convert(conn, fname, False, NULL, &sbuf);
1631 if (!NT_STATUS_IS_OK(status)) {
1632 END_PROFILE(SMBctemp);
1633 return ERROR_NT(status);
1636 status = check_name(conn, fname);
1637 if (!NT_STATUS_IS_OK(status)) {
1638 END_PROFILE(SMBctemp);
1639 return ERROR_NT(status);
1642 tmpfd = smb_mkstemp(fname);
1643 if (tmpfd == -1) {
1644 END_PROFILE(SMBctemp);
1645 return(UNIXERROR(ERRDOS,ERRnoaccess));
1648 SMB_VFS_STAT(conn,fname,&sbuf);
1650 /* We should fail if file does not exist. */
1651 status = open_file_ntcreate(conn,fname,&sbuf,
1652 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1653 FILE_SHARE_READ|FILE_SHARE_WRITE,
1654 FILE_OPEN,
1656 fattr,
1657 oplock_request,
1658 NULL, &fsp);
1660 /* close fd from smb_mkstemp() */
1661 close(tmpfd);
1663 if (!NT_STATUS_IS_OK(status)) {
1664 END_PROFILE(SMBctemp);
1665 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1666 /* We have re-scheduled this call. */
1667 return -1;
1669 return ERROR_NT(status);
1672 outsize = set_message(outbuf,1,0,True);
1673 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1675 /* the returned filename is relative to the directory */
1676 s = strrchr_m(fname, '/');
1677 if (!s) {
1678 s = fname;
1679 } else {
1680 s++;
1683 p = smb_buf(outbuf);
1684 #if 0
1685 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1686 thing in the byte section. JRA */
1687 SSVALS(p, 0, -1); /* what is this? not in spec */
1688 #endif
1689 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1690 p += namelen;
1691 outsize = set_message_end(outbuf, p);
1693 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1694 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1697 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1698 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1701 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1702 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1703 (unsigned int)sbuf.st_mode ) );
1705 END_PROFILE(SMBctemp);
1706 return(outsize);
1709 /*******************************************************************
1710 Check if a user is allowed to rename a file.
1711 ********************************************************************/
1713 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1715 files_struct *fsp;
1716 uint32 fmode;
1717 NTSTATUS status;
1719 if (!CAN_WRITE(conn)) {
1720 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1723 fmode = dos_mode(conn,fname,pst);
1724 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1725 return NT_STATUS_NO_SUCH_FILE;
1728 if (S_ISDIR(pst->st_mode)) {
1729 return NT_STATUS_OK;
1732 status = open_file_ntcreate(conn, fname, pst,
1733 DELETE_ACCESS,
1734 FILE_SHARE_READ|FILE_SHARE_WRITE,
1735 FILE_OPEN,
1737 FILE_ATTRIBUTE_NORMAL,
1739 NULL, &fsp);
1741 if (!NT_STATUS_IS_OK(status)) {
1742 return status;
1744 close_file(fsp,NORMAL_CLOSE);
1745 return NT_STATUS_OK;
1748 /*******************************************************************
1749 Check if a user is allowed to delete a file.
1750 ********************************************************************/
1752 static NTSTATUS can_delete(connection_struct *conn, char *fname,
1753 uint32 dirtype, BOOL can_defer)
1755 SMB_STRUCT_STAT sbuf;
1756 uint32 fattr;
1757 files_struct *fsp;
1758 uint32 dirtype_orig = dirtype;
1759 NTSTATUS status;
1761 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1763 if (!CAN_WRITE(conn)) {
1764 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1767 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1768 return map_nt_error_from_unix(errno);
1771 fattr = dos_mode(conn,fname,&sbuf);
1773 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1774 dirtype = aDIR|aARCH|aRONLY;
1777 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1778 if (!dirtype) {
1779 return NT_STATUS_NO_SUCH_FILE;
1782 if (!dir_check_ftype(conn, fattr, dirtype)) {
1783 if (fattr & aDIR) {
1784 return NT_STATUS_FILE_IS_A_DIRECTORY;
1786 return NT_STATUS_NO_SUCH_FILE;
1789 if (dirtype_orig & 0x8000) {
1790 /* These will never be set for POSIX. */
1791 return NT_STATUS_NO_SUCH_FILE;
1794 #if 0
1795 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1796 return NT_STATUS_FILE_IS_A_DIRECTORY;
1799 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1800 return NT_STATUS_NO_SUCH_FILE;
1803 if (dirtype & 0xFF00) {
1804 /* These will never be set for POSIX. */
1805 return NT_STATUS_NO_SUCH_FILE;
1808 dirtype &= 0xFF;
1809 if (!dirtype) {
1810 return NT_STATUS_NO_SUCH_FILE;
1813 /* Can't delete a directory. */
1814 if (fattr & aDIR) {
1815 return NT_STATUS_FILE_IS_A_DIRECTORY;
1817 #endif
1819 #if 0 /* JRATEST */
1820 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1821 return NT_STATUS_OBJECT_NAME_INVALID;
1822 #endif /* JRATEST */
1824 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1826 On a Windows share, a file with read-only dosmode can be opened with
1827 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1828 fails with NT_STATUS_CANNOT_DELETE error.
1830 This semantic causes a problem that a user can not
1831 rename a file with read-only dosmode on a Samba share
1832 from a Windows command prompt (i.e. cmd.exe, but can rename
1833 from Windows Explorer).
1836 if (!lp_delete_readonly(SNUM(conn))) {
1837 if (fattr & aRONLY) {
1838 return NT_STATUS_CANNOT_DELETE;
1842 /* On open checks the open itself will check the share mode, so
1843 don't do it here as we'll get it wrong. */
1845 status = open_file_ntcreate(conn, fname, &sbuf,
1846 DELETE_ACCESS,
1847 FILE_SHARE_NONE,
1848 FILE_OPEN,
1850 FILE_ATTRIBUTE_NORMAL,
1851 can_defer ? 0 : INTERNAL_OPEN_ONLY,
1852 NULL, &fsp);
1854 if (NT_STATUS_IS_OK(status)) {
1855 close_file(fsp,NORMAL_CLOSE);
1857 return status;
1860 /****************************************************************************
1861 The guts of the unlink command, split out so it may be called by the NT SMB
1862 code.
1863 ****************************************************************************/
1865 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
1866 char *name, BOOL has_wild, BOOL can_defer)
1868 pstring directory;
1869 pstring mask;
1870 char *p;
1871 int count=0;
1872 NTSTATUS status = NT_STATUS_OK;
1873 SMB_STRUCT_STAT sbuf;
1875 *directory = *mask = 0;
1877 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1878 if (!NT_STATUS_IS_OK(status)) {
1879 return status;
1882 p = strrchr_m(name,'/');
1883 if (!p) {
1884 pstrcpy(directory,".");
1885 pstrcpy(mask,name);
1886 } else {
1887 *p = 0;
1888 pstrcpy(directory,name);
1889 pstrcpy(mask,p+1);
1893 * We should only check the mangled cache
1894 * here if unix_convert failed. This means
1895 * that the path in 'mask' doesn't exist
1896 * on the file system and so we need to look
1897 * for a possible mangle. This patch from
1898 * Tine Smukavec <valentin.smukavec@hermes.si>.
1901 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
1902 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
1904 if (!has_wild) {
1905 pstrcat(directory,"/");
1906 pstrcat(directory,mask);
1907 if (dirtype == 0) {
1908 dirtype = FILE_ATTRIBUTE_NORMAL;
1911 status = check_name(conn, directory);
1912 if (!NT_STATUS_IS_OK(status)) {
1913 return status;
1916 status = can_delete(conn,directory,dirtype,can_defer);
1917 if (!NT_STATUS_IS_OK(status)) {
1918 return status;
1921 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1922 count++;
1923 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1924 FILE_NOTIFY_CHANGE_FILE_NAME,
1925 directory);
1927 } else {
1928 struct smb_Dir *dir_hnd = NULL;
1929 long offset = 0;
1930 const char *dname;
1932 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
1933 return NT_STATUS_OBJECT_NAME_INVALID;
1936 if (strequal(mask,"????????.???")) {
1937 pstrcpy(mask,"*");
1940 status = check_name(conn, directory);
1941 if (!NT_STATUS_IS_OK(status)) {
1942 return status;
1945 dir_hnd = OpenDir(conn, directory, mask, dirtype);
1946 if (dir_hnd == NULL) {
1947 return map_nt_error_from_unix(errno);
1950 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1951 the pattern matches against the long name, otherwise the short name
1952 We don't implement this yet XXXX
1955 status = NT_STATUS_NO_SUCH_FILE;
1957 while ((dname = ReadDirName(dir_hnd, &offset))) {
1958 SMB_STRUCT_STAT st;
1959 pstring fname;
1960 pstrcpy(fname,dname);
1962 if (!is_visible_file(conn, directory, dname, &st, True)) {
1963 continue;
1966 /* Quick check for "." and ".." */
1967 if (fname[0] == '.') {
1968 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1969 continue;
1973 if(!mask_match(fname, mask, conn->case_sensitive)) {
1974 continue;
1977 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1979 status = check_name(conn, fname);
1980 if (!NT_STATUS_IS_OK(status)) {
1981 return status;
1984 status = can_delete(conn, fname, dirtype, can_defer);
1985 if (!NT_STATUS_IS_OK(status)) {
1986 continue;
1988 if (SMB_VFS_UNLINK(conn,fname) == 0) {
1989 count++;
1990 DEBUG(3,("unlink_internals: succesful unlink "
1991 "[%s]\n",fname));
1992 notify_fname(conn, NOTIFY_ACTION_REMOVED,
1993 FILE_NOTIFY_CHANGE_FILE_NAME,
1994 fname);
1998 CloseDir(dir_hnd);
2001 if (count == 0 && NT_STATUS_IS_OK(status)) {
2002 status = map_nt_error_from_unix(errno);
2005 return status;
2008 /****************************************************************************
2009 Reply to a unlink
2010 ****************************************************************************/
2012 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2013 int dum_buffsize)
2015 int outsize = 0;
2016 pstring name;
2017 uint32 dirtype;
2018 NTSTATUS status;
2019 BOOL path_contains_wcard = False;
2021 START_PROFILE(SMBunlink);
2023 dirtype = SVAL(inbuf,smb_vwv0);
2025 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
2026 if (!NT_STATUS_IS_OK(status)) {
2027 END_PROFILE(SMBunlink);
2028 return ERROR_NT(status);
2031 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) {
2032 END_PROFILE(SMBunlink);
2033 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
2036 DEBUG(3,("reply_unlink : %s\n",name));
2038 status = unlink_internals(conn, dirtype, name, path_contains_wcard,
2039 True);
2040 if (!NT_STATUS_IS_OK(status)) {
2041 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2042 /* We have re-scheduled this call. */
2043 return -1;
2045 return ERROR_NT(status);
2048 outsize = set_message(outbuf,0,0,False);
2050 END_PROFILE(SMBunlink);
2051 return outsize;
2054 /****************************************************************************
2055 Fail for readbraw.
2056 ****************************************************************************/
2058 static void fail_readraw(void)
2060 pstring errstr;
2061 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2062 strerror(errno) );
2063 exit_server_cleanly(errstr);
2066 #if defined(WITH_SENDFILE)
2067 /****************************************************************************
2068 Fake (read/write) sendfile. Returns -1 on read or write fail.
2069 ****************************************************************************/
2071 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2073 ssize_t ret=0;
2075 /* Paranioa check... */
2076 if (nread > bufsize) {
2077 fail_readraw();
2080 if (nread > 0) {
2081 ret = read_file(fsp,buf,startpos,nread);
2082 if (ret == -1) {
2083 return -1;
2087 /* If we had a short read, fill with zeros. */
2088 if (ret < nread) {
2089 memset(buf, '\0', nread - ret);
2092 if (write_data(smbd_server_fd(),buf,nread) != nread) {
2093 return -1;
2096 return (ssize_t)nread;
2098 #endif
2100 /****************************************************************************
2101 Use sendfile in readbraw.
2102 ****************************************************************************/
2104 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2105 ssize_t mincount, char *outbuf, int out_buffsize)
2107 ssize_t ret=0;
2109 #if defined(WITH_SENDFILE)
2111 * We can only use sendfile on a non-chained packet
2112 * but we can use on a non-oplocked file. tridge proved this
2113 * on a train in Germany :-). JRA.
2114 * reply_readbraw has already checked the length.
2117 if ( (chain_size == 0) && (nread > 0) &&
2118 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2119 DATA_BLOB header;
2121 _smb_setlen(outbuf,nread);
2122 header.data = (uint8 *)outbuf;
2123 header.length = 4;
2124 header.free = NULL;
2126 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2127 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2128 if (errno == ENOSYS) {
2129 goto normal_readbraw;
2133 * Special hack for broken Linux with no working sendfile. If we
2134 * return EINTR we sent the header but not the rest of the data.
2135 * Fake this up by doing read/write calls.
2137 if (errno == EINTR) {
2138 /* Ensure we don't do this again. */
2139 set_use_sendfile(SNUM(conn), False);
2140 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2142 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2143 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2144 fsp->fsp_name, strerror(errno) ));
2145 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2147 return;
2150 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2151 fsp->fsp_name, strerror(errno) ));
2152 exit_server_cleanly("send_file_readbraw sendfile failed");
2157 normal_readbraw:
2159 #endif
2161 if (nread > 0) {
2162 ret = read_file(fsp,outbuf+4,startpos,nread);
2163 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2164 if (ret < mincount)
2165 ret = 0;
2166 #else
2167 if (ret < nread)
2168 ret = 0;
2169 #endif
2172 _smb_setlen(outbuf,ret);
2173 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2174 fail_readraw();
2177 /****************************************************************************
2178 Reply to a readbraw (core+ protocol).
2179 ****************************************************************************/
2181 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2183 ssize_t maxcount,mincount;
2184 size_t nread = 0;
2185 SMB_OFF_T startpos;
2186 char *header = outbuf;
2187 files_struct *fsp;
2188 START_PROFILE(SMBreadbraw);
2190 if (srv_is_signing_active()) {
2191 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2195 * Special check if an oplock break has been issued
2196 * and the readraw request croses on the wire, we must
2197 * return a zero length response here.
2200 fsp = file_fsp(inbuf,smb_vwv0);
2202 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2204 * fsp could be NULL here so use the value from the packet. JRA.
2206 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2207 _smb_setlen(header,0);
2208 if (write_data(smbd_server_fd(),header,4) != 4)
2209 fail_readraw();
2210 END_PROFILE(SMBreadbraw);
2211 return(-1);
2214 CHECK_FSP(fsp,conn);
2216 flush_write_cache(fsp, READRAW_FLUSH);
2218 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2219 if(CVAL(inbuf,smb_wct) == 10) {
2221 * This is a large offset (64 bit) read.
2223 #ifdef LARGE_SMB_OFF_T
2225 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2227 #else /* !LARGE_SMB_OFF_T */
2230 * Ensure we haven't been sent a >32 bit offset.
2233 if(IVAL(inbuf,smb_vwv8) != 0) {
2234 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2235 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2236 _smb_setlen(header,0);
2237 if (write_data(smbd_server_fd(),header,4) != 4)
2238 fail_readraw();
2239 END_PROFILE(SMBreadbraw);
2240 return(-1);
2243 #endif /* LARGE_SMB_OFF_T */
2245 if(startpos < 0) {
2246 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2247 _smb_setlen(header,0);
2248 if (write_data(smbd_server_fd(),header,4) != 4)
2249 fail_readraw();
2250 END_PROFILE(SMBreadbraw);
2251 return(-1);
2254 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2255 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2257 /* ensure we don't overrun the packet size */
2258 maxcount = MIN(65535,maxcount);
2260 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2261 SMB_STRUCT_STAT st;
2262 SMB_OFF_T size = 0;
2264 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2265 size = st.st_size;
2268 if (startpos >= size) {
2269 nread = 0;
2270 } else {
2271 nread = MIN(maxcount,(size - startpos));
2275 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2276 if (nread < mincount)
2277 nread = 0;
2278 #endif
2280 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2281 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2283 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2285 DEBUG(5,("readbraw finished\n"));
2286 END_PROFILE(SMBreadbraw);
2287 return -1;
2290 #undef DBGC_CLASS
2291 #define DBGC_CLASS DBGC_LOCKING
2293 /****************************************************************************
2294 Reply to a lockread (core+ protocol).
2295 ****************************************************************************/
2297 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2299 ssize_t nread = -1;
2300 char *data;
2301 int outsize = 0;
2302 SMB_OFF_T startpos;
2303 size_t numtoread;
2304 NTSTATUS status;
2305 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2306 struct byte_range_lock *br_lck = NULL;
2307 START_PROFILE(SMBlockread);
2309 CHECK_FSP(fsp,conn);
2310 if (!CHECK_READ(fsp,inbuf)) {
2311 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2314 release_level_2_oplocks_on_change(fsp);
2316 numtoread = SVAL(inbuf,smb_vwv1);
2317 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2319 outsize = set_message(outbuf,5,3,True);
2320 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2321 data = smb_buf(outbuf) + 3;
2324 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2325 * protocol request that predates the read/write lock concept.
2326 * Thus instead of asking for a read lock here we need to ask
2327 * for a write lock. JRA.
2328 * Note that the requested lock size is unaffected by max_recv.
2331 br_lck = do_lock(fsp,
2332 (uint32)SVAL(inbuf,smb_pid),
2333 (SMB_BIG_UINT)numtoread,
2334 (SMB_BIG_UINT)startpos,
2335 WRITE_LOCK,
2336 WINDOWS_LOCK,
2337 False, /* Non-blocking lock. */
2338 &status);
2339 TALLOC_FREE(br_lck);
2341 if (NT_STATUS_V(status)) {
2342 END_PROFILE(SMBlockread);
2343 return ERROR_NT(status);
2347 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2350 if (numtoread > max_recv) {
2351 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2352 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2353 (unsigned int)numtoread, (unsigned int)max_recv ));
2354 numtoread = MIN(numtoread,max_recv);
2356 nread = read_file(fsp,data,startpos,numtoread);
2358 if (nread < 0) {
2359 END_PROFILE(SMBlockread);
2360 return(UNIXERROR(ERRDOS,ERRnoaccess));
2363 outsize += nread;
2364 SSVAL(outbuf,smb_vwv0,nread);
2365 SSVAL(outbuf,smb_vwv5,nread+3);
2366 SSVAL(smb_buf(outbuf),1,nread);
2368 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2369 fsp->fnum, (int)numtoread, (int)nread));
2371 END_PROFILE(SMBlockread);
2372 return(outsize);
2375 #undef DBGC_CLASS
2376 #define DBGC_CLASS DBGC_ALL
2378 /****************************************************************************
2379 Reply to a read.
2380 ****************************************************************************/
2382 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2384 size_t numtoread;
2385 ssize_t nread = 0;
2386 char *data;
2387 SMB_OFF_T startpos;
2388 int outsize = 0;
2389 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2390 START_PROFILE(SMBread);
2392 CHECK_FSP(fsp,conn);
2393 if (!CHECK_READ(fsp,inbuf)) {
2394 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2397 numtoread = SVAL(inbuf,smb_vwv1);
2398 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2400 outsize = set_message(outbuf,5,3,True);
2401 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2403 * The requested read size cannot be greater than max_recv. JRA.
2405 if (numtoread > max_recv) {
2406 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2407 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2408 (unsigned int)numtoread, (unsigned int)max_recv ));
2409 numtoread = MIN(numtoread,max_recv);
2412 data = smb_buf(outbuf) + 3;
2414 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2415 END_PROFILE(SMBread);
2416 return ERROR_DOS(ERRDOS,ERRlock);
2419 if (numtoread > 0)
2420 nread = read_file(fsp,data,startpos,numtoread);
2422 if (nread < 0) {
2423 END_PROFILE(SMBread);
2424 return(UNIXERROR(ERRDOS,ERRnoaccess));
2427 outsize += nread;
2428 SSVAL(outbuf,smb_vwv0,nread);
2429 SSVAL(outbuf,smb_vwv5,nread+3);
2430 SCVAL(smb_buf(outbuf),0,1);
2431 SSVAL(smb_buf(outbuf),1,nread);
2433 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2434 fsp->fnum, (int)numtoread, (int)nread ) );
2436 END_PROFILE(SMBread);
2437 return(outsize);
2440 /****************************************************************************
2441 Reply to a read and X - possibly using sendfile.
2442 ****************************************************************************/
2444 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2445 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2447 int outsize = 0;
2448 ssize_t nread = -1;
2449 char *data = smb_buf(outbuf);
2451 #if defined(WITH_SENDFILE)
2453 * We can only use sendfile on a non-chained packet
2454 * but we can use on a non-oplocked file. tridge proved this
2455 * on a train in Germany :-). JRA.
2458 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2459 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2460 SMB_STRUCT_STAT sbuf;
2461 DATA_BLOB header;
2463 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2464 return(UNIXERROR(ERRDOS,ERRnoaccess));
2466 if (startpos > sbuf.st_size)
2467 goto normal_read;
2469 if (smb_maxcnt > (sbuf.st_size - startpos))
2470 smb_maxcnt = (sbuf.st_size - startpos);
2472 if (smb_maxcnt == 0)
2473 goto normal_read;
2476 * Set up the packet header before send. We
2477 * assume here the sendfile will work (get the
2478 * correct amount of data).
2481 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2482 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2483 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2484 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2485 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2486 SCVAL(outbuf,smb_vwv0,0xFF);
2487 set_message(outbuf,12,smb_maxcnt,False);
2488 header.data = (uint8 *)outbuf;
2489 header.length = data - outbuf;
2490 header.free = NULL;
2492 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2493 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2494 if (errno == ENOSYS) {
2495 goto normal_read;
2499 * Special hack for broken Linux with no working sendfile. If we
2500 * return EINTR we sent the header but not the rest of the data.
2501 * Fake this up by doing read/write calls.
2504 if (errno == EINTR) {
2505 /* Ensure we don't do this again. */
2506 set_use_sendfile(SNUM(conn), False);
2507 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2509 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2510 len_outbuf - (data-outbuf))) == -1) {
2511 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2512 fsp->fsp_name, strerror(errno) ));
2513 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2515 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2516 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2517 /* Returning -1 here means successful sendfile. */
2518 return -1;
2521 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2522 fsp->fsp_name, strerror(errno) ));
2523 exit_server_cleanly("send_file_readX sendfile failed");
2526 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2527 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2528 /* Returning -1 here means successful sendfile. */
2529 return -1;
2532 normal_read:
2534 #endif
2536 nread = read_file(fsp,data,startpos,smb_maxcnt);
2538 if (nread < 0) {
2539 return(UNIXERROR(ERRDOS,ERRnoaccess));
2542 outsize = set_message(outbuf,12,nread,False);
2543 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2544 SSVAL(outbuf,smb_vwv5,nread);
2545 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2546 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2547 SSVAL(smb_buf(outbuf),-2,nread);
2549 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2550 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2552 /* Returning the number of bytes we want to send back - including header. */
2553 return outsize;
2556 /****************************************************************************
2557 Reply to a read and X.
2558 ****************************************************************************/
2560 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2562 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2563 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2564 ssize_t nread = -1;
2565 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2566 #if 0
2567 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2568 #endif
2570 START_PROFILE(SMBreadX);
2572 /* If it's an IPC, pass off the pipe handler. */
2573 if (IS_IPC(conn)) {
2574 END_PROFILE(SMBreadX);
2575 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2578 CHECK_FSP(fsp,conn);
2579 if (!CHECK_READ(fsp,inbuf)) {
2580 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2583 set_message(outbuf,12,0,True);
2585 if (global_client_caps & CAP_LARGE_READX) {
2586 if (SVAL(inbuf,smb_vwv7) == 1) {
2587 smb_maxcnt |= (1<<16);
2589 if (smb_maxcnt > BUFFER_SIZE) {
2590 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2591 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2592 END_PROFILE(SMBreadX);
2593 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2597 if(CVAL(inbuf,smb_wct) == 12) {
2598 #ifdef LARGE_SMB_OFF_T
2600 * This is a large offset (64 bit) read.
2602 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2604 #else /* !LARGE_SMB_OFF_T */
2607 * Ensure we haven't been sent a >32 bit offset.
2610 if(IVAL(inbuf,smb_vwv10) != 0) {
2611 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2612 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2613 END_PROFILE(SMBreadX);
2614 return ERROR_DOS(ERRDOS,ERRbadaccess);
2617 #endif /* LARGE_SMB_OFF_T */
2621 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2622 END_PROFILE(SMBreadX);
2623 return ERROR_DOS(ERRDOS,ERRlock);
2626 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2627 END_PROFILE(SMBreadX);
2628 return -1;
2631 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2632 if (nread != -1)
2633 nread = chain_reply(inbuf,outbuf,length,bufsize);
2635 END_PROFILE(SMBreadX);
2636 return nread;
2639 /****************************************************************************
2640 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2641 ****************************************************************************/
2643 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2645 ssize_t nwritten=0;
2646 ssize_t total_written=0;
2647 size_t numtowrite=0;
2648 size_t tcount;
2649 SMB_OFF_T startpos;
2650 char *data=NULL;
2651 BOOL write_through;
2652 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2653 int outsize = 0;
2654 START_PROFILE(SMBwritebraw);
2656 if (srv_is_signing_active()) {
2657 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2660 CHECK_FSP(fsp,conn);
2661 if (!CHECK_WRITE(fsp)) {
2662 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2665 tcount = IVAL(inbuf,smb_vwv1);
2666 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2667 write_through = BITSETW(inbuf+smb_vwv7,0);
2669 /* We have to deal with slightly different formats depending
2670 on whether we are using the core+ or lanman1.0 protocol */
2672 if(Protocol <= PROTOCOL_COREPLUS) {
2673 numtowrite = SVAL(smb_buf(inbuf),-2);
2674 data = smb_buf(inbuf);
2675 } else {
2676 numtowrite = SVAL(inbuf,smb_vwv10);
2677 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2680 /* force the error type */
2681 SCVAL(inbuf,smb_com,SMBwritec);
2682 SCVAL(outbuf,smb_com,SMBwritec);
2684 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2685 END_PROFILE(SMBwritebraw);
2686 return(ERROR_DOS(ERRDOS,ERRlock));
2689 if (numtowrite>0)
2690 nwritten = write_file(fsp,data,startpos,numtowrite);
2692 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2693 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2695 if (nwritten < (ssize_t)numtowrite) {
2696 END_PROFILE(SMBwritebraw);
2697 return(UNIXERROR(ERRHRD,ERRdiskfull));
2700 total_written = nwritten;
2702 /* Return a message to the redirector to tell it to send more bytes */
2703 SCVAL(outbuf,smb_com,SMBwritebraw);
2704 SSVALS(outbuf,smb_vwv0,-1);
2705 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2706 show_msg(outbuf);
2707 if (!send_smb(smbd_server_fd(),outbuf))
2708 exit_server_cleanly("reply_writebraw: send_smb failed.");
2710 /* Now read the raw data into the buffer and write it */
2711 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2712 exit_server_cleanly("secondary writebraw failed");
2715 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2716 numtowrite = smb_len(inbuf);
2718 /* Set up outbuf to return the correct return */
2719 outsize = set_message(outbuf,1,0,True);
2720 SCVAL(outbuf,smb_com,SMBwritec);
2722 if (numtowrite != 0) {
2724 if (numtowrite > BUFFER_SIZE) {
2725 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2726 (unsigned int)numtowrite ));
2727 exit_server_cleanly("secondary writebraw failed");
2730 if (tcount > nwritten+numtowrite) {
2731 DEBUG(3,("Client overestimated the write %d %d %d\n",
2732 (int)tcount,(int)nwritten,(int)numtowrite));
2735 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2736 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2737 strerror(errno) ));
2738 exit_server_cleanly("secondary writebraw failed");
2741 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2742 if (nwritten == -1) {
2743 END_PROFILE(SMBwritebraw);
2744 return(UNIXERROR(ERRHRD,ERRdiskfull));
2747 if (nwritten < (ssize_t)numtowrite) {
2748 SCVAL(outbuf,smb_rcls,ERRHRD);
2749 SSVAL(outbuf,smb_err,ERRdiskfull);
2752 if (nwritten > 0)
2753 total_written += nwritten;
2756 SSVAL(outbuf,smb_vwv0,total_written);
2758 sync_file(conn, fsp, write_through);
2760 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2761 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2763 /* we won't return a status if write through is not selected - this follows what WfWg does */
2764 END_PROFILE(SMBwritebraw);
2765 if (!write_through && total_written==tcount) {
2767 #if RABBIT_PELLET_FIX
2769 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2770 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2772 if (!send_keepalive(smbd_server_fd()))
2773 exit_server_cleanly("reply_writebraw: send of keepalive failed");
2774 #endif
2775 return(-1);
2778 return(outsize);
2781 #undef DBGC_CLASS
2782 #define DBGC_CLASS DBGC_LOCKING
2784 /****************************************************************************
2785 Reply to a writeunlock (core+).
2786 ****************************************************************************/
2788 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2789 int size, int dum_buffsize)
2791 ssize_t nwritten = -1;
2792 size_t numtowrite;
2793 SMB_OFF_T startpos;
2794 char *data;
2795 NTSTATUS status = NT_STATUS_OK;
2796 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2797 int outsize = 0;
2798 START_PROFILE(SMBwriteunlock);
2800 CHECK_FSP(fsp,conn);
2801 if (!CHECK_WRITE(fsp)) {
2802 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2805 numtowrite = SVAL(inbuf,smb_vwv1);
2806 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2807 data = smb_buf(inbuf) + 3;
2809 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2810 END_PROFILE(SMBwriteunlock);
2811 return ERROR_DOS(ERRDOS,ERRlock);
2814 /* The special X/Open SMB protocol handling of
2815 zero length writes is *NOT* done for
2816 this call */
2817 if(numtowrite == 0) {
2818 nwritten = 0;
2819 } else {
2820 nwritten = write_file(fsp,data,startpos,numtowrite);
2823 sync_file(conn, fsp, False /* write through */);
2825 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2826 END_PROFILE(SMBwriteunlock);
2827 return(UNIXERROR(ERRHRD,ERRdiskfull));
2830 if (numtowrite) {
2831 status = do_unlock(fsp,
2832 (uint32)SVAL(inbuf,smb_pid),
2833 (SMB_BIG_UINT)numtowrite,
2834 (SMB_BIG_UINT)startpos,
2835 WINDOWS_LOCK);
2837 if (NT_STATUS_V(status)) {
2838 END_PROFILE(SMBwriteunlock);
2839 return ERROR_NT(status);
2843 outsize = set_message(outbuf,1,0,True);
2845 SSVAL(outbuf,smb_vwv0,nwritten);
2847 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2848 fsp->fnum, (int)numtowrite, (int)nwritten));
2850 END_PROFILE(SMBwriteunlock);
2851 return outsize;
2854 #undef DBGC_CLASS
2855 #define DBGC_CLASS DBGC_ALL
2857 /****************************************************************************
2858 Reply to a write.
2859 ****************************************************************************/
2861 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2863 size_t numtowrite;
2864 ssize_t nwritten = -1;
2865 SMB_OFF_T startpos;
2866 char *data;
2867 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2868 int outsize = 0;
2869 START_PROFILE(SMBwrite);
2871 /* If it's an IPC, pass off the pipe handler. */
2872 if (IS_IPC(conn)) {
2873 END_PROFILE(SMBwrite);
2874 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2877 CHECK_FSP(fsp,conn);
2878 if (!CHECK_WRITE(fsp)) {
2879 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2882 numtowrite = SVAL(inbuf,smb_vwv1);
2883 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2884 data = smb_buf(inbuf) + 3;
2886 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2887 END_PROFILE(SMBwrite);
2888 return ERROR_DOS(ERRDOS,ERRlock);
2892 * X/Open SMB protocol says that if smb_vwv1 is
2893 * zero then the file size should be extended or
2894 * truncated to the size given in smb_vwv[2-3].
2897 if(numtowrite == 0) {
2899 * This is actually an allocate call, and set EOF. JRA.
2901 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2902 if (nwritten < 0) {
2903 END_PROFILE(SMBwrite);
2904 return ERROR_NT(NT_STATUS_DISK_FULL);
2906 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2907 if (nwritten < 0) {
2908 END_PROFILE(SMBwrite);
2909 return ERROR_NT(NT_STATUS_DISK_FULL);
2911 } else
2912 nwritten = write_file(fsp,data,startpos,numtowrite);
2914 sync_file(conn, fsp, False);
2916 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2917 END_PROFILE(SMBwrite);
2918 return(UNIXERROR(ERRHRD,ERRdiskfull));
2921 outsize = set_message(outbuf,1,0,True);
2923 SSVAL(outbuf,smb_vwv0,nwritten);
2925 if (nwritten < (ssize_t)numtowrite) {
2926 SCVAL(outbuf,smb_rcls,ERRHRD);
2927 SSVAL(outbuf,smb_err,ERRdiskfull);
2930 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2932 END_PROFILE(SMBwrite);
2933 return(outsize);
2936 /****************************************************************************
2937 Reply to a write and X.
2938 ****************************************************************************/
2940 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2942 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2943 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2944 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2945 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2946 ssize_t nwritten = -1;
2947 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2948 unsigned int smblen = smb_len(inbuf);
2949 char *data;
2950 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2951 START_PROFILE(SMBwriteX);
2953 /* If it's an IPC, pass off the pipe handler. */
2954 if (IS_IPC(conn)) {
2955 END_PROFILE(SMBwriteX);
2956 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2959 CHECK_FSP(fsp,conn);
2960 if (!CHECK_WRITE(fsp)) {
2961 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2964 set_message(outbuf,6,0,True);
2966 /* Deal with possible LARGE_WRITEX */
2967 if (large_writeX) {
2968 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2971 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2972 END_PROFILE(SMBwriteX);
2973 return ERROR_DOS(ERRDOS,ERRbadmem);
2976 data = smb_base(inbuf) + smb_doff;
2978 if(CVAL(inbuf,smb_wct) == 14) {
2979 #ifdef LARGE_SMB_OFF_T
2981 * This is a large offset (64 bit) write.
2983 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2985 #else /* !LARGE_SMB_OFF_T */
2988 * Ensure we haven't been sent a >32 bit offset.
2991 if(IVAL(inbuf,smb_vwv12) != 0) {
2992 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2993 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2994 END_PROFILE(SMBwriteX);
2995 return ERROR_DOS(ERRDOS,ERRbadaccess);
2998 #endif /* LARGE_SMB_OFF_T */
3001 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3002 END_PROFILE(SMBwriteX);
3003 return ERROR_DOS(ERRDOS,ERRlock);
3006 /* X/Open SMB protocol says that, unlike SMBwrite
3007 if the length is zero then NO truncation is
3008 done, just a write of zero. To truncate a file,
3009 use SMBwrite. */
3011 if(numtowrite == 0) {
3012 nwritten = 0;
3013 } else {
3015 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3016 fsp,data,startpos,numtowrite)) {
3017 END_PROFILE(SMBwriteX);
3018 return -1;
3021 nwritten = write_file(fsp,data,startpos,numtowrite);
3024 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3025 END_PROFILE(SMBwriteX);
3026 return(UNIXERROR(ERRHRD,ERRdiskfull));
3029 SSVAL(outbuf,smb_vwv2,nwritten);
3030 if (large_writeX)
3031 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3033 if (nwritten < (ssize_t)numtowrite) {
3034 SCVAL(outbuf,smb_rcls,ERRHRD);
3035 SSVAL(outbuf,smb_err,ERRdiskfull);
3038 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3039 fsp->fnum, (int)numtowrite, (int)nwritten));
3041 sync_file(conn, fsp, write_through);
3043 END_PROFILE(SMBwriteX);
3044 return chain_reply(inbuf,outbuf,length,bufsize);
3047 /****************************************************************************
3048 Reply to a lseek.
3049 ****************************************************************************/
3051 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3053 SMB_OFF_T startpos;
3054 SMB_OFF_T res= -1;
3055 int mode,umode;
3056 int outsize = 0;
3057 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3058 START_PROFILE(SMBlseek);
3060 CHECK_FSP(fsp,conn);
3062 flush_write_cache(fsp, SEEK_FLUSH);
3064 mode = SVAL(inbuf,smb_vwv1) & 3;
3065 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3066 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3068 switch (mode) {
3069 case 0:
3070 umode = SEEK_SET;
3071 res = startpos;
3072 break;
3073 case 1:
3074 umode = SEEK_CUR;
3075 res = fsp->fh->pos + startpos;
3076 break;
3077 case 2:
3078 umode = SEEK_END;
3079 break;
3080 default:
3081 umode = SEEK_SET;
3082 res = startpos;
3083 break;
3086 if (umode == SEEK_END) {
3087 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3088 if(errno == EINVAL) {
3089 SMB_OFF_T current_pos = startpos;
3090 SMB_STRUCT_STAT sbuf;
3092 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3093 END_PROFILE(SMBlseek);
3094 return(UNIXERROR(ERRDOS,ERRnoaccess));
3097 current_pos += sbuf.st_size;
3098 if(current_pos < 0)
3099 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3103 if(res == -1) {
3104 END_PROFILE(SMBlseek);
3105 return(UNIXERROR(ERRDOS,ERRnoaccess));
3109 fsp->fh->pos = res;
3111 outsize = set_message(outbuf,2,0,True);
3112 SIVAL(outbuf,smb_vwv0,res);
3114 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3115 fsp->fnum, (double)startpos, (double)res, mode));
3117 END_PROFILE(SMBlseek);
3118 return(outsize);
3121 /****************************************************************************
3122 Reply to a flush.
3123 ****************************************************************************/
3125 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3127 int outsize = set_message(outbuf,0,0,False);
3128 uint16 fnum = SVAL(inbuf,smb_vwv0);
3129 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3130 START_PROFILE(SMBflush);
3132 if (fnum != 0xFFFF)
3133 CHECK_FSP(fsp,conn);
3135 if (!fsp) {
3136 file_sync_all(conn);
3137 } else {
3138 sync_file(conn,fsp, True);
3141 DEBUG(3,("flush\n"));
3142 END_PROFILE(SMBflush);
3143 return(outsize);
3146 /****************************************************************************
3147 Reply to a exit.
3148 conn POINTER CAN BE NULL HERE !
3149 ****************************************************************************/
3151 int reply_exit(connection_struct *conn,
3152 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3154 int outsize;
3155 START_PROFILE(SMBexit);
3157 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3159 outsize = set_message(outbuf,0,0,False);
3161 DEBUG(3,("exit\n"));
3163 END_PROFILE(SMBexit);
3164 return(outsize);
3167 /****************************************************************************
3168 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3169 ****************************************************************************/
3171 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3172 int dum_buffsize)
3174 NTSTATUS status = NT_STATUS_OK;
3175 int outsize = 0;
3176 files_struct *fsp = NULL;
3177 START_PROFILE(SMBclose);
3179 outsize = set_message(outbuf,0,0,False);
3181 /* If it's an IPC, pass off to the pipe handler. */
3182 if (IS_IPC(conn)) {
3183 END_PROFILE(SMBclose);
3184 return reply_pipe_close(conn, inbuf,outbuf);
3187 fsp = file_fsp(inbuf,smb_vwv0);
3190 * We can only use CHECK_FSP if we know it's not a directory.
3193 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3194 END_PROFILE(SMBclose);
3195 return ERROR_DOS(ERRDOS,ERRbadfid);
3198 if(fsp->is_directory) {
3200 * Special case - close NT SMB directory handle.
3202 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3203 status = close_file(fsp,NORMAL_CLOSE);
3204 } else {
3206 * Close ordinary file.
3209 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3210 fsp->fh->fd, fsp->fnum,
3211 conn->num_files_open));
3214 * Take care of any time sent in the close.
3217 fsp_set_pending_modtime(fsp,
3218 convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
3221 * close_file() returns the unix errno if an error
3222 * was detected on close - normally this is due to
3223 * a disk full error. If not then it was probably an I/O error.
3226 status = close_file(fsp,NORMAL_CLOSE);
3229 if(!NT_STATUS_IS_OK(status)) {
3230 END_PROFILE(SMBclose);
3231 return ERROR_NT(status);
3234 END_PROFILE(SMBclose);
3235 return(outsize);
3238 /****************************************************************************
3239 Reply to a writeclose (Core+ protocol).
3240 ****************************************************************************/
3242 int reply_writeclose(connection_struct *conn,
3243 char *inbuf,char *outbuf, int size, int dum_buffsize)
3245 size_t numtowrite;
3246 ssize_t nwritten = -1;
3247 int outsize = 0;
3248 NTSTATUS close_status = NT_STATUS_OK;
3249 SMB_OFF_T startpos;
3250 char *data;
3251 struct timespec mtime;
3252 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3253 START_PROFILE(SMBwriteclose);
3255 CHECK_FSP(fsp,conn);
3256 if (!CHECK_WRITE(fsp)) {
3257 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3260 numtowrite = SVAL(inbuf,smb_vwv1);
3261 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3262 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3263 data = smb_buf(inbuf) + 1;
3265 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3266 END_PROFILE(SMBwriteclose);
3267 return ERROR_DOS(ERRDOS,ERRlock);
3270 nwritten = write_file(fsp,data,startpos,numtowrite);
3272 set_filetime(conn, fsp->fsp_name, mtime);
3275 * More insanity. W2K only closes the file if writelen > 0.
3276 * JRA.
3279 if (numtowrite) {
3280 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3281 fsp->fsp_name ));
3282 close_status = close_file(fsp,NORMAL_CLOSE);
3285 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3286 fsp->fnum, (int)numtowrite, (int)nwritten,
3287 conn->num_files_open));
3289 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3290 END_PROFILE(SMBwriteclose);
3291 return(UNIXERROR(ERRHRD,ERRdiskfull));
3294 if(!NT_STATUS_IS_OK(close_status)) {
3295 END_PROFILE(SMBwriteclose);
3296 return ERROR_NT(close_status);
3299 outsize = set_message(outbuf,1,0,True);
3301 SSVAL(outbuf,smb_vwv0,nwritten);
3302 END_PROFILE(SMBwriteclose);
3303 return(outsize);
3306 #undef DBGC_CLASS
3307 #define DBGC_CLASS DBGC_LOCKING
3309 /****************************************************************************
3310 Reply to a lock.
3311 ****************************************************************************/
3313 int reply_lock(connection_struct *conn,
3314 char *inbuf,char *outbuf, int length, int dum_buffsize)
3316 int outsize = set_message(outbuf,0,0,False);
3317 SMB_BIG_UINT count,offset;
3318 NTSTATUS status;
3319 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3320 struct byte_range_lock *br_lck = NULL;
3322 START_PROFILE(SMBlock);
3324 CHECK_FSP(fsp,conn);
3326 release_level_2_oplocks_on_change(fsp);
3328 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3329 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3331 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3332 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3334 br_lck = do_lock(fsp,
3335 (uint32)SVAL(inbuf,smb_pid),
3336 count,
3337 offset,
3338 WRITE_LOCK,
3339 WINDOWS_LOCK,
3340 False, /* Non-blocking lock. */
3341 &status);
3343 TALLOC_FREE(br_lck);
3345 if (NT_STATUS_V(status)) {
3346 END_PROFILE(SMBlock);
3347 return ERROR_NT(status);
3350 END_PROFILE(SMBlock);
3351 return(outsize);
3354 /****************************************************************************
3355 Reply to a unlock.
3356 ****************************************************************************/
3358 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3359 int dum_buffsize)
3361 int outsize = set_message(outbuf,0,0,False);
3362 SMB_BIG_UINT count,offset;
3363 NTSTATUS status;
3364 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3365 START_PROFILE(SMBunlock);
3367 CHECK_FSP(fsp,conn);
3369 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3370 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3372 status = do_unlock(fsp,
3373 (uint32)SVAL(inbuf,smb_pid),
3374 count,
3375 offset,
3376 WINDOWS_LOCK);
3378 if (NT_STATUS_V(status)) {
3379 END_PROFILE(SMBunlock);
3380 return ERROR_NT(status);
3383 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3384 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3386 END_PROFILE(SMBunlock);
3387 return(outsize);
3390 #undef DBGC_CLASS
3391 #define DBGC_CLASS DBGC_ALL
3393 /****************************************************************************
3394 Reply to a tdis.
3395 conn POINTER CAN BE NULL HERE !
3396 ****************************************************************************/
3398 int reply_tdis(connection_struct *conn,
3399 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3401 int outsize = set_message(outbuf,0,0,False);
3402 uint16 vuid;
3403 START_PROFILE(SMBtdis);
3405 vuid = SVAL(inbuf,smb_uid);
3407 if (!conn) {
3408 DEBUG(4,("Invalid connection in tdis\n"));
3409 END_PROFILE(SMBtdis);
3410 return ERROR_DOS(ERRSRV,ERRinvnid);
3413 conn->used = False;
3415 close_cnum(conn,vuid);
3417 END_PROFILE(SMBtdis);
3418 return outsize;
3421 /****************************************************************************
3422 Reply to a echo.
3423 conn POINTER CAN BE NULL HERE !
3424 ****************************************************************************/
3426 int reply_echo(connection_struct *conn,
3427 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3429 int smb_reverb = SVAL(inbuf,smb_vwv0);
3430 int seq_num;
3431 unsigned int data_len = smb_buflen(inbuf);
3432 int outsize = set_message(outbuf,1,data_len,True);
3433 START_PROFILE(SMBecho);
3435 if (data_len > BUFFER_SIZE) {
3436 DEBUG(0,("reply_echo: data_len too large.\n"));
3437 END_PROFILE(SMBecho);
3438 return -1;
3441 /* copy any incoming data back out */
3442 if (data_len > 0)
3443 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3445 if (smb_reverb > 100) {
3446 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3447 smb_reverb = 100;
3450 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3451 SSVAL(outbuf,smb_vwv0,seq_num);
3453 smb_setlen(outbuf,outsize - 4);
3455 show_msg(outbuf);
3456 if (!send_smb(smbd_server_fd(),outbuf))
3457 exit_server_cleanly("reply_echo: send_smb failed.");
3460 DEBUG(3,("echo %d times\n", smb_reverb));
3462 smb_echo_count++;
3464 END_PROFILE(SMBecho);
3465 return -1;
3468 /****************************************************************************
3469 Reply to a printopen.
3470 ****************************************************************************/
3472 int reply_printopen(connection_struct *conn,
3473 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3475 int outsize = 0;
3476 files_struct *fsp;
3477 NTSTATUS status;
3479 START_PROFILE(SMBsplopen);
3481 if (!CAN_PRINT(conn)) {
3482 END_PROFILE(SMBsplopen);
3483 return ERROR_DOS(ERRDOS,ERRnoaccess);
3486 /* Open for exclusive use, write only. */
3487 status = print_fsp_open(conn, NULL, &fsp);
3489 if (!NT_STATUS_IS_OK(status)) {
3490 END_PROFILE(SMBsplopen);
3491 return(ERROR_NT(status));
3494 outsize = set_message(outbuf,1,0,True);
3495 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3497 DEBUG(3,("openprint fd=%d fnum=%d\n",
3498 fsp->fh->fd, fsp->fnum));
3500 END_PROFILE(SMBsplopen);
3501 return(outsize);
3504 /****************************************************************************
3505 Reply to a printclose.
3506 ****************************************************************************/
3508 int reply_printclose(connection_struct *conn,
3509 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3511 int outsize = set_message(outbuf,0,0,False);
3512 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3513 NTSTATUS status;
3514 START_PROFILE(SMBsplclose);
3516 CHECK_FSP(fsp,conn);
3518 if (!CAN_PRINT(conn)) {
3519 END_PROFILE(SMBsplclose);
3520 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3523 DEBUG(3,("printclose fd=%d fnum=%d\n",
3524 fsp->fh->fd,fsp->fnum));
3526 status = close_file(fsp,NORMAL_CLOSE);
3528 if(!NT_STATUS_IS_OK(status)) {
3529 END_PROFILE(SMBsplclose);
3530 return ERROR_NT(status);
3533 END_PROFILE(SMBsplclose);
3534 return(outsize);
3537 /****************************************************************************
3538 Reply to a printqueue.
3539 ****************************************************************************/
3541 int reply_printqueue(connection_struct *conn,
3542 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3544 int outsize = set_message(outbuf,2,3,True);
3545 int max_count = SVAL(inbuf,smb_vwv0);
3546 int start_index = SVAL(inbuf,smb_vwv1);
3547 START_PROFILE(SMBsplretq);
3549 /* we used to allow the client to get the cnum wrong, but that
3550 is really quite gross and only worked when there was only
3551 one printer - I think we should now only accept it if they
3552 get it right (tridge) */
3553 if (!CAN_PRINT(conn)) {
3554 END_PROFILE(SMBsplretq);
3555 return ERROR_DOS(ERRDOS,ERRnoaccess);
3558 SSVAL(outbuf,smb_vwv0,0);
3559 SSVAL(outbuf,smb_vwv1,0);
3560 SCVAL(smb_buf(outbuf),0,1);
3561 SSVAL(smb_buf(outbuf),1,0);
3563 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3564 start_index, max_count));
3567 print_queue_struct *queue = NULL;
3568 print_status_struct status;
3569 char *p = smb_buf(outbuf) + 3;
3570 int count = print_queue_status(SNUM(conn), &queue, &status);
3571 int num_to_get = ABS(max_count);
3572 int first = (max_count>0?start_index:start_index+max_count+1);
3573 int i;
3575 if (first >= count)
3576 num_to_get = 0;
3577 else
3578 num_to_get = MIN(num_to_get,count-first);
3581 for (i=first;i<first+num_to_get;i++) {
3582 srv_put_dos_date2(p,0,queue[i].time);
3583 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3584 SSVAL(p,5, queue[i].job);
3585 SIVAL(p,7,queue[i].size);
3586 SCVAL(p,11,0);
3587 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3588 p += 28;
3591 if (count > 0) {
3592 outsize = set_message(outbuf,2,28*count+3,False);
3593 SSVAL(outbuf,smb_vwv0,count);
3594 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3595 SCVAL(smb_buf(outbuf),0,1);
3596 SSVAL(smb_buf(outbuf),1,28*count);
3599 SAFE_FREE(queue);
3601 DEBUG(3,("%d entries returned in queue\n",count));
3604 END_PROFILE(SMBsplretq);
3605 return(outsize);
3608 /****************************************************************************
3609 Reply to a printwrite.
3610 ****************************************************************************/
3612 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3614 int numtowrite;
3615 int outsize = set_message(outbuf,0,0,False);
3616 char *data;
3617 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3619 START_PROFILE(SMBsplwr);
3621 if (!CAN_PRINT(conn)) {
3622 END_PROFILE(SMBsplwr);
3623 return ERROR_DOS(ERRDOS,ERRnoaccess);
3626 CHECK_FSP(fsp,conn);
3627 if (!CHECK_WRITE(fsp)) {
3628 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3631 numtowrite = SVAL(smb_buf(inbuf),1);
3632 data = smb_buf(inbuf) + 3;
3634 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3635 END_PROFILE(SMBsplwr);
3636 return(UNIXERROR(ERRHRD,ERRdiskfull));
3639 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3641 END_PROFILE(SMBsplwr);
3642 return(outsize);
3645 /****************************************************************************
3646 Reply to a mkdir.
3647 ****************************************************************************/
3649 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3651 pstring directory;
3652 int outsize;
3653 NTSTATUS status;
3654 SMB_STRUCT_STAT sbuf;
3656 START_PROFILE(SMBmkdir);
3658 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 END_PROFILE(SMBmkdir);
3661 return ERROR_NT(status);
3664 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory)) {
3665 END_PROFILE(SMBmkdir);
3666 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3669 status = unix_convert(conn, directory, False, NULL, &sbuf);
3670 if (!NT_STATUS_IS_OK(status)) {
3671 END_PROFILE(SMBmkdir);
3672 return ERROR_NT(status);
3675 status = check_name(conn, directory);
3676 if (!NT_STATUS_IS_OK(status)) {
3677 END_PROFILE(SMBmkdir);
3678 return ERROR_NT(status);
3681 status = create_directory(conn, directory);
3683 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3685 if (!NT_STATUS_IS_OK(status)) {
3687 if (!use_nt_status()
3688 && NT_STATUS_EQUAL(status,
3689 NT_STATUS_OBJECT_NAME_COLLISION)) {
3691 * Yes, in the DOS error code case we get a
3692 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3693 * samba4 torture test.
3695 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3698 END_PROFILE(SMBmkdir);
3699 return ERROR_NT(status);
3702 outsize = set_message(outbuf,0,0,False);
3704 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3706 END_PROFILE(SMBmkdir);
3707 return(outsize);
3710 /****************************************************************************
3711 Static function used by reply_rmdir to delete an entire directory
3712 tree recursively. Return True on ok, False on fail.
3713 ****************************************************************************/
3715 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3717 const char *dname = NULL;
3718 BOOL ret = True;
3719 long offset = 0;
3720 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3722 if(dir_hnd == NULL)
3723 return False;
3725 while((dname = ReadDirName(dir_hnd, &offset))) {
3726 pstring fullname;
3727 SMB_STRUCT_STAT st;
3729 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3730 continue;
3732 if (!is_visible_file(conn, directory, dname, &st, False))
3733 continue;
3735 /* Construct the full name. */
3736 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3737 errno = ENOMEM;
3738 ret = False;
3739 break;
3742 pstrcpy(fullname, directory);
3743 pstrcat(fullname, "/");
3744 pstrcat(fullname, dname);
3746 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3747 ret = False;
3748 break;
3751 if(st.st_mode & S_IFDIR) {
3752 if(!recursive_rmdir(conn, fullname)) {
3753 ret = False;
3754 break;
3756 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3757 ret = False;
3758 break;
3760 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3761 ret = False;
3762 break;
3765 CloseDir(dir_hnd);
3766 return ret;
3769 /****************************************************************************
3770 The internals of the rmdir code - called elsewhere.
3771 ****************************************************************************/
3773 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
3775 int ret;
3776 SMB_STRUCT_STAT st;
3778 ret = SMB_VFS_RMDIR(conn,directory);
3779 if (ret == 0) {
3780 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3781 FILE_NOTIFY_CHANGE_DIR_NAME,
3782 directory);
3783 return NT_STATUS_OK;
3786 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3788 * Check to see if the only thing in this directory are
3789 * vetoed files/directories. If so then delete them and
3790 * retry. If we fail to delete any of them (and we *don't*
3791 * do a recursive delete) then fail the rmdir.
3793 const char *dname;
3794 long dirpos = 0;
3795 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3797 if(dir_hnd == NULL) {
3798 errno = ENOTEMPTY;
3799 goto err;
3802 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3803 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3804 continue;
3805 if (!is_visible_file(conn, directory, dname, &st, False))
3806 continue;
3807 if(!IS_VETO_PATH(conn, dname)) {
3808 CloseDir(dir_hnd);
3809 errno = ENOTEMPTY;
3810 goto err;
3814 /* We only have veto files/directories. Recursive delete. */
3816 RewindDir(dir_hnd,&dirpos);
3817 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3818 pstring fullname;
3820 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3821 continue;
3822 if (!is_visible_file(conn, directory, dname, &st, False))
3823 continue;
3825 /* Construct the full name. */
3826 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3827 errno = ENOMEM;
3828 break;
3831 pstrcpy(fullname, directory);
3832 pstrcat(fullname, "/");
3833 pstrcat(fullname, dname);
3835 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3836 break;
3837 if(st.st_mode & S_IFDIR) {
3838 if(lp_recursive_veto_delete(SNUM(conn))) {
3839 if(!recursive_rmdir(conn, fullname))
3840 break;
3842 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3843 break;
3844 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3845 break;
3847 CloseDir(dir_hnd);
3848 /* Retry the rmdir */
3849 ret = SMB_VFS_RMDIR(conn,directory);
3852 err:
3854 if (ret != 0) {
3855 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
3856 "%s\n", directory,strerror(errno)));
3857 return map_nt_error_from_unix(errno);
3860 notify_fname(conn, NOTIFY_ACTION_REMOVED,
3861 FILE_NOTIFY_CHANGE_DIR_NAME,
3862 directory);
3864 return NT_STATUS_OK;
3867 /****************************************************************************
3868 Reply to a rmdir.
3869 ****************************************************************************/
3871 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3873 pstring directory;
3874 int outsize = 0;
3875 SMB_STRUCT_STAT sbuf;
3876 NTSTATUS status;
3877 START_PROFILE(SMBrmdir);
3879 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3880 if (!NT_STATUS_IS_OK(status)) {
3881 END_PROFILE(SMBrmdir);
3882 return ERROR_NT(status);
3885 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory)) {
3886 END_PROFILE(SMBrmdir);
3887 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3890 status = unix_convert(conn, directory, False, NULL, &sbuf);
3891 if (!NT_STATUS_IS_OK(status)) {
3892 END_PROFILE(SMBrmdir);
3893 return ERROR_NT(status);
3896 status = check_name(conn, directory);
3897 if (!NT_STATUS_IS_OK(status)) {
3898 END_PROFILE(SMBrmdir);
3899 return ERROR_NT(status);
3902 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3903 status = rmdir_internals(conn, directory);
3904 if (!NT_STATUS_IS_OK(status)) {
3905 END_PROFILE(SMBrmdir);
3906 return ERROR_NT(status);
3909 outsize = set_message(outbuf,0,0,False);
3911 DEBUG( 3, ( "rmdir %s\n", directory ) );
3913 END_PROFILE(SMBrmdir);
3914 return(outsize);
3917 /*******************************************************************
3918 Resolve wildcards in a filename rename.
3919 Note that name is in UNIX charset and thus potentially can be more
3920 than fstring buffer (255 bytes) especially in default UTF-8 case.
3921 Therefore, we use pstring inside and all calls should ensure that
3922 name2 is at least pstring-long (they do already)
3923 ********************************************************************/
3925 static BOOL resolve_wildcards(const char *name1, char *name2)
3927 pstring root1,root2;
3928 pstring ext1,ext2;
3929 char *p,*p2, *pname1, *pname2;
3930 int available_space, actual_space;
3932 pname1 = strrchr_m(name1,'/');
3933 pname2 = strrchr_m(name2,'/');
3935 if (!pname1 || !pname2)
3936 return(False);
3938 pstrcpy(root1,pname1);
3939 pstrcpy(root2,pname2);
3940 p = strrchr_m(root1,'.');
3941 if (p) {
3942 *p = 0;
3943 pstrcpy(ext1,p+1);
3944 } else {
3945 pstrcpy(ext1,"");
3947 p = strrchr_m(root2,'.');
3948 if (p) {
3949 *p = 0;
3950 pstrcpy(ext2,p+1);
3951 } else {
3952 pstrcpy(ext2,"");
3955 p = root1;
3956 p2 = root2;
3957 while (*p2) {
3958 if (*p2 == '?') {
3959 *p2 = *p;
3960 p2++;
3961 } else if (*p2 == '*') {
3962 pstrcpy(p2, p);
3963 break;
3964 } else {
3965 p2++;
3967 if (*p)
3968 p++;
3971 p = ext1;
3972 p2 = ext2;
3973 while (*p2) {
3974 if (*p2 == '?') {
3975 *p2 = *p;
3976 p2++;
3977 } else if (*p2 == '*') {
3978 pstrcpy(p2, p);
3979 break;
3980 } else {
3981 p2++;
3983 if (*p)
3984 p++;
3987 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3989 if (ext2[0]) {
3990 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3991 if (actual_space >= available_space - 1) {
3992 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3993 actual_space - available_space));
3995 } else {
3996 pstrcpy_base(pname2, root2, name2);
3999 return(True);
4002 /****************************************************************************
4003 Ensure open files have their names updated. Updated to notify other smbd's
4004 asynchronously.
4005 ****************************************************************************/
4007 static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
4008 SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
4010 files_struct *fsp;
4011 BOOL did_rename = False;
4013 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
4014 /* fsp_name is a relative path under the fsp. To change this for other
4015 sharepaths we need to manipulate relative paths. */
4016 /* TODO - create the absolute path and manipulate the newname
4017 relative to the sharepath. */
4018 if (fsp->conn != conn) {
4019 continue;
4021 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
4022 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
4023 fsp->fsp_name, newname ));
4024 string_set(&fsp->fsp_name, newname);
4025 did_rename = True;
4028 if (!did_rename) {
4029 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
4030 (unsigned int)dev, (double)inode, newname ));
4033 /* Send messages to all smbd's (not ourself) that the name has changed. */
4034 rename_share_filename(lck, conn->connectpath, newname);
4037 /****************************************************************************
4038 We need to check if the source path is a parent directory of the destination
4039 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4040 refuse the rename with a sharing violation. Under UNIX the above call can
4041 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4042 probably need to check that the client is a Windows one before disallowing
4043 this as a UNIX client (one with UNIX extensions) can know the source is a
4044 symlink and make this decision intelligently. Found by an excellent bug
4045 report from <AndyLiebman@aol.com>.
4046 ****************************************************************************/
4048 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4050 const char *psrc = src;
4051 const char *pdst = dest;
4052 size_t slen;
4054 if (psrc[0] == '.' && psrc[1] == '/') {
4055 psrc += 2;
4057 if (pdst[0] == '.' && pdst[1] == '/') {
4058 pdst += 2;
4060 if ((slen = strlen(psrc)) > strlen(pdst)) {
4061 return False;
4063 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4066 /****************************************************************************
4067 Rename an open file - given an fsp.
4068 ****************************************************************************/
4070 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4072 SMB_STRUCT_STAT sbuf;
4073 pstring newname_last_component;
4074 NTSTATUS status = NT_STATUS_OK;
4075 BOOL dest_exists;
4076 struct share_mode_lock *lck = NULL;
4078 ZERO_STRUCT(sbuf);
4080 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4081 if (!NT_STATUS_IS_OK(status)) {
4082 return status;
4085 status = check_name(conn, newname);
4086 if (!NT_STATUS_IS_OK(status)) {
4087 return status;
4090 /* Ensure newname contains a '/' */
4091 if(strrchr_m(newname,'/') == 0) {
4092 pstring tmpstr;
4094 pstrcpy(tmpstr, "./");
4095 pstrcat(tmpstr, newname);
4096 pstrcpy(newname, tmpstr);
4100 * Check for special case with case preserving and not
4101 * case sensitive. If the old last component differs from the original
4102 * last component only by case, then we should allow
4103 * the rename (user is trying to change the case of the
4104 * filename).
4107 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4108 strequal(newname, fsp->fsp_name)) {
4109 char *p;
4110 pstring newname_modified_last_component;
4113 * Get the last component of the modified name.
4114 * Note that we guarantee that newname contains a '/'
4115 * character above.
4117 p = strrchr_m(newname,'/');
4118 pstrcpy(newname_modified_last_component,p+1);
4120 if(strcsequal(newname_modified_last_component,
4121 newname_last_component) == False) {
4123 * Replace the modified last component with
4124 * the original.
4126 pstrcpy(p+1, newname_last_component);
4131 * If the src and dest names are identical - including case,
4132 * don't do the rename, just return success.
4135 if (strcsequal(fsp->fsp_name, newname)) {
4136 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4137 newname));
4138 return NT_STATUS_OK;
4141 dest_exists = vfs_object_exist(conn,newname,NULL);
4143 if(!replace_if_exists && dest_exists) {
4144 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4145 fsp->fsp_name,newname));
4146 return NT_STATUS_OBJECT_NAME_COLLISION;
4149 status = can_rename(conn,newname,attrs,&sbuf);
4151 if (dest_exists && !NT_STATUS_IS_OK(status)) {
4152 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4153 nt_errstr(status), fsp->fsp_name,newname));
4154 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4155 status = NT_STATUS_ACCESS_DENIED;
4156 return status;
4159 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4160 return NT_STATUS_ACCESS_DENIED;
4163 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
4165 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4166 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4167 fsp->fsp_name,newname));
4168 rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
4169 TALLOC_FREE(lck);
4170 return NT_STATUS_OK;
4173 TALLOC_FREE(lck);
4175 if (errno == ENOTDIR || errno == EISDIR) {
4176 status = NT_STATUS_OBJECT_NAME_COLLISION;
4177 } else {
4178 status = map_nt_error_from_unix(errno);
4181 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4182 nt_errstr(status), fsp->fsp_name,newname));
4184 return status;
4188 * Do the notify calls from a rename
4191 static void notify_rename(connection_struct *conn, BOOL is_dir,
4192 const char *oldpath, const char *newpath)
4194 char *olddir, *newdir;
4195 const char *oldname, *newname;
4196 uint32 mask;
4198 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4199 : FILE_NOTIFY_CHANGE_FILE_NAME;
4201 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4202 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4203 TALLOC_FREE(olddir);
4204 return;
4207 if (strcmp(olddir, newdir) == 0) {
4208 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4209 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4211 else {
4212 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4213 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4215 TALLOC_FREE(olddir);
4216 TALLOC_FREE(newdir);
4218 /* this is a strange one. w2k3 gives an additional event for
4219 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4220 files, but not directories */
4221 if (!is_dir) {
4222 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4223 FILE_NOTIFY_CHANGE_ATTRIBUTES
4224 |FILE_NOTIFY_CHANGE_CREATION,
4225 newpath);
4229 /****************************************************************************
4230 The guts of the rename command, split out so it may be called by the NT SMB
4231 code.
4232 ****************************************************************************/
4234 NTSTATUS rename_internals(connection_struct *conn,
4235 pstring name,
4236 pstring newname,
4237 uint32 attrs,
4238 BOOL replace_if_exists,
4239 BOOL src_has_wild,
4240 BOOL dest_has_wild)
4242 pstring directory;
4243 pstring mask;
4244 pstring last_component_src;
4245 pstring last_component_dest;
4246 char *p;
4247 int count=0;
4248 NTSTATUS status = NT_STATUS_OK;
4249 SMB_STRUCT_STAT sbuf1, sbuf2;
4250 struct share_mode_lock *lck = NULL;
4251 struct smb_Dir *dir_hnd = NULL;
4252 const char *dname;
4253 long offset = 0;
4254 pstring destname;
4256 *directory = *mask = 0;
4258 ZERO_STRUCT(sbuf1);
4259 ZERO_STRUCT(sbuf2);
4261 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4262 if (!NT_STATUS_IS_OK(status)) {
4263 return status;
4266 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4267 if (!NT_STATUS_IS_OK(status)) {
4268 return status;
4272 * Split the old name into directory and last component
4273 * strings. Note that unix_convert may have stripped off a
4274 * leading ./ from both name and newname if the rename is
4275 * at the root of the share. We need to make sure either both
4276 * name and newname contain a / character or neither of them do
4277 * as this is checked in resolve_wildcards().
4280 p = strrchr_m(name,'/');
4281 if (!p) {
4282 pstrcpy(directory,".");
4283 pstrcpy(mask,name);
4284 } else {
4285 *p = 0;
4286 pstrcpy(directory,name);
4287 pstrcpy(mask,p+1);
4288 *p = '/'; /* Replace needed for exceptional test below. */
4292 * We should only check the mangled cache
4293 * here if unix_convert failed. This means
4294 * that the path in 'mask' doesn't exist
4295 * on the file system and so we need to look
4296 * for a possible mangle. This patch from
4297 * Tine Smukavec <valentin.smukavec@hermes.si>.
4300 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4301 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4304 if (!src_has_wild) {
4306 * No wildcards - just process the one file.
4308 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4310 /* Add a terminating '/' to the directory name. */
4311 pstrcat(directory,"/");
4312 pstrcat(directory,mask);
4314 /* Ensure newname contains a '/' also */
4315 if(strrchr_m(newname,'/') == 0) {
4316 pstring tmpstr;
4318 pstrcpy(tmpstr, "./");
4319 pstrcat(tmpstr, newname);
4320 pstrcpy(newname, tmpstr);
4323 DEBUG(3, ("rename_internals: case_sensitive = %d, "
4324 "case_preserve = %d, short case preserve = %d, "
4325 "directory = %s, newname = %s, "
4326 "last_component_dest = %s, is_8_3 = %d\n",
4327 conn->case_sensitive, conn->case_preserve,
4328 conn->short_case_preserve, directory,
4329 newname, last_component_dest, is_short_name));
4331 /* Ensure the source name is valid for us to access. */
4332 status = check_name(conn, directory);
4333 if (!NT_STATUS_IS_OK(status)) {
4334 return status;
4337 /* The dest name still may have wildcards. */
4338 if (dest_has_wild) {
4339 if (!resolve_wildcards(directory,newname)) {
4340 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4341 directory,newname));
4342 return NT_STATUS_NO_MEMORY;
4347 * Check for special case with case preserving and not
4348 * case sensitive, if directory and newname are identical,
4349 * and the old last component differs from the original
4350 * last component only by case, then we should allow
4351 * the rename (user is trying to change the case of the
4352 * filename).
4354 if((conn->case_sensitive == False) &&
4355 (((conn->case_preserve == True) &&
4356 (is_short_name == False)) ||
4357 ((conn->short_case_preserve == True) &&
4358 (is_short_name == True))) &&
4359 strcsequal(directory, newname)) {
4360 pstring modified_last_component;
4363 * Get the last component of the modified name.
4364 * Note that we guarantee that newname contains a '/'
4365 * character above.
4367 p = strrchr_m(newname,'/');
4368 pstrcpy(modified_last_component,p+1);
4370 if(strcsequal(modified_last_component,
4371 last_component_dest) == False) {
4373 * Replace the modified last component with
4374 * the original.
4376 pstrcpy(p+1, last_component_dest);
4380 /* Ensure the dest name is valid for us to access. */
4381 status = check_name(conn, newname);
4382 if (!NT_STATUS_IS_OK(status)) {
4383 return status;
4387 * The source object must exist.
4390 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4391 DEBUG(3, ("rename_internals: source doesn't exist "
4392 "doing rename %s -> %s\n",
4393 directory,newname));
4395 if (errno == ENOTDIR || errno == EISDIR
4396 || errno == ENOENT) {
4398 * Must return different errors depending on
4399 * whether the parent directory existed or
4400 * not.
4403 p = strrchr_m(directory, '/');
4404 if (!p)
4405 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4406 *p = '\0';
4407 if (vfs_object_exist(conn, directory, NULL))
4408 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4409 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4411 status = map_nt_error_from_unix(errno);
4412 DEBUG(3, ("rename_internals: Error %s rename %s -> "
4413 "%s\n", nt_errstr(status), directory,
4414 newname));
4416 return status;
4419 status = can_rename(conn,directory,attrs,&sbuf1);
4421 if (!NT_STATUS_IS_OK(status)) {
4422 DEBUG(3,("rename_internals: Error %s rename %s -> "
4423 "%s\n", nt_errstr(status), directory,
4424 newname));
4425 return status;
4429 * If the src and dest names are identical - including case,
4430 * don't do the rename, just return success.
4433 if (strcsequal(directory, newname)) {
4434 rename_open_files(conn, NULL, sbuf1.st_dev,
4435 sbuf1.st_ino, newname);
4436 DEBUG(3, ("rename_internals: identical names in "
4437 "rename %s - returning success\n",
4438 directory));
4439 return NT_STATUS_OK;
4442 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4443 DEBUG(3,("rename_internals: dest exists doing "
4444 "rename %s -> %s\n", directory, newname));
4445 return NT_STATUS_OBJECT_NAME_COLLISION;
4448 if (rename_path_prefix_equal(directory, newname)) {
4449 return NT_STATUS_SHARING_VIOLATION;
4452 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
4453 NULL, NULL);
4455 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4456 DEBUG(3,("rename_internals: succeeded doing rename "
4457 "on %s -> %s\n", directory, newname));
4458 rename_open_files(conn, lck, sbuf1.st_dev,
4459 sbuf1.st_ino, newname);
4460 TALLOC_FREE(lck);
4461 notify_rename(conn, S_ISDIR(sbuf1.st_mode),
4462 directory, newname);
4463 return NT_STATUS_OK;
4466 TALLOC_FREE(lck);
4467 if (errno == ENOTDIR || errno == EISDIR) {
4468 status = NT_STATUS_OBJECT_NAME_COLLISION;
4469 } else {
4470 status = map_nt_error_from_unix(errno);
4473 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4474 nt_errstr(status), directory,newname));
4476 return status;
4480 * Wildcards - process each file that matches.
4482 if (strequal(mask,"????????.???")) {
4483 pstrcpy(mask,"*");
4486 status = check_name(conn, directory);
4487 if (!NT_STATUS_IS_OK(status)) {
4488 return status;
4491 dir_hnd = OpenDir(conn, directory, mask, attrs);
4492 if (dir_hnd == NULL) {
4493 return map_nt_error_from_unix(errno);
4496 status = NT_STATUS_NO_SUCH_FILE;
4498 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4499 * - gentest fix. JRA
4502 while ((dname = ReadDirName(dir_hnd, &offset))) {
4503 pstring fname;
4504 BOOL sysdir_entry = False;
4506 pstrcpy(fname,dname);
4508 /* Quick check for "." and ".." */
4509 if (fname[0] == '.') {
4510 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4511 if (attrs & aDIR) {
4512 sysdir_entry = True;
4513 } else {
4514 continue;
4519 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4520 continue;
4523 if(!mask_match(fname, mask, conn->case_sensitive)) {
4524 continue;
4527 if (sysdir_entry) {
4528 status = NT_STATUS_OBJECT_NAME_INVALID;
4529 break;
4532 status = NT_STATUS_ACCESS_DENIED;
4533 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4535 /* Ensure the source name is valid for us to access. */
4536 status = check_name(conn, fname);
4537 if (!NT_STATUS_IS_OK(status)) {
4538 return status;
4541 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4542 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4543 DEBUG(6, ("rename %s failed. Error %s\n",
4544 fname, nt_errstr(status)));
4545 continue;
4547 status = can_rename(conn,fname,attrs,&sbuf1);
4548 if (!NT_STATUS_IS_OK(status)) {
4549 DEBUG(6, ("rename %s refused\n", fname));
4550 continue;
4552 pstrcpy(destname,newname);
4554 if (!resolve_wildcards(fname,destname)) {
4555 DEBUG(6, ("resolve_wildcards %s %s failed\n",
4556 fname, destname));
4557 continue;
4560 /* Ensure the dest name is valid for us to access. */
4561 status = check_name(conn, destname);
4562 if (!NT_STATUS_IS_OK(status)) {
4563 return status;
4566 if (strcsequal(fname,destname)) {
4567 rename_open_files(conn, NULL, sbuf1.st_dev,
4568 sbuf1.st_ino, newname);
4569 DEBUG(3,("rename_internals: identical names "
4570 "in wildcard rename %s - success\n",
4571 fname));
4572 count++;
4573 status = NT_STATUS_OK;
4574 continue;
4577 if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
4578 DEBUG(6,("file_exist %s\n", destname));
4579 status = NT_STATUS_OBJECT_NAME_COLLISION;
4580 continue;
4583 if (rename_path_prefix_equal(fname, destname)) {
4584 return NT_STATUS_SHARING_VIOLATION;
4587 lck = get_share_mode_lock(NULL, sbuf1.st_dev,
4588 sbuf1.st_ino, NULL, NULL);
4590 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4591 rename_open_files(conn, lck, sbuf1.st_dev,
4592 sbuf1.st_ino, newname);
4593 count++;
4594 status = NT_STATUS_OK;
4596 TALLOC_FREE(lck);
4597 DEBUG(3,("rename_internals: doing rename on %s -> "
4598 "%s\n",fname,destname));
4600 CloseDir(dir_hnd);
4602 if (count == 0 && NT_STATUS_IS_OK(status)) {
4603 status = map_nt_error_from_unix(errno);
4606 return status;
4609 /****************************************************************************
4610 Reply to a mv.
4611 ****************************************************************************/
4613 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4614 int dum_buffsize)
4616 int outsize = 0;
4617 pstring name;
4618 pstring newname;
4619 char *p;
4620 uint32 attrs = SVAL(inbuf,smb_vwv0);
4621 NTSTATUS status;
4622 BOOL src_has_wcard = False;
4623 BOOL dest_has_wcard = False;
4625 START_PROFILE(SMBmv);
4627 p = smb_buf(inbuf) + 1;
4628 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
4629 if (!NT_STATUS_IS_OK(status)) {
4630 END_PROFILE(SMBmv);
4631 return ERROR_NT(status);
4633 p++;
4634 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
4635 if (!NT_STATUS_IS_OK(status)) {
4636 END_PROFILE(SMBmv);
4637 return ERROR_NT(status);
4640 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) {
4641 END_PROFILE(SMBmv);
4642 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4644 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) {
4645 END_PROFILE(SMBmv);
4646 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4649 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4651 status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
4652 if (!NT_STATUS_IS_OK(status)) {
4653 END_PROFILE(SMBmv);
4654 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4655 /* We have re-scheduled this call. */
4656 return -1;
4658 return ERROR_NT(status);
4661 outsize = set_message(outbuf,0,0,False);
4663 END_PROFILE(SMBmv);
4664 return(outsize);
4667 /*******************************************************************
4668 Copy a file as part of a reply_copy.
4669 ******************************************************************/
4672 * TODO: check error codes on all callers
4675 NTSTATUS copy_file(connection_struct *conn,
4676 char *src,
4677 char *dest1,
4678 int ofun,
4679 int count,
4680 BOOL target_is_directory)
4682 SMB_STRUCT_STAT src_sbuf, sbuf2;
4683 SMB_OFF_T ret=-1;
4684 files_struct *fsp1,*fsp2;
4685 pstring dest;
4686 uint32 dosattrs;
4687 uint32 new_create_disposition;
4688 NTSTATUS status;
4690 pstrcpy(dest,dest1);
4691 if (target_is_directory) {
4692 char *p = strrchr_m(src,'/');
4693 if (p) {
4694 p++;
4695 } else {
4696 p = src;
4698 pstrcat(dest,"/");
4699 pstrcat(dest,p);
4702 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4703 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4706 if (!target_is_directory && count) {
4707 new_create_disposition = FILE_OPEN;
4708 } else {
4709 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4710 NULL, NULL, &new_create_disposition, NULL)) {
4711 return NT_STATUS_INVALID_PARAMETER;
4715 status = open_file_ntcreate(conn,src,&src_sbuf,
4716 FILE_GENERIC_READ,
4717 FILE_SHARE_READ|FILE_SHARE_WRITE,
4718 FILE_OPEN,
4720 FILE_ATTRIBUTE_NORMAL,
4721 INTERNAL_OPEN_ONLY,
4722 NULL, &fsp1);
4724 if (!NT_STATUS_IS_OK(status)) {
4725 return status;
4728 dosattrs = dos_mode(conn, src, &src_sbuf);
4729 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4730 ZERO_STRUCTP(&sbuf2);
4733 status = open_file_ntcreate(conn,dest,&sbuf2,
4734 FILE_GENERIC_WRITE,
4735 FILE_SHARE_READ|FILE_SHARE_WRITE,
4736 new_create_disposition,
4738 dosattrs,
4739 INTERNAL_OPEN_ONLY,
4740 NULL, &fsp2);
4742 if (!NT_STATUS_IS_OK(status)) {
4743 close_file(fsp1,ERROR_CLOSE);
4744 return status;
4747 if ((ofun&3) == 1) {
4748 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4749 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4751 * Stop the copy from occurring.
4753 ret = -1;
4754 src_sbuf.st_size = 0;
4758 if (src_sbuf.st_size) {
4759 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4762 close_file(fsp1,NORMAL_CLOSE);
4764 /* Ensure the modtime is set correctly on the destination file. */
4765 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
4768 * As we are opening fsp1 read-only we only expect
4769 * an error on close on fsp2 if we are out of space.
4770 * Thus we don't look at the error return from the
4771 * close of fsp1.
4773 status = close_file(fsp2,NORMAL_CLOSE);
4775 if (!NT_STATUS_IS_OK(status)) {
4776 return status;
4779 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4780 return NT_STATUS_DISK_FULL;
4783 return NT_STATUS_OK;
4786 /****************************************************************************
4787 Reply to a file copy.
4788 ****************************************************************************/
4790 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4792 int outsize = 0;
4793 pstring name;
4794 pstring directory;
4795 pstring mask,newname;
4796 char *p;
4797 int count=0;
4798 int error = ERRnoaccess;
4799 int err = 0;
4800 int tid2 = SVAL(inbuf,smb_vwv0);
4801 int ofun = SVAL(inbuf,smb_vwv1);
4802 int flags = SVAL(inbuf,smb_vwv2);
4803 BOOL target_is_directory=False;
4804 BOOL source_has_wild = False;
4805 BOOL dest_has_wild = False;
4806 SMB_STRUCT_STAT sbuf1, sbuf2;
4807 NTSTATUS status;
4808 START_PROFILE(SMBcopy);
4810 *directory = *mask = 0;
4812 p = smb_buf(inbuf);
4813 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
4814 if (!NT_STATUS_IS_OK(status)) {
4815 END_PROFILE(SMBcopy);
4816 return ERROR_NT(status);
4818 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
4819 if (!NT_STATUS_IS_OK(status)) {
4820 END_PROFILE(SMBcopy);
4821 return ERROR_NT(status);
4824 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4826 if (tid2 != conn->cnum) {
4827 /* can't currently handle inter share copies XXXX */
4828 DEBUG(3,("Rejecting inter-share copy\n"));
4829 END_PROFILE(SMBcopy);
4830 return ERROR_DOS(ERRSRV,ERRinvdevice);
4833 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name)) {
4834 END_PROFILE(SMBcopy);
4835 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4837 if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) {
4838 END_PROFILE(SMBcopy);
4839 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4842 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
4843 if (!NT_STATUS_IS_OK(status)) {
4844 END_PROFILE(SMBcopy);
4845 return ERROR_NT(status);
4848 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
4849 if (!NT_STATUS_IS_OK(status)) {
4850 END_PROFILE(SMBcopy);
4851 return ERROR_NT(status);
4854 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4856 if ((flags&1) && target_is_directory) {
4857 END_PROFILE(SMBcopy);
4858 return ERROR_DOS(ERRDOS,ERRbadfile);
4861 if ((flags&2) && !target_is_directory) {
4862 END_PROFILE(SMBcopy);
4863 return ERROR_DOS(ERRDOS,ERRbadpath);
4866 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4867 /* wants a tree copy! XXXX */
4868 DEBUG(3,("Rejecting tree copy\n"));
4869 END_PROFILE(SMBcopy);
4870 return ERROR_DOS(ERRSRV,ERRerror);
4873 p = strrchr_m(name,'/');
4874 if (!p) {
4875 pstrcpy(directory,"./");
4876 pstrcpy(mask,name);
4877 } else {
4878 *p = 0;
4879 pstrcpy(directory,name);
4880 pstrcpy(mask,p+1);
4884 * We should only check the mangled cache
4885 * here if unix_convert failed. This means
4886 * that the path in 'mask' doesn't exist
4887 * on the file system and so we need to look
4888 * for a possible mangle. This patch from
4889 * Tine Smukavec <valentin.smukavec@hermes.si>.
4892 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4893 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4896 if (!source_has_wild) {
4897 pstrcat(directory,"/");
4898 pstrcat(directory,mask);
4899 if (dest_has_wild) {
4900 if (!resolve_wildcards(directory,newname)) {
4901 END_PROFILE(SMBcopy);
4902 return ERROR_NT(NT_STATUS_NO_MEMORY);
4906 status = check_name(conn, directory);
4907 if (!NT_STATUS_IS_OK(status)) {
4908 return ERROR_NT(status);
4911 status = check_name(conn, newname);
4912 if (!NT_STATUS_IS_OK(status)) {
4913 return ERROR_NT(status);
4916 status = copy_file(conn,directory,newname,ofun,
4917 count,target_is_directory);
4919 if(!NT_STATUS_IS_OK(status)) {
4920 END_PROFILE(SMBcopy);
4921 return ERROR_NT(status);
4922 } else {
4923 count++;
4925 } else {
4926 struct smb_Dir *dir_hnd = NULL;
4927 const char *dname;
4928 long offset = 0;
4929 pstring destname;
4931 if (strequal(mask,"????????.???"))
4932 pstrcpy(mask,"*");
4934 status = check_name(conn, directory);
4935 if (!NT_STATUS_IS_OK(status)) {
4936 return ERROR_NT(status);
4939 dir_hnd = OpenDir(conn, directory, mask, 0);
4940 if (dir_hnd == NULL) {
4941 status = map_nt_error_from_unix(errno);
4942 return ERROR_NT(status);
4945 error = ERRbadfile;
4947 while ((dname = ReadDirName(dir_hnd, &offset))) {
4948 pstring fname;
4949 pstrcpy(fname,dname);
4951 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4952 continue;
4955 if(!mask_match(fname, mask, conn->case_sensitive)) {
4956 continue;
4959 error = ERRnoaccess;
4960 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4961 pstrcpy(destname,newname);
4962 if (!resolve_wildcards(fname,destname)) {
4963 continue;
4966 status = check_name(conn, fname);
4967 if (!NT_STATUS_IS_OK(status)) {
4968 return ERROR_NT(status);
4971 status = check_name(conn, destname);
4972 if (!NT_STATUS_IS_OK(status)) {
4973 return ERROR_NT(status);
4976 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
4978 status = copy_file(conn,fname,destname,ofun,
4979 count,target_is_directory);
4980 if (NT_STATUS_IS_OK(status)) {
4981 count++;
4984 CloseDir(dir_hnd);
4987 if (count == 0) {
4988 if(err) {
4989 /* Error on close... */
4990 errno = err;
4991 END_PROFILE(SMBcopy);
4992 return(UNIXERROR(ERRHRD,ERRgeneral));
4995 END_PROFILE(SMBcopy);
4996 return ERROR_DOS(ERRDOS,error);
4999 outsize = set_message(outbuf,1,0,True);
5000 SSVAL(outbuf,smb_vwv0,count);
5002 END_PROFILE(SMBcopy);
5003 return(outsize);
5006 /****************************************************************************
5007 Reply to a setdir.
5008 ****************************************************************************/
5010 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5012 int snum;
5013 int outsize = 0;
5014 pstring newdir;
5015 NTSTATUS status;
5017 START_PROFILE(pathworks_setdir);
5019 snum = SNUM(conn);
5020 if (!CAN_SETDIR(snum)) {
5021 END_PROFILE(pathworks_setdir);
5022 return ERROR_DOS(ERRDOS,ERRnoaccess);
5025 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
5026 if (!NT_STATUS_IS_OK(status)) {
5027 END_PROFILE(pathworks_setdir);
5028 return ERROR_NT(status);
5031 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir)) {
5032 END_PROFILE(pathworks_setdir);
5033 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5036 if (strlen(newdir) != 0) {
5037 if (!vfs_directory_exist(conn,newdir,NULL)) {
5038 END_PROFILE(pathworks_setdir);
5039 return ERROR_DOS(ERRDOS,ERRbadpath);
5041 set_conn_connectpath(conn,newdir);
5044 outsize = set_message(outbuf,0,0,False);
5045 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5047 DEBUG(3,("setdir %s\n", newdir));
5049 END_PROFILE(pathworks_setdir);
5050 return(outsize);
5053 #undef DBGC_CLASS
5054 #define DBGC_CLASS DBGC_LOCKING
5056 /****************************************************************************
5057 Get a lock pid, dealing with large count requests.
5058 ****************************************************************************/
5060 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5062 if(!large_file_format)
5063 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5064 else
5065 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5068 /****************************************************************************
5069 Get a lock count, dealing with large count requests.
5070 ****************************************************************************/
5072 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5074 SMB_BIG_UINT count = 0;
5076 if(!large_file_format) {
5077 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5078 } else {
5080 #if defined(HAVE_LONGLONG)
5081 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5082 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5083 #else /* HAVE_LONGLONG */
5086 * NT4.x seems to be broken in that it sends large file (64 bit)
5087 * lockingX calls even if the CAP_LARGE_FILES was *not*
5088 * negotiated. For boxes without large unsigned ints truncate the
5089 * lock count by dropping the top 32 bits.
5092 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5093 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5094 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5095 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5096 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5099 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5100 #endif /* HAVE_LONGLONG */
5103 return count;
5106 #if !defined(HAVE_LONGLONG)
5107 /****************************************************************************
5108 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5109 ****************************************************************************/
5111 static uint32 map_lock_offset(uint32 high, uint32 low)
5113 unsigned int i;
5114 uint32 mask = 0;
5115 uint32 highcopy = high;
5118 * Try and find out how many significant bits there are in high.
5121 for(i = 0; highcopy; i++)
5122 highcopy >>= 1;
5125 * We use 31 bits not 32 here as POSIX
5126 * lock offsets may not be negative.
5129 mask = (~0) << (31 - i);
5131 if(low & mask)
5132 return 0; /* Fail. */
5134 high <<= (31 - i);
5136 return (high|low);
5138 #endif /* !defined(HAVE_LONGLONG) */
5140 /****************************************************************************
5141 Get a lock offset, dealing with large offset requests.
5142 ****************************************************************************/
5144 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5146 SMB_BIG_UINT offset = 0;
5148 *err = False;
5150 if(!large_file_format) {
5151 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5152 } else {
5154 #if defined(HAVE_LONGLONG)
5155 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5156 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5157 #else /* HAVE_LONGLONG */
5160 * NT4.x seems to be broken in that it sends large file (64 bit)
5161 * lockingX calls even if the CAP_LARGE_FILES was *not*
5162 * negotiated. For boxes without large unsigned ints mangle the
5163 * lock offset by mapping the top 32 bits onto the lower 32.
5166 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5167 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5168 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5169 uint32 new_low = 0;
5171 if((new_low = map_lock_offset(high, low)) == 0) {
5172 *err = True;
5173 return (SMB_BIG_UINT)-1;
5176 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5177 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5178 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5179 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5182 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5183 #endif /* HAVE_LONGLONG */
5186 return offset;
5189 /****************************************************************************
5190 Reply to a lockingX request.
5191 ****************************************************************************/
5193 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5194 int length, int bufsize)
5196 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5197 unsigned char locktype = CVAL(inbuf,smb_vwv3);
5198 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5199 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5200 uint16 num_locks = SVAL(inbuf,smb_vwv7);
5201 SMB_BIG_UINT count = 0, offset = 0;
5202 uint32 lock_pid;
5203 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5204 int i;
5205 char *data;
5206 BOOL large_file_format =
5207 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5208 BOOL err;
5209 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5211 START_PROFILE(SMBlockingX);
5213 CHECK_FSP(fsp,conn);
5215 data = smb_buf(inbuf);
5217 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5218 /* we don't support these - and CANCEL_LOCK makes w2k
5219 and XP reboot so I don't really want to be
5220 compatible! (tridge) */
5221 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5224 /* Check if this is an oplock break on a file
5225 we have granted an oplock on.
5227 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5228 /* Client can insist on breaking to none. */
5229 BOOL break_to_none = (oplocklevel == 0);
5230 BOOL result;
5232 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5233 "for fnum = %d\n", (unsigned int)oplocklevel,
5234 fsp->fnum ));
5237 * Make sure we have granted an exclusive or batch oplock on
5238 * this file.
5241 if (fsp->oplock_type == 0) {
5243 /* The Samba4 nbench simulator doesn't understand
5244 the difference between break to level2 and break
5245 to none from level2 - it sends oplock break
5246 replies in both cases. Don't keep logging an error
5247 message here - just ignore it. JRA. */
5249 DEBUG(5,("reply_lockingX: Error : oplock break from "
5250 "client for fnum = %d (oplock=%d) and no "
5251 "oplock granted on this file (%s).\n",
5252 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5254 /* if this is a pure oplock break request then don't
5255 * send a reply */
5256 if (num_locks == 0 && num_ulocks == 0) {
5257 END_PROFILE(SMBlockingX);
5258 return -1;
5259 } else {
5260 END_PROFILE(SMBlockingX);
5261 return ERROR_DOS(ERRDOS,ERRlock);
5265 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5266 (break_to_none)) {
5267 result = remove_oplock(fsp);
5268 } else {
5269 result = downgrade_oplock(fsp);
5272 if (!result) {
5273 DEBUG(0, ("reply_lockingX: error in removing "
5274 "oplock on file %s\n", fsp->fsp_name));
5275 /* Hmmm. Is this panic justified? */
5276 smb_panic("internal tdb error");
5279 reply_to_oplock_break_requests(fsp);
5281 /* if this is a pure oplock break request then don't send a
5282 * reply */
5283 if (num_locks == 0 && num_ulocks == 0) {
5284 /* Sanity check - ensure a pure oplock break is not a
5285 chained request. */
5286 if(CVAL(inbuf,smb_vwv0) != 0xff)
5287 DEBUG(0,("reply_lockingX: Error : pure oplock "
5288 "break is a chained %d request !\n",
5289 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5290 END_PROFILE(SMBlockingX);
5291 return -1;
5296 * We do this check *after* we have checked this is not a oplock break
5297 * response message. JRA.
5300 release_level_2_oplocks_on_change(fsp);
5302 /* Data now points at the beginning of the list
5303 of smb_unlkrng structs */
5304 for(i = 0; i < (int)num_ulocks; i++) {
5305 lock_pid = get_lock_pid( data, i, large_file_format);
5306 count = get_lock_count( data, i, large_file_format);
5307 offset = get_lock_offset( data, i, large_file_format, &err);
5310 * There is no error code marked "stupid client bug".... :-).
5312 if(err) {
5313 END_PROFILE(SMBlockingX);
5314 return ERROR_DOS(ERRDOS,ERRnoaccess);
5317 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5318 "pid %u, file %s\n", (double)offset, (double)count,
5319 (unsigned int)lock_pid, fsp->fsp_name ));
5321 status = do_unlock(fsp,
5322 lock_pid,
5323 count,
5324 offset,
5325 WINDOWS_LOCK);
5327 if (NT_STATUS_V(status)) {
5328 END_PROFILE(SMBlockingX);
5329 return ERROR_NT(status);
5333 /* Setup the timeout in seconds. */
5335 if (!lp_blocking_locks(SNUM(conn))) {
5336 lock_timeout = 0;
5339 /* Now do any requested locks */
5340 data += ((large_file_format ? 20 : 10)*num_ulocks);
5342 /* Data now points at the beginning of the list
5343 of smb_lkrng structs */
5345 for(i = 0; i < (int)num_locks; i++) {
5346 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5347 READ_LOCK:WRITE_LOCK);
5348 lock_pid = get_lock_pid( data, i, large_file_format);
5349 count = get_lock_count( data, i, large_file_format);
5350 offset = get_lock_offset( data, i, large_file_format, &err);
5353 * There is no error code marked "stupid client bug".... :-).
5355 if(err) {
5356 END_PROFILE(SMBlockingX);
5357 return ERROR_DOS(ERRDOS,ERRnoaccess);
5360 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5361 "%u, file %s timeout = %d\n", (double)offset,
5362 (double)count, (unsigned int)lock_pid,
5363 fsp->fsp_name, (int)lock_timeout ));
5365 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5366 if (lp_blocking_locks(SNUM(conn))) {
5368 /* Schedule a message to ourselves to
5369 remove the blocking lock record and
5370 return the right error. */
5372 if (!blocking_lock_cancel(fsp,
5373 lock_pid,
5374 offset,
5375 count,
5376 WINDOWS_LOCK,
5377 locktype,
5378 NT_STATUS_FILE_LOCK_CONFLICT)) {
5379 END_PROFILE(SMBlockingX);
5380 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5383 /* Remove a matching pending lock. */
5384 status = do_lock_cancel(fsp,
5385 lock_pid,
5386 count,
5387 offset,
5388 WINDOWS_LOCK);
5389 } else {
5390 BOOL blocking_lock = lock_timeout ? True : False;
5391 BOOL defer_lock = False;
5392 struct byte_range_lock *br_lck;
5394 br_lck = do_lock(fsp,
5395 lock_pid,
5396 count,
5397 offset,
5398 lock_type,
5399 WINDOWS_LOCK,
5400 blocking_lock,
5401 &status);
5403 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5404 /* Windows internal resolution for blocking locks seems
5405 to be about 200ms... Don't wait for less than that. JRA. */
5406 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5407 lock_timeout = lp_lock_spin_time();
5409 defer_lock = True;
5412 /* This heuristic seems to match W2K3 very well. If a
5413 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5414 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5415 far as I can tell. Replacement for do_lock_spin(). JRA. */
5417 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5418 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5419 defer_lock = True;
5420 lock_timeout = lp_lock_spin_time();
5423 if (br_lck && defer_lock) {
5425 * A blocking lock was requested. Package up
5426 * this smb into a queued request and push it
5427 * onto the blocking lock queue.
5429 if(push_blocking_lock_request(br_lck,
5430 inbuf, length,
5431 fsp,
5432 lock_timeout,
5434 lock_pid,
5435 lock_type,
5436 WINDOWS_LOCK,
5437 offset,
5438 count)) {
5439 TALLOC_FREE(br_lck);
5440 END_PROFILE(SMBlockingX);
5441 return -1;
5445 TALLOC_FREE(br_lck);
5448 if (NT_STATUS_V(status)) {
5449 END_PROFILE(SMBlockingX);
5450 return ERROR_NT(status);
5454 /* If any of the above locks failed, then we must unlock
5455 all of the previous locks (X/Open spec). */
5457 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5458 (i != num_locks) &&
5459 (num_locks != 0)) {
5461 * Ensure we don't do a remove on the lock that just failed,
5462 * as under POSIX rules, if we have a lock already there, we
5463 * will delete it (and we shouldn't) .....
5465 for(i--; i >= 0; i--) {
5466 lock_pid = get_lock_pid( data, i, large_file_format);
5467 count = get_lock_count( data, i, large_file_format);
5468 offset = get_lock_offset( data, i, large_file_format,
5469 &err);
5472 * There is no error code marked "stupid client
5473 * bug".... :-).
5475 if(err) {
5476 END_PROFILE(SMBlockingX);
5477 return ERROR_DOS(ERRDOS,ERRnoaccess);
5480 do_unlock(fsp,
5481 lock_pid,
5482 count,
5483 offset,
5484 WINDOWS_LOCK);
5486 END_PROFILE(SMBlockingX);
5487 return ERROR_NT(status);
5490 set_message(outbuf,2,0,True);
5492 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5493 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5495 END_PROFILE(SMBlockingX);
5496 return chain_reply(inbuf,outbuf,length,bufsize);
5499 #undef DBGC_CLASS
5500 #define DBGC_CLASS DBGC_ALL
5502 /****************************************************************************
5503 Reply to a SMBreadbmpx (read block multiplex) request.
5504 ****************************************************************************/
5506 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5508 ssize_t nread = -1;
5509 ssize_t total_read;
5510 char *data;
5511 SMB_OFF_T startpos;
5512 int outsize;
5513 size_t maxcount;
5514 int max_per_packet;
5515 size_t tcount;
5516 int pad;
5517 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5518 START_PROFILE(SMBreadBmpx);
5520 /* this function doesn't seem to work - disable by default */
5521 if (!lp_readbmpx()) {
5522 END_PROFILE(SMBreadBmpx);
5523 return ERROR_DOS(ERRSRV,ERRuseSTD);
5526 outsize = set_message(outbuf,8,0,True);
5528 CHECK_FSP(fsp,conn);
5529 if (!CHECK_READ(fsp,inbuf)) {
5530 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5533 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5534 maxcount = SVAL(inbuf,smb_vwv3);
5536 data = smb_buf(outbuf);
5537 pad = ((long)data)%4;
5538 if (pad)
5539 pad = 4 - pad;
5540 data += pad;
5542 max_per_packet = bufsize-(outsize+pad);
5543 tcount = maxcount;
5544 total_read = 0;
5546 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5547 END_PROFILE(SMBreadBmpx);
5548 return ERROR_DOS(ERRDOS,ERRlock);
5551 do {
5552 size_t N = MIN(max_per_packet,tcount-total_read);
5554 nread = read_file(fsp,data,startpos,N);
5556 if (nread <= 0)
5557 nread = 0;
5559 if (nread < (ssize_t)N)
5560 tcount = total_read + nread;
5562 set_message(outbuf,8,nread+pad,False);
5563 SIVAL(outbuf,smb_vwv0,startpos);
5564 SSVAL(outbuf,smb_vwv2,tcount);
5565 SSVAL(outbuf,smb_vwv6,nread);
5566 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5568 show_msg(outbuf);
5569 if (!send_smb(smbd_server_fd(),outbuf))
5570 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5572 total_read += nread;
5573 startpos += nread;
5574 } while (total_read < (ssize_t)tcount);
5576 END_PROFILE(SMBreadBmpx);
5577 return(-1);
5580 /****************************************************************************
5581 Reply to a SMBsetattrE.
5582 ****************************************************************************/
5584 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5586 struct timespec ts[2];
5587 int outsize = 0;
5588 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5589 START_PROFILE(SMBsetattrE);
5591 outsize = set_message(outbuf,0,0,False);
5593 if(!fsp || (fsp->conn != conn)) {
5594 END_PROFILE(SMBsetattrE);
5595 return ERROR_DOS(ERRDOS,ERRbadfid);
5599 * Convert the DOS times into unix times. Ignore create
5600 * time as UNIX can't set this.
5603 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5604 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5607 * Patch from Ray Frush <frush@engr.colostate.edu>
5608 * Sometimes times are sent as zero - ignore them.
5611 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5612 /* Ignore request */
5613 if( DEBUGLVL( 3 ) ) {
5614 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5615 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5617 END_PROFILE(SMBsetattrE);
5618 return(outsize);
5619 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5620 /* set modify time = to access time if modify time was unset */
5621 ts[1] = ts[0];
5624 /* Set the date on this file */
5625 /* Should we set pending modtime here ? JRA */
5626 if(file_ntimes(conn, fsp->fsp_name, ts)) {
5627 END_PROFILE(SMBsetattrE);
5628 return ERROR_DOS(ERRDOS,ERRnoaccess);
5631 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5632 fsp->fnum,
5633 (unsigned int)ts[0].tv_sec,
5634 (unsigned int)ts[1].tv_sec));
5636 END_PROFILE(SMBsetattrE);
5637 return(outsize);
5641 /* Back from the dead for OS/2..... JRA. */
5643 /****************************************************************************
5644 Reply to a SMBwritebmpx (write block multiplex primary) request.
5645 ****************************************************************************/
5647 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5649 size_t numtowrite;
5650 ssize_t nwritten = -1;
5651 int outsize = 0;
5652 SMB_OFF_T startpos;
5653 size_t tcount;
5654 BOOL write_through;
5655 int smb_doff;
5656 char *data;
5657 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5658 START_PROFILE(SMBwriteBmpx);
5660 CHECK_FSP(fsp,conn);
5661 if (!CHECK_WRITE(fsp)) {
5662 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5664 if (HAS_CACHED_ERROR(fsp)) {
5665 return(CACHED_ERROR(fsp));
5668 tcount = SVAL(inbuf,smb_vwv1);
5669 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5670 write_through = BITSETW(inbuf+smb_vwv7,0);
5671 numtowrite = SVAL(inbuf,smb_vwv10);
5672 smb_doff = SVAL(inbuf,smb_vwv11);
5674 data = smb_base(inbuf) + smb_doff;
5676 /* If this fails we need to send an SMBwriteC response,
5677 not an SMBwritebmpx - set this up now so we don't forget */
5678 SCVAL(outbuf,smb_com,SMBwritec);
5680 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5681 END_PROFILE(SMBwriteBmpx);
5682 return(ERROR_DOS(ERRDOS,ERRlock));
5685 nwritten = write_file(fsp,data,startpos,numtowrite);
5687 sync_file(conn, fsp, write_through);
5689 if(nwritten < (ssize_t)numtowrite) {
5690 END_PROFILE(SMBwriteBmpx);
5691 return(UNIXERROR(ERRHRD,ERRdiskfull));
5694 /* If the maximum to be written to this file
5695 is greater than what we just wrote then set
5696 up a secondary struct to be attached to this
5697 fd, we will use this to cache error messages etc. */
5699 if((ssize_t)tcount > nwritten) {
5700 write_bmpx_struct *wbms;
5701 if(fsp->wbmpx_ptr != NULL)
5702 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5703 else
5704 wbms = SMB_MALLOC_P(write_bmpx_struct);
5705 if(!wbms) {
5706 DEBUG(0,("Out of memory in reply_readmpx\n"));
5707 END_PROFILE(SMBwriteBmpx);
5708 return(ERROR_DOS(ERRSRV,ERRnoresource));
5710 wbms->wr_mode = write_through;
5711 wbms->wr_discard = False; /* No errors yet */
5712 wbms->wr_total_written = nwritten;
5713 wbms->wr_errclass = 0;
5714 wbms->wr_error = 0;
5715 fsp->wbmpx_ptr = wbms;
5718 /* We are returning successfully, set the message type back to
5719 SMBwritebmpx */
5720 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5722 outsize = set_message(outbuf,1,0,True);
5724 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5726 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5727 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5729 if (write_through && tcount==nwritten) {
5730 /* We need to send both a primary and a secondary response */
5731 smb_setlen(outbuf,outsize - 4);
5732 show_msg(outbuf);
5733 if (!send_smb(smbd_server_fd(),outbuf))
5734 exit_server_cleanly("reply_writebmpx: send_smb failed.");
5736 /* Now the secondary */
5737 outsize = set_message(outbuf,1,0,True);
5738 SCVAL(outbuf,smb_com,SMBwritec);
5739 SSVAL(outbuf,smb_vwv0,nwritten);
5742 END_PROFILE(SMBwriteBmpx);
5743 return(outsize);
5746 /****************************************************************************
5747 Reply to a SMBwritebs (write block multiplex secondary) request.
5748 ****************************************************************************/
5750 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5752 size_t numtowrite;
5753 ssize_t nwritten = -1;
5754 int outsize = 0;
5755 SMB_OFF_T startpos;
5756 size_t tcount;
5757 BOOL write_through;
5758 int smb_doff;
5759 char *data;
5760 write_bmpx_struct *wbms;
5761 BOOL send_response = False;
5762 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5763 START_PROFILE(SMBwriteBs);
5765 CHECK_FSP(fsp,conn);
5766 if (!CHECK_WRITE(fsp)) {
5767 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5770 tcount = SVAL(inbuf,smb_vwv1);
5771 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5772 numtowrite = SVAL(inbuf,smb_vwv6);
5773 smb_doff = SVAL(inbuf,smb_vwv7);
5775 data = smb_base(inbuf) + smb_doff;
5777 /* We need to send an SMBwriteC response, not an SMBwritebs */
5778 SCVAL(outbuf,smb_com,SMBwritec);
5780 /* This fd should have an auxiliary struct attached,
5781 check that it does */
5782 wbms = fsp->wbmpx_ptr;
5783 if(!wbms) {
5784 END_PROFILE(SMBwriteBs);
5785 return(-1);
5788 /* If write through is set we can return errors, else we must cache them */
5789 write_through = wbms->wr_mode;
5791 /* Check for an earlier error */
5792 if(wbms->wr_discard) {
5793 END_PROFILE(SMBwriteBs);
5794 return -1; /* Just discard the packet */
5797 nwritten = write_file(fsp,data,startpos,numtowrite);
5799 sync_file(conn, fsp, write_through);
5801 if (nwritten < (ssize_t)numtowrite) {
5802 if(write_through) {
5803 /* We are returning an error - we can delete the aux struct */
5804 if (wbms)
5805 free((char *)wbms);
5806 fsp->wbmpx_ptr = NULL;
5807 END_PROFILE(SMBwriteBs);
5808 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5810 wbms->wr_errclass = ERRHRD;
5811 wbms->wr_error = ERRdiskfull;
5812 wbms->wr_status = NT_STATUS_DISK_FULL;
5813 wbms->wr_discard = True;
5814 END_PROFILE(SMBwriteBs);
5815 return -1;
5818 /* Increment the total written, if this matches tcount
5819 we can discard the auxiliary struct (hurrah !) and return a writeC */
5820 wbms->wr_total_written += nwritten;
5821 if(wbms->wr_total_written >= tcount) {
5822 if (write_through) {
5823 outsize = set_message(outbuf,1,0,True);
5824 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5825 send_response = True;
5828 free((char *)wbms);
5829 fsp->wbmpx_ptr = NULL;
5832 if(send_response) {
5833 END_PROFILE(SMBwriteBs);
5834 return(outsize);
5837 END_PROFILE(SMBwriteBs);
5838 return(-1);
5841 /****************************************************************************
5842 Reply to a SMBgetattrE.
5843 ****************************************************************************/
5845 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5847 SMB_STRUCT_STAT sbuf;
5848 int outsize = 0;
5849 int mode;
5850 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5851 START_PROFILE(SMBgetattrE);
5853 outsize = set_message(outbuf,11,0,True);
5855 if(!fsp || (fsp->conn != conn)) {
5856 END_PROFILE(SMBgetattrE);
5857 return ERROR_DOS(ERRDOS,ERRbadfid);
5860 /* Do an fstat on this file */
5861 if(fsp_stat(fsp, &sbuf)) {
5862 END_PROFILE(SMBgetattrE);
5863 return(UNIXERROR(ERRDOS,ERRnoaccess));
5866 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5869 * Convert the times into dos times. Set create
5870 * date to be last modify date as UNIX doesn't save
5871 * this.
5874 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5875 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5876 /* Should we check pending modtime here ? JRA */
5877 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5879 if (mode & aDIR) {
5880 SIVAL(outbuf,smb_vwv6,0);
5881 SIVAL(outbuf,smb_vwv8,0);
5882 } else {
5883 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5884 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5885 SIVAL(outbuf,smb_vwv8,allocation_size);
5887 SSVAL(outbuf,smb_vwv10, mode);
5889 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5891 END_PROFILE(SMBgetattrE);
5892 return(outsize);