r6369: update release notes
[Samba.git] / source / smbd / reply.c
blobc3cb81ddfc412b8333d0147f408342386715cb85
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-2004.
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 extern char magic_char;
34 extern int global_oplock_break;
35 unsigned int smb_echo_count = 0;
36 extern uint32 global_client_caps;
38 extern struct current_user current_user;
39 extern BOOL global_encrypted_passwords_negotiated;
41 /****************************************************************************
42 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
43 We're assuming here that '/' is not the second byte in any multibyte char
44 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
45 set.
46 ****************************************************************************/
48 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
50 char *d = destname;
51 const char *s = srcname;
52 NTSTATUS ret = NT_STATUS_OK;
53 BOOL start_of_name_component = True;
54 unsigned int num_bad_components = 0;
56 while (*s) {
57 if (IS_DIRECTORY_SEP(*s)) {
59 * Safe to assume is not the second part of a mb char as this is handled below.
61 /* Eat multiple '/' or '\\' */
62 while (IS_DIRECTORY_SEP(*s)) {
63 s++;
65 if ((d != destname) && (*s != '\0')) {
66 /* We only care about non-leading or trailing '/' or '\\' */
67 *d++ = '/';
70 start_of_name_component = True;
71 continue;
74 if (start_of_name_component) {
75 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
76 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
79 * No mb char starts with '.' so we're safe checking the directory separator here.
82 /* If we just added a '/' - delete it */
83 if ((d > destname) && (*(d-1) == '/')) {
84 *(d-1) = '\0';
85 d--;
88 /* Are we at the start ? Can't go back further if so. */
89 if (d <= destname) {
90 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
91 break;
93 /* Go back one level... */
94 /* We know this is safe as '/' cannot be part of a mb sequence. */
95 /* NOTE - if this assumption is invalid we are not in good shape... */
96 /* Decrement d first as d points to the *next* char to write into. */
97 for (d--; d > destname; d--) {
98 if (*d == '/')
99 break;
101 s += 2; /* Else go past the .. */
102 /* We're still at the start of a name component, just the previous one. */
104 if (num_bad_components) {
105 /* Hmmm. Should we only decrement the bad_components if
106 we're removing a bad component ? Need to check this. JRA. */
107 num_bad_components--;
110 continue;
112 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
113 /* Component of pathname can't be "." only. */
114 ret = NT_STATUS_OBJECT_NAME_INVALID;
115 num_bad_components++;
116 *d++ = *s++;
117 continue;
121 if (!(*s & 0x80)) {
122 switch (*s) {
123 case '*':
124 case '?':
125 case '<':
126 case '>':
127 case '"':
128 return NT_STATUS_OBJECT_NAME_INVALID;
129 default:
130 *d++ = *s++;
131 break;
133 } else {
134 switch(next_mb_char_size(s)) {
135 case 4:
136 *d++ = *s++;
137 case 3:
138 *d++ = *s++;
139 case 2:
140 *d++ = *s++;
141 case 1:
142 *d++ = *s++;
143 break;
144 default:
145 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
146 *d = '\0';
147 return NT_STATUS_INVALID_PARAMETER;
150 if (start_of_name_component && num_bad_components) {
151 num_bad_components++;
153 start_of_name_component = False;
156 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
157 if (num_bad_components > 1) {
158 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
162 *d = '\0';
163 return ret;
166 /****************************************************************************
167 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
168 path or anything including wildcards.
169 We're assuming here that '/' is not the second byte in any multibyte char
170 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
171 set.
172 ****************************************************************************/
174 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname)
176 char *d = destname;
177 const char *s = srcname;
178 NTSTATUS ret = NT_STATUS_OK;
179 BOOL start_of_name_component = True;
180 unsigned int num_bad_components = 0;
182 while (*s) {
183 if (IS_DIRECTORY_SEP(*s)) {
185 * Safe to assume is not the second part of a mb char as this is handled below.
187 /* Eat multiple '/' or '\\' */
188 while (IS_DIRECTORY_SEP(*s)) {
189 s++;
191 if ((d != destname) && (*s != '\0')) {
192 /* We only care about non-leading or trailing '/' or '\\' */
193 *d++ = '/';
196 start_of_name_component = True;
197 continue;
200 if (start_of_name_component) {
201 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
202 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
205 * No mb char starts with '.' so we're safe checking the directory separator here.
208 /* If we just added a '/' - delete it */
209 if ((d > destname) && (*(d-1) == '/')) {
210 *(d-1) = '\0';
211 d--;
214 /* Are we at the start ? Can't go back further if so. */
215 if (d <= destname) {
216 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
217 break;
219 /* Go back one level... */
220 /* We know this is safe as '/' cannot be part of a mb sequence. */
221 /* NOTE - if this assumption is invalid we are not in good shape... */
222 /* Decrement d first as d points to the *next* char to write into. */
223 for (d--; d > destname; d--) {
224 if (*d == '/')
225 break;
227 s += 2; /* Else go past the .. */
228 /* We're still at the start of a name component, just the previous one. */
230 if (num_bad_components) {
231 /* Hmmm. Should we only decrement the bad_components if
232 we're removing a bad component ? Need to check this. JRA. */
233 num_bad_components--;
236 continue;
238 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
239 /* Component of pathname can't be "." only. */
240 ret = NT_STATUS_OBJECT_NAME_INVALID;
241 num_bad_components++;
242 *d++ = *s++;
243 continue;
247 if (!(*s & 0x80)) {
248 *d++ = *s++;
249 } else {
250 switch(next_mb_char_size(s)) {
251 case 4:
252 *d++ = *s++;
253 case 3:
254 *d++ = *s++;
255 case 2:
256 *d++ = *s++;
257 case 1:
258 *d++ = *s++;
259 break;
260 default:
261 DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
262 *d = '\0';
263 return NT_STATUS_INVALID_PARAMETER;
266 if (start_of_name_component && num_bad_components) {
267 num_bad_components++;
269 start_of_name_component = False;
272 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
273 /* For some strange reason being called from findfirst changes
274 the num_components number to cause the error return to change. JRA. */
275 if (num_bad_components > 2) {
276 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
280 *d = '\0';
281 return ret;
284 /****************************************************************************
285 Pull a string and check the path - provide for error return.
286 ****************************************************************************/
288 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names)
290 pstring tmppath;
291 char *tmppath_ptr = tmppath;
292 size_t ret;
293 #ifdef DEVELOPER
294 SMB_ASSERT(dest_len == sizeof(pstring));
295 #endif
297 if (src_len == 0) {
298 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
299 } else {
300 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
302 if (allow_wcard_names) {
303 *err = check_path_syntax_wcard(dest, tmppath);
304 } else {
305 *err = check_path_syntax(dest, tmppath);
307 return ret;
310 /****************************************************************************
311 Reply to a special message.
312 ****************************************************************************/
314 int reply_special(char *inbuf,char *outbuf)
316 int outsize = 4;
317 int msg_type = CVAL(inbuf,0);
318 int msg_flags = CVAL(inbuf,1);
319 fstring name1,name2;
320 char name_type = 0;
322 static BOOL already_got_session = False;
324 *name1 = *name2 = 0;
326 memset(outbuf,'\0',smb_size);
328 smb_setlen(outbuf,0);
330 switch (msg_type) {
331 case 0x81: /* session request */
333 if (already_got_session) {
334 exit_server("multiple session request not permitted");
337 SCVAL(outbuf,0,0x82);
338 SCVAL(outbuf,3,0);
339 if (name_len(inbuf+4) > 50 ||
340 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
341 DEBUG(0,("Invalid name length in session request\n"));
342 return(0);
344 name_extract(inbuf,4,name1);
345 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
346 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
347 name1,name2));
349 set_local_machine_name(name1, True);
350 set_remote_machine_name(name2, True);
352 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
353 get_local_machine_name(), get_remote_machine_name(),
354 name_type));
356 if (name_type == 'R') {
357 /* We are being asked for a pathworks session ---
358 no thanks! */
359 SCVAL(outbuf, 0,0x83);
360 break;
363 /* only add the client's machine name to the list
364 of possibly valid usernames if we are operating
365 in share mode security */
366 if (lp_security() == SEC_SHARE) {
367 add_session_user(get_remote_machine_name());
370 reload_services(True);
371 reopen_logs();
373 already_got_session = True;
374 break;
376 case 0x89: /* session keepalive request
377 (some old clients produce this?) */
378 SCVAL(outbuf,0,SMBkeepalive);
379 SCVAL(outbuf,3,0);
380 break;
382 case 0x82: /* positive session response */
383 case 0x83: /* negative session response */
384 case 0x84: /* retarget session response */
385 DEBUG(0,("Unexpected session response\n"));
386 break;
388 case SMBkeepalive: /* session keepalive */
389 default:
390 return(0);
393 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
394 msg_type, msg_flags));
396 return(outsize);
399 /****************************************************************************
400 Reply to a tcon.
401 ****************************************************************************/
403 int reply_tcon(connection_struct *conn,
404 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
406 const char *service;
407 pstring service_buf;
408 pstring password;
409 pstring dev;
410 int outsize = 0;
411 uint16 vuid = SVAL(inbuf,smb_uid);
412 int pwlen=0;
413 NTSTATUS nt_status;
414 char *p;
415 DATA_BLOB password_blob;
417 START_PROFILE(SMBtcon);
419 *service_buf = *password = *dev = 0;
421 p = smb_buf(inbuf)+1;
422 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
423 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
424 p += pwlen;
425 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
427 p = strrchr_m(service_buf,'\\');
428 if (p) {
429 service = p+1;
430 } else {
431 service = service_buf;
434 password_blob = data_blob(password, pwlen+1);
436 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
438 data_blob_clear_free(&password_blob);
440 if (!conn) {
441 END_PROFILE(SMBtcon);
442 return ERROR_NT(nt_status);
445 outsize = set_message(outbuf,2,0,True);
446 SSVAL(outbuf,smb_vwv0,max_recv);
447 SSVAL(outbuf,smb_vwv1,conn->cnum);
448 SSVAL(outbuf,smb_tid,conn->cnum);
450 DEBUG(3,("tcon service=%s cnum=%d\n",
451 service, conn->cnum));
453 END_PROFILE(SMBtcon);
454 return(outsize);
457 /****************************************************************************
458 Reply to a tcon and X.
459 ****************************************************************************/
461 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
463 fstring service;
464 DATA_BLOB password;
466 /* what the cleint thinks the device is */
467 fstring client_devicetype;
468 /* what the server tells the client the share represents */
469 const char *server_devicetype;
470 NTSTATUS nt_status;
471 uint16 vuid = SVAL(inbuf,smb_uid);
472 int passlen = SVAL(inbuf,smb_vwv3);
473 pstring path;
474 char *p, *q;
476 START_PROFILE(SMBtconX);
478 *service = *client_devicetype = 0;
480 /* we might have to close an old one */
481 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
482 close_cnum(conn,vuid);
485 if (passlen > MAX_PASS_LEN) {
486 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
489 if (global_encrypted_passwords_negotiated) {
490 password = data_blob(smb_buf(inbuf),passlen);
491 } else {
492 password = data_blob(smb_buf(inbuf),passlen+1);
493 /* Ensure correct termination */
494 password.data[passlen]=0;
497 p = smb_buf(inbuf) + passlen;
498 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
501 * the service name can be either: \\server\share
502 * or share directly like on the DELL PowerVault 705
504 if (*path=='\\') {
505 q = strchr_m(path+2,'\\');
506 if (!q) {
507 END_PROFILE(SMBtconX);
508 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
510 fstrcpy(service,q+1);
512 else
513 fstrcpy(service,path);
515 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
517 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
519 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
521 data_blob_clear_free(&password);
523 if (!conn) {
524 END_PROFILE(SMBtconX);
525 return ERROR_NT(nt_status);
528 if ( IS_IPC(conn) )
529 server_devicetype = "IPC";
530 else if ( IS_PRINT(conn) )
531 server_devicetype = "LPT1:";
532 else
533 server_devicetype = "A:";
535 if (Protocol < PROTOCOL_NT1) {
536 set_message(outbuf,2,0,True);
537 p = smb_buf(outbuf);
538 p += srvstr_push(outbuf, p, server_devicetype, -1,
539 STR_TERMINATE|STR_ASCII);
540 set_message_end(outbuf,p);
541 } else {
542 /* NT sets the fstype of IPC$ to the null string */
543 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
545 set_message(outbuf,3,0,True);
547 p = smb_buf(outbuf);
548 p += srvstr_push(outbuf, p, server_devicetype, -1,
549 STR_TERMINATE|STR_ASCII);
550 p += srvstr_push(outbuf, p, fstype, -1,
551 STR_TERMINATE);
553 set_message_end(outbuf,p);
555 /* what does setting this bit do? It is set by NT4 and
556 may affect the ability to autorun mounted cdroms */
557 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
558 (lp_csc_policy(SNUM(conn)) << 2));
560 init_dfsroot(conn, inbuf, outbuf);
564 DEBUG(3,("tconX service=%s \n",
565 service));
567 /* set the incoming and outgoing tid to the just created one */
568 SSVAL(inbuf,smb_tid,conn->cnum);
569 SSVAL(outbuf,smb_tid,conn->cnum);
571 END_PROFILE(SMBtconX);
572 return chain_reply(inbuf,outbuf,length,bufsize);
575 /****************************************************************************
576 Reply to an unknown type.
577 ****************************************************************************/
579 int reply_unknown(char *inbuf,char *outbuf)
581 int type;
582 type = CVAL(inbuf,smb_com);
584 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
585 smb_fn_name(type), type, type));
587 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
590 /****************************************************************************
591 Reply to an ioctl.
592 ****************************************************************************/
594 int reply_ioctl(connection_struct *conn,
595 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
597 uint16 device = SVAL(inbuf,smb_vwv1);
598 uint16 function = SVAL(inbuf,smb_vwv2);
599 uint32 ioctl_code = (device << 16) + function;
600 int replysize, outsize;
601 char *p;
602 START_PROFILE(SMBioctl);
604 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
606 switch (ioctl_code) {
607 case IOCTL_QUERY_JOB_INFO:
608 replysize = 32;
609 break;
610 default:
611 END_PROFILE(SMBioctl);
612 return(ERROR_DOS(ERRSRV,ERRnosupport));
615 outsize = set_message(outbuf,8,replysize+1,True);
616 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
617 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
618 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
619 p = smb_buf(outbuf) + 1; /* Allow for alignment */
621 switch (ioctl_code) {
622 case IOCTL_QUERY_JOB_INFO:
624 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
625 if (!fsp) {
626 END_PROFILE(SMBioctl);
627 return(UNIXERROR(ERRDOS,ERRbadfid));
629 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
630 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
631 if (conn) {
632 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
634 break;
638 END_PROFILE(SMBioctl);
639 return outsize;
642 /****************************************************************************
643 Reply to a chkpth.
644 ****************************************************************************/
646 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
648 int outsize = 0;
649 pstring name;
650 BOOL ok = False;
651 BOOL bad_path = False;
652 SMB_STRUCT_STAT sbuf;
653 NTSTATUS status;
655 START_PROFILE(SMBchkpth);
657 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
658 if (!NT_STATUS_IS_OK(status)) {
659 END_PROFILE(SMBchkpth);
660 return ERROR_NT(status);
663 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
665 unix_convert(name,conn,0,&bad_path,&sbuf);
666 if (bad_path) {
667 END_PROFILE(SMBchkpth);
668 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
671 if (check_name(name,conn)) {
672 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
673 if (!(ok = S_ISDIR(sbuf.st_mode))) {
674 END_PROFILE(SMBchkpth);
675 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
679 if (!ok) {
680 /* We special case this - as when a Windows machine
681 is parsing a path is steps through the components
682 one at a time - if a component fails it expects
683 ERRbadpath, not ERRbadfile.
685 if(errno == ENOENT) {
687 * Windows returns different error codes if
688 * the parent directory is valid but not the
689 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
690 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
691 * if the path is invalid. This is different from set_bad_path_error()
692 * in the non-NT error case.
694 END_PROFILE(SMBchkpth);
695 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
698 END_PROFILE(SMBchkpth);
699 return(UNIXERROR(ERRDOS,ERRbadpath));
702 outsize = set_message(outbuf,0,0,True);
703 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
705 END_PROFILE(SMBchkpth);
706 return(outsize);
709 /****************************************************************************
710 Reply to a getatr.
711 ****************************************************************************/
713 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
715 pstring fname;
716 int outsize = 0;
717 SMB_STRUCT_STAT sbuf;
718 BOOL ok = False;
719 int mode=0;
720 SMB_OFF_T size=0;
721 time_t mtime=0;
722 BOOL bad_path = False;
723 char *p;
724 NTSTATUS status;
726 START_PROFILE(SMBgetatr);
728 p = smb_buf(inbuf) + 1;
729 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
730 if (!NT_STATUS_IS_OK(status)) {
731 END_PROFILE(SMBgetatr);
732 return ERROR_NT(status);
735 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
737 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
738 under WfWg - weird! */
739 if (! (*fname)) {
740 mode = aHIDDEN | aDIR;
741 if (!CAN_WRITE(conn))
742 mode |= aRONLY;
743 size = 0;
744 mtime = 0;
745 ok = True;
746 } else {
747 unix_convert(fname,conn,0,&bad_path,&sbuf);
748 if (bad_path) {
749 END_PROFILE(SMBgetatr);
750 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
752 if (check_name(fname,conn)) {
753 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
754 mode = dos_mode(conn,fname,&sbuf);
755 size = sbuf.st_size;
756 mtime = sbuf.st_mtime;
757 if (mode & aDIR)
758 size = 0;
759 ok = True;
760 } else {
761 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
766 if (!ok) {
767 END_PROFILE(SMBgetatr);
768 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
771 outsize = set_message(outbuf,10,0,True);
773 SSVAL(outbuf,smb_vwv0,mode);
774 if(lp_dos_filetime_resolution(SNUM(conn)) )
775 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
776 else
777 put_dos_date3(outbuf,smb_vwv1,mtime);
778 SIVAL(outbuf,smb_vwv3,(uint32)size);
780 if (Protocol >= PROTOCOL_NT1)
781 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
783 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
785 END_PROFILE(SMBgetatr);
786 return(outsize);
789 /****************************************************************************
790 Reply to a setatr.
791 ****************************************************************************/
793 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
795 pstring fname;
796 int outsize = 0;
797 BOOL ok=False;
798 int mode;
799 time_t mtime;
800 SMB_STRUCT_STAT sbuf;
801 BOOL bad_path = False;
802 char *p;
803 NTSTATUS status;
805 START_PROFILE(SMBsetatr);
807 p = smb_buf(inbuf) + 1;
808 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
809 if (!NT_STATUS_IS_OK(status)) {
810 END_PROFILE(SMBsetatr);
811 return ERROR_NT(status);
814 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
816 unix_convert(fname,conn,0,&bad_path,&sbuf);
817 if (bad_path) {
818 END_PROFILE(SMBsetatr);
819 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
822 mode = SVAL(inbuf,smb_vwv0);
823 mtime = make_unix_date3(inbuf+smb_vwv1);
825 if (mode != FILE_ATTRIBUTE_NORMAL) {
826 if (VALID_STAT_OF_DIR(sbuf))
827 mode |= aDIR;
828 else
829 mode &= ~aDIR;
831 if (check_name(fname,conn)) {
832 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
834 } else {
835 ok = True;
838 if (ok)
839 ok = set_filetime(conn,fname,mtime);
841 if (!ok) {
842 END_PROFILE(SMBsetatr);
843 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
846 outsize = set_message(outbuf,0,0,True);
848 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
850 END_PROFILE(SMBsetatr);
851 return(outsize);
854 /****************************************************************************
855 Reply to a dskattr.
856 ****************************************************************************/
858 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
860 int outsize = 0;
861 SMB_BIG_UINT dfree,dsize,bsize;
862 START_PROFILE(SMBdskattr);
864 if (SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
865 END_PROFILE(SMBdskattr);
866 return(UNIXERROR(ERRHRD,ERRgeneral));
869 outsize = set_message(outbuf,5,0,True);
871 if (Protocol <= PROTOCOL_LANMAN2) {
872 double total_space, free_space;
873 /* we need to scale this to a number that DOS6 can handle. We
874 use floating point so we can handle large drives on systems
875 that don't have 64 bit integers
877 we end up displaying a maximum of 2G to DOS systems
879 total_space = dsize * (double)bsize;
880 free_space = dfree * (double)bsize;
882 dsize = (total_space+63*512) / (64*512);
883 dfree = (free_space+63*512) / (64*512);
885 if (dsize > 0xFFFF) dsize = 0xFFFF;
886 if (dfree > 0xFFFF) dfree = 0xFFFF;
888 SSVAL(outbuf,smb_vwv0,dsize);
889 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
890 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
891 SSVAL(outbuf,smb_vwv3,dfree);
892 } else {
893 SSVAL(outbuf,smb_vwv0,dsize);
894 SSVAL(outbuf,smb_vwv1,bsize/512);
895 SSVAL(outbuf,smb_vwv2,512);
896 SSVAL(outbuf,smb_vwv3,dfree);
899 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
901 END_PROFILE(SMBdskattr);
902 return(outsize);
905 /****************************************************************************
906 Reply to a search.
907 Can be called from SMBsearch, SMBffirst or SMBfunique.
908 ****************************************************************************/
910 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
912 pstring mask;
913 pstring directory;
914 pstring fname;
915 SMB_OFF_T size;
916 int mode;
917 time_t date;
918 int dirtype;
919 int outsize = 0;
920 unsigned int numentries = 0;
921 unsigned int maxentries = 0;
922 BOOL finished = False;
923 char *p;
924 BOOL ok = False;
925 int status_len;
926 pstring path;
927 char status[21];
928 int dptr_num= -1;
929 BOOL check_descend = False;
930 BOOL expect_close = False;
931 BOOL can_open = True;
932 BOOL bad_path = False;
933 NTSTATUS nt_status;
934 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
936 START_PROFILE(SMBsearch);
938 *mask = *directory = *fname = 0;
940 /* If we were called as SMBffirst then we must expect close. */
941 if(CVAL(inbuf,smb_com) == SMBffirst)
942 expect_close = True;
944 outsize = set_message(outbuf,1,3,True);
945 maxentries = SVAL(inbuf,smb_vwv0);
946 dirtype = SVAL(inbuf,smb_vwv1);
947 p = smb_buf(inbuf) + 1;
948 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
949 if (!NT_STATUS_IS_OK(nt_status)) {
950 END_PROFILE(SMBsearch);
951 return ERROR_NT(nt_status);
954 RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
956 p++;
957 status_len = SVAL(p, 0);
958 p += 2;
960 /* dirtype &= ~aDIR; */
962 if (status_len == 0) {
963 SMB_STRUCT_STAT sbuf;
964 pstring dir2;
966 pstrcpy(directory,path);
967 pstrcpy(dir2,path);
968 unix_convert(directory,conn,0,&bad_path,&sbuf);
969 unix_format(dir2);
971 if (!check_name(directory,conn))
972 can_open = False;
974 p = strrchr_m(dir2,'/');
975 if (p == NULL) {
976 pstrcpy(mask,dir2);
977 *dir2 = 0;
978 } else {
979 *p = 0;
980 pstrcpy(mask,p+1);
983 p = strrchr_m(directory,'/');
984 if (!p)
985 *directory = 0;
986 else
987 *p = 0;
989 if (strlen(directory) == 0)
990 pstrcpy(directory,".");
991 memset((char *)status,'\0',21);
992 SCVAL(status,0,(dirtype & 0x1F));
993 } else {
994 int status_dirtype;
996 memcpy(status,p,21);
997 status_dirtype = CVAL(status,0) & 0x1F;
998 if (status_dirtype != (dirtype & 0x1F))
999 dirtype = status_dirtype;
1001 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1002 if (!conn->dirptr)
1003 goto SearchEmpty;
1004 string_set(&conn->dirpath,dptr_path(dptr_num));
1005 pstrcpy(mask, dptr_wcard(dptr_num));
1008 if (can_open) {
1009 p = smb_buf(outbuf) + 3;
1010 ok = True;
1012 if (status_len == 0) {
1013 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1014 if (dptr_num < 0) {
1015 if(dptr_num == -2) {
1016 END_PROFILE(SMBsearch);
1017 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
1019 END_PROFILE(SMBsearch);
1020 return ERROR_DOS(ERRDOS,ERRnofids);
1022 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1023 END_PROFILE(SMBsearch);
1024 return ERROR_DOS(ERRDOS,ERRnomem);
1026 } else {
1027 dirtype = dptr_attr(dptr_num);
1030 DEBUG(4,("dptr_num is %d\n",dptr_num));
1032 if (ok) {
1033 if ((dirtype&0x1F) == aVOLID) {
1034 memcpy(p,status,21);
1035 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1036 0,aVOLID,0,!allow_long_path_components);
1037 dptr_fill(p+12,dptr_num);
1038 if (dptr_zero(p+12) && (status_len==0))
1039 numentries = 1;
1040 else
1041 numentries = 0;
1042 p += DIR_STRUCT_SIZE;
1043 } else {
1044 unsigned int i;
1045 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1047 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1048 conn->dirpath,lp_dontdescend(SNUM(conn))));
1049 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1050 check_descend = True;
1052 for (i=numentries;(i<maxentries) && !finished;i++) {
1053 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1054 if (!finished) {
1055 memcpy(p,status,21);
1056 make_dir_struct(p,mask,fname,size, mode,date,
1057 !allow_long_path_components);
1058 dptr_fill(p+12,dptr_num);
1059 numentries++;
1060 p += DIR_STRUCT_SIZE;
1064 } /* if (ok ) */
1068 SearchEmpty:
1070 /* If we were called as SMBffirst with smb_search_id == NULL
1071 and no entries were found then return error and close dirptr
1072 (X/Open spec) */
1074 if (numentries == 0 || !ok) {
1075 dptr_close(&dptr_num);
1076 } else if(ok && expect_close && status_len == 0) {
1077 /* Close the dptr - we know it's gone */
1078 dptr_close(&dptr_num);
1081 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1082 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1083 dptr_close(&dptr_num);
1086 if ((numentries == 0) && !ms_has_wild(mask)) {
1087 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1090 SSVAL(outbuf,smb_vwv0,numentries);
1091 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1092 SCVAL(smb_buf(outbuf),0,5);
1093 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1095 /* The replies here are never long name. */
1096 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1097 if (!allow_long_path_components) {
1098 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1101 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1102 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1104 outsize += DIR_STRUCT_SIZE*numentries;
1105 smb_setlen(outbuf,outsize - 4);
1107 if ((! *directory) && dptr_path(dptr_num))
1108 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1110 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1111 smb_fn_name(CVAL(inbuf,smb_com)),
1112 mask, directory, dirtype, numentries, maxentries ) );
1114 END_PROFILE(SMBsearch);
1115 return(outsize);
1118 /****************************************************************************
1119 Reply to a fclose (stop directory search).
1120 ****************************************************************************/
1122 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1124 int outsize = 0;
1125 int status_len;
1126 pstring path;
1127 char status[21];
1128 int dptr_num= -2;
1129 char *p;
1130 NTSTATUS err;
1132 START_PROFILE(SMBfclose);
1134 outsize = set_message(outbuf,1,0,True);
1135 p = smb_buf(inbuf) + 1;
1136 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1137 if (!NT_STATUS_IS_OK(err)) {
1138 END_PROFILE(SMBfclose);
1139 return ERROR_NT(err);
1141 p++;
1142 status_len = SVAL(p,0);
1143 p += 2;
1145 if (status_len == 0) {
1146 END_PROFILE(SMBfclose);
1147 return ERROR_DOS(ERRSRV,ERRsrverror);
1150 memcpy(status,p,21);
1152 if(dptr_fetch(status+12,&dptr_num)) {
1153 /* Close the dptr - we know it's gone */
1154 dptr_close(&dptr_num);
1157 SSVAL(outbuf,smb_vwv0,0);
1159 DEBUG(3,("search close\n"));
1161 END_PROFILE(SMBfclose);
1162 return(outsize);
1165 /****************************************************************************
1166 Reply to an open.
1167 ****************************************************************************/
1169 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1171 pstring fname;
1172 int outsize = 0;
1173 int fmode=0;
1174 int share_mode;
1175 SMB_OFF_T size = 0;
1176 time_t mtime=0;
1177 int rmode=0;
1178 SMB_STRUCT_STAT sbuf;
1179 BOOL bad_path = False;
1180 files_struct *fsp;
1181 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1182 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1183 NTSTATUS status;
1184 START_PROFILE(SMBopen);
1186 share_mode = SVAL(inbuf,smb_vwv0);
1188 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 END_PROFILE(SMBopen);
1191 return ERROR_NT(status);
1194 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1196 unix_convert(fname,conn,0,&bad_path,&sbuf);
1197 if (bad_path) {
1198 END_PROFILE(SMBopen);
1199 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1202 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1203 (uint32)dos_attr, oplock_request,&rmode,NULL);
1205 if (!fsp) {
1206 END_PROFILE(SMBopen);
1207 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1208 /* We have re-scheduled this call. */
1209 return -1;
1211 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1214 size = sbuf.st_size;
1215 fmode = dos_mode(conn,fname,&sbuf);
1216 mtime = sbuf.st_mtime;
1218 if (fmode & aDIR) {
1219 DEBUG(3,("attempt to open a directory %s\n",fname));
1220 close_file(fsp,False);
1221 END_PROFILE(SMBopen);
1222 return ERROR_DOS(ERRDOS,ERRnoaccess);
1225 outsize = set_message(outbuf,7,0,True);
1226 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1227 SSVAL(outbuf,smb_vwv1,fmode);
1228 if(lp_dos_filetime_resolution(SNUM(conn)) )
1229 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1230 else
1231 put_dos_date3(outbuf,smb_vwv2,mtime);
1232 SIVAL(outbuf,smb_vwv4,(uint32)size);
1233 SSVAL(outbuf,smb_vwv6,rmode);
1235 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1236 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1238 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1239 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1240 END_PROFILE(SMBopen);
1241 return(outsize);
1244 /****************************************************************************
1245 Reply to an open and X.
1246 ****************************************************************************/
1248 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1250 pstring fname;
1251 int smb_mode = SVAL(inbuf,smb_vwv3);
1252 int smb_attr = SVAL(inbuf,smb_vwv5);
1253 /* Breakout the oplock request bits so we can set the
1254 reply bits separately. */
1255 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1256 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1257 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1258 #if 0
1259 int open_flags = SVAL(inbuf,smb_vwv2);
1260 int smb_sattr = SVAL(inbuf,smb_vwv4);
1261 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1262 #endif
1263 int smb_ofun = SVAL(inbuf,smb_vwv8);
1264 SMB_OFF_T size=0;
1265 int fmode=0,mtime=0,rmode=0;
1266 SMB_STRUCT_STAT sbuf;
1267 int smb_action = 0;
1268 BOOL bad_path = False;
1269 files_struct *fsp;
1270 NTSTATUS status;
1271 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1272 ssize_t retval = -1;
1274 START_PROFILE(SMBopenX);
1276 /* If it's an IPC, pass off the pipe handler. */
1277 if (IS_IPC(conn)) {
1278 if (lp_nt_pipe_support()) {
1279 END_PROFILE(SMBopenX);
1280 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1281 } else {
1282 END_PROFILE(SMBopenX);
1283 return ERROR_DOS(ERRSRV,ERRaccess);
1287 /* XXXX we need to handle passed times, sattr and flags */
1288 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 END_PROFILE(SMBopenX);
1291 return ERROR_NT(status);
1294 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1296 unix_convert(fname,conn,0,&bad_path,&sbuf);
1297 if (bad_path) {
1298 END_PROFILE(SMBopenX);
1299 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1302 /* Strange open mode mapping. */
1303 if (smb_ofun == 0) {
1304 if (GET_OPEN_MODE(smb_mode) == DOS_OPEN_EXEC) {
1305 smb_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST;
1306 } else {
1307 END_PROFILE(SMBopenX);
1308 return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess);
1312 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1313 oplock_request, &rmode,&smb_action);
1315 if (!fsp) {
1316 END_PROFILE(SMBopenX);
1317 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1318 /* We have re-scheduled this call. */
1319 return -1;
1321 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1324 size = sbuf.st_size;
1326 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1327 if the file is truncated or created. */
1328 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1329 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1330 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1331 close_file(fsp,False);
1332 END_PROFILE(SMBntcreateX);
1333 return ERROR_NT(NT_STATUS_DISK_FULL);
1335 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1336 if (retval < 0) {
1337 close_file(fsp,False);
1338 END_PROFILE(SMBwrite);
1339 return ERROR_NT(NT_STATUS_DISK_FULL);
1341 size = get_allocation_size(conn,fsp,&sbuf);
1344 fmode = dos_mode(conn,fname,&sbuf);
1345 mtime = sbuf.st_mtime;
1346 if (fmode & aDIR) {
1347 close_file(fsp,False);
1348 END_PROFILE(SMBopenX);
1349 return ERROR_DOS(ERRDOS,ERRnoaccess);
1352 /* If the caller set the extended oplock request bit
1353 and we granted one (by whatever means) - set the
1354 correct bit for extended oplock reply.
1357 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1358 smb_action |= EXTENDED_OPLOCK_GRANTED;
1360 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1361 smb_action |= EXTENDED_OPLOCK_GRANTED;
1363 /* If the caller set the core oplock request bit
1364 and we granted one (by whatever means) - set the
1365 correct bit for core oplock reply.
1368 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1369 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1371 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1372 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1374 set_message(outbuf,15,0,True);
1375 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1376 SSVAL(outbuf,smb_vwv3,fmode);
1377 if(lp_dos_filetime_resolution(SNUM(conn)) )
1378 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1379 else
1380 put_dos_date3(outbuf,smb_vwv4,mtime);
1381 SIVAL(outbuf,smb_vwv6,(uint32)size);
1382 SSVAL(outbuf,smb_vwv8,rmode);
1383 SSVAL(outbuf,smb_vwv11,smb_action);
1385 END_PROFILE(SMBopenX);
1386 return chain_reply(inbuf,outbuf,length,bufsize);
1389 /****************************************************************************
1390 Reply to a SMBulogoffX.
1391 ****************************************************************************/
1393 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1395 uint16 vuid = SVAL(inbuf,smb_uid);
1396 user_struct *vuser = get_valid_user_struct(vuid);
1397 START_PROFILE(SMBulogoffX);
1399 if(vuser == 0)
1400 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1402 /* in user level security we are supposed to close any files
1403 open by this user */
1404 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1405 file_close_user(vuid);
1407 invalidate_vuid(vuid);
1409 set_message(outbuf,2,0,True);
1411 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1413 END_PROFILE(SMBulogoffX);
1414 return chain_reply(inbuf,outbuf,length,bufsize);
1417 /****************************************************************************
1418 Reply to a mknew or a create.
1419 ****************************************************************************/
1421 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1423 pstring fname;
1424 int com;
1425 int outsize = 0;
1426 int createmode;
1427 int ofun = 0;
1428 BOOL bad_path = False;
1429 files_struct *fsp;
1430 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1431 SMB_STRUCT_STAT sbuf;
1432 NTSTATUS status;
1433 START_PROFILE(SMBcreate);
1435 com = SVAL(inbuf,smb_com);
1437 createmode = SVAL(inbuf,smb_vwv0);
1438 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 END_PROFILE(SMBcreate);
1441 return ERROR_NT(status);
1444 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1446 unix_convert(fname,conn,0,&bad_path,&sbuf);
1447 if (bad_path) {
1448 END_PROFILE(SMBcreate);
1449 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1452 if (createmode & aVOLID)
1453 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1455 if(com == SMBmknew) {
1456 /* We should fail if file exists. */
1457 ofun = FILE_CREATE_IF_NOT_EXIST;
1458 } else {
1459 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1460 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1463 /* Open file in dos compatibility share mode. */
1464 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1465 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1467 if (!fsp) {
1468 END_PROFILE(SMBcreate);
1469 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1470 /* We have re-scheduled this call. */
1471 return -1;
1473 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1476 outsize = set_message(outbuf,1,0,True);
1477 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1479 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1480 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1482 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1483 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1485 DEBUG( 2, ( "new file %s\n", fname ) );
1486 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1488 END_PROFILE(SMBcreate);
1489 return(outsize);
1492 /****************************************************************************
1493 Reply to a create temporary file.
1494 ****************************************************************************/
1496 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1498 pstring fname;
1499 int outsize = 0;
1500 int createattr;
1501 BOOL bad_path = False;
1502 files_struct *fsp;
1503 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1504 int tmpfd;
1505 SMB_STRUCT_STAT sbuf;
1506 char *p, *s;
1507 NTSTATUS status;
1508 unsigned int namelen;
1510 START_PROFILE(SMBctemp);
1512 createattr = SVAL(inbuf,smb_vwv0);
1513 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1514 if (!NT_STATUS_IS_OK(status)) {
1515 END_PROFILE(SMBctemp);
1516 return ERROR_NT(status);
1518 if (*fname) {
1519 pstrcat(fname,"/TMXXXXXX");
1520 } else {
1521 pstrcat(fname,"TMXXXXXX");
1524 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1526 unix_convert(fname,conn,0,&bad_path,&sbuf);
1527 if (bad_path) {
1528 END_PROFILE(SMBctemp);
1529 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1532 tmpfd = smb_mkstemp(fname);
1533 if (tmpfd == -1) {
1534 END_PROFILE(SMBctemp);
1535 return(UNIXERROR(ERRDOS,ERRnoaccess));
1538 SMB_VFS_STAT(conn,fname,&sbuf);
1540 /* Open file in dos compatibility share mode. */
1541 /* We should fail if file does not exist. */
1542 fsp = open_file_shared(conn,fname,&sbuf,
1543 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1544 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1545 (uint32)createattr, oplock_request, NULL, NULL);
1547 /* close fd from smb_mkstemp() */
1548 close(tmpfd);
1550 if (!fsp) {
1551 END_PROFILE(SMBctemp);
1552 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1553 /* We have re-scheduled this call. */
1554 return -1;
1556 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1559 outsize = set_message(outbuf,1,0,True);
1560 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1562 /* the returned filename is relative to the directory */
1563 s = strrchr_m(fname, '/');
1564 if (!s)
1565 s = fname;
1566 else
1567 s++;
1569 p = smb_buf(outbuf);
1570 #if 0
1571 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1572 thing in the byte section. JRA */
1573 SSVALS(p, 0, -1); /* what is this? not in spec */
1574 #endif
1575 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1576 p += namelen;
1577 outsize = set_message_end(outbuf, p);
1579 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1580 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1582 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1583 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1585 DEBUG( 2, ( "created temp file %s\n", fname ) );
1586 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1587 fname, fsp->fd, sbuf.st_mode ) );
1589 END_PROFILE(SMBctemp);
1590 return(outsize);
1593 /*******************************************************************
1594 Check if a user is allowed to rename a file.
1595 ********************************************************************/
1597 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1599 int smb_action;
1600 int access_mode;
1601 files_struct *fsp;
1602 uint16 fmode;
1604 if (!CAN_WRITE(conn))
1605 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1607 fmode = dos_mode(conn,fname,pst);
1608 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1609 return NT_STATUS_NO_SUCH_FILE;
1611 if (S_ISDIR(pst->st_mode))
1612 return NT_STATUS_OK;
1614 /* We need a better way to return NT status codes from open... */
1615 set_saved_error_triple(0, 0, NT_STATUS_OK);
1617 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1618 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1620 if (!fsp) {
1621 NTSTATUS ret;
1622 if (get_saved_error_triple(NULL, NULL, &ret)) {
1623 set_saved_error_triple(0, 0, NT_STATUS_OK);
1624 return ret;
1626 set_saved_error_triple(0, 0, NT_STATUS_OK);
1627 return NT_STATUS_ACCESS_DENIED;
1629 close_file(fsp,False);
1630 return NT_STATUS_OK;
1633 /*******************************************************************
1634 Check if a user is allowed to delete a file.
1635 ********************************************************************/
1637 NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
1639 SMB_STRUCT_STAT sbuf;
1640 int fmode;
1641 int smb_action;
1642 int access_mode;
1643 files_struct *fsp;
1645 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1646 fname, dirtype ));
1648 if (!CAN_WRITE(conn))
1649 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1651 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1652 if(errno == ENOENT) {
1653 if (bad_path)
1654 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1655 else
1656 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1658 return map_nt_error_from_unix(errno);
1661 fmode = dos_mode(conn,fname,&sbuf);
1663 /* Can't delete a directory. */
1664 if (fmode & aDIR)
1665 return NT_STATUS_FILE_IS_A_DIRECTORY;
1666 #if 0 /* JRATEST */
1667 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1668 return NT_STATUS_OBJECT_NAME_INVALID;
1669 #endif /* JRATEST */
1671 if (!lp_delete_readonly(SNUM(conn))) {
1672 if (fmode & aRONLY)
1673 return NT_STATUS_CANNOT_DELETE;
1675 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1676 return NT_STATUS_NO_SUCH_FILE;
1678 if (check_is_at_open) {
1679 if (!can_delete_file_in_directory(conn, fname)) {
1680 return NT_STATUS_ACCESS_DENIED;
1682 } else {
1683 /* On open checks the open itself will check the share mode, so
1684 don't do it here as we'll get it wrong. */
1686 /* We need a better way to return NT status codes from open... */
1687 set_saved_error_triple(0, 0, NT_STATUS_OK);
1689 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1690 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1692 if (!fsp) {
1693 NTSTATUS ret;
1694 if (get_saved_error_triple(NULL, NULL, &ret)) {
1695 set_saved_error_triple(0, 0, NT_STATUS_OK);
1696 return ret;
1698 set_saved_error_triple(0, 0, NT_STATUS_OK);
1699 return NT_STATUS_ACCESS_DENIED;
1701 close_file(fsp,False);
1703 return NT_STATUS_OK;
1706 /****************************************************************************
1707 The guts of the unlink command, split out so it may be called by the NT SMB
1708 code.
1709 ****************************************************************************/
1711 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1713 pstring directory;
1714 pstring mask;
1715 char *p;
1716 int count=0;
1717 NTSTATUS error = NT_STATUS_OK;
1718 BOOL has_wild;
1719 BOOL bad_path = False;
1720 BOOL rc = True;
1721 SMB_STRUCT_STAT sbuf;
1723 *directory = *mask = 0;
1725 /* We must check for wildcards in the name given
1726 * directly by the client - before any unmangling.
1727 * This prevents an unmangling of a UNIX name containing
1728 * a DOS wildcard like '*' or '?' from unmangling into
1729 * a wildcard delete which was not intended.
1730 * FIX for #226. JRA.
1733 has_wild = ms_has_wild(name);
1735 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1737 p = strrchr_m(name,'/');
1738 if (!p) {
1739 pstrcpy(directory,".");
1740 pstrcpy(mask,name);
1741 } else {
1742 *p = 0;
1743 pstrcpy(directory,name);
1744 pstrcpy(mask,p+1);
1748 * We should only check the mangled cache
1749 * here if unix_convert failed. This means
1750 * that the path in 'mask' doesn't exist
1751 * on the file system and so we need to look
1752 * for a possible mangle. This patch from
1753 * Tine Smukavec <valentin.smukavec@hermes.si>.
1756 if (!rc && mangle_is_mangled(mask))
1757 mangle_check_cache( mask, sizeof(pstring)-1 );
1759 if (!has_wild) {
1760 pstrcat(directory,"/");
1761 pstrcat(directory,mask);
1762 error = can_delete(conn,directory,dirtype,bad_path,False);
1763 if (!NT_STATUS_IS_OK(error))
1764 return error;
1766 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1767 count++;
1769 } else {
1770 struct smb_Dir *dir_hnd = NULL;
1771 const char *dname;
1773 if (check_name(directory,conn))
1774 dir_hnd = OpenDir(conn, directory);
1776 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1777 the pattern matches against the long name, otherwise the short name
1778 We don't implement this yet XXXX
1781 if (dir_hnd) {
1782 long offset = 0;
1783 error = NT_STATUS_NO_SUCH_FILE;
1785 if (strequal(mask,"????????.???"))
1786 pstrcpy(mask,"*");
1788 while ((dname = ReadDirName(dir_hnd, &offset))) {
1789 SMB_STRUCT_STAT st;
1790 pstring fname;
1791 BOOL sys_direntry = False;
1792 pstrcpy(fname,dname);
1794 if (!is_visible_file(conn, directory, dname, &st, True)) {
1795 continue;
1798 /* Quick check for "." and ".." */
1799 if (fname[0] == '.') {
1800 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1801 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1802 sys_direntry = True;
1803 } else {
1804 continue;
1809 if(!mask_match(fname, mask, conn->case_sensitive))
1810 continue;
1812 if (sys_direntry) {
1813 error = NT_STATUS_OBJECT_NAME_INVALID;
1814 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1815 fname, mask));
1816 break;
1819 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1820 error = can_delete(conn,fname,dirtype,bad_path,False);
1821 if (!NT_STATUS_IS_OK(error)) {
1822 continue;
1824 if (SMB_VFS_UNLINK(conn,fname) == 0)
1825 count++;
1826 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1828 CloseDir(dir_hnd);
1832 if (count == 0 && NT_STATUS_IS_OK(error)) {
1833 error = map_nt_error_from_unix(errno);
1836 return error;
1839 /****************************************************************************
1840 Reply to a unlink
1841 ****************************************************************************/
1843 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1844 int dum_buffsize)
1846 int outsize = 0;
1847 pstring name;
1848 int dirtype;
1849 NTSTATUS status;
1850 START_PROFILE(SMBunlink);
1852 dirtype = SVAL(inbuf,smb_vwv0);
1854 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 END_PROFILE(SMBunlink);
1857 return ERROR_NT(status);
1860 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
1862 DEBUG(3,("reply_unlink : %s\n",name));
1864 status = unlink_internals(conn, dirtype, name);
1865 if (!NT_STATUS_IS_OK(status)) {
1866 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1867 /* We have re-scheduled this call. */
1868 return -1;
1870 return ERROR_NT(status);
1874 * Win2k needs a changenotify request response before it will
1875 * update after a rename..
1877 process_pending_change_notify_queue((time_t)0);
1879 outsize = set_message(outbuf,0,0,True);
1881 END_PROFILE(SMBunlink);
1882 return outsize;
1885 /****************************************************************************
1886 Fail for readbraw.
1887 ****************************************************************************/
1889 static void fail_readraw(void)
1891 pstring errstr;
1892 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1893 strerror(errno) );
1894 exit_server(errstr);
1897 #if defined(WITH_SENDFILE)
1898 /****************************************************************************
1899 Fake (read/write) sendfile. Returns -1 on read or write fail.
1900 ****************************************************************************/
1902 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1904 ssize_t ret=0;
1906 /* Paranioa check... */
1907 if (nread > bufsize) {
1908 fail_readraw();
1911 if (nread > 0) {
1912 ret = read_file(fsp,buf,startpos,nread);
1913 if (ret == -1) {
1914 return -1;
1918 /* If we had a short read, fill with zeros. */
1919 if (ret < nread) {
1920 memset(buf, '\0', nread - ret);
1923 if (write_data(smbd_server_fd(),buf,nread) != nread) {
1924 return -1;
1927 return (ssize_t)nread;
1929 #endif
1931 /****************************************************************************
1932 Use sendfile in readbraw.
1933 ****************************************************************************/
1935 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1936 ssize_t mincount, char *outbuf, int out_buffsize)
1938 ssize_t ret=0;
1940 #if defined(WITH_SENDFILE)
1942 * We can only use sendfile on a non-chained packet
1943 * but we can use on a non-oplocked file. tridge proved this
1944 * on a train in Germany :-). JRA.
1945 * reply_readbraw has already checked the length.
1948 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1949 DATA_BLOB header;
1951 _smb_setlen(outbuf,nread);
1952 header.data = outbuf;
1953 header.length = 4;
1954 header.free = NULL;
1956 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1957 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
1958 if (errno == ENOSYS) {
1959 goto normal_readbraw;
1963 * Special hack for broken Linux with no working sendfile. If we
1964 * return EINTR we sent the header but not the rest of the data.
1965 * Fake this up by doing read/write calls.
1967 if (errno == EINTR) {
1968 /* Ensure we don't do this again. */
1969 set_use_sendfile(SNUM(conn), False);
1970 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
1972 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
1973 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
1974 fsp->fsp_name, strerror(errno) ));
1975 exit_server("send_file_readbraw fake_sendfile failed");
1977 return;
1980 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1981 fsp->fsp_name, strerror(errno) ));
1982 exit_server("send_file_readbraw sendfile failed");
1987 normal_readbraw:
1989 #endif
1991 if (nread > 0) {
1992 ret = read_file(fsp,outbuf+4,startpos,nread);
1993 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1994 if (ret < mincount)
1995 ret = 0;
1996 #else
1997 if (ret < nread)
1998 ret = 0;
1999 #endif
2002 _smb_setlen(outbuf,ret);
2003 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2004 fail_readraw();
2007 /****************************************************************************
2008 Reply to a readbraw (core+ protocol).
2009 ****************************************************************************/
2011 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2013 ssize_t maxcount,mincount;
2014 size_t nread = 0;
2015 SMB_OFF_T startpos;
2016 char *header = outbuf;
2017 files_struct *fsp;
2018 START_PROFILE(SMBreadbraw);
2020 if (srv_is_signing_active()) {
2021 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2025 * Special check if an oplock break has been issued
2026 * and the readraw request croses on the wire, we must
2027 * return a zero length response here.
2030 if(global_oplock_break) {
2031 _smb_setlen(header,0);
2032 if (write_data(smbd_server_fd(),header,4) != 4)
2033 fail_readraw();
2034 DEBUG(5,("readbraw - oplock break finished\n"));
2035 END_PROFILE(SMBreadbraw);
2036 return -1;
2039 fsp = file_fsp(inbuf,smb_vwv0);
2041 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2043 * fsp could be NULL here so use the value from the packet. JRA.
2045 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2046 _smb_setlen(header,0);
2047 if (write_data(smbd_server_fd(),header,4) != 4)
2048 fail_readraw();
2049 END_PROFILE(SMBreadbraw);
2050 return(-1);
2053 CHECK_FSP(fsp,conn);
2055 flush_write_cache(fsp, READRAW_FLUSH);
2057 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2058 if(CVAL(inbuf,smb_wct) == 10) {
2060 * This is a large offset (64 bit) read.
2062 #ifdef LARGE_SMB_OFF_T
2064 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2066 #else /* !LARGE_SMB_OFF_T */
2069 * Ensure we haven't been sent a >32 bit offset.
2072 if(IVAL(inbuf,smb_vwv8) != 0) {
2073 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
2074 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2075 _smb_setlen(header,0);
2076 if (write_data(smbd_server_fd(),header,4) != 4)
2077 fail_readraw();
2078 END_PROFILE(SMBreadbraw);
2079 return(-1);
2082 #endif /* LARGE_SMB_OFF_T */
2084 if(startpos < 0) {
2085 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2086 _smb_setlen(header,0);
2087 if (write_data(smbd_server_fd(),header,4) != 4)
2088 fail_readraw();
2089 END_PROFILE(SMBreadbraw);
2090 return(-1);
2093 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2094 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2096 /* ensure we don't overrun the packet size */
2097 maxcount = MIN(65535,maxcount);
2099 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2100 SMB_OFF_T size = fsp->size;
2101 SMB_OFF_T sizeneeded = startpos + maxcount;
2103 if (size < sizeneeded) {
2104 SMB_STRUCT_STAT st;
2105 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
2106 size = st.st_size;
2107 if (!fsp->can_write)
2108 fsp->size = size;
2111 if (startpos >= size)
2112 nread = 0;
2113 else
2114 nread = MIN(maxcount,(size - startpos));
2117 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2118 if (nread < mincount)
2119 nread = 0;
2120 #endif
2122 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
2123 (int)maxcount, (int)mincount, (int)nread ) );
2125 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2127 DEBUG(5,("readbraw finished\n"));
2128 END_PROFILE(SMBreadbraw);
2129 return -1;
2132 /****************************************************************************
2133 Reply to a lockread (core+ protocol).
2134 ****************************************************************************/
2136 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2138 ssize_t nread = -1;
2139 char *data;
2140 int outsize = 0;
2141 SMB_OFF_T startpos;
2142 size_t numtoread;
2143 NTSTATUS status;
2144 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2145 BOOL my_lock_ctx = False;
2146 START_PROFILE(SMBlockread);
2148 CHECK_FSP(fsp,conn);
2149 CHECK_READ(fsp);
2151 release_level_2_oplocks_on_change(fsp);
2153 numtoread = SVAL(inbuf,smb_vwv1);
2154 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2156 outsize = set_message(outbuf,5,3,True);
2157 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2158 data = smb_buf(outbuf) + 3;
2161 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2162 * protocol request that predates the read/write lock concept.
2163 * Thus instead of asking for a read lock here we need to ask
2164 * for a write lock. JRA.
2165 * Note that the requested lock size is unaffected by max_recv.
2168 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2169 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2171 if (NT_STATUS_V(status)) {
2172 #if 0
2174 * We used to make lockread a blocking lock. It turns out
2175 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2176 * tester. JRA.
2179 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2181 * A blocking lock was requested. Package up
2182 * this smb into a queued request and push it
2183 * onto the blocking lock queue.
2185 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2186 (SMB_BIG_UINT)numtoread)) {
2187 END_PROFILE(SMBlockread);
2188 return -1;
2191 #endif
2192 END_PROFILE(SMBlockread);
2193 return ERROR_NT(status);
2197 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2200 if (numtoread > max_recv) {
2201 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2202 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2203 (unsigned int)numtoread, (unsigned int)max_recv ));
2204 numtoread = MIN(numtoread,max_recv);
2206 nread = read_file(fsp,data,startpos,numtoread);
2208 if (nread < 0) {
2209 END_PROFILE(SMBlockread);
2210 return(UNIXERROR(ERRDOS,ERRnoaccess));
2213 outsize += nread;
2214 SSVAL(outbuf,smb_vwv0,nread);
2215 SSVAL(outbuf,smb_vwv5,nread+3);
2216 SSVAL(smb_buf(outbuf),1,nread);
2218 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2219 fsp->fnum, (int)numtoread, (int)nread));
2221 END_PROFILE(SMBlockread);
2222 return(outsize);
2225 /****************************************************************************
2226 Reply to a read.
2227 ****************************************************************************/
2229 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2231 size_t numtoread;
2232 ssize_t nread = 0;
2233 char *data;
2234 SMB_OFF_T startpos;
2235 int outsize = 0;
2236 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2237 START_PROFILE(SMBread);
2239 CHECK_FSP(fsp,conn);
2240 CHECK_READ(fsp);
2242 numtoread = SVAL(inbuf,smb_vwv1);
2243 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2245 outsize = set_message(outbuf,5,3,True);
2246 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2248 * The requested read size cannot be greater than max_recv. JRA.
2250 if (numtoread > max_recv) {
2251 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2252 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2253 (unsigned int)numtoread, (unsigned int)max_recv ));
2254 numtoread = MIN(numtoread,max_recv);
2257 data = smb_buf(outbuf) + 3;
2259 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2260 END_PROFILE(SMBread);
2261 return ERROR_DOS(ERRDOS,ERRlock);
2264 if (numtoread > 0)
2265 nread = read_file(fsp,data,startpos,numtoread);
2267 if (nread < 0) {
2268 END_PROFILE(SMBread);
2269 return(UNIXERROR(ERRDOS,ERRnoaccess));
2272 outsize += nread;
2273 SSVAL(outbuf,smb_vwv0,nread);
2274 SSVAL(outbuf,smb_vwv5,nread+3);
2275 SCVAL(smb_buf(outbuf),0,1);
2276 SSVAL(smb_buf(outbuf),1,nread);
2278 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2279 fsp->fnum, (int)numtoread, (int)nread ) );
2281 END_PROFILE(SMBread);
2282 return(outsize);
2285 /****************************************************************************
2286 Reply to a read and X - possibly using sendfile.
2287 ****************************************************************************/
2289 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2290 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2292 int outsize = 0;
2293 ssize_t nread = -1;
2294 char *data = smb_buf(outbuf);
2296 #if defined(WITH_SENDFILE)
2298 * We can only use sendfile on a non-chained packet
2299 * but we can use on a non-oplocked file. tridge proved this
2300 * on a train in Germany :-). JRA.
2303 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2304 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2305 SMB_STRUCT_STAT sbuf;
2306 DATA_BLOB header;
2308 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2309 return(UNIXERROR(ERRDOS,ERRnoaccess));
2311 if (startpos > sbuf.st_size)
2312 goto normal_read;
2314 if (smb_maxcnt > (sbuf.st_size - startpos))
2315 smb_maxcnt = (sbuf.st_size - startpos);
2317 if (smb_maxcnt == 0)
2318 goto normal_read;
2321 * Set up the packet header before send. We
2322 * assume here the sendfile will work (get the
2323 * correct amount of data).
2326 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2327 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2328 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2329 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2330 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2331 SCVAL(outbuf,smb_vwv0,0xFF);
2332 set_message(outbuf,12,smb_maxcnt,False);
2333 header.data = outbuf;
2334 header.length = data - outbuf;
2335 header.free = NULL;
2337 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2338 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2339 if (errno == ENOSYS) {
2340 goto normal_read;
2344 * Special hack for broken Linux with no working sendfile. If we
2345 * return EINTR we sent the header but not the rest of the data.
2346 * Fake this up by doing read/write calls.
2349 if (errno == EINTR) {
2350 /* Ensure we don't do this again. */
2351 set_use_sendfile(SNUM(conn), False);
2352 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2354 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2355 len_outbuf - (data-outbuf))) == -1) {
2356 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2357 fsp->fsp_name, strerror(errno) ));
2358 exit_server("send_file_readX: fake_sendfile failed");
2360 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2361 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2362 /* Returning -1 here means successful sendfile. */
2363 return -1;
2366 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2367 fsp->fsp_name, strerror(errno) ));
2368 exit_server("send_file_readX sendfile failed");
2371 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2372 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2373 /* Returning -1 here means successful sendfile. */
2374 return -1;
2377 normal_read:
2379 #endif
2381 nread = read_file(fsp,data,startpos,smb_maxcnt);
2383 if (nread < 0) {
2384 END_PROFILE(SMBreadX);
2385 return(UNIXERROR(ERRDOS,ERRnoaccess));
2388 outsize = set_message(outbuf,12,nread,False);
2389 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2390 SSVAL(outbuf,smb_vwv5,nread);
2391 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2392 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2393 SSVAL(smb_buf(outbuf),-2,nread);
2395 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2396 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2398 /* Returning the number of bytes we want to send back - including header. */
2399 return outsize;
2402 /****************************************************************************
2403 Reply to a read and X.
2404 ****************************************************************************/
2406 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2408 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2409 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2410 ssize_t nread = -1;
2411 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2412 #if 0
2413 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2414 #endif
2416 START_PROFILE(SMBreadX);
2418 /* If it's an IPC, pass off the pipe handler. */
2419 if (IS_IPC(conn)) {
2420 END_PROFILE(SMBreadX);
2421 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2424 CHECK_FSP(fsp,conn);
2425 CHECK_READ(fsp);
2427 set_message(outbuf,12,0,True);
2429 if (global_client_caps & CAP_LARGE_READX) {
2430 if (SVAL(inbuf,smb_vwv7) == 1) {
2431 smb_maxcnt |= (1<<16);
2433 if (smb_maxcnt > BUFFER_SIZE) {
2434 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2435 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2436 END_PROFILE(SMBreadX);
2437 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2441 if(CVAL(inbuf,smb_wct) == 12) {
2442 #ifdef LARGE_SMB_OFF_T
2444 * This is a large offset (64 bit) read.
2446 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2448 #else /* !LARGE_SMB_OFF_T */
2451 * Ensure we haven't been sent a >32 bit offset.
2454 if(IVAL(inbuf,smb_vwv10) != 0) {
2455 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2456 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2457 END_PROFILE(SMBreadX);
2458 return ERROR_DOS(ERRDOS,ERRbadaccess);
2461 #endif /* LARGE_SMB_OFF_T */
2465 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2466 END_PROFILE(SMBreadX);
2467 return ERROR_DOS(ERRDOS,ERRlock);
2470 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2471 if (nread != -1)
2472 nread = chain_reply(inbuf,outbuf,length,bufsize);
2474 END_PROFILE(SMBreadX);
2475 return nread;
2478 /****************************************************************************
2479 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2480 ****************************************************************************/
2482 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2484 ssize_t nwritten=0;
2485 ssize_t total_written=0;
2486 size_t numtowrite=0;
2487 size_t tcount;
2488 SMB_OFF_T startpos;
2489 char *data=NULL;
2490 BOOL write_through;
2491 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2492 int outsize = 0;
2493 START_PROFILE(SMBwritebraw);
2495 if (srv_is_signing_active()) {
2496 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2499 CHECK_FSP(fsp,conn);
2500 CHECK_WRITE(fsp);
2502 tcount = IVAL(inbuf,smb_vwv1);
2503 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2504 write_through = BITSETW(inbuf+smb_vwv7,0);
2506 /* We have to deal with slightly different formats depending
2507 on whether we are using the core+ or lanman1.0 protocol */
2509 if(Protocol <= PROTOCOL_COREPLUS) {
2510 numtowrite = SVAL(smb_buf(inbuf),-2);
2511 data = smb_buf(inbuf);
2512 } else {
2513 numtowrite = SVAL(inbuf,smb_vwv10);
2514 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2517 /* force the error type */
2518 SCVAL(inbuf,smb_com,SMBwritec);
2519 SCVAL(outbuf,smb_com,SMBwritec);
2521 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2522 END_PROFILE(SMBwritebraw);
2523 return(ERROR_DOS(ERRDOS,ERRlock));
2526 if (numtowrite>0)
2527 nwritten = write_file(fsp,data,startpos,numtowrite);
2529 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2530 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2532 if (nwritten < (ssize_t)numtowrite) {
2533 END_PROFILE(SMBwritebraw);
2534 return(UNIXERROR(ERRHRD,ERRdiskfull));
2537 total_written = nwritten;
2539 /* Return a message to the redirector to tell it to send more bytes */
2540 SCVAL(outbuf,smb_com,SMBwritebraw);
2541 SSVALS(outbuf,smb_vwv0,-1);
2542 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2543 if (!send_smb(smbd_server_fd(),outbuf))
2544 exit_server("reply_writebraw: send_smb failed.");
2546 /* Now read the raw data into the buffer and write it */
2547 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2548 exit_server("secondary writebraw failed");
2551 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2552 numtowrite = smb_len(inbuf);
2554 /* Set up outbuf to return the correct return */
2555 outsize = set_message(outbuf,1,0,True);
2556 SCVAL(outbuf,smb_com,SMBwritec);
2557 SSVAL(outbuf,smb_vwv0,total_written);
2559 if (numtowrite != 0) {
2561 if (numtowrite > BUFFER_SIZE) {
2562 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2563 (unsigned int)numtowrite ));
2564 exit_server("secondary writebraw failed");
2567 if (tcount > nwritten+numtowrite) {
2568 DEBUG(3,("Client overestimated the write %d %d %d\n",
2569 (int)tcount,(int)nwritten,(int)numtowrite));
2572 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2573 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2574 strerror(errno) ));
2575 exit_server("secondary writebraw failed");
2578 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2580 if (nwritten < (ssize_t)numtowrite) {
2581 SCVAL(outbuf,smb_rcls,ERRHRD);
2582 SSVAL(outbuf,smb_err,ERRdiskfull);
2585 if (nwritten > 0)
2586 total_written += nwritten;
2589 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2590 sync_file(conn,fsp);
2592 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2593 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2595 /* we won't return a status if write through is not selected - this follows what WfWg does */
2596 END_PROFILE(SMBwritebraw);
2597 if (!write_through && total_written==tcount) {
2599 #if RABBIT_PELLET_FIX
2601 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2602 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2604 if (!send_keepalive(smbd_server_fd()))
2605 exit_server("reply_writebraw: send of keepalive failed");
2606 #endif
2607 return(-1);
2610 return(outsize);
2613 /****************************************************************************
2614 Reply to a writeunlock (core+).
2615 ****************************************************************************/
2617 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2618 int size, int dum_buffsize)
2620 ssize_t nwritten = -1;
2621 size_t numtowrite;
2622 SMB_OFF_T startpos;
2623 char *data;
2624 NTSTATUS status = NT_STATUS_OK;
2625 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2626 int outsize = 0;
2627 START_PROFILE(SMBwriteunlock);
2629 CHECK_FSP(fsp,conn);
2630 CHECK_WRITE(fsp);
2632 numtowrite = SVAL(inbuf,smb_vwv1);
2633 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2634 data = smb_buf(inbuf) + 3;
2636 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2637 END_PROFILE(SMBwriteunlock);
2638 return ERROR_DOS(ERRDOS,ERRlock);
2641 /* The special X/Open SMB protocol handling of
2642 zero length writes is *NOT* done for
2643 this call */
2644 if(numtowrite == 0)
2645 nwritten = 0;
2646 else
2647 nwritten = write_file(fsp,data,startpos,numtowrite);
2649 if (lp_syncalways(SNUM(conn)))
2650 sync_file(conn,fsp);
2652 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2653 END_PROFILE(SMBwriteunlock);
2654 return(UNIXERROR(ERRHRD,ERRdiskfull));
2657 if (numtowrite) {
2658 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2659 (SMB_BIG_UINT)startpos);
2660 if (NT_STATUS_V(status)) {
2661 END_PROFILE(SMBwriteunlock);
2662 return ERROR_NT(status);
2666 outsize = set_message(outbuf,1,0,True);
2668 SSVAL(outbuf,smb_vwv0,nwritten);
2670 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2671 fsp->fnum, (int)numtowrite, (int)nwritten));
2673 END_PROFILE(SMBwriteunlock);
2674 return outsize;
2677 /****************************************************************************
2678 Reply to a write.
2679 ****************************************************************************/
2681 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2683 size_t numtowrite;
2684 ssize_t nwritten = -1;
2685 SMB_OFF_T startpos;
2686 char *data;
2687 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2688 int outsize = 0;
2689 START_PROFILE(SMBwrite);
2691 /* If it's an IPC, pass off the pipe handler. */
2692 if (IS_IPC(conn)) {
2693 END_PROFILE(SMBwrite);
2694 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2697 CHECK_FSP(fsp,conn);
2698 CHECK_WRITE(fsp);
2700 numtowrite = SVAL(inbuf,smb_vwv1);
2701 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2702 data = smb_buf(inbuf) + 3;
2704 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2705 END_PROFILE(SMBwrite);
2706 return ERROR_DOS(ERRDOS,ERRlock);
2710 * X/Open SMB protocol says that if smb_vwv1 is
2711 * zero then the file size should be extended or
2712 * truncated to the size given in smb_vwv[2-3].
2715 if(numtowrite == 0) {
2717 * This is actually an allocate call, and set EOF. JRA.
2719 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2720 if (nwritten < 0) {
2721 END_PROFILE(SMBwrite);
2722 return ERROR_NT(NT_STATUS_DISK_FULL);
2724 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2725 if (nwritten < 0) {
2726 END_PROFILE(SMBwrite);
2727 return ERROR_NT(NT_STATUS_DISK_FULL);
2729 } else
2730 nwritten = write_file(fsp,data,startpos,numtowrite);
2732 if (lp_syncalways(SNUM(conn)))
2733 sync_file(conn,fsp);
2735 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2736 END_PROFILE(SMBwrite);
2737 return(UNIXERROR(ERRHRD,ERRdiskfull));
2740 outsize = set_message(outbuf,1,0,True);
2742 SSVAL(outbuf,smb_vwv0,nwritten);
2744 if (nwritten < (ssize_t)numtowrite) {
2745 SCVAL(outbuf,smb_rcls,ERRHRD);
2746 SSVAL(outbuf,smb_err,ERRdiskfull);
2749 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2751 END_PROFILE(SMBwrite);
2752 return(outsize);
2755 /****************************************************************************
2756 Reply to a write and X.
2757 ****************************************************************************/
2759 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2761 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2762 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2763 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2764 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2765 ssize_t nwritten = -1;
2766 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2767 unsigned int smblen = smb_len(inbuf);
2768 char *data;
2769 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2770 START_PROFILE(SMBwriteX);
2772 /* If it's an IPC, pass off the pipe handler. */
2773 if (IS_IPC(conn)) {
2774 END_PROFILE(SMBwriteX);
2775 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2778 CHECK_FSP(fsp,conn);
2779 CHECK_WRITE(fsp);
2781 /* Deal with possible LARGE_WRITEX */
2782 if (large_writeX)
2783 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2785 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2786 END_PROFILE(SMBwriteX);
2787 return ERROR_DOS(ERRDOS,ERRbadmem);
2790 data = smb_base(inbuf) + smb_doff;
2792 if(CVAL(inbuf,smb_wct) == 14) {
2793 #ifdef LARGE_SMB_OFF_T
2795 * This is a large offset (64 bit) write.
2797 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2799 #else /* !LARGE_SMB_OFF_T */
2802 * Ensure we haven't been sent a >32 bit offset.
2805 if(IVAL(inbuf,smb_vwv12) != 0) {
2806 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2807 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2808 END_PROFILE(SMBwriteX);
2809 return ERROR_DOS(ERRDOS,ERRbadaccess);
2812 #endif /* LARGE_SMB_OFF_T */
2815 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2816 END_PROFILE(SMBwriteX);
2817 return ERROR_DOS(ERRDOS,ERRlock);
2820 /* X/Open SMB protocol says that, unlike SMBwrite
2821 if the length is zero then NO truncation is
2822 done, just a write of zero. To truncate a file,
2823 use SMBwrite. */
2825 if(numtowrite == 0)
2826 nwritten = 0;
2827 else
2828 nwritten = write_file(fsp,data,startpos,numtowrite);
2830 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2831 END_PROFILE(SMBwriteX);
2832 return(UNIXERROR(ERRHRD,ERRdiskfull));
2835 set_message(outbuf,6,0,True);
2837 SSVAL(outbuf,smb_vwv2,nwritten);
2838 if (large_writeX)
2839 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2841 if (nwritten < (ssize_t)numtowrite) {
2842 SCVAL(outbuf,smb_rcls,ERRHRD);
2843 SSVAL(outbuf,smb_err,ERRdiskfull);
2846 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2847 fsp->fnum, (int)numtowrite, (int)nwritten));
2849 if (lp_syncalways(SNUM(conn)) || write_through)
2850 sync_file(conn,fsp);
2852 END_PROFILE(SMBwriteX);
2853 return chain_reply(inbuf,outbuf,length,bufsize);
2856 /****************************************************************************
2857 Reply to a lseek.
2858 ****************************************************************************/
2860 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2862 SMB_OFF_T startpos;
2863 SMB_OFF_T res= -1;
2864 int mode,umode;
2865 int outsize = 0;
2866 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2867 START_PROFILE(SMBlseek);
2869 CHECK_FSP(fsp,conn);
2871 flush_write_cache(fsp, SEEK_FLUSH);
2873 mode = SVAL(inbuf,smb_vwv1) & 3;
2874 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2875 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2877 switch (mode) {
2878 case 0:
2879 umode = SEEK_SET;
2880 res = startpos;
2881 break;
2882 case 1:
2883 umode = SEEK_CUR;
2884 res = fsp->pos + startpos;
2885 break;
2886 case 2:
2887 umode = SEEK_END;
2888 break;
2889 default:
2890 umode = SEEK_SET;
2891 res = startpos;
2892 break;
2895 if (umode == SEEK_END) {
2896 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2897 if(errno == EINVAL) {
2898 SMB_OFF_T current_pos = startpos;
2899 SMB_STRUCT_STAT sbuf;
2901 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2902 END_PROFILE(SMBlseek);
2903 return(UNIXERROR(ERRDOS,ERRnoaccess));
2906 current_pos += sbuf.st_size;
2907 if(current_pos < 0)
2908 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2912 if(res == -1) {
2913 END_PROFILE(SMBlseek);
2914 return(UNIXERROR(ERRDOS,ERRnoaccess));
2918 fsp->pos = res;
2920 outsize = set_message(outbuf,2,0,True);
2921 SIVAL(outbuf,smb_vwv0,res);
2923 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2924 fsp->fnum, (double)startpos, (double)res, mode));
2926 END_PROFILE(SMBlseek);
2927 return(outsize);
2930 /****************************************************************************
2931 Reply to a flush.
2932 ****************************************************************************/
2934 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2936 int outsize = set_message(outbuf,0,0,True);
2937 uint16 fnum = SVAL(inbuf,smb_vwv0);
2938 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2939 START_PROFILE(SMBflush);
2941 if (fnum != 0xFFFF)
2942 CHECK_FSP(fsp,conn);
2944 if (!fsp) {
2945 file_sync_all(conn);
2946 } else {
2947 sync_file(conn,fsp);
2950 DEBUG(3,("flush\n"));
2951 END_PROFILE(SMBflush);
2952 return(outsize);
2955 /****************************************************************************
2956 Reply to a exit.
2957 ****************************************************************************/
2959 int reply_exit(connection_struct *conn,
2960 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2962 int outsize;
2963 START_PROFILE(SMBexit);
2965 file_close_pid(SVAL(inbuf,smb_pid));
2967 outsize = set_message(outbuf,0,0,True);
2969 DEBUG(3,("exit\n"));
2971 END_PROFILE(SMBexit);
2972 return(outsize);
2975 /****************************************************************************
2976 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2977 ****************************************************************************/
2979 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2980 int dum_buffsize)
2982 int outsize = 0;
2983 time_t mtime;
2984 int32 eclass = 0, err = 0;
2985 files_struct *fsp = NULL;
2986 START_PROFILE(SMBclose);
2988 outsize = set_message(outbuf,0,0,True);
2990 /* If it's an IPC, pass off to the pipe handler. */
2991 if (IS_IPC(conn)) {
2992 END_PROFILE(SMBclose);
2993 return reply_pipe_close(conn, inbuf,outbuf);
2996 fsp = file_fsp(inbuf,smb_vwv0);
2999 * We can only use CHECK_FSP if we know it's not a directory.
3002 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3003 END_PROFILE(SMBclose);
3004 return ERROR_DOS(ERRDOS,ERRbadfid);
3007 if(fsp->is_directory) {
3009 * Special case - close NT SMB directory handle.
3011 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
3012 close_file(fsp,True);
3013 } else {
3015 * Close ordinary file.
3017 int close_err;
3018 pstring file_name;
3020 /* Save the name for time set in close. */
3021 pstrcpy( file_name, fsp->fsp_name);
3023 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3024 fsp->fd, fsp->fnum,
3025 conn->num_files_open));
3028 * Take care of any time sent in the close.
3031 mtime = make_unix_date3(inbuf+smb_vwv1);
3032 fsp_set_pending_modtime(fsp, mtime);
3035 * close_file() returns the unix errno if an error
3036 * was detected on close - normally this is due to
3037 * a disk full error. If not then it was probably an I/O error.
3040 if((close_err = close_file(fsp,True)) != 0) {
3041 errno = close_err;
3042 END_PROFILE(SMBclose);
3043 return (UNIXERROR(ERRHRD,ERRgeneral));
3047 /* We have a cached error */
3048 if(eclass || err) {
3049 END_PROFILE(SMBclose);
3050 return ERROR_DOS(eclass,err);
3053 END_PROFILE(SMBclose);
3054 return(outsize);
3057 /****************************************************************************
3058 Reply to a writeclose (Core+ protocol).
3059 ****************************************************************************/
3061 int reply_writeclose(connection_struct *conn,
3062 char *inbuf,char *outbuf, int size, int dum_buffsize)
3064 size_t numtowrite;
3065 ssize_t nwritten = -1;
3066 int outsize = 0;
3067 int close_err = 0;
3068 SMB_OFF_T startpos;
3069 char *data;
3070 time_t mtime;
3071 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3072 START_PROFILE(SMBwriteclose);
3074 CHECK_FSP(fsp,conn);
3075 CHECK_WRITE(fsp);
3077 numtowrite = SVAL(inbuf,smb_vwv1);
3078 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3079 mtime = make_unix_date3(inbuf+smb_vwv4);
3080 data = smb_buf(inbuf) + 1;
3082 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3083 END_PROFILE(SMBwriteclose);
3084 return ERROR_DOS(ERRDOS,ERRlock);
3087 nwritten = write_file(fsp,data,startpos,numtowrite);
3089 set_filetime(conn, fsp->fsp_name,mtime);
3092 * More insanity. W2K only closes the file if writelen > 0.
3093 * JRA.
3096 if (numtowrite) {
3097 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3098 fsp->fsp_name ));
3099 close_err = close_file(fsp,True);
3102 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3103 fsp->fnum, (int)numtowrite, (int)nwritten,
3104 conn->num_files_open));
3106 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3107 END_PROFILE(SMBwriteclose);
3108 return(UNIXERROR(ERRHRD,ERRdiskfull));
3111 if(close_err != 0) {
3112 errno = close_err;
3113 END_PROFILE(SMBwriteclose);
3114 return(UNIXERROR(ERRHRD,ERRgeneral));
3117 outsize = set_message(outbuf,1,0,True);
3119 SSVAL(outbuf,smb_vwv0,nwritten);
3120 END_PROFILE(SMBwriteclose);
3121 return(outsize);
3124 /****************************************************************************
3125 Reply to a lock.
3126 ****************************************************************************/
3128 int reply_lock(connection_struct *conn,
3129 char *inbuf,char *outbuf, int length, int dum_buffsize)
3131 int outsize = set_message(outbuf,0,0,True);
3132 SMB_BIG_UINT count,offset;
3133 NTSTATUS status;
3134 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3135 BOOL my_lock_ctx = False;
3137 START_PROFILE(SMBlock);
3139 CHECK_FSP(fsp,conn);
3141 release_level_2_oplocks_on_change(fsp);
3143 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3144 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3146 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3147 fsp->fd, fsp->fnum, (double)offset, (double)count));
3149 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3150 if (NT_STATUS_V(status)) {
3151 #if 0
3152 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3153 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3155 * A blocking lock was requested. Package up
3156 * this smb into a queued request and push it
3157 * onto the blocking lock queue.
3159 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3160 END_PROFILE(SMBlock);
3161 return -1;
3164 #endif
3165 END_PROFILE(SMBlock);
3166 return ERROR_NT(status);
3169 END_PROFILE(SMBlock);
3170 return(outsize);
3173 /****************************************************************************
3174 Reply to a unlock.
3175 ****************************************************************************/
3177 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3178 int dum_buffsize)
3180 int outsize = set_message(outbuf,0,0,True);
3181 SMB_BIG_UINT count,offset;
3182 NTSTATUS status;
3183 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3184 START_PROFILE(SMBunlock);
3186 CHECK_FSP(fsp,conn);
3188 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3189 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3191 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3192 if (NT_STATUS_V(status)) {
3193 END_PROFILE(SMBunlock);
3194 return ERROR_NT(status);
3197 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3198 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3200 END_PROFILE(SMBunlock);
3201 return(outsize);
3204 /****************************************************************************
3205 Reply to a tdis.
3206 ****************************************************************************/
3208 int reply_tdis(connection_struct *conn,
3209 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3211 int outsize = set_message(outbuf,0,0,True);
3212 uint16 vuid;
3213 START_PROFILE(SMBtdis);
3215 vuid = SVAL(inbuf,smb_uid);
3217 if (!conn) {
3218 DEBUG(4,("Invalid connection in tdis\n"));
3219 END_PROFILE(SMBtdis);
3220 return ERROR_DOS(ERRSRV,ERRinvnid);
3223 conn->used = False;
3225 close_cnum(conn,vuid);
3227 END_PROFILE(SMBtdis);
3228 return outsize;
3231 /****************************************************************************
3232 Reply to a echo.
3233 ****************************************************************************/
3235 int reply_echo(connection_struct *conn,
3236 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3238 int smb_reverb = SVAL(inbuf,smb_vwv0);
3239 int seq_num;
3240 unsigned int data_len = smb_buflen(inbuf);
3241 int outsize = set_message(outbuf,1,data_len,True);
3242 START_PROFILE(SMBecho);
3244 if (data_len > BUFFER_SIZE) {
3245 DEBUG(0,("reply_echo: data_len too large.\n"));
3246 END_PROFILE(SMBecho);
3247 return -1;
3250 /* copy any incoming data back out */
3251 if (data_len > 0)
3252 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3254 if (smb_reverb > 100) {
3255 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3256 smb_reverb = 100;
3259 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3260 SSVAL(outbuf,smb_vwv0,seq_num);
3262 smb_setlen(outbuf,outsize - 4);
3264 if (!send_smb(smbd_server_fd(),outbuf))
3265 exit_server("reply_echo: send_smb failed.");
3268 DEBUG(3,("echo %d times\n", smb_reverb));
3270 smb_echo_count++;
3272 END_PROFILE(SMBecho);
3273 return -1;
3276 /****************************************************************************
3277 Reply to a printopen.
3278 ****************************************************************************/
3280 int reply_printopen(connection_struct *conn,
3281 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3283 int outsize = 0;
3284 files_struct *fsp;
3285 START_PROFILE(SMBsplopen);
3287 if (!CAN_PRINT(conn)) {
3288 END_PROFILE(SMBsplopen);
3289 return ERROR_DOS(ERRDOS,ERRnoaccess);
3292 /* Open for exclusive use, write only. */
3293 fsp = print_fsp_open(conn, NULL);
3295 if (!fsp) {
3296 END_PROFILE(SMBsplopen);
3297 return(UNIXERROR(ERRDOS,ERRnoaccess));
3300 outsize = set_message(outbuf,1,0,True);
3301 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3303 DEBUG(3,("openprint fd=%d fnum=%d\n",
3304 fsp->fd, fsp->fnum));
3306 END_PROFILE(SMBsplopen);
3307 return(outsize);
3310 /****************************************************************************
3311 Reply to a printclose.
3312 ****************************************************************************/
3314 int reply_printclose(connection_struct *conn,
3315 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3317 int outsize = set_message(outbuf,0,0,True);
3318 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3319 int close_err = 0;
3320 START_PROFILE(SMBsplclose);
3322 CHECK_FSP(fsp,conn);
3324 if (!CAN_PRINT(conn)) {
3325 END_PROFILE(SMBsplclose);
3326 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3329 DEBUG(3,("printclose fd=%d fnum=%d\n",
3330 fsp->fd,fsp->fnum));
3332 close_err = close_file(fsp,True);
3334 if(close_err != 0) {
3335 errno = close_err;
3336 END_PROFILE(SMBsplclose);
3337 return(UNIXERROR(ERRHRD,ERRgeneral));
3340 END_PROFILE(SMBsplclose);
3341 return(outsize);
3344 /****************************************************************************
3345 Reply to a printqueue.
3346 ****************************************************************************/
3348 int reply_printqueue(connection_struct *conn,
3349 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3351 int outsize = set_message(outbuf,2,3,True);
3352 int max_count = SVAL(inbuf,smb_vwv0);
3353 int start_index = SVAL(inbuf,smb_vwv1);
3354 START_PROFILE(SMBsplretq);
3356 /* we used to allow the client to get the cnum wrong, but that
3357 is really quite gross and only worked when there was only
3358 one printer - I think we should now only accept it if they
3359 get it right (tridge) */
3360 if (!CAN_PRINT(conn)) {
3361 END_PROFILE(SMBsplretq);
3362 return ERROR_DOS(ERRDOS,ERRnoaccess);
3365 SSVAL(outbuf,smb_vwv0,0);
3366 SSVAL(outbuf,smb_vwv1,0);
3367 SCVAL(smb_buf(outbuf),0,1);
3368 SSVAL(smb_buf(outbuf),1,0);
3370 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3371 start_index, max_count));
3374 print_queue_struct *queue = NULL;
3375 print_status_struct status;
3376 char *p = smb_buf(outbuf) + 3;
3377 int count = print_queue_status(SNUM(conn), &queue, &status);
3378 int num_to_get = ABS(max_count);
3379 int first = (max_count>0?start_index:start_index+max_count+1);
3380 int i;
3382 if (first >= count)
3383 num_to_get = 0;
3384 else
3385 num_to_get = MIN(num_to_get,count-first);
3388 for (i=first;i<first+num_to_get;i++) {
3389 put_dos_date2(p,0,queue[i].time);
3390 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3391 SSVAL(p,5, queue[i].job);
3392 SIVAL(p,7,queue[i].size);
3393 SCVAL(p,11,0);
3394 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3395 p += 28;
3398 if (count > 0) {
3399 outsize = set_message(outbuf,2,28*count+3,False);
3400 SSVAL(outbuf,smb_vwv0,count);
3401 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3402 SCVAL(smb_buf(outbuf),0,1);
3403 SSVAL(smb_buf(outbuf),1,28*count);
3406 SAFE_FREE(queue);
3408 DEBUG(3,("%d entries returned in queue\n",count));
3411 END_PROFILE(SMBsplretq);
3412 return(outsize);
3415 /****************************************************************************
3416 Reply to a printwrite.
3417 ****************************************************************************/
3419 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3421 int numtowrite;
3422 int outsize = set_message(outbuf,0,0,True);
3423 char *data;
3424 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3426 START_PROFILE(SMBsplwr);
3428 if (!CAN_PRINT(conn)) {
3429 END_PROFILE(SMBsplwr);
3430 return ERROR_DOS(ERRDOS,ERRnoaccess);
3433 CHECK_FSP(fsp,conn);
3434 CHECK_WRITE(fsp);
3436 numtowrite = SVAL(smb_buf(inbuf),1);
3437 data = smb_buf(inbuf) + 3;
3439 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3440 END_PROFILE(SMBsplwr);
3441 return(UNIXERROR(ERRHRD,ERRdiskfull));
3444 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3446 END_PROFILE(SMBsplwr);
3447 return(outsize);
3450 /****************************************************************************
3451 The guts of the mkdir command, split out so it may be called by the NT SMB
3452 code.
3453 ****************************************************************************/
3455 NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
3457 int ret= -1;
3459 if(!CAN_WRITE(conn)) {
3460 DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
3461 errno = EACCES;
3462 return map_nt_error_from_unix(errno);
3465 if (bad_path) {
3466 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3469 if (!check_name(directory, conn)) {
3470 if(errno == ENOENT) {
3471 if (bad_path) {
3472 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3473 } else {
3474 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3477 return map_nt_error_from_unix(errno);
3480 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3481 if (ret == -1) {
3482 if(errno == ENOENT) {
3483 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3485 return map_nt_error_from_unix(errno);
3488 return NT_STATUS_OK;
3491 /****************************************************************************
3492 Reply to a mkdir.
3493 ****************************************************************************/
3495 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3497 pstring directory;
3498 int outsize;
3499 NTSTATUS status;
3500 BOOL bad_path = False;
3501 SMB_STRUCT_STAT sbuf;
3503 START_PROFILE(SMBmkdir);
3505 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3506 if (!NT_STATUS_IS_OK(status)) {
3507 END_PROFILE(SMBmkdir);
3508 return ERROR_NT(status);
3511 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3513 unix_convert(directory,conn,0,&bad_path,&sbuf);
3515 if( strchr_m(directory, ':')) {
3516 DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
3517 END_PROFILE(SMBmkdir);
3518 return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
3521 status = mkdir_internal(conn, directory,bad_path);
3522 if (!NT_STATUS_IS_OK(status)) {
3523 END_PROFILE(SMBmkdir);
3524 return ERROR_NT(status);
3527 if (lp_inherit_owner(SNUM(conn))) {
3528 /* Ensure we're checking for a symlink here.... */
3529 /* We don't want to get caught by a symlink racer. */
3531 if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
3532 END_PROFILE(SMBmkdir);
3533 return(UNIXERROR(ERRDOS,ERRnoaccess));
3536 if(!S_ISDIR(sbuf.st_mode)) {
3537 DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
3538 END_PROFILE(SMBmkdir);
3539 return(UNIXERROR(ERRDOS,ERRnoaccess));
3542 change_owner_to_parent(conn, NULL, directory, &sbuf);
3545 outsize = set_message(outbuf,0,0,True);
3547 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3549 END_PROFILE(SMBmkdir);
3550 return(outsize);
3553 /****************************************************************************
3554 Static function used by reply_rmdir to delete an entire directory
3555 tree recursively. Return False on ok, True on fail.
3556 ****************************************************************************/
3558 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3560 const char *dname = NULL;
3561 BOOL ret = False;
3562 long offset = 0;
3563 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3565 if(dir_hnd == NULL)
3566 return True;
3568 while((dname = ReadDirName(dir_hnd, &offset))) {
3569 pstring fullname;
3570 SMB_STRUCT_STAT st;
3572 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3573 continue;
3575 if (!is_visible_file(conn, directory, dname, &st, False))
3576 continue;
3578 /* Construct the full name. */
3579 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3580 errno = ENOMEM;
3581 ret = True;
3582 break;
3585 pstrcpy(fullname, directory);
3586 pstrcat(fullname, "/");
3587 pstrcat(fullname, dname);
3589 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3590 ret = True;
3591 break;
3594 if(st.st_mode & S_IFDIR) {
3595 if(recursive_rmdir(conn, fullname)!=0) {
3596 ret = True;
3597 break;
3599 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3600 ret = True;
3601 break;
3603 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3604 ret = True;
3605 break;
3608 CloseDir(dir_hnd);
3609 return ret;
3612 /****************************************************************************
3613 The internals of the rmdir code - called elsewhere.
3614 ****************************************************************************/
3616 BOOL rmdir_internals(connection_struct *conn, char *directory)
3618 BOOL ok;
3619 SMB_STRUCT_STAT st;
3621 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3622 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3624 * Check to see if the only thing in this directory are
3625 * vetoed files/directories. If so then delete them and
3626 * retry. If we fail to delete any of them (and we *don't*
3627 * do a recursive delete) then fail the rmdir.
3629 BOOL all_veto_files = True;
3630 const char *dname;
3631 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3633 if(dir_hnd != NULL) {
3634 long dirpos = TellDir(dir_hnd);
3635 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3636 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3637 continue;
3638 if (!is_visible_file(conn, directory, dname, &st, False))
3639 continue;
3640 if(!IS_VETO_PATH(conn, dname)) {
3641 all_veto_files = False;
3642 break;
3646 if(all_veto_files) {
3647 SeekDir(dir_hnd,dirpos);
3648 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3649 pstring fullname;
3651 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3652 continue;
3653 if (!is_visible_file(conn, directory, dname, &st, False))
3654 continue;
3656 /* Construct the full name. */
3657 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3658 errno = ENOMEM;
3659 break;
3662 pstrcpy(fullname, directory);
3663 pstrcat(fullname, "/");
3664 pstrcat(fullname, dname);
3666 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3667 break;
3668 if(st.st_mode & S_IFDIR) {
3669 if(lp_recursive_veto_delete(SNUM(conn))) {
3670 if(recursive_rmdir(conn, fullname) != 0)
3671 break;
3673 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3674 break;
3675 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3676 break;
3678 CloseDir(dir_hnd);
3679 /* Retry the rmdir */
3680 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3681 } else {
3682 CloseDir(dir_hnd);
3684 } else {
3685 errno = ENOTEMPTY;
3689 if (!ok)
3690 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3692 return ok;
3695 /****************************************************************************
3696 Reply to a rmdir.
3697 ****************************************************************************/
3699 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3701 pstring directory;
3702 int outsize = 0;
3703 BOOL ok = False;
3704 BOOL bad_path = False;
3705 SMB_STRUCT_STAT sbuf;
3706 NTSTATUS status;
3707 START_PROFILE(SMBrmdir);
3709 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3710 if (!NT_STATUS_IS_OK(status)) {
3711 END_PROFILE(SMBrmdir);
3712 return ERROR_NT(status);
3715 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3717 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3718 if (bad_path) {
3719 END_PROFILE(SMBrmdir);
3720 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3723 if (check_name(directory,conn)) {
3724 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3725 ok = rmdir_internals(conn, directory);
3728 if (!ok) {
3729 END_PROFILE(SMBrmdir);
3730 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3733 outsize = set_message(outbuf,0,0,True);
3735 DEBUG( 3, ( "rmdir %s\n", directory ) );
3737 END_PROFILE(SMBrmdir);
3738 return(outsize);
3741 /*******************************************************************
3742 Resolve wildcards in a filename rename.
3743 Note that name is in UNIX charset and thus potentially can be more
3744 than fstring buffer (255 bytes) especially in default UTF-8 case.
3745 Therefore, we use pstring inside and all calls should ensure that
3746 name2 is at least pstring-long (they do already)
3747 ********************************************************************/
3749 static BOOL resolve_wildcards(const char *name1, char *name2)
3751 pstring root1,root2;
3752 pstring ext1,ext2;
3753 char *p,*p2, *pname1, *pname2;
3754 int available_space, actual_space;
3757 pname1 = strrchr_m(name1,'/');
3758 pname2 = strrchr_m(name2,'/');
3760 if (!pname1 || !pname2)
3761 return(False);
3763 pstrcpy(root1,pname1);
3764 pstrcpy(root2,pname2);
3765 p = strrchr_m(root1,'.');
3766 if (p) {
3767 *p = 0;
3768 pstrcpy(ext1,p+1);
3769 } else {
3770 pstrcpy(ext1,"");
3772 p = strrchr_m(root2,'.');
3773 if (p) {
3774 *p = 0;
3775 pstrcpy(ext2,p+1);
3776 } else {
3777 pstrcpy(ext2,"");
3780 p = root1;
3781 p2 = root2;
3782 while (*p2) {
3783 if (*p2 == '?') {
3784 *p2 = *p;
3785 p2++;
3786 } else if (*p2 == '*') {
3787 pstrcpy(p2, p);
3788 break;
3789 } else {
3790 p2++;
3792 if (*p)
3793 p++;
3796 p = ext1;
3797 p2 = ext2;
3798 while (*p2) {
3799 if (*p2 == '?') {
3800 *p2 = *p;
3801 p2++;
3802 } else if (*p2 == '*') {
3803 pstrcpy(p2, p);
3804 break;
3805 } else {
3806 p2++;
3808 if (*p)
3809 p++;
3812 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3814 if (ext2[0]) {
3815 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3816 if (actual_space >= available_space - 1) {
3817 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3818 actual_space - available_space));
3820 } else {
3821 pstrcpy_base(pname2, root2, name2);
3824 return(True);
3827 /****************************************************************************
3828 Ensure open files have their names updates.
3829 ****************************************************************************/
3831 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3833 files_struct *fsp;
3834 BOOL did_rename = False;
3836 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3837 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3838 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3839 fsp->fsp_name, newname ));
3840 string_set(&fsp->fsp_name, newname);
3841 did_rename = True;
3844 if (!did_rename)
3845 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3846 (unsigned int)dev, (double)inode, newname ));
3849 /****************************************************************************
3850 Rename an open file - given an fsp.
3851 ****************************************************************************/
3853 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3855 SMB_STRUCT_STAT sbuf;
3856 BOOL bad_path = False;
3857 pstring newname_last_component;
3858 NTSTATUS error = NT_STATUS_OK;
3859 BOOL dest_exists;
3860 BOOL rcdest = True;
3862 ZERO_STRUCT(sbuf);
3863 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3865 /* Quick check for "." and ".." */
3866 if (!bad_path && newname_last_component[0] == '.') {
3867 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3868 return NT_STATUS_ACCESS_DENIED;
3871 if (!rcdest && bad_path) {
3872 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3875 /* Ensure newname contains a '/' */
3876 if(strrchr_m(newname,'/') == 0) {
3877 pstring tmpstr;
3879 pstrcpy(tmpstr, "./");
3880 pstrcat(tmpstr, newname);
3881 pstrcpy(newname, tmpstr);
3885 * Check for special case with case preserving and not
3886 * case sensitive. If the old last component differs from the original
3887 * last component only by case, then we should allow
3888 * the rename (user is trying to change the case of the
3889 * filename).
3892 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3893 strequal(newname, fsp->fsp_name)) {
3894 char *p;
3895 pstring newname_modified_last_component;
3898 * Get the last component of the modified name.
3899 * Note that we guarantee that newname contains a '/'
3900 * character above.
3902 p = strrchr_m(newname,'/');
3903 pstrcpy(newname_modified_last_component,p+1);
3905 if(strcsequal(newname_modified_last_component,
3906 newname_last_component) == False) {
3908 * Replace the modified last component with
3909 * the original.
3911 pstrcpy(p+1, newname_last_component);
3916 * If the src and dest names are identical - including case,
3917 * don't do the rename, just return success.
3920 if (strcsequal(fsp->fsp_name, newname)) {
3921 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3922 newname));
3923 return NT_STATUS_OK;
3926 dest_exists = vfs_object_exist(conn,newname,NULL);
3928 if(!replace_if_exists && dest_exists) {
3929 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3930 fsp->fsp_name,newname));
3931 return NT_STATUS_OBJECT_NAME_COLLISION;
3934 error = can_rename(conn,newname,attrs,&sbuf);
3936 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3937 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3938 nt_errstr(error), fsp->fsp_name,newname));
3939 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3940 error = NT_STATUS_ACCESS_DENIED;
3941 return error;
3944 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3945 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3946 fsp->fsp_name,newname));
3947 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3948 return NT_STATUS_OK;
3951 if (errno == ENOTDIR || errno == EISDIR)
3952 error = NT_STATUS_OBJECT_NAME_COLLISION;
3953 else
3954 error = map_nt_error_from_unix(errno);
3956 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3957 nt_errstr(error), fsp->fsp_name,newname));
3959 return error;
3962 /****************************************************************************
3963 The guts of the rename command, split out so it may be called by the NT SMB
3964 code.
3965 ****************************************************************************/
3967 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3969 pstring directory;
3970 pstring mask;
3971 pstring last_component_src;
3972 pstring last_component_dest;
3973 char *p;
3974 BOOL has_wild;
3975 BOOL bad_path_src = False;
3976 BOOL bad_path_dest = False;
3977 int count=0;
3978 NTSTATUS error = NT_STATUS_OK;
3979 BOOL rc = True;
3980 BOOL rcdest = True;
3981 SMB_STRUCT_STAT sbuf1, sbuf2;
3983 *directory = *mask = 0;
3985 ZERO_STRUCT(sbuf1);
3986 ZERO_STRUCT(sbuf2);
3988 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3989 if (!rc && bad_path_src) {
3990 if (ms_has_wild(last_component_src))
3991 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3992 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3995 /* Quick check for "." and ".." */
3996 if (last_component_src[0] == '.') {
3997 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3998 return NT_STATUS_OBJECT_NAME_INVALID;
4002 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
4004 /* Quick check for "." and ".." */
4005 if (last_component_dest[0] == '.') {
4006 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
4007 return NT_STATUS_OBJECT_NAME_INVALID;
4012 * Split the old name into directory and last component
4013 * strings. Note that unix_convert may have stripped off a
4014 * leading ./ from both name and newname if the rename is
4015 * at the root of the share. We need to make sure either both
4016 * name and newname contain a / character or neither of them do
4017 * as this is checked in resolve_wildcards().
4020 p = strrchr_m(name,'/');
4021 if (!p) {
4022 pstrcpy(directory,".");
4023 pstrcpy(mask,name);
4024 } else {
4025 *p = 0;
4026 pstrcpy(directory,name);
4027 pstrcpy(mask,p+1);
4028 *p = '/'; /* Replace needed for exceptional test below. */
4032 * We should only check the mangled cache
4033 * here if unix_convert failed. This means
4034 * that the path in 'mask' doesn't exist
4035 * on the file system and so we need to look
4036 * for a possible mangle. This patch from
4037 * Tine Smukavec <valentin.smukavec@hermes.si>.
4040 if (!rc && mangle_is_mangled(mask))
4041 mangle_check_cache( mask, sizeof(pstring)-1 );
4043 has_wild = ms_has_wild(mask);
4045 if (!has_wild) {
4047 * No wildcards - just process the one file.
4049 BOOL is_short_name = mangle_is_8_3(name, True);
4051 /* Add a terminating '/' to the directory name. */
4052 pstrcat(directory,"/");
4053 pstrcat(directory,mask);
4055 /* Ensure newname contains a '/' also */
4056 if(strrchr_m(newname,'/') == 0) {
4057 pstring tmpstr;
4059 pstrcpy(tmpstr, "./");
4060 pstrcat(tmpstr, newname);
4061 pstrcpy(newname, tmpstr);
4064 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
4065 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
4066 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
4067 newname, last_component_dest, is_short_name));
4070 * Check for special case with case preserving and not
4071 * case sensitive, if directory and newname are identical,
4072 * and the old last component differs from the original
4073 * last component only by case, then we should allow
4074 * the rename (user is trying to change the case of the
4075 * filename).
4077 if((conn->case_sensitive == False) &&
4078 (((conn->case_preserve == True) &&
4079 (is_short_name == False)) ||
4080 ((conn->short_case_preserve == True) &&
4081 (is_short_name == True))) &&
4082 strcsequal(directory, newname)) {
4083 pstring modified_last_component;
4086 * Get the last component of the modified name.
4087 * Note that we guarantee that newname contains a '/'
4088 * character above.
4090 p = strrchr_m(newname,'/');
4091 pstrcpy(modified_last_component,p+1);
4093 if(strcsequal(modified_last_component,
4094 last_component_dest) == False) {
4096 * Replace the modified last component with
4097 * the original.
4099 pstrcpy(p+1, last_component_dest);
4103 resolve_wildcards(directory,newname);
4106 * The source object must exist.
4109 if (!vfs_object_exist(conn, directory, &sbuf1)) {
4110 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
4111 directory,newname));
4113 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
4115 * Must return different errors depending on whether the parent
4116 * directory existed or not.
4119 p = strrchr_m(directory, '/');
4120 if (!p)
4121 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4122 *p = '\0';
4123 if (vfs_object_exist(conn, directory, NULL))
4124 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4125 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4127 error = map_nt_error_from_unix(errno);
4128 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4129 nt_errstr(error), directory,newname));
4131 return error;
4134 if (!rcdest && bad_path_dest) {
4135 if (ms_has_wild(last_component_dest))
4136 return NT_STATUS_OBJECT_NAME_INVALID;
4137 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4140 error = can_rename(conn,directory,attrs,&sbuf1);
4142 if (!NT_STATUS_IS_OK(error)) {
4143 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4144 nt_errstr(error), directory,newname));
4145 return error;
4149 * If the src and dest names are identical - including case,
4150 * don't do the rename, just return success.
4153 if (strcsequal(directory, newname)) {
4154 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4155 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
4156 return NT_STATUS_OK;
4159 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4160 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
4161 directory,newname));
4162 return NT_STATUS_OBJECT_NAME_COLLISION;
4165 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4166 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
4167 directory,newname));
4168 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4169 return NT_STATUS_OK;
4172 if (errno == ENOTDIR || errno == EISDIR)
4173 error = NT_STATUS_OBJECT_NAME_COLLISION;
4174 else
4175 error = map_nt_error_from_unix(errno);
4177 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4178 nt_errstr(error), directory,newname));
4180 return error;
4181 } else {
4183 * Wildcards - process each file that matches.
4185 struct smb_Dir *dir_hnd = NULL;
4186 const char *dname;
4187 pstring destname;
4189 if (check_name(directory,conn))
4190 dir_hnd = OpenDir(conn, directory);
4192 if (dir_hnd) {
4193 long offset = 0;
4194 error = NT_STATUS_NO_SUCH_FILE;
4195 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4197 if (strequal(mask,"????????.???"))
4198 pstrcpy(mask,"*");
4200 while ((dname = ReadDirName(dir_hnd, &offset))) {
4201 pstring fname;
4202 BOOL sysdir_entry = False;
4204 pstrcpy(fname,dname);
4206 /* Quick check for "." and ".." */
4207 if (fname[0] == '.') {
4208 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4209 if (attrs & aDIR) {
4210 sysdir_entry = True;
4211 } else {
4212 continue;
4217 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4218 continue;
4220 if(!mask_match(fname, mask, conn->case_sensitive))
4221 continue;
4223 if (sysdir_entry) {
4224 error = NT_STATUS_OBJECT_NAME_INVALID;
4225 break;
4228 error = NT_STATUS_ACCESS_DENIED;
4229 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4230 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4231 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4232 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4233 continue;
4235 error = can_rename(conn,fname,attrs,&sbuf1);
4236 if (!NT_STATUS_IS_OK(error)) {
4237 DEBUG(6,("rename %s refused\n", fname));
4238 continue;
4240 pstrcpy(destname,newname);
4242 if (!resolve_wildcards(fname,destname)) {
4243 DEBUG(6,("resolve_wildcards %s %s failed\n",
4244 fname, destname));
4245 continue;
4248 if (strcsequal(fname,destname)) {
4249 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4250 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4251 count++;
4252 error = NT_STATUS_OK;
4253 continue;
4256 if (!replace_if_exists &&
4257 vfs_file_exist(conn,destname, NULL)) {
4258 DEBUG(6,("file_exist %s\n", destname));
4259 error = NT_STATUS_OBJECT_NAME_COLLISION;
4260 continue;
4263 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4264 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4265 count++;
4266 error = NT_STATUS_OK;
4268 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4270 CloseDir(dir_hnd);
4273 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4274 if (!rcdest && bad_path_dest) {
4275 if (ms_has_wild(last_component_dest))
4276 return NT_STATUS_OBJECT_NAME_INVALID;
4277 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4282 if (count == 0 && NT_STATUS_IS_OK(error)) {
4283 error = map_nt_error_from_unix(errno);
4286 return error;
4289 /****************************************************************************
4290 Reply to a mv.
4291 ****************************************************************************/
4293 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4294 int dum_buffsize)
4296 int outsize = 0;
4297 pstring name;
4298 pstring newname;
4299 char *p;
4300 uint16 attrs = SVAL(inbuf,smb_vwv0);
4301 NTSTATUS status;
4303 START_PROFILE(SMBmv);
4305 p = smb_buf(inbuf) + 1;
4306 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4307 if (!NT_STATUS_IS_OK(status)) {
4308 END_PROFILE(SMBmv);
4309 return ERROR_NT(status);
4311 p++;
4312 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4313 if (!NT_STATUS_IS_OK(status)) {
4314 END_PROFILE(SMBmv);
4315 return ERROR_NT(status);
4318 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4319 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4321 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4323 status = rename_internals(conn, name, newname, attrs, False);
4324 if (!NT_STATUS_IS_OK(status)) {
4325 END_PROFILE(SMBmv);
4326 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4327 /* We have re-scheduled this call. */
4328 return -1;
4330 return ERROR_NT(status);
4334 * Win2k needs a changenotify request response before it will
4335 * update after a rename..
4337 process_pending_change_notify_queue((time_t)0);
4338 outsize = set_message(outbuf,0,0,True);
4340 END_PROFILE(SMBmv);
4341 return(outsize);
4344 /*******************************************************************
4345 Copy a file as part of a reply_copy.
4346 ******************************************************************/
4348 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4349 int count,BOOL target_is_directory, int *err_ret)
4351 int Access,action;
4352 SMB_STRUCT_STAT src_sbuf, sbuf2;
4353 SMB_OFF_T ret=-1;
4354 files_struct *fsp1,*fsp2;
4355 pstring dest;
4356 uint32 dosattrs;
4358 *err_ret = 0;
4360 pstrcpy(dest,dest1);
4361 if (target_is_directory) {
4362 char *p = strrchr_m(src,'/');
4363 if (p)
4364 p++;
4365 else
4366 p = src;
4367 pstrcat(dest,"/");
4368 pstrcat(dest,p);
4371 if (!vfs_file_exist(conn,src,&src_sbuf))
4372 return(False);
4374 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4375 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4376 &Access,&action);
4378 if (!fsp1)
4379 return(False);
4381 if (!target_is_directory && count)
4382 ofun = FILE_EXISTS_OPEN;
4384 dosattrs = dos_mode(conn, src, &src_sbuf);
4385 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4386 ZERO_STRUCTP(&sbuf2);
4388 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4389 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4391 if (!fsp2) {
4392 close_file(fsp1,False);
4393 return(False);
4396 if ((ofun&3) == 1) {
4397 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4398 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4400 * Stop the copy from occurring.
4402 ret = -1;
4403 src_sbuf.st_size = 0;
4407 if (src_sbuf.st_size)
4408 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4410 close_file(fsp1,False);
4412 /* Ensure the modtime is set correctly on the destination file. */
4413 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4416 * As we are opening fsp1 read-only we only expect
4417 * an error on close on fsp2 if we are out of space.
4418 * Thus we don't look at the error return from the
4419 * close of fsp1.
4421 *err_ret = close_file(fsp2,False);
4423 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4426 /****************************************************************************
4427 Reply to a file copy.
4428 ****************************************************************************/
4430 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4432 int outsize = 0;
4433 pstring name;
4434 pstring directory;
4435 pstring mask,newname;
4436 char *p;
4437 int count=0;
4438 int error = ERRnoaccess;
4439 int err = 0;
4440 BOOL has_wild;
4441 BOOL exists=False;
4442 int tid2 = SVAL(inbuf,smb_vwv0);
4443 int ofun = SVAL(inbuf,smb_vwv1);
4444 int flags = SVAL(inbuf,smb_vwv2);
4445 BOOL target_is_directory=False;
4446 BOOL bad_path1 = False;
4447 BOOL bad_path2 = False;
4448 BOOL rc = True;
4449 SMB_STRUCT_STAT sbuf1, sbuf2;
4450 NTSTATUS status;
4452 START_PROFILE(SMBcopy);
4454 *directory = *mask = 0;
4456 p = smb_buf(inbuf);
4457 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4458 if (!NT_STATUS_IS_OK(status)) {
4459 END_PROFILE(SMBcopy);
4460 return ERROR_NT(status);
4462 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4463 if (!NT_STATUS_IS_OK(status)) {
4464 END_PROFILE(SMBcopy);
4465 return ERROR_NT(status);
4468 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4470 if (tid2 != conn->cnum) {
4471 /* can't currently handle inter share copies XXXX */
4472 DEBUG(3,("Rejecting inter-share copy\n"));
4473 END_PROFILE(SMBcopy);
4474 return ERROR_DOS(ERRSRV,ERRinvdevice);
4477 RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
4478 RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
4480 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4481 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4483 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4485 if ((flags&1) && target_is_directory) {
4486 END_PROFILE(SMBcopy);
4487 return ERROR_DOS(ERRDOS,ERRbadfile);
4490 if ((flags&2) && !target_is_directory) {
4491 END_PROFILE(SMBcopy);
4492 return ERROR_DOS(ERRDOS,ERRbadpath);
4495 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4496 /* wants a tree copy! XXXX */
4497 DEBUG(3,("Rejecting tree copy\n"));
4498 END_PROFILE(SMBcopy);
4499 return ERROR_DOS(ERRSRV,ERRerror);
4502 p = strrchr_m(name,'/');
4503 if (!p) {
4504 pstrcpy(directory,"./");
4505 pstrcpy(mask,name);
4506 } else {
4507 *p = 0;
4508 pstrcpy(directory,name);
4509 pstrcpy(mask,p+1);
4513 * We should only check the mangled cache
4514 * here if unix_convert failed. This means
4515 * that the path in 'mask' doesn't exist
4516 * on the file system and so we need to look
4517 * for a possible mangle. This patch from
4518 * Tine Smukavec <valentin.smukavec@hermes.si>.
4521 if (!rc && mangle_is_mangled(mask))
4522 mangle_check_cache( mask, sizeof(pstring)-1 );
4524 has_wild = ms_has_wild(mask);
4526 if (!has_wild) {
4527 pstrcat(directory,"/");
4528 pstrcat(directory,mask);
4529 if (resolve_wildcards(directory,newname) &&
4530 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4531 count++;
4532 if(!count && err) {
4533 errno = err;
4534 END_PROFILE(SMBcopy);
4535 return(UNIXERROR(ERRHRD,ERRgeneral));
4537 if (!count) {
4538 exists = vfs_file_exist(conn,directory,NULL);
4540 } else {
4541 struct smb_Dir *dir_hnd = NULL;
4542 const char *dname;
4543 pstring destname;
4545 if (check_name(directory,conn))
4546 dir_hnd = OpenDir(conn, directory);
4548 if (dir_hnd) {
4549 long offset = 0;
4550 error = ERRbadfile;
4552 if (strequal(mask,"????????.???"))
4553 pstrcpy(mask,"*");
4555 while ((dname = ReadDirName(dir_hnd, &offset))) {
4556 pstring fname;
4557 pstrcpy(fname,dname);
4559 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4560 continue;
4562 if(!mask_match(fname, mask, conn->case_sensitive))
4563 continue;
4565 error = ERRnoaccess;
4566 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4567 pstrcpy(destname,newname);
4568 if (resolve_wildcards(fname,destname) &&
4569 copy_file(fname,destname,conn,ofun,
4570 count,target_is_directory,&err))
4571 count++;
4572 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4574 CloseDir(dir_hnd);
4578 if (count == 0) {
4579 if(err) {
4580 /* Error on close... */
4581 errno = err;
4582 END_PROFILE(SMBcopy);
4583 return(UNIXERROR(ERRHRD,ERRgeneral));
4586 if (exists) {
4587 END_PROFILE(SMBcopy);
4588 return ERROR_DOS(ERRDOS,error);
4589 } else {
4590 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4591 set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
4593 END_PROFILE(SMBcopy);
4594 return(UNIXERROR(ERRDOS,error));
4598 outsize = set_message(outbuf,1,0,True);
4599 SSVAL(outbuf,smb_vwv0,count);
4601 END_PROFILE(SMBcopy);
4602 return(outsize);
4605 /****************************************************************************
4606 Reply to a setdir.
4607 ****************************************************************************/
4609 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4611 int snum;
4612 int outsize = 0;
4613 BOOL ok = False;
4614 pstring newdir;
4615 NTSTATUS status;
4617 START_PROFILE(pathworks_setdir);
4619 snum = SNUM(conn);
4620 if (!CAN_SETDIR(snum)) {
4621 END_PROFILE(pathworks_setdir);
4622 return ERROR_DOS(ERRDOS,ERRnoaccess);
4625 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4626 if (!NT_STATUS_IS_OK(status)) {
4627 END_PROFILE(pathworks_setdir);
4628 return ERROR_NT(status);
4631 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4633 if (strlen(newdir) == 0) {
4634 ok = True;
4635 } else {
4636 ok = vfs_directory_exist(conn,newdir,NULL);
4637 if (ok)
4638 string_set(&conn->connectpath,newdir);
4641 if (!ok) {
4642 END_PROFILE(pathworks_setdir);
4643 return ERROR_DOS(ERRDOS,ERRbadpath);
4646 outsize = set_message(outbuf,0,0,True);
4647 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4649 DEBUG(3,("setdir %s\n", newdir));
4651 END_PROFILE(pathworks_setdir);
4652 return(outsize);
4655 /****************************************************************************
4656 Get a lock pid, dealing with large count requests.
4657 ****************************************************************************/
4659 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4661 if(!large_file_format)
4662 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4663 else
4664 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4667 /****************************************************************************
4668 Get a lock count, dealing with large count requests.
4669 ****************************************************************************/
4671 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4673 SMB_BIG_UINT count = 0;
4675 if(!large_file_format) {
4676 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4677 } else {
4679 #if defined(HAVE_LONGLONG)
4680 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4681 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4682 #else /* HAVE_LONGLONG */
4685 * NT4.x seems to be broken in that it sends large file (64 bit)
4686 * lockingX calls even if the CAP_LARGE_FILES was *not*
4687 * negotiated. For boxes without large unsigned ints truncate the
4688 * lock count by dropping the top 32 bits.
4691 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4692 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4693 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4694 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4695 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4698 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4699 #endif /* HAVE_LONGLONG */
4702 return count;
4705 #if !defined(HAVE_LONGLONG)
4706 /****************************************************************************
4707 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4708 ****************************************************************************/
4710 static uint32 map_lock_offset(uint32 high, uint32 low)
4712 unsigned int i;
4713 uint32 mask = 0;
4714 uint32 highcopy = high;
4717 * Try and find out how many significant bits there are in high.
4720 for(i = 0; highcopy; i++)
4721 highcopy >>= 1;
4724 * We use 31 bits not 32 here as POSIX
4725 * lock offsets may not be negative.
4728 mask = (~0) << (31 - i);
4730 if(low & mask)
4731 return 0; /* Fail. */
4733 high <<= (31 - i);
4735 return (high|low);
4737 #endif /* !defined(HAVE_LONGLONG) */
4739 /****************************************************************************
4740 Get a lock offset, dealing with large offset requests.
4741 ****************************************************************************/
4743 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4745 SMB_BIG_UINT offset = 0;
4747 *err = False;
4749 if(!large_file_format) {
4750 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4751 } else {
4753 #if defined(HAVE_LONGLONG)
4754 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4755 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4756 #else /* HAVE_LONGLONG */
4759 * NT4.x seems to be broken in that it sends large file (64 bit)
4760 * lockingX calls even if the CAP_LARGE_FILES was *not*
4761 * negotiated. For boxes without large unsigned ints mangle the
4762 * lock offset by mapping the top 32 bits onto the lower 32.
4765 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4766 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4767 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4768 uint32 new_low = 0;
4770 if((new_low = map_lock_offset(high, low)) == 0) {
4771 *err = True;
4772 return (SMB_BIG_UINT)-1;
4775 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4776 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4777 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4778 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4781 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4782 #endif /* HAVE_LONGLONG */
4785 return offset;
4788 /****************************************************************************
4789 Reply to a lockingX request.
4790 ****************************************************************************/
4792 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4794 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4795 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4796 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4797 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4798 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4799 SMB_BIG_UINT count = 0, offset = 0;
4800 uint16 lock_pid;
4801 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4802 int i;
4803 char *data;
4804 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4805 BOOL err;
4806 BOOL my_lock_ctx = False;
4807 NTSTATUS status;
4809 START_PROFILE(SMBlockingX);
4811 CHECK_FSP(fsp,conn);
4813 data = smb_buf(inbuf);
4815 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4816 /* we don't support these - and CANCEL_LOCK makes w2k
4817 and XP reboot so I don't really want to be
4818 compatible! (tridge) */
4819 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4822 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4823 /* Need to make this like a cancel.... JRA. */
4824 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4827 /* Check if this is an oplock break on a file
4828 we have granted an oplock on.
4830 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4831 /* Client can insist on breaking to none. */
4832 BOOL break_to_none = (oplocklevel == 0);
4834 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4835 (unsigned int)oplocklevel, fsp->fnum ));
4838 * Make sure we have granted an exclusive or batch oplock on this file.
4841 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4842 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4843 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4845 /* if this is a pure oplock break request then don't send a reply */
4846 if (num_locks == 0 && num_ulocks == 0) {
4847 END_PROFILE(SMBlockingX);
4848 return -1;
4849 } else {
4850 END_PROFILE(SMBlockingX);
4851 return ERROR_DOS(ERRDOS,ERRlock);
4855 if (remove_oplock(fsp, break_to_none) == False) {
4856 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4857 fsp->fsp_name ));
4860 /* if this is a pure oplock break request then don't send a reply */
4861 if (num_locks == 0 && num_ulocks == 0) {
4862 /* Sanity check - ensure a pure oplock break is not a
4863 chained request. */
4864 if(CVAL(inbuf,smb_vwv0) != 0xff)
4865 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4866 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4867 END_PROFILE(SMBlockingX);
4868 return -1;
4873 * We do this check *after* we have checked this is not a oplock break
4874 * response message. JRA.
4877 release_level_2_oplocks_on_change(fsp);
4879 /* Data now points at the beginning of the list
4880 of smb_unlkrng structs */
4881 for(i = 0; i < (int)num_ulocks; i++) {
4882 lock_pid = get_lock_pid( data, i, large_file_format);
4883 count = get_lock_count( data, i, large_file_format);
4884 offset = get_lock_offset( data, i, large_file_format, &err);
4887 * There is no error code marked "stupid client bug".... :-).
4889 if(err) {
4890 END_PROFILE(SMBlockingX);
4891 return ERROR_DOS(ERRDOS,ERRnoaccess);
4894 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4895 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4897 status = do_unlock(fsp,conn,lock_pid,count,offset);
4898 if (NT_STATUS_V(status)) {
4899 END_PROFILE(SMBlockingX);
4900 return ERROR_NT(status);
4904 /* Setup the timeout in seconds. */
4906 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4908 /* Now do any requested locks */
4909 data += ((large_file_format ? 20 : 10)*num_ulocks);
4911 /* Data now points at the beginning of the list
4912 of smb_lkrng structs */
4914 for(i = 0; i < (int)num_locks; i++) {
4915 lock_pid = get_lock_pid( data, i, large_file_format);
4916 count = get_lock_count( data, i, large_file_format);
4917 offset = get_lock_offset( data, i, large_file_format, &err);
4920 * There is no error code marked "stupid client bug".... :-).
4922 if(err) {
4923 END_PROFILE(SMBlockingX);
4924 return ERROR_DOS(ERRDOS,ERRnoaccess);
4927 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4928 (double)offset, (double)count, (unsigned int)lock_pid,
4929 fsp->fsp_name, (int)lock_timeout ));
4931 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4932 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4933 if (NT_STATUS_V(status)) {
4935 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4936 * Even if it's our own lock context, we need to wait here as
4937 * there may be an unlock on the way.
4938 * So I removed a "&& !my_lock_ctx" from the following
4939 * if statement. JRA.
4941 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4943 * A blocking lock was requested. Package up
4944 * this smb into a queued request and push it
4945 * onto the blocking lock queue.
4947 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4948 END_PROFILE(SMBlockingX);
4949 return -1;
4952 break;
4956 /* If any of the above locks failed, then we must unlock
4957 all of the previous locks (X/Open spec). */
4958 if (i != num_locks && num_locks != 0) {
4960 * Ensure we don't do a remove on the lock that just failed,
4961 * as under POSIX rules, if we have a lock already there, we
4962 * will delete it (and we shouldn't) .....
4964 for(i--; i >= 0; i--) {
4965 lock_pid = get_lock_pid( data, i, large_file_format);
4966 count = get_lock_count( data, i, large_file_format);
4967 offset = get_lock_offset( data, i, large_file_format, &err);
4970 * There is no error code marked "stupid client bug".... :-).
4972 if(err) {
4973 END_PROFILE(SMBlockingX);
4974 return ERROR_DOS(ERRDOS,ERRnoaccess);
4977 do_unlock(fsp,conn,lock_pid,count,offset);
4979 END_PROFILE(SMBlockingX);
4980 return ERROR_NT(status);
4983 set_message(outbuf,2,0,True);
4985 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4986 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4988 END_PROFILE(SMBlockingX);
4989 return chain_reply(inbuf,outbuf,length,bufsize);
4992 /****************************************************************************
4993 Reply to a SMBreadbmpx (read block multiplex) request.
4994 ****************************************************************************/
4996 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4998 ssize_t nread = -1;
4999 ssize_t total_read;
5000 char *data;
5001 SMB_OFF_T startpos;
5002 int outsize;
5003 size_t maxcount;
5004 int max_per_packet;
5005 size_t tcount;
5006 int pad;
5007 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5008 START_PROFILE(SMBreadBmpx);
5010 /* this function doesn't seem to work - disable by default */
5011 if (!lp_readbmpx()) {
5012 END_PROFILE(SMBreadBmpx);
5013 return ERROR_DOS(ERRSRV,ERRuseSTD);
5016 outsize = set_message(outbuf,8,0,True);
5018 CHECK_FSP(fsp,conn);
5019 CHECK_READ(fsp);
5021 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5022 maxcount = SVAL(inbuf,smb_vwv3);
5024 data = smb_buf(outbuf);
5025 pad = ((long)data)%4;
5026 if (pad)
5027 pad = 4 - pad;
5028 data += pad;
5030 max_per_packet = bufsize-(outsize+pad);
5031 tcount = maxcount;
5032 total_read = 0;
5034 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5035 END_PROFILE(SMBreadBmpx);
5036 return ERROR_DOS(ERRDOS,ERRlock);
5039 do {
5040 size_t N = MIN(max_per_packet,tcount-total_read);
5042 nread = read_file(fsp,data,startpos,N);
5044 if (nread <= 0)
5045 nread = 0;
5047 if (nread < (ssize_t)N)
5048 tcount = total_read + nread;
5050 set_message(outbuf,8,nread,False);
5051 SIVAL(outbuf,smb_vwv0,startpos);
5052 SSVAL(outbuf,smb_vwv2,tcount);
5053 SSVAL(outbuf,smb_vwv6,nread);
5054 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5056 if (!send_smb(smbd_server_fd(),outbuf))
5057 exit_server("reply_readbmpx: send_smb failed.");
5059 total_read += nread;
5060 startpos += nread;
5061 } while (total_read < (ssize_t)tcount);
5063 END_PROFILE(SMBreadBmpx);
5064 return(-1);
5067 /****************************************************************************
5068 Reply to a SMBsetattrE.
5069 ****************************************************************************/
5071 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5073 struct utimbuf unix_times;
5074 int outsize = 0;
5075 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5076 START_PROFILE(SMBsetattrE);
5078 outsize = set_message(outbuf,0,0,True);
5080 if(!fsp || (fsp->conn != conn)) {
5081 END_PROFILE(SMBgetattrE);
5082 return ERROR_DOS(ERRDOS,ERRbadfid);
5086 * Convert the DOS times into unix times. Ignore create
5087 * time as UNIX can't set this.
5090 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
5091 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
5094 * Patch from Ray Frush <frush@engr.colostate.edu>
5095 * Sometimes times are sent as zero - ignore them.
5098 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5099 /* Ignore request */
5100 if( DEBUGLVL( 3 ) ) {
5101 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5102 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5104 END_PROFILE(SMBsetattrE);
5105 return(outsize);
5106 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
5107 /* set modify time = to access time if modify time was unset */
5108 unix_times.modtime = unix_times.actime;
5111 /* Set the date on this file */
5112 /* Should we set pending modtime here ? JRA */
5113 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
5114 END_PROFILE(SMBsetattrE);
5115 return ERROR_DOS(ERRDOS,ERRnoaccess);
5118 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
5119 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
5121 END_PROFILE(SMBsetattrE);
5122 return(outsize);
5126 /* Back from the dead for OS/2..... JRA. */
5128 /****************************************************************************
5129 Reply to a SMBwritebmpx (write block multiplex primary) request.
5130 ****************************************************************************/
5132 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5134 size_t numtowrite;
5135 ssize_t nwritten = -1;
5136 int outsize = 0;
5137 SMB_OFF_T startpos;
5138 size_t tcount;
5139 BOOL write_through;
5140 int smb_doff;
5141 char *data;
5142 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5143 START_PROFILE(SMBwriteBmpx);
5145 CHECK_FSP(fsp,conn);
5146 CHECK_WRITE(fsp);
5147 if (HAS_CACHED_ERROR(fsp)) {
5148 return(CACHED_ERROR(fsp));
5151 tcount = SVAL(inbuf,smb_vwv1);
5152 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
5153 write_through = BITSETW(inbuf+smb_vwv7,0);
5154 numtowrite = SVAL(inbuf,smb_vwv10);
5155 smb_doff = SVAL(inbuf,smb_vwv11);
5157 data = smb_base(inbuf) + smb_doff;
5159 /* If this fails we need to send an SMBwriteC response,
5160 not an SMBwritebmpx - set this up now so we don't forget */
5161 SCVAL(outbuf,smb_com,SMBwritec);
5163 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
5164 END_PROFILE(SMBwriteBmpx);
5165 return(ERROR_DOS(ERRDOS,ERRlock));
5168 nwritten = write_file(fsp,data,startpos,numtowrite);
5170 if(lp_syncalways(SNUM(conn)) || write_through)
5171 sync_file(conn,fsp);
5173 if(nwritten < (ssize_t)numtowrite) {
5174 END_PROFILE(SMBwriteBmpx);
5175 return(UNIXERROR(ERRHRD,ERRdiskfull));
5178 /* If the maximum to be written to this file
5179 is greater than what we just wrote then set
5180 up a secondary struct to be attached to this
5181 fd, we will use this to cache error messages etc. */
5183 if((ssize_t)tcount > nwritten) {
5184 write_bmpx_struct *wbms;
5185 if(fsp->wbmpx_ptr != NULL)
5186 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5187 else
5188 wbms = SMB_MALLOC_P(write_bmpx_struct);
5189 if(!wbms) {
5190 DEBUG(0,("Out of memory in reply_readmpx\n"));
5191 END_PROFILE(SMBwriteBmpx);
5192 return(ERROR_DOS(ERRSRV,ERRnoresource));
5194 wbms->wr_mode = write_through;
5195 wbms->wr_discard = False; /* No errors yet */
5196 wbms->wr_total_written = nwritten;
5197 wbms->wr_errclass = 0;
5198 wbms->wr_error = 0;
5199 fsp->wbmpx_ptr = wbms;
5202 /* We are returning successfully, set the message type back to
5203 SMBwritebmpx */
5204 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5206 outsize = set_message(outbuf,1,0,True);
5208 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5210 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5211 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5213 if (write_through && tcount==nwritten) {
5214 /* We need to send both a primary and a secondary response */
5215 smb_setlen(outbuf,outsize - 4);
5216 if (!send_smb(smbd_server_fd(),outbuf))
5217 exit_server("reply_writebmpx: send_smb failed.");
5219 /* Now the secondary */
5220 outsize = set_message(outbuf,1,0,True);
5221 SCVAL(outbuf,smb_com,SMBwritec);
5222 SSVAL(outbuf,smb_vwv0,nwritten);
5225 END_PROFILE(SMBwriteBmpx);
5226 return(outsize);
5229 /****************************************************************************
5230 Reply to a SMBwritebs (write block multiplex secondary) request.
5231 ****************************************************************************/
5233 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5235 size_t numtowrite;
5236 ssize_t nwritten = -1;
5237 int outsize = 0;
5238 SMB_OFF_T startpos;
5239 size_t tcount;
5240 BOOL write_through;
5241 int smb_doff;
5242 char *data;
5243 write_bmpx_struct *wbms;
5244 BOOL send_response = False;
5245 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5246 START_PROFILE(SMBwriteBs);
5248 CHECK_FSP(fsp,conn);
5249 CHECK_WRITE(fsp);
5251 tcount = SVAL(inbuf,smb_vwv1);
5252 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5253 numtowrite = SVAL(inbuf,smb_vwv6);
5254 smb_doff = SVAL(inbuf,smb_vwv7);
5256 data = smb_base(inbuf) + smb_doff;
5258 /* We need to send an SMBwriteC response, not an SMBwritebs */
5259 SCVAL(outbuf,smb_com,SMBwritec);
5261 /* This fd should have an auxiliary struct attached,
5262 check that it does */
5263 wbms = fsp->wbmpx_ptr;
5264 if(!wbms) {
5265 END_PROFILE(SMBwriteBs);
5266 return(-1);
5269 /* If write through is set we can return errors, else we must cache them */
5270 write_through = wbms->wr_mode;
5272 /* Check for an earlier error */
5273 if(wbms->wr_discard) {
5274 END_PROFILE(SMBwriteBs);
5275 return -1; /* Just discard the packet */
5278 nwritten = write_file(fsp,data,startpos,numtowrite);
5280 if(lp_syncalways(SNUM(conn)) || write_through)
5281 sync_file(conn,fsp);
5283 if (nwritten < (ssize_t)numtowrite) {
5284 if(write_through) {
5285 /* We are returning an error - we can delete the aux struct */
5286 if (wbms)
5287 free((char *)wbms);
5288 fsp->wbmpx_ptr = NULL;
5289 END_PROFILE(SMBwriteBs);
5290 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5292 wbms->wr_errclass = ERRHRD;
5293 wbms->wr_error = ERRdiskfull;
5294 wbms->wr_status = NT_STATUS_DISK_FULL;
5295 wbms->wr_discard = True;
5296 END_PROFILE(SMBwriteBs);
5297 return -1;
5300 /* Increment the total written, if this matches tcount
5301 we can discard the auxiliary struct (hurrah !) and return a writeC */
5302 wbms->wr_total_written += nwritten;
5303 if(wbms->wr_total_written >= tcount) {
5304 if (write_through) {
5305 outsize = set_message(outbuf,1,0,True);
5306 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5307 send_response = True;
5310 free((char *)wbms);
5311 fsp->wbmpx_ptr = NULL;
5314 if(send_response) {
5315 END_PROFILE(SMBwriteBs);
5316 return(outsize);
5319 END_PROFILE(SMBwriteBs);
5320 return(-1);
5323 /****************************************************************************
5324 Reply to a SMBgetattrE.
5325 ****************************************************************************/
5327 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5329 SMB_STRUCT_STAT sbuf;
5330 int outsize = 0;
5331 int mode;
5332 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5333 START_PROFILE(SMBgetattrE);
5335 outsize = set_message(outbuf,11,0,True);
5337 if(!fsp || (fsp->conn != conn)) {
5338 END_PROFILE(SMBgetattrE);
5339 return ERROR_DOS(ERRDOS,ERRbadfid);
5342 /* Do an fstat on this file */
5343 if(fsp_stat(fsp, &sbuf)) {
5344 END_PROFILE(SMBgetattrE);
5345 return(UNIXERROR(ERRDOS,ERRnoaccess));
5348 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5351 * Convert the times into dos times. Set create
5352 * date to be last modify date as UNIX doesn't save
5353 * this.
5356 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5357 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5358 /* Should we check pending modtime here ? JRA */
5359 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5361 if (mode & aDIR) {
5362 SIVAL(outbuf,smb_vwv6,0);
5363 SIVAL(outbuf,smb_vwv8,0);
5364 } else {
5365 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5366 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5367 SIVAL(outbuf,smb_vwv8,allocation_size);
5369 SSVAL(outbuf,smb_vwv10, mode);
5371 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5373 END_PROFILE(SMBgetattrE);
5374 return(outsize);