r6334: revert 3.0.15pre1 changes. roll back to 3.0.14.
[Samba.git] / source / smbd / reply.c
blob5802720b7e9b0d29caebd1b79901cc161bea544f
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 BOOL global_encrypted_passwords_negotiated;
40 /****************************************************************************
41 Ensure we check the path in *exactly* the same way as W2K.
42 We're assuming here that '/' is not the second byte in any multibyte char
43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44 set.
45 ****************************************************************************/
47 NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names)
49 char *d = destname;
50 const char *s = srcname;
51 NTSTATUS ret = NT_STATUS_OK;
52 BOOL start_of_name_component = True;
53 unsigned int num_bad_components = 0;
55 while (*s) {
56 if (IS_DIRECTORY_SEP(*s)) {
58 * Safe to assume is not the second part of a mb char as this is handled below.
60 /* Eat multiple '/' or '\\' */
61 while (IS_DIRECTORY_SEP(*s)) {
62 s++;
64 if ((d != destname) && (*s != '\0')) {
65 /* We only care about non-leading or trailing '/' or '\\' */
66 *d++ = '/';
69 start_of_name_component = True;
70 continue;
73 if (start_of_name_component) {
74 if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
75 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
78 * No mb char starts with '.' so we're safe checking the directory separator here.
81 /* If we just added a '/' - delete it */
82 if ((d > destname) && (*(d-1) == '/')) {
83 *(d-1) = '\0';
84 d--;
87 /* Are we at the start ? Can't go back further if so. */
88 if (d <= destname) {
89 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
90 break;
92 /* Go back one level... */
93 /* We know this is safe as '/' cannot be part of a mb sequence. */
94 /* NOTE - if this assumption is invalid we are not in good shape... */
95 /* Decrement d first as d points to the *next* char to write into. */
96 for (d--; d > destname; d--) {
97 if (*d == '/')
98 break;
100 s += 2; /* Else go past the .. */
101 /* We're still at the start of a name component, just the previous one. */
103 if (num_bad_components) {
104 /* Hmmm. Should we only decrement the bad_components if
105 we're removing a bad component ? Need to check this. JRA. */
106 num_bad_components--;
109 continue;
111 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
112 /* Component of pathname can't be "." only. */
113 ret = NT_STATUS_OBJECT_NAME_INVALID;
114 num_bad_components++;
115 *d++ = *s++;
116 continue;
120 if (!(*s & 0x80)) {
121 if (allow_wcard_names) {
122 *d++ = *s++;
123 } else {
124 switch (*s) {
125 case '*':
126 case '?':
127 case '<':
128 case '>':
129 case '"':
130 return NT_STATUS_OBJECT_NAME_INVALID;
131 default:
132 *d++ = *s++;
133 break;
136 } else {
137 switch(next_mb_char_size(s)) {
138 case 4:
139 *d++ = *s++;
140 case 3:
141 *d++ = *s++;
142 case 2:
143 *d++ = *s++;
144 case 1:
145 *d++ = *s++;
146 break;
147 default:
148 DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
149 *d = '\0';
150 return NT_STATUS_INVALID_PARAMETER;
153 if (start_of_name_component && num_bad_components) {
154 num_bad_components++;
156 start_of_name_component = False;
159 if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
160 /* For some strange reason being called from findfirst changes
161 the num_components number to cause the error return to change. JRA. */
162 if (allow_wcard_names) {
163 if (num_bad_components > 2) {
164 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
166 } else {
167 if (num_bad_components > 1) {
168 ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
173 *d = '\0';
174 return ret;
177 /****************************************************************************
178 Pull a string and check the path - provide for error return.
179 ****************************************************************************/
181 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)
183 pstring tmppath;
184 char *tmppath_ptr = tmppath;
185 size_t ret;
186 #ifdef DEVELOPER
187 SMB_ASSERT(dest_len == sizeof(pstring));
188 #endif
190 if (src_len == 0) {
191 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
192 } else {
193 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
195 *err = check_path_syntax(dest, tmppath, allow_wcard_names);
196 return ret;
199 /****************************************************************************
200 Reply to a special message.
201 ****************************************************************************/
203 int reply_special(char *inbuf,char *outbuf)
205 int outsize = 4;
206 int msg_type = CVAL(inbuf,0);
207 int msg_flags = CVAL(inbuf,1);
208 fstring name1,name2;
209 char name_type = 0;
211 static BOOL already_got_session = False;
213 *name1 = *name2 = 0;
215 memset(outbuf,'\0',smb_size);
217 smb_setlen(outbuf,0);
219 switch (msg_type) {
220 case 0x81: /* session request */
222 if (already_got_session) {
223 exit_server("multiple session request not permitted");
226 SCVAL(outbuf,0,0x82);
227 SCVAL(outbuf,3,0);
228 if (name_len(inbuf+4) > 50 ||
229 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
230 DEBUG(0,("Invalid name length in session request\n"));
231 return(0);
233 name_extract(inbuf,4,name1);
234 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
235 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
236 name1,name2));
238 set_local_machine_name(name1, True);
239 set_remote_machine_name(name2, True);
241 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
242 get_local_machine_name(), get_remote_machine_name(),
243 name_type));
245 if (name_type == 'R') {
246 /* We are being asked for a pathworks session ---
247 no thanks! */
248 SCVAL(outbuf, 0,0x83);
249 break;
252 /* only add the client's machine name to the list
253 of possibly valid usernames if we are operating
254 in share mode security */
255 if (lp_security() == SEC_SHARE) {
256 add_session_user(get_remote_machine_name());
259 reload_services(True);
260 reopen_logs();
262 already_got_session = True;
263 break;
265 case 0x89: /* session keepalive request
266 (some old clients produce this?) */
267 SCVAL(outbuf,0,SMBkeepalive);
268 SCVAL(outbuf,3,0);
269 break;
271 case 0x82: /* positive session response */
272 case 0x83: /* negative session response */
273 case 0x84: /* retarget session response */
274 DEBUG(0,("Unexpected session response\n"));
275 break;
277 case SMBkeepalive: /* session keepalive */
278 default:
279 return(0);
282 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
283 msg_type, msg_flags));
285 return(outsize);
288 /****************************************************************************
289 Reply to a tcon.
290 ****************************************************************************/
292 int reply_tcon(connection_struct *conn,
293 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
295 const char *service;
296 pstring service_buf;
297 pstring password;
298 pstring dev;
299 int outsize = 0;
300 uint16 vuid = SVAL(inbuf,smb_uid);
301 int pwlen=0;
302 NTSTATUS nt_status;
303 char *p;
304 DATA_BLOB password_blob;
306 START_PROFILE(SMBtcon);
308 *service_buf = *password = *dev = 0;
310 p = smb_buf(inbuf)+1;
311 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
312 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
313 p += pwlen;
314 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
316 p = strrchr_m(service_buf,'\\');
317 if (p) {
318 service = p+1;
319 } else {
320 service = service_buf;
323 password_blob = data_blob(password, pwlen+1);
325 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
327 data_blob_clear_free(&password_blob);
329 if (!conn) {
330 END_PROFILE(SMBtcon);
331 return ERROR_NT(nt_status);
334 outsize = set_message(outbuf,2,0,True);
335 SSVAL(outbuf,smb_vwv0,max_recv);
336 SSVAL(outbuf,smb_vwv1,conn->cnum);
337 SSVAL(outbuf,smb_tid,conn->cnum);
339 DEBUG(3,("tcon service=%s cnum=%d\n",
340 service, conn->cnum));
342 END_PROFILE(SMBtcon);
343 return(outsize);
346 /****************************************************************************
347 Reply to a tcon and X.
348 ****************************************************************************/
350 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
352 fstring service;
353 DATA_BLOB password;
355 /* what the cleint thinks the device is */
356 fstring client_devicetype;
357 /* what the server tells the client the share represents */
358 const char *server_devicetype;
359 NTSTATUS nt_status;
360 uint16 vuid = SVAL(inbuf,smb_uid);
361 int passlen = SVAL(inbuf,smb_vwv3);
362 pstring path;
363 char *p, *q;
364 extern BOOL global_encrypted_passwords_negotiated;
366 START_PROFILE(SMBtconX);
368 *service = *client_devicetype = 0;
370 /* we might have to close an old one */
371 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
372 close_cnum(conn,vuid);
375 if (passlen > MAX_PASS_LEN) {
376 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
379 if (global_encrypted_passwords_negotiated) {
380 password = data_blob(smb_buf(inbuf),passlen);
381 } else {
382 password = data_blob(smb_buf(inbuf),passlen+1);
383 /* Ensure correct termination */
384 password.data[passlen]=0;
387 p = smb_buf(inbuf) + passlen;
388 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
391 * the service name can be either: \\server\share
392 * or share directly like on the DELL PowerVault 705
394 if (*path=='\\') {
395 q = strchr_m(path+2,'\\');
396 if (!q) {
397 END_PROFILE(SMBtconX);
398 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
400 fstrcpy(service,q+1);
402 else
403 fstrcpy(service,path);
405 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
407 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
409 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
411 data_blob_clear_free(&password);
413 if (!conn) {
414 END_PROFILE(SMBtconX);
415 return ERROR_NT(nt_status);
418 if ( IS_IPC(conn) )
419 server_devicetype = "IPC";
420 else if ( IS_PRINT(conn) )
421 server_devicetype = "LPT1:";
422 else
423 server_devicetype = "A:";
425 if (Protocol < PROTOCOL_NT1) {
426 set_message(outbuf,2,0,True);
427 p = smb_buf(outbuf);
428 p += srvstr_push(outbuf, p, server_devicetype, -1,
429 STR_TERMINATE|STR_ASCII);
430 set_message_end(outbuf,p);
431 } else {
432 /* NT sets the fstype of IPC$ to the null string */
433 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
435 set_message(outbuf,3,0,True);
437 p = smb_buf(outbuf);
438 p += srvstr_push(outbuf, p, server_devicetype, -1,
439 STR_TERMINATE|STR_ASCII);
440 p += srvstr_push(outbuf, p, fstype, -1,
441 STR_TERMINATE);
443 set_message_end(outbuf,p);
445 /* what does setting this bit do? It is set by NT4 and
446 may affect the ability to autorun mounted cdroms */
447 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
448 (lp_csc_policy(SNUM(conn)) << 2));
450 init_dfsroot(conn, inbuf, outbuf);
454 DEBUG(3,("tconX service=%s \n",
455 service));
457 /* set the incoming and outgoing tid to the just created one */
458 SSVAL(inbuf,smb_tid,conn->cnum);
459 SSVAL(outbuf,smb_tid,conn->cnum);
461 END_PROFILE(SMBtconX);
462 return chain_reply(inbuf,outbuf,length,bufsize);
465 /****************************************************************************
466 Reply to an unknown type.
467 ****************************************************************************/
469 int reply_unknown(char *inbuf,char *outbuf)
471 int type;
472 type = CVAL(inbuf,smb_com);
474 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
475 smb_fn_name(type), type, type));
477 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
480 /****************************************************************************
481 Reply to an ioctl.
482 ****************************************************************************/
484 int reply_ioctl(connection_struct *conn,
485 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
487 uint16 device = SVAL(inbuf,smb_vwv1);
488 uint16 function = SVAL(inbuf,smb_vwv2);
489 uint32 ioctl_code = (device << 16) + function;
490 int replysize, outsize;
491 char *p;
492 START_PROFILE(SMBioctl);
494 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
496 switch (ioctl_code) {
497 case IOCTL_QUERY_JOB_INFO:
498 replysize = 32;
499 break;
500 default:
501 END_PROFILE(SMBioctl);
502 return(ERROR_DOS(ERRSRV,ERRnosupport));
505 outsize = set_message(outbuf,8,replysize+1,True);
506 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
507 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
508 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
509 p = smb_buf(outbuf) + 1; /* Allow for alignment */
511 switch (ioctl_code) {
512 case IOCTL_QUERY_JOB_INFO:
514 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
515 if (!fsp) {
516 END_PROFILE(SMBioctl);
517 return(UNIXERROR(ERRDOS,ERRbadfid));
519 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
520 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
521 if (conn) {
522 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
524 break;
528 END_PROFILE(SMBioctl);
529 return outsize;
532 /****************************************************************************
533 Reply to a chkpth.
534 ****************************************************************************/
536 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
538 int outsize = 0;
539 pstring name;
540 BOOL ok = False;
541 BOOL bad_path = False;
542 SMB_STRUCT_STAT sbuf;
543 NTSTATUS status;
545 START_PROFILE(SMBchkpth);
547 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
548 if (!NT_STATUS_IS_OK(status)) {
549 END_PROFILE(SMBchkpth);
550 return ERROR_NT(status);
553 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
555 unix_convert(name,conn,0,&bad_path,&sbuf);
556 if (bad_path) {
557 END_PROFILE(SMBchkpth);
558 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
561 if (check_name(name,conn)) {
562 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
563 if (!(ok = S_ISDIR(sbuf.st_mode))) {
564 END_PROFILE(SMBchkpth);
565 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
569 if (!ok) {
570 /* We special case this - as when a Windows machine
571 is parsing a path is steps through the components
572 one at a time - if a component fails it expects
573 ERRbadpath, not ERRbadfile.
575 if(errno == ENOENT) {
577 * Windows returns different error codes if
578 * the parent directory is valid but not the
579 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
580 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
581 * if the path is invalid. This is different from set_bad_path_error()
582 * in the non-NT error case.
584 END_PROFILE(SMBchkpth);
585 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
588 END_PROFILE(SMBchkpth);
589 return(UNIXERROR(ERRDOS,ERRbadpath));
592 outsize = set_message(outbuf,0,0,True);
593 DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
595 END_PROFILE(SMBchkpth);
596 return(outsize);
599 /****************************************************************************
600 Reply to a getatr.
601 ****************************************************************************/
603 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
605 pstring fname;
606 int outsize = 0;
607 SMB_STRUCT_STAT sbuf;
608 BOOL ok = False;
609 int mode=0;
610 SMB_OFF_T size=0;
611 time_t mtime=0;
612 BOOL bad_path = False;
613 char *p;
614 NTSTATUS status;
616 START_PROFILE(SMBgetatr);
618 p = smb_buf(inbuf) + 1;
619 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
620 if (!NT_STATUS_IS_OK(status)) {
621 END_PROFILE(SMBgetatr);
622 return ERROR_NT(status);
625 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
627 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
628 under WfWg - weird! */
629 if (! (*fname)) {
630 mode = aHIDDEN | aDIR;
631 if (!CAN_WRITE(conn))
632 mode |= aRONLY;
633 size = 0;
634 mtime = 0;
635 ok = True;
636 } else {
637 unix_convert(fname,conn,0,&bad_path,&sbuf);
638 if (bad_path) {
639 END_PROFILE(SMBgetatr);
640 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
642 if (check_name(fname,conn)) {
643 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
644 mode = dos_mode(conn,fname,&sbuf);
645 size = sbuf.st_size;
646 mtime = sbuf.st_mtime;
647 if (mode & aDIR)
648 size = 0;
649 ok = True;
650 } else {
651 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
656 if (!ok) {
657 END_PROFILE(SMBgetatr);
658 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
661 outsize = set_message(outbuf,10,0,True);
663 SSVAL(outbuf,smb_vwv0,mode);
664 if(lp_dos_filetime_resolution(SNUM(conn)) )
665 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
666 else
667 put_dos_date3(outbuf,smb_vwv1,mtime);
668 SIVAL(outbuf,smb_vwv3,(uint32)size);
670 if (Protocol >= PROTOCOL_NT1)
671 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
673 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
675 END_PROFILE(SMBgetatr);
676 return(outsize);
679 /****************************************************************************
680 Reply to a setatr.
681 ****************************************************************************/
683 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
685 pstring fname;
686 int outsize = 0;
687 BOOL ok=False;
688 int mode;
689 time_t mtime;
690 SMB_STRUCT_STAT sbuf;
691 BOOL bad_path = False;
692 char *p;
693 NTSTATUS status;
695 START_PROFILE(SMBsetatr);
697 p = smb_buf(inbuf) + 1;
698 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
699 if (!NT_STATUS_IS_OK(status)) {
700 END_PROFILE(SMBsetatr);
701 return ERROR_NT(status);
704 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
706 unix_convert(fname,conn,0,&bad_path,&sbuf);
707 if (bad_path) {
708 END_PROFILE(SMBsetatr);
709 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
712 mode = SVAL(inbuf,smb_vwv0);
713 mtime = make_unix_date3(inbuf+smb_vwv1);
715 if (mode != FILE_ATTRIBUTE_NORMAL) {
716 if (VALID_STAT_OF_DIR(sbuf))
717 mode |= aDIR;
718 else
719 mode &= ~aDIR;
721 if (check_name(fname,conn)) {
722 ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
724 } else {
725 ok = True;
728 if (ok)
729 ok = set_filetime(conn,fname,mtime);
731 if (!ok) {
732 END_PROFILE(SMBsetatr);
733 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
736 outsize = set_message(outbuf,0,0,True);
738 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
740 END_PROFILE(SMBsetatr);
741 return(outsize);
744 /****************************************************************************
745 Reply to a dskattr.
746 ****************************************************************************/
748 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
750 int outsize = 0;
751 SMB_BIG_UINT dfree,dsize,bsize;
752 START_PROFILE(SMBdskattr);
754 if (SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
755 END_PROFILE(SMBdskattr);
756 return(UNIXERROR(ERRHRD,ERRgeneral));
759 outsize = set_message(outbuf,5,0,True);
761 if (Protocol <= PROTOCOL_LANMAN2) {
762 double total_space, free_space;
763 /* we need to scale this to a number that DOS6 can handle. We
764 use floating point so we can handle large drives on systems
765 that don't have 64 bit integers
767 we end up displaying a maximum of 2G to DOS systems
769 total_space = dsize * (double)bsize;
770 free_space = dfree * (double)bsize;
772 dsize = (total_space+63*512) / (64*512);
773 dfree = (free_space+63*512) / (64*512);
775 if (dsize > 0xFFFF) dsize = 0xFFFF;
776 if (dfree > 0xFFFF) dfree = 0xFFFF;
778 SSVAL(outbuf,smb_vwv0,dsize);
779 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
780 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
781 SSVAL(outbuf,smb_vwv3,dfree);
782 } else {
783 SSVAL(outbuf,smb_vwv0,dsize);
784 SSVAL(outbuf,smb_vwv1,bsize/512);
785 SSVAL(outbuf,smb_vwv2,512);
786 SSVAL(outbuf,smb_vwv3,dfree);
789 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
791 END_PROFILE(SMBdskattr);
792 return(outsize);
795 /****************************************************************************
796 Reply to a search.
797 Can be called from SMBsearch, SMBffirst or SMBfunique.
798 ****************************************************************************/
800 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
802 pstring mask;
803 pstring directory;
804 pstring fname;
805 SMB_OFF_T size;
806 int mode;
807 time_t date;
808 int dirtype;
809 int outsize = 0;
810 unsigned int numentries = 0;
811 unsigned int maxentries = 0;
812 BOOL finished = False;
813 char *p;
814 BOOL ok = False;
815 int status_len;
816 pstring path;
817 char status[21];
818 int dptr_num= -1;
819 BOOL check_descend = False;
820 BOOL expect_close = False;
821 BOOL can_open = True;
822 BOOL bad_path = False;
823 NTSTATUS nt_status;
824 START_PROFILE(SMBsearch);
826 *mask = *directory = *fname = 0;
828 /* If we were called as SMBffirst then we must expect close. */
829 if(CVAL(inbuf,smb_com) == SMBffirst)
830 expect_close = True;
832 outsize = set_message(outbuf,1,3,True);
833 maxentries = SVAL(inbuf,smb_vwv0);
834 dirtype = SVAL(inbuf,smb_vwv1);
835 p = smb_buf(inbuf) + 1;
836 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
837 if (!NT_STATUS_IS_OK(nt_status)) {
838 END_PROFILE(SMBsearch);
839 return ERROR_NT(nt_status);
842 RESOLVE_DFSPATH(path, conn, inbuf, outbuf);
844 p++;
845 status_len = SVAL(p, 0);
846 p += 2;
848 /* dirtype &= ~aDIR; */
850 if (status_len == 0) {
851 SMB_STRUCT_STAT sbuf;
852 pstring dir2;
854 pstrcpy(directory,path);
855 pstrcpy(dir2,path);
856 unix_convert(directory,conn,0,&bad_path,&sbuf);
857 unix_format(dir2);
859 if (!check_name(directory,conn))
860 can_open = False;
862 p = strrchr_m(dir2,'/');
863 if (p == NULL) {
864 pstrcpy(mask,dir2);
865 *dir2 = 0;
866 } else {
867 *p = 0;
868 pstrcpy(mask,p+1);
871 p = strrchr_m(directory,'/');
872 if (!p)
873 *directory = 0;
874 else
875 *p = 0;
877 if (strlen(directory) == 0)
878 pstrcpy(directory,".");
879 memset((char *)status,'\0',21);
880 SCVAL(status,0,(dirtype & 0x1F));
881 } else {
882 int status_dirtype;
884 memcpy(status,p,21);
885 status_dirtype = CVAL(status,0) & 0x1F;
886 if (status_dirtype != (dirtype & 0x1F))
887 dirtype = status_dirtype;
889 conn->dirptr = dptr_fetch(status+12,&dptr_num);
890 if (!conn->dirptr)
891 goto SearchEmpty;
892 string_set(&conn->dirpath,dptr_path(dptr_num));
893 pstrcpy(mask, dptr_wcard(dptr_num));
896 if (can_open) {
897 p = smb_buf(outbuf) + 3;
898 ok = True;
900 if (status_len == 0) {
901 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
902 if (dptr_num < 0) {
903 if(dptr_num == -2) {
904 END_PROFILE(SMBsearch);
905 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
907 END_PROFILE(SMBsearch);
908 return ERROR_DOS(ERRDOS,ERRnofids);
910 if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
911 END_PROFILE(SMBsearch);
912 return ERROR_DOS(ERRDOS,ERRnomem);
914 } else {
915 dirtype = dptr_attr(dptr_num);
918 DEBUG(4,("dptr_num is %d\n",dptr_num));
920 if (ok) {
921 if ((dirtype&0x1F) == aVOLID) {
922 memcpy(p,status,21);
923 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
924 dptr_fill(p+12,dptr_num);
925 if (dptr_zero(p+12) && (status_len==0))
926 numentries = 1;
927 else
928 numentries = 0;
929 p += DIR_STRUCT_SIZE;
930 } else {
931 unsigned int i;
932 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
934 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
935 conn->dirpath,lp_dontdescend(SNUM(conn))));
936 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
937 check_descend = True;
939 for (i=numentries;(i<maxentries) && !finished;i++) {
940 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
941 if (!finished) {
942 memcpy(p,status,21);
943 make_dir_struct(p,mask,fname,size,mode,date);
944 dptr_fill(p+12,dptr_num);
945 numentries++;
946 p += DIR_STRUCT_SIZE;
950 } /* if (ok ) */
954 SearchEmpty:
956 /* If we were called as SMBffirst with smb_search_id == NULL
957 and no entries were found then return error and close dirptr
958 (X/Open spec) */
960 if (numentries == 0 || !ok) {
961 dptr_close(&dptr_num);
962 } else if(ok && expect_close && status_len == 0) {
963 /* Close the dptr - we know it's gone */
964 dptr_close(&dptr_num);
967 /* If we were called as SMBfunique, then we can close the dirptr now ! */
968 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
969 dptr_close(&dptr_num);
972 if ((numentries == 0) && !ms_has_wild(mask)) {
973 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
976 SSVAL(outbuf,smb_vwv0,numentries);
977 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
978 SCVAL(smb_buf(outbuf),0,5);
979 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
981 if (Protocol >= PROTOCOL_NT1)
982 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
984 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
985 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
987 outsize += DIR_STRUCT_SIZE*numentries;
988 smb_setlen(outbuf,outsize - 4);
990 if ((! *directory) && dptr_path(dptr_num))
991 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
993 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
994 smb_fn_name(CVAL(inbuf,smb_com)),
995 mask, directory, dirtype, numentries, maxentries ) );
997 END_PROFILE(SMBsearch);
998 return(outsize);
1001 /****************************************************************************
1002 Reply to a fclose (stop directory search).
1003 ****************************************************************************/
1005 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1007 int outsize = 0;
1008 int status_len;
1009 pstring path;
1010 char status[21];
1011 int dptr_num= -2;
1012 char *p;
1013 NTSTATUS err;
1015 START_PROFILE(SMBfclose);
1017 outsize = set_message(outbuf,1,0,True);
1018 p = smb_buf(inbuf) + 1;
1019 p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
1020 if (!NT_STATUS_IS_OK(err)) {
1021 END_PROFILE(SMBfclose);
1022 return ERROR_NT(err);
1024 p++;
1025 status_len = SVAL(p,0);
1026 p += 2;
1028 if (status_len == 0) {
1029 END_PROFILE(SMBfclose);
1030 return ERROR_DOS(ERRSRV,ERRsrverror);
1033 memcpy(status,p,21);
1035 if(dptr_fetch(status+12,&dptr_num)) {
1036 /* Close the dptr - we know it's gone */
1037 dptr_close(&dptr_num);
1040 SSVAL(outbuf,smb_vwv0,0);
1042 DEBUG(3,("search close\n"));
1044 END_PROFILE(SMBfclose);
1045 return(outsize);
1048 /****************************************************************************
1049 Reply to an open.
1050 ****************************************************************************/
1052 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1054 pstring fname;
1055 int outsize = 0;
1056 int fmode=0;
1057 int share_mode;
1058 SMB_OFF_T size = 0;
1059 time_t mtime=0;
1060 int rmode=0;
1061 SMB_STRUCT_STAT sbuf;
1062 BOOL bad_path = False;
1063 files_struct *fsp;
1064 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1065 uint16 dos_attr = SVAL(inbuf,smb_vwv1);
1066 NTSTATUS status;
1067 START_PROFILE(SMBopen);
1069 share_mode = SVAL(inbuf,smb_vwv0);
1071 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1072 if (!NT_STATUS_IS_OK(status)) {
1073 END_PROFILE(SMBopen);
1074 return ERROR_NT(status);
1077 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1079 unix_convert(fname,conn,0,&bad_path,&sbuf);
1080 if (bad_path) {
1081 END_PROFILE(SMBopen);
1082 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1085 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1086 (uint32)dos_attr, oplock_request,&rmode,NULL);
1088 if (!fsp) {
1089 END_PROFILE(SMBopen);
1090 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1091 /* We have re-scheduled this call. */
1092 clear_cached_errors();
1093 return -1;
1095 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1098 size = sbuf.st_size;
1099 fmode = dos_mode(conn,fname,&sbuf);
1100 mtime = sbuf.st_mtime;
1102 if (fmode & aDIR) {
1103 DEBUG(3,("attempt to open a directory %s\n",fname));
1104 close_file(fsp,False);
1105 END_PROFILE(SMBopen);
1106 return ERROR_DOS(ERRDOS,ERRnoaccess);
1109 outsize = set_message(outbuf,7,0,True);
1110 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1111 SSVAL(outbuf,smb_vwv1,fmode);
1112 if(lp_dos_filetime_resolution(SNUM(conn)) )
1113 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1114 else
1115 put_dos_date3(outbuf,smb_vwv2,mtime);
1116 SIVAL(outbuf,smb_vwv4,(uint32)size);
1117 SSVAL(outbuf,smb_vwv6,rmode);
1119 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1120 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1122 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1123 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1124 END_PROFILE(SMBopen);
1125 return(outsize);
1128 /****************************************************************************
1129 Reply to an open and X.
1130 ****************************************************************************/
1132 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1134 pstring fname;
1135 int smb_mode = SVAL(inbuf,smb_vwv3);
1136 int smb_attr = SVAL(inbuf,smb_vwv5);
1137 /* Breakout the oplock request bits so we can set the
1138 reply bits separately. */
1139 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1140 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1141 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1142 #if 0
1143 int open_flags = SVAL(inbuf,smb_vwv2);
1144 int smb_sattr = SVAL(inbuf,smb_vwv4);
1145 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1146 #endif
1147 int smb_ofun = SVAL(inbuf,smb_vwv8);
1148 SMB_OFF_T size=0;
1149 int fmode=0,mtime=0,rmode=0;
1150 SMB_STRUCT_STAT sbuf;
1151 int smb_action = 0;
1152 BOOL bad_path = False;
1153 files_struct *fsp;
1154 NTSTATUS status;
1155 START_PROFILE(SMBopenX);
1157 /* If it's an IPC, pass off the pipe handler. */
1158 if (IS_IPC(conn)) {
1159 if (lp_nt_pipe_support()) {
1160 END_PROFILE(SMBopenX);
1161 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1162 } else {
1163 END_PROFILE(SMBopenX);
1164 return ERROR_DOS(ERRSRV,ERRaccess);
1168 /* XXXX we need to handle passed times, sattr and flags */
1169 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
1170 if (!NT_STATUS_IS_OK(status)) {
1171 END_PROFILE(SMBopenX);
1172 return ERROR_NT(status);
1175 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1177 unix_convert(fname,conn,0,&bad_path,&sbuf);
1178 if (bad_path) {
1179 END_PROFILE(SMBopenX);
1180 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1183 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
1184 oplock_request, &rmode,&smb_action);
1186 if (!fsp) {
1187 END_PROFILE(SMBopenX);
1188 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1189 /* We have re-scheduled this call. */
1190 clear_cached_errors();
1191 return -1;
1193 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1196 size = sbuf.st_size;
1197 fmode = dos_mode(conn,fname,&sbuf);
1198 mtime = sbuf.st_mtime;
1199 if (fmode & aDIR) {
1200 close_file(fsp,False);
1201 END_PROFILE(SMBopenX);
1202 return ERROR_DOS(ERRDOS,ERRnoaccess);
1205 /* If the caller set the extended oplock request bit
1206 and we granted one (by whatever means) - set the
1207 correct bit for extended oplock reply.
1210 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1211 smb_action |= EXTENDED_OPLOCK_GRANTED;
1213 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1214 smb_action |= EXTENDED_OPLOCK_GRANTED;
1216 /* If the caller set the core oplock request bit
1217 and we granted one (by whatever means) - set the
1218 correct bit for core oplock reply.
1221 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1222 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1224 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1225 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1227 set_message(outbuf,15,0,True);
1228 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1229 SSVAL(outbuf,smb_vwv3,fmode);
1230 if(lp_dos_filetime_resolution(SNUM(conn)) )
1231 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1232 else
1233 put_dos_date3(outbuf,smb_vwv4,mtime);
1234 SIVAL(outbuf,smb_vwv6,(uint32)size);
1235 SSVAL(outbuf,smb_vwv8,rmode);
1236 SSVAL(outbuf,smb_vwv11,smb_action);
1238 END_PROFILE(SMBopenX);
1239 return chain_reply(inbuf,outbuf,length,bufsize);
1242 /****************************************************************************
1243 Reply to a SMBulogoffX.
1244 ****************************************************************************/
1246 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1248 uint16 vuid = SVAL(inbuf,smb_uid);
1249 user_struct *vuser = get_valid_user_struct(vuid);
1250 START_PROFILE(SMBulogoffX);
1252 if(vuser == 0)
1253 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1255 /* in user level security we are supposed to close any files
1256 open by this user */
1257 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1258 file_close_user(vuid);
1260 invalidate_vuid(vuid);
1262 set_message(outbuf,2,0,True);
1264 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1266 END_PROFILE(SMBulogoffX);
1267 return chain_reply(inbuf,outbuf,length,bufsize);
1270 /****************************************************************************
1271 Reply to a mknew or a create.
1272 ****************************************************************************/
1274 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1276 pstring fname;
1277 int com;
1278 int outsize = 0;
1279 int createmode;
1280 int ofun = 0;
1281 BOOL bad_path = False;
1282 files_struct *fsp;
1283 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1284 SMB_STRUCT_STAT sbuf;
1285 NTSTATUS status;
1286 START_PROFILE(SMBcreate);
1288 com = SVAL(inbuf,smb_com);
1290 createmode = SVAL(inbuf,smb_vwv0);
1291 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1292 if (!NT_STATUS_IS_OK(status)) {
1293 END_PROFILE(SMBcreate);
1294 return ERROR_NT(status);
1297 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1299 unix_convert(fname,conn,0,&bad_path,&sbuf);
1300 if (bad_path) {
1301 END_PROFILE(SMBcreate);
1302 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1305 if (createmode & aVOLID)
1306 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1308 if(com == SMBmknew) {
1309 /* We should fail if file exists. */
1310 ofun = FILE_CREATE_IF_NOT_EXIST;
1311 } else {
1312 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1313 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1316 /* Open file in dos compatibility share mode. */
1317 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1318 ofun, (uint32)createmode, oplock_request, NULL, NULL);
1320 if (!fsp) {
1321 END_PROFILE(SMBcreate);
1322 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1323 /* We have re-scheduled this call. */
1324 clear_cached_errors();
1325 return -1;
1327 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1330 outsize = set_message(outbuf,1,0,True);
1331 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1333 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1334 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1336 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1337 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1339 DEBUG( 2, ( "new file %s\n", fname ) );
1340 DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
1342 END_PROFILE(SMBcreate);
1343 return(outsize);
1346 /****************************************************************************
1347 Reply to a create temporary file.
1348 ****************************************************************************/
1350 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1352 pstring fname;
1353 int outsize = 0;
1354 int createattr;
1355 BOOL bad_path = False;
1356 files_struct *fsp;
1357 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1358 int tmpfd;
1359 SMB_STRUCT_STAT sbuf;
1360 char *p, *s;
1361 NTSTATUS status;
1362 unsigned int namelen;
1364 START_PROFILE(SMBctemp);
1366 createattr = SVAL(inbuf,smb_vwv0);
1367 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
1368 if (!NT_STATUS_IS_OK(status)) {
1369 END_PROFILE(SMBctemp);
1370 return ERROR_NT(status);
1372 if (*fname) {
1373 pstrcat(fname,"/TMXXXXXX");
1374 } else {
1375 pstrcat(fname,"TMXXXXXX");
1378 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1380 unix_convert(fname,conn,0,&bad_path,&sbuf);
1381 if (bad_path) {
1382 END_PROFILE(SMBctemp);
1383 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1386 tmpfd = smb_mkstemp(fname);
1387 if (tmpfd == -1) {
1388 END_PROFILE(SMBctemp);
1389 return(UNIXERROR(ERRDOS,ERRnoaccess));
1392 SMB_VFS_STAT(conn,fname,&sbuf);
1394 /* Open file in dos compatibility share mode. */
1395 /* We should fail if file does not exist. */
1396 fsp = open_file_shared(conn,fname,&sbuf,
1397 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1398 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1399 (uint32)createattr, oplock_request, NULL, NULL);
1401 /* close fd from smb_mkstemp() */
1402 close(tmpfd);
1404 if (!fsp) {
1405 END_PROFILE(SMBctemp);
1406 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1407 /* We have re-scheduled this call. */
1408 clear_cached_errors();
1409 return -1;
1411 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1414 outsize = set_message(outbuf,1,0,True);
1415 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1417 /* the returned filename is relative to the directory */
1418 s = strrchr_m(fname, '/');
1419 if (!s)
1420 s = fname;
1421 else
1422 s++;
1424 p = smb_buf(outbuf);
1425 #if 0
1426 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1427 thing in the byte section. JRA */
1428 SSVALS(p, 0, -1); /* what is this? not in spec */
1429 #endif
1430 namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1431 p += namelen;
1432 outsize = set_message_end(outbuf, p);
1434 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1435 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1437 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1438 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1440 DEBUG( 2, ( "created temp file %s\n", fname ) );
1441 DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
1442 fname, fsp->fd, sbuf.st_mode ) );
1444 END_PROFILE(SMBctemp);
1445 return(outsize);
1448 /*******************************************************************
1449 Check if a user is allowed to rename a file.
1450 ********************************************************************/
1452 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
1454 int smb_action;
1455 int access_mode;
1456 files_struct *fsp;
1457 uint16 fmode;
1459 if (!CAN_WRITE(conn))
1460 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1462 fmode = dos_mode(conn,fname,pst);
1463 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1464 return NT_STATUS_NO_SUCH_FILE;
1466 if (S_ISDIR(pst->st_mode))
1467 return NT_STATUS_OK;
1469 /* We need a better way to return NT status codes from open... */
1470 unix_ERR_class = 0;
1471 unix_ERR_code = 0;
1473 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1474 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1476 if (!fsp) {
1477 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1478 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1479 ret = NT_STATUS_SHARING_VIOLATION;
1480 unix_ERR_class = 0;
1481 unix_ERR_code = 0;
1482 unix_ERR_ntstatus = NT_STATUS_OK;
1483 return ret;
1485 close_file(fsp,False);
1486 return NT_STATUS_OK;
1489 /*******************************************************************
1490 Check if a user is allowed to delete a file.
1491 ********************************************************************/
1493 NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
1495 SMB_STRUCT_STAT sbuf;
1496 int fmode;
1497 int smb_action;
1498 int access_mode;
1499 files_struct *fsp;
1501 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1502 fname, dirtype ));
1504 if (!CAN_WRITE(conn))
1505 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1507 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1508 if(errno == ENOENT) {
1509 if (bad_path)
1510 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1511 else
1512 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1514 return map_nt_error_from_unix(errno);
1517 fmode = dos_mode(conn,fname,&sbuf);
1519 /* Can't delete a directory. */
1520 if (fmode & aDIR)
1521 return NT_STATUS_FILE_IS_A_DIRECTORY;
1522 #if 0 /* JRATEST */
1523 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1524 return NT_STATUS_OBJECT_NAME_INVALID;
1525 #endif /* JRATEST */
1527 if (!lp_delete_readonly(SNUM(conn))) {
1528 if (fmode & aRONLY)
1529 return NT_STATUS_CANNOT_DELETE;
1531 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1532 return NT_STATUS_NO_SUCH_FILE;
1534 if (check_is_at_open) {
1535 if (!can_delete_file_in_directory(conn, fname)) {
1536 return NT_STATUS_ACCESS_DENIED;
1538 } else {
1539 /* On open checks the open itself will check the share mode, so
1540 don't do it here as we'll get it wrong. */
1542 /* We need a better way to return NT status codes from open... */
1543 unix_ERR_class = 0;
1544 unix_ERR_code = 0;
1546 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1547 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
1549 if (!fsp) {
1550 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1551 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1552 ret = unix_ERR_ntstatus;
1553 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1554 ret = NT_STATUS_SHARING_VIOLATION;
1555 unix_ERR_class = 0;
1556 unix_ERR_code = 0;
1557 unix_ERR_ntstatus = NT_STATUS_OK;
1558 return ret;
1560 close_file(fsp,False);
1562 return NT_STATUS_OK;
1565 /****************************************************************************
1566 The guts of the unlink command, split out so it may be called by the NT SMB
1567 code.
1568 ****************************************************************************/
1570 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1572 pstring directory;
1573 pstring mask;
1574 char *p;
1575 int count=0;
1576 NTSTATUS error = NT_STATUS_OK;
1577 BOOL has_wild;
1578 BOOL bad_path = False;
1579 BOOL rc = True;
1580 SMB_STRUCT_STAT sbuf;
1582 *directory = *mask = 0;
1584 /* We must check for wildcards in the name given
1585 * directly by the client - before any unmangling.
1586 * This prevents an unmangling of a UNIX name containing
1587 * a DOS wildcard like '*' or '?' from unmangling into
1588 * a wildcard delete which was not intended.
1589 * FIX for #226. JRA.
1592 has_wild = ms_has_wild(name);
1594 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1596 p = strrchr_m(name,'/');
1597 if (!p) {
1598 pstrcpy(directory,".");
1599 pstrcpy(mask,name);
1600 } else {
1601 *p = 0;
1602 pstrcpy(directory,name);
1603 pstrcpy(mask,p+1);
1607 * We should only check the mangled cache
1608 * here if unix_convert failed. This means
1609 * that the path in 'mask' doesn't exist
1610 * on the file system and so we need to look
1611 * for a possible mangle. This patch from
1612 * Tine Smukavec <valentin.smukavec@hermes.si>.
1615 if (!rc && mangle_is_mangled(mask))
1616 mangle_check_cache( mask, sizeof(pstring)-1 );
1618 if (!has_wild) {
1619 pstrcat(directory,"/");
1620 pstrcat(directory,mask);
1621 error = can_delete(conn,directory,dirtype,bad_path,False);
1622 if (!NT_STATUS_IS_OK(error))
1623 return error;
1625 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1626 count++;
1628 } else {
1629 struct smb_Dir *dir_hnd = NULL;
1630 const char *dname;
1632 if (check_name(directory,conn))
1633 dir_hnd = OpenDir(conn, directory);
1635 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1636 the pattern matches against the long name, otherwise the short name
1637 We don't implement this yet XXXX
1640 if (dir_hnd) {
1641 long offset = 0;
1642 error = NT_STATUS_NO_SUCH_FILE;
1644 if (strequal(mask,"????????.???"))
1645 pstrcpy(mask,"*");
1647 while ((dname = ReadDirName(dir_hnd, &offset))) {
1648 SMB_STRUCT_STAT st;
1649 pstring fname;
1650 BOOL sys_direntry = False;
1651 pstrcpy(fname,dname);
1653 if (!is_visible_file(conn, directory, dname, &st, True)) {
1654 continue;
1657 /* Quick check for "." and ".." */
1658 if (fname[0] == '.') {
1659 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
1660 if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
1661 sys_direntry = True;
1662 } else {
1663 continue;
1668 if(!mask_match(fname, mask, conn->case_sensitive))
1669 continue;
1671 if (sys_direntry) {
1672 error = NT_STATUS_OBJECT_NAME_INVALID;
1673 DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
1674 fname, mask));
1675 break;
1678 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1679 error = can_delete(conn,fname,dirtype,bad_path,False);
1680 if (!NT_STATUS_IS_OK(error)) {
1681 continue;
1683 if (SMB_VFS_UNLINK(conn,fname) == 0)
1684 count++;
1685 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1687 CloseDir(dir_hnd);
1691 if (count == 0 && NT_STATUS_IS_OK(error)) {
1692 error = map_nt_error_from_unix(errno);
1695 return error;
1698 /****************************************************************************
1699 Reply to a unlink
1700 ****************************************************************************/
1702 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1703 int dum_buffsize)
1705 int outsize = 0;
1706 pstring name;
1707 int dirtype;
1708 NTSTATUS status;
1709 START_PROFILE(SMBunlink);
1711 dirtype = SVAL(inbuf,smb_vwv0);
1713 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
1714 if (!NT_STATUS_IS_OK(status)) {
1715 END_PROFILE(SMBunlink);
1716 return ERROR_NT(status);
1719 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1721 DEBUG(3,("reply_unlink : %s\n",name));
1723 status = unlink_internals(conn, dirtype, name);
1724 if (!NT_STATUS_IS_OK(status)) {
1725 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1726 /* We have re-scheduled this call. */
1727 clear_cached_errors();
1728 return -1;
1730 return ERROR_NT(status);
1734 * Win2k needs a changenotify request response before it will
1735 * update after a rename..
1737 process_pending_change_notify_queue((time_t)0);
1739 outsize = set_message(outbuf,0,0,True);
1741 END_PROFILE(SMBunlink);
1742 return outsize;
1745 /****************************************************************************
1746 Fail for readbraw.
1747 ****************************************************************************/
1749 static void fail_readraw(void)
1751 pstring errstr;
1752 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1753 strerror(errno) );
1754 exit_server(errstr);
1757 #if defined(WITH_SENDFILE)
1758 /****************************************************************************
1759 Fake (read/write) sendfile. Returns -1 on read or write fail.
1760 ****************************************************************************/
1762 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
1764 ssize_t ret=0;
1766 /* Paranioa check... */
1767 if (nread > bufsize) {
1768 fail_readraw();
1771 if (nread > 0) {
1772 ret = read_file(fsp,buf,startpos,nread);
1773 if (ret == -1) {
1774 return -1;
1778 /* If we had a short read, fill with zeros. */
1779 if (ret < nread) {
1780 memset(buf, '\0', nread - ret);
1783 if (write_data(smbd_server_fd(),buf,nread) != nread) {
1784 return -1;
1787 return (ssize_t)nread;
1789 #endif
1791 /****************************************************************************
1792 Use sendfile in readbraw.
1793 ****************************************************************************/
1795 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1796 ssize_t mincount, char *outbuf, int out_buffsize)
1798 ssize_t ret=0;
1800 #if defined(WITH_SENDFILE)
1802 * We can only use sendfile on a non-chained packet
1803 * but we can use on a non-oplocked file. tridge proved this
1804 * on a train in Germany :-). JRA.
1805 * reply_readbraw has already checked the length.
1808 if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
1809 DATA_BLOB header;
1811 _smb_setlen(outbuf,nread);
1812 header.data = outbuf;
1813 header.length = 4;
1814 header.free = NULL;
1816 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1817 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
1818 if (errno == ENOSYS) {
1819 goto normal_readbraw;
1823 * Special hack for broken Linux with no working sendfile. If we
1824 * return EINTR we sent the header but not the rest of the data.
1825 * Fake this up by doing read/write calls.
1827 if (errno == EINTR) {
1828 /* Ensure we don't do this again. */
1829 set_use_sendfile(SNUM(conn), False);
1830 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
1832 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
1833 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
1834 fsp->fsp_name, strerror(errno) ));
1835 exit_server("send_file_readbraw fake_sendfile failed");
1837 return;
1840 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1841 fsp->fsp_name, strerror(errno) ));
1842 exit_server("send_file_readbraw sendfile failed");
1847 normal_readbraw:
1849 #endif
1851 if (nread > 0) {
1852 ret = read_file(fsp,outbuf+4,startpos,nread);
1853 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1854 if (ret < mincount)
1855 ret = 0;
1856 #else
1857 if (ret < nread)
1858 ret = 0;
1859 #endif
1862 _smb_setlen(outbuf,ret);
1863 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1864 fail_readraw();
1867 /****************************************************************************
1868 Reply to a readbraw (core+ protocol).
1869 ****************************************************************************/
1871 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
1873 extern struct current_user current_user;
1874 ssize_t maxcount,mincount;
1875 size_t nread = 0;
1876 SMB_OFF_T startpos;
1877 char *header = outbuf;
1878 files_struct *fsp;
1879 START_PROFILE(SMBreadbraw);
1881 if (srv_is_signing_active()) {
1882 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1886 * Special check if an oplock break has been issued
1887 * and the readraw request croses on the wire, we must
1888 * return a zero length response here.
1891 if(global_oplock_break) {
1892 _smb_setlen(header,0);
1893 if (write_data(smbd_server_fd(),header,4) != 4)
1894 fail_readraw();
1895 DEBUG(5,("readbraw - oplock break finished\n"));
1896 END_PROFILE(SMBreadbraw);
1897 return -1;
1900 fsp = file_fsp(inbuf,smb_vwv0);
1902 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1904 * fsp could be NULL here so use the value from the packet. JRA.
1906 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1907 _smb_setlen(header,0);
1908 if (write_data(smbd_server_fd(),header,4) != 4)
1909 fail_readraw();
1910 END_PROFILE(SMBreadbraw);
1911 return(-1);
1914 CHECK_FSP(fsp,conn);
1916 flush_write_cache(fsp, READRAW_FLUSH);
1918 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1919 if(CVAL(inbuf,smb_wct) == 10) {
1921 * This is a large offset (64 bit) read.
1923 #ifdef LARGE_SMB_OFF_T
1925 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1927 #else /* !LARGE_SMB_OFF_T */
1930 * Ensure we haven't been sent a >32 bit offset.
1933 if(IVAL(inbuf,smb_vwv8) != 0) {
1934 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1935 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1936 _smb_setlen(header,0);
1937 if (write_data(smbd_server_fd(),header,4) != 4)
1938 fail_readraw();
1939 END_PROFILE(SMBreadbraw);
1940 return(-1);
1943 #endif /* LARGE_SMB_OFF_T */
1945 if(startpos < 0) {
1946 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1947 _smb_setlen(header,0);
1948 if (write_data(smbd_server_fd(),header,4) != 4)
1949 fail_readraw();
1950 END_PROFILE(SMBreadbraw);
1951 return(-1);
1954 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1955 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1957 /* ensure we don't overrun the packet size */
1958 maxcount = MIN(65535,maxcount);
1960 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
1961 SMB_OFF_T size = fsp->size;
1962 SMB_OFF_T sizeneeded = startpos + maxcount;
1964 if (size < sizeneeded) {
1965 SMB_STRUCT_STAT st;
1966 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1967 size = st.st_size;
1968 if (!fsp->can_write)
1969 fsp->size = size;
1972 if (startpos >= size)
1973 nread = 0;
1974 else
1975 nread = MIN(maxcount,(size - startpos));
1978 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1979 if (nread < mincount)
1980 nread = 0;
1981 #endif
1983 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1984 (int)maxcount, (int)mincount, (int)nread ) );
1986 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
1988 DEBUG(5,("readbraw finished\n"));
1989 END_PROFILE(SMBreadbraw);
1990 return -1;
1993 /****************************************************************************
1994 Reply to a lockread (core+ protocol).
1995 ****************************************************************************/
1997 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1999 ssize_t nread = -1;
2000 char *data;
2001 int outsize = 0;
2002 SMB_OFF_T startpos;
2003 size_t numtoread;
2004 NTSTATUS status;
2005 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2006 BOOL my_lock_ctx = False;
2007 START_PROFILE(SMBlockread);
2009 CHECK_FSP(fsp,conn);
2010 CHECK_READ(fsp);
2012 release_level_2_oplocks_on_change(fsp);
2014 numtoread = SVAL(inbuf,smb_vwv1);
2015 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2017 outsize = set_message(outbuf,5,3,True);
2018 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2019 data = smb_buf(outbuf) + 3;
2022 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2023 * protocol request that predates the read/write lock concept.
2024 * Thus instead of asking for a read lock here we need to ask
2025 * for a write lock. JRA.
2026 * Note that the requested lock size is unaffected by max_recv.
2029 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
2030 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
2032 if (NT_STATUS_V(status)) {
2033 #if 0
2035 * We used to make lockread a blocking lock. It turns out
2036 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
2037 * tester. JRA.
2040 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2042 * A blocking lock was requested. Package up
2043 * this smb into a queued request and push it
2044 * onto the blocking lock queue.
2046 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
2047 (SMB_BIG_UINT)numtoread)) {
2048 END_PROFILE(SMBlockread);
2049 return -1;
2052 #endif
2053 END_PROFILE(SMBlockread);
2054 return ERROR_NT(status);
2058 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2061 if (numtoread > max_recv) {
2062 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2063 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2064 (unsigned int)numtoread, (unsigned int)max_recv ));
2065 numtoread = MIN(numtoread,max_recv);
2067 nread = read_file(fsp,data,startpos,numtoread);
2069 if (nread < 0) {
2070 END_PROFILE(SMBlockread);
2071 return(UNIXERROR(ERRDOS,ERRnoaccess));
2074 outsize += nread;
2075 SSVAL(outbuf,smb_vwv0,nread);
2076 SSVAL(outbuf,smb_vwv5,nread+3);
2077 SSVAL(smb_buf(outbuf),1,nread);
2079 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2080 fsp->fnum, (int)numtoread, (int)nread));
2082 END_PROFILE(SMBlockread);
2083 return(outsize);
2086 /****************************************************************************
2087 Reply to a read.
2088 ****************************************************************************/
2090 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2092 size_t numtoread;
2093 ssize_t nread = 0;
2094 char *data;
2095 SMB_OFF_T startpos;
2096 int outsize = 0;
2097 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2098 START_PROFILE(SMBread);
2100 CHECK_FSP(fsp,conn);
2101 CHECK_READ(fsp);
2103 numtoread = SVAL(inbuf,smb_vwv1);
2104 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2106 outsize = set_message(outbuf,5,3,True);
2107 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2109 * The requested read size cannot be greater than max_recv. JRA.
2111 if (numtoread > max_recv) {
2112 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2113 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2114 (unsigned int)numtoread, (unsigned int)max_recv ));
2115 numtoread = MIN(numtoread,max_recv);
2118 data = smb_buf(outbuf) + 3;
2120 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2121 END_PROFILE(SMBread);
2122 return ERROR_DOS(ERRDOS,ERRlock);
2125 if (numtoread > 0)
2126 nread = read_file(fsp,data,startpos,numtoread);
2128 if (nread < 0) {
2129 END_PROFILE(SMBread);
2130 return(UNIXERROR(ERRDOS,ERRnoaccess));
2133 outsize += nread;
2134 SSVAL(outbuf,smb_vwv0,nread);
2135 SSVAL(outbuf,smb_vwv5,nread+3);
2136 SCVAL(smb_buf(outbuf),0,1);
2137 SSVAL(smb_buf(outbuf),1,nread);
2139 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2140 fsp->fnum, (int)numtoread, (int)nread ) );
2142 END_PROFILE(SMBread);
2143 return(outsize);
2146 /****************************************************************************
2147 Reply to a read and X - possibly using sendfile.
2148 ****************************************************************************/
2150 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2151 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2153 int outsize = 0;
2154 ssize_t nread = -1;
2155 char *data = smb_buf(outbuf);
2157 #if defined(WITH_SENDFILE)
2159 * We can only use sendfile on a non-chained packet
2160 * but we can use on a non-oplocked file. tridge proved this
2161 * on a train in Germany :-). JRA.
2164 if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
2165 (lp_write_cache_size(SNUM(conn)) == 0) ) {
2166 SMB_STRUCT_STAT sbuf;
2167 DATA_BLOB header;
2169 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
2170 return(UNIXERROR(ERRDOS,ERRnoaccess));
2172 if (startpos > sbuf.st_size)
2173 goto normal_read;
2175 if (smb_maxcnt > (sbuf.st_size - startpos))
2176 smb_maxcnt = (sbuf.st_size - startpos);
2178 if (smb_maxcnt == 0)
2179 goto normal_read;
2182 * Set up the packet header before send. We
2183 * assume here the sendfile will work (get the
2184 * correct amount of data).
2187 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2188 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2189 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2190 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2191 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2192 SCVAL(outbuf,smb_vwv0,0xFF);
2193 set_message(outbuf,12,smb_maxcnt,False);
2194 header.data = outbuf;
2195 header.length = data - outbuf;
2196 header.free = NULL;
2198 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt)) == -1) {
2199 /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2200 if (errno == ENOSYS) {
2201 goto normal_read;
2205 * Special hack for broken Linux with no working sendfile. If we
2206 * return EINTR we sent the header but not the rest of the data.
2207 * Fake this up by doing read/write calls.
2210 if (errno == EINTR) {
2211 /* Ensure we don't do this again. */
2212 set_use_sendfile(SNUM(conn), False);
2213 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2215 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2216 len_outbuf - (data-outbuf))) == -1) {
2217 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2218 fsp->fsp_name, strerror(errno) ));
2219 exit_server("send_file_readX: fake_sendfile failed");
2221 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2222 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2223 /* Returning -1 here means successful sendfile. */
2224 return -1;
2227 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2228 fsp->fsp_name, strerror(errno) ));
2229 exit_server("send_file_readX sendfile failed");
2232 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2233 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2234 /* Returning -1 here means successful sendfile. */
2235 return -1;
2238 normal_read:
2240 #endif
2242 nread = read_file(fsp,data,startpos,smb_maxcnt);
2244 if (nread < 0) {
2245 END_PROFILE(SMBreadX);
2246 return(UNIXERROR(ERRDOS,ERRnoaccess));
2249 outsize = set_message(outbuf,12,nread,False);
2250 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2251 SSVAL(outbuf,smb_vwv5,nread);
2252 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2253 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2254 SSVAL(smb_buf(outbuf),-2,nread);
2256 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2257 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2259 /* Returning the number of bytes we want to send back - including header. */
2260 return outsize;
2263 /****************************************************************************
2264 Reply to a read and X.
2265 ****************************************************************************/
2267 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2269 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2270 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2271 ssize_t nread = -1;
2272 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2273 #if 0
2274 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2275 #endif
2277 START_PROFILE(SMBreadX);
2279 /* If it's an IPC, pass off the pipe handler. */
2280 if (IS_IPC(conn)) {
2281 END_PROFILE(SMBreadX);
2282 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2285 CHECK_FSP(fsp,conn);
2286 CHECK_READ(fsp);
2288 set_message(outbuf,12,0,True);
2290 if (global_client_caps & CAP_LARGE_READX) {
2291 if (SVAL(inbuf,smb_vwv7) == 1) {
2292 smb_maxcnt |= (1<<16);
2294 if (smb_maxcnt > BUFFER_SIZE) {
2295 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2296 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2297 END_PROFILE(SMBreadX);
2298 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2302 if(CVAL(inbuf,smb_wct) == 12) {
2303 #ifdef LARGE_SMB_OFF_T
2305 * This is a large offset (64 bit) read.
2307 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2309 #else /* !LARGE_SMB_OFF_T */
2312 * Ensure we haven't been sent a >32 bit offset.
2315 if(IVAL(inbuf,smb_vwv10) != 0) {
2316 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2317 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2318 END_PROFILE(SMBreadX);
2319 return ERROR_DOS(ERRDOS,ERRbadaccess);
2322 #endif /* LARGE_SMB_OFF_T */
2326 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2327 END_PROFILE(SMBreadX);
2328 return ERROR_DOS(ERRDOS,ERRlock);
2331 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2332 if (nread != -1)
2333 nread = chain_reply(inbuf,outbuf,length,bufsize);
2335 END_PROFILE(SMBreadX);
2336 return nread;
2339 /****************************************************************************
2340 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2341 ****************************************************************************/
2343 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2345 ssize_t nwritten=0;
2346 ssize_t total_written=0;
2347 size_t numtowrite=0;
2348 size_t tcount;
2349 SMB_OFF_T startpos;
2350 char *data=NULL;
2351 BOOL write_through;
2352 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2353 int outsize = 0;
2354 START_PROFILE(SMBwritebraw);
2356 if (srv_is_signing_active()) {
2357 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2360 CHECK_FSP(fsp,conn);
2361 CHECK_WRITE(fsp);
2363 tcount = IVAL(inbuf,smb_vwv1);
2364 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2365 write_through = BITSETW(inbuf+smb_vwv7,0);
2367 /* We have to deal with slightly different formats depending
2368 on whether we are using the core+ or lanman1.0 protocol */
2370 if(Protocol <= PROTOCOL_COREPLUS) {
2371 numtowrite = SVAL(smb_buf(inbuf),-2);
2372 data = smb_buf(inbuf);
2373 } else {
2374 numtowrite = SVAL(inbuf,smb_vwv10);
2375 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2378 /* force the error type */
2379 SCVAL(inbuf,smb_com,SMBwritec);
2380 SCVAL(outbuf,smb_com,SMBwritec);
2382 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2383 END_PROFILE(SMBwritebraw);
2384 return(ERROR_DOS(ERRDOS,ERRlock));
2387 if (numtowrite>0)
2388 nwritten = write_file(fsp,data,startpos,numtowrite);
2390 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2391 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2393 if (nwritten < (ssize_t)numtowrite) {
2394 END_PROFILE(SMBwritebraw);
2395 return(UNIXERROR(ERRHRD,ERRdiskfull));
2398 total_written = nwritten;
2400 /* Return a message to the redirector to tell it to send more bytes */
2401 SCVAL(outbuf,smb_com,SMBwritebraw);
2402 SSVALS(outbuf,smb_vwv0,-1);
2403 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2404 if (!send_smb(smbd_server_fd(),outbuf))
2405 exit_server("reply_writebraw: send_smb failed.");
2407 /* Now read the raw data into the buffer and write it */
2408 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2409 exit_server("secondary writebraw failed");
2412 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2413 numtowrite = smb_len(inbuf);
2415 /* Set up outbuf to return the correct return */
2416 outsize = set_message(outbuf,1,0,True);
2417 SCVAL(outbuf,smb_com,SMBwritec);
2418 SSVAL(outbuf,smb_vwv0,total_written);
2420 if (numtowrite != 0) {
2422 if (numtowrite > BUFFER_SIZE) {
2423 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2424 (unsigned int)numtowrite ));
2425 exit_server("secondary writebraw failed");
2428 if (tcount > nwritten+numtowrite) {
2429 DEBUG(3,("Client overestimated the write %d %d %d\n",
2430 (int)tcount,(int)nwritten,(int)numtowrite));
2433 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2434 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2435 strerror(errno) ));
2436 exit_server("secondary writebraw failed");
2439 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2441 if (nwritten < (ssize_t)numtowrite) {
2442 SCVAL(outbuf,smb_rcls,ERRHRD);
2443 SSVAL(outbuf,smb_err,ERRdiskfull);
2446 if (nwritten > 0)
2447 total_written += nwritten;
2450 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2451 sync_file(conn,fsp);
2453 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2454 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2456 /* we won't return a status if write through is not selected - this follows what WfWg does */
2457 END_PROFILE(SMBwritebraw);
2458 if (!write_through && total_written==tcount) {
2460 #if RABBIT_PELLET_FIX
2462 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2463 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2465 if (!send_keepalive(smbd_server_fd()))
2466 exit_server("reply_writebraw: send of keepalive failed");
2467 #endif
2468 return(-1);
2471 return(outsize);
2474 /****************************************************************************
2475 Reply to a writeunlock (core+).
2476 ****************************************************************************/
2478 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2479 int size, int dum_buffsize)
2481 ssize_t nwritten = -1;
2482 size_t numtowrite;
2483 SMB_OFF_T startpos;
2484 char *data;
2485 NTSTATUS status = NT_STATUS_OK;
2486 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2487 int outsize = 0;
2488 START_PROFILE(SMBwriteunlock);
2490 CHECK_FSP(fsp,conn);
2491 CHECK_WRITE(fsp);
2493 numtowrite = SVAL(inbuf,smb_vwv1);
2494 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2495 data = smb_buf(inbuf) + 3;
2497 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2498 END_PROFILE(SMBwriteunlock);
2499 return ERROR_DOS(ERRDOS,ERRlock);
2502 /* The special X/Open SMB protocol handling of
2503 zero length writes is *NOT* done for
2504 this call */
2505 if(numtowrite == 0)
2506 nwritten = 0;
2507 else
2508 nwritten = write_file(fsp,data,startpos,numtowrite);
2510 if (lp_syncalways(SNUM(conn)))
2511 sync_file(conn,fsp);
2513 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2514 END_PROFILE(SMBwriteunlock);
2515 return(UNIXERROR(ERRHRD,ERRdiskfull));
2518 if (numtowrite) {
2519 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2520 (SMB_BIG_UINT)startpos);
2521 if (NT_STATUS_V(status)) {
2522 END_PROFILE(SMBwriteunlock);
2523 return ERROR_NT(status);
2527 outsize = set_message(outbuf,1,0,True);
2529 SSVAL(outbuf,smb_vwv0,nwritten);
2531 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2532 fsp->fnum, (int)numtowrite, (int)nwritten));
2534 END_PROFILE(SMBwriteunlock);
2535 return outsize;
2538 /****************************************************************************
2539 Reply to a write.
2540 ****************************************************************************/
2542 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2544 size_t numtowrite;
2545 ssize_t nwritten = -1;
2546 SMB_OFF_T startpos;
2547 char *data;
2548 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2549 int outsize = 0;
2550 START_PROFILE(SMBwrite);
2552 /* If it's an IPC, pass off the pipe handler. */
2553 if (IS_IPC(conn)) {
2554 END_PROFILE(SMBwrite);
2555 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2558 CHECK_FSP(fsp,conn);
2559 CHECK_WRITE(fsp);
2561 numtowrite = SVAL(inbuf,smb_vwv1);
2562 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2563 data = smb_buf(inbuf) + 3;
2565 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2566 END_PROFILE(SMBwrite);
2567 return ERROR_DOS(ERRDOS,ERRlock);
2571 * X/Open SMB protocol says that if smb_vwv1 is
2572 * zero then the file size should be extended or
2573 * truncated to the size given in smb_vwv[2-3].
2576 if(numtowrite == 0) {
2578 * This is actually an allocate call, and set EOF. JRA.
2580 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2581 if (nwritten < 0) {
2582 END_PROFILE(SMBwrite);
2583 return ERROR_NT(NT_STATUS_DISK_FULL);
2585 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2586 if (nwritten < 0) {
2587 END_PROFILE(SMBwrite);
2588 return ERROR_NT(NT_STATUS_DISK_FULL);
2590 } else
2591 nwritten = write_file(fsp,data,startpos,numtowrite);
2593 if (lp_syncalways(SNUM(conn)))
2594 sync_file(conn,fsp);
2596 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2597 END_PROFILE(SMBwrite);
2598 return(UNIXERROR(ERRHRD,ERRdiskfull));
2601 outsize = set_message(outbuf,1,0,True);
2603 SSVAL(outbuf,smb_vwv0,nwritten);
2605 if (nwritten < (ssize_t)numtowrite) {
2606 SCVAL(outbuf,smb_rcls,ERRHRD);
2607 SSVAL(outbuf,smb_err,ERRdiskfull);
2610 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2612 END_PROFILE(SMBwrite);
2613 return(outsize);
2616 /****************************************************************************
2617 Reply to a write and X.
2618 ****************************************************************************/
2620 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2622 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2623 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2624 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2625 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2626 ssize_t nwritten = -1;
2627 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2628 unsigned int smblen = smb_len(inbuf);
2629 char *data;
2630 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2631 START_PROFILE(SMBwriteX);
2633 /* If it's an IPC, pass off the pipe handler. */
2634 if (IS_IPC(conn)) {
2635 END_PROFILE(SMBwriteX);
2636 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2639 CHECK_FSP(fsp,conn);
2640 CHECK_WRITE(fsp);
2642 /* Deal with possible LARGE_WRITEX */
2643 if (large_writeX)
2644 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2646 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2647 END_PROFILE(SMBwriteX);
2648 return ERROR_DOS(ERRDOS,ERRbadmem);
2651 data = smb_base(inbuf) + smb_doff;
2653 if(CVAL(inbuf,smb_wct) == 14) {
2654 #ifdef LARGE_SMB_OFF_T
2656 * This is a large offset (64 bit) write.
2658 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2660 #else /* !LARGE_SMB_OFF_T */
2663 * Ensure we haven't been sent a >32 bit offset.
2666 if(IVAL(inbuf,smb_vwv12) != 0) {
2667 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2668 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2669 END_PROFILE(SMBwriteX);
2670 return ERROR_DOS(ERRDOS,ERRbadaccess);
2673 #endif /* LARGE_SMB_OFF_T */
2676 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2677 END_PROFILE(SMBwriteX);
2678 return ERROR_DOS(ERRDOS,ERRlock);
2681 /* X/Open SMB protocol says that, unlike SMBwrite
2682 if the length is zero then NO truncation is
2683 done, just a write of zero. To truncate a file,
2684 use SMBwrite. */
2686 if(numtowrite == 0)
2687 nwritten = 0;
2688 else
2689 nwritten = write_file(fsp,data,startpos,numtowrite);
2691 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2692 END_PROFILE(SMBwriteX);
2693 return(UNIXERROR(ERRHRD,ERRdiskfull));
2696 set_message(outbuf,6,0,True);
2698 SSVAL(outbuf,smb_vwv2,nwritten);
2699 if (large_writeX)
2700 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2702 if (nwritten < (ssize_t)numtowrite) {
2703 SCVAL(outbuf,smb_rcls,ERRHRD);
2704 SSVAL(outbuf,smb_err,ERRdiskfull);
2707 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2708 fsp->fnum, (int)numtowrite, (int)nwritten));
2710 if (lp_syncalways(SNUM(conn)) || write_through)
2711 sync_file(conn,fsp);
2713 END_PROFILE(SMBwriteX);
2714 return chain_reply(inbuf,outbuf,length,bufsize);
2717 /****************************************************************************
2718 Reply to a lseek.
2719 ****************************************************************************/
2721 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2723 SMB_OFF_T startpos;
2724 SMB_OFF_T res= -1;
2725 int mode,umode;
2726 int outsize = 0;
2727 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2728 START_PROFILE(SMBlseek);
2730 CHECK_FSP(fsp,conn);
2732 flush_write_cache(fsp, SEEK_FLUSH);
2734 mode = SVAL(inbuf,smb_vwv1) & 3;
2735 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2736 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2738 switch (mode) {
2739 case 0:
2740 umode = SEEK_SET;
2741 res = startpos;
2742 break;
2743 case 1:
2744 umode = SEEK_CUR;
2745 res = fsp->pos + startpos;
2746 break;
2747 case 2:
2748 umode = SEEK_END;
2749 break;
2750 default:
2751 umode = SEEK_SET;
2752 res = startpos;
2753 break;
2756 if (umode == SEEK_END) {
2757 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2758 if(errno == EINVAL) {
2759 SMB_OFF_T current_pos = startpos;
2760 SMB_STRUCT_STAT sbuf;
2762 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2763 END_PROFILE(SMBlseek);
2764 return(UNIXERROR(ERRDOS,ERRnoaccess));
2767 current_pos += sbuf.st_size;
2768 if(current_pos < 0)
2769 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2773 if(res == -1) {
2774 END_PROFILE(SMBlseek);
2775 return(UNIXERROR(ERRDOS,ERRnoaccess));
2779 fsp->pos = res;
2781 outsize = set_message(outbuf,2,0,True);
2782 SIVAL(outbuf,smb_vwv0,res);
2784 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2785 fsp->fnum, (double)startpos, (double)res, mode));
2787 END_PROFILE(SMBlseek);
2788 return(outsize);
2791 /****************************************************************************
2792 Reply to a flush.
2793 ****************************************************************************/
2795 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2797 int outsize = set_message(outbuf,0,0,True);
2798 uint16 fnum = SVAL(inbuf,smb_vwv0);
2799 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2800 START_PROFILE(SMBflush);
2802 if (fnum != 0xFFFF)
2803 CHECK_FSP(fsp,conn);
2805 if (!fsp) {
2806 file_sync_all(conn);
2807 } else {
2808 sync_file(conn,fsp);
2811 DEBUG(3,("flush\n"));
2812 END_PROFILE(SMBflush);
2813 return(outsize);
2816 /****************************************************************************
2817 Reply to a exit.
2818 ****************************************************************************/
2820 int reply_exit(connection_struct *conn,
2821 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2823 int outsize;
2824 START_PROFILE(SMBexit);
2826 file_close_pid(SVAL(inbuf,smb_pid));
2828 outsize = set_message(outbuf,0,0,True);
2830 DEBUG(3,("exit\n"));
2832 END_PROFILE(SMBexit);
2833 return(outsize);
2836 /****************************************************************************
2837 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2838 ****************************************************************************/
2840 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2841 int dum_buffsize)
2843 extern struct current_user current_user;
2844 int outsize = 0;
2845 time_t mtime;
2846 int32 eclass = 0, err = 0;
2847 files_struct *fsp = NULL;
2848 START_PROFILE(SMBclose);
2850 outsize = set_message(outbuf,0,0,True);
2852 /* If it's an IPC, pass off to the pipe handler. */
2853 if (IS_IPC(conn)) {
2854 END_PROFILE(SMBclose);
2855 return reply_pipe_close(conn, inbuf,outbuf);
2858 fsp = file_fsp(inbuf,smb_vwv0);
2861 * We can only use CHECK_FSP if we know it's not a directory.
2864 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2865 END_PROFILE(SMBclose);
2866 return ERROR_DOS(ERRDOS,ERRbadfid);
2869 if(fsp->is_directory) {
2871 * Special case - close NT SMB directory handle.
2873 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2874 close_file(fsp,True);
2875 } else {
2877 * Close ordinary file.
2879 int close_err;
2880 pstring file_name;
2882 /* Save the name for time set in close. */
2883 pstrcpy( file_name, fsp->fsp_name);
2885 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2886 fsp->fd, fsp->fnum,
2887 conn->num_files_open));
2890 * Take care of any time sent in the close.
2893 mtime = make_unix_date3(inbuf+smb_vwv1);
2894 fsp_set_pending_modtime(fsp, mtime);
2897 * close_file() returns the unix errno if an error
2898 * was detected on close - normally this is due to
2899 * a disk full error. If not then it was probably an I/O error.
2902 if((close_err = close_file(fsp,True)) != 0) {
2903 errno = close_err;
2904 END_PROFILE(SMBclose);
2905 return (UNIXERROR(ERRHRD,ERRgeneral));
2909 /* We have a cached error */
2910 if(eclass || err) {
2911 END_PROFILE(SMBclose);
2912 return ERROR_DOS(eclass,err);
2915 END_PROFILE(SMBclose);
2916 return(outsize);
2919 /****************************************************************************
2920 Reply to a writeclose (Core+ protocol).
2921 ****************************************************************************/
2923 int reply_writeclose(connection_struct *conn,
2924 char *inbuf,char *outbuf, int size, int dum_buffsize)
2926 size_t numtowrite;
2927 ssize_t nwritten = -1;
2928 int outsize = 0;
2929 int close_err = 0;
2930 SMB_OFF_T startpos;
2931 char *data;
2932 time_t mtime;
2933 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2934 START_PROFILE(SMBwriteclose);
2936 CHECK_FSP(fsp,conn);
2937 CHECK_WRITE(fsp);
2939 numtowrite = SVAL(inbuf,smb_vwv1);
2940 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2941 mtime = make_unix_date3(inbuf+smb_vwv4);
2942 data = smb_buf(inbuf) + 1;
2944 if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2945 END_PROFILE(SMBwriteclose);
2946 return ERROR_DOS(ERRDOS,ERRlock);
2949 nwritten = write_file(fsp,data,startpos,numtowrite);
2951 set_filetime(conn, fsp->fsp_name,mtime);
2954 * More insanity. W2K only closes the file if writelen > 0.
2955 * JRA.
2958 if (numtowrite) {
2959 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2960 fsp->fsp_name ));
2961 close_err = close_file(fsp,True);
2964 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2965 fsp->fnum, (int)numtowrite, (int)nwritten,
2966 conn->num_files_open));
2968 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2969 END_PROFILE(SMBwriteclose);
2970 return(UNIXERROR(ERRHRD,ERRdiskfull));
2973 if(close_err != 0) {
2974 errno = close_err;
2975 END_PROFILE(SMBwriteclose);
2976 return(UNIXERROR(ERRHRD,ERRgeneral));
2979 outsize = set_message(outbuf,1,0,True);
2981 SSVAL(outbuf,smb_vwv0,nwritten);
2982 END_PROFILE(SMBwriteclose);
2983 return(outsize);
2986 /****************************************************************************
2987 Reply to a lock.
2988 ****************************************************************************/
2990 int reply_lock(connection_struct *conn,
2991 char *inbuf,char *outbuf, int length, int dum_buffsize)
2993 int outsize = set_message(outbuf,0,0,True);
2994 SMB_BIG_UINT count,offset;
2995 NTSTATUS status;
2996 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2997 BOOL my_lock_ctx = False;
2999 START_PROFILE(SMBlock);
3001 CHECK_FSP(fsp,conn);
3003 release_level_2_oplocks_on_change(fsp);
3005 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3006 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3008 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3009 fsp->fd, fsp->fnum, (double)offset, (double)count));
3011 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
3012 if (NT_STATUS_V(status)) {
3013 #if 0
3014 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
3015 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
3017 * A blocking lock was requested. Package up
3018 * this smb into a queued request and push it
3019 * onto the blocking lock queue.
3021 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
3022 END_PROFILE(SMBlock);
3023 return -1;
3026 #endif
3027 END_PROFILE(SMBlock);
3028 return ERROR_NT(status);
3031 END_PROFILE(SMBlock);
3032 return(outsize);
3035 /****************************************************************************
3036 Reply to a unlock.
3037 ****************************************************************************/
3039 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3040 int dum_buffsize)
3042 int outsize = set_message(outbuf,0,0,True);
3043 SMB_BIG_UINT count,offset;
3044 NTSTATUS status;
3045 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3046 START_PROFILE(SMBunlock);
3048 CHECK_FSP(fsp,conn);
3050 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3051 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3053 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
3054 if (NT_STATUS_V(status)) {
3055 END_PROFILE(SMBunlock);
3056 return ERROR_NT(status);
3059 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3060 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
3062 END_PROFILE(SMBunlock);
3063 return(outsize);
3066 /****************************************************************************
3067 Reply to a tdis.
3068 ****************************************************************************/
3070 int reply_tdis(connection_struct *conn,
3071 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3073 int outsize = set_message(outbuf,0,0,True);
3074 uint16 vuid;
3075 START_PROFILE(SMBtdis);
3077 vuid = SVAL(inbuf,smb_uid);
3079 if (!conn) {
3080 DEBUG(4,("Invalid connection in tdis\n"));
3081 END_PROFILE(SMBtdis);
3082 return ERROR_DOS(ERRSRV,ERRinvnid);
3085 conn->used = False;
3087 close_cnum(conn,vuid);
3089 END_PROFILE(SMBtdis);
3090 return outsize;
3093 /****************************************************************************
3094 Reply to a echo.
3095 ****************************************************************************/
3097 int reply_echo(connection_struct *conn,
3098 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3100 int smb_reverb = SVAL(inbuf,smb_vwv0);
3101 int seq_num;
3102 unsigned int data_len = smb_buflen(inbuf);
3103 int outsize = set_message(outbuf,1,data_len,True);
3104 START_PROFILE(SMBecho);
3106 if (data_len > BUFFER_SIZE) {
3107 DEBUG(0,("reply_echo: data_len too large.\n"));
3108 END_PROFILE(SMBecho);
3109 return -1;
3112 /* copy any incoming data back out */
3113 if (data_len > 0)
3114 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3116 if (smb_reverb > 100) {
3117 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3118 smb_reverb = 100;
3121 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3122 SSVAL(outbuf,smb_vwv0,seq_num);
3124 smb_setlen(outbuf,outsize - 4);
3126 if (!send_smb(smbd_server_fd(),outbuf))
3127 exit_server("reply_echo: send_smb failed.");
3130 DEBUG(3,("echo %d times\n", smb_reverb));
3132 smb_echo_count++;
3134 END_PROFILE(SMBecho);
3135 return -1;
3138 /****************************************************************************
3139 Reply to a printopen.
3140 ****************************************************************************/
3142 int reply_printopen(connection_struct *conn,
3143 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3145 int outsize = 0;
3146 files_struct *fsp;
3147 START_PROFILE(SMBsplopen);
3149 if (!CAN_PRINT(conn)) {
3150 END_PROFILE(SMBsplopen);
3151 return ERROR_DOS(ERRDOS,ERRnoaccess);
3154 /* Open for exclusive use, write only. */
3155 fsp = print_fsp_open(conn, NULL);
3157 if (!fsp) {
3158 END_PROFILE(SMBsplopen);
3159 return(UNIXERROR(ERRDOS,ERRnoaccess));
3162 outsize = set_message(outbuf,1,0,True);
3163 SSVAL(outbuf,smb_vwv0,fsp->fnum);
3165 DEBUG(3,("openprint fd=%d fnum=%d\n",
3166 fsp->fd, fsp->fnum));
3168 END_PROFILE(SMBsplopen);
3169 return(outsize);
3172 /****************************************************************************
3173 Reply to a printclose.
3174 ****************************************************************************/
3176 int reply_printclose(connection_struct *conn,
3177 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3179 int outsize = set_message(outbuf,0,0,True);
3180 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3181 int close_err = 0;
3182 START_PROFILE(SMBsplclose);
3184 CHECK_FSP(fsp,conn);
3186 if (!CAN_PRINT(conn)) {
3187 END_PROFILE(SMBsplclose);
3188 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
3191 DEBUG(3,("printclose fd=%d fnum=%d\n",
3192 fsp->fd,fsp->fnum));
3194 close_err = close_file(fsp,True);
3196 if(close_err != 0) {
3197 errno = close_err;
3198 END_PROFILE(SMBsplclose);
3199 return(UNIXERROR(ERRHRD,ERRgeneral));
3202 END_PROFILE(SMBsplclose);
3203 return(outsize);
3206 /****************************************************************************
3207 Reply to a printqueue.
3208 ****************************************************************************/
3210 int reply_printqueue(connection_struct *conn,
3211 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3213 int outsize = set_message(outbuf,2,3,True);
3214 int max_count = SVAL(inbuf,smb_vwv0);
3215 int start_index = SVAL(inbuf,smb_vwv1);
3216 START_PROFILE(SMBsplretq);
3218 /* we used to allow the client to get the cnum wrong, but that
3219 is really quite gross and only worked when there was only
3220 one printer - I think we should now only accept it if they
3221 get it right (tridge) */
3222 if (!CAN_PRINT(conn)) {
3223 END_PROFILE(SMBsplretq);
3224 return ERROR_DOS(ERRDOS,ERRnoaccess);
3227 SSVAL(outbuf,smb_vwv0,0);
3228 SSVAL(outbuf,smb_vwv1,0);
3229 SCVAL(smb_buf(outbuf),0,1);
3230 SSVAL(smb_buf(outbuf),1,0);
3232 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3233 start_index, max_count));
3236 print_queue_struct *queue = NULL;
3237 print_status_struct status;
3238 char *p = smb_buf(outbuf) + 3;
3239 int count = print_queue_status(SNUM(conn), &queue, &status);
3240 int num_to_get = ABS(max_count);
3241 int first = (max_count>0?start_index:start_index+max_count+1);
3242 int i;
3244 if (first >= count)
3245 num_to_get = 0;
3246 else
3247 num_to_get = MIN(num_to_get,count-first);
3250 for (i=first;i<first+num_to_get;i++) {
3251 put_dos_date2(p,0,queue[i].time);
3252 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3253 SSVAL(p,5, queue[i].job);
3254 SIVAL(p,7,queue[i].size);
3255 SCVAL(p,11,0);
3256 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3257 p += 28;
3260 if (count > 0) {
3261 outsize = set_message(outbuf,2,28*count+3,False);
3262 SSVAL(outbuf,smb_vwv0,count);
3263 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3264 SCVAL(smb_buf(outbuf),0,1);
3265 SSVAL(smb_buf(outbuf),1,28*count);
3268 SAFE_FREE(queue);
3270 DEBUG(3,("%d entries returned in queue\n",count));
3273 END_PROFILE(SMBsplretq);
3274 return(outsize);
3277 /****************************************************************************
3278 Reply to a printwrite.
3279 ****************************************************************************/
3281 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3283 int numtowrite;
3284 int outsize = set_message(outbuf,0,0,True);
3285 char *data;
3286 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3288 START_PROFILE(SMBsplwr);
3290 if (!CAN_PRINT(conn)) {
3291 END_PROFILE(SMBsplwr);
3292 return ERROR_DOS(ERRDOS,ERRnoaccess);
3295 CHECK_FSP(fsp,conn);
3296 CHECK_WRITE(fsp);
3298 numtowrite = SVAL(smb_buf(inbuf),1);
3299 data = smb_buf(inbuf) + 3;
3301 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3302 END_PROFILE(SMBsplwr);
3303 return(UNIXERROR(ERRHRD,ERRdiskfull));
3306 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3308 END_PROFILE(SMBsplwr);
3309 return(outsize);
3312 /****************************************************************************
3313 The guts of the mkdir command, split out so it may be called by the NT SMB
3314 code.
3315 ****************************************************************************/
3317 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3319 BOOL bad_path = False;
3320 SMB_STRUCT_STAT sbuf;
3321 int ret= -1;
3323 unix_convert(directory,conn,0,&bad_path,&sbuf);
3325 if( strchr_m(directory, ':')) {
3326 return NT_STATUS_NOT_A_DIRECTORY;
3329 if (ms_has_wild(directory)) {
3330 return NT_STATUS_OBJECT_NAME_INVALID;
3333 if (bad_path) {
3334 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3337 if (check_name(directory, conn))
3338 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
3340 if (ret == -1) {
3341 if(errno == ENOENT) {
3342 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3344 return map_nt_error_from_unix(errno);
3347 return NT_STATUS_OK;
3350 /****************************************************************************
3351 Reply to a mkdir.
3352 ****************************************************************************/
3354 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3356 pstring directory;
3357 int outsize;
3358 NTSTATUS status;
3359 START_PROFILE(SMBmkdir);
3361 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3362 if (!NT_STATUS_IS_OK(status)) {
3363 END_PROFILE(SMBmkdir);
3364 return ERROR_NT(status);
3367 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3369 status = mkdir_internal(conn, directory);
3370 if (!NT_STATUS_IS_OK(status)) {
3371 END_PROFILE(SMBmkdir);
3372 return ERROR_NT(status);
3375 outsize = set_message(outbuf,0,0,True);
3377 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3379 END_PROFILE(SMBmkdir);
3380 return(outsize);
3383 /****************************************************************************
3384 Static function used by reply_rmdir to delete an entire directory
3385 tree recursively. Return False on ok, True on fail.
3386 ****************************************************************************/
3388 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3390 const char *dname = NULL;
3391 BOOL ret = False;
3392 long offset = 0;
3393 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3395 if(dir_hnd == NULL)
3396 return True;
3398 while((dname = ReadDirName(dir_hnd, &offset))) {
3399 pstring fullname;
3400 SMB_STRUCT_STAT st;
3402 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3403 continue;
3405 if (!is_visible_file(conn, directory, dname, &st, False))
3406 continue;
3408 /* Construct the full name. */
3409 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3410 errno = ENOMEM;
3411 ret = True;
3412 break;
3415 pstrcpy(fullname, directory);
3416 pstrcat(fullname, "/");
3417 pstrcat(fullname, dname);
3419 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3420 ret = True;
3421 break;
3424 if(st.st_mode & S_IFDIR) {
3425 if(recursive_rmdir(conn, fullname)!=0) {
3426 ret = True;
3427 break;
3429 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3430 ret = True;
3431 break;
3433 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3434 ret = True;
3435 break;
3438 CloseDir(dir_hnd);
3439 return ret;
3442 /****************************************************************************
3443 The internals of the rmdir code - called elsewhere.
3444 ****************************************************************************/
3446 BOOL rmdir_internals(connection_struct *conn, char *directory)
3448 BOOL ok;
3449 SMB_STRUCT_STAT st;
3451 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3452 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3454 * Check to see if the only thing in this directory are
3455 * vetoed files/directories. If so then delete them and
3456 * retry. If we fail to delete any of them (and we *don't*
3457 * do a recursive delete) then fail the rmdir.
3459 BOOL all_veto_files = True;
3460 const char *dname;
3461 struct smb_Dir *dir_hnd = OpenDir(conn, directory);
3463 if(dir_hnd != NULL) {
3464 long dirpos = TellDir(dir_hnd);
3465 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3466 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3467 continue;
3468 if (!is_visible_file(conn, directory, dname, &st, False))
3469 continue;
3470 if(!IS_VETO_PATH(conn, dname)) {
3471 all_veto_files = False;
3472 break;
3476 if(all_veto_files) {
3477 SeekDir(dir_hnd,dirpos);
3478 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
3479 pstring fullname;
3481 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3482 continue;
3483 if (!is_visible_file(conn, directory, dname, &st, False))
3484 continue;
3486 /* Construct the full name. */
3487 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3488 errno = ENOMEM;
3489 break;
3492 pstrcpy(fullname, directory);
3493 pstrcat(fullname, "/");
3494 pstrcat(fullname, dname);
3496 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3497 break;
3498 if(st.st_mode & S_IFDIR) {
3499 if(lp_recursive_veto_delete(SNUM(conn))) {
3500 if(recursive_rmdir(conn, fullname) != 0)
3501 break;
3503 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3504 break;
3505 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3506 break;
3508 CloseDir(dir_hnd);
3509 /* Retry the rmdir */
3510 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3511 } else {
3512 CloseDir(dir_hnd);
3514 } else {
3515 errno = ENOTEMPTY;
3519 if (!ok)
3520 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3522 return ok;
3525 /****************************************************************************
3526 Reply to a rmdir.
3527 ****************************************************************************/
3529 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3531 pstring directory;
3532 int outsize = 0;
3533 BOOL ok = False;
3534 BOOL bad_path = False;
3535 SMB_STRUCT_STAT sbuf;
3536 NTSTATUS status;
3537 START_PROFILE(SMBrmdir);
3539 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
3540 if (!NT_STATUS_IS_OK(status)) {
3541 END_PROFILE(SMBrmdir);
3542 return ERROR_NT(status);
3545 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3547 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3548 if (bad_path) {
3549 END_PROFILE(SMBrmdir);
3550 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3553 if (check_name(directory,conn)) {
3554 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3555 ok = rmdir_internals(conn, directory);
3558 if (!ok) {
3559 END_PROFILE(SMBrmdir);
3560 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3563 outsize = set_message(outbuf,0,0,True);
3565 DEBUG( 3, ( "rmdir %s\n", directory ) );
3567 END_PROFILE(SMBrmdir);
3568 return(outsize);
3571 /*******************************************************************
3572 Resolve wildcards in a filename rename.
3573 Note that name is in UNIX charset and thus potentially can be more
3574 than fstring buffer (255 bytes) especially in default UTF-8 case.
3575 Therefore, we use pstring inside and all calls should ensure that
3576 name2 is at least pstring-long (they do already)
3577 ********************************************************************/
3579 static BOOL resolve_wildcards(const char *name1, char *name2)
3581 pstring root1,root2;
3582 pstring ext1,ext2;
3583 char *p,*p2, *pname1, *pname2;
3584 int available_space, actual_space;
3587 pname1 = strrchr_m(name1,'/');
3588 pname2 = strrchr_m(name2,'/');
3590 if (!pname1 || !pname2)
3591 return(False);
3593 pstrcpy(root1,pname1);
3594 pstrcpy(root2,pname2);
3595 p = strrchr_m(root1,'.');
3596 if (p) {
3597 *p = 0;
3598 pstrcpy(ext1,p+1);
3599 } else {
3600 pstrcpy(ext1,"");
3602 p = strrchr_m(root2,'.');
3603 if (p) {
3604 *p = 0;
3605 pstrcpy(ext2,p+1);
3606 } else {
3607 pstrcpy(ext2,"");
3610 p = root1;
3611 p2 = root2;
3612 while (*p2) {
3613 if (*p2 == '?') {
3614 *p2 = *p;
3615 p2++;
3616 } else if (*p2 == '*') {
3617 pstrcpy(p2, p);
3618 break;
3619 } else {
3620 p2++;
3622 if (*p)
3623 p++;
3626 p = ext1;
3627 p2 = ext2;
3628 while (*p2) {
3629 if (*p2 == '?') {
3630 *p2 = *p;
3631 p2++;
3632 } else if (*p2 == '*') {
3633 pstrcpy(p2, p);
3634 break;
3635 } else {
3636 p2++;
3638 if (*p)
3639 p++;
3642 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3644 if (ext2[0]) {
3645 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3646 if (actual_space >= available_space - 1) {
3647 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
3648 actual_space - available_space));
3650 } else {
3651 pstrcpy_base(pname2, root2, name2);
3654 return(True);
3657 /****************************************************************************
3658 Ensure open files have their names updates.
3659 ****************************************************************************/
3661 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3663 files_struct *fsp;
3664 BOOL did_rename = False;
3666 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3667 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3668 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3669 fsp->fsp_name, newname ));
3670 string_set(&fsp->fsp_name, newname);
3671 did_rename = True;
3674 if (!did_rename)
3675 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3676 (unsigned int)dev, (double)inode, newname ));
3679 /****************************************************************************
3680 Rename an open file - given an fsp.
3681 ****************************************************************************/
3683 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint16 attrs, BOOL replace_if_exists)
3685 SMB_STRUCT_STAT sbuf;
3686 BOOL bad_path = False;
3687 pstring newname_last_component;
3688 NTSTATUS error = NT_STATUS_OK;
3689 BOOL dest_exists;
3690 BOOL rcdest = True;
3692 ZERO_STRUCT(sbuf);
3693 rcdest = unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3695 /* Quick check for "." and ".." */
3696 if (!bad_path && newname_last_component[0] == '.') {
3697 if (!newname_last_component[1] || (newname_last_component[1] == '.' && !newname_last_component[2])) {
3698 return NT_STATUS_ACCESS_DENIED;
3701 if (!rcdest && bad_path) {
3702 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3705 /* Ensure newname contains a '/' */
3706 if(strrchr_m(newname,'/') == 0) {
3707 pstring tmpstr;
3709 pstrcpy(tmpstr, "./");
3710 pstrcat(tmpstr, newname);
3711 pstrcpy(newname, tmpstr);
3715 * Check for special case with case preserving and not
3716 * case sensitive. If the old last component differs from the original
3717 * last component only by case, then we should allow
3718 * the rename (user is trying to change the case of the
3719 * filename).
3722 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
3723 strequal(newname, fsp->fsp_name)) {
3724 char *p;
3725 pstring newname_modified_last_component;
3728 * Get the last component of the modified name.
3729 * Note that we guarantee that newname contains a '/'
3730 * character above.
3732 p = strrchr_m(newname,'/');
3733 pstrcpy(newname_modified_last_component,p+1);
3735 if(strcsequal(newname_modified_last_component,
3736 newname_last_component) == False) {
3738 * Replace the modified last component with
3739 * the original.
3741 pstrcpy(p+1, newname_last_component);
3746 * If the src and dest names are identical - including case,
3747 * don't do the rename, just return success.
3750 if (strcsequal(fsp->fsp_name, newname)) {
3751 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3752 newname));
3753 return NT_STATUS_OK;
3756 dest_exists = vfs_object_exist(conn,newname,NULL);
3758 if(!replace_if_exists && dest_exists) {
3759 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3760 fsp->fsp_name,newname));
3761 return NT_STATUS_OBJECT_NAME_COLLISION;
3764 error = can_rename(conn,newname,attrs,&sbuf);
3766 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3767 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3768 nt_errstr(error), fsp->fsp_name,newname));
3769 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3770 error = NT_STATUS_ACCESS_DENIED;
3771 return error;
3774 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3775 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3776 fsp->fsp_name,newname));
3777 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3778 return NT_STATUS_OK;
3781 if (errno == ENOTDIR || errno == EISDIR)
3782 error = NT_STATUS_OBJECT_NAME_COLLISION;
3783 else
3784 error = map_nt_error_from_unix(errno);
3786 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3787 nt_errstr(error), fsp->fsp_name,newname));
3789 return error;
3792 /****************************************************************************
3793 The guts of the rename command, split out so it may be called by the NT SMB
3794 code.
3795 ****************************************************************************/
3797 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
3799 pstring directory;
3800 pstring mask;
3801 pstring last_component_src;
3802 pstring last_component_dest;
3803 char *p;
3804 BOOL has_wild;
3805 BOOL bad_path_src = False;
3806 BOOL bad_path_dest = False;
3807 int count=0;
3808 NTSTATUS error = NT_STATUS_OK;
3809 BOOL rc = True;
3810 BOOL rcdest = True;
3811 SMB_STRUCT_STAT sbuf1, sbuf2;
3813 *directory = *mask = 0;
3815 ZERO_STRUCT(sbuf1);
3816 ZERO_STRUCT(sbuf2);
3818 rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
3819 if (!rc && bad_path_src) {
3820 if (ms_has_wild(last_component_src))
3821 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3822 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3825 /* Quick check for "." and ".." */
3826 if (last_component_src[0] == '.') {
3827 if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
3828 return NT_STATUS_OBJECT_NAME_INVALID;
3832 rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
3834 /* Quick check for "." and ".." */
3835 if (last_component_dest[0] == '.') {
3836 if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
3837 return NT_STATUS_OBJECT_NAME_INVALID;
3842 * Split the old name into directory and last component
3843 * strings. Note that unix_convert may have stripped off a
3844 * leading ./ from both name and newname if the rename is
3845 * at the root of the share. We need to make sure either both
3846 * name and newname contain a / character or neither of them do
3847 * as this is checked in resolve_wildcards().
3850 p = strrchr_m(name,'/');
3851 if (!p) {
3852 pstrcpy(directory,".");
3853 pstrcpy(mask,name);
3854 } else {
3855 *p = 0;
3856 pstrcpy(directory,name);
3857 pstrcpy(mask,p+1);
3858 *p = '/'; /* Replace needed for exceptional test below. */
3862 * We should only check the mangled cache
3863 * here if unix_convert failed. This means
3864 * that the path in 'mask' doesn't exist
3865 * on the file system and so we need to look
3866 * for a possible mangle. This patch from
3867 * Tine Smukavec <valentin.smukavec@hermes.si>.
3870 if (!rc && mangle_is_mangled(mask))
3871 mangle_check_cache( mask, sizeof(pstring)-1 );
3873 has_wild = ms_has_wild(mask);
3875 if (!has_wild) {
3877 * No wildcards - just process the one file.
3879 BOOL is_short_name = mangle_is_8_3(name, True);
3881 /* Add a terminating '/' to the directory name. */
3882 pstrcat(directory,"/");
3883 pstrcat(directory,mask);
3885 /* Ensure newname contains a '/' also */
3886 if(strrchr_m(newname,'/') == 0) {
3887 pstring tmpstr;
3889 pstrcpy(tmpstr, "./");
3890 pstrcat(tmpstr, newname);
3891 pstrcpy(newname, tmpstr);
3894 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3895 directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
3896 conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
3897 newname, last_component_dest, is_short_name));
3900 * Check for special case with case preserving and not
3901 * case sensitive, if directory and newname are identical,
3902 * and the old last component differs from the original
3903 * last component only by case, then we should allow
3904 * the rename (user is trying to change the case of the
3905 * filename).
3907 if((conn->case_sensitive == False) &&
3908 (((conn->case_preserve == True) &&
3909 (is_short_name == False)) ||
3910 ((conn->short_case_preserve == True) &&
3911 (is_short_name == True))) &&
3912 strcsequal(directory, newname)) {
3913 pstring modified_last_component;
3916 * Get the last component of the modified name.
3917 * Note that we guarantee that newname contains a '/'
3918 * character above.
3920 p = strrchr_m(newname,'/');
3921 pstrcpy(modified_last_component,p+1);
3923 if(strcsequal(modified_last_component,
3924 last_component_dest) == False) {
3926 * Replace the modified last component with
3927 * the original.
3929 pstrcpy(p+1, last_component_dest);
3933 resolve_wildcards(directory,newname);
3936 * The source object must exist.
3939 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3940 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3941 directory,newname));
3943 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3945 * Must return different errors depending on whether the parent
3946 * directory existed or not.
3949 p = strrchr_m(directory, '/');
3950 if (!p)
3951 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3952 *p = '\0';
3953 if (vfs_object_exist(conn, directory, NULL))
3954 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3955 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3957 error = map_nt_error_from_unix(errno);
3958 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3959 nt_errstr(error), directory,newname));
3961 return error;
3964 if (!rcdest && bad_path_dest) {
3965 if (ms_has_wild(last_component_dest))
3966 return NT_STATUS_OBJECT_NAME_INVALID;
3967 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3970 error = can_rename(conn,directory,attrs,&sbuf1);
3972 if (!NT_STATUS_IS_OK(error)) {
3973 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3974 nt_errstr(error), directory,newname));
3975 return error;
3979 * If the src and dest names are identical - including case,
3980 * don't do the rename, just return success.
3983 if (strcsequal(directory, newname)) {
3984 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3985 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3986 return NT_STATUS_OK;
3989 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3990 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3991 directory,newname));
3992 return NT_STATUS_OBJECT_NAME_COLLISION;
3995 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3996 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3997 directory,newname));
3998 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3999 return NT_STATUS_OK;
4002 if (errno == ENOTDIR || errno == EISDIR)
4003 error = NT_STATUS_OBJECT_NAME_COLLISION;
4004 else
4005 error = map_nt_error_from_unix(errno);
4007 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4008 nt_errstr(error), directory,newname));
4010 return error;
4011 } else {
4013 * Wildcards - process each file that matches.
4015 struct smb_Dir *dir_hnd = NULL;
4016 const char *dname;
4017 pstring destname;
4019 if (check_name(directory,conn))
4020 dir_hnd = OpenDir(conn, directory);
4022 if (dir_hnd) {
4023 long offset = 0;
4024 error = NT_STATUS_NO_SUCH_FILE;
4025 /* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
4027 if (strequal(mask,"????????.???"))
4028 pstrcpy(mask,"*");
4030 while ((dname = ReadDirName(dir_hnd, &offset))) {
4031 pstring fname;
4032 BOOL sysdir_entry = False;
4034 pstrcpy(fname,dname);
4036 /* Quick check for "." and ".." */
4037 if (fname[0] == '.') {
4038 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4039 if (attrs & aDIR) {
4040 sysdir_entry = True;
4041 } else {
4042 continue;
4047 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4048 continue;
4050 if(!mask_match(fname, mask, conn->case_sensitive))
4051 continue;
4053 if (sysdir_entry) {
4054 error = NT_STATUS_OBJECT_NAME_INVALID;
4055 break;
4058 error = NT_STATUS_ACCESS_DENIED;
4059 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
4060 if (!vfs_object_exist(conn, fname, &sbuf1)) {
4061 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4062 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
4063 continue;
4065 error = can_rename(conn,fname,attrs,&sbuf1);
4066 if (!NT_STATUS_IS_OK(error)) {
4067 DEBUG(6,("rename %s refused\n", fname));
4068 continue;
4070 pstrcpy(destname,newname);
4072 if (!resolve_wildcards(fname,destname)) {
4073 DEBUG(6,("resolve_wildcards %s %s failed\n",
4074 fname, destname));
4075 continue;
4078 if (strcsequal(fname,destname)) {
4079 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4080 DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
4081 count++;
4082 error = NT_STATUS_OK;
4083 continue;
4086 if (!replace_if_exists &&
4087 vfs_file_exist(conn,destname, NULL)) {
4088 DEBUG(6,("file_exist %s\n", destname));
4089 error = NT_STATUS_OBJECT_NAME_COLLISION;
4090 continue;
4093 if (!SMB_VFS_RENAME(conn,fname,destname)) {
4094 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
4095 count++;
4096 error = NT_STATUS_OK;
4098 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
4100 CloseDir(dir_hnd);
4103 if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
4104 if (!rcdest && bad_path_dest) {
4105 if (ms_has_wild(last_component_dest))
4106 return NT_STATUS_OBJECT_NAME_INVALID;
4107 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4112 if (count == 0 && NT_STATUS_IS_OK(error)) {
4113 error = map_nt_error_from_unix(errno);
4116 return error;
4119 /****************************************************************************
4120 Reply to a mv.
4121 ****************************************************************************/
4123 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4124 int dum_buffsize)
4126 int outsize = 0;
4127 pstring name;
4128 pstring newname;
4129 char *p;
4130 uint16 attrs = SVAL(inbuf,smb_vwv0);
4131 NTSTATUS status;
4133 START_PROFILE(SMBmv);
4135 p = smb_buf(inbuf) + 1;
4136 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4137 if (!NT_STATUS_IS_OK(status)) {
4138 END_PROFILE(SMBmv);
4139 return ERROR_NT(status);
4141 p++;
4142 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4143 if (!NT_STATUS_IS_OK(status)) {
4144 END_PROFILE(SMBmv);
4145 return ERROR_NT(status);
4148 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4149 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4151 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4153 status = rename_internals(conn, name, newname, attrs, False);
4154 if (!NT_STATUS_IS_OK(status)) {
4155 END_PROFILE(SMBmv);
4156 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4157 /* We have re-scheduled this call. */
4158 clear_cached_errors();
4159 return -1;
4161 return ERROR_NT(status);
4165 * Win2k needs a changenotify request response before it will
4166 * update after a rename..
4168 process_pending_change_notify_queue((time_t)0);
4169 outsize = set_message(outbuf,0,0,True);
4171 END_PROFILE(SMBmv);
4172 return(outsize);
4175 /*******************************************************************
4176 Copy a file as part of a reply_copy.
4177 ******************************************************************/
4179 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
4180 int count,BOOL target_is_directory, int *err_ret)
4182 int Access,action;
4183 SMB_STRUCT_STAT src_sbuf, sbuf2;
4184 SMB_OFF_T ret=-1;
4185 files_struct *fsp1,*fsp2;
4186 pstring dest;
4187 uint32 dosattrs;
4189 *err_ret = 0;
4191 pstrcpy(dest,dest1);
4192 if (target_is_directory) {
4193 char *p = strrchr_m(src,'/');
4194 if (p)
4195 p++;
4196 else
4197 p = src;
4198 pstrcat(dest,"/");
4199 pstrcat(dest,p);
4202 if (!vfs_file_exist(conn,src,&src_sbuf))
4203 return(False);
4205 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
4206 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,INTERNAL_OPEN_ONLY,
4207 &Access,&action);
4209 if (!fsp1)
4210 return(False);
4212 if (!target_is_directory && count)
4213 ofun = FILE_EXISTS_OPEN;
4215 dosattrs = dos_mode(conn, src, &src_sbuf);
4216 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
4217 ZERO_STRUCTP(&sbuf2);
4219 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
4220 ofun,dosattrs,INTERNAL_OPEN_ONLY,&Access,&action);
4222 if (!fsp2) {
4223 close_file(fsp1,False);
4224 return(False);
4227 if ((ofun&3) == 1) {
4228 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
4229 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
4231 * Stop the copy from occurring.
4233 ret = -1;
4234 src_sbuf.st_size = 0;
4238 if (src_sbuf.st_size)
4239 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
4241 close_file(fsp1,False);
4243 /* Ensure the modtime is set correctly on the destination file. */
4244 fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
4247 * As we are opening fsp1 read-only we only expect
4248 * an error on close on fsp2 if we are out of space.
4249 * Thus we don't look at the error return from the
4250 * close of fsp1.
4252 *err_ret = close_file(fsp2,False);
4254 return(ret == (SMB_OFF_T)src_sbuf.st_size);
4257 /****************************************************************************
4258 Reply to a file copy.
4259 ****************************************************************************/
4261 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4263 int outsize = 0;
4264 pstring name;
4265 pstring directory;
4266 pstring mask,newname;
4267 char *p;
4268 int count=0;
4269 int error = ERRnoaccess;
4270 int err = 0;
4271 BOOL has_wild;
4272 BOOL exists=False;
4273 int tid2 = SVAL(inbuf,smb_vwv0);
4274 int ofun = SVAL(inbuf,smb_vwv1);
4275 int flags = SVAL(inbuf,smb_vwv2);
4276 BOOL target_is_directory=False;
4277 BOOL bad_path1 = False;
4278 BOOL bad_path2 = False;
4279 BOOL rc = True;
4280 SMB_STRUCT_STAT sbuf1, sbuf2;
4281 NTSTATUS status;
4283 START_PROFILE(SMBcopy);
4285 *directory = *mask = 0;
4287 p = smb_buf(inbuf);
4288 p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
4289 if (!NT_STATUS_IS_OK(status)) {
4290 END_PROFILE(SMBcopy);
4291 return ERROR_NT(status);
4293 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
4294 if (!NT_STATUS_IS_OK(status)) {
4295 END_PROFILE(SMBcopy);
4296 return ERROR_NT(status);
4299 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
4301 if (tid2 != conn->cnum) {
4302 /* can't currently handle inter share copies XXXX */
4303 DEBUG(3,("Rejecting inter-share copy\n"));
4304 END_PROFILE(SMBcopy);
4305 return ERROR_DOS(ERRSRV,ERRinvdevice);
4308 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4309 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4311 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
4312 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
4314 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
4316 if ((flags&1) && target_is_directory) {
4317 END_PROFILE(SMBcopy);
4318 return ERROR_DOS(ERRDOS,ERRbadfile);
4321 if ((flags&2) && !target_is_directory) {
4322 END_PROFILE(SMBcopy);
4323 return ERROR_DOS(ERRDOS,ERRbadpath);
4326 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
4327 /* wants a tree copy! XXXX */
4328 DEBUG(3,("Rejecting tree copy\n"));
4329 END_PROFILE(SMBcopy);
4330 return ERROR_DOS(ERRSRV,ERRerror);
4333 p = strrchr_m(name,'/');
4334 if (!p) {
4335 pstrcpy(directory,"./");
4336 pstrcpy(mask,name);
4337 } else {
4338 *p = 0;
4339 pstrcpy(directory,name);
4340 pstrcpy(mask,p+1);
4344 * We should only check the mangled cache
4345 * here if unix_convert failed. This means
4346 * that the path in 'mask' doesn't exist
4347 * on the file system and so we need to look
4348 * for a possible mangle. This patch from
4349 * Tine Smukavec <valentin.smukavec@hermes.si>.
4352 if (!rc && mangle_is_mangled(mask))
4353 mangle_check_cache( mask, sizeof(pstring)-1 );
4355 has_wild = ms_has_wild(mask);
4357 if (!has_wild) {
4358 pstrcat(directory,"/");
4359 pstrcat(directory,mask);
4360 if (resolve_wildcards(directory,newname) &&
4361 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
4362 count++;
4363 if(!count && err) {
4364 errno = err;
4365 END_PROFILE(SMBcopy);
4366 return(UNIXERROR(ERRHRD,ERRgeneral));
4368 if (!count) {
4369 exists = vfs_file_exist(conn,directory,NULL);
4371 } else {
4372 struct smb_Dir *dir_hnd = NULL;
4373 const char *dname;
4374 pstring destname;
4376 if (check_name(directory,conn))
4377 dir_hnd = OpenDir(conn, directory);
4379 if (dir_hnd) {
4380 long offset = 0;
4381 error = ERRbadfile;
4383 if (strequal(mask,"????????.???"))
4384 pstrcpy(mask,"*");
4386 while ((dname = ReadDirName(dir_hnd, &offset))) {
4387 pstring fname;
4388 pstrcpy(fname,dname);
4390 if (!is_visible_file(conn, directory, dname, &sbuf1, False))
4391 continue;
4393 if(!mask_match(fname, mask, conn->case_sensitive))
4394 continue;
4396 error = ERRnoaccess;
4397 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
4398 pstrcpy(destname,newname);
4399 if (resolve_wildcards(fname,destname) &&
4400 copy_file(fname,destname,conn,ofun,
4401 count,target_is_directory,&err))
4402 count++;
4403 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
4405 CloseDir(dir_hnd);
4409 if (count == 0) {
4410 if(err) {
4411 /* Error on close... */
4412 errno = err;
4413 END_PROFILE(SMBcopy);
4414 return(UNIXERROR(ERRHRD,ERRgeneral));
4417 if (exists) {
4418 END_PROFILE(SMBcopy);
4419 return ERROR_DOS(ERRDOS,error);
4420 } else {
4421 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
4422 unix_ERR_class = ERRDOS;
4423 unix_ERR_code = ERRbadpath;
4425 END_PROFILE(SMBcopy);
4426 return(UNIXERROR(ERRDOS,error));
4430 outsize = set_message(outbuf,1,0,True);
4431 SSVAL(outbuf,smb_vwv0,count);
4433 END_PROFILE(SMBcopy);
4434 return(outsize);
4437 /****************************************************************************
4438 Reply to a setdir.
4439 ****************************************************************************/
4441 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4443 int snum;
4444 int outsize = 0;
4445 BOOL ok = False;
4446 pstring newdir;
4447 NTSTATUS status;
4449 START_PROFILE(pathworks_setdir);
4451 snum = SNUM(conn);
4452 if (!CAN_SETDIR(snum)) {
4453 END_PROFILE(pathworks_setdir);
4454 return ERROR_DOS(ERRDOS,ERRnoaccess);
4457 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
4458 if (!NT_STATUS_IS_OK(status)) {
4459 END_PROFILE(pathworks_setdir);
4460 return ERROR_NT(status);
4463 RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
4465 if (strlen(newdir) == 0) {
4466 ok = True;
4467 } else {
4468 ok = vfs_directory_exist(conn,newdir,NULL);
4469 if (ok)
4470 string_set(&conn->connectpath,newdir);
4473 if (!ok) {
4474 END_PROFILE(pathworks_setdir);
4475 return ERROR_DOS(ERRDOS,ERRbadpath);
4478 outsize = set_message(outbuf,0,0,True);
4479 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4481 DEBUG(3,("setdir %s\n", newdir));
4483 END_PROFILE(pathworks_setdir);
4484 return(outsize);
4487 /****************************************************************************
4488 Get a lock pid, dealing with large count requests.
4489 ****************************************************************************/
4491 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4493 if(!large_file_format)
4494 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4495 else
4496 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4499 /****************************************************************************
4500 Get a lock count, dealing with large count requests.
4501 ****************************************************************************/
4503 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4505 SMB_BIG_UINT count = 0;
4507 if(!large_file_format) {
4508 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4509 } else {
4511 #if defined(HAVE_LONGLONG)
4512 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4513 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4514 #else /* HAVE_LONGLONG */
4517 * NT4.x seems to be broken in that it sends large file (64 bit)
4518 * lockingX calls even if the CAP_LARGE_FILES was *not*
4519 * negotiated. For boxes without large unsigned ints truncate the
4520 * lock count by dropping the top 32 bits.
4523 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4524 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4525 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4526 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4527 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4530 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4531 #endif /* HAVE_LONGLONG */
4534 return count;
4537 #if !defined(HAVE_LONGLONG)
4538 /****************************************************************************
4539 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4540 ****************************************************************************/
4542 static uint32 map_lock_offset(uint32 high, uint32 low)
4544 unsigned int i;
4545 uint32 mask = 0;
4546 uint32 highcopy = high;
4549 * Try and find out how many significant bits there are in high.
4552 for(i = 0; highcopy; i++)
4553 highcopy >>= 1;
4556 * We use 31 bits not 32 here as POSIX
4557 * lock offsets may not be negative.
4560 mask = (~0) << (31 - i);
4562 if(low & mask)
4563 return 0; /* Fail. */
4565 high <<= (31 - i);
4567 return (high|low);
4569 #endif /* !defined(HAVE_LONGLONG) */
4571 /****************************************************************************
4572 Get a lock offset, dealing with large offset requests.
4573 ****************************************************************************/
4575 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4577 SMB_BIG_UINT offset = 0;
4579 *err = False;
4581 if(!large_file_format) {
4582 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4583 } else {
4585 #if defined(HAVE_LONGLONG)
4586 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4587 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4588 #else /* HAVE_LONGLONG */
4591 * NT4.x seems to be broken in that it sends large file (64 bit)
4592 * lockingX calls even if the CAP_LARGE_FILES was *not*
4593 * negotiated. For boxes without large unsigned ints mangle the
4594 * lock offset by mapping the top 32 bits onto the lower 32.
4597 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4598 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4599 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4600 uint32 new_low = 0;
4602 if((new_low = map_lock_offset(high, low)) == 0) {
4603 *err = True;
4604 return (SMB_BIG_UINT)-1;
4607 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4608 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4609 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4610 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4613 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4614 #endif /* HAVE_LONGLONG */
4617 return offset;
4620 /****************************************************************************
4621 Reply to a lockingX request.
4622 ****************************************************************************/
4624 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4626 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4627 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4628 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4629 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4630 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4631 SMB_BIG_UINT count = 0, offset = 0;
4632 uint16 lock_pid;
4633 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4634 int i;
4635 char *data;
4636 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4637 BOOL err;
4638 BOOL my_lock_ctx = False;
4639 NTSTATUS status;
4641 START_PROFILE(SMBlockingX);
4643 CHECK_FSP(fsp,conn);
4645 data = smb_buf(inbuf);
4647 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
4648 /* we don't support these - and CANCEL_LOCK makes w2k
4649 and XP reboot so I don't really want to be
4650 compatible! (tridge) */
4651 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4654 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
4655 /* Need to make this like a cancel.... JRA. */
4656 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
4659 /* Check if this is an oplock break on a file
4660 we have granted an oplock on.
4662 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4663 /* Client can insist on breaking to none. */
4664 BOOL break_to_none = (oplocklevel == 0);
4666 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4667 (unsigned int)oplocklevel, fsp->fnum ));
4670 * Make sure we have granted an exclusive or batch oplock on this file.
4673 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4674 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4675 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4677 /* if this is a pure oplock break request then don't send a reply */
4678 if (num_locks == 0 && num_ulocks == 0) {
4679 END_PROFILE(SMBlockingX);
4680 return -1;
4681 } else {
4682 END_PROFILE(SMBlockingX);
4683 return ERROR_DOS(ERRDOS,ERRlock);
4687 if (remove_oplock(fsp, break_to_none) == False) {
4688 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4689 fsp->fsp_name ));
4692 /* if this is a pure oplock break request then don't send a reply */
4693 if (num_locks == 0 && num_ulocks == 0) {
4694 /* Sanity check - ensure a pure oplock break is not a
4695 chained request. */
4696 if(CVAL(inbuf,smb_vwv0) != 0xff)
4697 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4698 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4699 END_PROFILE(SMBlockingX);
4700 return -1;
4705 * We do this check *after* we have checked this is not a oplock break
4706 * response message. JRA.
4709 release_level_2_oplocks_on_change(fsp);
4711 /* Data now points at the beginning of the list
4712 of smb_unlkrng structs */
4713 for(i = 0; i < (int)num_ulocks; i++) {
4714 lock_pid = get_lock_pid( data, i, large_file_format);
4715 count = get_lock_count( data, i, large_file_format);
4716 offset = get_lock_offset( data, i, large_file_format, &err);
4719 * There is no error code marked "stupid client bug".... :-).
4721 if(err) {
4722 END_PROFILE(SMBlockingX);
4723 return ERROR_DOS(ERRDOS,ERRnoaccess);
4726 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4727 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4729 status = do_unlock(fsp,conn,lock_pid,count,offset);
4730 if (NT_STATUS_V(status)) {
4731 END_PROFILE(SMBlockingX);
4732 return ERROR_NT(status);
4736 /* Setup the timeout in seconds. */
4738 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
4740 /* Now do any requested locks */
4741 data += ((large_file_format ? 20 : 10)*num_ulocks);
4743 /* Data now points at the beginning of the list
4744 of smb_lkrng structs */
4746 for(i = 0; i < (int)num_locks; i++) {
4747 lock_pid = get_lock_pid( data, i, large_file_format);
4748 count = get_lock_count( data, i, large_file_format);
4749 offset = get_lock_offset( data, i, large_file_format, &err);
4752 * There is no error code marked "stupid client bug".... :-).
4754 if(err) {
4755 END_PROFILE(SMBlockingX);
4756 return ERROR_DOS(ERRDOS,ERRnoaccess);
4759 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4760 (double)offset, (double)count, (unsigned int)lock_pid,
4761 fsp->fsp_name, (int)lock_timeout ));
4763 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4764 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4765 if (NT_STATUS_V(status)) {
4767 * Interesting fact found by IFSTEST /t LockOverlappedTest...
4768 * Even if it's our own lock context, we need to wait here as
4769 * there may be an unlock on the way.
4770 * So I removed a "&& !my_lock_ctx" from the following
4771 * if statement. JRA.
4773 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4775 * A blocking lock was requested. Package up
4776 * this smb into a queued request and push it
4777 * onto the blocking lock queue.
4779 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4780 END_PROFILE(SMBlockingX);
4781 return -1;
4784 break;
4788 /* If any of the above locks failed, then we must unlock
4789 all of the previous locks (X/Open spec). */
4790 if (i != num_locks && num_locks != 0) {
4792 * Ensure we don't do a remove on the lock that just failed,
4793 * as under POSIX rules, if we have a lock already there, we
4794 * will delete it (and we shouldn't) .....
4796 for(i--; i >= 0; i--) {
4797 lock_pid = get_lock_pid( data, i, large_file_format);
4798 count = get_lock_count( data, i, large_file_format);
4799 offset = get_lock_offset( data, i, large_file_format, &err);
4802 * There is no error code marked "stupid client bug".... :-).
4804 if(err) {
4805 END_PROFILE(SMBlockingX);
4806 return ERROR_DOS(ERRDOS,ERRnoaccess);
4809 do_unlock(fsp,conn,lock_pid,count,offset);
4811 END_PROFILE(SMBlockingX);
4812 return ERROR_NT(status);
4815 set_message(outbuf,2,0,True);
4817 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4818 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4820 END_PROFILE(SMBlockingX);
4821 return chain_reply(inbuf,outbuf,length,bufsize);
4824 /****************************************************************************
4825 Reply to a SMBreadbmpx (read block multiplex) request.
4826 ****************************************************************************/
4828 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4830 ssize_t nread = -1;
4831 ssize_t total_read;
4832 char *data;
4833 SMB_OFF_T startpos;
4834 int outsize;
4835 size_t maxcount;
4836 int max_per_packet;
4837 size_t tcount;
4838 int pad;
4839 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4840 START_PROFILE(SMBreadBmpx);
4842 /* this function doesn't seem to work - disable by default */
4843 if (!lp_readbmpx()) {
4844 END_PROFILE(SMBreadBmpx);
4845 return ERROR_DOS(ERRSRV,ERRuseSTD);
4848 outsize = set_message(outbuf,8,0,True);
4850 CHECK_FSP(fsp,conn);
4851 CHECK_READ(fsp);
4853 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4854 maxcount = SVAL(inbuf,smb_vwv3);
4856 data = smb_buf(outbuf);
4857 pad = ((long)data)%4;
4858 if (pad)
4859 pad = 4 - pad;
4860 data += pad;
4862 max_per_packet = bufsize-(outsize+pad);
4863 tcount = maxcount;
4864 total_read = 0;
4866 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
4867 END_PROFILE(SMBreadBmpx);
4868 return ERROR_DOS(ERRDOS,ERRlock);
4871 do {
4872 size_t N = MIN(max_per_packet,tcount-total_read);
4874 nread = read_file(fsp,data,startpos,N);
4876 if (nread <= 0)
4877 nread = 0;
4879 if (nread < (ssize_t)N)
4880 tcount = total_read + nread;
4882 set_message(outbuf,8,nread,False);
4883 SIVAL(outbuf,smb_vwv0,startpos);
4884 SSVAL(outbuf,smb_vwv2,tcount);
4885 SSVAL(outbuf,smb_vwv6,nread);
4886 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4888 if (!send_smb(smbd_server_fd(),outbuf))
4889 exit_server("reply_readbmpx: send_smb failed.");
4891 total_read += nread;
4892 startpos += nread;
4893 } while (total_read < (ssize_t)tcount);
4895 END_PROFILE(SMBreadBmpx);
4896 return(-1);
4899 /****************************************************************************
4900 Reply to a SMBsetattrE.
4901 ****************************************************************************/
4903 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4905 struct utimbuf unix_times;
4906 int outsize = 0;
4907 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4908 START_PROFILE(SMBsetattrE);
4910 outsize = set_message(outbuf,0,0,True);
4912 if(!fsp || (fsp->conn != conn)) {
4913 END_PROFILE(SMBgetattrE);
4914 return ERROR_DOS(ERRDOS,ERRbadfid);
4918 * Convert the DOS times into unix times. Ignore create
4919 * time as UNIX can't set this.
4922 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4923 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4926 * Patch from Ray Frush <frush@engr.colostate.edu>
4927 * Sometimes times are sent as zero - ignore them.
4930 if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
4931 /* Ignore request */
4932 if( DEBUGLVL( 3 ) ) {
4933 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4934 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4936 END_PROFILE(SMBsetattrE);
4937 return(outsize);
4938 } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
4939 /* set modify time = to access time if modify time was unset */
4940 unix_times.modtime = unix_times.actime;
4943 /* Set the date on this file */
4944 /* Should we set pending modtime here ? JRA */
4945 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4946 END_PROFILE(SMBsetattrE);
4947 return ERROR_DOS(ERRDOS,ERRnoaccess);
4950 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4951 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4953 END_PROFILE(SMBsetattrE);
4954 return(outsize);
4958 /* Back from the dead for OS/2..... JRA. */
4960 /****************************************************************************
4961 Reply to a SMBwritebmpx (write block multiplex primary) request.
4962 ****************************************************************************/
4964 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4966 size_t numtowrite;
4967 ssize_t nwritten = -1;
4968 int outsize = 0;
4969 SMB_OFF_T startpos;
4970 size_t tcount;
4971 BOOL write_through;
4972 int smb_doff;
4973 char *data;
4974 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4975 START_PROFILE(SMBwriteBmpx);
4977 CHECK_FSP(fsp,conn);
4978 CHECK_WRITE(fsp);
4979 CHECK_ERROR(fsp);
4981 tcount = SVAL(inbuf,smb_vwv1);
4982 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4983 write_through = BITSETW(inbuf+smb_vwv7,0);
4984 numtowrite = SVAL(inbuf,smb_vwv10);
4985 smb_doff = SVAL(inbuf,smb_vwv11);
4987 data = smb_base(inbuf) + smb_doff;
4989 /* If this fails we need to send an SMBwriteC response,
4990 not an SMBwritebmpx - set this up now so we don't forget */
4991 SCVAL(outbuf,smb_com,SMBwritec);
4993 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
4994 END_PROFILE(SMBwriteBmpx);
4995 return(ERROR_DOS(ERRDOS,ERRlock));
4998 nwritten = write_file(fsp,data,startpos,numtowrite);
5000 if(lp_syncalways(SNUM(conn)) || write_through)
5001 sync_file(conn,fsp);
5003 if(nwritten < (ssize_t)numtowrite) {
5004 END_PROFILE(SMBwriteBmpx);
5005 return(UNIXERROR(ERRHRD,ERRdiskfull));
5008 /* If the maximum to be written to this file
5009 is greater than what we just wrote then set
5010 up a secondary struct to be attached to this
5011 fd, we will use this to cache error messages etc. */
5013 if((ssize_t)tcount > nwritten) {
5014 write_bmpx_struct *wbms;
5015 if(fsp->wbmpx_ptr != NULL)
5016 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
5017 else
5018 wbms = SMB_MALLOC_P(write_bmpx_struct);
5019 if(!wbms) {
5020 DEBUG(0,("Out of memory in reply_readmpx\n"));
5021 END_PROFILE(SMBwriteBmpx);
5022 return(ERROR_DOS(ERRSRV,ERRnoresource));
5024 wbms->wr_mode = write_through;
5025 wbms->wr_discard = False; /* No errors yet */
5026 wbms->wr_total_written = nwritten;
5027 wbms->wr_errclass = 0;
5028 wbms->wr_error = 0;
5029 fsp->wbmpx_ptr = wbms;
5032 /* We are returning successfully, set the message type back to
5033 SMBwritebmpx */
5034 SCVAL(outbuf,smb_com,SMBwriteBmpx);
5036 outsize = set_message(outbuf,1,0,True);
5038 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
5040 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
5041 fsp->fnum, (int)numtowrite, (int)nwritten ) );
5043 if (write_through && tcount==nwritten) {
5044 /* We need to send both a primary and a secondary response */
5045 smb_setlen(outbuf,outsize - 4);
5046 if (!send_smb(smbd_server_fd(),outbuf))
5047 exit_server("reply_writebmpx: send_smb failed.");
5049 /* Now the secondary */
5050 outsize = set_message(outbuf,1,0,True);
5051 SCVAL(outbuf,smb_com,SMBwritec);
5052 SSVAL(outbuf,smb_vwv0,nwritten);
5055 END_PROFILE(SMBwriteBmpx);
5056 return(outsize);
5059 /****************************************************************************
5060 Reply to a SMBwritebs (write block multiplex secondary) request.
5061 ****************************************************************************/
5063 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5065 size_t numtowrite;
5066 ssize_t nwritten = -1;
5067 int outsize = 0;
5068 SMB_OFF_T startpos;
5069 size_t tcount;
5070 BOOL write_through;
5071 int smb_doff;
5072 char *data;
5073 write_bmpx_struct *wbms;
5074 BOOL send_response = False;
5075 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5076 START_PROFILE(SMBwriteBs);
5078 CHECK_FSP(fsp,conn);
5079 CHECK_WRITE(fsp);
5081 tcount = SVAL(inbuf,smb_vwv1);
5082 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
5083 numtowrite = SVAL(inbuf,smb_vwv6);
5084 smb_doff = SVAL(inbuf,smb_vwv7);
5086 data = smb_base(inbuf) + smb_doff;
5088 /* We need to send an SMBwriteC response, not an SMBwritebs */
5089 SCVAL(outbuf,smb_com,SMBwritec);
5091 /* This fd should have an auxiliary struct attached,
5092 check that it does */
5093 wbms = fsp->wbmpx_ptr;
5094 if(!wbms) {
5095 END_PROFILE(SMBwriteBs);
5096 return(-1);
5099 /* If write through is set we can return errors, else we must cache them */
5100 write_through = wbms->wr_mode;
5102 /* Check for an earlier error */
5103 if(wbms->wr_discard) {
5104 END_PROFILE(SMBwriteBs);
5105 return -1; /* Just discard the packet */
5108 nwritten = write_file(fsp,data,startpos,numtowrite);
5110 if(lp_syncalways(SNUM(conn)) || write_through)
5111 sync_file(conn,fsp);
5113 if (nwritten < (ssize_t)numtowrite) {
5114 if(write_through) {
5115 /* We are returning an error - we can delete the aux struct */
5116 if (wbms)
5117 free((char *)wbms);
5118 fsp->wbmpx_ptr = NULL;
5119 END_PROFILE(SMBwriteBs);
5120 return(ERROR_DOS(ERRHRD,ERRdiskfull));
5122 END_PROFILE(SMBwriteBs);
5123 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
5126 /* Increment the total written, if this matches tcount
5127 we can discard the auxiliary struct (hurrah !) and return a writeC */
5128 wbms->wr_total_written += nwritten;
5129 if(wbms->wr_total_written >= tcount) {
5130 if (write_through) {
5131 outsize = set_message(outbuf,1,0,True);
5132 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
5133 send_response = True;
5136 free((char *)wbms);
5137 fsp->wbmpx_ptr = NULL;
5140 if(send_response) {
5141 END_PROFILE(SMBwriteBs);
5142 return(outsize);
5145 END_PROFILE(SMBwriteBs);
5146 return(-1);
5149 /****************************************************************************
5150 Reply to a SMBgetattrE.
5151 ****************************************************************************/
5153 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5155 SMB_STRUCT_STAT sbuf;
5156 int outsize = 0;
5157 int mode;
5158 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5159 START_PROFILE(SMBgetattrE);
5161 outsize = set_message(outbuf,11,0,True);
5163 if(!fsp || (fsp->conn != conn)) {
5164 END_PROFILE(SMBgetattrE);
5165 return ERROR_DOS(ERRDOS,ERRbadfid);
5168 /* Do an fstat on this file */
5169 if(fsp_stat(fsp, &sbuf)) {
5170 END_PROFILE(SMBgetattrE);
5171 return(UNIXERROR(ERRDOS,ERRnoaccess));
5174 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
5177 * Convert the times into dos times. Set create
5178 * date to be last modify date as UNIX doesn't save
5179 * this.
5182 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
5183 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
5184 /* Should we check pending modtime here ? JRA */
5185 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
5187 if (mode & aDIR) {
5188 SIVAL(outbuf,smb_vwv6,0);
5189 SIVAL(outbuf,smb_vwv8,0);
5190 } else {
5191 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
5192 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
5193 SIVAL(outbuf,smb_vwv8,allocation_size);
5195 SSVAL(outbuf,smb_vwv10, mode);
5197 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
5199 END_PROFILE(SMBgetattrE);
5200 return(outsize);