r20837: Use real type name, to fix compilation with -WC++-compat
[Samba.git] / source / smbd / reply.c
blob3a1514f1aa4146158f0e2e322bcc93d21eabe3cb
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 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
637 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
639 status = unix_convert(conn, name, False, NULL, &sbuf);
640 if (!NT_STATUS_IS_OK(status)) {
641 END_PROFILE(SMBcheckpath);
642 status = map_checkpath_error(inbuf, status);
643 return ERROR_NT(status);
646 if (check_name(name,conn) && (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)) {
647 if (!S_ISDIR(sbuf.st_mode)) {
648 END_PROFILE(SMBcheckpath);
649 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
651 } else {
652 /* We special case this - as when a Windows machine
653 is parsing a path is steps through the components
654 one at a time - if a component fails it expects
655 ERRbadpath, not ERRbadfile.
657 if(errno == ENOENT) {
659 * Windows returns different error codes if
660 * the parent directory is valid but not the
661 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
662 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
663 * if the path is invalid.
665 END_PROFILE(SMBcheckpath);
666 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
669 END_PROFILE(SMBcheckpath);
670 return(UNIXERROR(ERRDOS,ERRbadpath));
673 outsize = set_message(outbuf,0,0,False);
675 END_PROFILE(SMBcheckpath);
676 return outsize;
679 /****************************************************************************
680 Reply to a getatr.
681 ****************************************************************************/
683 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
685 pstring fname;
686 int outsize = 0;
687 SMB_STRUCT_STAT sbuf;
688 int mode=0;
689 SMB_OFF_T size=0;
690 time_t mtime=0;
691 char *p;
692 NTSTATUS status;
694 START_PROFILE(SMBgetatr);
696 p = smb_buf(inbuf) + 1;
697 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
698 if (!NT_STATUS_IS_OK(status)) {
699 END_PROFILE(SMBgetatr);
700 return ERROR_NT(status);
703 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
705 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
706 under WfWg - weird! */
707 if (*fname == '\0') {
708 mode = aHIDDEN | aDIR;
709 if (!CAN_WRITE(conn)) {
710 mode |= aRONLY;
712 size = 0;
713 mtime = 0;
714 } else {
715 status = unix_convert(conn, fname, False, NULL,&sbuf);
716 if (!NT_STATUS_IS_OK(status)) {
717 END_PROFILE(SMBgetatr);
718 return ERROR_NT(status);
720 if (check_name(fname,conn) &&
721 (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0)) {
722 mode = dos_mode(conn,fname,&sbuf);
723 size = sbuf.st_size;
724 mtime = sbuf.st_mtime;
725 if (mode & aDIR) {
726 size = 0;
728 } else {
729 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
730 END_PROFILE(SMBgetatr);
731 return UNIXERROR(ERRDOS,ERRbadfile);
735 outsize = set_message(outbuf,10,0,True);
737 SSVAL(outbuf,smb_vwv0,mode);
738 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
739 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
740 } else {
741 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
743 SIVAL(outbuf,smb_vwv3,(uint32)size);
745 if (Protocol >= PROTOCOL_NT1) {
746 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
749 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
751 END_PROFILE(SMBgetatr);
752 return(outsize);
755 /****************************************************************************
756 Reply to a setatr.
757 ****************************************************************************/
759 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
761 pstring fname;
762 int outsize = 0;
763 int mode;
764 time_t mtime;
765 SMB_STRUCT_STAT sbuf;
766 char *p;
767 NTSTATUS status;
769 START_PROFILE(SMBsetatr);
771 p = smb_buf(inbuf) + 1;
772 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
773 if (!NT_STATUS_IS_OK(status)) {
774 END_PROFILE(SMBsetatr);
775 return ERROR_NT(status);
778 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
780 status = unix_convert(conn, fname, False, NULL, &sbuf);
781 if (!NT_STATUS_IS_OK(status)) {
782 END_PROFILE(SMBsetatr);
783 return ERROR_NT(status);
786 if (fname[0] == '.' && fname[1] == '\0') {
788 * Not sure here is the right place to catch this
789 * condition. Might be moved to somewhere else later -- vl
791 END_PROFILE(SMBsetatr);
792 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
795 if (!check_name(fname,conn)) {
796 END_PROFILE(SMBsetatr);
797 return UNIXERROR(ERRDOS, ERRnoaccess);
800 mode = SVAL(inbuf,smb_vwv0);
801 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
803 if (mode != FILE_ATTRIBUTE_NORMAL) {
804 if (VALID_STAT_OF_DIR(sbuf))
805 mode |= aDIR;
806 else
807 mode &= ~aDIR;
809 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
810 END_PROFILE(SMBsetatr);
811 return UNIXERROR(ERRDOS, ERRnoaccess);
815 if (!set_filetime(conn,fname,mtime)) {
816 END_PROFILE(SMBsetatr);
817 return UNIXERROR(ERRDOS, ERRnoaccess);
820 outsize = set_message(outbuf,0,0,False);
822 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
824 END_PROFILE(SMBsetatr);
825 return(outsize);
828 /****************************************************************************
829 Reply to a dskattr.
830 ****************************************************************************/
832 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
834 int outsize = 0;
835 SMB_BIG_UINT dfree,dsize,bsize;
836 START_PROFILE(SMBdskattr);
838 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
839 END_PROFILE(SMBdskattr);
840 return(UNIXERROR(ERRHRD,ERRgeneral));
843 outsize = set_message(outbuf,5,0,True);
845 if (Protocol <= PROTOCOL_LANMAN2) {
846 double total_space, free_space;
847 /* we need to scale this to a number that DOS6 can handle. We
848 use floating point so we can handle large drives on systems
849 that don't have 64 bit integers
851 we end up displaying a maximum of 2G to DOS systems
853 total_space = dsize * (double)bsize;
854 free_space = dfree * (double)bsize;
856 dsize = (total_space+63*512) / (64*512);
857 dfree = (free_space+63*512) / (64*512);
859 if (dsize > 0xFFFF) dsize = 0xFFFF;
860 if (dfree > 0xFFFF) dfree = 0xFFFF;
862 SSVAL(outbuf,smb_vwv0,dsize);
863 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
864 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
865 SSVAL(outbuf,smb_vwv3,dfree);
866 } else {
867 SSVAL(outbuf,smb_vwv0,dsize);
868 SSVAL(outbuf,smb_vwv1,bsize/512);
869 SSVAL(outbuf,smb_vwv2,512);
870 SSVAL(outbuf,smb_vwv3,dfree);
873 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
875 END_PROFILE(SMBdskattr);
876 return(outsize);
879 /****************************************************************************
880 Reply to a search.
881 Can be called from SMBsearch, SMBffirst or SMBfunique.
882 ****************************************************************************/
884 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
886 pstring mask;
887 pstring directory;
888 pstring fname;
889 SMB_OFF_T size;
890 uint32 mode;
891 time_t date;
892 uint32 dirtype;
893 int outsize = 0;
894 unsigned int numentries = 0;
895 unsigned int maxentries = 0;
896 BOOL finished = False;
897 char *p;
898 BOOL ok = False;
899 int status_len;
900 pstring path;
901 char status[21];
902 int dptr_num= -1;
903 BOOL check_descend = False;
904 BOOL expect_close = False;
905 BOOL can_open = True;
906 NTSTATUS nt_status;
907 BOOL mask_contains_wcard = False;
908 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
910 START_PROFILE(SMBsearch);
912 if (lp_posix_pathnames()) {
913 END_PROFILE(SMBsearch);
914 return reply_unknown(inbuf, outbuf);
917 *mask = *directory = *fname = 0;
919 /* If we were called as SMBffirst then we must expect close. */
920 if(CVAL(inbuf,smb_com) == SMBffirst)
921 expect_close = True;
923 outsize = set_message(outbuf,1,3,True);
924 maxentries = SVAL(inbuf,smb_vwv0);
925 dirtype = SVAL(inbuf,smb_vwv1);
926 p = smb_buf(inbuf) + 1;
927 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
928 if (!NT_STATUS_IS_OK(nt_status)) {
929 END_PROFILE(SMBsearch);
930 return ERROR_NT(nt_status);
933 RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
935 p++;
936 status_len = SVAL(p, 0);
937 p += 2;
939 /* dirtype &= ~aDIR; */
941 if (status_len == 0) {
942 SMB_STRUCT_STAT sbuf;
943 pstring dir2;
945 pstrcpy(directory,path);
946 pstrcpy(dir2,path);
947 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
948 if (!NT_STATUS_IS_OK(nt_status)) {
949 END_PROFILE(SMBsearch);
950 return ERROR_NT(nt_status);
952 unix_format(dir2);
954 if (!check_name(directory,conn))
955 can_open = False;
957 p = strrchr_m(dir2,'/');
958 if (p == NULL) {
959 pstrcpy(mask,dir2);
960 *dir2 = 0;
961 } else {
962 *p = 0;
963 pstrcpy(mask,p+1);
966 p = strrchr_m(directory,'/');
967 if (!p)
968 *directory = 0;
969 else
970 *p = 0;
972 if (strlen(directory) == 0)
973 pstrcpy(directory,".");
974 memset((char *)status,'\0',21);
975 SCVAL(status,0,(dirtype & 0x1F));
976 } else {
977 int status_dirtype;
979 memcpy(status,p,21);
980 status_dirtype = CVAL(status,0) & 0x1F;
981 if (status_dirtype != (dirtype & 0x1F))
982 dirtype = status_dirtype;
984 conn->dirptr = dptr_fetch(status+12,&dptr_num);
985 if (!conn->dirptr)
986 goto SearchEmpty;
987 string_set(&conn->dirpath,dptr_path(dptr_num));
988 pstrcpy(mask, dptr_wcard(dptr_num));
991 if (can_open) {
992 p = smb_buf(outbuf) + 3;
993 ok = True;
995 if (status_len == 0) {
996 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
997 if (dptr_num < 0) {
998 if(dptr_num == -2) {
999 END_PROFILE(SMBsearch);
1000 return UNIXERROR(ERRDOS, ERRnofids);
1002 END_PROFILE(SMBsearch);
1003 return ERROR_DOS(ERRDOS,ERRnofids);
1005 } else {
1006 dirtype = dptr_attr(dptr_num);
1009 DEBUG(4,("dptr_num is %d\n",dptr_num));
1011 if (ok) {
1012 if ((dirtype&0x1F) == aVOLID) {
1013 memcpy(p,status,21);
1014 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1015 0,aVOLID,0,!allow_long_path_components);
1016 dptr_fill(p+12,dptr_num);
1017 if (dptr_zero(p+12) && (status_len==0))
1018 numentries = 1;
1019 else
1020 numentries = 0;
1021 p += DIR_STRUCT_SIZE;
1022 } else {
1023 unsigned int i;
1024 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1026 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1027 conn->dirpath,lp_dontdescend(SNUM(conn))));
1028 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1029 check_descend = True;
1031 for (i=numentries;(i<maxentries) && !finished;i++) {
1032 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1033 if (!finished) {
1034 memcpy(p,status,21);
1035 make_dir_struct(p,mask,fname,size, mode,date,
1036 !allow_long_path_components);
1037 if (!dptr_fill(p+12,dptr_num)) {
1038 break;
1040 numentries++;
1041 p += DIR_STRUCT_SIZE;
1045 } /* if (ok ) */
1049 SearchEmpty:
1051 /* If we were called as SMBffirst with smb_search_id == NULL
1052 and no entries were found then return error and close dirptr
1053 (X/Open spec) */
1055 if (numentries == 0 || !ok) {
1056 dptr_close(&dptr_num);
1057 } else if(ok && expect_close && status_len == 0) {
1058 /* Close the dptr - we know it's gone */
1059 dptr_close(&dptr_num);
1062 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1063 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1064 dptr_close(&dptr_num);
1067 if ((numentries == 0) && !mask_contains_wcard) {
1068 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1071 SSVAL(outbuf,smb_vwv0,numentries);
1072 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1073 SCVAL(smb_buf(outbuf),0,5);
1074 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1076 /* The replies here are never long name. */
1077 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1078 if (!allow_long_path_components) {
1079 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1082 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1083 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1085 outsize += DIR_STRUCT_SIZE*numentries;
1086 smb_setlen(outbuf,outsize - 4);
1088 if ((! *directory) && dptr_path(dptr_num))
1089 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1091 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1092 smb_fn_name(CVAL(inbuf,smb_com)),
1093 mask, directory, dirtype, numentries, maxentries ) );
1095 END_PROFILE(SMBsearch);
1096 return(outsize);
1099 /****************************************************************************
1100 Reply to a fclose (stop directory search).
1101 ****************************************************************************/
1103 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1105 int outsize = 0;
1106 int status_len;
1107 pstring path;
1108 char status[21];
1109 int dptr_num= -2;
1110 char *p;
1111 NTSTATUS err;
1112 BOOL path_contains_wcard = False;
1114 START_PROFILE(SMBfclose);
1116 if (lp_posix_pathnames()) {
1117 END_PROFILE(SMBfclose);
1118 return reply_unknown(inbuf, outbuf);
1121 outsize = set_message(outbuf,1,0,True);
1122 p = smb_buf(inbuf) + 1;
1123 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1124 if (!NT_STATUS_IS_OK(err)) {
1125 END_PROFILE(SMBfclose);
1126 return ERROR_NT(err);
1128 p++;
1129 status_len = SVAL(p,0);
1130 p += 2;
1132 if (status_len == 0) {
1133 END_PROFILE(SMBfclose);
1134 return ERROR_DOS(ERRSRV,ERRsrverror);
1137 memcpy(status,p,21);
1139 if(dptr_fetch(status+12,&dptr_num)) {
1140 /* Close the dptr - we know it's gone */
1141 dptr_close(&dptr_num);
1144 SSVAL(outbuf,smb_vwv0,0);
1146 DEBUG(3,("search close\n"));
1148 END_PROFILE(SMBfclose);
1149 return(outsize);
1152 /****************************************************************************
1153 Reply to an open.
1154 ****************************************************************************/
1156 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1158 pstring fname;
1159 int outsize = 0;
1160 uint32 fattr=0;
1161 SMB_OFF_T size = 0;
1162 time_t mtime=0;
1163 int info;
1164 SMB_STRUCT_STAT sbuf;
1165 files_struct *fsp;
1166 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1167 int deny_mode;
1168 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1169 uint32 access_mask;
1170 uint32 share_mode;
1171 uint32 create_disposition;
1172 uint32 create_options = 0;
1173 NTSTATUS status;
1174 START_PROFILE(SMBopen);
1176 deny_mode = SVAL(inbuf,smb_vwv0);
1178 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1179 if (!NT_STATUS_IS_OK(status)) {
1180 END_PROFILE(SMBopen);
1181 return ERROR_NT(status);
1184 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1186 status = unix_convert(conn, fname, False, NULL, &sbuf);
1187 if (!NT_STATUS_IS_OK(status)) {
1188 END_PROFILE(SMBopen);
1189 return ERROR_NT(status);
1192 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1193 &access_mask, &share_mode, &create_disposition, &create_options)) {
1194 END_PROFILE(SMBopen);
1195 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1198 status = open_file_ntcreate(conn,fname,&sbuf,
1199 access_mask,
1200 share_mode,
1201 create_disposition,
1202 create_options,
1203 dos_attr,
1204 oplock_request,
1205 &info, &fsp);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 END_PROFILE(SMBopen);
1209 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1210 /* We have re-scheduled this call. */
1211 return -1;
1213 return ERROR_NT(status);
1216 size = sbuf.st_size;
1217 fattr = dos_mode(conn,fname,&sbuf);
1218 mtime = sbuf.st_mtime;
1220 if (fattr & aDIR) {
1221 DEBUG(3,("attempt to open a directory %s\n",fname));
1222 close_file(fsp,ERROR_CLOSE);
1223 END_PROFILE(SMBopen);
1224 return ERROR_DOS(ERRDOS,ERRnoaccess);
1227 outsize = set_message(outbuf,7,0,True);
1228 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1229 SSVAL(outbuf,smb_vwv1,fattr);
1230 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1231 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1232 } else {
1233 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1235 SIVAL(outbuf,smb_vwv4,(uint32)size);
1236 SSVAL(outbuf,smb_vwv6,deny_mode);
1238 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1239 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1242 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1243 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1245 END_PROFILE(SMBopen);
1246 return(outsize);
1249 /****************************************************************************
1250 Reply to an open and X.
1251 ****************************************************************************/
1253 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1255 pstring fname;
1256 uint16 open_flags = SVAL(inbuf,smb_vwv2);
1257 int deny_mode = SVAL(inbuf,smb_vwv3);
1258 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1259 /* Breakout the oplock request bits so we can set the
1260 reply bits separately. */
1261 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1262 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1263 int oplock_request = ex_oplock_request | core_oplock_request;
1264 #if 0
1265 int smb_sattr = SVAL(inbuf,smb_vwv4);
1266 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1267 #endif
1268 int smb_ofun = SVAL(inbuf,smb_vwv8);
1269 uint32 fattr=0;
1270 int mtime=0;
1271 SMB_STRUCT_STAT sbuf;
1272 int smb_action = 0;
1273 files_struct *fsp;
1274 NTSTATUS status;
1275 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1276 ssize_t retval = -1;
1277 uint32 access_mask;
1278 uint32 share_mode;
1279 uint32 create_disposition;
1280 uint32 create_options = 0;
1282 START_PROFILE(SMBopenX);
1284 /* If it's an IPC, pass off the pipe handler. */
1285 if (IS_IPC(conn)) {
1286 if (lp_nt_pipe_support()) {
1287 END_PROFILE(SMBopenX);
1288 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1289 } else {
1290 END_PROFILE(SMBopenX);
1291 return ERROR_DOS(ERRSRV,ERRaccess);
1295 /* XXXX we need to handle passed times, sattr and flags */
1296 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1297 if (!NT_STATUS_IS_OK(status)) {
1298 END_PROFILE(SMBopenX);
1299 return ERROR_NT(status);
1302 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1304 status = unix_convert(conn, fname, False, NULL, &sbuf);
1305 if (!NT_STATUS_IS_OK(status)) {
1306 END_PROFILE(SMBopenX);
1307 return ERROR_NT(status);
1310 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1311 &access_mask,
1312 &share_mode,
1313 &create_disposition,
1314 &create_options)) {
1315 END_PROFILE(SMBopenX);
1316 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1319 status = open_file_ntcreate(conn,fname,&sbuf,
1320 access_mask,
1321 share_mode,
1322 create_disposition,
1323 create_options,
1324 smb_attr,
1325 oplock_request,
1326 &smb_action, &fsp);
1328 if (!NT_STATUS_IS_OK(status)) {
1329 END_PROFILE(SMBopenX);
1330 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1331 /* We have re-scheduled this call. */
1332 return -1;
1334 return ERROR_NT(status);
1337 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1338 if the file is truncated or created. */
1339 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1340 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1341 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1342 close_file(fsp,ERROR_CLOSE);
1343 END_PROFILE(SMBopenX);
1344 return ERROR_NT(NT_STATUS_DISK_FULL);
1346 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1347 if (retval < 0) {
1348 close_file(fsp,ERROR_CLOSE);
1349 END_PROFILE(SMBopenX);
1350 return ERROR_NT(NT_STATUS_DISK_FULL);
1352 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1355 fattr = dos_mode(conn,fname,&sbuf);
1356 mtime = sbuf.st_mtime;
1357 if (fattr & aDIR) {
1358 close_file(fsp,ERROR_CLOSE);
1359 END_PROFILE(SMBopenX);
1360 return ERROR_DOS(ERRDOS,ERRnoaccess);
1363 /* If the caller set the extended oplock request bit
1364 and we granted one (by whatever means) - set the
1365 correct bit for extended oplock reply.
1368 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1369 smb_action |= EXTENDED_OPLOCK_GRANTED;
1372 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1373 smb_action |= EXTENDED_OPLOCK_GRANTED;
1376 /* If the caller set the core oplock request bit
1377 and we granted one (by whatever means) - set the
1378 correct bit for core oplock reply.
1381 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1382 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1385 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1386 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1389 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1390 set_message(outbuf,19,0,True);
1391 } else {
1392 set_message(outbuf,15,0,True);
1394 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1395 SSVAL(outbuf,smb_vwv3,fattr);
1396 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1397 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1398 } else {
1399 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1401 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1402 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1403 SSVAL(outbuf,smb_vwv11,smb_action);
1405 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1406 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1409 END_PROFILE(SMBopenX);
1410 return chain_reply(inbuf,outbuf,length,bufsize);
1413 /****************************************************************************
1414 Reply to a SMBulogoffX.
1415 conn POINTER CAN BE NULL HERE !
1416 ****************************************************************************/
1418 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1420 uint16 vuid = SVAL(inbuf,smb_uid);
1421 user_struct *vuser = get_valid_user_struct(vuid);
1422 START_PROFILE(SMBulogoffX);
1424 if(vuser == 0)
1425 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1427 /* in user level security we are supposed to close any files
1428 open by this user */
1429 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1430 file_close_user(vuid);
1432 invalidate_vuid(vuid);
1434 set_message(outbuf,2,0,True);
1436 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1438 END_PROFILE(SMBulogoffX);
1439 return chain_reply(inbuf,outbuf,length,bufsize);
1442 /****************************************************************************
1443 Reply to a mknew or a create.
1444 ****************************************************************************/
1446 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1448 pstring fname;
1449 int com;
1450 int outsize = 0;
1451 uint32 fattr = SVAL(inbuf,smb_vwv0);
1452 struct utimbuf times;
1453 files_struct *fsp;
1454 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1455 SMB_STRUCT_STAT sbuf;
1456 NTSTATUS status;
1457 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1458 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1459 uint32 create_disposition;
1460 uint32 create_options = 0;
1462 START_PROFILE(SMBcreate);
1464 com = SVAL(inbuf,smb_com);
1466 times.modtime = srv_make_unix_date3(inbuf + smb_vwv1);
1468 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1469 if (!NT_STATUS_IS_OK(status)) {
1470 END_PROFILE(SMBcreate);
1471 return ERROR_NT(status);
1474 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1476 status = unix_convert(conn, fname, False, NULL, &sbuf);
1477 if (!NT_STATUS_IS_OK(status)) {
1478 END_PROFILE(SMBcreate);
1479 return ERROR_NT(status);
1482 if (fattr & aVOLID) {
1483 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1486 if(com == SMBmknew) {
1487 /* We should fail if file exists. */
1488 create_disposition = FILE_CREATE;
1489 } else {
1490 /* Create if file doesn't exist, truncate if it does. */
1491 create_disposition = FILE_OVERWRITE_IF;
1494 /* Open file using ntcreate. */
1495 status = open_file_ntcreate(conn,fname,&sbuf,
1496 access_mask,
1497 share_mode,
1498 create_disposition,
1499 create_options,
1500 fattr,
1501 oplock_request,
1502 NULL, &fsp);
1504 if (!NT_STATUS_IS_OK(status)) {
1505 END_PROFILE(SMBcreate);
1506 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1507 /* We have re-scheduled this call. */
1508 return -1;
1510 return ERROR_NT(status);
1513 times.actime = sbuf.st_atime;
1514 file_utime(conn, fname, &times);
1516 outsize = set_message(outbuf,1,0,True);
1517 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1519 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1520 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1523 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1524 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1527 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1528 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1530 END_PROFILE(SMBcreate);
1531 return(outsize);
1534 /****************************************************************************
1535 Reply to a create temporary file.
1536 ****************************************************************************/
1538 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1540 pstring fname;
1541 int outsize = 0;
1542 uint32 fattr = SVAL(inbuf,smb_vwv0);
1543 files_struct *fsp;
1544 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1545 int tmpfd;
1546 SMB_STRUCT_STAT sbuf;
1547 char *p, *s;
1548 NTSTATUS status;
1549 unsigned int namelen;
1551 START_PROFILE(SMBctemp);
1553 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 END_PROFILE(SMBctemp);
1556 return ERROR_NT(status);
1558 if (*fname) {
1559 pstrcat(fname,"/TMXXXXXX");
1560 } else {
1561 pstrcat(fname,"TMXXXXXX");
1564 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1566 status = unix_convert(conn, fname, False, NULL, &sbuf);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 END_PROFILE(SMBctemp);
1569 return ERROR_NT(status);
1572 tmpfd = smb_mkstemp(fname);
1573 if (tmpfd == -1) {
1574 END_PROFILE(SMBctemp);
1575 return(UNIXERROR(ERRDOS,ERRnoaccess));
1578 SMB_VFS_STAT(conn,fname,&sbuf);
1580 /* We should fail if file does not exist. */
1581 status = open_file_ntcreate(conn,fname,&sbuf,
1582 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1583 FILE_SHARE_READ|FILE_SHARE_WRITE,
1584 FILE_OPEN,
1586 fattr,
1587 oplock_request,
1588 NULL, &fsp);
1590 /* close fd from smb_mkstemp() */
1591 close(tmpfd);
1593 if (!NT_STATUS_IS_OK(status)) {
1594 END_PROFILE(SMBctemp);
1595 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1596 /* We have re-scheduled this call. */
1597 return -1;
1599 return ERROR_NT(status);
1602 outsize = set_message(outbuf,1,0,True);
1603 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1605 /* the returned filename is relative to the directory */
1606 s = strrchr_m(fname, '/');
1607 if (!s) {
1608 s = fname;
1609 } else {
1610 s++;
1613 p = smb_buf(outbuf);
1614 #if 0
1615 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1616 thing in the byte section. JRA */
1617 SSVALS(p, 0, -1); /* what is this? not in spec */
1618 #endif
1619 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1620 p += namelen;
1621 outsize = set_message_end(outbuf, p);
1623 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1624 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1627 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1628 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1631 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1632 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1633 (unsigned int)sbuf.st_mode ) );
1635 END_PROFILE(SMBctemp);
1636 return(outsize);
1639 /*******************************************************************
1640 Check if a user is allowed to rename a file.
1641 ********************************************************************/
1643 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1645 files_struct *fsp;
1646 uint32 fmode;
1647 NTSTATUS status;
1649 if (!CAN_WRITE(conn)) {
1650 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1653 fmode = dos_mode(conn,fname,pst);
1654 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1655 return NT_STATUS_NO_SUCH_FILE;
1658 if (S_ISDIR(pst->st_mode)) {
1659 return NT_STATUS_OK;
1662 status = open_file_ntcreate(conn, fname, pst,
1663 DELETE_ACCESS,
1664 FILE_SHARE_READ|FILE_SHARE_WRITE,
1665 FILE_OPEN,
1667 FILE_ATTRIBUTE_NORMAL,
1669 NULL, &fsp);
1671 if (!NT_STATUS_IS_OK(status)) {
1672 return status;
1674 close_file(fsp,NORMAL_CLOSE);
1675 return NT_STATUS_OK;
1678 /*******************************************************************
1679 Check if a user is allowed to delete a file.
1680 ********************************************************************/
1682 static NTSTATUS can_delete(connection_struct *conn, char *fname,
1683 uint32 dirtype, BOOL can_defer)
1685 SMB_STRUCT_STAT sbuf;
1686 uint32 fattr;
1687 files_struct *fsp;
1688 uint32 dirtype_orig = dirtype;
1689 NTSTATUS status;
1691 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1693 if (!CAN_WRITE(conn)) {
1694 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1697 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1698 return map_nt_error_from_unix(errno);
1701 fattr = dos_mode(conn,fname,&sbuf);
1703 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1704 dirtype = aDIR|aARCH|aRONLY;
1707 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1708 if (!dirtype) {
1709 return NT_STATUS_NO_SUCH_FILE;
1712 if (!dir_check_ftype(conn, fattr, dirtype)) {
1713 if (fattr & aDIR) {
1714 return NT_STATUS_FILE_IS_A_DIRECTORY;
1716 return NT_STATUS_NO_SUCH_FILE;
1719 if (dirtype_orig & 0x8000) {
1720 /* These will never be set for POSIX. */
1721 return NT_STATUS_NO_SUCH_FILE;
1724 #if 0
1725 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1726 return NT_STATUS_FILE_IS_A_DIRECTORY;
1729 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1730 return NT_STATUS_NO_SUCH_FILE;
1733 if (dirtype & 0xFF00) {
1734 /* These will never be set for POSIX. */
1735 return NT_STATUS_NO_SUCH_FILE;
1738 dirtype &= 0xFF;
1739 if (!dirtype) {
1740 return NT_STATUS_NO_SUCH_FILE;
1743 /* Can't delete a directory. */
1744 if (fattr & aDIR) {
1745 return NT_STATUS_FILE_IS_A_DIRECTORY;
1747 #endif
1749 #if 0 /* JRATEST */
1750 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1751 return NT_STATUS_OBJECT_NAME_INVALID;
1752 #endif /* JRATEST */
1754 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1756 On a Windows share, a file with read-only dosmode can be opened with
1757 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1758 fails with NT_STATUS_CANNOT_DELETE error.
1760 This semantic causes a problem that a user can not
1761 rename a file with read-only dosmode on a Samba share
1762 from a Windows command prompt (i.e. cmd.exe, but can rename
1763 from Windows Explorer).
1766 if (!lp_delete_readonly(SNUM(conn))) {
1767 if (fattr & aRONLY) {
1768 return NT_STATUS_CANNOT_DELETE;
1772 /* On open checks the open itself will check the share mode, so
1773 don't do it here as we'll get it wrong. */
1775 status = open_file_ntcreate(conn, fname, &sbuf,
1776 DELETE_ACCESS,
1777 FILE_SHARE_NONE,
1778 FILE_OPEN,
1780 FILE_ATTRIBUTE_NORMAL,
1781 can_defer ? 0 : INTERNAL_OPEN_ONLY,
1782 NULL, &fsp);
1784 if (NT_STATUS_IS_OK(status)) {
1785 close_file(fsp,NORMAL_CLOSE);
1787 return status;
1790 /****************************************************************************
1791 The guts of the unlink command, split out so it may be called by the NT SMB
1792 code.
1793 ****************************************************************************/
1795 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
1796 char *name, BOOL has_wild, BOOL can_defer)
1798 pstring directory;
1799 pstring mask;
1800 char *p;
1801 int count=0;
1802 NTSTATUS status = NT_STATUS_OK;
1803 SMB_STRUCT_STAT sbuf;
1805 *directory = *mask = 0;
1807 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1808 if (!NT_STATUS_IS_OK(status)) {
1809 return status;
1812 p = strrchr_m(name,'/');
1813 if (!p) {
1814 pstrcpy(directory,".");
1815 pstrcpy(mask,name);
1816 } else {
1817 *p = 0;
1818 pstrcpy(directory,name);
1819 pstrcpy(mask,p+1);
1823 * We should only check the mangled cache
1824 * here if unix_convert failed. This means
1825 * that the path in 'mask' doesn't exist
1826 * on the file system and so we need to look
1827 * for a possible mangle. This patch from
1828 * Tine Smukavec <valentin.smukavec@hermes.si>.
1831 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
1832 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
1834 if (!has_wild) {
1835 pstrcat(directory,"/");
1836 pstrcat(directory,mask);
1837 if (dirtype == 0) {
1838 dirtype = FILE_ATTRIBUTE_NORMAL;
1840 status = can_delete(conn,directory,dirtype,can_defer);
1841 if (!NT_STATUS_IS_OK(status))
1842 return status;
1844 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1845 count++;
1847 } else {
1848 struct smb_Dir *dir_hnd = NULL;
1849 const char *dname;
1851 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
1852 return NT_STATUS_OBJECT_NAME_INVALID;
1855 if (strequal(mask,"????????.???"))
1856 pstrcpy(mask,"*");
1858 if (check_name(directory,conn))
1859 dir_hnd = OpenDir(conn, directory, mask, dirtype);
1861 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1862 the pattern matches against the long name, otherwise the short name
1863 We don't implement this yet XXXX
1866 if (dir_hnd) {
1867 long offset = 0;
1868 status = NT_STATUS_NO_SUCH_FILE;
1870 while ((dname = ReadDirName(dir_hnd, &offset))) {
1871 SMB_STRUCT_STAT st;
1872 pstring fname;
1873 pstrcpy(fname,dname);
1875 if (!is_visible_file(conn, directory, dname, &st, True)) {
1876 continue;
1879 /* Quick check for "." and ".." */
1880 if (fname[0] == '.') {
1881 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1882 continue;
1886 if(!mask_match(fname, mask, conn->case_sensitive))
1887 continue;
1889 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1890 status = can_delete(conn, fname, dirtype,
1891 can_defer);
1892 if (!NT_STATUS_IS_OK(status)) {
1893 continue;
1895 if (SMB_VFS_UNLINK(conn,fname) == 0)
1896 count++;
1897 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1899 CloseDir(dir_hnd);
1903 if (count == 0 && NT_STATUS_IS_OK(status)) {
1904 status = map_nt_error_from_unix(errno);
1907 return status;
1910 /****************************************************************************
1911 Reply to a unlink
1912 ****************************************************************************/
1914 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1915 int dum_buffsize)
1917 int outsize = 0;
1918 pstring name;
1919 uint32 dirtype;
1920 NTSTATUS status;
1921 BOOL path_contains_wcard = False;
1923 START_PROFILE(SMBunlink);
1925 dirtype = SVAL(inbuf,smb_vwv0);
1927 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
1928 if (!NT_STATUS_IS_OK(status)) {
1929 END_PROFILE(SMBunlink);
1930 return ERROR_NT(status);
1933 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
1935 DEBUG(3,("reply_unlink : %s\n",name));
1937 status = unlink_internals(conn, dirtype, name, path_contains_wcard,
1938 True);
1939 if (!NT_STATUS_IS_OK(status)) {
1940 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1941 /* We have re-scheduled this call. */
1942 return -1;
1944 return ERROR_NT(status);
1948 * Win2k needs a changenotify request response before it will
1949 * update after a rename..
1951 process_pending_change_notify_queue((time_t)0);
1953 outsize = set_message(outbuf,0,0,False);
1955 END_PROFILE(SMBunlink);
1956 return outsize;
1959 /****************************************************************************
1960 Fail for readbraw.
1961 ****************************************************************************/
1963 static void fail_readraw(void)
1965 pstring errstr;
1966 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1967 strerror(errno) );
1968 exit_server_cleanly(errstr);
1971 #if defined(WITH_SENDFILE)
1972 /****************************************************************************
1973 Fake (read/write) sendfile. Returns -1 on read or write fail.
1974 ****************************************************************************/
1976 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1978 ssize_t ret=0;
1980 /* Paranioa check... */
1981 if (nread > bufsize) {
1982 fail_readraw();
1985 if (nread > 0) {
1986 ret = read_file(fsp,buf,startpos,nread);
1987 if (ret == -1) {
1988 return -1;
1992 /* If we had a short read, fill with zeros. */
1993 if (ret < nread) {
1994 memset(buf, '\0', nread - ret);
1997 if (write_data(smbd_server_fd(),buf,nread) != nread) {
1998 return -1;
2001 return (ssize_t)nread;
2003 #endif
2005 /****************************************************************************
2006 Use sendfile in readbraw.
2007 ****************************************************************************/
2009 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2010 ssize_t mincount, char *outbuf, int out_buffsize)
2012 ssize_t ret=0;
2014 #if defined(WITH_SENDFILE)
2016 * We can only use sendfile on a non-chained packet
2017 * but we can use on a non-oplocked file. tridge proved this
2018 * on a train in Germany :-). JRA.
2019 * reply_readbraw has already checked the length.
2022 if ( (chain_size == 0) && (nread > 0) &&
2023 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2024 DATA_BLOB header;
2026 _smb_setlen(outbuf,nread);
2027 header.data = (uint8 *)outbuf;
2028 header.length = 4;
2029 header.free = NULL;
2031 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2032 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2033 if (errno == ENOSYS) {
2034 goto normal_readbraw;
2038 * Special hack for broken Linux with no working sendfile. If we
2039 * return EINTR we sent the header but not the rest of the data.
2040 * Fake this up by doing read/write calls.
2042 if (errno == EINTR) {
2043 /* Ensure we don't do this again. */
2044 set_use_sendfile(SNUM(conn), False);
2045 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2047 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2048 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2049 fsp->fsp_name, strerror(errno) ));
2050 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2052 return;
2055 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2056 fsp->fsp_name, strerror(errno) ));
2057 exit_server_cleanly("send_file_readbraw sendfile failed");
2062 normal_readbraw:
2064 #endif
2066 if (nread > 0) {
2067 ret = read_file(fsp,outbuf+4,startpos,nread);
2068 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2069 if (ret < mincount)
2070 ret = 0;
2071 #else
2072 if (ret < nread)
2073 ret = 0;
2074 #endif
2077 _smb_setlen(outbuf,ret);
2078 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2079 fail_readraw();
2082 /****************************************************************************
2083 Reply to a readbraw (core+ protocol).
2084 ****************************************************************************/
2086 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2088 ssize_t maxcount,mincount;
2089 size_t nread = 0;
2090 SMB_OFF_T startpos;
2091 char *header = outbuf;
2092 files_struct *fsp;
2093 START_PROFILE(SMBreadbraw);
2095 if (srv_is_signing_active()) {
2096 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2100 * Special check if an oplock break has been issued
2101 * and the readraw request croses on the wire, we must
2102 * return a zero length response here.
2105 fsp = file_fsp(inbuf,smb_vwv0);
2107 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2109 * fsp could be NULL here so use the value from the packet. JRA.
2111 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2112 _smb_setlen(header,0);
2113 if (write_data(smbd_server_fd(),header,4) != 4)
2114 fail_readraw();
2115 END_PROFILE(SMBreadbraw);
2116 return(-1);
2119 CHECK_FSP(fsp,conn);
2121 flush_write_cache(fsp, READRAW_FLUSH);
2123 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2124 if(CVAL(inbuf,smb_wct) == 10) {
2126 * This is a large offset (64 bit) read.
2128 #ifdef LARGE_SMB_OFF_T
2130 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2132 #else /* !LARGE_SMB_OFF_T */
2135 * Ensure we haven't been sent a >32 bit offset.
2138 if(IVAL(inbuf,smb_vwv8) != 0) {
2139 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2140 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2141 _smb_setlen(header,0);
2142 if (write_data(smbd_server_fd(),header,4) != 4)
2143 fail_readraw();
2144 END_PROFILE(SMBreadbraw);
2145 return(-1);
2148 #endif /* LARGE_SMB_OFF_T */
2150 if(startpos < 0) {
2151 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2152 _smb_setlen(header,0);
2153 if (write_data(smbd_server_fd(),header,4) != 4)
2154 fail_readraw();
2155 END_PROFILE(SMBreadbraw);
2156 return(-1);
2159 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2160 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2162 /* ensure we don't overrun the packet size */
2163 maxcount = MIN(65535,maxcount);
2165 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2166 SMB_STRUCT_STAT st;
2167 SMB_OFF_T size = 0;
2169 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2170 size = st.st_size;
2173 if (startpos >= size) {
2174 nread = 0;
2175 } else {
2176 nread = MIN(maxcount,(size - startpos));
2180 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2181 if (nread < mincount)
2182 nread = 0;
2183 #endif
2185 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2186 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2188 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2190 DEBUG(5,("readbraw finished\n"));
2191 END_PROFILE(SMBreadbraw);
2192 return -1;
2195 #undef DBGC_CLASS
2196 #define DBGC_CLASS DBGC_LOCKING
2198 /****************************************************************************
2199 Reply to a lockread (core+ protocol).
2200 ****************************************************************************/
2202 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2204 ssize_t nread = -1;
2205 char *data;
2206 int outsize = 0;
2207 SMB_OFF_T startpos;
2208 size_t numtoread;
2209 NTSTATUS status;
2210 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2211 struct byte_range_lock *br_lck = NULL;
2212 START_PROFILE(SMBlockread);
2214 CHECK_FSP(fsp,conn);
2215 if (!CHECK_READ(fsp,inbuf)) {
2216 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2219 release_level_2_oplocks_on_change(fsp);
2221 numtoread = SVAL(inbuf,smb_vwv1);
2222 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2224 outsize = set_message(outbuf,5,3,True);
2225 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2226 data = smb_buf(outbuf) + 3;
2229 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2230 * protocol request that predates the read/write lock concept.
2231 * Thus instead of asking for a read lock here we need to ask
2232 * for a write lock. JRA.
2233 * Note that the requested lock size is unaffected by max_recv.
2236 br_lck = do_lock(fsp,
2237 (uint32)SVAL(inbuf,smb_pid),
2238 (SMB_BIG_UINT)numtoread,
2239 (SMB_BIG_UINT)startpos,
2240 WRITE_LOCK,
2241 WINDOWS_LOCK,
2242 False, /* Non-blocking lock. */
2243 &status);
2244 TALLOC_FREE(br_lck);
2246 if (NT_STATUS_V(status)) {
2247 END_PROFILE(SMBlockread);
2248 return ERROR_NT(status);
2252 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2255 if (numtoread > max_recv) {
2256 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2257 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2258 (unsigned int)numtoread, (unsigned int)max_recv ));
2259 numtoread = MIN(numtoread,max_recv);
2261 nread = read_file(fsp,data,startpos,numtoread);
2263 if (nread < 0) {
2264 END_PROFILE(SMBlockread);
2265 return(UNIXERROR(ERRDOS,ERRnoaccess));
2268 outsize += nread;
2269 SSVAL(outbuf,smb_vwv0,nread);
2270 SSVAL(outbuf,smb_vwv5,nread+3);
2271 SSVAL(smb_buf(outbuf),1,nread);
2273 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2274 fsp->fnum, (int)numtoread, (int)nread));
2276 END_PROFILE(SMBlockread);
2277 return(outsize);
2280 #undef DBGC_CLASS
2281 #define DBGC_CLASS DBGC_ALL
2283 /****************************************************************************
2284 Reply to a read.
2285 ****************************************************************************/
2287 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2289 size_t numtoread;
2290 ssize_t nread = 0;
2291 char *data;
2292 SMB_OFF_T startpos;
2293 int outsize = 0;
2294 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2295 START_PROFILE(SMBread);
2297 CHECK_FSP(fsp,conn);
2298 if (!CHECK_READ(fsp,inbuf)) {
2299 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2302 numtoread = SVAL(inbuf,smb_vwv1);
2303 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2305 outsize = set_message(outbuf,5,3,True);
2306 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2308 * The requested read size cannot be greater than max_recv. JRA.
2310 if (numtoread > max_recv) {
2311 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2312 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2313 (unsigned int)numtoread, (unsigned int)max_recv ));
2314 numtoread = MIN(numtoread,max_recv);
2317 data = smb_buf(outbuf) + 3;
2319 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2320 END_PROFILE(SMBread);
2321 return ERROR_DOS(ERRDOS,ERRlock);
2324 if (numtoread > 0)
2325 nread = read_file(fsp,data,startpos,numtoread);
2327 if (nread < 0) {
2328 END_PROFILE(SMBread);
2329 return(UNIXERROR(ERRDOS,ERRnoaccess));
2332 outsize += nread;
2333 SSVAL(outbuf,smb_vwv0,nread);
2334 SSVAL(outbuf,smb_vwv5,nread+3);
2335 SCVAL(smb_buf(outbuf),0,1);
2336 SSVAL(smb_buf(outbuf),1,nread);
2338 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2339 fsp->fnum, (int)numtoread, (int)nread ) );
2341 END_PROFILE(SMBread);
2342 return(outsize);
2345 /****************************************************************************
2346 Reply to a read and X - possibly using sendfile.
2347 ****************************************************************************/
2349 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2350 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2352 int outsize = 0;
2353 ssize_t nread = -1;
2354 char *data = smb_buf(outbuf);
2356 #if defined(WITH_SENDFILE)
2358 * We can only use sendfile on a non-chained packet
2359 * but we can use on a non-oplocked file. tridge proved this
2360 * on a train in Germany :-). JRA.
2363 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2364 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2365 SMB_STRUCT_STAT sbuf;
2366 DATA_BLOB header;
2368 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2369 return(UNIXERROR(ERRDOS,ERRnoaccess));
2371 if (startpos > sbuf.st_size)
2372 goto normal_read;
2374 if (smb_maxcnt > (sbuf.st_size - startpos))
2375 smb_maxcnt = (sbuf.st_size - startpos);
2377 if (smb_maxcnt == 0)
2378 goto normal_read;
2381 * Set up the packet header before send. We
2382 * assume here the sendfile will work (get the
2383 * correct amount of data).
2386 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2387 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2388 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2389 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2390 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2391 SCVAL(outbuf,smb_vwv0,0xFF);
2392 set_message(outbuf,12,smb_maxcnt,False);
2393 header.data = (uint8 *)outbuf;
2394 header.length = data - outbuf;
2395 header.free = NULL;
2397 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2398 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2399 if (errno == ENOSYS) {
2400 goto normal_read;
2404 * Special hack for broken Linux with no working sendfile. If we
2405 * return EINTR we sent the header but not the rest of the data.
2406 * Fake this up by doing read/write calls.
2409 if (errno == EINTR) {
2410 /* Ensure we don't do this again. */
2411 set_use_sendfile(SNUM(conn), False);
2412 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2414 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2415 len_outbuf - (data-outbuf))) == -1) {
2416 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2417 fsp->fsp_name, strerror(errno) ));
2418 exit_server_cleanly("send_file_readX: fake_sendfile failed");
2420 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2421 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2422 /* Returning -1 here means successful sendfile. */
2423 return -1;
2426 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2427 fsp->fsp_name, strerror(errno) ));
2428 exit_server_cleanly("send_file_readX sendfile failed");
2431 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2432 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2433 /* Returning -1 here means successful sendfile. */
2434 return -1;
2437 normal_read:
2439 #endif
2441 nread = read_file(fsp,data,startpos,smb_maxcnt);
2443 if (nread < 0) {
2444 return(UNIXERROR(ERRDOS,ERRnoaccess));
2447 outsize = set_message(outbuf,12,nread,False);
2448 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2449 SSVAL(outbuf,smb_vwv5,nread);
2450 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2451 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2452 SSVAL(smb_buf(outbuf),-2,nread);
2454 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2455 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2457 /* Returning the number of bytes we want to send back - including header. */
2458 return outsize;
2461 /****************************************************************************
2462 Reply to a read and X.
2463 ****************************************************************************/
2465 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2467 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2468 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2469 ssize_t nread = -1;
2470 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2471 #if 0
2472 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2473 #endif
2475 START_PROFILE(SMBreadX);
2477 /* If it's an IPC, pass off the pipe handler. */
2478 if (IS_IPC(conn)) {
2479 END_PROFILE(SMBreadX);
2480 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2483 CHECK_FSP(fsp,conn);
2484 if (!CHECK_READ(fsp,inbuf)) {
2485 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2488 set_message(outbuf,12,0,True);
2490 if (global_client_caps & CAP_LARGE_READX) {
2491 if (SVAL(inbuf,smb_vwv7) == 1) {
2492 smb_maxcnt |= (1<<16);
2494 if (smb_maxcnt > BUFFER_SIZE) {
2495 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2496 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2497 END_PROFILE(SMBreadX);
2498 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2502 if(CVAL(inbuf,smb_wct) == 12) {
2503 #ifdef LARGE_SMB_OFF_T
2505 * This is a large offset (64 bit) read.
2507 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2509 #else /* !LARGE_SMB_OFF_T */
2512 * Ensure we haven't been sent a >32 bit offset.
2515 if(IVAL(inbuf,smb_vwv10) != 0) {
2516 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2517 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2518 END_PROFILE(SMBreadX);
2519 return ERROR_DOS(ERRDOS,ERRbadaccess);
2522 #endif /* LARGE_SMB_OFF_T */
2526 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2527 END_PROFILE(SMBreadX);
2528 return ERROR_DOS(ERRDOS,ERRlock);
2531 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2532 END_PROFILE(SMBreadX);
2533 return -1;
2536 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2537 if (nread != -1)
2538 nread = chain_reply(inbuf,outbuf,length,bufsize);
2540 END_PROFILE(SMBreadX);
2541 return nread;
2544 /****************************************************************************
2545 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2546 ****************************************************************************/
2548 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2550 ssize_t nwritten=0;
2551 ssize_t total_written=0;
2552 size_t numtowrite=0;
2553 size_t tcount;
2554 SMB_OFF_T startpos;
2555 char *data=NULL;
2556 BOOL write_through;
2557 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2558 int outsize = 0;
2559 START_PROFILE(SMBwritebraw);
2561 if (srv_is_signing_active()) {
2562 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2565 CHECK_FSP(fsp,conn);
2566 if (!CHECK_WRITE(fsp)) {
2567 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2570 tcount = IVAL(inbuf,smb_vwv1);
2571 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2572 write_through = BITSETW(inbuf+smb_vwv7,0);
2574 /* We have to deal with slightly different formats depending
2575 on whether we are using the core+ or lanman1.0 protocol */
2577 if(Protocol <= PROTOCOL_COREPLUS) {
2578 numtowrite = SVAL(smb_buf(inbuf),-2);
2579 data = smb_buf(inbuf);
2580 } else {
2581 numtowrite = SVAL(inbuf,smb_vwv10);
2582 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2585 /* force the error type */
2586 SCVAL(inbuf,smb_com,SMBwritec);
2587 SCVAL(outbuf,smb_com,SMBwritec);
2589 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2590 END_PROFILE(SMBwritebraw);
2591 return(ERROR_DOS(ERRDOS,ERRlock));
2594 if (numtowrite>0)
2595 nwritten = write_file(fsp,data,startpos,numtowrite);
2597 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2598 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2600 if (nwritten < (ssize_t)numtowrite) {
2601 END_PROFILE(SMBwritebraw);
2602 return(UNIXERROR(ERRHRD,ERRdiskfull));
2605 total_written = nwritten;
2607 /* Return a message to the redirector to tell it to send more bytes */
2608 SCVAL(outbuf,smb_com,SMBwritebraw);
2609 SSVALS(outbuf,smb_vwv0,-1);
2610 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2611 show_msg(outbuf);
2612 if (!send_smb(smbd_server_fd(),outbuf))
2613 exit_server_cleanly("reply_writebraw: send_smb failed.");
2615 /* Now read the raw data into the buffer and write it */
2616 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2617 exit_server_cleanly("secondary writebraw failed");
2620 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2621 numtowrite = smb_len(inbuf);
2623 /* Set up outbuf to return the correct return */
2624 outsize = set_message(outbuf,1,0,True);
2625 SCVAL(outbuf,smb_com,SMBwritec);
2627 if (numtowrite != 0) {
2629 if (numtowrite > BUFFER_SIZE) {
2630 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2631 (unsigned int)numtowrite ));
2632 exit_server_cleanly("secondary writebraw failed");
2635 if (tcount > nwritten+numtowrite) {
2636 DEBUG(3,("Client overestimated the write %d %d %d\n",
2637 (int)tcount,(int)nwritten,(int)numtowrite));
2640 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2641 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2642 strerror(errno) ));
2643 exit_server_cleanly("secondary writebraw failed");
2646 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2647 if (nwritten == -1) {
2648 END_PROFILE(SMBwritebraw);
2649 return(UNIXERROR(ERRHRD,ERRdiskfull));
2652 if (nwritten < (ssize_t)numtowrite) {
2653 SCVAL(outbuf,smb_rcls,ERRHRD);
2654 SSVAL(outbuf,smb_err,ERRdiskfull);
2657 if (nwritten > 0)
2658 total_written += nwritten;
2661 SSVAL(outbuf,smb_vwv0,total_written);
2663 sync_file(conn, fsp, write_through);
2665 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2666 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2668 /* we won't return a status if write through is not selected - this follows what WfWg does */
2669 END_PROFILE(SMBwritebraw);
2670 if (!write_through && total_written==tcount) {
2672 #if RABBIT_PELLET_FIX
2674 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2675 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2677 if (!send_keepalive(smbd_server_fd()))
2678 exit_server_cleanly("reply_writebraw: send of keepalive failed");
2679 #endif
2680 return(-1);
2683 return(outsize);
2686 #undef DBGC_CLASS
2687 #define DBGC_CLASS DBGC_LOCKING
2689 /****************************************************************************
2690 Reply to a writeunlock (core+).
2691 ****************************************************************************/
2693 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2694 int size, int dum_buffsize)
2696 ssize_t nwritten = -1;
2697 size_t numtowrite;
2698 SMB_OFF_T startpos;
2699 char *data;
2700 NTSTATUS status = NT_STATUS_OK;
2701 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2702 int outsize = 0;
2703 START_PROFILE(SMBwriteunlock);
2705 CHECK_FSP(fsp,conn);
2706 if (!CHECK_WRITE(fsp)) {
2707 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2710 numtowrite = SVAL(inbuf,smb_vwv1);
2711 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2712 data = smb_buf(inbuf) + 3;
2714 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2715 END_PROFILE(SMBwriteunlock);
2716 return ERROR_DOS(ERRDOS,ERRlock);
2719 /* The special X/Open SMB protocol handling of
2720 zero length writes is *NOT* done for
2721 this call */
2722 if(numtowrite == 0) {
2723 nwritten = 0;
2724 } else {
2725 nwritten = write_file(fsp,data,startpos,numtowrite);
2728 sync_file(conn, fsp, False /* write through */);
2730 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2731 END_PROFILE(SMBwriteunlock);
2732 return(UNIXERROR(ERRHRD,ERRdiskfull));
2735 if (numtowrite) {
2736 status = do_unlock(fsp,
2737 (uint32)SVAL(inbuf,smb_pid),
2738 (SMB_BIG_UINT)numtowrite,
2739 (SMB_BIG_UINT)startpos,
2740 WINDOWS_LOCK);
2742 if (NT_STATUS_V(status)) {
2743 END_PROFILE(SMBwriteunlock);
2744 return ERROR_NT(status);
2748 outsize = set_message(outbuf,1,0,True);
2750 SSVAL(outbuf,smb_vwv0,nwritten);
2752 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2753 fsp->fnum, (int)numtowrite, (int)nwritten));
2755 END_PROFILE(SMBwriteunlock);
2756 return outsize;
2759 #undef DBGC_CLASS
2760 #define DBGC_CLASS DBGC_ALL
2762 /****************************************************************************
2763 Reply to a write.
2764 ****************************************************************************/
2766 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2768 size_t numtowrite;
2769 ssize_t nwritten = -1;
2770 SMB_OFF_T startpos;
2771 char *data;
2772 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2773 int outsize = 0;
2774 START_PROFILE(SMBwrite);
2776 /* If it's an IPC, pass off the pipe handler. */
2777 if (IS_IPC(conn)) {
2778 END_PROFILE(SMBwrite);
2779 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2782 CHECK_FSP(fsp,conn);
2783 if (!CHECK_WRITE(fsp)) {
2784 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2787 numtowrite = SVAL(inbuf,smb_vwv1);
2788 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2789 data = smb_buf(inbuf) + 3;
2791 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2792 END_PROFILE(SMBwrite);
2793 return ERROR_DOS(ERRDOS,ERRlock);
2797 * X/Open SMB protocol says that if smb_vwv1 is
2798 * zero then the file size should be extended or
2799 * truncated to the size given in smb_vwv[2-3].
2802 if(numtowrite == 0) {
2804 * This is actually an allocate call, and set EOF. JRA.
2806 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2807 if (nwritten < 0) {
2808 END_PROFILE(SMBwrite);
2809 return ERROR_NT(NT_STATUS_DISK_FULL);
2811 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2812 if (nwritten < 0) {
2813 END_PROFILE(SMBwrite);
2814 return ERROR_NT(NT_STATUS_DISK_FULL);
2816 } else
2817 nwritten = write_file(fsp,data,startpos,numtowrite);
2819 sync_file(conn, fsp, False);
2821 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2822 END_PROFILE(SMBwrite);
2823 return(UNIXERROR(ERRHRD,ERRdiskfull));
2826 outsize = set_message(outbuf,1,0,True);
2828 SSVAL(outbuf,smb_vwv0,nwritten);
2830 if (nwritten < (ssize_t)numtowrite) {
2831 SCVAL(outbuf,smb_rcls,ERRHRD);
2832 SSVAL(outbuf,smb_err,ERRdiskfull);
2835 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2837 END_PROFILE(SMBwrite);
2838 return(outsize);
2841 /****************************************************************************
2842 Reply to a write and X.
2843 ****************************************************************************/
2845 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2847 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2848 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2849 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2850 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2851 ssize_t nwritten = -1;
2852 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2853 unsigned int smblen = smb_len(inbuf);
2854 char *data;
2855 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2856 START_PROFILE(SMBwriteX);
2858 /* If it's an IPC, pass off the pipe handler. */
2859 if (IS_IPC(conn)) {
2860 END_PROFILE(SMBwriteX);
2861 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2864 CHECK_FSP(fsp,conn);
2865 if (!CHECK_WRITE(fsp)) {
2866 return(ERROR_DOS(ERRDOS,ERRbadaccess));
2869 set_message(outbuf,6,0,True);
2871 /* Deal with possible LARGE_WRITEX */
2872 if (large_writeX) {
2873 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2876 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2877 END_PROFILE(SMBwriteX);
2878 return ERROR_DOS(ERRDOS,ERRbadmem);
2881 data = smb_base(inbuf) + smb_doff;
2883 if(CVAL(inbuf,smb_wct) == 14) {
2884 #ifdef LARGE_SMB_OFF_T
2886 * This is a large offset (64 bit) write.
2888 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2890 #else /* !LARGE_SMB_OFF_T */
2893 * Ensure we haven't been sent a >32 bit offset.
2896 if(IVAL(inbuf,smb_vwv12) != 0) {
2897 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2898 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2899 END_PROFILE(SMBwriteX);
2900 return ERROR_DOS(ERRDOS,ERRbadaccess);
2903 #endif /* LARGE_SMB_OFF_T */
2906 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2907 END_PROFILE(SMBwriteX);
2908 return ERROR_DOS(ERRDOS,ERRlock);
2911 /* X/Open SMB protocol says that, unlike SMBwrite
2912 if the length is zero then NO truncation is
2913 done, just a write of zero. To truncate a file,
2914 use SMBwrite. */
2916 if(numtowrite == 0) {
2917 nwritten = 0;
2918 } else {
2920 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
2921 fsp,data,startpos,numtowrite)) {
2922 END_PROFILE(SMBwriteX);
2923 return -1;
2926 nwritten = write_file(fsp,data,startpos,numtowrite);
2929 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2930 END_PROFILE(SMBwriteX);
2931 return(UNIXERROR(ERRHRD,ERRdiskfull));
2934 SSVAL(outbuf,smb_vwv2,nwritten);
2935 if (large_writeX)
2936 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2938 if (nwritten < (ssize_t)numtowrite) {
2939 SCVAL(outbuf,smb_rcls,ERRHRD);
2940 SSVAL(outbuf,smb_err,ERRdiskfull);
2943 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2944 fsp->fnum, (int)numtowrite, (int)nwritten));
2946 sync_file(conn, fsp, write_through);
2948 END_PROFILE(SMBwriteX);
2949 return chain_reply(inbuf,outbuf,length,bufsize);
2952 /****************************************************************************
2953 Reply to a lseek.
2954 ****************************************************************************/
2956 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2958 SMB_OFF_T startpos;
2959 SMB_OFF_T res= -1;
2960 int mode,umode;
2961 int outsize = 0;
2962 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2963 START_PROFILE(SMBlseek);
2965 CHECK_FSP(fsp,conn);
2967 flush_write_cache(fsp, SEEK_FLUSH);
2969 mode = SVAL(inbuf,smb_vwv1) & 3;
2970 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2971 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2973 switch (mode) {
2974 case 0:
2975 umode = SEEK_SET;
2976 res = startpos;
2977 break;
2978 case 1:
2979 umode = SEEK_CUR;
2980 res = fsp->fh->pos + startpos;
2981 break;
2982 case 2:
2983 umode = SEEK_END;
2984 break;
2985 default:
2986 umode = SEEK_SET;
2987 res = startpos;
2988 break;
2991 if (umode == SEEK_END) {
2992 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
2993 if(errno == EINVAL) {
2994 SMB_OFF_T current_pos = startpos;
2995 SMB_STRUCT_STAT sbuf;
2997 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
2998 END_PROFILE(SMBlseek);
2999 return(UNIXERROR(ERRDOS,ERRnoaccess));
3002 current_pos += sbuf.st_size;
3003 if(current_pos < 0)
3004 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3008 if(res == -1) {
3009 END_PROFILE(SMBlseek);
3010 return(UNIXERROR(ERRDOS,ERRnoaccess));
3014 fsp->fh->pos = res;
3016 outsize = set_message(outbuf,2,0,True);
3017 SIVAL(outbuf,smb_vwv0,res);
3019 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3020 fsp->fnum, (double)startpos, (double)res, mode));
3022 END_PROFILE(SMBlseek);
3023 return(outsize);
3026 /****************************************************************************
3027 Reply to a flush.
3028 ****************************************************************************/
3030 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3032 int outsize = set_message(outbuf,0,0,False);
3033 uint16 fnum = SVAL(inbuf,smb_vwv0);
3034 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3035 START_PROFILE(SMBflush);
3037 if (fnum != 0xFFFF)
3038 CHECK_FSP(fsp,conn);
3040 if (!fsp) {
3041 file_sync_all(conn);
3042 } else {
3043 sync_file(conn,fsp, True);
3046 DEBUG(3,("flush\n"));
3047 END_PROFILE(SMBflush);
3048 return(outsize);
3051 /****************************************************************************
3052 Reply to a exit.
3053 conn POINTER CAN BE NULL HERE !
3054 ****************************************************************************/
3056 int reply_exit(connection_struct *conn,
3057 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3059 int outsize;
3060 START_PROFILE(SMBexit);
3062 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3064 outsize = set_message(outbuf,0,0,False);
3066 DEBUG(3,("exit\n"));
3068 END_PROFILE(SMBexit);
3069 return(outsize);
3072 /****************************************************************************
3073 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3074 ****************************************************************************/
3076 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3077 int dum_buffsize)
3079 int outsize = 0;
3080 time_t mtime;
3081 int32 eclass = 0, err = 0;
3082 files_struct *fsp = NULL;
3083 START_PROFILE(SMBclose);
3085 outsize = set_message(outbuf,0,0,False);
3087 /* If it's an IPC, pass off to the pipe handler. */
3088 if (IS_IPC(conn)) {
3089 END_PROFILE(SMBclose);
3090 return reply_pipe_close(conn, inbuf,outbuf);
3093 fsp = file_fsp(inbuf,smb_vwv0);
3096 * We can only use CHECK_FSP if we know it's not a directory.
3099 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3100 END_PROFILE(SMBclose);
3101 return ERROR_DOS(ERRDOS,ERRbadfid);
3104 if(fsp->is_directory) {
3106 * Special case - close NT SMB directory handle.
3108 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3109 close_file(fsp,NORMAL_CLOSE);
3110 } else {
3112 * Close ordinary file.
3114 int close_err;
3116 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3117 fsp->fh->fd, fsp->fnum,
3118 conn->num_files_open));
3121 * Take care of any time sent in the close.
3124 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
3125 fsp_set_pending_modtime(fsp, mtime);
3128 * close_file() returns the unix errno if an error
3129 * was detected on close - normally this is due to
3130 * a disk full error. If not then it was probably an I/O error.
3133 if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) {
3134 errno = close_err;
3135 END_PROFILE(SMBclose);
3136 return (UNIXERROR(ERRHRD,ERRgeneral));
3140 /* We have a cached error */
3141 if(eclass || err) {
3142 END_PROFILE(SMBclose);
3143 return ERROR_DOS(eclass,err);
3146 END_PROFILE(SMBclose);
3147 return(outsize);
3150 /****************************************************************************
3151 Reply to a writeclose (Core+ protocol).
3152 ****************************************************************************/
3154 int reply_writeclose(connection_struct *conn,
3155 char *inbuf,char *outbuf, int size, int dum_buffsize)
3157 size_t numtowrite;
3158 ssize_t nwritten = -1;
3159 int outsize = 0;
3160 int close_err = 0;
3161 SMB_OFF_T startpos;
3162 char *data;
3163 time_t mtime;
3164 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3165 START_PROFILE(SMBwriteclose);
3167 CHECK_FSP(fsp,conn);
3168 if (!CHECK_WRITE(fsp)) {
3169 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3172 numtowrite = SVAL(inbuf,smb_vwv1);
3173 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3174 mtime = srv_make_unix_date3(inbuf+smb_vwv4);
3175 data = smb_buf(inbuf) + 1;
3177 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3178 END_PROFILE(SMBwriteclose);
3179 return ERROR_DOS(ERRDOS,ERRlock);
3182 nwritten = write_file(fsp,data,startpos,numtowrite);
3184 set_filetime(conn, fsp->fsp_name,mtime);
3187 * More insanity. W2K only closes the file if writelen > 0.
3188 * JRA.
3191 if (numtowrite) {
3192 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3193 fsp->fsp_name ));
3194 close_err = close_file(fsp,NORMAL_CLOSE);
3197 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3198 fsp->fnum, (int)numtowrite, (int)nwritten,
3199 conn->num_files_open));
3201 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3202 END_PROFILE(SMBwriteclose);
3203 return(UNIXERROR(ERRHRD,ERRdiskfull));
3206 if(close_err != 0) {
3207 errno = close_err;
3208 END_PROFILE(SMBwriteclose);
3209 return(UNIXERROR(ERRHRD,ERRgeneral));
3212 outsize = set_message(outbuf,1,0,True);
3214 SSVAL(outbuf,smb_vwv0,nwritten);
3215 END_PROFILE(SMBwriteclose);
3216 return(outsize);
3219 #undef DBGC_CLASS
3220 #define DBGC_CLASS DBGC_LOCKING
3222 /****************************************************************************
3223 Reply to a lock.
3224 ****************************************************************************/
3226 int reply_lock(connection_struct *conn,
3227 char *inbuf,char *outbuf, int length, int dum_buffsize)
3229 int outsize = set_message(outbuf,0,0,False);
3230 SMB_BIG_UINT count,offset;
3231 NTSTATUS status;
3232 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3233 struct byte_range_lock *br_lck = NULL;
3235 START_PROFILE(SMBlock);
3237 CHECK_FSP(fsp,conn);
3239 release_level_2_oplocks_on_change(fsp);
3241 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3242 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3244 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3245 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3247 br_lck = do_lock(fsp,
3248 (uint32)SVAL(inbuf,smb_pid),
3249 count,
3250 offset,
3251 WRITE_LOCK,
3252 WINDOWS_LOCK,
3253 False, /* Non-blocking lock. */
3254 &status);
3256 TALLOC_FREE(br_lck);
3258 if (NT_STATUS_V(status)) {
3259 END_PROFILE(SMBlock);
3260 return ERROR_NT(status);
3263 END_PROFILE(SMBlock);
3264 return(outsize);
3267 /****************************************************************************
3268 Reply to a unlock.
3269 ****************************************************************************/
3271 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3272 int dum_buffsize)
3274 int outsize = set_message(outbuf,0,0,False);
3275 SMB_BIG_UINT count,offset;
3276 NTSTATUS status;
3277 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3278 START_PROFILE(SMBunlock);
3280 CHECK_FSP(fsp,conn);
3282 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3283 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3285 status = do_unlock(fsp,
3286 (uint32)SVAL(inbuf,smb_pid),
3287 count,
3288 offset,
3289 WINDOWS_LOCK);
3291 if (NT_STATUS_V(status)) {
3292 END_PROFILE(SMBunlock);
3293 return ERROR_NT(status);
3296 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3297 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3299 END_PROFILE(SMBunlock);
3300 return(outsize);
3303 #undef DBGC_CLASS
3304 #define DBGC_CLASS DBGC_ALL
3306 /****************************************************************************
3307 Reply to a tdis.
3308 conn POINTER CAN BE NULL HERE !
3309 ****************************************************************************/
3311 int reply_tdis(connection_struct *conn,
3312 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3314 int outsize = set_message(outbuf,0,0,False);
3315 uint16 vuid;
3316 START_PROFILE(SMBtdis);
3318 vuid = SVAL(inbuf,smb_uid);
3320 if (!conn) {
3321 DEBUG(4,("Invalid connection in tdis\n"));
3322 END_PROFILE(SMBtdis);
3323 return ERROR_DOS(ERRSRV,ERRinvnid);
3326 conn->used = False;
3328 close_cnum(conn,vuid);
3330 END_PROFILE(SMBtdis);
3331 return outsize;
3334 /****************************************************************************
3335 Reply to a echo.
3336 conn POINTER CAN BE NULL HERE !
3337 ****************************************************************************/
3339 int reply_echo(connection_struct *conn,
3340 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3342 int smb_reverb = SVAL(inbuf,smb_vwv0);
3343 int seq_num;
3344 unsigned int data_len = smb_buflen(inbuf);
3345 int outsize = set_message(outbuf,1,data_len,True);
3346 START_PROFILE(SMBecho);
3348 if (data_len > BUFFER_SIZE) {
3349 DEBUG(0,("reply_echo: data_len too large.\n"));
3350 END_PROFILE(SMBecho);
3351 return -1;
3354 /* copy any incoming data back out */
3355 if (data_len > 0)
3356 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3358 if (smb_reverb > 100) {
3359 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3360 smb_reverb = 100;
3363 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3364 SSVAL(outbuf,smb_vwv0,seq_num);
3366 smb_setlen(outbuf,outsize - 4);
3368 show_msg(outbuf);
3369 if (!send_smb(smbd_server_fd(),outbuf))
3370 exit_server_cleanly("reply_echo: send_smb failed.");
3373 DEBUG(3,("echo %d times\n", smb_reverb));
3375 smb_echo_count++;
3377 END_PROFILE(SMBecho);
3378 return -1;
3381 /****************************************************************************
3382 Reply to a printopen.
3383 ****************************************************************************/
3385 int reply_printopen(connection_struct *conn,
3386 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3388 int outsize = 0;
3389 files_struct *fsp;
3390 NTSTATUS status;
3392 START_PROFILE(SMBsplopen);
3394 if (!CAN_PRINT(conn)) {
3395 END_PROFILE(SMBsplopen);
3396 return ERROR_DOS(ERRDOS,ERRnoaccess);
3399 /* Open for exclusive use, write only. */
3400 status = print_fsp_open(conn, NULL, &fsp);
3402 if (!NT_STATUS_IS_OK(status)) {
3403 END_PROFILE(SMBsplopen);
3404 return(ERROR_NT(status));
3407 outsize = set_message(outbuf,1,0,True);
3408 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3410 DEBUG(3,("openprint fd=%d fnum=%d\n",
3411 fsp->fh->fd, fsp->fnum));
3413 END_PROFILE(SMBsplopen);
3414 return(outsize);
3417 /****************************************************************************
3418 Reply to a printclose.
3419 ****************************************************************************/
3421 int reply_printclose(connection_struct *conn,
3422 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3424 int outsize = set_message(outbuf,0,0,False);
3425 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3426 int close_err = 0;
3427 START_PROFILE(SMBsplclose);
3429 CHECK_FSP(fsp,conn);
3431 if (!CAN_PRINT(conn)) {
3432 END_PROFILE(SMBsplclose);
3433 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3436 DEBUG(3,("printclose fd=%d fnum=%d\n",
3437 fsp->fh->fd,fsp->fnum));
3439 close_err = close_file(fsp,NORMAL_CLOSE);
3441 if(close_err != 0) {
3442 errno = close_err;
3443 END_PROFILE(SMBsplclose);
3444 return(UNIXERROR(ERRHRD,ERRgeneral));
3447 END_PROFILE(SMBsplclose);
3448 return(outsize);
3451 /****************************************************************************
3452 Reply to a printqueue.
3453 ****************************************************************************/
3455 int reply_printqueue(connection_struct *conn,
3456 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3458 int outsize = set_message(outbuf,2,3,True);
3459 int max_count = SVAL(inbuf,smb_vwv0);
3460 int start_index = SVAL(inbuf,smb_vwv1);
3461 START_PROFILE(SMBsplretq);
3463 /* we used to allow the client to get the cnum wrong, but that
3464 is really quite gross and only worked when there was only
3465 one printer - I think we should now only accept it if they
3466 get it right (tridge) */
3467 if (!CAN_PRINT(conn)) {
3468 END_PROFILE(SMBsplretq);
3469 return ERROR_DOS(ERRDOS,ERRnoaccess);
3472 SSVAL(outbuf,smb_vwv0,0);
3473 SSVAL(outbuf,smb_vwv1,0);
3474 SCVAL(smb_buf(outbuf),0,1);
3475 SSVAL(smb_buf(outbuf),1,0);
3477 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3478 start_index, max_count));
3481 print_queue_struct *queue = NULL;
3482 print_status_struct status;
3483 char *p = smb_buf(outbuf) + 3;
3484 int count = print_queue_status(SNUM(conn), &queue, &status);
3485 int num_to_get = ABS(max_count);
3486 int first = (max_count>0?start_index:start_index+max_count+1);
3487 int i;
3489 if (first >= count)
3490 num_to_get = 0;
3491 else
3492 num_to_get = MIN(num_to_get,count-first);
3495 for (i=first;i<first+num_to_get;i++) {
3496 srv_put_dos_date2(p,0,queue[i].time);
3497 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3498 SSVAL(p,5, queue[i].job);
3499 SIVAL(p,7,queue[i].size);
3500 SCVAL(p,11,0);
3501 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3502 p += 28;
3505 if (count > 0) {
3506 outsize = set_message(outbuf,2,28*count+3,False);
3507 SSVAL(outbuf,smb_vwv0,count);
3508 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3509 SCVAL(smb_buf(outbuf),0,1);
3510 SSVAL(smb_buf(outbuf),1,28*count);
3513 SAFE_FREE(queue);
3515 DEBUG(3,("%d entries returned in queue\n",count));
3518 END_PROFILE(SMBsplretq);
3519 return(outsize);
3522 /****************************************************************************
3523 Reply to a printwrite.
3524 ****************************************************************************/
3526 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3528 int numtowrite;
3529 int outsize = set_message(outbuf,0,0,False);
3530 char *data;
3531 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3533 START_PROFILE(SMBsplwr);
3535 if (!CAN_PRINT(conn)) {
3536 END_PROFILE(SMBsplwr);
3537 return ERROR_DOS(ERRDOS,ERRnoaccess);
3540 CHECK_FSP(fsp,conn);
3541 if (!CHECK_WRITE(fsp)) {
3542 return(ERROR_DOS(ERRDOS,ERRbadaccess));
3545 numtowrite = SVAL(smb_buf(inbuf),1);
3546 data = smb_buf(inbuf) + 3;
3548 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3549 END_PROFILE(SMBsplwr);
3550 return(UNIXERROR(ERRHRD,ERRdiskfull));
3553 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3555 END_PROFILE(SMBsplwr);
3556 return(outsize);
3559 /****************************************************************************
3560 Reply to a mkdir.
3561 ****************************************************************************/
3563 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3565 pstring directory;
3566 int outsize;
3567 NTSTATUS status;
3568 SMB_STRUCT_STAT sbuf;
3570 START_PROFILE(SMBmkdir);
3572 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3573 if (!NT_STATUS_IS_OK(status)) {
3574 END_PROFILE(SMBmkdir);
3575 return ERROR_NT(status);
3578 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3580 status = unix_convert(conn, directory, False, NULL, &sbuf);
3581 if (!NT_STATUS_IS_OK(status)) {
3582 END_PROFILE(SMBmkdir);
3583 return ERROR_NT(status);
3586 status = create_directory(conn, directory);
3588 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3590 if (!NT_STATUS_IS_OK(status)) {
3592 if (!use_nt_status()
3593 && NT_STATUS_EQUAL(status,
3594 NT_STATUS_OBJECT_NAME_COLLISION)) {
3596 * Yes, in the DOS error code case we get a
3597 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3598 * samba4 torture test.
3600 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3603 END_PROFILE(SMBmkdir);
3604 return ERROR_NT(status);
3607 outsize = set_message(outbuf,0,0,False);
3609 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3611 END_PROFILE(SMBmkdir);
3612 return(outsize);
3615 /****************************************************************************
3616 Static function used by reply_rmdir to delete an entire directory
3617 tree recursively. Return True on ok, False on fail.
3618 ****************************************************************************/
3620 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3622 const char *dname = NULL;
3623 BOOL ret = True;
3624 long offset = 0;
3625 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3627 if(dir_hnd == NULL)
3628 return False;
3630 while((dname = ReadDirName(dir_hnd, &offset))) {
3631 pstring fullname;
3632 SMB_STRUCT_STAT st;
3634 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3635 continue;
3637 if (!is_visible_file(conn, directory, dname, &st, False))
3638 continue;
3640 /* Construct the full name. */
3641 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3642 errno = ENOMEM;
3643 ret = False;
3644 break;
3647 pstrcpy(fullname, directory);
3648 pstrcat(fullname, "/");
3649 pstrcat(fullname, dname);
3651 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3652 ret = False;
3653 break;
3656 if(st.st_mode & S_IFDIR) {
3657 if(!recursive_rmdir(conn, fullname)) {
3658 ret = False;
3659 break;
3661 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3662 ret = False;
3663 break;
3665 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3666 ret = False;
3667 break;
3670 CloseDir(dir_hnd);
3671 return ret;
3674 /****************************************************************************
3675 The internals of the rmdir code - called elsewhere.
3676 ****************************************************************************/
3678 BOOL rmdir_internals(connection_struct *conn, const char *directory)
3680 BOOL ok;
3681 SMB_STRUCT_STAT st;
3683 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3684 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3686 * Check to see if the only thing in this directory are
3687 * vetoed files/directories. If so then delete them and
3688 * retry. If we fail to delete any of them (and we *don't*
3689 * do a recursive delete) then fail the rmdir.
3691 const char *dname;
3692 long dirpos = 0;
3693 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3695 if(dir_hnd == NULL) {
3696 errno = ENOTEMPTY;
3697 goto err;
3700 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3701 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3702 continue;
3703 if (!is_visible_file(conn, directory, dname, &st, False))
3704 continue;
3705 if(!IS_VETO_PATH(conn, dname)) {
3706 CloseDir(dir_hnd);
3707 errno = ENOTEMPTY;
3708 goto err;
3712 /* We only have veto files/directories. Recursive delete. */
3714 RewindDir(dir_hnd,&dirpos);
3715 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3716 pstring fullname;
3718 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3719 continue;
3720 if (!is_visible_file(conn, directory, dname, &st, False))
3721 continue;
3723 /* Construct the full name. */
3724 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3725 errno = ENOMEM;
3726 break;
3729 pstrcpy(fullname, directory);
3730 pstrcat(fullname, "/");
3731 pstrcat(fullname, dname);
3733 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3734 break;
3735 if(st.st_mode & S_IFDIR) {
3736 if(lp_recursive_veto_delete(SNUM(conn))) {
3737 if(!recursive_rmdir(conn, fullname))
3738 break;
3740 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3741 break;
3742 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3743 break;
3745 CloseDir(dir_hnd);
3746 /* Retry the rmdir */
3747 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3750 err:
3752 if (!ok) {
3753 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
3754 "%s\n", directory,strerror(errno)));
3755 return False;
3758 return True;
3761 /****************************************************************************
3762 Reply to a rmdir.
3763 ****************************************************************************/
3765 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3767 pstring directory;
3768 int outsize = 0;
3769 BOOL ok = False;
3770 SMB_STRUCT_STAT sbuf;
3771 NTSTATUS status;
3772 START_PROFILE(SMBrmdir);
3774 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3775 if (!NT_STATUS_IS_OK(status)) {
3776 END_PROFILE(SMBrmdir);
3777 return ERROR_NT(status);
3780 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3782 status = unix_convert(conn, directory, False, NULL, &sbuf);
3783 if (!NT_STATUS_IS_OK(status)) {
3784 END_PROFILE(SMBrmdir);
3785 return ERROR_NT(status);
3788 if (check_name(directory,conn)) {
3789 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3790 ok = rmdir_internals(conn, directory);
3793 if (!ok) {
3794 END_PROFILE(SMBrmdir);
3795 return UNIXERROR(ERRDOS, ERRbadpath);
3798 outsize = set_message(outbuf,0,0,False);
3800 DEBUG( 3, ( "rmdir %s\n", directory ) );
3802 END_PROFILE(SMBrmdir);
3803 return(outsize);
3806 /*******************************************************************
3807 Resolve wildcards in a filename rename.
3808 Note that name is in UNIX charset and thus potentially can be more
3809 than fstring buffer (255 bytes) especially in default UTF-8 case.
3810 Therefore, we use pstring inside and all calls should ensure that
3811 name2 is at least pstring-long (they do already)
3812 ********************************************************************/
3814 static BOOL resolve_wildcards(const char *name1, char *name2)
3816 pstring root1,root2;
3817 pstring ext1,ext2;
3818 char *p,*p2, *pname1, *pname2;
3819 int available_space, actual_space;
3822 pname1 = strrchr_m(name1,'/');
3823 pname2 = strrchr_m(name2,'/');
3825 if (!pname1 || !pname2)
3826 return(False);
3828 pstrcpy(root1,pname1);
3829 pstrcpy(root2,pname2);
3830 p = strrchr_m(root1,'.');
3831 if (p) {
3832 *p = 0;
3833 pstrcpy(ext1,p+1);
3834 } else {
3835 pstrcpy(ext1,"");
3837 p = strrchr_m(root2,'.');
3838 if (p) {
3839 *p = 0;
3840 pstrcpy(ext2,p+1);
3841 } else {
3842 pstrcpy(ext2,"");
3845 p = root1;
3846 p2 = root2;
3847 while (*p2) {
3848 if (*p2 == '?') {
3849 *p2 = *p;
3850 p2++;
3851 } else if (*p2 == '*') {
3852 pstrcpy(p2, p);
3853 break;
3854 } else {
3855 p2++;
3857 if (*p)
3858 p++;
3861 p = ext1;
3862 p2 = ext2;
3863 while (*p2) {
3864 if (*p2 == '?') {
3865 *p2 = *p;
3866 p2++;
3867 } else if (*p2 == '*') {
3868 pstrcpy(p2, p);
3869 break;
3870 } else {
3871 p2++;
3873 if (*p)
3874 p++;
3877 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3879 if (ext2[0]) {
3880 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3881 if (actual_space >= available_space - 1) {
3882 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3883 actual_space - available_space));
3885 } else {
3886 pstrcpy_base(pname2, root2, name2);
3889 return(True);
3892 /****************************************************************************
3893 Ensure open files have their names updated. Updated to notify other smbd's
3894 asynchronously.
3895 ****************************************************************************/
3897 static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
3898 SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
3900 files_struct *fsp;
3901 BOOL did_rename = False;
3903 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3904 /* fsp_name is a relative path under the fsp. To change this for other
3905 sharepaths we need to manipulate relative paths. */
3906 /* TODO - create the absolute path and manipulate the newname
3907 relative to the sharepath. */
3908 if (fsp->conn != conn) {
3909 continue;
3911 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3912 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3913 fsp->fsp_name, newname ));
3914 string_set(&fsp->fsp_name, newname);
3915 did_rename = True;
3918 if (!did_rename) {
3919 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3920 (unsigned int)dev, (double)inode, newname ));
3923 /* Send messages to all smbd's (not ourself) that the name has changed. */
3924 rename_share_filename(lck, conn->connectpath, newname);
3927 /****************************************************************************
3928 We need to check if the source path is a parent directory of the destination
3929 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
3930 refuse the rename with a sharing violation. Under UNIX the above call can
3931 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
3932 probably need to check that the client is a Windows one before disallowing
3933 this as a UNIX client (one with UNIX extensions) can know the source is a
3934 symlink and make this decision intelligently. Found by an excellent bug
3935 report from <AndyLiebman@aol.com>.
3936 ****************************************************************************/
3938 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
3940 const char *psrc = src;
3941 const char *pdst = dest;
3942 size_t slen;
3944 if (psrc[0] == '.' && psrc[1] == '/') {
3945 psrc += 2;
3947 if (pdst[0] == '.' && pdst[1] == '/') {
3948 pdst += 2;
3950 if ((slen = strlen(psrc)) > strlen(pdst)) {
3951 return False;
3953 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
3956 /****************************************************************************
3957 Rename an open file - given an fsp.
3958 ****************************************************************************/
3960 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists)
3962 SMB_STRUCT_STAT sbuf;
3963 pstring newname_last_component;
3964 NTSTATUS status = NT_STATUS_OK;
3965 BOOL dest_exists;
3966 struct share_mode_lock *lck = NULL;
3968 ZERO_STRUCT(sbuf);
3970 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 return status;
3975 /* Ensure newname contains a '/' */
3976 if(strrchr_m(newname,'/') == 0) {
3977 pstring tmpstr;
3979 pstrcpy(tmpstr, "./");
3980 pstrcat(tmpstr, newname);
3981 pstrcpy(newname, tmpstr);
3985 * Check for special case with case preserving and not
3986 * case sensitive. If the old last component differs from the original
3987 * last component only by case, then we should allow
3988 * the rename (user is trying to change the case of the
3989 * filename).
3992 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3993 strequal(newname, fsp->fsp_name)) {
3994 char *p;
3995 pstring newname_modified_last_component;
3998 * Get the last component of the modified name.
3999 * Note that we guarantee that newname contains a '/'
4000 * character above.
4002 p = strrchr_m(newname,'/');
4003 pstrcpy(newname_modified_last_component,p+1);
4005 if(strcsequal(newname_modified_last_component,
4006 newname_last_component) == False) {
4008 * Replace the modified last component with
4009 * the original.
4011 pstrcpy(p+1, newname_last_component);
4016 * If the src and dest names are identical - including case,
4017 * don't do the rename, just return success.
4020 if (strcsequal(fsp->fsp_name, newname)) {
4021 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4022 newname));
4023 return NT_STATUS_OK;
4026 dest_exists = vfs_object_exist(conn,newname,NULL);
4028 if(!replace_if_exists && dest_exists) {
4029 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4030 fsp->fsp_name,newname));
4031 return NT_STATUS_OBJECT_NAME_COLLISION;
4034 status = can_rename(conn,newname,attrs,&sbuf);
4036 if (dest_exists && !NT_STATUS_IS_OK(status)) {
4037 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4038 nt_errstr(status), fsp->fsp_name,newname));
4039 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4040 status = NT_STATUS_ACCESS_DENIED;
4041 return status;
4044 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4045 return NT_STATUS_ACCESS_DENIED;
4048 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
4050 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4051 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4052 fsp->fsp_name,newname));
4053 rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
4054 TALLOC_FREE(lck);
4055 return NT_STATUS_OK;
4058 TALLOC_FREE(lck);
4060 if (errno == ENOTDIR || errno == EISDIR) {
4061 status = NT_STATUS_OBJECT_NAME_COLLISION;
4062 } else {
4063 status = map_nt_error_from_unix(errno);
4066 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4067 nt_errstr(status), fsp->fsp_name,newname));
4069 return status;
4072 /****************************************************************************
4073 The guts of the rename command, split out so it may be called by the NT SMB
4074 code.
4075 ****************************************************************************/
4077 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists, BOOL has_wild)
4079 pstring directory;
4080 pstring mask;
4081 pstring last_component_src;
4082 pstring last_component_dest;
4083 char *p;
4084 int count=0;
4085 NTSTATUS status = NT_STATUS_OK;
4086 SMB_STRUCT_STAT sbuf1, sbuf2;
4087 struct share_mode_lock *lck = NULL;
4089 *directory = *mask = 0;
4091 ZERO_STRUCT(sbuf1);
4092 ZERO_STRUCT(sbuf2);
4094 status = unix_convert(conn, name, has_wild, last_component_src, &sbuf1);
4095 if (!NT_STATUS_IS_OK(status)) {
4096 return status;
4099 status = unix_convert(conn, newname, True, last_component_dest, &sbuf2);
4100 if (!NT_STATUS_IS_OK(status)) {
4101 return status;
4105 * Split the old name into directory and last component
4106 * strings. Note that unix_convert may have stripped off a
4107 * leading ./ from both name and newname if the rename is
4108 * at the root of the share. We need to make sure either both
4109 * name and newname contain a / character or neither of them do
4110 * as this is checked in resolve_wildcards().
4113 p = strrchr_m(name,'/');
4114 if (!p) {
4115 pstrcpy(directory,".");
4116 pstrcpy(mask,name);
4117 } else {
4118 *p = 0;
4119 pstrcpy(directory,name);
4120 pstrcpy(mask,p+1);
4121 *p = '/'; /* Replace needed for exceptional test below. */
4125 * We should only check the mangled cache
4126 * here if unix_convert failed. This means
4127 * that the path in 'mask' doesn't exist
4128 * on the file system and so we need to look
4129 * for a possible mangle. This patch from
4130 * Tine Smukavec <valentin.smukavec@hermes.si>.
4133 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
4134 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4136 if (!has_wild) {
4138 * No wildcards - just process the one file.
4140 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4142 /* Add a terminating '/' to the directory name. */
4143 pstrcat(directory,"/");
4144 pstrcat(directory,mask);
4146 /* Ensure newname contains a '/' also */
4147 if(strrchr_m(newname,'/') == 0) {
4148 pstring tmpstr;
4150 pstrcpy(tmpstr, "./");
4151 pstrcat(tmpstr, newname);
4152 pstrcpy(newname, tmpstr);
4155 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4156 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4157 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4158 newname, last_component_dest, is_short_name));
4161 * Check for special case with case preserving and not
4162 * case sensitive, if directory and newname are identical,
4163 * and the old last component differs from the original
4164 * last component only by case, then we should allow
4165 * the rename (user is trying to change the case of the
4166 * filename).
4168 if((conn->case_sensitive == False) &&
4169 (((conn->case_preserve == True) &&
4170 (is_short_name == False)) ||
4171 ((conn->short_case_preserve == True) &&
4172 (is_short_name == True))) &&
4173 strcsequal(directory, newname)) {
4174 pstring modified_last_component;
4177 * Get the last component of the modified name.
4178 * Note that we guarantee that newname contains a '/'
4179 * character above.
4181 p = strrchr_m(newname,'/');
4182 pstrcpy(modified_last_component,p+1);
4184 if(strcsequal(modified_last_component,
4185 last_component_dest) == False) {
4187 * Replace the modified last component with
4188 * the original.
4190 pstrcpy(p+1, last_component_dest);
4194 resolve_wildcards(directory,newname);
4197 * The source object must exist.
4200 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4201 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4202 directory,newname));
4204 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4206 * Must return different errors depending on whether the parent
4207 * directory existed or not.
4210 p = strrchr_m(directory, '/');
4211 if (!p)
4212 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4213 *p = '\0';
4214 if (vfs_object_exist(conn, directory, NULL))
4215 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4216 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4218 status = map_nt_error_from_unix(errno);
4219 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4220 nt_errstr(status), directory,newname));
4222 return status;
4225 status = can_rename(conn,directory,attrs,&sbuf1);
4227 if (!NT_STATUS_IS_OK(status)) {
4228 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4229 nt_errstr(status), directory,newname));
4230 return status;
4234 * If the src and dest names are identical - including case,
4235 * don't do the rename, just return success.
4238 if (strcsequal(directory, newname)) {
4239 rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
4240 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4241 return NT_STATUS_OK;
4244 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4245 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4246 directory,newname));
4247 return NT_STATUS_OBJECT_NAME_COLLISION;
4250 if (rename_path_prefix_equal(directory, newname)) {
4251 return NT_STATUS_SHARING_VIOLATION;
4254 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
4256 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4257 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4258 directory,newname));
4259 rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
4260 TALLOC_FREE(lck);
4261 return NT_STATUS_OK;
4264 TALLOC_FREE(lck);
4265 if (errno == ENOTDIR || errno == EISDIR)
4266 status = NT_STATUS_OBJECT_NAME_COLLISION;
4267 else
4268 status = map_nt_error_from_unix(errno);
4270 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4271 nt_errstr(status), directory,newname));
4273 return status;
4274 } else {
4276 * Wildcards - process each file that matches.
4278 struct smb_Dir *dir_hnd = NULL;
4279 const char *dname;
4280 pstring destname;
4282 if (strequal(mask,"????????.???"))
4283 pstrcpy(mask,"*");
4285 if (check_name(directory,conn))
4286 dir_hnd = OpenDir(conn, directory, mask, attrs);
4288 if (dir_hnd) {
4289 long offset = 0;
4290 status = NT_STATUS_NO_SUCH_FILE;
4291 /* Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4293 while ((dname = ReadDirName(dir_hnd, &offset))) {
4294 pstring fname;
4295 BOOL sysdir_entry = False;
4297 pstrcpy(fname,dname);
4299 /* Quick check for "." and ".." */
4300 if (fname[0] == '.') {
4301 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4302 if (attrs & aDIR) {
4303 sysdir_entry = True;
4304 } else {
4305 continue;
4310 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4311 continue;
4313 if(!mask_match(fname, mask, conn->case_sensitive))
4314 continue;
4316 if (sysdir_entry) {
4317 status = NT_STATUS_OBJECT_NAME_INVALID;
4318 break;
4321 status = NT_STATUS_ACCESS_DENIED;
4322 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4323 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4324 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4325 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(status)));
4326 continue;
4328 status = can_rename(conn,fname,attrs,&sbuf1);
4329 if (!NT_STATUS_IS_OK(status)) {
4330 DEBUG(6,("rename %s refused\n", fname));
4331 continue;
4333 pstrcpy(destname,newname);
4335 if (!resolve_wildcards(fname,destname)) {
4336 DEBUG(6,("resolve_wildcards %s %s failed\n",
4337 fname, destname));
4338 continue;
4341 if (strcsequal(fname,destname)) {
4342 rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
4343 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4344 count++;
4345 status = NT_STATUS_OK;
4346 continue;
4349 if (!replace_if_exists &&
4350 vfs_file_exist(conn,destname, NULL)) {
4351 DEBUG(6,("file_exist %s\n", destname));
4352 status = NT_STATUS_OBJECT_NAME_COLLISION;
4353 continue;
4356 if (rename_path_prefix_equal(fname, destname)) {
4357 return NT_STATUS_SHARING_VIOLATION;
4360 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
4362 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4363 rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
4364 count++;
4365 status = NT_STATUS_OK;
4367 TALLOC_FREE(lck);
4368 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4370 CloseDir(dir_hnd);
4373 #if 0
4374 /* Don't think needed any more - JRA. */
4375 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4376 if (!rcdest && bad_path_dest) {
4377 if (ms_has_wild(last_component_dest))
4378 return NT_STATUS_OBJECT_NAME_INVALID;
4379 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4382 #endif
4386 if (count == 0 && NT_STATUS_IS_OK(status)) {
4387 status = map_nt_error_from_unix(errno);
4390 return status;
4393 /****************************************************************************
4394 Reply to a mv.
4395 ****************************************************************************/
4397 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4398 int dum_buffsize)
4400 int outsize = 0;
4401 pstring name;
4402 pstring newname;
4403 char *p;
4404 uint32 attrs = SVAL(inbuf,smb_vwv0);
4405 NTSTATUS status;
4406 BOOL path1_contains_wcard = False;
4407 BOOL path2_contains_wcard = False;
4409 START_PROFILE(SMBmv);
4411 p = smb_buf(inbuf) + 1;
4412 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path1_contains_wcard);
4413 if (!NT_STATUS_IS_OK(status)) {
4414 END_PROFILE(SMBmv);
4415 return ERROR_NT(status);
4417 p++;
4418 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard);
4419 if (!NT_STATUS_IS_OK(status)) {
4420 END_PROFILE(SMBmv);
4421 return ERROR_NT(status);
4424 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4425 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4427 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4429 status = rename_internals(conn, name, newname, attrs, False, path1_contains_wcard);
4430 if (!NT_STATUS_IS_OK(status)) {
4431 END_PROFILE(SMBmv);
4432 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4433 /* We have re-scheduled this call. */
4434 return -1;
4436 return ERROR_NT(status);
4440 * Win2k needs a changenotify request response before it will
4441 * update after a rename..
4443 process_pending_change_notify_queue((time_t)0);
4444 outsize = set_message(outbuf,0,0,False);
4446 END_PROFILE(SMBmv);
4447 return(outsize);
4450 /*******************************************************************
4451 Copy a file as part of a reply_copy.
4452 ******************************************************************/
4455 * TODO: check error codes on all callers
4458 NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
4459 int count, BOOL target_is_directory)
4461 SMB_STRUCT_STAT src_sbuf, sbuf2;
4462 SMB_OFF_T ret=-1;
4463 files_struct *fsp1,*fsp2;
4464 pstring dest;
4465 uint32 dosattrs;
4466 uint32 new_create_disposition;
4467 NTSTATUS status;
4468 int close_err;
4470 pstrcpy(dest,dest1);
4471 if (target_is_directory) {
4472 char *p = strrchr_m(src,'/');
4473 if (p) {
4474 p++;
4475 } else {
4476 p = src;
4478 pstrcat(dest,"/");
4479 pstrcat(dest,p);
4482 if (!vfs_file_exist(conn,src,&src_sbuf)) {
4483 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4486 if (!target_is_directory && count) {
4487 new_create_disposition = FILE_OPEN;
4488 } else {
4489 if (!map_open_params_to_ntcreate(dest1,0,ofun,
4490 NULL, NULL, &new_create_disposition, NULL)) {
4491 return NT_STATUS_INVALID_PARAMETER;
4495 status = open_file_ntcreate(conn,src,&src_sbuf,
4496 FILE_GENERIC_READ,
4497 FILE_SHARE_READ|FILE_SHARE_WRITE,
4498 FILE_OPEN,
4500 FILE_ATTRIBUTE_NORMAL,
4501 INTERNAL_OPEN_ONLY,
4502 NULL, &fsp1);
4504 if (!NT_STATUS_IS_OK(status)) {
4505 return status;
4508 dosattrs = dos_mode(conn, src, &src_sbuf);
4509 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
4510 ZERO_STRUCTP(&sbuf2);
4513 status = open_file_ntcreate(conn,dest,&sbuf2,
4514 FILE_GENERIC_WRITE,
4515 FILE_SHARE_READ|FILE_SHARE_WRITE,
4516 new_create_disposition,
4518 dosattrs,
4519 INTERNAL_OPEN_ONLY,
4520 NULL, &fsp2);
4522 if (!NT_STATUS_IS_OK(status)) {
4523 close_file(fsp1,ERROR_CLOSE);
4524 return status;
4527 if ((ofun&3) == 1) {
4528 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
4529 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4531 * Stop the copy from occurring.
4533 ret = -1;
4534 src_sbuf.st_size = 0;
4538 if (src_sbuf.st_size) {
4539 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4542 close_file(fsp1,NORMAL_CLOSE);
4544 /* Ensure the modtime is set correctly on the destination file. */
4545 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4548 * As we are opening fsp1 read-only we only expect
4549 * an error on close on fsp2 if we are out of space.
4550 * Thus we don't look at the error return from the
4551 * close of fsp1.
4553 close_err = close_file(fsp2,NORMAL_CLOSE);
4555 if (close_err != 0) {
4556 return map_nt_error_from_unix(close_err);
4559 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
4560 return NT_STATUS_DISK_FULL;
4563 return NT_STATUS_OK;
4566 /****************************************************************************
4567 Reply to a file copy.
4568 ****************************************************************************/
4570 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4572 int outsize = 0;
4573 pstring name;
4574 pstring directory;
4575 pstring mask,newname;
4576 char *p;
4577 int count=0;
4578 int error = ERRnoaccess;
4579 int err = 0;
4580 BOOL has_wild;
4581 BOOL exists=False;
4582 int tid2 = SVAL(inbuf,smb_vwv0);
4583 int ofun = SVAL(inbuf,smb_vwv1);
4584 int flags = SVAL(inbuf,smb_vwv2);
4585 BOOL target_is_directory=False;
4586 BOOL path_contains_wcard1 = False;
4587 BOOL path_contains_wcard2 = False;
4588 SMB_STRUCT_STAT sbuf1, sbuf2;
4589 NTSTATUS status;
4590 START_PROFILE(SMBcopy);
4592 *directory = *mask = 0;
4594 p = smb_buf(inbuf);
4595 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
4596 if (!NT_STATUS_IS_OK(status)) {
4597 END_PROFILE(SMBcopy);
4598 return ERROR_NT(status);
4600 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2);
4601 if (!NT_STATUS_IS_OK(status)) {
4602 END_PROFILE(SMBcopy);
4603 return ERROR_NT(status);
4606 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4608 if (tid2 != conn->cnum) {
4609 /* can't currently handle inter share copies XXXX */
4610 DEBUG(3,("Rejecting inter-share copy\n"));
4611 END_PROFILE(SMBcopy);
4612 return ERROR_DOS(ERRSRV,ERRinvdevice);
4615 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4616 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4618 status = unix_convert(conn, name, path_contains_wcard1, NULL, &sbuf1);
4619 if (!NT_STATUS_IS_OK(status)) {
4620 END_PROFILE(SMBcopy);
4621 return ERROR_NT(status);
4624 status = unix_convert(conn, newname, path_contains_wcard2, NULL, &sbuf2);
4625 if (!NT_STATUS_IS_OK(status)) {
4626 END_PROFILE(SMBcopy);
4627 return ERROR_NT(status);
4630 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4632 if ((flags&1) && target_is_directory) {
4633 END_PROFILE(SMBcopy);
4634 return ERROR_DOS(ERRDOS,ERRbadfile);
4637 if ((flags&2) && !target_is_directory) {
4638 END_PROFILE(SMBcopy);
4639 return ERROR_DOS(ERRDOS,ERRbadpath);
4642 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4643 /* wants a tree copy! XXXX */
4644 DEBUG(3,("Rejecting tree copy\n"));
4645 END_PROFILE(SMBcopy);
4646 return ERROR_DOS(ERRSRV,ERRerror);
4649 p = strrchr_m(name,'/');
4650 if (!p) {
4651 pstrcpy(directory,"./");
4652 pstrcpy(mask,name);
4653 } else {
4654 *p = 0;
4655 pstrcpy(directory,name);
4656 pstrcpy(mask,p+1);
4660 * We should only check the mangled cache
4661 * here if unix_convert failed. This means
4662 * that the path in 'mask' doesn't exist
4663 * on the file system and so we need to look
4664 * for a possible mangle. This patch from
4665 * Tine Smukavec <valentin.smukavec@hermes.si>.
4668 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
4669 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4671 has_wild = path_contains_wcard1;
4673 if (!has_wild) {
4674 pstrcat(directory,"/");
4675 pstrcat(directory,mask);
4676 if (resolve_wildcards(directory,newname)
4677 && NT_STATUS_IS_OK(status = copy_file(
4678 directory,newname,conn,ofun,
4679 count,target_is_directory)))
4680 count++;
4681 if(!count && !NT_STATUS_IS_OK(status)) {
4682 END_PROFILE(SMBcopy);
4683 return ERROR_NT(status);
4685 if (!count) {
4686 exists = vfs_file_exist(conn,directory,NULL);
4688 } else {
4689 struct smb_Dir *dir_hnd = NULL;
4690 const char *dname;
4691 pstring destname;
4693 if (strequal(mask,"????????.???"))
4694 pstrcpy(mask,"*");
4696 if (check_name(directory,conn))
4697 dir_hnd = OpenDir(conn, directory, mask, 0);
4699 if (dir_hnd) {
4700 long offset = 0;
4701 error = ERRbadfile;
4703 while ((dname = ReadDirName(dir_hnd, &offset))) {
4704 pstring fname;
4705 pstrcpy(fname,dname);
4707 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4708 continue;
4710 if(!mask_match(fname, mask, conn->case_sensitive))
4711 continue;
4713 error = ERRnoaccess;
4714 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4715 pstrcpy(destname,newname);
4716 if (resolve_wildcards(fname,destname)
4717 && NT_STATUS_IS_OK(status = copy_file(
4718 fname,destname,conn,ofun,
4719 count,target_is_directory)))
4720 count++;
4721 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4723 CloseDir(dir_hnd);
4727 if (count == 0) {
4728 if(err) {
4729 /* Error on close... */
4730 errno = err;
4731 END_PROFILE(SMBcopy);
4732 return(UNIXERROR(ERRHRD,ERRgeneral));
4735 END_PROFILE(SMBcopy);
4736 return ERROR_DOS(ERRDOS,error);
4739 outsize = set_message(outbuf,1,0,True);
4740 SSVAL(outbuf,smb_vwv0,count);
4742 END_PROFILE(SMBcopy);
4743 return(outsize);
4746 /****************************************************************************
4747 Reply to a setdir.
4748 ****************************************************************************/
4750 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4752 int snum;
4753 int outsize = 0;
4754 BOOL ok = False;
4755 pstring newdir;
4756 NTSTATUS status;
4758 START_PROFILE(pathworks_setdir);
4760 snum = SNUM(conn);
4761 if (!CAN_SETDIR(snum)) {
4762 END_PROFILE(pathworks_setdir);
4763 return ERROR_DOS(ERRDOS,ERRnoaccess);
4766 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
4767 if (!NT_STATUS_IS_OK(status)) {
4768 END_PROFILE(pathworks_setdir);
4769 return ERROR_NT(status);
4772 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4774 if (strlen(newdir) == 0) {
4775 ok = True;
4776 } else {
4777 ok = vfs_directory_exist(conn,newdir,NULL);
4778 if (ok)
4779 set_conn_connectpath(conn,newdir);
4782 if (!ok) {
4783 END_PROFILE(pathworks_setdir);
4784 return ERROR_DOS(ERRDOS,ERRbadpath);
4787 outsize = set_message(outbuf,0,0,False);
4788 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4790 DEBUG(3,("setdir %s\n", newdir));
4792 END_PROFILE(pathworks_setdir);
4793 return(outsize);
4796 #undef DBGC_CLASS
4797 #define DBGC_CLASS DBGC_LOCKING
4799 /****************************************************************************
4800 Get a lock pid, dealing with large count requests.
4801 ****************************************************************************/
4803 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4805 if(!large_file_format)
4806 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
4807 else
4808 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4811 /****************************************************************************
4812 Get a lock count, dealing with large count requests.
4813 ****************************************************************************/
4815 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4817 SMB_BIG_UINT count = 0;
4819 if(!large_file_format) {
4820 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4821 } else {
4823 #if defined(HAVE_LONGLONG)
4824 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4825 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4826 #else /* HAVE_LONGLONG */
4829 * NT4.x seems to be broken in that it sends large file (64 bit)
4830 * lockingX calls even if the CAP_LARGE_FILES was *not*
4831 * negotiated. For boxes without large unsigned ints truncate the
4832 * lock count by dropping the top 32 bits.
4835 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4836 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4837 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4838 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4839 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4842 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4843 #endif /* HAVE_LONGLONG */
4846 return count;
4849 #if !defined(HAVE_LONGLONG)
4850 /****************************************************************************
4851 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4852 ****************************************************************************/
4854 static uint32 map_lock_offset(uint32 high, uint32 low)
4856 unsigned int i;
4857 uint32 mask = 0;
4858 uint32 highcopy = high;
4861 * Try and find out how many significant bits there are in high.
4864 for(i = 0; highcopy; i++)
4865 highcopy >>= 1;
4868 * We use 31 bits not 32 here as POSIX
4869 * lock offsets may not be negative.
4872 mask = (~0) << (31 - i);
4874 if(low & mask)
4875 return 0; /* Fail. */
4877 high <<= (31 - i);
4879 return (high|low);
4881 #endif /* !defined(HAVE_LONGLONG) */
4883 /****************************************************************************
4884 Get a lock offset, dealing with large offset requests.
4885 ****************************************************************************/
4887 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4889 SMB_BIG_UINT offset = 0;
4891 *err = False;
4893 if(!large_file_format) {
4894 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4895 } else {
4897 #if defined(HAVE_LONGLONG)
4898 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4899 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4900 #else /* HAVE_LONGLONG */
4903 * NT4.x seems to be broken in that it sends large file (64 bit)
4904 * lockingX calls even if the CAP_LARGE_FILES was *not*
4905 * negotiated. For boxes without large unsigned ints mangle the
4906 * lock offset by mapping the top 32 bits onto the lower 32.
4909 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4910 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4911 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4912 uint32 new_low = 0;
4914 if((new_low = map_lock_offset(high, low)) == 0) {
4915 *err = True;
4916 return (SMB_BIG_UINT)-1;
4919 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4920 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4921 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4922 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4925 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4926 #endif /* HAVE_LONGLONG */
4929 return offset;
4932 /****************************************************************************
4933 Reply to a lockingX request.
4934 ****************************************************************************/
4936 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
4937 int length, int bufsize)
4939 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4940 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4941 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4942 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4943 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4944 SMB_BIG_UINT count = 0, offset = 0;
4945 uint32 lock_pid;
4946 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4947 int i;
4948 char *data;
4949 BOOL large_file_format =
4950 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4951 BOOL err;
4952 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
4954 START_PROFILE(SMBlockingX);
4956 CHECK_FSP(fsp,conn);
4958 data = smb_buf(inbuf);
4960 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4961 /* we don't support these - and CANCEL_LOCK makes w2k
4962 and XP reboot so I don't really want to be
4963 compatible! (tridge) */
4964 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
4967 /* Check if this is an oplock break on a file
4968 we have granted an oplock on.
4970 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4971 /* Client can insist on breaking to none. */
4972 BOOL break_to_none = (oplocklevel == 0);
4973 BOOL result;
4975 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
4976 "for fnum = %d\n", (unsigned int)oplocklevel,
4977 fsp->fnum ));
4980 * Make sure we have granted an exclusive or batch oplock on
4981 * this file.
4984 if (fsp->oplock_type == 0) {
4986 /* The Samba4 nbench simulator doesn't understand
4987 the difference between break to level2 and break
4988 to none from level2 - it sends oplock break
4989 replies in both cases. Don't keep logging an error
4990 message here - just ignore it. JRA. */
4992 DEBUG(5,("reply_lockingX: Error : oplock break from "
4993 "client for fnum = %d (oplock=%d) and no "
4994 "oplock granted on this file (%s).\n",
4995 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
4997 /* if this is a pure oplock break request then don't
4998 * send a reply */
4999 if (num_locks == 0 && num_ulocks == 0) {
5000 END_PROFILE(SMBlockingX);
5001 return -1;
5002 } else {
5003 END_PROFILE(SMBlockingX);
5004 return ERROR_DOS(ERRDOS,ERRlock);
5008 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5009 (break_to_none)) {
5010 result = remove_oplock(fsp);
5011 } else {
5012 result = downgrade_oplock(fsp);
5015 if (!result) {
5016 DEBUG(0, ("reply_lockingX: error in removing "
5017 "oplock on file %s\n", fsp->fsp_name));
5018 /* Hmmm. Is this panic justified? */
5019 smb_panic("internal tdb error");
5022 reply_to_oplock_break_requests(fsp);
5024 /* if this is a pure oplock break request then don't send a
5025 * reply */
5026 if (num_locks == 0 && num_ulocks == 0) {
5027 /* Sanity check - ensure a pure oplock break is not a
5028 chained request. */
5029 if(CVAL(inbuf,smb_vwv0) != 0xff)
5030 DEBUG(0,("reply_lockingX: Error : pure oplock "
5031 "break is a chained %d request !\n",
5032 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5033 END_PROFILE(SMBlockingX);
5034 return -1;
5039 * We do this check *after* we have checked this is not a oplock break
5040 * response message. JRA.
5043 release_level_2_oplocks_on_change(fsp);
5045 /* Data now points at the beginning of the list
5046 of smb_unlkrng structs */
5047 for(i = 0; i < (int)num_ulocks; i++) {
5048 lock_pid = get_lock_pid( data, i, large_file_format);
5049 count = get_lock_count( data, i, large_file_format);
5050 offset = get_lock_offset( data, i, large_file_format, &err);
5053 * There is no error code marked "stupid client bug".... :-).
5055 if(err) {
5056 END_PROFILE(SMBlockingX);
5057 return ERROR_DOS(ERRDOS,ERRnoaccess);
5060 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5061 "pid %u, file %s\n", (double)offset, (double)count,
5062 (unsigned int)lock_pid, fsp->fsp_name ));
5064 status = do_unlock(fsp,
5065 lock_pid,
5066 count,
5067 offset,
5068 WINDOWS_LOCK);
5070 if (NT_STATUS_V(status)) {
5071 END_PROFILE(SMBlockingX);
5072 return ERROR_NT(status);
5076 /* Setup the timeout in seconds. */
5078 if (!lp_blocking_locks(SNUM(conn))) {
5079 lock_timeout = 0;
5082 /* Now do any requested locks */
5083 data += ((large_file_format ? 20 : 10)*num_ulocks);
5085 /* Data now points at the beginning of the list
5086 of smb_lkrng structs */
5088 for(i = 0; i < (int)num_locks; i++) {
5089 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5090 READ_LOCK:WRITE_LOCK);
5091 lock_pid = get_lock_pid( data, i, large_file_format);
5092 count = get_lock_count( data, i, large_file_format);
5093 offset = get_lock_offset( data, i, large_file_format, &err);
5096 * There is no error code marked "stupid client bug".... :-).
5098 if(err) {
5099 END_PROFILE(SMBlockingX);
5100 return ERROR_DOS(ERRDOS,ERRnoaccess);
5103 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5104 "%u, file %s timeout = %d\n", (double)offset,
5105 (double)count, (unsigned int)lock_pid,
5106 fsp->fsp_name, (int)lock_timeout ));
5108 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5109 if (lp_blocking_locks(SNUM(conn))) {
5111 /* Schedule a message to ourselves to
5112 remove the blocking lock record and
5113 return the right error. */
5115 if (!blocking_lock_cancel(fsp,
5116 lock_pid,
5117 offset,
5118 count,
5119 WINDOWS_LOCK,
5120 locktype,
5121 NT_STATUS_FILE_LOCK_CONFLICT)) {
5122 END_PROFILE(SMBlockingX);
5123 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5126 /* Remove a matching pending lock. */
5127 status = do_lock_cancel(fsp,
5128 lock_pid,
5129 count,
5130 offset,
5131 WINDOWS_LOCK);
5132 } else {
5133 BOOL blocking_lock = lock_timeout ? True : False;
5134 BOOL defer_lock = False;
5135 struct byte_range_lock *br_lck;
5137 br_lck = do_lock(fsp,
5138 lock_pid,
5139 count,
5140 offset,
5141 lock_type,
5142 WINDOWS_LOCK,
5143 blocking_lock,
5144 &status);
5146 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5147 /* Windows internal resolution for blocking locks seems
5148 to be about 200ms... Don't wait for less than that. JRA. */
5149 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5150 lock_timeout = lp_lock_spin_time();
5152 defer_lock = True;
5155 /* This heuristic seems to match W2K3 very well. If a
5156 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5157 it pretends we asked for a timeout of between 150 - 300 milliseconds as
5158 far as I can tell. Replacement for do_lock_spin(). JRA. */
5160 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5161 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5162 defer_lock = True;
5163 lock_timeout = lp_lock_spin_time();
5166 if (br_lck && defer_lock) {
5168 * A blocking lock was requested. Package up
5169 * this smb into a queued request and push it
5170 * onto the blocking lock queue.
5172 if(push_blocking_lock_request(br_lck,
5173 inbuf, length,
5174 fsp,
5175 lock_timeout,
5177 lock_pid,
5178 lock_type,
5179 WINDOWS_LOCK,
5180 offset,
5181 count)) {
5182 TALLOC_FREE(br_lck);
5183 END_PROFILE(SMBlockingX);
5184 return -1;
5188 TALLOC_FREE(br_lck);
5191 if (NT_STATUS_V(status)) {
5192 END_PROFILE(SMBlockingX);
5193 return ERROR_NT(status);
5197 /* If any of the above locks failed, then we must unlock
5198 all of the previous locks (X/Open spec). */
5200 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5201 (i != num_locks) &&
5202 (num_locks != 0)) {
5204 * Ensure we don't do a remove on the lock that just failed,
5205 * as under POSIX rules, if we have a lock already there, we
5206 * will delete it (and we shouldn't) .....
5208 for(i--; i >= 0; i--) {
5209 lock_pid = get_lock_pid( data, i, large_file_format);
5210 count = get_lock_count( data, i, large_file_format);
5211 offset = get_lock_offset( data, i, large_file_format,
5212 &err);
5215 * There is no error code marked "stupid client
5216 * bug".... :-).
5218 if(err) {
5219 END_PROFILE(SMBlockingX);
5220 return ERROR_DOS(ERRDOS,ERRnoaccess);
5223 do_unlock(fsp,
5224 lock_pid,
5225 count,
5226 offset,
5227 WINDOWS_LOCK);
5229 END_PROFILE(SMBlockingX);
5230 return ERROR_NT(status);
5233 set_message(outbuf,2,0,True);
5235 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5236 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5238 END_PROFILE(SMBlockingX);
5239 return chain_reply(inbuf,outbuf,length,bufsize);
5242 #undef DBGC_CLASS
5243 #define DBGC_CLASS DBGC_ALL
5245 /****************************************************************************
5246 Reply to a SMBreadbmpx (read block multiplex) request.
5247 ****************************************************************************/
5249 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5251 ssize_t nread = -1;
5252 ssize_t total_read;
5253 char *data;
5254 SMB_OFF_T startpos;
5255 int outsize;
5256 size_t maxcount;
5257 int max_per_packet;
5258 size_t tcount;
5259 int pad;
5260 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5261 START_PROFILE(SMBreadBmpx);
5263 /* this function doesn't seem to work - disable by default */
5264 if (!lp_readbmpx()) {
5265 END_PROFILE(SMBreadBmpx);
5266 return ERROR_DOS(ERRSRV,ERRuseSTD);
5269 outsize = set_message(outbuf,8,0,True);
5271 CHECK_FSP(fsp,conn);
5272 if (!CHECK_READ(fsp,inbuf)) {
5273 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5276 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5277 maxcount = SVAL(inbuf,smb_vwv3);
5279 data = smb_buf(outbuf);
5280 pad = ((long)data)%4;
5281 if (pad)
5282 pad = 4 - pad;
5283 data += pad;
5285 max_per_packet = bufsize-(outsize+pad);
5286 tcount = maxcount;
5287 total_read = 0;
5289 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5290 END_PROFILE(SMBreadBmpx);
5291 return ERROR_DOS(ERRDOS,ERRlock);
5294 do {
5295 size_t N = MIN(max_per_packet,tcount-total_read);
5297 nread = read_file(fsp,data,startpos,N);
5299 if (nread <= 0)
5300 nread = 0;
5302 if (nread < (ssize_t)N)
5303 tcount = total_read + nread;
5305 set_message(outbuf,8,nread+pad,False);
5306 SIVAL(outbuf,smb_vwv0,startpos);
5307 SSVAL(outbuf,smb_vwv2,tcount);
5308 SSVAL(outbuf,smb_vwv6,nread);
5309 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5311 show_msg(outbuf);
5312 if (!send_smb(smbd_server_fd(),outbuf))
5313 exit_server_cleanly("reply_readbmpx: send_smb failed.");
5315 total_read += nread;
5316 startpos += nread;
5317 } while (total_read < (ssize_t)tcount);
5319 END_PROFILE(SMBreadBmpx);
5320 return(-1);
5323 /****************************************************************************
5324 Reply to a SMBsetattrE.
5325 ****************************************************************************/
5327 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5329 struct utimbuf unix_times;
5330 int outsize = 0;
5331 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5332 START_PROFILE(SMBsetattrE);
5334 outsize = set_message(outbuf,0,0,False);
5336 if(!fsp || (fsp->conn != conn)) {
5337 END_PROFILE(SMBsetattrE);
5338 return ERROR_DOS(ERRDOS,ERRbadfid);
5342 * Convert the DOS times into unix times. Ignore create
5343 * time as UNIX can't set this.
5346 unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3);
5347 unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5);
5350 * Patch from Ray Frush <frush@engr.colostate.edu>
5351 * Sometimes times are sent as zero - ignore them.
5354 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5355 /* Ignore request */
5356 if( DEBUGLVL( 3 ) ) {
5357 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5358 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5360 END_PROFILE(SMBsetattrE);
5361 return(outsize);
5362 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5363 /* set modify time = to access time if modify time was unset */
5364 unix_times.modtime = unix_times.actime;
5367 /* Set the date on this file */
5368 /* Should we set pending modtime here ? JRA */
5369 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5370 END_PROFILE(SMBsetattrE);
5371 return ERROR_DOS(ERRDOS,ERRnoaccess);
5374 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5375 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5377 END_PROFILE(SMBsetattrE);
5378 return(outsize);
5382 /* Back from the dead for OS/2..... JRA. */
5384 /****************************************************************************
5385 Reply to a SMBwritebmpx (write block multiplex primary) request.
5386 ****************************************************************************/
5388 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5390 size_t numtowrite;
5391 ssize_t nwritten = -1;
5392 int outsize = 0;
5393 SMB_OFF_T startpos;
5394 size_t tcount;
5395 BOOL write_through;
5396 int smb_doff;
5397 char *data;
5398 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5399 START_PROFILE(SMBwriteBmpx);
5401 CHECK_FSP(fsp,conn);
5402 if (!CHECK_WRITE(fsp)) {
5403 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5405 if (HAS_CACHED_ERROR(fsp)) {
5406 return(CACHED_ERROR(fsp));
5409 tcount = SVAL(inbuf,smb_vwv1);
5410 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5411 write_through = BITSETW(inbuf+smb_vwv7,0);
5412 numtowrite = SVAL(inbuf,smb_vwv10);
5413 smb_doff = SVAL(inbuf,smb_vwv11);
5415 data = smb_base(inbuf) + smb_doff;
5417 /* If this fails we need to send an SMBwriteC response,
5418 not an SMBwritebmpx - set this up now so we don't forget */
5419 SCVAL(outbuf,smb_com,SMBwritec);
5421 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5422 END_PROFILE(SMBwriteBmpx);
5423 return(ERROR_DOS(ERRDOS,ERRlock));
5426 nwritten = write_file(fsp,data,startpos,numtowrite);
5428 sync_file(conn, fsp, write_through);
5430 if(nwritten < (ssize_t)numtowrite) {
5431 END_PROFILE(SMBwriteBmpx);
5432 return(UNIXERROR(ERRHRD,ERRdiskfull));
5435 /* If the maximum to be written to this file
5436 is greater than what we just wrote then set
5437 up a secondary struct to be attached to this
5438 fd, we will use this to cache error messages etc. */
5440 if((ssize_t)tcount > nwritten) {
5441 write_bmpx_struct *wbms;
5442 if(fsp->wbmpx_ptr != NULL)
5443 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5444 else
5445 wbms = SMB_MALLOC_P(write_bmpx_struct);
5446 if(!wbms) {
5447 DEBUG(0,("Out of memory in reply_readmpx\n"));
5448 END_PROFILE(SMBwriteBmpx);
5449 return(ERROR_DOS(ERRSRV,ERRnoresource));
5451 wbms->wr_mode = write_through;
5452 wbms->wr_discard = False; /* No errors yet */
5453 wbms->wr_total_written = nwritten;
5454 wbms->wr_errclass = 0;
5455 wbms->wr_error = 0;
5456 fsp->wbmpx_ptr = wbms;
5459 /* We are returning successfully, set the message type back to
5460 SMBwritebmpx */
5461 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5463 outsize = set_message(outbuf,1,0,True);
5465 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5467 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5468 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5470 if (write_through && tcount==nwritten) {
5471 /* We need to send both a primary and a secondary response */
5472 smb_setlen(outbuf,outsize - 4);
5473 show_msg(outbuf);
5474 if (!send_smb(smbd_server_fd(),outbuf))
5475 exit_server_cleanly("reply_writebmpx: send_smb failed.");
5477 /* Now the secondary */
5478 outsize = set_message(outbuf,1,0,True);
5479 SCVAL(outbuf,smb_com,SMBwritec);
5480 SSVAL(outbuf,smb_vwv0,nwritten);
5483 END_PROFILE(SMBwriteBmpx);
5484 return(outsize);
5487 /****************************************************************************
5488 Reply to a SMBwritebs (write block multiplex secondary) request.
5489 ****************************************************************************/
5491 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5493 size_t numtowrite;
5494 ssize_t nwritten = -1;
5495 int outsize = 0;
5496 SMB_OFF_T startpos;
5497 size_t tcount;
5498 BOOL write_through;
5499 int smb_doff;
5500 char *data;
5501 write_bmpx_struct *wbms;
5502 BOOL send_response = False;
5503 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5504 START_PROFILE(SMBwriteBs);
5506 CHECK_FSP(fsp,conn);
5507 if (!CHECK_WRITE(fsp)) {
5508 return(ERROR_DOS(ERRDOS,ERRbadaccess));
5511 tcount = SVAL(inbuf,smb_vwv1);
5512 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5513 numtowrite = SVAL(inbuf,smb_vwv6);
5514 smb_doff = SVAL(inbuf,smb_vwv7);
5516 data = smb_base(inbuf) + smb_doff;
5518 /* We need to send an SMBwriteC response, not an SMBwritebs */
5519 SCVAL(outbuf,smb_com,SMBwritec);
5521 /* This fd should have an auxiliary struct attached,
5522 check that it does */
5523 wbms = fsp->wbmpx_ptr;
5524 if(!wbms) {
5525 END_PROFILE(SMBwriteBs);
5526 return(-1);
5529 /* If write through is set we can return errors, else we must cache them */
5530 write_through = wbms->wr_mode;
5532 /* Check for an earlier error */
5533 if(wbms->wr_discard) {
5534 END_PROFILE(SMBwriteBs);
5535 return -1; /* Just discard the packet */
5538 nwritten = write_file(fsp,data,startpos,numtowrite);
5540 sync_file(conn, fsp, write_through);
5542 if (nwritten < (ssize_t)numtowrite) {
5543 if(write_through) {
5544 /* We are returning an error - we can delete the aux struct */
5545 if (wbms)
5546 free((char *)wbms);
5547 fsp->wbmpx_ptr = NULL;
5548 END_PROFILE(SMBwriteBs);
5549 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5551 wbms->wr_errclass = ERRHRD;
5552 wbms->wr_error = ERRdiskfull;
5553 wbms->wr_status = NT_STATUS_DISK_FULL;
5554 wbms->wr_discard = True;
5555 END_PROFILE(SMBwriteBs);
5556 return -1;
5559 /* Increment the total written, if this matches tcount
5560 we can discard the auxiliary struct (hurrah !) and return a writeC */
5561 wbms->wr_total_written += nwritten;
5562 if(wbms->wr_total_written >= tcount) {
5563 if (write_through) {
5564 outsize = set_message(outbuf,1,0,True);
5565 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5566 send_response = True;
5569 free((char *)wbms);
5570 fsp->wbmpx_ptr = NULL;
5573 if(send_response) {
5574 END_PROFILE(SMBwriteBs);
5575 return(outsize);
5578 END_PROFILE(SMBwriteBs);
5579 return(-1);
5582 /****************************************************************************
5583 Reply to a SMBgetattrE.
5584 ****************************************************************************/
5586 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5588 SMB_STRUCT_STAT sbuf;
5589 int outsize = 0;
5590 int mode;
5591 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5592 START_PROFILE(SMBgetattrE);
5594 outsize = set_message(outbuf,11,0,True);
5596 if(!fsp || (fsp->conn != conn)) {
5597 END_PROFILE(SMBgetattrE);
5598 return ERROR_DOS(ERRDOS,ERRbadfid);
5601 /* Do an fstat on this file */
5602 if(fsp_stat(fsp, &sbuf)) {
5603 END_PROFILE(SMBgetattrE);
5604 return(UNIXERROR(ERRDOS,ERRnoaccess));
5607 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5610 * Convert the times into dos times. Set create
5611 * date to be last modify date as UNIX doesn't save
5612 * this.
5615 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5616 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5617 /* Should we check pending modtime here ? JRA */
5618 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5620 if (mode & aDIR) {
5621 SIVAL(outbuf,smb_vwv6,0);
5622 SIVAL(outbuf,smb_vwv8,0);
5623 } else {
5624 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5625 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5626 SIVAL(outbuf,smb_vwv8,allocation_size);
5628 SSVAL(outbuf,smb_vwv10, mode);
5630 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5632 END_PROFILE(SMBgetattrE);
5633 return(outsize);